5 #include <avr/interrupt.h>
10 * I2C Register Map (8 Bit)
11 * 0x00 Register select
12 * 0x01 Distance left MSB
13 * 0x02 Distance left LSB
14 * 0x03 Distance right MSB
15 * 0x04 Distance right LSB
21 #define TWI_ACK TWCR = (1<<TWEA) | (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
22 #define TWI_RESET TWCR &= ~((1 << TWSTO) | (1 << TWEN)); TWI_ACK
23 #define TWI_NAK TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
25 static volatile uint8_t ireg=0;
26 static volatile uint8_t bootloader=0;
27 static volatile uint16_t dist_left=0;
28 static volatile uint16_t dist_right=0;
32 static int16_t tmp16=0;
36 case 0x60: // start write
42 case 0x00: // register select
44 ireg--; // because we do ireg++ below
47 case 0xff: // bootloader
54 case 0xA8: // start read
57 case 0x01: // Distance left MSB
62 case 0x02: // Distance right LSB
66 case 0x03: // Distance right MSB
71 case 0x04: // Distance right LSB
87 uint16_t ReadChannel(uint8_t mux) {
91 ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
92 // setzen auf 8 (1) und ADC aktivieren (1)
94 ADMUX = mux; // Kanal waehlen
95 ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
97 /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
98 also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
99 ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
100 while ( ADCSRA & (1<<ADSC) ) {
101 // auf Abschluss der Konvertierung warten
103 result = ADCW; // ADCW muss einmal gelesen werden,
104 // sonst wird Ergebnis der nächsten Wandlung
105 // nicht übernommen.
107 /* Eigentliche Messung - Mittelwert aus 5 aufeinanderfolgenden Wandlungen */
111 ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
112 while ( ADCSRA & (1<<ADSC) ) {
113 // auf Abschluss der Konvertierung warten
115 result += ADCW; // Wandlungsergebnisse aufaddieren
118 ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
120 result /= 5; // Summe durch 5 teilen = arithm. Mittelwert
126 static unsigned short get_distance(uint8_t i) {
127 return ReadChannel(i);
140 printf("\r\nStart\r\n");
142 set_sleep_mode(SLEEP_MODE_IDLE);
147 dist_left = get_distance(0);
150 dist_right = get_distance(1);
152 case 0xff: // Magic reg that starts the bootloader
153 if (bootloader == 0xa5) {
156 void (*start)(void) = (void*)0x1800;