| 1 | /*************************************************************************
 | 
| 2 |  *                                                                       *
 | 
| 3 |  *   Projekt:    Studienarbeit 6.Semester                             *
 | 
| 4 |  *   Thema:      Entwicklung eines DJ-Mischpultes mit USB-Anschluss   *
 | 
| 5 |  *   Student:    Eric Schrön                                          *
 | 
| 6 |  *   Kurs:      TEL05AAT                                             *
 | 
| 7 |  *   Betreuer:    Prof. Walter Berthold                                *
 | 
| 8 |  *   Datei:      mischpult.c                                          *
 | 
| 9 |  *   Editor:    AVR Studio 4                     *
 | 
| 10 |  *   Copmiler:      GNU-GCC Compiler                   *
 | 
| 11 |  *   Abgabedatum:  27.03.2008                                           *
 | 
| 12 |  *                                                                       *
 | 
| 13 |  *   Beschreibung:  Das folgende Programm wird auf den Mikrocontroller   *
 | 
| 14 |  *          im Mischpult geladen. Das Programm ist für einen   *
 | 
| 15 |  *          ATMEGA16 von der Firma Atmel geschrieben.       *
 | 
| 16 |  *          Das folgende Programm sammelt alle Daten der Dreh-   *
 | 
| 17 |  *          geber und der Schiebepotis, wertet sie aus und     *
 | 
| 18 |  *          ordnet ihnen die entsprechende Funktion zu. Außer-   *
 | 
| 19 |  *          dem stellt das Programm die Kommuikation mit einem   *
 | 
| 20 |  *          PC über die  USART Schnittstelle des µC her.       *
 | 
| 21 |  *           Zunächst werden alle notwendigen Daten initiali-   *
 | 
| 22 |  *          siert. Anschließend wird erstmalig der AD-Wandler   *
 | 
| 23 |  *          zu Initialisierungszwecken aufgerufen. Der Ab-     *
 | 
| 24 |  *          schluss der Wandlung wird von dem µC mit einem     *
 | 
| 25 |  *          Interrupt signalisiert, womit eine entsprechende   *
 | 
| 26 |  *          Interruptserviceroutine(ISR) aufgerufen wird. Dort   *
 | 
| 27 |  *          wird zu Beginn der AD-Wandler wieder gestartet,     *
 | 
| 28 |  *          der nur mit einem Bruchteil der Taktfrequenz, Ein-   *
 | 
| 29 |  *          gangsdaten wandeln kann. In der Zwischenzeit werden   *
 | 
| 30 |  *          alle nicht AD-Pins abgefragt und ausgewertet. Wenn   *
 | 
| 31 |  *          sich bei irgendeinem Pin etwas wird dies in eine   *
 | 
| 32 |  *          Variable geschrieben und in der dazu gehörigen     *
 | 
| 33 |  *          Adressvariable ein Dirty-Bit gesetzt. Wenn die AD-   *
 | 
| 34 |  *          Wandlung abgeschlossen ist, wird erneut die ISR     *
 | 
| 35 |  *          aufgerufen.                       *
 | 
| 36 |  *          Wenn die ISR nicht aktiv ist, wird main durch-     *
 | 
| 37 |  *          laufen. Dort wird das Speicherabbild auf gesetzte   *
 | 
| 38 |  *          Dirty-Bits geprüft. In diesem Fall wird eine     *
 | 
| 39 |  *          Funktion senden aufgerufen, die das Adress- und     *
 | 
| 40 |  *          Datenbyte des jeweiligen Reglers sendet. Außerdem   *
 | 
| 41 |  *          ist ein 200 Byte großer FIFO implementiert.       *
 | 
| 42 |  *                                                                       *
 | 
| 43 |  *************************************************************************/
 | 
| 44 | 
 | 
| 45 | #include <stdint.h>
 | 
| 46 | #include <avr/io.h>
 | 
| 47 | #include <avr/interrupt.h>
 | 
| 48 | #include <variablen.h>
 | 
| 49 | //#include "funktionen.c"
 | 
| 50 | 
 | 
| 51 | #define F_OSC 12000000               /* oscillator-frequency in Hz */
 | 
| 52 | #define UART_BAUD_RATE 57600
 | 
| 53 | #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16l)-1)
 | 
| 54 | 
 | 
| 55 | 
 | 
| 56 | 
 | 
| 57 | uint8_t geber(uint8_t bits_alt1, uint8_t bits_neu);
 | 
| 58 | uint8_t taster(uint16_t wert);
 | 
| 59 | void senden(uint8_t adresse, uint16_t wert);
 | 
| 60 | 
 | 
| 61 | /**************************************************
 | 
| 62 |  *                          *
 | 
| 63 |  *   Initialisierung der globalen Variablen      *
 | 
| 64 |  *   Diese werden in main() und in der ISR      *
 | 
| 65 |  *   benötigt                    *
 | 
| 66 |  *                          *
 | 
| 67 |  **************************************************/
 | 
| 68 | 
 | 
| 69 |    //vol, pitch, fader, lpbs, rpbs sind werte vom ADC
 | 
| 70 |   uint16_t lvol, lpitch, mvol, fader, rpitch, rvol, lpbs, rpbs;
 | 
| 71 |   uint16_t lvol_old, lpitch_old, mvol_old, fader_old, rpitch_old, rvol_old, lpbs_old, rpbs_old;
 | 
| 72 |   uint16_t lpbs_temp[10]={0,0,0,0,0,0,0,0,0,0};
 | 
| 73 |   uint8_t alvol, alpitch, amvol, afader, arpitch, arvol, altaste, artaste;
 | 
| 74 |   uint8_t shift, trigger=0;
 | 
| 75 | 
 | 
| 76 |   //Digitalwerte von den Drehgebern
 | 
| 77 |   uint8_t leh, lem, lel, reh, rem, rel, ljw, rjw, hpvol, hpsel;
 | 
| 78 |   uint8_t aleh, alem, alel, areh, arem, arel, aljw, arjw, ahpvol, ahpsel;
 | 
