PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/MSP-EXP430FR5969/MSP-EXP430FR5969_RC5_to_I2C_Slave.4th

https://gitlab.com/Jean-Michel/FastForthForMSP430fr5xxx
Forth | 375 lines | 341 code | 34 blank | 0 comment | 12 complexity | 5babb597ad9d4bb0bc2723ec7715bb6f MD5 | raw file
Possible License(s): GPL-3.0
  1. ; -------------------------------------
  2. ; MSP-EXP430FR5969_RC5_to_I2C_Slave.4th
  3. ; -------------------------------------
  4. STOP ; to stop any interrupt in progress
  5. WIPE ;
  6. NOECHO ; comment to debug
  7. ; FORTH source file
  8. ; Copyright (C) <2016> <J.M. THOORENS>
  9. ;
  10. ; This program is free software: you can redistribute it and/or modify
  11. ; it under the terms of the GNU General Public License as published by
  12. ; the Free Software Foundation, either version 3 of the License, or
  13. ; (at your option) any later version.
  14. ;
  15. ; This program is distributed in the hope that it will be useful,
  16. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ; GNU General Public License for more details.
  19. ;
  20. ; You should have received a copy of the GNU General Public License
  21. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. ; ========================================
  23. ; DEMO with two MSP-EXP430FR5969 LAUNCHPAD
  24. ; test : I2C_MASTER READ & I2C_SLAVE WRITE
  25. ; ========================================
  26. ; load this MSP-EXP430FR969_RC5_to_I2C_Slave.4th file on the first LAUNCHPAD
  27. ; load MSP-EXP430FR5969_I2C_Soft_Master_to_PJ_LCD_2x20.4th on the other LAUNCHPAD
  28. ; target : MSP-EXP430fr5969 LAUNCHPAD
  29. ; with code : "FORTH_MSP430FR596916MHzT16.HEX"
  30. ; ===================================================================================
  31. ; in case of 3.3V powered by UARTtoUSB bridge, open J13 straps {RST,TST,V+,5V} BEFORE
  32. ; ===================================================================================
  33. ; -----------------------------------------------
  34. ; MSP - LAUNCHPAD <--> OUTPUT WORLD
  35. ; -----------------------------------------------
  36. ; P4.6 - J6 - LED1 red
  37. ; P1.0 - LED2 green
  38. ; P4.5 - Switch S1 \\\ <--- LCD contrast + (finger :-)
  39. ; P1.1 - Switch S2 \\\ <--- LCD contrast - (finger ;-)
  40. ; GND - J1.2 \\\ <-------+---0V0----------> 1 LCD_Vss
  41. ; VCC - J1.3 \\\ >------ | --3V6-----+----> 2 LCD_Vdd
  42. ; \\\ | |
  43. ; \\\ |___ 470n ---
  44. ; \\\ ^ | ---
  45. ; \\\ / \ BAT54 |
  46. ; \\\ --- |
  47. ; \\\ 100n | 2k2 |
  48. ; P2.2 - J4.7 UCB0 CLK TB0.2 \\\ >---||--+--^/\/\/v--+----> 3 LCD_Vo (=0V6 without modulation)
  49. ; P3.4 - J4.8 \\\ -------------------------> 4 LCD_RS
  50. ; P3.5 - J4.9 \\\ -------------------------> 5 LCD_R/W
  51. ; P3.6 - J4.10 \\\ -------------------------> 6 LCD_EN0
  52. ; PJ.0 - J3.1 \\\ <------------------------> 11 LCD_DB4
  53. ; PJ.1 - J3.3 \\\ <------------------------> 12 LCD_DB5
  54. ; PJ.2 - J3.5 \\\ <------------------------> 13 LCD_DB5
  55. ; PJ.3 - J3.7 \\\ <------------------------> 14 LCD_DB7
  56. ; P2.0 - J13.8 UCA0 TXD ---> RX UARTtoUSB bridge
  57. ; P2.1 - J13.10 UCA0 RXD <--- TX UARTtoUSB bridge
  58. ; P4.1 - J13.14 RTS ---> CTS UARTtoUSB bridge (optional hardware control flow)
  59. ; VCC - J13.16 <--- VCC (optional supply from UARTtoUSB bridge - WARNING ! 3.3V !)
  60. ; GND - J13.20 <--> GND (optional supply from UARTtoUSB bridge)
  61. ; VCC - J11.1 ---> VCC SD_CardAdapter
  62. ; GND - J12.3 <--> GND SD_CardAdapter
  63. ; P2.4 - J4.6 UCA1 CLK ---> CLK SD_CardAdapter (SCK)
  64. ; P4.3 - J4.5 ---> CS SD_CardAdapter (Card Select)
  65. ; P2.5 - J4.4 UCA1 TXD/SIMO ---> SDI SD_CardAdapter (MOSI)
  66. ; P2.6 - J4.3 UCA1 RXD/SOMI <--- SDO SD_CardAdapter (MISO)
  67. ; P4.2 - J4.2 <--- CD SD_CardAdapter (Card Detect)
  68. ; P4.0 - J3.10 <--- OUT IR_Receiver (1 TSOP32236)
  69. ; VCC - J3.2 ---> VCC IR_Receiver (2 TSOP32236)
  70. ; GND - J3.9 <--> GND IR_Receiver (3 TSOP32236)
  71. ; PJ.4 - LFXI 32768Hz quartz
  72. ; PJ.5 - LFXO 32768Hz quartz
  73. ; PJ.6 - HFXI
  74. ; PJ.7 - HFXO
  75. ; P1.2 - J5.19 Soft I2C_Master <--> SDA
  76. ; P1.3 - J5.11 Soft I2C_Master ---> SCL
  77. ; P1.4 - J5.12 TB0.1 <--> free
  78. ; P1.5 - J5.13 UCA0 CLK TB0.2 <--> free
  79. ; P1.6 - J5.15 UCB0 SDA/SIMO <--> SDA <------------------------------------------------------> P1.2 other LAUNCHPAD
  80. ; P1.7 - J5.14 UCB0 SCL/SOMI <--- SCL <------------------------------------------------------- P1.3 other LAUNCHPAD
  81. ; P3.0 - J5.7 <--- free
  82. ; P2.3 - NC
  83. ; P2.7 - NC
  84. ; P3.1 - NC
  85. ; P3.2 - NC
  86. ; P3.3 - NC
  87. ; P3.7 - NC
  88. ; P4.4 - NC
  89. ; P4.7 - NC
  90. ; HERE ; general minidump, part 1
  91. VARIABLE MY_I2CADR ; slave I2C address without RW flag (low byte) + DATA0 input (HIGH byte)
  92. 2 ALLOT ; next the low byte of MY_I2CADR word, it is the input buffer
  93. VARIABLE I2CS_OUT ; buffer output, lentgh (low byte),DATA0 output (HIGH byte)
  94. ; 2 ALLOT ; this byte lentgh is shared by input and output buffers
  95. ; P4.0 - J3.10 <--- OUT IR_Receiver (1 TSOP32236)
  96. ; VCC - J3.2 ---> VCC IR_Receiver (2 TSOP32236)
  97. ; GND - J3.9 <--> GND IR_Receiver (3 TSOP32236)
  98. ; ------------------------------;
  99. ; IR_RC5 driver ;
  100. ; ******************************;
  101. CODE IR_RC5 ; wake up on P4.0 change interrupt
  102. ; ******************************;
  103. BIC #0xF8,0(RSP) ; CPU on, GIE off in oldSR
  104. ; ------------------------------;
  105. ; in : SR(9)=old Toggle bit memory
  106. ; SMclock = 8 MHz or 16 MHz
  107. ; use : U,V,W,X,Y, TA0 timer, TA0R register
  108. ; out : U = 0 x T A4 A3 A2 A1 A0| 0 C6 C5 C4 C3 C2 C1 C0
  109. ; SR(9)=new Toggle bit memory
  110. ; ------------------------------;
  111. ; RC5_FirstStartBitHalfCycle: ;
  112. ; ------------------------------;
  113. MOV #0,&0x0360 ; predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
  114. ; MOV #1,&0x0360 ; predivide by 2 in TA0EX0 register (16 MHZ)
  115. ; MOV #2,&0x0360 ; predivide by 3 in TA0EX0 register (24 MHZ)
  116. MOV #1778,X ; RC5_Period in us
  117. MOV #14,W ; count of loop
  118. BEGIN ;
  119. ; ------------------------------;
  120. ; RC5_TopSynchro: ; <--- loop back ---+ with readjusted RC5_Period
  121. ; ------------------------------; | here, we are just after 1/2 RC5_cycle
  122. MOV #0b1011100100,&0x0340 ; (re)start timer_A | SMCLK_pre/2 /8 : 2us time interval,free running,clear TA0_IFG and TA0R
  123. ; RC5_Compute_3_4Period: ; |
  124. RRUM #1,X ; X=1/2 cycle |
  125. MOV X,Y ; Y=1/2 ^
  126. RRUM #1,Y ; Y=1/4
  127. ADD X,Y ; Y=3/4
  128. ; RC5_Wait_1_4: ; wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle
  129. BEGIN CMP Y,&0x0350 ; CMP &TA0R with 3/4 cycle value
  130. = UNTIL ;
  131. ; ------------------------------;
  132. ; RC5_Sample: ; at 1/4 cycle, we can sample RC5_input, ST2/C6 bit first
  133. ; ------------------------------;
  134. BIT.B #0x01,&0x0221 ; C_flag = P4.0 = IR bit
  135. ADDC V,V ; C_flag <-- V(15):V(0) <-- C_flag
  136. MOV.B &0x0221,&0x0239 ; preset IES_4.0 state for next IFG
  137. BIC.B #0x01,&0x023D ; clear P4.0_IFG after full cycle pin change
  138. SUB #1,W ; decrement count loop
  139. ; count = 13 ==> V = x x x x x x x x |x x x x x x x /C6
  140. ; count = 0 ==> V = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
  141. 0<> WHILE ; ----> out of loop ----+
  142. ; RC5_compute_2_4_OverFlow: ; |
  143. ADD X,Y ; | out of bound = 5/4 period
  144. ; RC5_WaitHalfCycleP1.2_IFG: ; |
  145. BEGIN ; |
  146. CMP Y,&0x0350 ; | TA0R = 5/4 cycle test
  147. >= IF ; | if cycle time out of bound
  148. MOV #4,&0x0340 ; | stop timer_A and clear TA0R
  149. RETI ; | then quit to do nothing
  150. THEN ; |
  151. ; ------------------------------; |
  152. BIT.B #0x01,&0x023D ; ^ | test P4.0_IFG
  153. <> UNTIL ; | |
  154. MOV &0x0350,X ; | | get new RC5_period value
  155. REPEAT ; ----> loop back --+ |
  156. ; ------------------------------; |
  157. ; RC5_SampleEndOf: ; <---------------------+
  158. ; ------------------------------;
  159. MOV #4,&0x0340 ; stop timer_A
  160. RLAM #1,V ; V = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
  161. ; ------------------------------;
  162. ; ------------------------------;
  163. ; Only New_RC5_Command ADD_ON ; use SR(9) bit as toggle bit
  164. ; ------------------------------;
  165. MOV @RSP,X ; retiSR(9) = old RC5 toggle bit
  166. RLAM #4,X ; retiSR(9) --> X(13)
  167. XOR V,X ; (new XOR old)(13) Toggle bit
  168. BIT #0x2000,X ; X(13) = New_RC5_command
  169. 0= IF ;
  170. RETI ; case of repeated RC5_command : RETI without SR(9) change
  171. THEN ;
  172. XOR #0x0200,0(RSP) ; change Toggle bit memory SR(9)
  173. ; ------------------------------;
  174. ; ------------------------------;
  175. ; RC5_ComputeNewRC5word ;
  176. ; ------------------------------;
  177. MOV.B V,U ; U= 0 0 0 0 0 0 0 0 C5 C4 C3 C2 C1 C0 0 0
  178. RRUM #2,U ; U= 0 0 0 0 0 0 0 0 0 0 C5 C4 C3 C2 C1 C0
  179. ; AND #0x7F00,V ; V= 0 /C6 Tg A4 A3 A2 A1 A0 0 0 0 0 0 0 0 0
  180. ; ADD V,U ; U= 0 /C6 Tg A4 A3 A2 A1 A0 0 0 C5 C4 C3 C2 C1 C0
  181. ; ------------------------------;
  182. ; RC5_ComputeC6bit ;
  183. ; ------------------------------;
  184. BIT #0x4000,V ; test /C6
  185. 0= IF BIS.B #0x40,U ; set C6 bit
  186. THEN ;
  187. ; ------------------------------;
  188. ; RC5_CommandByteIsDone: ; U= 0 0 0 0 0 0 0 0 0 C6 C5 C4 C3 C2 C1 C0
  189. ; ------------------------------;
  190. SWPB U ; 1
  191. MOV U,&I2CS_OUT ; 3 count=low byte, Command=high byte
  192. ; ------------------------------;
  193. ; SUB #2,PSP
  194. ; MOV TOS,0(PSP)
  195. ; MOV.B U,TOS
  196. ; ASM>FORTH
  197. ; SPACE ." 0x" HEX 2 U.R
  198. ; FORTH>ASM
  199. ; ------------------------------;
  200. RETI ;
  201. ENDCODE ;
  202. ; ------------------------------;
  203. ; P1.7 - J5.14 UCB0 SCL/SOMI ---> SCL I2C MASTER/SLAVE
  204. ; P1.6 - J5.15 UCB0 SDA/SIMO <--> SDA I2C MASTER/SLAVE
  205. ; **************************************;
  206. CODE I2C_S ; <== eUSCIB0 interrupt vector
  207. ; **************************************;
  208. BIC #0xF8,0(RSP) ; CPU on, GIE off in oldSR
  209. ; --------------------------------------;
  210. MOV #I2CS_OUT,W ; W = buffer output address -1
  211. MOV #MY_I2CADR,X ; X = buffer input address -1
  212. CMP.B @X,&0x65C ; UCBR0ADDRX = own address ?
  213. MOV #0,&0x66C ; write UCB0IFG to clear all int flags
  214. = IF ;
  215. BIS.B #0x20,&0x640 ; UCB0CTLW0(UCTXACK) : software Ack address
  216. BIT.B #0x10,&0X640 ; test UCB0CTLW0(UCTR) R/W bit
  217. 0= IF ; I2C_Master Write ?
  218. ; ------------------------------;
  219. ; slave receive datas ; yes
  220. ; ------------------------------;
  221. MOV X,Y ; Y = input buffer ptr
  222. BEGIN ;
  223. ; --------------------------;
  224. ; slave receive one byte ;
  225. ; --------------------------;
  226. BEGIN ;
  227. BIT.B #0x8C,&0x66C ; UCB0IFG(CLTO,STP,STT,) = 1 ? ( SCL low timeout,STOP, START)
  228. 0<> IF ;
  229. ; ------------------;
  230. ; master stoP/rStart;
  231. ; ------------------;
  232. SUB X,Y ; (ptr-org) = count
  233. MOV.B Y,0(W) ; store length in first byte of buffer output
  234. ; ------------------;
  235. RETI ;
  236. ; ------------------;
  237. THEN ; if not (stop, restart, CLTO)
  238. BIT.B #0x01,&0x66C ; UCB0IFG(RX0) = 1 ?
  239. <> UNTIL ;
  240. ADD #1,Y ; reserve one byte for length first, then preincrement
  241. MOV.B &0x64C,0(Y) ; [UCB0RXBUF] = data --> +[Y]
  242. AGAIN ; loop for new received data if any
  243. THEN ; I2C_Master read
  244. ; ------------------------------;
  245. ; slave transmit datas ; no
  246. ; ------------------------------;
  247. MOV W,Y ; Y = output buffer ptr
  248. ADD #1,Y ; first reserve one byte for length
  249. BEGIN ;
  250. ; --------------------------;
  251. ; slave send byte ;
  252. ; --------------------------;
  253. MOV.B @Y+,&0x64E ; [Y]+ --> UCB0TXBUF
  254. BEGIN ;
  255. BIT.B #0x8C,&0x66C ; UCB0IFG(CLTO,STP,STT,) = 1 ? ( SCL low timeout,STOP, START)
  256. 0<> IF ;
  257. ; ------------------;
  258. ; master stop/rStart;
  259. ; ------------------;
  260. SUB W,Y ; BUF (ptr-org)= count+1
  261. SUB.B #1,Y ; Y = count
  262. MOV.B Y,0(W) ; store length in buf_out(0)
  263. ; ------------------;
  264. RETI ;
  265. ; ------------------;
  266. THEN ;
  267. BIT.B #0x02,&0x66C ; UCB0IFG(TX0) = 1 ?
  268. <> UNTIL ;
  269. AGAIN ;
  270. THEN ; if bad I2C address
  271. BIC.B #0x20,&0x640 ; UCB0CTLW0(UCTXACK) : send Nack address
  272. RETI ;
  273. ENDCODE
  274. ; --------------------------------------;
  275. CODE START ;
  276. ; --------------------------------------;
  277. ; init I2C_slave ;
  278. ; UCB0CTLW0 = 0b0000 0111 1100 0001 0x640
  279. ; - UCMST = 0 : I2C_Slave
  280. ; -- UCMODE = 0b11 = I2C
  281. ; _ USYNC=1 (always 1)
  282. ; -- UCSSEL=SMCLK (don't care in slave mode)
  283. ; - UCTXACK=0 not auto ACK slave address
  284. ; - UCTR=0 : RX (for RX address)
  285. ; - UCSWRST=1
  286. ; UCB0CTLW1 = 0b0000 0000 1101 0000 0x642
  287. ; - UCETXINT=0 : UCTXIFG0 set address match UCxI2COAx and TX mode
  288. ; -- UCCLTO=0b11 : SCL low time out = 34 ms
  289. ; - UCSWACK=1 : UCTXACK must be written to continue
  290. ; UCB0RXBUF 0x64C
  291. ; UCB0TXBUF 0x64E
  292. ; UCB0I2COA0 0x654 must be written ? enabled ?
  293. ; UCB0ADDRX 0x65C
  294. ; UCB0ADDMSK 0x65E
  295. ; UCB0IE = 0b0000 0000 0000 0100 0x66A
  296. ; - UCSTTIE : StartCond Interrupt only
  297. ; UCB0IFG 0x66C
  298. ; UCB0IV 0x66E : write it to clear all IFG
  299. ; ------------------------------;
  300. ; init I2C_slave ;
  301. ; ------------------------------;
  302. MOV #1,&0x640 ; set eUSCI_B in reset state
  303. BIS #0x07A0,&0x640
  304. BIS #0x0010,&0x642 ; UCB0CTLW1 : set software ack address
  305. MOV #0x040A,&0x654 ; UCB0I2COA0 : UCOAEN=1 enable with address slave
  306. MOV #0,&0x65E ; UCB0ADDMSK : enable address mask for all addresses i.e. software address
  307. BIC #1,&0x640 ; activate eUSCI_B
  308. MOV #0x0004,&0x66A ; UCB0IE : enable StartCond interrupt
  309. MOV #0b1010,&MY_I2CADR ; my slave address, without RW flag !
  310. ; ------------------------------;
  311. ; init interrupt vectors
  312. ; ------------------------------;
  313. MOV #IR_RC5,&0xFFD0 ; init P4 vector interrupt
  314. MOV #I2C_S,&0xFFEE ; eUSCIB0 interrupt vector
  315. ; ------------------------------;
  316. ; init PORTA (P2:P1) (complement) default I/O are input with pullup resistors
  317. ; ------------------------------;
  318. BIC.B #0xC0,&0x206 ; P1REN.76 SDA + SCL pullup/down disable
  319. BIS.B #0xC0,&0x20C ; P1SEL1.76 on : enable I2C I/O
  320. ; ------------------------------;
  321. ; init PORTB (P4:P3) (complement) default I/O are input with pullup resistors
  322. ; ------------------------------;
  323. BIC.B #0x01,&0x23D ; P4IFG.0 clear int flag for TSOP32236 (after IES select)
  324. BIS.B #0x01,&0x23B ; P4IE.0 enable interrupt for TSOP32236
  325. ; ------------------------------;
  326. ASM>FORTH
  327. ." Type STOP to quit RC5_to_I2C_Slave"
  328. LIT RECURSE IS WARM \ ; insert this starting routine between COLD and WARM...
  329. (WARM) ; ; ...and continue with WARM
  330. CODE STOP
  331. MOV #1,&0x640 ; set eUSCI_B in reset state
  332. BIC.B #0x01,&0x023B ; Clear P4IE.0 IR_RC5 interrupt from TSOP32236
  333. ASM>FORTH
  334. ['] (WARM) IS WARM \ ; reconnect RUNNING to WARM
  335. -1 ABORT"
  336. ; ; above, ABORT" followed by CRLF allows ABORT" without message...
  337. ; DUP HERE SWAP - DUMP ; general minidump, part 2
  338. FORGET I2C_S FORGET IR_RC5 ; not FORTH executable
  339. ECHO
  340. RST_HERE
  341. START