-- Sony Infrared Remote Control(aka SIRC) protocol decoder -- SIRC is widely used protocol for consumer entertainment devices -- such as TV's, VCR's, DVD players, Hi-Fi receivers, etc -- SIRC is found in 12-bit, 15-bit, 20- bit versions -- This decoder is for the 12-bit version -- -- 12-bit SIRC is comprised of a pulse-width modulated bit stream -- with 5 address bits and 7 data bits. A logical 1 is represented -- by a 1.2 mS burst of the 40 khz carrier, whereas a logical 0 -- is represented by a 0.6 mS burst of the carrier. -- -- The data stream is preceeded by a start burst 2.4 mS in duration -- of the 40 khz carrier and then the data is sent LSB first with the -- command preceeding the address. Commands are repeated every 45 mS -- (measured from start to start) as long as the button is pressed. -- For more info on this and other remote protocols see -- www.sbprojects.com/knowledge/ir.htm -- -- A short list of commands from a "universal" remote set to be a Sony TV remote -- button address command -- 1 01 00 -- 2 01 01 -- 3 01 02 -- | | | -- 0 01 09 -- note that the numbers are 1 less than face value except 0 -- vol- 01 19 -- vol+ 01 18 -- ch- 01 17 -- ch+ 01 16 -- mute 01 20 -- Intresting that for the 5 different Sony codes for my universal -- remote all had the same address value of 01 and all of the above -- buttons had the same address value regardless of which code I -- programmed into the remote. Maybe some of the more advanced -- features transmit a different address or command code or both. -- Why else would you need multiple codes ? -- -- In this demo we are just displaying the address and command -- values on an LCD display, but by detecting a specific button press -- we could turn a pin on or off, thereby controlling a LED, relay, etc. -- As an example, say we wanted pin_B1 to turn on when we pressed "9" -- after the GetSIRC procedure completes in the main program simply code -- if (my_cmd == 01) & (my_add == 08) then pin_B1 = 1. -- As you see this is setup to use the internal oscillator but does work -- with an external crystal with no modification except changing the -- oscillator type. It should port to a 12F629/675 with minor -- modifications to account for pin differences and that those devices -- do not support LVP ( low voltage programming ) include 16f628 pragma target clock 4_000_000 -- 4 MHz xtal pragma target OSC INTOSC_NOCLKOUT -- internal osc pragma target MCLR external pragma target WDT disabled -- no watchdog, please pragma target LVP disabled -- no low voltage programming pragma target PWRTE enabled enable_digital_io() -- no analog pins used in this sample -- pin_B0_direction = input pin_B1_direction = output pin_B2_direction = output pin_B3_direction = output pin_B4_direction = output include delay var byte my_add = 0 var byte my_cmd = 0 var bit IR_pin is pin_B0 var bit Red_1 is pin_B1 var bit Green is pin_B2 var bit Yellow is pin_B3 var bit Red_2 is pin_B4 Red_1 = 0 Green = 0 Yellow = 0 Red_2 = 0 Procedure Get_SIRC(byte out my_add, byte out my_cmd) is var byte lTime var byte ir_add var byte ir_cmd asm local StartLook asm StartLook: ir_add = 0 ir_cmd = 0 while(IR_pin == 1) loop lTime = 0 -- wait for it to be low and reset the counter end loop while(IR_pin == 0) loop -- while the pin is low which is our pulse count lTime = lTime + 1 -- increment every 200uS until pin is high _usec_delay (200) end loop if (lTime <= 10) then asm goto StartLook end if if (lTime >= 14) then asm goto StartLook end if -- Start too short or too long so restart lTime = 0 for 7 loop -- repeat 7 times for command ir_cmd = ir_cmd >> 1 -- if it was skipped or is done ORing then shift over the 1 while(IR_pin == 1) loop -- wait for it to be low and reset the counter lTime = 0 end loop while(IR_pin == 0) loop -- while the pin is low which is our pulse count lTime = lTime + 1 -- increment every 200uS until pin is high _usec_delay (200) -- 200uS delay end loop if (lTime >= 6) then ir_cmd = (ir_cmd | 0x40) end if -- If its high then OR a 1 in else skip -- if its less than 6 its a 0 so dont OR it end loop for 5 loop -- repeat 5 times for address/device ir_add = ir_add >> 1 -- if it was skipped or is done ORing then shift over the 1 while(IR_pin == 1) loop lTime = 0 -- wait for it to be low reset the counter end loop while(IR_pin == 0) loop -- while the pin is low which is our pulse count lTime = lTime + 1 -- increment every 200uS until pin is high _usec_delay (200) -- 200uS delay end loop if(lTime >= 6) then ir_add = (ir_add | 0x10) end if -- If its high then OR a 1 in else skip -- if its less than 6 its a 0 so dont OR it end loop my_cmd = ir_cmd my_add = ir_add end procedure forever loop if IR_pin == 0 then Get_SIRC(my_add,my_cmd) end if if (my_add == 01) & (my_cmd == 16) then Red_1 = !Red_1 end if if (my_add == 01) & (my_cmd == 17) then Green = !Green end if if (my_add == 01) & (my_cmd == 18) then Yellow = !Yellow end if if (my_add == 01) & (my_cmd == 19) then Red_2 = !Red_2 end if end loop