4 RST_STATE \ to rub out this test with <reset> or RST_STATE or COLD
6 \ Copyright (C) <2014> <J.M. THOORENS>
8 \ This program is free software: you can redistribute it and/or modify
9 \ it under the terms of the GNU General Public License as published by
10 \ the Free Software Foundation, either version 3 of the License, or
11 \ (at your option) any later version.
13 \ This program is distributed in the hope that it will be useful,
14 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
15 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 \ GNU General Public License for more details.
18 \ You should have received a copy of the GNU General Public License
19 \ along with this program. If not, see <http://www.gnu.org/licenses/>.
22 \ FORTH driver for IR remote compatible with the PHILIPS RC5 protocol, with select new/repeated command
23 \ target : see IR_RC5.pat
25 \ Send to terminal the RC5 new command.
26 \ Press S1 to send also RC5 repeated command.
29 \ HERE \ general minidump, part 1
31 \ --------------------------------------------------------------------------------------------
32 \ MSP-EXP430FR5969 driver for IR_RC5 receiver TSOP32236 wired on Px.y input \ 65 words, 24.5ms
33 \ --------------------------------------------------------------------------------------------
35 \ layout : see config.pat file for defining I/O
37 \ ******************************\
38 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39 \ ******************************\
40 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41 \ ******************************\
42 \ \ in : SR(9)=old Toggle bit memory (ADD on)
43 \ \ SMclock = 8|16|24 MHz
44 \ \ use : TOS,IP,W,X,Y, TA0 timer, TA0R register
45 \ \ out : TOS = 0 C6 C5 C4 C3 C2 C1 C0
46 \ \ SR(9)=new Toggle bit memory (ADD on)
47 \ ******************************\
48 \ RC5_FirstStartBitHalfCycle: \
49 \ ******************************\ division in TA0CTL (SMCLK/1,SMCLK/1,SMCLK/2,SMCLK/4,SMCLK/8)
50 \ MOV #0,&TA0EX0 \ predivide by 1 in TA0EX0 register ( 125kHz, 1MHz, 2MHZ, 4MHZ, 8MHZ), reset value
51 \ MOV #1,&TA0EX0 \ predivide by 2 in TA0EX0 register ( 250kHZ, 2MHz, 4MHZ, 8MHZ, 16MHZ)
52 \ MOV #2,&TA0EX0 \ predivide by 3 in TA0EX0 register ( 375kHz, 3MHz, 6MHZ, 12MHZ, 24MHZ)
53 \ MOV #3,&TA0EX0 \ predivide by 4 in TA0EX0 register ( 500kHZ, 4MHz, 8MHZ, 16MHZ)
54 \ MOV #4,&TA0EX0 \ predivide by 6 in TA0EX0 register ( 625kHz, 5MHz, 10MHZ, 20MHZ)
55 \ MOV #5,&TA0EX0 \ predivide by 6 in TA0EX0 register ( 750kHz, 6MHz, 12MHZ, 24MHZ)
56 \ MOV #6,&TA0EX0 \ predivide by 7 in TA0EX0 register ( 875kHz, 7MHz, 14MHZ, 28MHZ)
57 \ MOV #7,&TA0EX0 \ predivide by 8 in TA0EX0 register ( 1MHz, 8MHz, 16MHZ, 32MHZ)
58 MOV #1778,X \ RC5_Period * 1us
59 \ MOV #222,X \ RC5_Period * 8us (SMCLK/1 and first column above)
60 MOV #14,W \ count of loop
62 \ ******************************\
63 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
64 \ ******************************\ |
65 \ MOV #%1000100100,&TA0CTL \ (re)start timer_A | SMCLK/1 time interval,free running,clear TA0_IFG and TA0R
66 \ MOV #%1002100100,&TA0CTL \ (re)start timer_A | SMCLK/2 time interval,free running,clear TA0_IFG and TA0R
67 \ MOV #%1010100100,&TA0CTL \ (re)start timer_A | SMCLK/4 time interval,free running,clear TA0_IFG and TA0R
68 MOV #%1011100100,&TA0CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear TA0_IFG and TA0R
69 \ RC5_Compute_3/4_Period: \ |
70 RRUM #1,X \ X=1/2 cycle |
74 BEGIN CMP Y,&TA0R \3 wait 1/2 + 3/4 cycle = n+1/4 cycles
76 \ ******************************\
77 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
78 \ ******************************\
79 BIT.B #RC5,&IR_IN \ C_flag = IR bit
80 ADDC IP,IP \ C_flag <-- IP(15):IP(0) <-- C_flag
81 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
82 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
83 SUB #1,W \ decrement count loop
84 \ \ count = 13 ==> IP = x x x x x x x x |x x x x x x x /C6
85 \ \ count = 0 ==> IP = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
86 0<> WHILE \ ----> out of loop ----+
87 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
89 MOV &TA0R,X \3 | X grows from n+1/4 up to n+3/4 cycles
90 CMP Y,X \1 | cycle time out of bound ?
91 U>= ?GOTO FW1 \2 ^ | yes: quit on truncated RC5 message
92 BIT.B #RC5,&IR_IFG \3 | | n+1/2 cycles edge is always present
94 REPEAT \ ----> loop back --+ | with X = new RC5_period value
95 \ ******************************\ |
96 \ RC5_SampleEndOf: \ <---------------------+
97 \ ******************************\
98 \ RC5_ComputeNewRC5word \
99 \ ******************************\
101 MOV TOS,0(PSP) \ save TOS before use
102 RLAM #1,IP \ IP = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
103 MOV.B IP,TOS \ TOS = C5 C4 C3 C2 C1 C0 1 0
104 RRUM #2,TOS \ TOS = 0 0 C5 C4 C3 C2 C1 C0
105 \ ******************************\
107 \ ******************************\
108 BIT #BIT14,IP \ test /C6 bit in IP
109 0= IF BIS #BIT6,TOS \ set C6 bit in TOS
110 THEN \ TOS = 0 C6 C5 C4 C3 C2 C1 C0
111 \ ******************************\
112 \ RC5_CommandByteIsDone \ -- BASE RC5_code
113 \ ******************************\
114 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
115 \ ******************************\
116 RRUM #4,IP \5 new toggle bit = IP(13) ==> IP(9)
117 XOR SR,IP \ (new XOR old) Toggle bits
118 BIT #UF1,IP \ repeated RC5_command ?
119 0= ?GOTO FW2 \ yes, RETI without UF1 change
120 \ ******************************\
121 XOR #UF1,0(RSP) \ 5 toggle bit memory
122 FW2 \ endof repeated RC5_command : RETI without UF1 change
123 FW1 \ endof truncated RC5 message
124 BIC #$30,&TA0CTL \ stop timer_A0
125 BIC #$F8,0(RSP) \ 4 SCG1,SCG0,OSCOFF,CPUOFF and GIE are OFF in retiSR to force LPM0_LOOP despite pending interrupt
126 RETI \ 5 for system OFF / 1 sec. ==> 1mA * 5us = 5nC + 6,5uA
131 \ ------------------------------\
133 \ ------------------------------\
134 \ init PORTX (P2:P1) (complement) default I/O are input with pullup resistors
135 BIC.B #RC5,&PIRIFG \ P1IFG.2 clear int flag for TSOP32236 (after IES select)
136 BIS.B #RC5,&PIRIE \ P1IE.2 enable interrupt for TSOP32236
137 \ ------------------------------\
138 \ define LPM mode for ACCEPT \
139 \ ------------------------------\
140 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
141 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
142 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
143 \ ------------------------------\
144 \ init interrupt vectors \
145 \ ------------------------------\
146 MOV #INT_RC5,&IR_Vec \ init Px vector interrupt
147 \ ------------------------------\
149 \ ------------------------------\
150 \ START is included in WARM \
151 \ ------------------------------\
152 LIT RECURSE IS WARM \ insert this starting routine between COLD and WARM...
153 ['] WARM >BODY EXECUTE \ ...and continue with WARM (that unlocks I/O).
156 \ ------------------------------\
157 : STOP \ stops multitasking, must to be used before downloading app
158 \ ------------------------------\
159 ['] WARM >BODY IS WARM \ remove START app from FORTH init process
160 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
163 \ HERE OVER - DUMP \ general minidump, part 2
169 \ --------------------------------------------------\
170 \ PHILIPS IR REMOTE RC5/RC6 protocol \
171 \ --------------------------------------------------\
172 \ first half bit = no light, same as idle state
173 \ second half bit : 32 IR-light pulses of 6,944us,light ON/off ratio = 1/3
175 \ |<------32 IR light pulses = second half of first start bit ------->|
176 \ |_ _ _ _ _ _ _ _ _ _ _ _|
177 \ ...____| |___| |___| |___| |___| |___| |...| |___| |___| |___| |___| |___| |____________________________________...
182 \ at the output of IR receiver TSOPxxx during the first start bit :
184 \ ...idle state ->|<----- first half bit ------>|<- second half bit (IR light) ->|
185 \ ..._____________|_____________________________| |_________...
188 \ | |________________________________|
190 \ 32 cycles of 27,777us (36kHz) = 888,888 us
191 \ one bit = 888,888 x 2 = 1778 us.
195 \ 14 bits of active message = 24.889 ms
196 \ + 50 bits of silent (idle) = 88.888 ms
197 \ = RC5 message = 113.792 ms
200 \ RC5_message on IR LIGHT \ idle state = light off
202 \ 89ms>|<--------------------------------------------------24.889 ms-------------------------------------------------->|<88,
204 \ | | | | | | | | | | | | | | |
205 \ | ST1 | ST2/C6| Tog | A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 |
206 \ | | | | | | | | | | | | | | |
207 \ 1 1 1 1 0 0 1 1 1 1 1 1 1 1
208 \ ___ ___ ___ _______ ___ ___ ___ ___ ___ ___ ___ ___ ___
209 \ ^ | ^ | ^ | ^ | | | ^ | ^ | ^ | ^ | ^ | ^ | ^ | ^ |
210 \ idle____| |___| |___| |___| v___| v_______| |___| |___| |___| |___| |___| |___| |___| |____
213 \ notice that each cycle contains its bit value preceded by its complement
218 \ the same RC5_message inverted at the output of IR receiver : idle state = 1
220 \ | | | | | | | | | | | | | | |
221 \ | ST1 | ST2/C6| Tog | A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 |
222 \ | | | | | | | | | | | | | | |
223 \ 1 1 1 1 0 0 1 1 1 1 1 1 1 1
224 \ idle_____ ___ ___ ___ ___ _______ ___ ___ ___ ___ ___ ___ ___ __idle
225 \ | | | | | | | ^ | ^ | | | | | | | | | | | | | | | |
226 \ v___| v___| v___| v_______| |___| v___| v___| v___| v___| v___| v___| v___| v___|
227 \ I R R R R R R R R R R R R R
229 \ notice that each cycle contains its bit value followed by its complement
234 \ principe of the driver : 13 samples at 1/4 period and Resynchronise (R) on 1/2 period (two examples)
237 \ |<->|<--------------------------------routine time = 12 3/4 cycles = 22.644 ms--------------------------->|
238 \ | | | | | | | | | | | | | | | |
239 \ | ST1 | ST2/C6| Toggle| A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | |C0 |
240 \ | | | | | | | | | | | | | | | |
241 \ 1 1 1 1 0 0 1 1 1 1 1 1 1 | 1
242 \ idle_____ _s_ _s_ _s_ ___ _____s_ _s_ _s_ _s_ _s_ _s_ _s_ _s_ __idle
243 \ | | | | | | | ^ | ^ | | | | | | | | | | | | | | | |
244 \ v___| v___| v___| v_____s_| |_s_| v___| v___| v___| v___| v___| v___| v___| v___|
245 \ I R R R R R R R R R R R R ^ ^
246 \ | | | | | | | | | | | | | | |
247 \ samples : 1 2 3 4 5 6 4 8 9 10 11 12 13| |
249 \ good ! but we have too many RC5_Int...----------------> I I
252 \ |<->|<--------------------------------routine time = 12 3/4 cycles = 22.644 ms--------------------------->|
253 \ | | | | | | | | | | | | | | | |
254 \ | ST1 | ST2/C6| Toggle| A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | |C0 |
255 \ | | | | | | | | | | | | | | | |
256 \ 1 1 1 1 0 0 1 1 1 1 1 1 1 | 1
257 \ idle_____ _s_ _s_ ___ _o_ _o___s_ _s_ _s_ _s_ _s_ _s_ _s_ ______idle
258 \ | | | | | | | ^ | ^ | | | | | | | | | | | | | ^
259 \ v___| v_o_| v_o_| v_o___s_| |_s_| v_o_| v_o_| v_o_| v_o_| v_o_| v_o_| v_o___s_|
260 \ I R R R R R R R R R R R R ^
261 \ | | | | | | | | | | | | | |
262 \ samples : 1 2 3 4 5 6 7 8 9 10 11 12 13|
264 \ good ! but we have too many RC5_Int...------------------> I
270 \ So, to avoid these RC5_Int after end : 13+1=14 samples, then the result is shifted one to wipe the 14th (two examples)
273 \ |<->|<--------------------------------routine time = 13 3/4 cycles = 24.447 ms----------------------------------->|
274 \ | | | | | | | | | | | | | | | |
275 \ | ST1 | ST2/C6| Toggle| A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 | |
276 \ | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |
277 \ | | | | | | | | | | | | | | | |
278 \ idle_____ _s_ _s_ _s_ _o_ _o___s_ _s_ _s_ _s_ _s_ _s_ _s_ _s_ _s_idle
279 \ | | | | | | | ^ | ^ | | | | | | | | | | | | | | | |
280 \ v___| v_o_| v_o_| v_o___s_| |_s_| v_o_| v_o_| v_o_| v_o_| v_o_| v_o_| v_o_| v_o_|
281 \ I i R i R i R R i R R i R i R i R i R i R i R i R i
282 \ | | | | | | | | | | | | | |
283 \ samples : 1 2 3 4 5 6 7 8 9 10 11 12 13 14
287 \ |<->|<--------------------------------routine time = 13 3/4 cycles = 24.447 ms----------------------------------->|
288 \ | | | | | | | | | | | | | | | |
289 \ | ST1 | ST2/C6| Toggle| A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 | |
290 \ | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | |
291 \ | | | | | | | | | | | | | | | |
292 \ idle_____ _s_ _s_ _s_ _o_ _o___s_ _s_ _s_ _s_ _s_ _s_ _s_ _o___s_idle
293 \ | | | | | | | ^ | ^ | | | | | | | | | | | | | ^
294 \ v___| v_o_| v_o_| v_o___s_| |_s_| v_o_| v_o_| v_o_| v_o_| v_o_| v_o_| v_o___s_|
295 \ I i R i R i R R i R R i R i R i R i R i R i R R
296 \ | | | | | | | | | | | | | |
297 \ samples : 1 2 3 4 5 6 7 8 9 10 11 12 13 14
300 \ I = first interruption at the first 1/2 cycle : clear and start timer
301 \ i = useless RC5_Int (because aperiodic) at 4/4 cycle
302 \ s = sample RC5_intput at (1/2+3/4) = 5/4 cycle = n+1/4 cycles and clear useless RC5_Int
303 \ R = usefull (periodic) RC5_Int at 6/4 cycle = n+1/2 cycles : load new timer value, then clear it and restart it
304 \ o = RC5_Int time out at 7/4 cycle = n+3/4 cycles, used to detect truncated RC5_message (samples<14)
306 \ see also : http://www.sbprojects.com/knowledge/ir/rc5.php
307 \ http://laurent.deschamps.free.fr/ir/rc5/rc5.htm
308 \ Code RC5 : http://en.wikipedia.org/wiki/RC-5