| 79 |   uint8_t leh_old, lem_old, lel_old, reh_old, rem_old, rel_old, ljw_old, rjw_old, hpvol_old, hpsel_old;
 | 
| 80 |   uint8_t ljw_old2, rjw_old2;
 | 
| 81 |   //Zähler zur ADC-Kanal auswahl
 | 
| 82 |   uint8_t zaehler, k;
 | 
| 83 | 
 | 
| 84 | int main(void)
 | 
| 85 | {
 | 
| 86 |   
 | 
| 87 |   
 | 
| 88 | /**************************************************
 | 
| 89 |  *                          *
 | 
| 90 |  *   Initialisierung der Variablen für den FIFO    *
 | 
| 91 |  *                          *
 | 
| 92 |  **************************************************/
 | 
| 93 | 
 | 
| 94 | //daten[200]: FIFO für die Datenvariablen
 | 
| 95 | //adresse[200]: FIFO für die Adressvariablen
 | 
| 96 | //i: Zählvariable für den schreibenden Zugriff auf das FIFO
 | 
| 97 | //j: Zählvariable für den lesenden Zugriff auf das FIFO
 | 
| 98 | //imax: maximal mögliche Anzahl schreibender Einträge im nächsten Zyklus
 | 
| 99 | //jmax: maximal mögliche Anzahl lesender Einträge
 | 
| 100 | //zaehler: Zählvariable für die Auswahl des Analogeinganges
 | 
| 101 | 
 | 
| 102 |   uint8_t i, j, imax, jmax, adresse[200];
 | 
| 103 |   uint16_t daten[200];
 | 
| 104 |   i = 0;
 | 
| 105 |   j = 0;
 | 
| 106 |   imax = 200;
 | 
| 107 |   jmax = 200;
 | 
| 108 |   zaehler = 0;
 | 
| 109 | 
 | 
| 110 | /*********************************************************
 | 
| 111 |  *                               *
 | 
| 112 |  *   Initialisierung der Variablen für die Reglerdaten   *
 | 
| 113 |  *   entsprechend den Bezeichnungen der Bauteile     *
 | 
| 114 |  *                               *
 | 
| 115 |  *********************************************************/
 | 
| 116 | 
 | 
| 117 |   leh = 128;
 | 
| 118 |   lem = 128;
 | 
| 119 |   lel = 128;
 | 
| 120 |   reh = 128;
 | 
| 121 |   rem = 128;
 | 
| 122 |   rel = 128;
 | 
| 123 |   ljw = 128;
 | 
| 124 |   rjw = 128;
 | 
| 125 |   hpsel = 128;
 | 
| 126 |   hpvol = 128;
 | 
| 127 | 
 | 
| 128 |   leh_old = 0xFF;
 | 
| 129 |   lem_old = 0xFF;
 | 
| 130 |   lel_old = 0xFF;
 | 
| 131 |   reh_old = 0xFF;
 | 
| 132 |   rem_old = 0xFF;
 | 
| 133 |   rel_old = 0xFF;
 | 
| 134 |   ljw_old = 0xFF;
 | 
| 135 |   rjw_old = 0xFF;
 | 
| 136 |   hpvol_old = 0xFF;
 | 
| 137 |   hpsel_old = 0xFF;
 | 
| 138 |   ljw_old2 = 0xFF;
 | 
| 139 |   rjw_old2 = 0xFF;
 | 
| 140 | 
 | 
| 141 |   lvol = 0;
 | 
| 142 |   lpitch = 0;
 | 
| 143 |   mvol = 0;
 | 
| 144 |   fader = 0;
 | 
| 145 |   rpitch  = 0;
 | 
| 146 |   rvol  = 0;
 | 
| 147 |   lpbs = 0;
 | 
| 148 |   rpbs = 0;
 | 
| 149 | 
 | 
| 150 |   lvol_old = 0xFFFF;
 | 
| 151 |   lpitch_old = 0xFFFF;
 | 
| 152 |   mvol_old = 0xFFFF;
 | 
| 153 |   fader_old = 0xFFFF;
 | 
| 154 |   rpitch_old  = 0xFFFF;
 | 
| 155 |   rvol_old  = 0xFFFF;
 | 
| 156 |   lpbs_old = 0xFFFF;
 | 
| 157 |   rpbs_old = 0xFFFF;
 | 
| 158 | 
 | 
| 159 | 
 | 
| 160 | /***************************************************************
 | 
| 161 |  *                                   *
 | 
| 162 |  *   Initialisierung der Adressvariablen für die Reglerdaten   *
 | 
| 163 |  *                                   *
 | 
| 164 |  ***************************************************************/
 | 
| 165 |   
 | 
| 166 |   alvol = 0x10;
 | 
| 167 |   alpitch = 0x18;
 | 
| 168 |   amvol = 0x20;
 | 
| 169 |   afader = 0x28;
 | 
| 170 |   arpitch = 0x30;
 | 
| 171 |   arvol = 0x38;
 | 
| 172 |   aleh = 0x40;
 | 
| 173 |   alem = 0x48;
 | 
| 174 |   alel = 0x50;
 | 
| 175 |   ahpvol = 0x58;
 | 
| 176 |   areh = 0x60;
 | 
| 177 |   arem = 0x68;
 | 
| 178 |   arel = 0x70;
 | 
| 179 |   aljw = 0x78;
 | 
| 180 |   arjw = 0x80;
 | 
| 181 |   ahpsel = 0x88;
 | 
| 182 |   altaste = 0x90;
 | 
| 183 |   artaste = 0x98;
 | 
| 184 | 
 | 
| 185 | /*********************************************************
 | 
| 186 |  *                             *
 | 
| 187 |  *   Initialisierung der Ports des µC           *
 | 
| 188 |  *   PORTx für die Aktivierung der Pull-Up Widerstände   *
 | 
| 189 |  *   DDRx für die Angabe der Datenrichtung (I/O)     *
 | 
| 190 |  *                             *
 | 
| 191 |  *********************************************************/
 | 
| 192 | 
 | 
| 193 | //PORTx: Einstellung für die Pull-Up Widerstände
 | 
| 194 | //DDRx: Einstellung für die Datenrichtung (I/O)
 | 
| 195 |     
 | 
| 196 |   PORTA = 0x00;
 | 
| 197 |   DDRA = 0x00;
 | 
| 198 |   PORTB = 0x3F;
 | 
| 199 |   DDRB = 0xC0;
 | 
| 200 |   PORTC = 0xFF;
 | 
| 201 |   DDRC = 0x00;
 | 
| 202 |   PORTD = 0xFC;
 | 
| 203 |   DDRD = 0x02;
 | 
| 204 | 
 | 
| 205 | /***********************************************************************
 | 
| 206 |  *                                       *
 | 
| 207 |  *   Initialisierung der Variablen für den USART und des AD-Wandlers   *
 | 
| 208 |  *                                       *
 | 
| 209 |  ***********************************************************************/
 | 
| 210 | 
 | 
| 211 | //UBRR: Register zur Einstellung der Baudrate
 | 
| 212 | //RXEN: Aktivierung des µC zum Empfangen von Daten
 | 
| 213 | //TXEN: Aktivierung des µC zum Senden von Daten
 | 
| 214 | //URSEL: Schreibzugriff auf UCSRC Register
 | 
| 215 | //USBS: Anzahl der Stoppbits, hier 1
 | 
| 216 | //UCSZ0: Anzahl der Datenbits, hier 8
 | 
| 217 | 
 | 
| 218 |   UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)>>8);
 | 
