/* ================================================================================ This program measures the amount of light that is detected by both the bottom-side track sensor diodes. These measured values are used to control the brightness of the corresponding brake leds. The left brake led will shine brigther if the left track-sensor receives more light. The right brake led will shine dimmer if the right track-sensor receives more light. Timer/counter0 is running free, counting up from 0 to 255 and then restarts counting from 0. Each time timer/counter0 counts from 255 to 0, an interrupt will be generated. This will happen each 250us or with a frequency of 3906Hz. The timer/counter0 interrupt-handler function will start the AD-Converter to read one of both track sensors. As an AD-Conversion takes some time, the conversion is only started and if completed will generate an AD-Conversion-finished interrupt. The timer/counter0 interrupt function automatically toggles starting reading left or right track sensor. The AD-Conversion-finished interrupt-handler stores the measured value from left or right track-sensor in different track-sensor-variables. Timer1 is continuously counting up and then counting douwn. Each time when value 0 is reached an interrupt will occur. This interrupt function will copy the track-sensor-variables into compare value A and compare value B. When counter1 reached compare value A while upcounting or while downcounting an compareA interrupt will occur. Same story applies to B generating a compareB interrupt. Inside both interrupt handlers the corresponding brake-leds are toggled on or off. Using: - timer/counter0 with overflow interrupt - AD-Conversion with interrupt (interrupt toggles between reading left/right sensor) - timer/counter1 with zero/compareA/compareB interrupts ================================================================================ Program : Asuro 017, Build 001, Left/right tracksensor controls left/right breakled.c Release date : 2005-02-11 Author : Henk van Winkoop Build : 001, 2005-02-11, original release ================================================================================ */ //-------------------------------------------------------------------------------- // INCLUDES //-------------------------------------------------------------------------------- #include "hvwdefines.h" //-------------------------------------------------------------------------------- // GLOBAL VARIABLES //-------------------------------------------------------------------------------- volatile byte gyCurLftTrkSnsVal; volatile byte gyCurRgtTrkSnsVal; //================================================================================ // TOGGLE LEFT BRAKE LED //================================================================================ void vToggleLeftBrakeLed(void){ //---toggle-tracking-led---// //if tracking led is on if(PORTC&BOD_LFT_H){ //switch tracking led off SFRX(PORTC,BOD_LFT_L); } //if tracking led is off else{ //switch tracking led on SFRX(PORTC,BOD_LFT_H); } } //================================================================================ // TOGGLE RIGHT BRAKE LED //================================================================================ void vToggleRightBrakeLed(void){ //---toggle-tracking-led---// //if tracking led is on if(PORTC&BOD_RGT_H){ //switch tracking led off SFRX(PORTC,BOD_RGT_L); } //if tracking led is off else{ //switch tracking led on SFRX(PORTC,BOD_RGT_H); } } //================================================================================ // INIT UNUSED IO PORTS //================================================================================ void vInitUnusedIoPorts(void){ //disconnect both left engine connections from VCC //+-------------------------------------------------------------------------------------------+ //| Init microcontroller I/O-port D | //+-------------------------------------------------------------------------------------------+ //| | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|port name | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|pin number | 13 | 12 | 11 | 6 | 5 | 4 | 3 | 2 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|signal name|BOD_COM |TRK_LED |REV_LFT |FWD_LFT |SWI_IAC |SLD_RED |IR_TXD2 |IR_RXD | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( DDRD , REV_LFT_O|FWD_LFT_O ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( PORTD , REV_LFT_H|FWD_LFT_H ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //disconnect both right engine connections from VCC //+-------------------------------------------------------------------------------------------+ //| DDRB = Data Direction Register port B | //+-------------------------------------------------------------------------------------------+ //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|port name | PB7 | PB6 | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|pin number | 10 | 9 | 19 | 18 | 17 | 16 | 15 | 14 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|signal name| XTAL2 | XTAL1 |REV_RGT |FWD_RGT |IR_TXD1 |SPD_RGT |SPD_LFT |SLD_GRN | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( DDRB , REV_RGT_O|FWD_RGT_O ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( PORTB , REV_RGT_H|FWD_RGT_H ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //set left/right engine speed ports as output and low (low = engines disabled) //+-------------------------------------------------------------------------------------------+ //| DDRB = Data Direction Register port B | //+-------------------------------------------------------------------------------------------+ //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|port name | PB7 | PB6 | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|pin number | 10 | 9 | 19 | 18 | 17 | 16 | 15 | 14 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|signal name| XTAL2 | XTAL1 |REV_RGT |FWD_RGT |IR_TXD1 |SPD_RGT |SPD_LFT |SLD_GRN | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( DDRB , SPD_RGT_O|SPD_LFT_O ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( PORTB , SPD_RGT_L|SPD_LFT_L ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ } //================================================================================ // INIT TIMER COUNTER 1 MODE 10 //================================================================================ void vInitTimerCounter1Mode10(void){ //---init-timer-counter-register-1-for-controlling-engine-speeds---// //CLK-i/o lijkt 8MHz/2=4MHz te zijn! //In Waveform Generation Mode 1, 8-bit, TOP = 0xFF = 255 //In prescaler mode 1, Counter clock (CLK-i/o) should be external clock (8MHz) but seems to be external clock / 2 (4MHz) //Frequency = CLK-i/o / 8 / 256 = 4MHz / 8 / 256 = 2KHz //+-------------------------------------------------------------------------------------------+ //| TCCR1B = Timer Counter 1 Control Register B | //+-------------------------------------------------------------------------------------------+ //| | //| CSnn = Clock Source | //| 000 = no clock source, timer/counter stopped (counter max set to 0x00FF) | //| 001 = 8MHz/ 1 = 8.000.000Hz => /256 = 31250.00Hz = 32us | //| 010 = 8MHz/ 8 = 1.000.000Hz => /256 = 3906.25Hz = 256us | //| 011 = 8MHz/ 64 = 125.000Hz => /256 = 488.28Hz = 2048us | //| 100 = 8MHz/ 256 = 31.250Hz => /256 = 122.07Hz = 8.192us | //| 101 = 8MHz/1024 = 7.813Hz => /256 = 30.52Hz = 32.768us | //| 110 = External clock source on T0 pin. Clock on falling edge | //| 111 = External clock source on T0 pin. Clock on rising edge | //| | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|signal name| ICNC1_X | ICES1_X |RESERVED | WGM13_X | WGM12_X | CS12_X | CS11_X | CS10_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( TCCR1B , ICNC1_L | //no noise-canceler (no 4 clock AD conversion delay) ICES1_L | //no 'input capture' selection RESERVED | //unused WGM13_H | WGM12_L | //high part of timer1 operating mode 10 selection CS12_L | CS11_H | CS10_L ); //timer1 runs at 3906Hz (see list above) //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //+-------------------------------------------------------------------------------------------+ //| TCCR1A = Timer Counter 1 Control Register A | //+-------------------------------------------------------------------------------------------+ //| | //| | //| | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|signal name|COM1A1_X |COM1A0_X |COM1B1_X |COM1B0_X | FOC1A_X | FOC1B_X | WGM11_X | WGM10_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( TCCR1A , COM1A1_L |COM1A0_L | //deselect 'timer1 controlling pin OC1A (left engine speed) directly' COM1B1_L |COM1B0_L | //deselect 'timer1 controlling pin OC1B (right engine speed) directly' FOC1A_L | FOC1B_L | //set to 0 in PWM mode (for compatibility, see pdf page 96) WGM11_H | WGM10_L ); //low part of timer1 operating mode 10 selection //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //+-------------------------------------------------------------------------------------------+ //| TIMSK = Timer/Counter Interrupt Mask Register | //+-------------------------------------------------------------------------------------------+ //| | //| OCIE2 = timer/counter2, output-compare-match interrupt enable | //| TOIE2 = timer/counter2, overflow interrupt enable | //| TICIE1 = timer/counter1, input-capture interrupt enable | //| OCIE1A = timer/counter1, equal to output-compare-A-match register, interrupt enable | //| OCIE1B = timer/counter1, equal to output-compare-B-match register, interrupt enable | //| TOIE1 = timer/counter1 overflow interrupt enable | //| RESERVED = unused | //| TOIE0 = timer/counter0 overflow interrupt enable | //| | //+-------------------------------------------------------------------------------------------+ //| enable timer/counter1 interrupt on output compares A and B | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| | Timer2 | Timer2 | Timer1 | Timer1 | Timer1 | Timer1 | - | Timer0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|signal name| OCIE2_X | TOIE2_X |TICIE1_X |OCIE1A_X |OCIE1B_X | TOIE1_X |RESERVED | TOIE0_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( TIMSK , OCIE2_L | TOIE2_L |TICIE1_L |RESERVED | TOIE0_L | //not used OCIE1A_H |OCIE1B_H | //A + B compare interrupts enable TOIE1_H ); //timer1 overflow interrupt enable //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ } //================================================================================// // ENABLE GLOBAL INTERRUPT // //================================================================================// void vEnableGlobalInterrupt(void){ //+-------------------------------------------------------------------------------------------+ //| SREG = Status Register | //+-------------------------------------------------------------------------------------------+ //| | //| GIE = I = Global Interrupt Enable | //| BCS = T = Bit Copy Storage | //| HCF = H = Half Carry Flag | //| SB = S = Sign Bit | //| TCOF = V = Two's Complement Overflow Flag | //| GIE = I = Global Interrupt Enable | //| NF = N = Negative Flag | //| ZF = Z = Zero Flag | //| CF = C = Carry Flag | //| | //+-------------------------------------------------------------------------------------------+ //| programmer settings comment | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| SREG | GIE_X | BCS_X | HCF_X | SB_X | TCOF_X | NF_X | ZF_X | CF_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( SREG , GIE_H ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ // n . . . . . . . = 1 = global interrupt enable // . n . . . . . . = 1 = // . . n . . . . . = 1 = // . . . n . . . . = 1 = // . . . . n . . . = 1 = // . . . . . n . . = 1 = // . . . . . . n . = 1 = // . . . . . . . n = 1 = //+-------------------------------------------------------------------------------------------+ } /* //================================================================================// // SELECT LEFT TRACK SENSOR AS AD-CONVERTER INPUT // //================================================================================// void vSelectLeftTrackSensorAsAdcInput(void){ //+-------------------------------------------------------------------------------------------+ //| ADMUX = ADC Multiplexer Selection Register | //+-------------------------------------------------------------------------------------------+ //| | //| REFSn = select reference voltage source (= maximum measurement voltage value) | //| ADLAR = left justify or right justify measured value into register ADCH/ADCL | //| MUXn = select measurement-point to be connected to the AD-converter measurement input | //| | //+-------------------------------------------------------------------------------------------+ //| select AVCC pin as reference, use left justify, use left track sensor as measurement-point| //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| ADMUX | REFS1_X | REFS0_X | ADLAR_X |RESERVED | MUX3_X | MUX2_X | MUX1_X | MUX0_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( ADMUX , REFS1_L | REFS0_H | ADLAR_H |RESERVED | MUX3_L | MUX2_L | MUX1_H | MUX0_H ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ // n n . . . . . . = 00 = external AREF pin // n n . . . . . . = 01 = external AVCC pin with capacitor at AREF pin // n n . . . . . . = 10 = reserved // n n . . . . . . = 11 = internal 2.56V Voltage Reference with external capacitor at AREF pin // . . n . . . . . = 0 = right justify => ADCH:ADCL = ......98:76543210 // . . n . . . . . = 1 = left justify => ADCH:ADCL = 98765432:10...... // . . . . n n n n = select AD-Converter measurement input // n n n n = 0000-0111 = external pins ADC0 - ADC7 // n n n n = 1000-1101 = reserved // n n n n = 1110 = internal bandgap level 1.23V // n n n n = 1111 = external AGND pin level //+-------------------------------------------------------------------------------------------+ } */ //================================================================================ // INIT AD-CONVERTER USING INTERRUPT //================================================================================ void vInitAdConverterUsingInterrupt(void){ //+-------------------------------------------------------------------------------------------+ //| ADMUX = ADC Multiplexer Selection Register | //+-------------------------------------------------------------------------------------------+ //| | //| REFSn = select reference voltage source (= maximum measurement voltage value) | //| ADLAR = left justify or right justify measured value into register ADCH/ADCL | //| MUXn = select measurement-point to be connected to the AD-converter measurement input | //| | //+-------------------------------------------------------------------------------------------+ //| select AVCC pin as reference, use left justify, use left track sensor as measurement-point| //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| ADMUX | REFS1_X | REFS0_X | ADLAR_X |RESERVED | MUX3_X | MUX2_X | MUX1_X | MUX0_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( ADMUX , REFS1_L | REFS0_H | ADLAR_H |RESERVED | MUX3_L | MUX2_L | MUX1_L | MUX0_L ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ // n n . . . . . . = 00 = external AREF pin // n n . . . . . . = 01 = external AVCC pin with capacitor at AREF pin // n n . . . . . . = 10 = reserved // n n . . . . . . = 11 = internal 2.56V Voltage Reference with external capacitor at AREF pin // . . n . . . . . = 0 = right justify => ADCH:ADCL = ......98:76543210 // . . n . . . . . = 1 = left justify => ADCH:ADCL = 98765432:10...... // . . . . n n n n = select AD-Converter measurement input // n n n n = 0000-0111 = external pins ADC0 - ADC7 // n n n n = 1000-1101 = reserved // n n n n = 1110 = internal bandgap level 1.23V // n n n n = 1111 = external AGND pin level //+-------------------------------------------------------------------------------------------+ //+-------------------------------------------------------------------------------------------+ //| ADCSRA = ADC Control and Status Register A | //+-------------------------------------------------------------------------------------------+ //| | //| A complete ad-conversion takes 13 clock cycles (clock speed defined by prescaler) | //| | //| ADEN = enable ad-converter (switch ad-converter on, consumes extra current) | //| ADSC = start ad-conversion (set low by microcontroller if conversion has finished) | //| ADFR = select free-running mode (checking on ADSC or ADIF bit is useless) | //| ADIF = ad-converter interrupt flag (is set when conversion has finished, using interrupt) | //| ADIE = ad-converter interrupt enable (interrupt occurs when conversion has finished) | //| ADPSn = select ad-converter clock prescaler | //| | //+-------------------------------------------------------------------------------------------+ //| ADC Clock frequency should be between 50KHz and 200KHz (.pdf) | //| | //| Prescaler ADC clock freq. measured ADC duration (by oscilloscoop) | //| | //| 000 8 MHz/ 2 = 4000 KHz 7.8 us | //| 001 8 MHz/ 2 = 4000 KHz 7.8 us | //| 010 8 MHz/ 4 = 2000 KHz 10 us | //| 011 8 MHz/ 8 = 1000 KHz 16 us | //| 100 8 MHz/ 16 = 500 KHz 30 us | //| 101 8 MHz/ 32 = 250 KHz 55 us | //| 110 8 MHz/ 64 = 125 KHz 110 us <--- use these | //| 111 8 MHz/128 = 63 KHz 230 us | //| | //+-------------------------------------------------------------------------------------------+ //| enable ADC, nostart ADC, no free-running, interrupt enabled, clear int. flag, prescaler 6 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| ADCSRA | ADEN_X | ADSC_X | ADFR_X | ADIF_X | ADIE_X | ADPS2_X | ADPS1_X | ADPS0_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( ADCSRA , ADEN_H | ADSC_L | ADFR_L | ADIF_L | ADIE_H | ADPS2_H | ADPS1_H | ADPS0_L ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ // n . . . . . . . = 1 = AD-Converter enable // . n . . . . . . = 1 = start AD-conversion // . n . . . . . . = 0 = AD-conversion finished // . . n . . . . . = 1 = free running mode // . . . n . . . . = 1 = interrupt (or: conversion finished) // . . . . n . . . = 1 = AD-conversion interrupt enable // . . . . . n n n = ADC prescaler // . . . . . n n n = 000-111 = adc clock division factors // . . . . . n n n = 0=2,1=2,2=4,3=8,4=16,5=32,6=64,7=128 //+-------------------------------------------------------------------------------------------+ } //================================================================================ // INIT TIMER 0 //================================================================================ void vSetupFreeRunningTimer0UsingOverflowInterrupt(void){ //+-------------------------------------------------------------------------------------------+ //| TCCR0 = Timer/Counter Control Register | //+-------------------------------------------------------------------------------------------+ //| | //| CSnn = Clock Source | //| | //+-------------------------------------------------------------------------------------------+ //| use clkio/1024 that makes freerunning frequency of 30.52Hz | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| | - | - | - | - | - | Timer0 | Timer0 | Timer0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| TCCR0 |RESERVED |RESERVED |RESERVED |RESERVED |RESERVED | CS02_X | CS01_X | CS00_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( TCCR0 ,RESERVED |RESERVED |RESERVED |RESERVED |RESERVED | CS02_H | CS01_L | CS00_H ); //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ // 0MHz n n n = 000 = No clock source (Timer/Counter stopped). // 8MHz/ 1 = 8.000.000Hz => /256 = 31250.00Hz = 32us n n n = 001 = clkI/O/(No prescaling) // 8MHz/ 8 = 1.000.000Hz => /256 = 3906.25Hz = 256us n n n = 010 = clkI/O/8 (From prescaler) // 8MHz/ 64 = 125.000Hz => /256 = 488.28Hz = 2048us n n n = 011 = clkI/O/64 (From prescaler) // 8MHz/ 256 = 31.250Hz => /256 = 122.07Hz = 8.192us n n n = 100 = clkI/O/256 (From prescaler) // 8MHz/1024 = 7.813Hz => /256 = 30.52Hz = 32.768us n n n = 101 = clkI/O/1024 (From prescaler) // n n n = 110 = External clock source on T0 pin. Clock on falling edge. // n n n = 111 = External clock source on T0 pin. Clock on rising edge. //+-------------------------------------------------------------------------------------------+ //+-------------------------------------------------------------------------------------------+ //| TIMSK = Timer/Counter Interrupt Mask Register | //+-------------------------------------------------------------------------------------------+ //| | //| OCIE2 = timer/counter2, output-compare-match interrupt enable | //| TOIE2 = timer/counter2, overflow interrupt enable | //| TICIE1 = timer/counter1, input-capture interrupt enable | //| OCIE1A = timer/counter1, equal to output-compare-A-match register, interrupt enable | //| OCIE1B = timer/counter1, equal to output-compare-B-match register, interrupt enable | //| TOIE1 = timer/counter1 overflow interrupt enable | //| RESERVED = unused | //| TOIE0 = timer/counter0 overflow interrupt enable | //| | //+-------------------------------------------------------------------------------------------+ //| enable timer/counter0 interrupt | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| | Timer2 | Timer2 | Timer1 | Timer1 | Timer1 | Timer1 | - | Timer0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|signal name| OCIE2_X | TOIE2_X |TICIE1_X |OCIE1A_X |OCIE1B_X | TOIE1_X |RESERVED | TOIE0_X | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRX ( TIMSK , TOIE0_H ); //Timer0 overflow (0xFF->0x00) interrupt enable //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //+-------------------------------------------------------------------------------------------+ //| TCNT0 = Timer/Counter0 Register | //+-------------------------------------------------------------------------------------------+ //| | //| | //| | //+-------------------------------------------------------------------------------------------+ //| timer/counter 0 read/write counter value | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //|bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| | Timer0 | Timer0 | Timer0 | Timer0 | Timer0 | Timer0 | Timer0 | Timer0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ //| TCT0 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ SFRW ( TCNT0 , 0x00 ); //clear timer/counter0 //+-----------+---------+---------+---------+---------+---------+---------+---------+---------+ } //================================================================================ // MAIN //================================================================================ int main(void){ //stop the 36KHz timer2 (left active by boot sector) but does not harm anything SFRX(TCCR2,CS22_L|CS21_L|CS20_L); //---init-green-system-led---// //set green system led UC-pin as low (led off) SFRX(PORTB,SLD_GRN_L); //set green system led UC-pin as output SFRX(DDRB ,SLD_GRN_O); //---init-red-system-led---// //set red system led UC-pin as low (led off) SFRX(PORTD,SLD_RED_L); //set red system led UC-pin as output SFRX(DDRD ,SLD_RED_O); //---init-track-led---// //set tracking led UC-pin as low (led off) SFRX(PORTD,TRK_LED_L); //set tracking led UC-pin as output SFRX(DDRD, TRK_LED_O); //---init-break-leds---// //set brake leds common kathode UC-pin to low SFRX(PORTD,BOD_COM_L); //set brake leds common kathode UC-pin to output SFRX(DDRD ,BOD_COM_O); //set both brake leds anode UC-pins to low (leds off) SFRX(PORTC,BOD_LFT_L|BOD_RGT_L); //set both brake leds anode UC-pins to outpouts SFRX(DDRC ,BOD_LFT_O|BOD_RGT_O); //init unused io-ports vInitUnusedIoPorts(); //init timer/counter1 to generate two different interrupts depending on two compare-values vInitTimerCounter1Mode10(); //define timer/counter1 max count value (write high byte first!) ICR1H=0x00; ICR1L=0xFF; //enable global interrupt vEnableGlobalInterrupt(); //init ad-converter using interrupt vInitAdConverterUsingInterrupt(); //select left tracking sensor as ad-converter measurement-input SFRX(ADMUX,MUX3_L|MUX2_L|MUX1_H|MUX0_H); //start timer/counter0 vSetupFreeRunningTimer0UsingOverflowInterrupt(); //endless loop while(1); //exit function return 0; } //================================================================================ // interrupt handler for timer/counter0 overflow // #define SIG_OVERFLOW0 _VECTOR(9) // Enable bit: Register TIMSK, Bit TOIE0 (bit0) //================================================================================ SIGNAL (SIG_OVERFLOW0){ //start ad-conversion SFRX(ADCSRA,ADSC_H); } //================================================================================ // interrupt handler, timer/counter1 output compare A // enable bit: register TIMSK bit OCIE1A // #define SIG_OUTPUT_COMPARE1A _VECTOR(6) //================================================================================ SIGNAL(SIG_OUTPUT_COMPARE1A){ //toggle left brake led vToggleLeftBrakeLed(); } //================================================================================ // interrupt handler, timer/counter1 output compare B // enable bit: register TIMSK bit OCIE1B // #define SIG_OUTPUT_COMPARE1B _VECTOR(7) //================================================================================ SIGNAL(SIG_OUTPUT_COMPARE1B){ //toggle right brake led vToggleRightBrakeLed(); } //================================================================================ // interrupt handler, timer/counter1 overflow // enable bit: register TIMSK bit TOIE1 // #define SIG_OVERFLOW1 _VECTOR(8) //================================================================================ SIGNAL(SIG_OVERFLOW1){ //copy measured left track-sensor value into compare A register OCR1A=gyCurLftTrkSnsVal^0xff; //copy measured right track-sensor value inverted into compare B register OCR1B=gyCurRgtTrkSnsVal; } //================================================================================ // interrupt handler, ad-conversion finished // enable bit: register ADCSRA bit ADIE // #define SIG_ADC _VECTOR(14) //================================================================================ SIGNAL (SIG_ADC){ //switch tracking led off //SFRX(PORTD,TRK_LED_L); //if left tracking sensor AD-Converter is selected if(SFRQ(ADMUX,MUX3_L|MUX2_L|MUX1_H|MUX0_H)){ //store left track AD-converter value in global variable (used left-justified mode only needs reading ADCH) gyCurLftTrkSnsVal=ADCH; //OCR1A=ADCH; //now select right track sensor SFRX(ADMUX,MUX3_L|MUX2_L|MUX1_H|MUX0_L); }//if //if right tracking sensor AD-Converter is selected else{ //store left track AD-converter value in global variable (used left-justified mode only needs reading ADCH) gyCurRgtTrkSnsVal=ADCH; //OCR1B=ADCH; //now select left track sensor SFRX(ADMUX,MUX3_L|MUX2_L|MUX1_H|MUX0_H); }//else }