Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* S107G IR packet transmitter (ver 1.3)
- 0-07 MAY 2011 (Aqualung)
- 1-14 MAY 2011 - replaced digitalWrites with port operations
- 2-15 MAY 2011 - added pre-defined bit pattern to eliminate
- the need to rotate the bit into position
- 3-05 MAY 2011 - added safe restart state 7
- */
- /*
- Uses ATmega328 @ 16MHz (your mileage may vary)
- Connect anode (+) of IR LED to 5V and connect
- cathode (-) to pin 8 using a 100 ohm resistor
- The ISR is called every 13us and is implemented as a state
- machine:
- state 0 idle
- state 1 start pulses
- state 2 start pause
- state 3 mark pulses states 3 and 4
- state 4 data pause(s) repeat 32 times
- state 5 stop pulses
- state 6 inter-packet pause (!busy during this time)
- state 7 safe start state (use after state 0 is set)
- During the loop() function, the busy flag should be used to
- know when it's okay to update data values - updating the
- values during transmission may corrupt the data - setting
- the state to 0 effectively disables transmission of data -
- setting it to 7 will safely restart the next packet sequence.
- Data values are 7-bits in length - the yaw, pitch, and
- adjustment (yaw offset) values are centered at 63/64 -
- a range of 64->127 will increase in one direction while
- a range of 63->0 will increase in the opposite direction -
- the throttle values range from 0->127 and increase as the
- value increases.
- Setting state to 0 and immediately setting it back to 1 can
- possibly send data sooner than intended. Setting state to 0
- while busy can cause counter values to be corrupted and send
- the state machine into a black hole. After setting the state
- to 0, restart the state machine by setting the state to 7.
- */
- #define LED 8
- #define PORT PORTB
- #define PIN 1<<PORTB0
- #define STARTL 153
- #define STARTH 153
- #define MARKL 23
- #define DATAC0 21
- #define DATAC1 51
- #define STOPL 23
- #define SPACEH 15385
- #define TCOUNT 92
- volatile byte state,startH,startL,markL,stopL,dataC,countP,countR;
- volatile unsigned int spaceH;
- volatile bool busy;
- // maskB[] contains bit mask values
- const volatile byte maskB[] = {128,64,32,16,8,4,2,1};
- // dataP[] has four 7-bit packet values
- // dataP[0] = yaw 63->0 / 64->127
- // dataP[1] = pitch 63->0 / 64->127
- // dataP[2] = throttle 0->127
- // dataP[3] = offset 63->0 / 64->127
- volatile byte dataP[] = {63,63,0,63};
- void setup()
- {
- pinMode(LED,OUTPUT);
- digitalWrite(LED,HIGH);
- Serial.begin(9600);
- // Disable the timer2 overflow interrupt
- TIMSK2 &= ~(1<<TOIE2);
- // Configure timer2 in normal mode
- TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
- TCCR2B &= ~(1<<WGM22);
- // Select internal clock source
- ASSR &= ~(1<<AS2);
- // Disable compMatchA interrupt
- TIMSK2 &= ~(1<<OCIE2A);
- // Disable pre-scaler (use system clock)
- TCCR2B |= (1<<CS20);
- TCCR2B &= ~((1<<CS22) | (1<<CS21));
- // Set the initial values - all cycle count values must be odd
- startL = STARTL;
- startH = STARTH;
- markL = MARKL;
- stopL = STOPL;
- spaceH = SPACEH;
- //------------
- countP = 4;
- countR = 8;
- state = 1;
- busy = true;
- Serial.println("Starting ... 5 second delay");
- delay(5000);
- // Load timer counter and enable the timer
- TCNT2 = TCOUNT;
- TIMSK2 |= (1<<TOIE2);
- }
- void loop()
- {
- if(!busy)
- {
- // --- approximately 165ms is available ---
- // set dataP[0] to new yaw value
- // dataP[0] = 77;
- // set dataP[1] to new pitch value
- // dataP[1] += 3;
- // set dataP[2] to new throttle value
- // dataP[2]--;
- // set dataP[3] to new adjustment value
- // dataP[3] = dataP[2] / 32;
- // make sure to set the busy flag to avoid the
- // next pass through the loop
- busy = true;
- }
- }
- ISR(TIMER2_OVF_vect)
- {
- TCNT2 = TCOUNT;
- switch(state)
- {
- case 0: // idle state
- {
- PORT |= PIN; // make sure LED is turned off
- }
- break;
- case 1: // startL (low)
- spaceH--;
- if(startL--)
- {
- if(startL & 1)
- {
- PORT |= PIN;
- }
- else
- {
- PORT &= ~PIN;
- }
- }
- else
- {
- PORT |= PIN;
- startL = STARTL;
- state = 2;
- }
- break;
- case 2: // startH (high)
- spaceH--;
- if(!startH--)
- {
- startH = STARTH;
- countP = 4;
- state = 3;
- }
- break;
- case 3: // markL (low)
- spaceH--;
- if(markL--)
- {
- if(markL & 1)
- {
- PORT |= PIN;
- }
- else
- {
- PORT &= ~PIN;
- }
- }
- else
- {
- PORT |= PIN;
- if(dataP[4-countP] & maskB[8-(countR--)])
- {
- dataC = DATAC1;
- }
- else
- {
- dataC = DATAC0;
- }
- markL = MARKL;
- state = 4;
- }
- break;
- case 4: // dataH (high)
- spaceH--;
- if(!dataC--)
- {
- if(!countR)
- {
- countR = 8;
- countP--;
- }
- if(!countP)
- {
- state = 5;
- }
- else
- {
- state = 3;
- }
- }
- break;
- case 5: // stopL (low)
- spaceH--;
- if(stopL--)
- {
- if(stopL & 1)
- {
- PORT |= PIN;
- }
- else
- {
- PORT &= ~PIN;
- }
- }
- else
- {
- PORT |= PIN;
- stopL = STOPL;
- busy = false;
- state = 6;
- }
- break;
- case 6: // spaceH (high)
- if(!spaceH--)
- {
- spaceH = SPACEH;
- busy = true;
- state = 1;
- }
- break;
- case 7: // safe start (set state to 7 to restart state machine after setting state to 0)
- {
- startL = STARTL;
- startH = STARTH;
- markL = MARKL;
- stopL = STOPL;
- countP = 4;
- countR = 8;
- state = 6;
- }
- break;
- }
- }
Add Comment
Please, Sign In to add comment