| 219 |   UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);
 | 
| 220 | 
 | 
| 221 |   
 | 
| 222 |   // Enable receiver and transmitter; enable RX interrupt
 | 
| 223 |   UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
 | 
| 224 | 
 | 
| 225 |   //asynchronous 8N1
 | 
| 226 |   UCSRC = (1 << URSEL) | (3 << UCSZ0);
 | 
| 227 | 
 | 
| 228 | 
 | 
| 229 | //ADEN: Aktivierung des AD-Wandlers
 | 
| 230 | //ADPS0-2: Teilungsfaktor für AD-Takt, hier 64
 | 
| 231 | //ADIE: Aktivierung des AD-Wandler Interrupts
 | 
| 232 | //ADMUX: Auswahl des AD-Input Pins
 | 
| 233 | 
 | 
| 234 |   ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
 | 
| 235 |   ADCSRA |= (1<<ADIE);
 | 
| 236 |   ADMUX = 0x20;
 | 
| 237 |   
 | 
| 238 | /**********************************************************************
 | 
| 239 |  *                                    *
 | 
| 240 |  *   Aktivieren des Global Interrupt Enable Flags im Statusregister   *
 | 
| 241 |  *   Starten des AD-Wandler für die Initialisierung            *
 | 
| 242 |  *                                    *
 | 
| 243 |  **********************************************************************/
 | 
| 244 | 
 | 
| 245 |   sei(); //Aktivierung des Global Interrupt Enable Flags im Statusregister (SREG)
 | 
| 246 | 
 | 
| 247 |   ADCSRA |= (1<<ADSC); //Aktivierung des AD-Wandlers
 | 
| 248 |   while(!(ADCSRA & 0x10)) //Warten auf Beendigung der AD-Wandlung
 | 
| 249 |   {
 | 
| 250 | 
 | 
| 251 |   }
 | 
| 252 | 
 | 
| 253 | /**************************************************************************
 | 
| 254 |  *                                      *
 | 
| 255 |  *   Beginn der Endlosschleife zur Abfrage der Dirty-Bits          *
 | 
| 256 |  *   1) Prüfen ob noch genügend Platz im FIFO ist (30 Werte mindestens)   *
 | 
| 257 |  *      - "i" ist die Zählvariable der schreibenden Einträge im FIFO    *
 | 
| 258 |  *    - "imax" ist die Maximalanzahl von schreibbaren Einträgen      *
 | 
| 259 |  *   2) Prüfen ob im jeweiligen Adressbyte das Dirty-Bit gesetzt ist    *
 | 
| 260 |  *    - Maskierung mit 0x04 und gleichzeitigen Prüfen aus "TRUE"      *
 | 
| 261 |  *   3) Wenn "FALSE" ist wird das nächste Adressbyte geprüft        *
 | 
| 262 |  *   4) Wenn "TRUE" ist, dann werden der Interrupt deaktiviert,        *
 | 
| 263 |  *     Adress- und Datenbyte in den FIFO geschrieben, das Dirty-Bit    *
 | 
| 264 |  *    gelöscht, der Interrupt aktiviert und "i" inkrementiert.      *
 | 
| 265 |  *                                      *
 | 
| 266 |  **************************************************************************/
 | 
| 267 | 
 | 
| 268 |   while(1)   //Endlosschleife
 | 
