1 | //Look-Up-Tabelle
|
2 | volatile uint8_t crctable[32] =
|
3 | {
|
4 | 0, 14, 28, 18, 17, 31, 13, 3,
|
5 | 11, 5, 23, 25, 26, 20, 6, 8,
|
6 | 22, 24, 10, 4, 7, 9, 27, 21,
|
7 | 29, 19, 1, 15, 12, 2, 16, 30
|
8 | };
|
9 |
|
10 | //Enthält die Nummer des Empfangenen Bytes
|
11 | volatile uint8_t incomingByteCounter = 0;
|
12 |
|
13 | //Die Werte der Empfangenen Datenbytes
|
14 | volatile uint8_t byte0 = 0;
|
15 | volatile uint8_t byte1 = 0;
|
16 | volatile uint8_t byte2 = 0;
|
17 | volatile uint8_t byte3 = 0;
|
18 |
|
19 | //Der aktuelle crc-Wert
|
20 | volatile uint8_t crcValue = 0;
|
21 |
|
22 | //Wenn nach einer bestimmten Zeit (~6ms) kein weiteres Byte eingetroffen ist, werden die Daten resettet
|
23 | uint8_t uartResetCounter = 0;
|
24 |
|
25 |
|
26 |
|
27 | // ===== Usart Empfangsinterrupt ================================
|
28 | ISR (USART_RX_vect) //Daten liegen in UDR0
|
29 | {
|
30 | //TimingInterrupt deaktivieren
|
31 | cli();
|
32 | //ResetCounter zurücksetzen
|
33 | uartResetCounter = 0;
|
34 |
|
35 | //die Bytenummer des eingehenden Bytes bestimmen
|
36 | incomingByteCounter++;
|
37 |
|
38 | //crc-lookup-Index für das aktuelle Byte berechnen
|
39 | uint8_t nextCrcIndex = (UDR0 & 0x1f) ^ (crcValue & 0x1f);
|
40 |
|
41 | //Eingetroffenes Byte verarbeiten
|
42 | //Je nach Bytenummer, entweder zwischenspeichern, oder alle eingetroffenen Daten verarbeiten
|
43 | switch(incomingByteCounter)
|
44 | {
|
45 | case 1:
|
46 | byte0 = UDR0;
|
47 | crcValue = crctable[nextCrcIndex];
|
48 | break;
|
49 | case 2:
|
50 | byte1 = UDR0;
|
51 | crcValue = crctable[nextCrcIndex];
|
52 | break;
|
53 | case 3:
|
54 | byte2 = UDR0;
|
55 | crcValue = crctable[nextCrcIndex];
|
56 | break;
|
57 | case 4:
|
58 | byte3 = UDR0;
|
59 | crcValue = crctable[nextCrcIndex];
|
60 | break;
|
61 | case 5:
|
62 | //Entscheidender Vergleich: letztes Byte == crc-Wert?
|
63 | if(crcValue == UDR0)
|
64 | {
|
65 | //Bytes aufteilen
|
66 | /*
|
67 | * Empfangene Bytes:
|
68 | * Byte 0: XXAAA
|
69 | * Byte 1: AAABB
|
70 | * Byte 2: BBBBC
|
71 | * Byte 3: CCCCC
|
72 | * Byte 4: DDDDD
|
73 |
|
74 | Legende:
|
75 | X: zum bestimmen, was für Daten empfangen wurden
|
76 | A: 6 Bit Daten
|
77 | B: 6 Bit Daten
|
78 | C: 6 Bit Daten
|
79 | D: Parität/Prüfsumme
|
80 | */
|
81 | uint8_t tby1 = ((byte0 & 0x07) << 3) | ((byte1 & 0x1C) >> 2);
|
82 | uint8_t tby2 = ((byte1 & 0x03) << 4) | ((byte2 & 0x1E) >> 1);
|
83 | uint8_t tby3 = ((byte2 & 0x01) << 5) | byte3;
|
84 | if((byte0 & 0x18) == 0) //Es wurden bestimmte Daten empfangen
|
85 | {
|
86 | //ocrR, ocrG, ocrB: PWM-Compare-Values, für die Helligkeit
|
87 | //pwmtable: lookup-Table für logarythmische Helligkeitsausgabe (->Linear fürs Auge), enthält 64 Werte
|
88 | ocrR = pwmtable[tby1];
|
89 | ocrG = pwmtable[tby2];
|
90 | ocrB = pwmtable[tby3];
|
91 | }
|
92 | else if((byte0 & 0x18) == 8) //Es wurden andere Daten empfangen
|
93 | {
|
94 | ocrK = pwmtable[tby1];
|
95 | ocrW = pwmtable[tby2];
|
96 | pinB = tby3;
|
97 | }
|
98 | }
|
99 |
|
100 | //Kritische Variablen zurücksetzen
|
101 | incomingByteCounter = 0;
|
102 | crcValue = 0;
|
103 | break;
|
104 | default:
|
105 | break;
|
106 | }
|
107 |
|
108 | //Timinginterrupt wieder aktivieren
|
109 | sei();
|
110 | }
|
111 |
|
112 |
|
113 |
|
114 | /*
|
115 | * Timerinterrupt von Timer2
|
116 | * Timer2 wurde folgendermaßen initialisiert:
|
117 | * Timereinstellungen setzen: TCCR2A = (1<<COM2A0) | (1<<COM2A1) | (1<<COM2B0) | (1<<COM2B1) | (1<<WGM20);
|
118 | TCCR2A = 0xF1;
|
119 |
|
120 | * Prescaler auf 8 eingestellt (CS21): TCCR2B = (1<<CS21);
|
121 | TCCR2B = 0x02;
|
122 |
|
123 | * Interrupt für OCR2A aktivieren (für Timings, OCIE2A)
|
124 | TIMSK2 = 0x02;
|
125 |
|
126 | * Bei einer Baudrate von 4800 kommt alle 208µs ein bit, also kommt mein ganzes Datenpaket
|
127 | * (1*Start, 5*Daten, 1*Stop = 7 bit) schnellstens alle 1,45ms.
|
128 | *
|
129 | * Das AVR-Studio zeigt als Zeit zwischen dem Auslösen von zwei Interrupten eine Zeitspanne von ~4090µs bei 1MHz,
|
130 | * was auf 7,3728MHz hochgerechnet etwa 555µs entspricht, daher lasse ich den uartResetCounter bis 10 Zählen (->5,5ms)
|
131 | * Auf dasselbe Ergebnis komme ich auch, wenn ich manuell die Zeit berechne: 8*512/7232800 = 555µs
|
132 | * Erst wenn 5ms zwischen zwei Datenpaketen vergangen sind, werden die alten Daten resettet.
|
133 | */
|
134 | ISR(TIMER2_COMPA_vect) //TIMER2 COMPA
|
135 | {
|
136 | if(incomingByteCounter != 0) //Wird gerade etwas empfangen? Nur dann muss die Zeit gezählt werden
|
137 | {
|
138 | uartResetCounter++; //Den Counter incrementieren
|
139 | if(uartResetCounter == 10) //Wenn der counter bei 10 ist, alles Resetten.
|
140 | //Dann ist zu viel Zeit vom Empfang des letzten Bytes vergangen (~6ms),
|
141 | //sofern ein Interrupt nicht wärend der byte-Verarbeitung aufgetreten wäre.
|
142 | //Dann hat das nächste Byte noch länger Zeit.
|
143 | {
|
144 | incomingByteCounter = 0;
|
145 | uartResetCounter = 0;
|
146 | crcValue = 0;
|
147 | }
|
148 | }
|
149 | }
|