<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pessinurmi.com/index.php?action=history&amp;feed=atom&amp;title=Vastaanottimen_l%C3%A4hdekoodi_V2</id>
	<title>Vastaanottimen lähdekoodi V2 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pessinurmi.com/index.php?action=history&amp;feed=atom&amp;title=Vastaanottimen_l%C3%A4hdekoodi_V2"/>
	<link rel="alternate" type="text/html" href="https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;action=history"/>
	<updated>2026-06-06T12:09:51Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;diff=766&amp;oldid=prev</id>
		<title>Exf: /* V2.0 */</title>
		<link rel="alternate" type="text/html" href="https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;diff=766&amp;oldid=prev"/>
		<updated>2025-10-04T18:43:15Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;V2.0&lt;/span&gt;&lt;/p&gt;
&lt;a href=&quot;https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;amp;diff=766&amp;amp;oldid=765&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Exf</name></author>
	</entry>
	<entry>
		<id>https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;diff=765&amp;oldid=prev</id>
		<title>Exf: /* V2.0 */</title>
		<link rel="alternate" type="text/html" href="https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;diff=765&amp;oldid=prev"/>
		<updated>2025-10-03T17:44:49Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;V2.0&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 17:44, 3 October 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l68&quot;&gt;Line 68:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 68:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;void loop() {&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;void loop() {&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   handleRadioReceiver(); //receive packages&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   handleRadioReceiver(); //receive packages&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l139&quot;&gt;Line 139:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 138:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;/*&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;bool checkChecksum(uint8_t *data, uint8_t *receivedCrc) {&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;bool checkChecksum(uint8_t *data, uint8_t *receivedCrc) {&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   CRC16 crc;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   CRC16 crc;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l146&quot;&gt;Line 146:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 145:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   uint16_t calcCrc = crc.calc();&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   uint16_t calcCrc = crc.calc();&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   return (calcCrc == *(uint16_t *)receivedCrc);&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   return (calcCrc == *(uint16_t *)receivedCrc);&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;*/&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;uint8_t processPacket(uint8_t *data, uint8_t dataLength) {&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;uint8_t processPacket(uint8_t *data, uint8_t dataLength) {&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key my_wiki:diff:1.41:old-760:rev-765:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Exf</name></author>
	</entry>
	<entry>
		<id>https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;diff=760&amp;oldid=prev</id>
		<title>Exf: Created page with &quot;=== Versiohistoria ===  ==== V2.0 ==== Muutettu täysin näytön näyttötapaa.  Parannettu vastaanotetun tiedon varmistamista käyttäen CRC-16 funktiota.  Tiedetyt ongelmat. Rekisteröi uuden vastaanotetun koodin vasta kun näyttö on piirtänyt KAIKKI ID:t.&lt;syntaxhighlight lang=&quot;c#&quot;&gt; #include &lt;SPI.h&gt; #include &lt;Wire.h&gt; #include &lt;Adafruit_GFX.h&gt; #include &lt;Adafruit_SSD1306.h&gt; #include &lt;RH_ASK.h&gt; #include &lt;CRC16.h&gt;  #define OLED_RESET -1 #define SCREEN_WIDTH 128 // OLED d...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.pessinurmi.com/index.php?title=Vastaanottimen_l%C3%A4hdekoodi_V2&amp;diff=760&amp;oldid=prev"/>
		<updated>2025-10-03T14:40:01Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;=== Versiohistoria ===  ==== V2.0 ==== Muutettu täysin näytön näyttötapaa.  Parannettu vastaanotetun tiedon varmistamista käyttäen CRC-16 funktiota.  Tiedetyt ongelmat. Rekisteröi uuden vastaanotetun koodin vasta kun näyttö on piirtänyt KAIKKI ID:t.&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot;&amp;gt; #include &amp;lt;SPI.h&amp;gt; #include &amp;lt;Wire.h&amp;gt; #include &amp;lt;Adafruit_GFX.h&amp;gt; #include &amp;lt;Adafruit_SSD1306.h&amp;gt; #include &amp;lt;RH_ASK.h&amp;gt; #include &amp;lt;CRC16.h&amp;gt;  #define OLED_RESET -1 #define SCREEN_WIDTH 128 // OLED d...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=== Versiohistoria ===&lt;br /&gt;
&lt;br /&gt;
==== V2.0 ====&lt;br /&gt;
Muutettu täysin näytön näyttötapaa.&lt;br /&gt;
&lt;br /&gt;
Parannettu vastaanotetun tiedon varmistamista käyttäen CRC-16 funktiota.&lt;br /&gt;
&lt;br /&gt;
Tiedetyt ongelmat. Rekisteröi uuden vastaanotetun koodin vasta kun näyttö on piirtänyt KAIKKI ID:t.&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Wire.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Adafruit_GFX.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Adafruit_SSD1306.h&amp;gt;&lt;br /&gt;
#include &amp;lt;RH_ASK.h&amp;gt;&lt;br /&gt;
#include &amp;lt;CRC16.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define OLED_RESET -1&lt;br /&gt;
#define SCREEN_WIDTH 128 // OLED display width, in pixels&lt;br /&gt;
#define SCREEN_HEIGHT 32 // OLED display height, in pixels&lt;br /&gt;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;amp;Wire, OLED_RESET);&lt;br /&gt;
&lt;br /&gt;
RH_ASK driver(1000, 12, 11, 10); // RX = D12&lt;br /&gt;
&lt;br /&gt;
//ID:n tallennusmuuttujat&lt;br /&gt;
const int MAX_IDS = 16;&lt;br /&gt;
uint8_t ids[MAX_IDS];&lt;br /&gt;
unsigned long idTimes[MAX_IDS]; //Aikaleima&lt;br /&gt;
int numIds = 0;&lt;br /&gt;
&lt;br /&gt;
//Screen indicator&lt;br /&gt;
const unsigned long BLINK_INTERVAL = 500;&lt;br /&gt;
bool indicatorOn = false;&lt;br /&gt;
unsigned long indicatorTime = 0;&lt;br /&gt;
&lt;br /&gt;
// ID activity &amp;amp; deactivity&lt;br /&gt;
//const unsigned long ACTIVE_TIME = 300000;    // time threshold for active IDs (5 minutes)&lt;br /&gt;
const unsigned long INACTIVE_TIME = 3600000; // time threshold for inactive IDs (1 hour)&lt;br /&gt;
&lt;br /&gt;
// Screen rotation time&lt;br /&gt;
const unsigned long DISPLAY_DURATION = 2500; // 2.5 s&lt;br /&gt;
int selectedId = 0;&lt;br /&gt;
unsigned long lastSelectedTime = 0;&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  Serial.begin(9600);&lt;br /&gt;
&lt;br /&gt;
  // initialize the OLED screen&lt;br /&gt;
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);&lt;br /&gt;
  display.clearDisplay();&lt;br /&gt;
  display.setTextColor(WHITE);&lt;br /&gt;
  display.setTextSize(2);&lt;br /&gt;
&lt;br /&gt;
  display.clearDisplay();&lt;br /&gt;
  display.setTextSize(1);&lt;br /&gt;
  display.setTextColor(SSD1306_WHITE);&lt;br /&gt;
  display.setCursor(0, 0);&lt;br /&gt;
  display.println(F(&amp;quot;Odotetaan...&amp;quot;));&lt;br /&gt;
  display.display();&lt;br /&gt;
  &lt;br /&gt;
  if (!driver.init()) {&lt;br /&gt;
    display.clearDisplay();&lt;br /&gt;
    display.setCursor(0, 0);&lt;br /&gt;
    display.println(F(&amp;quot;Radio ei vastaa&amp;quot;));&lt;br /&gt;
    display.display();&lt;br /&gt;
    while (1); // &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
&lt;br /&gt;
  handleRadioReceiver(); //receive packages&lt;br /&gt;
&lt;br /&gt;
  // update the selected ID every 3 seconds to show different ID&amp;#039;s timestamp&lt;br /&gt;
  if (millis() - lastSelectedTime &amp;gt;= DISPLAY_DURATION) {&lt;br /&gt;
    selectedId = (selectedId + 1) % numIds;&lt;br /&gt;
    lastSelectedTime = millis();&lt;br /&gt;
    displayData();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //displayData();  // display all of the received IDs and their last seen times, or &amp;quot;Waiting for message...&amp;quot; if there are no IDs recorded&lt;br /&gt;
  removeInactiveIds(); // remove any inactive IDs older than INACTIVE_TIME&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Receive the radio message&lt;br /&gt;
void handleRadioReceiver() {&lt;br /&gt;
  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];&lt;br /&gt;
  uint8_t buflen = sizeof(buf);&lt;br /&gt;
  static bool checksumReceived = false;&lt;br /&gt;
  static uint16_t receivedChecksum;&lt;br /&gt;
  uint16_t checksumValue;&lt;br /&gt;
  uint8_t data[4];&lt;br /&gt;
&lt;br /&gt;
  if (driver.recv(buf, &amp;amp;buflen)) { // Non-blocking&lt;br /&gt;
    int16_t rssi = driver.lastRssi();&lt;br /&gt;
&lt;br /&gt;
    if (buflen == 2 &amp;amp;&amp;amp; !checksumReceived) {&lt;br /&gt;
      // Received checksum packet&lt;br /&gt;
      receivedChecksum = *(uint16_t *)buf;&lt;br /&gt;
      checksumReceived = true;&lt;br /&gt;
&lt;br /&gt;
    } else if (buflen == 4 &amp;amp;&amp;amp; checksumReceived) {&lt;br /&gt;
      // Received data packet, with preceding valid checksum packet&lt;br /&gt;
      &lt;br /&gt;
      memcpy(data, buf, sizeof(data));&lt;br /&gt;
&lt;br /&gt;
      CRC16 crc;&lt;br /&gt;
      crc.add(data, sizeof(data));    // add the DIP switch values to the CRC calculation&lt;br /&gt;
      checksumValue = crc.calc();&lt;br /&gt;
&lt;br /&gt;
      if(checksumValue == receivedChecksum) {&lt;br /&gt;
        uint8_t id = processPacket(data, sizeof(data) / sizeof(data[0]));&lt;br /&gt;
&lt;br /&gt;
        // Check if ID value is valid&lt;br /&gt;
        if (id &amp;gt;= 0 &amp;amp;&amp;amp; id &amp;lt; MAX_IDS) {&lt;br /&gt;
          bool found = false;&lt;br /&gt;
          for (int i = 0; i &amp;lt; numIds; i++) {&lt;br /&gt;
            if (ids[i] == id) {&lt;br /&gt;
              found = true;&lt;br /&gt;
              idTimes[i] = millis(); // Update the last time this ID was received&lt;br /&gt;
              break;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
&lt;br /&gt;
          if (!found &amp;amp;&amp;amp; numIds &amp;lt; MAX_IDS) {&lt;br /&gt;
            ids[numIds] = id;&lt;br /&gt;
            idTimes[numIds] = millis();&lt;br /&gt;
            numIds++;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        checksumReceived = false;&lt;br /&gt;
      } else {&lt;br /&gt;
        checksumReceived = false;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Invalid packet length or out-of-order transmission&lt;br /&gt;
      checksumReceived = false;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bool checkChecksum(uint8_t *data, uint8_t *receivedCrc) {&lt;br /&gt;
  CRC16 crc;&lt;br /&gt;
  crc.setPolynome(0x1021); // CCITT polynomial (0x1021)&lt;br /&gt;
  crc.add(data, sizeof(data));&lt;br /&gt;
  uint16_t calcCrc = crc.calc();&lt;br /&gt;
  return (calcCrc == *(uint16_t *)receivedCrc);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t processPacket(uint8_t *data, uint8_t dataLength) {&lt;br /&gt;
  uint8_t id = 0;&lt;br /&gt;
  for (uint8_t i = 0; i &amp;lt; dataLength; i++) {&lt;br /&gt;
    id |= data[i] &amp;lt;&amp;lt; i; // convert DIP code to ID&lt;br /&gt;
  }&lt;br /&gt;
  return id;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void displayData() {&lt;br /&gt;
  display.clearDisplay();&lt;br /&gt;
&lt;br /&gt;
  if (numIds == 0) {&lt;br /&gt;
    display.setCursor(0, 10);&lt;br /&gt;
    display.println(&amp;quot;Waiting for&amp;quot;);&lt;br /&gt;
    display.print(&amp;quot;message...&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    // Valitaan fonttikoko ID-määrän perusteella&lt;br /&gt;
    int textSize;&lt;br /&gt;
    int idsPerRow = 4;&lt;br /&gt;
    if (numIds &amp;lt; 4) {&lt;br /&gt;
      textSize = 3;&lt;br /&gt;
    } else if (numIds &amp;lt; 8) {&lt;br /&gt;
      textSize = 2;&lt;br /&gt;
    } else {&lt;br /&gt;
      textSize = 1;&lt;br /&gt;
      idsPerRow = 6;&lt;br /&gt;
    }&lt;br /&gt;
    display.setTextSize(textSize);&lt;br /&gt;
&lt;br /&gt;
    // Perustiedot&lt;br /&gt;
    //const int charsPerId = 2;       // max 2 merkkiä ID:ssä&lt;br /&gt;
    //const int charWidth = 6;        // per merkki (fontti size=1)&lt;br /&gt;
    //const int idBoxWidth = charsPerId * charWidth * textSize + 2;  // pieni väli&lt;br /&gt;
    const int idBoxWidth = 15 * textSize;&lt;br /&gt;
    //int idsPerRow = (textSize == 1) ? 8 : 4;  // size=1 → 8 per rivi, muuten 4&lt;br /&gt;
    int rowHeight = 8 * textSize;&lt;br /&gt;
&lt;br /&gt;
    // Piirretään ID:t riveittäin&lt;br /&gt;
    for (int i = 0; i &amp;lt; numIds; i++) {&lt;br /&gt;
      int row = i / idsPerRow;&lt;br /&gt;
      int col = i % idsPerRow;&lt;br /&gt;
&lt;br /&gt;
      int x = col * idBoxWidth;&lt;br /&gt;
      int y = row * rowHeight;&lt;br /&gt;
&lt;br /&gt;
      if (i == selectedId) {&lt;br /&gt;
        display.setTextColor(BLACK, WHITE); // invertoitu&lt;br /&gt;
      } else {&lt;br /&gt;
        display.setTextColor(WHITE, BLACK);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      display.setCursor(x, y);&lt;br /&gt;
      display.print(ids[i]);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Last seen aika&lt;br /&gt;
    display.setTextSize(1);&lt;br /&gt;
    display.setTextColor(WHITE);&lt;br /&gt;
    int lastSeenMins = (millis() - idTimes[selectedId]) / 60000;&lt;br /&gt;
    display.setCursor(SCREEN_WIDTH - 24, SCREEN_HEIGHT - 8);&lt;br /&gt;
    display.print(lastSeenMins);&lt;br /&gt;
    display.print(&amp;quot;m&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // Vilkkuva indikaattori&lt;br /&gt;
  //if (millis() - indicatorTime &amp;gt;= BLINK_INTERVAL) {&lt;br /&gt;
    indicatorOn = !indicatorOn;&lt;br /&gt;
    indicatorTime = millis();&lt;br /&gt;
&lt;br /&gt;
    display.setCursor(0, SCREEN_HEIGHT - 8);&lt;br /&gt;
    if (indicatorOn) {&lt;br /&gt;
      display.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
      display.print(&amp;quot; &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  //}&lt;br /&gt;
&lt;br /&gt;
  display.display();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void removeInactiveIds() {&lt;br /&gt;
  for (int i = numIds - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
    if (millis() - idTimes[i] &amp;gt; INACTIVE_TIME) {&lt;br /&gt;
      // shift the remaining IDs and last seen times down by one position to overwrite the inactive ID&lt;br /&gt;
      for (int j = i + 1; j &amp;lt; numIds; j++) {&lt;br /&gt;
        ids[j - 1] = ids[j];&lt;br /&gt;
        idTimes[j - 1] = idTimes[j];&lt;br /&gt;
      }&lt;br /&gt;
      numIds--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Exf</name></author>
	</entry>
</feed>