| 269 |   {
 | 
| 270 |     if((i+30)<imax)   //Überprüfung ob genügend Speicherplatz im FIFO vorhanden ist
 | 
| 271 |     {
 | 
| 272 |       if(alvol & 0x04)   ///Überprüfung, ob das Dirty-Bit gesetzt ist
 | 
| 273 |       {
 | 
| 274 |         cli();   //Löschen des Global Interrupt Enable Flags im Statusregister
 | 
| 275 |         alvol &= ~0x04;   //Löschen des Dirty-Bits
 | 
| 276 |         adresse[i] = alvol;   //Speichern der Adressvariablen im FIFO
 | 
| 277 |         daten[i] = (lvol >> 6);   //Speicherung der Datenvariablen im FIFO
 | 
| 278 |         sei();   //Setzen des Global Interrupt Enable Flags im Statusregister
 | 
| 279 |         i++;   //Inkrementierung des Indizes für den schreibenden Zugriff auf das FIFO
 | 
| 280 |       }
 | 
| 281 |       if(alpitch & 0x04)
 | 
| 282 |       {
 | 
| 283 |         cli();
 | 
| 284 |         alpitch &= ~0x04;
 | 
| 285 |         adresse[i] = alpitch;
 | 
| 286 |         daten[i] = (lpitch >> 6);
 | 
| 287 |         sei();
 | 
| 288 |         i++;
 | 
| 289 |       }
 | 
| 290 |       if(amvol & 0x04)
 | 
| 291 |       {
 | 
| 292 |         cli();
 | 
| 293 |         amvol &= ~0x04;
 | 
| 294 |         adresse[i] = amvol;
 | 
| 295 |         daten[i] = (mvol >> 6);
 | 
| 296 |         sei();
 | 
| 297 |         i++;
 | 
| 298 |       }
 | 
| 299 |       if(afader & 0x04)
 | 
| 300 |       {
 | 
| 301 |         cli();
 | 
| 302 |         afader &= ~0x04;
 | 
| 303 |         adresse[i] = afader;
 | 
| 304 |         daten[i] = (fader >> 6);
 | 
| 305 |         sei();
 | 
| 306 |         i++;
 | 
| 307 |       }
 | 
| 308 |       if(arpitch & 0x04)
 | 
| 309 |       {
 | 
| 310 |         cli();
 | 
| 311 |         arpitch &= ~0x04;
 | 
| 312 |         adresse[i] = arpitch;
 | 
| 313 |         daten[i] = (rpitch >> 6);
 | 
| 314 |         sei();
 | 
| 315 |         i++;
 | 
| 316 |       }
 | 
| 317 |       if(arvol & 0x04)
 | 
| 318 |       {  
 | 
| 319 |         cli();
 | 
| 320 |         arvol &= ~0x04;
 | 
| 321 |         adresse[i] = arvol;
 | 
| 322 |         daten[i] = (rvol >> 6);
 | 
| 323 |         sei();
 | 
| 324 |         i++;
 | 
| 325 |       }
 | 
| 326 |       if(aleh & 0x04)
 | 
| 327 |       {
 | 
| 328 |         cli();
 | 
| 329 |         aleh &= ~0x04;
 | 
| 330 |         adresse[i] = aleh;
 | 
| 331 |         daten[i] = leh;
 | 
| 332 |         sei();
 | 
| 333 |         i++;
 | 
| 334 |       }
 | 
| 335 |       if(alem & 0x04)
 | 
| 336 |       {
 | 
| 337 |         cli();
 | 
| 338 |         alem &= ~0x04;
 | 
| 339 |         adresse[i] = alem;
 | 
| 340 |         daten[i] = lem;
 | 
| 341 |         sei();
 | 
| 342 |         i++;
 | 
| 343 |       }
 | 
| 344 |       if(alel & 0x04)
 | 
| 345 |       {
 | 
| 346 |         cli();
 | 
| 347 |         alel &= ~0x04;
 | 
| 348 |         adresse[i] = alel;
 | 
| 349 |         daten[i] = lel;
 | 
| 350 |         sei();
 | 
| 351 |         i++;
 | 
| 352 |       }
 | 
| 353 |       if(ahpvol & 0x04)
 | 
| 354 |       {
 | 
| 355 |         cli();
 | 
| 356 |         ahpvol &= ~0x04;
 | 
| 357 |         adresse[i] = ahpvol;
 | 
| 358 |         daten[i] = hpvol;
 | 
| 359 |         sei();
 | 
| 360 |         i++;
 | 
| 361 |       }
 | 
| 362 |       if(areh & 0x04)
 | 
| 363 |       {
 | 
| 364 |         cli();
 | 
| 365 |         areh &= ~0x04;
 | 
| 366 |         adresse[i] = areh;
 | 
| 367 |         daten[i] = reh;
 | 
| 368 |         sei();
 | 
| 369 |         i++;
 | 
| 370 |       }
 | 
| 371 |       if(arem & 0x04)
 | 
| 372 |       {
 | 
| 373 |         cli();
 | 
| 374 |         arem &= ~0x04;
 | 
| 375 |         adresse[i] = arem;
 | 
| 376 |         daten[i] = rem;
 | 
| 377 |         sei();
 | 
| 378 |         i++;
 | 
| 379 |       }
 | 
| 380 |       if(arel & 0x04)
 | 
| 381 |       {
 | 
| 382 |         cli();
 | 
| 383 |         arel &= ~0x04;
 | 
| 384 |         adresse[i] = arel;
 | 
| 385 |         daten[i] = rel;
 | 
| 386 |         sei();
 | 
| 387 |         i++;
 | 
| 388 |       }
 | 
| 389 |       if(aljw & 0x04)
 | 
| 390 |       {
 | 
| 391 |         cli();
 | 
| 392 |         aljw &= ~0x04;
 | 
| 393 |         adresse[i] = aljw;
 | 
| 394 |         daten[i] = ljw;
 | 
| 395 |         sei();
 | 
| 396 |         i++;
 | 
| 397 |       }
 | 
| 398 |       if(arjw & 0x04)
 | 
| 399 |       {
 | 
| 400 |         cli();
 | 
| 401 |         arjw &= ~0x04;
 | 
| 402 |         adresse[i] = arjw;
 | 
| 403 |         daten[i] = rjw;
 | 
| 404 |         sei();
 | 
| 405 |         i++;
 | 
| 406 |       }
 | 
| 407 |       if(ahpsel & 0x04)
 | 
| 408 |       {
 | 
| 409 |         cli();
 | 
| 410 |         ahpsel &= ~0x04;
 | 
| 411 |         adresse[i] = ahpsel;
 | 
| 412 |         daten[i] = hpsel;
 | 
| 413 |         sei();
 | 
| 414 |         i++;
 | 
| 415 |       }
 | 
| 416 |       if(altaste & 0x04)
 | 
| 417 |       {
 | 
| 418 |         cli();
 | 
| 419 |         altaste &= ~0x04;
 | 
| 420 |         adresse[i] = altaste;
 | 
| 421 |         daten[i] = lpbs;
 | 
| 422 |         sei();
 | 
| 423 |         i++;
 | 
| 424 |       }
 | 
| 425 |       if(artaste & 0x04)
 | 
| 426 |       {
 | 
| 427 |         cli();
 | 
| 428 |         artaste &= ~0x04;
 | 
| 429 |         adresse[i] = artaste;
 | 
| 430 |         daten[i] = rpbs;
 | 
| 431 |         sei();
 | 
| 432 |         i++;
 | 
| 433 |       }
 | 
| 434 |     }
 | 
| 435 | 
 | 
| 436 | /***********************************************************************************
 | 
| 437 |  *                                           *
 | 
| 438 |  *   5) Wenn mehr geschriebene als gelesene Daten im FIFO sind,             *
 | 
| 439 |  *     wird die Funktion "senden" aufgerufen und "j" inkrementiert           *
 | 
| 440 |  *    - "j" ist die Zählvariable der lesenden Einträge im FIFO           *
 | 
| 441 |  *    - "jmax" ist die Maximalanzahl der zu lesenden Einträgen           *
 | 
| 442 |  *   6) Wenn "i" größer als 170 wird, werden "imax", "jmax", und "i" neu gesetzt   *
 | 
| 443 |  *   7) Wenn "j" die Maximalanzahl erreicht, wird j zurückgesetzt           *
 | 
| 444 |  *   Ende der Endlosschleife                             *
 | 
| 445 |  *                                           *
 | 
| 446 |  ***********************************************************************************/
 | 
| 447 | 
 | 
| 448 |     if(i!=j)   //Überprüfung ob Indizes für schreibenden und lesenden Zugriff gleich ist, Index für schreibenden Zugriff ist immer voreilend
 | 
| 449 |     {
 | 
| 450 |       if(UCSRA & 0x20)   //Überprüfung ob das Senden-Register leer ist
 | 
| 451 |       {
 | 
| 452 |         senden(adresse[j], daten[j]);   //Aufruf der Funktion senden
 | 
| 453 |         j++;   //Inkrementierung des Indizes für den lesenden Zugriff
 | 
| 454 |         if(imax<=(i+30)) imax++;   //Überprüfung, ob noch Platz im FIFO für zu speichernde Werte ist
 | 
| 455 |       }
 | 
| 456 |     }
 | 
| 457 | 
 | 
| 458 |     if(i>170)   //Überprüfung, ob FIFO beim nächsten Durchlauf überlaufen könnte
 | 
| 459 |     {
 | 
| 460 |       imax = j;   //Festlegung der maximal zu schreibenden Einträge
 | 
| 461 |       jmax = i;   //Festlegung der maximal zu lesenden Einträge
 | 
| 462 |       i = 0;   //Reset des Indizes der schreibenden Einträge
 | 
| 463 |     }
 | 
| 464 | 
 | 
| 465 |     if(j==jmax) j = 0;   //Wenn die maximal zu lesende Anzahl der lesenden Einträge erreicht ist, wird Index für die lesenden Einträge resetet
 | 
| 466 | 
 | 
| 467 |   }
 | 
| 468 |       
 | 
| 469 |   return 0;
 | 
| 470 | }
 | 
| 471 | 
 | 
| 472 | /***********************************************************************************
 | 
| 473 |  *                                           *
 | 
| 474 |  *   Beginn der ISR, die aufgerufen wird, wenn die AD-Wandlung abgeschlossen ist   *
 | 
| 475 |  *                                           *
 | 
| 476 |  ***********************************************************************************/
 | 
| 477 | 
 | 
| 478 | ISR(_VECTOR(14))
 | 
| 479 | {
 | 
| 480 | 
 | 
| 481 | /******************************************************************************************
 | 
| 482 |  *                                              *
 | 
| 483 |  *   Auswahl der zu vergleichenden Reglervariablen mit dem ADC-Register,          *
 | 
| 484 |  *   das mit dem Ergfebnis der vorherigen Wandlung belegt ist                *
 | 
| 485 |  *   1) Wenn Ungleichheit besteht wird die Datenvariable mit dem  ADCH Register belegt,   *
 | 
| 486 |  *    und das Dirty-Bit gesetzt. Bei xPBS wird eine extra Funktion aufgerufen.        *
 | 
| 487 |  *   2) Wenn Gleichheit besteht, wird die Funktion fortgeführt                *
 | 
| 488 |  *   3) Wenn "zaehler" einmal alle AD-Pins durchlaufen hat, wird er auf "0" gesetzt      *
 | 
| 489 |  *                                              *
 | 
| 490 |  ******************************************************************************************/
 | 
| 491 | 
 | 
| 492 |   switch(zaehler)   //Auswahl des AD-Einganges
 | 
| 493 |   {
 | 
| 494 |     case 0: if((lvol != ADC) && (lvol_old != ADC))
 | 
| 495 |         {
 | 
| 496 |           lvol_old=lvol;
 | 
| 497 |           lvol = ADC;
 | 
| 498 |           alvol |= 0x04;
 | 
| 499 |         };
 | 
| 500 |     break;
 | 
| 501 |     case 1: if((lpitch != ADC) && (lpitch_old != ADC))   //bei Auswahl Vergleich, ob sich Datenvariable geändert hat
 | 
| 502 |         {
 | 
| 503 |           lpitch_old = lpitch;
 | 
| 504 |           lpitch = ADC;   //Speichern der neuen Datenvariablen
 | 
| 505 |           alpitch |= 0x04;   //setzen des Dirty-Bits
 | 
| 506 |         };
 | 
| 507 |     break;
 | 
| 508 |     case 2: /*{
 | 
| 509 |           if((lpbs != ADC) && (lpbs_old!=ACD))
 | 
| 510 |           {
 | 
| 511 |             trigger=1;
 | 
| 512 |           }
 | 
| 513 |           for(shift=8;shift>=0;shift--)
 | 
| 514 |           {
 | 
| 515 |             lpbs_temp[(shift+1)]=lpbs_temp[shift];
 | 
| 516 |           }
 | 
| 517 |           lpbs_temp[9]=lpbs_temp[8];
 | 
| 518 |           lpbs_temp[8]=lpbs_temp[7];
 | 
| 519 |           lpbs_temp[7]=lpbs_temp[6];
 | 
| 520 |           lpbs_temp[6]=lpbs_temp[5];
 | 
| 521 |           lpbs_temp[5]=lpbs_temp[4];
 | 
| 522 |           lpbs_temp[4]=lpbs_temp[3];
 | 
| 523 |           lpbs_temp[3]=lpbs_temp[2];
 | 
| 524 |           lpbs_temp[2]=lpbs_temp[1];
 | 
| 525 |           lpbs_temp[1]=lpbs_temp[0];
 | 
| 526 |           lpbs_temp[0]=ADC;
 | 
| 527 | 
 | 
| 528 |           if((lpbs_temp[0] == lpbs_temp[1]) && trigger==1)
 | 
| 529 |           {
 | 
| 530 |             lpbs_old=lpbs;
 | 
| 531 |             lpbs=ADC;
 | 
| 532 |             altaste |= 0x04;
 | 
| 533 |             trigger=0;
 | 
| 534 |           } 
 | 
| 535 |         };*/
 | 
| 536 |     break;
 | 
| 537 |     case 3: if((mvol != ADC) && (mvol_old != ADC))
 | 
| 538 |         {
 | 
| 539 |           mvol_old = mvol;
 | 
| 540 |           mvol = ADC;
 | 
| 541 |           amvol |= 0x04;
 | 
| 542 |         };
 | 
| 543 |     break;
 | 
| 544 |     case 4: if((fader != ADC) && (fader_old != ADC))   
 | 
| 545 |         {
 | 
| 546 |           fader_old=fader;      
 | 
| 547 |           fader = ADC;   
 | 
| 548 |           afader |= 0x04;
 | 
| 549 | 
 | 
| 550 |         };
 | 
| 551 |     break;
 | 
| 552 |     case 5: /*if(rpbs != ADC)
 | 
| 553 |         {
 | 
| 554 |           rpbs = ADC;
 | 
| 555 |           artaste |= 0x04;
 | 
| 556 |         };
 | 
| 557 |     break;*/
 | 
| 558 |     case 6: if((rpitch != ADC) &&(rpitch_old != ADC))
 | 
| 559 |         {
 | 
| 560 |           rpitch_old = rpitch;
 | 
| 561 |           rpitch = ADC;
 | 
| 562 |           arpitch |= 0x04;
 | 
| 563 |         };
 | 
| 564 |     break;
 | 
| 565 |     case 7: if((rvol != ADC) && (rvol_old != ADC))
 | 
| 566 |         {
 | 
| 567 |           rvol_old = rvol;
 | 
| 568 |           rvol = ADC;
 | 
| 569 |           arvol |= 0x04;
 | 
| 570 |         };
 | 
| 571 |     break;
 | 
| 572 |   }
 | 
| 573 | 
 | 
| 574 |   zaehler++;   //Inkrmentierung zur Auswahl des nächsten Analogeingangs
 | 
| 575 |   if(zaehler==8) zaehler = 0;   //Wenn alle Analogeingänge abgefragt wurden, wird der Zähler zurückgesetzt
 | 
| 576 | 
 | 
| 577 |   ADMUX = 0x20 | zaehler;   //Setzen des Auswahlregisters für den Analogeingang
 | 
| 578 |   ADCSRA |= (1<<ADSC);   //Aktivieren des AD-Wandlers
 | 
| 579 | 
 | 
| 580 | /*******************************************************************************
 | 
| 581 |  *                                         *
 | 
| 582 |  *   Vergleichen aller nicht AD-Variablen mit den jeweiligen Pinzuständen     *
 | 
| 583 |  *   1) Belegen von "k" mit den Variablenzuständen                 *
 | 
| 584 |  *   2) Vergleichen von "k" mit den Datenvariablen                 *
 | 
| 585 |  *   3) Wenn "FALSE", dann werden die restlichen Werte verglichen         *
 | 
| 586 |  *   4) Wenn "TRUE", dann wird die Funktion zur Berechnung der Geberwerte     *
 | 
| 587 |  *    aufgerufen, das Dirty-Bit gesetzt und die Vergleichsvariable belegt.   *
 | 
| 588 |  *                                         *
 | 
| 589 |  *******************************************************************************/
 | 
| 590 | 
 | 
| 591 |   k = PINB & 0x03;   //Belegung einer Variable mit den entsprechenden Pins
 | 
| 592 |   if(k!=leh_old)   //Überprüfung, ob sich die Bitkombination geändert hat
 | 
| 593 |   {
 | 
| 594 |     leh = geber(k, leh_old);   //Aufrufen der Funktion "geber" zur Berechnung des absoluten Wertes
 | 
| 595 |     aleh |= 0x04;   //setzen des Dirty-Bits
 | 
| 596 |     leh_old=k;
 | 
| 597 |   }
 | 
| 598 |   
 | 
| 599 |   k = (PINB & 0x0C) >> 2;  
 | 
| 600 |   if(k!=lem_old)
 | 
| 601 |   {
 | 
| 602 |     lem = geber(k, lem_old);
 | 
| 603 |     alem |= 0x04;
 | 
| 604 |     lem_old=k;
 | 
| 605 |   }
 | 
| 606 | 
 | 
| 607 |   k = (PINB & 0x30) >> 4;
 | 
| 608 |   if(k!=lel_old)
 | 
| 609 |   {
 | 
| 610 |     lel = geber(k, lel_old);
 | 
| 611 |     alel |= 0x04;
 | 
| 612 |     lel_old=k;
 | 
| 613 |   }
 | 
| 614 | 
 | 
| 615 |   k = PINC & 0x03;
 | 
| 616 |   if(k!=hpvol_old)
 | 
| 617 |   {
 | 
| 618 |     hpvol = geber(k, hpvol_old);
 | 
| 619 |     ahpvol |= 0x04;
 | 
| 620 |     hpvol_old=k;
 | 
| 621 |   }
 | 
| 622 | 
 | 
| 623 |   k = (PINC & 0x0C) >> 2;
 | 
| 624 |   if(k!=reh_old)
 | 
| 625 |   {
 | 
| 626 |     reh = geber(k, reh_old);
 | 
| 627 |     areh |= 0x04;
 | 
| 628 |     reh_old=k;
 | 
| 629 |   }
 | 
| 630 | 
 | 
| 631 |   k = (PINC & 0x30) >> 4;
 | 
| 632 |   if(k!=rem_old)
 | 
| 633 |   {
 | 
| 634 |     rem = geber(k, rem_old);
 | 
| 635 |     arem |= 0x04;
 | 
| 636 |     rem_old=k;
 | 
| 637 |   }
 | 
| 638 | 
 | 
| 639 |   k = (PINC & 0xC0) >> 6;
 | 
| 640 |   if(k!=rel_old)
 | 
| 641 |   {
 | 
| 642 |     rel = geber(k, rel_old);
 | 
| 643 |     arel |= 0x04;
 | 
| 644 |     rel_old=k;
 | 
| 645 |   }
 | 
| 646 | 
 | 
| 647 |   k = (PIND & 0x0C) >> 2;
 | 
| 648 |   if((k!=ljw_old) && (k!=ljw_old2))
 | 
| 649 |   {
 | 
| 650 |     ljw = geber(k, ljw_old);
 | 
| 651 |     aljw |= 0x04;
 | 
| 652 |     
 | 
| 653 |     ljw_old=k;
 | 
| 654 |   }
 | 
| 655 |   ljw_old2=ljw_old;
 | 
| 656 |   k = (PIND & 0x30) >> 4;
 | 
| 657 |   if((k!=rjw_old) && (k!=rjw_old))
 | 
| 658 |   {
 | 
| 659 |     rjw = geber(k, rjw_old2);
 | 
| 660 |     arjw |= 0x04;
 | 
| 661 |     
 | 
| 662 |     rjw_old=k;
 | 
| 663 |   }
 | 
| 664 |   rjw_old2=rjw_old;
 | 
| 665 |   k = (PIND & 0xC0) >> 6;
 | 
| 666 |   if(k!=hpsel_old)
 | 
| 667 |   {
 | 
| 668 |     hpsel = geber(k, hpsel_old);
 | 
| 669 |     if(hpsel==1)
 | 
| 670 |     {
 | 
| 671 |       PINB |=0x80;
 | 
| 672 |       PINB &=0xBF;
 | 
| 673 |     }
 | 
| 674 |     if(hpsel==3)
 | 
| 675 |     {
 | 
| 676 |       PINB |=0x40;
 | 
| 677 |       PINB &=0x7F;
 | 
| 678 |     }
 | 
| 679 |     ahpsel |= 0x04;
 | 
| 680 |     hpsel_old=k;
 | 
| 681 |   }
 | 
| 682 | }
 | 
| 683 | 
 | 
| 684 | /**********************************************************************************
 | 
| 685 |  *                                            *           *
 | 
| 686 |  *   Die ISR wird aufgerufen, sobald ein Zeichen über die USART-Schnittstelle     *
 | 
| 687 |  *   empfangen wurde. Das empfangene Zeichen steht dann im USART-Datenregister.   *
 | 
| 688 |  *   Empfangen werden Anforderungen zur Datenübertragung. Es ist möglich vom PC   *
 | 
| 689 |  *   aus alle oder nur einzelne Werte neu anzufordern. Eine Neuanforderung        *
 | 
| 690 |  *   ist nur für die Werte der Schieberegler sinnvoll, da die Drehgeber und       *
 | 
| 691 |  *   die Taster im Normalzustand 0 sind. Das  Senden wird ausgelöst durch setzen  *
 | 
| 692 |  *   des jeweiligen Dirty-Bits.                            *
 | 
| 693 |  *                                          *
 | 
| 694 |  *********************************************************************************/
 | 
| 695 | ISR(_VECTOR(11))
 | 
| 696 | {
 | 
| 697 |   int8_t wert;
 | 
| 698 | 
 | 
| 699 |   wert=UDR;
 | 
| 700 | 
 | 
| 701 |   if (wert==0x99) //Alle Werte neu senden. Sendeanforderung durch Setzten des Dirty-Bits
 | 
| 702 |   {
 | 
| 703 |     alvol   |= 0x04;
 | 
| 704 |     alpitch |= 0x04;
 | 
| 705 |     amvol  |= 0x04;
 | 
| 706 |     afader   |= 0x04;
 | 
| 707 |     arpitch |= 0x04;
 | 
| 708 |     arvol  |= 0x04;
 | 
| 709 |   }
 | 
| 710 |   else
 | 
| 711 |   {
 | 
| 712 |     switch (wert)
 | 
| 713 |     {
 | 
| 714 |       case 0x10: 
 | 
| 715 |       {
 | 
| 716 |         alvol   |= 0x04;
 | 
| 717 |         break;
 | 
| 718 |       }
 | 
| 719 |       case 0x18:
 | 
| 720 |       {
 | 
| 721 |         alpitch |= 0x04;
 | 
| 722 |         break;
 | 
| 723 |       }
 | 
| 724 |       case 0x20:
 | 
| 725 |       {
 | 
| 726 |         amvol |= 0x04;
 | 
| 727 |         break;
 | 
| 728 |       }
 | 
| 729 |       case 0x28:
 | 
| 730 |       {
 | 
| 731 |         afader   |= 0x04;
 | 
| 732 |         break;
 | 
| 733 |       }
 | 
| 734 |       case 0x30:
 | 
| 735 |       {
 | 
| 736 |         arpitch |= 0x04;
 | 
| 737 |         break;
 | 
| 738 |       }
 | 
| 739 |       case 0x38:
 | 
| 740 |       {
 | 
| 741 |         arvol |= 0x04;
 | 
| 742 |         break;
 | 
| 743 |       }
 | 
| 744 |     }
 | 
| 745 |   }
 | 
| 746 | }
 | 
| 747 | 
 | 
| 748 | 
 | 
| 749 | /**********************************************************************************
 | 
| 750 |  *                                            *  
 | 
| 751 |  *   Der Funktion "geber" wird die Ausgabe der Drehgeber übergeben                *
 | 
| 752 |  *   Je nach Bitkombination wird die Drehrichtung bestimmt und ein Wert         *
 | 
| 753 |  *   zurückgegeben. Dieser Wert basiert auf dem Drehsinn eines "normalen"         *
 | 
| 754 |  *   Drehreglers in der HiFi-Technik (links=- und rechts=+).                      *
 | 
| 755 |  *                                            *                                            *
 | 
| 756 |  *********************************************************************************/
 | 
| 757 | uint8_t geber(uint8_t bits_alt, uint8_t bits_neu)   //Übergabe der alten und neuen Bitkombination, Datenvariable 
 | 
| 758 | {
 | 
| 759 |   uint8_t wert;  
 | 
| 760 | 
 | 
| 761 |   switch(bits_alt)
 | 
| 762 |   {
 | 
| 763 |     case 0x00: 
 | 
| 764 |     {    
 | 
| 765 |           if(bits_neu==0x01) //Linksdrehung
 | 
| 766 |             wert=1;
 | 
| 767 |           else if(bits_neu==0x02) //Rechtsdrehung
 | 
| 768 |             wert=3;  
 | 
| 769 |           else 
 | 
| 770 |             wert=2; //Keine Drehung
 | 
| 771 |           break;
 | 
| 772 |     }    
 | 
| 773 |     
 | 
| 774 |     case 0x01: 
 | 
| 775 |     {   
 | 
| 776 |           if(bits_neu==0x03) //Linksdrehung
 | 
| 777 |             wert=1;
 | 
| 778 |           else if(bits_neu==0x00) //Rechtsdrehung
 | 
| 779 |             wert=3;
 | 
| 780 |           else
 | 
| 781 |             wert=2;  //Keine Drehung
 | 
| 782 |           break;
 | 
| 783 |     }
 | 
| 784 | 
 | 
| 785 |     case 0x02: 
 | 
| 786 |     {   
 | 
| 787 |           if(bits_neu==0x00) //Linksdrehung
 | 
| 788 |             wert=1;
 | 
| 789 |           else if(bits_neu==0x03) //Rechtsdrehung
 | 
| 790 |             wert=3;
 | 
| 791 |           else
 | 
| 792 |             wert=2;  //Keine Drehung
 | 
| 793 |           break;
 | 
| 794 |     }
 | 
| 795 | 
 | 
| 796 |     case 0x03: 
 | 
| 797 |     {   
 | 
| 798 |           if(bits_neu==0x02) //Linksdrehung
 | 
| 799 |             wert=1;
 | 
| 800 |           else if(bits_neu==0x01) //Rechtsdrehung
 | 
| 801 |             wert=3;
 | 
| 802 |           else
 | 
| 803 |             wert=2;  //Keine Drehung
 | 
| 804 |           break;
 | 
| 805 |     }
 | 
| 806 |   
 | 
| 807 |     default: wert=0xFF; //Nur zu Debug-Zwecken
 | 
| 808 |   }
 | 
| 809 | 
 | 
| 810 | 
 | 
| 811 |   return wert;   //Rückgabe der Drehrichtung
 | 
| 812 | }
 | 
| 813 | 
 | 
| 814 | /***********************************************************************************************
 | 
| 815 |  *                                                 *
 | 
| 816 |  *   Der Funktion "taster" wird der Wert des ADC übergeben. Über ein Array, das die zu den     *
 | 
| 817 |  *   jeweiligen Tastenkominationen gehörenden Analogwerte beinhaltet erfolgt die Auswertung    *
 | 
| 818 |  *   Je nach Analogwert wird die Variable "taste" mit einem Wert belegt und zurückgegeben.     *
 | 
| 819 |  *                                                 *
 | 
| 820 |  ***********************************************************************************************/
 | 
| 821 | 
 | 
| 822 | uint8_t taster(uint16_t wert)   //Übergabe der Datenvariable
 | 
| 823 | {
 | 
| 824 |   uint16_t taste=0;   //Festlegung einer Speichervariablen
 | 
| 825 |   uint8_t i;
 | 
| 826 |   uint16_t widerstand[32]={524,533,541,551,560,570,580,590,601,613,624,636,649,662,676,690,705,720,737,754,771,790,809,830,851,874,898,923,950,979,1009};
 | 
| 827 |   
 | 
| 828 |   if(wert>=512)   //Folgender Block dient der Auswahl der Tasterkombination
 | 
| 829 |   {
 | 
| 830 |     for(i=0; i<32; i++)
 | 
| 831 |     {
 | 
| 832 |       if(wert <= widerstand[i])
 | 
| 833 |       {
 | 
| 834 |         taste=32-i;
 | 
| 835 |         break;
 | 
| 836 |       }
 | 
| 837 |     }
 | 
| 838 |   }
 | 
| 839 | 
 | 
| 840 |   else taste = 0x00;
 | 
| 841 | 
 | 
| 842 |   return taste;
 | 
| 843 | }
 | 
| 844 | 
 | 
| 845 | /****************************************************************************************
 | 
| 846 |  *                                            *
 | 
| 847 |  *   Der Funktion "senden" wird die entsprechende Adress- und Datenvariable übergeben   *
 | 
| 848 |  *   Unmittelbar nacheinander werden Adresse und Das High und Low-Byte der Daten-       *
 | 
| 849 |  *   variable gesendet. Im Anschluss wird noch ein Füll-Byte übetragen, da der PC mit   *
 | 
| 850 |  *   vier Byte besser umgehen kann. Dieses Füll-Byte zeigt zugleich auch das Ende eines *
 | 
| 851 |  *   Datensatzes an und kann somit zur Synchronisation verwendet werden.        *                                          *
 | 
| 852 |  ****************************************************************************************/
 | 
| 853 | 
 | 
| 854 | void senden (uint8_t adresse, uint16_t wert)   //Übergabe der Adress- und Datenvariable
 | 
| 855 | {
 | 
| 856 |   while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
 | 
| 857 | 
 | 
| 858 |   UDR = adresse;   //Adresse senden
 | 
| 859 | 
 | 
| 860 |   while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
 | 
| 861 | 
 | 
| 862 |   UDR = (wert >> 8 );   //Daten HIGH senden
 | 
| 863 | 
 | 
| 864 |   while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
 | 
| 865 | 
 | 
| 866 |   UDR = (wert & 0xFF);   //Daten LOW senden
 | 
| 867 | 
 | 
| 868 |   while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
 | 
| 869 | 
 | 
| 870 |   UDR = 'X';   //Auf 4 Byte auffüllen
 | 
| 871 | }
 |