/MSP-EXP430FR5969/MSP-EXP430FR5969_RC5_to_I2CF_SoftM.4th
Forth | 445 lines | 411 code | 34 blank | 0 comment | 13 complexity | 060d1de55250ff529afb2387f4acf6e1 MD5 | raw file
Possible License(s): GPL-3.0
- ; --------------------------------------
- ; MSP-EXP430FR5969_RC5_to_I2CF_SoftM.4th
- ; --------------------------------------
- STOP ; to stop any interrupt in progress
- WIPE ;
- NOECHO ; comment to debug
- ; FORTH source file
- ; Copyright (C) <2016> <J.M. THOORENS>
- ;
- ; This program is free software: you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, either version 3 of the License, or
- ; (at your option) any later version.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program. If not, see <http://www.gnu.org/licenses/>.
- ; ========================================
- ; DEMO : I2C_MASTER WRITE & I2C_SLAVE READ
- ; I2C_MASTER PART
- ; ========================================
- ; target : MSP-EXP430fr5969 LAUNCHPAD @ 8MHz
- ; ===================================================================================
- ; in case of 3.3V powered by UARTtoUSB bridge, open J13 straps {RST,TST,V+,5V} BEFORE
- ; ===================================================================================
- ; -----------------------------------------------
- ; MSP - LAUNCHPAD <--> OUTPUT WORLD
- ; -----------------------------------------------
- ; P4.6 - J6 - LED1 red
- ; P1.0 - LED2 green
- ; P4.5 - Switch S1 \\\ <--- LCD contrast + (finger :-)
- ; P1.1 - Switch S2 \\\ <--- LCD contrast - (finger ;-)
- ; GND - J1.2 \\\ <-------+---0V0----------> 1 LCD_Vss
- ; VCC - J1.3 \\\ >------ | --3V6-----+----> 2 LCD_Vdd
- ; \\\ | |
- ; \\\ |___ 470n ---
- ; \\\ ^ | ---
- ; \\\ / \ BAT54 |
- ; \\\ --- |
- ; \\\ 100n | 2k2 |
- ; P2.2 - J4.7 UCB0 CLK TB0.2 \\\ >---||--+--^/\/\/v--+----> 3 LCD_Vo (=0V6 without modulation)
- ; P3.4 - J4.8 \\\ -------------------------> 4 LCD_RS
- ; P3.5 - J4.9 \\\ -------------------------> 5 LCD_R/W
- ; P3.6 - J4.10 \\\ -------------------------> 6 LCD_EN0
- ; PJ.0 - J3.1 \\\ <------------------------> 11 LCD_DB4
- ; PJ.1 - J3.3 \\\ <------------------------> 12 LCD_DB5
- ; PJ.2 - J3.5 \\\ <------------------------> 13 LCD_DB5
- ; PJ.3 - J3.7 \\\ <------------------------> 14 LCD_DB7
-
- ; P2.0 - J13.8 UCA0 TXD ---> RX UARTtoUSB bridge
- ; P2.1 - J13.10 UCA0 RXD <--- TX UARTtoUSB bridge
- ; P4.1 - J13.14 RTS ---> CTS UARTtoUSB bridge (optional hardware control flow)
- ; VCC - J13.16 <--- VCC (optional supply from UARTtoUSB bridge - WARNING ! 3.3V !)
- ; GND - J13.20 <--> GND (optional supply from UARTtoUSB bridge)
-
- ; VCC - J11.1 ---> VCC SD_CardAdapter
- ; GND - J12.3 <--> GND SD_CardAdapter
- ; P2.4 - J4.6 UCA1 CLK ---> CLK SD_CardAdapter (SCK)
- ; P4.3 - J4.5 ---> CS SD_CardAdapter (Card Select)
- ; P2.5 - J4.4 UCA1 TXD/SIMO ---> SDI SD_CardAdapter (MOSI)
- ; P2.6 - J4.3 UCA1 RXD/SOMI <--- SDO SD_CardAdapter (MISO)
- ; P4.2 - J4.2 <--- CD SD_CardAdapter (Card Detect)
-
- ; P4.0 - J3.10 <--- OUT IR_Receiver (1 TSOP32236)
- ; VCC - J3.2 ---> VCC IR_Receiver (2 TSOP32236)
- ; GND - J3.9 <--> GND IR_Receiver (3 TSOP32236)
-
- ; PJ.4 - LFXI 32768Hz quartz
- ; PJ.5 - LFXO 32768Hz quartz
- ; PJ.6 - HFXI
- ; PJ.7 - HFXO
-
- ; P1.2 - J5.19 Soft I2C_Master <--> SDA <----------------------------------------------------> P1.6 other LAUNCHPAD
- ; P1.3 - J5.11 Soft I2C_Master ---> SCL -----------------------------------------------------> P1.7 other LAUNCHPAD
- ; P1.4 - J5.12 TB0.1 <--> free
- ; P1.5 - J5.13 UCA0 CLK TB0.2 <--> free
- ; P1.6 - J5.15 UCB0 SDA/SIMO <--> SDA
- ; P1.7 - J5.14 UCB0 SCL/SOMI <--- SCL
- ; P3.0 - J5.7 <--> free
- ; P2.3 - NC
- ; P2.7 - NC
- ; P3.1 - NC
- ; P3.2 - NC
- ; P3.3 - NC
- ; P3.7 - NC
- ; P4.4 - NC
- ; P4.7 - NC
- ; HERE ; general minidump, part 1
- ; ==========================================================;
- ; I2C SOFT MASTER Fast mode (400kHz) ;
- ; ==========================================================;
- ; P1.2 = SDA
- ; P1.3 = SCL
- ; use Px.0 to Px.3 for good timing at 8 MHz
- ; tested in RX and TX at 8 MHZ with 3k3 external pullup resistors
- ; results : speed in RX = TX = 270 kHz
- VARIABLE I2CSLV_ADR ; contents slave address & R/W
- VARIABLE I2CM_OUT ; buffer output, lentgh,DATA (low,HIGH)
- VARIABLE I2CM_IN ; buffer input, lentgh,DATA (low,HIGH)
- 2 ALLOT
- ; ------------------------------;
- CODE I2C_MTX ; MASTER TX one byte ; shared code for address and TX data
- ; ------------------------------;
- BEGIN ;
- ADD.B X,X ; 1 l shift one left
- U>= IF ; 2 l carry set ?
- BIC.B #0x04,&0x204 ; 4 l yes : P1DIR.2 as input ==> SDA high because pull up resistor
- ELSE ; 2 l
- BIS.B #0x04,&0x204 ; 4 l no : P1DIR.2 as output ==> SDA low
- THEN ; l _
- BIC.B #0x08,&0x204 ; 4 l _^ P1DIR.3 release SCL (high)
- BEGIN ; 14/16~l
- BIT.B #0x08,&0x200 ; 3 h test if SCL is released
- 0<> UNTIL ; 2 h _
- BIS.B #0x08,&0x204 ; 4 h v_ P1DIR.3 as output : force SCL low
- SUB #1,W ; 1 l dec count of bits
- 0= UNTIL ; 2 l
- ; ------------------------------;
- ; I2C_Master_TXreadAckOrNack ; here, SDA is indetermined, SCL is strech low by master
- ; ------------------------------;
- BIC.B #0x04,&0x204 ; 3 l P1DIR.2 as input : release SDA high
- ; JMP M_SCL ; 2 l
- MOV @RSP+,PC ; 4 l
- ENDCODE ;
- ; ------------------------------;
- ; P4.0 - J3.10 <--- OUT IR_Receiver (1 TSOP32236)
- ; VCC - J3.2 ---> VCC IR_Receiver (2 TSOP32236)
- ; GND - J3.9 <--> GND IR_Receiver (3 TSOP32236)
-
- ; ------------------------------;
- ; IR_RC5 driver ;
- ; ******************************;
- CODE IR_RC5 ; wake up on P4.0 change interrupt
- ; ******************************;
- BIC #0xF8,0(RSP) ; CPU on, GIE off in oldSR
- ; ------------------------------;
- ; in : SR(9)=old Toggle bit memory
- ; SMclock = 8 MHz or 16 MHz
- ; use : U,V,W,X,Y, TA0 timer, TA0R register
- ; out : U = 0 x T A4 A3 A2 A1 A0| 0 C6 C5 C4 C3 C2 C1 C0
- ; SR(9)=new Toggle bit memory
- ; ------------------------------;
- ; RC5_FirstStartBitHalfCycle: ;
- ; ------------------------------;
- MOV #0,&0x0360 ; predivide by 1 in TA0EX0 register ( 8 MHZ), reset value
- ; MOV #1,&0x0360 ; predivide by 2 in TA0EX0 register (16 MHZ)
- ; MOV #2,&0x0360 ; predivide by 3 in TA0EX0 register (24 MHZ)
- MOV #1778,X ; RC5_Period in us
- MOV #14,W ; count of loop
- BEGIN ;
- ; ------------------------------;
- ; RC5_TopSynchro: ; <--- loop back ---+ with readjusted RC5_Period
- ; ------------------------------; | here, we are just after 1/2 RC5_cycle
- MOV #0b1011100100,&0x0340 ; (re)start timer_A | SMCLK_pre/2 /8 : 2us time interval,free running,clear TA0_IFG and TA0R
- ; RC5_Compute_3_4Period: ; |
- RRUM #1,X ; X=1/2 cycle |
- MOV X,Y ; Y=1/2 ^
- RRUM #1,Y ; Y=1/4
- ADD X,Y ; Y=3/4
- ; RC5_Wait_1_4: ; wait 3/4 cycle after 1/2 cycle to sample RC5_Input at 1/4 cycle
- BEGIN CMP Y,&0x0350 ; CMP &TA0R with 3/4 cycle value
- = UNTIL ;
- ; ------------------------------;
- ; RC5_Sample: ; at 1/4 cycle, we can sample RC5_input, ST2/C6 bit first
- ; ------------------------------;
- BIT.B #0x01,&0x0221 ; C_flag = P4.0 = IR bit
- ADDC V,V ; C_flag <-- V(15):V(0) <-- C_flag
- MOV.B &0x0221,&0x0239 ; preset IES_4.0 state for next IFG
- BIC.B #0x01,&0x023D ; clear P4.0_IFG after full cycle pin change
- SUB #1,W ; decrement count loop
- ; count = 13 ==> V = x x x x x x x x |x x x x x x x /C6
- ; count = 0 ==> V = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
- 0<> WHILE ; ----> out of loop ----+
- ; RC5_compute_2_4_OverFlow: ; |
- ADD X,Y ; | out of bound = 5/4 period
- ; RC5_WaitHalfCycleP1.2_IFG: ; |
- BEGIN ; |
- CMP Y,&0x0350 ; | TA0R = 5/4 cycle test
- >= IF ; | if cycle time out of bound
- MOV #4,&0x0340 ; | stop timer_A and clear TA0R
- RETI ; | then quit to do nothing
- THEN ; |
- ; ------------------------------; |
- BIT.B #0x01,&0x023D ; ^ | test P4.0_IFG
- <> UNTIL ; | |
- MOV &0x0350,X ; | | get new RC5_period value
- REPEAT ; ----> loop back --+ |
- ; ------------------------------; |
- ; RC5_SampleEndOf: ; <---------------------+
- ; ------------------------------;
- MOV #4,&0x0340 ; stop timer_A
- RLAM #1,V ; V = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
- ; ------------------------------;
- ; ------------------------------;
- ; Only New_RC5_Command ADD_ON ; use SR(9) bit as toggle bit
- ; ------------------------------;
- MOV @RSP,X ; retiSR(9) = old RC5 toggle bit
- RLAM #4,X ; retiSR(9) --> X(13)
- XOR V,X ; (new XOR old)(13) Toggle bit
- BIT #0x2000,X ; X(13) = New_RC5_command
- 0= IF ;
- RETI ; case of repeated RC5_command : RETI without SR(9) change
- THEN ;
- XOR #0x0200,0(RSP) ; change Toggle bit memory SR(9)
- ; ------------------------------;
- ; ------------------------------;
- ; RC5_ComputeNewRC5word ;
- ; ------------------------------;
- MOV.B V,U ; U= 0 0 0 0 0 0 0 0 C5 C4 C3 C2 C1 C0 0 0
- RRUM #2,U ; U= 0 0 0 0 0 0 0 0 0 0 C5 C4 C3 C2 C1 C0
- ; AND #0x7F00,V ; V= 0 /C6 Tg A4 A3 A2 A1 A0 0 0 0 0 0 0 0 0
- ; ADD V,U ; U= 0 /C6 Tg A4 A3 A2 A1 A0 0 0 C5 C4 C3 C2 C1 C0
- ; ------------------------------;
- ; RC5_ComputeC6bit ;
- ; ------------------------------;
- BIT #0x4000,V ; test /C6
- 0= IF BIS.B #0x40,U ; set C6 bit
- THEN ;
- ; ------------------------------;
- ; RC5_CommandByteIsDone: ; U= 0 0 0 0 0 0 0 0 0 C6 C5 C4 C3 C2 C1 C0
- ; ------------------------------;
- ; Prepare I2C_MASTER ;
- ; ------------------------------;
- SWPB U ; 1 high byte = data
- ADD #1,U ; 1 low byte = count
- MOV U,&I2CM_OUT ; 3
- ; ------------------------------;
- ; SUB #2,PSP
- ; MOV TOS,0(PSP)
- ; MOV.B U,TOS
- ; ASM>FORTH
- ; cr ." 0x" HEX 2 U.R
- ; FORTH>ASM
- ; ==============================;
- ; CODE I2C_M ; soft I2C_Master driver
- ; ==============================;
- ; ; in : I2CSLV_ADR & (R/W)
- ; ; : I2CM_IN/I2CM_OUT as requested by I2C_SLA_ADR(0)
- ; ; : I2CM_IN/I2CM_OUT(0) = count of datas to be TX/RX
- ; ; : I2CM_IN/I2CM_OUT(0) = 0 ==> send only I2C address
- ; ; used: U BUF_PTR
- ; ; V count of I2C datas exchanged
- ; ; W count of bits
- ; ; X data
- ; ; Y BUF_ORG
- ; ; out : I2CSLV_ADR & (R/W) unchanged
- ; ; Y = BUF_ORG
- ; ; U = BUF_PTR pointing on first data not exchanged
- ; ; V = count+1 of TX/RX datas exchanged (if ack on addr)
- ; ; I2CM_IN/OUT(0) = count of data not exchanged (normally = 0)
- ; ; I2CM_IN/OUT(0) = -1 <==> Nack on address
- ; ------------------------------;
- ; I2C_Master_Start_Cond: ; here, SDA and SCL are in idle state
- ; ------------------------------;
- BIS.B #0x04,&0x204 ; 4 l P1DIR.2 force SDA output (low)
- MOV.B &I2CSLV_ADR,X ; 3 h @ in X
- MOV #I2CM_OUT,U ; 2 h buffer out by default
- BIT.B #1,X ; 1 h test I2C R/w flag
- 0<> IF ; 2 h
- MOV #I2CM_IN,U ; 2 h buffer in
- THEN ;
- MOV U,Y ; 1 h U=BUF_ptr Y=BUF_org
- MOV.B @U+,V ; 2 h V = count of datas
- ; ; ------------------------------;
- ; ; Init M_TI2C first ! ; IP must be initialized
- ; ; ------------------------------;
- ; MOV #2,IP ; 1 h tHD:STA=4us, 15~ complement @ 8MHz
- ; ; MOV #13,IP ; 2 h tHD:STA=4us, 48~ complement @ 16MHz
- ; ; MOV #23,IP ; 2 h tHD:STA=4us, 78~ complement @ 24MHz
- ; ; ------------------------------;
- ; CALL #M_TI2C ; wait tHD;STA
- BIS.B #0x08,&0x204 ; 4 h P1DIR.3 force SCL output (low)
- ; ------------------------------; l
- ; I2C_Master_Start_EndOf: ;
- ; ------------------------------;
- ; I2C_Master_Send_address ; may be SCL is held low by slave
- ; ------------------------------;
- ADD #1,V ; 1 l to add address in count
- MOV #8,W ; 1 l prepare 8 bit Master writing
- ; ; ADD #0,IP ; 2 l tLOW=4,7us, 15~ complement @ 8MHz
- ; ; ADD #3,IP ; 2 l tLOW=4,7us, 54~ complement @ 16MHz
- ; ; ADD #4,IP ; 2 l tLOW=4,7us, 90~ complement @ 24MHz
- ; ------------------------------;
- CALL #I2C_MTX ; 4 l to send address
- ; ------------------------------;
- BEGIN ;
- ; ; ADD #0,IP ; 2 l +15~ complement @ 8MHz
- ; ; ADD #0,IP ; 2 l +45~ complement @ 16MHz
- ; ; ADD #0,IP ; 2 l +78~ complement @ 24MHz
- ; CALL #M_TI2C ; wait still tLOW=4,7us
- ; ------------------------------; l
- ; Master TX/RX ACK/NACK ;
- ; ------------------------------; l _
- ; CALL #M_SCL ; SCL _| |_ C flag = NACK
- BIC.B #0x08,&0x204 ; 3 l _^ P1DIR.3 release SCL (high)
- BEGIN ;
- BIT.B #0x08,&0x200 ; 3 h test if SCL is released
- 0<> UNTIL ; 2 h
- BIT.B #0x04,&0x200 ; 3 h _ P1IN.2 : get SDA
- BIS.B #0x08,&0x204 ; 3 h v_ P1DIR.3 as output : force SCL low
- ; ------------------------------; l
- ; I2C_Master_Loop_Data ;
- ; ------------------------------;
- 0<> IF BIS #2,SR ; 5 l if Nack (TX), force Z+1 ==> StopCond
- ELSE SUB.B #1,V ; 3 l else dec count
- THEN ; l
- ; --------------------------;
- ; I2C_Master_CheckCountDown ; count=0 or Nack received
- ; --------------------------;
- 0= IF ; 2 l count reached or Nack
- ; ----------------------;
- ; I2C_Master_StopCond ;
- ; ----------------------; _
- BIS.B #0x04,&0x204 ; SDA |_ P1DIR.2 as output ==> SDA low
- SUB.B V,0(Y) ; 4 l _ refresh buffer length
- BIC.B #0x08,&0x204 ; SCL _| P1DIR.3 release SCL (high)
- BEGIN ;
- BIT.B #0x08,&0x200 ; 3 h SCL released ?
- 0<> UNTIL ; 2 h
- ; CALL #M_TI2C ; _ wait tSU:STO=0.6us
- BIC.B #0x04,&0x204 ; SDA _| P1DIR.2 as input ==> SDA high with pull up resistor
- ; ----------------------;
- ; I2C_Master_Endof ;
- ; ----------------------;
- RETI ; ====> unique return
- ; --------------------------;
- THEN ;
- ; --------------------------;
- MOV.B #8,W ; 1 l prepare 8 bits transaction
- BIT #1,&I2CSLV_ADR ; 3 l I2C_Master Read/write bit test
- 0= IF ; 2 l write flag test
- ; ======================;
- ; I2C_Master_TX ;
- ; ======================;
- MOV.B @U+,X ; 2 l next byte to transmit
- ; ; ADD #0,IP ; 2 l tLOW=4,7us, 15~ complement @ 8MHz
- ; ; SUB #3,IP ; 2 l tLOW=4,7us, 36~ complement @ 16MHz
- ; ; SUB #2,IP ; 2 l tLOW=4,7us, 72~ complement @ 24MHz
- ; ----------------------; 17 l
- CALL #I2C_MTX ; Master send 8 bits of address then release SDA
- ; ----------------------; 4 l
- ELSE ; l
- ; ======================;
- ; I2C_Master_RX: ; here, SDA is indetermined, SCL is strech low by master
- ; ======================;
- BEGIN ;
- BIC.B #0x04,&0x204 ; 4 l P1DIR.2 as input ==> release SDA high because pull up resistor
- ; ; ADD #0,IP ; 2 l tLOW=4,7us, 6~ complement @ 8MHz
- ; ; SUB #1,IP ; 2 l tLOW=4,7us, 42~ complement @ 16MHz
- ; ; ADD #1,IP ; 2 l tLOW=4,7us, 81~ complement @ 24MHz
- ; ; CALL #M_TI2C ; wait still tLOW
- ; --------------------; 8 l _
- ; CALL #M_SCL ; SCL _| |_
- BIC.B #0x08,&0x204 ; 3 l _^ P1DIR.3 release SCL (high)
- BEGIN ;
- BIT.B #0x08,&0x200 ; 3 h test if SCL is released
- 0<> UNTIL ; 2 h
- BIT.B #0x04,&0x200 ; 3 h _ P1IN.2 : get SDA
- BIS.B #0x08,&0x204 ; 3 h v_ P1DIR.3 as output : force SCL low
- ; --------------------; 4 l
- ADDC.B X,X ; 1 l C <-- X <--- C
- SUB #1,W ; 1 l count of bits
- 0= UNTIL ; 2 l
- MOV.B X,0(U) ; 3 l store byte @ BUF_ptr
- ADD #1,U ; 1 l
- ; ----------------------;
- ; I2C_MSendAckOrNack ; here, SDA is released by slave, SCL is strech low by master
- ; ----------------------;
- SUB.B #1,V ;
- 0<> IF ; 2
- BIS.B #0x04,&0x204 ; 4 l prepare send Ack if byte count <> 1
- THEN ;
- THEN ;
- AGAIN ; 2 l
- ENDCODE ;
- ; ------------------------------;
- ; ------------------------------;
- CODE START ;
- ; ------------------------------;
- ; I2C_MASTER init part ;
- ; ------------------------------;
- MOV #0b0010100,&I2CSLV_ADR ; MSP-EXP430FR5969 slave address, not the tn2313_KPD12 one
- ; ------------------------------;
- ; init PORTB (P2:P1) (complement) default I/O are input with pullup resistors
- ; ------------------------------;
- BIC.B #0x0C,&0x206 ; P1REN.23 SDA, SCL internal pullup resistors disabled
- BIC.B #0x0C,&0x204 ; P1DIR.23 master SDA & SCL pins as input high
- BIC.B #0x0C,&0x202 ; P1OUT.23 preset SDA output low
- ; ------------------------------;
- ; init PORTB (P4:P3) (complement) default I/O are input with pullup resistors
- ; ------------------------------;
- BIC.B #0x01,&0x23D ; P4IFG.0 clear int flag for TSOP32236 (after IES select)
- BIS.B #0x01,&0x23B ; P4IE.0 enable interrupt for TSOP32236
- ; ------------------------------;
- ; init interrupt vectors ;
- ; ------------------------------;
- MOV #IR_RC5,&0xFFD0 ; init P4 vector interrupt
- ; ------------------------------;
- ASM>FORTH
- ." Type STOP to quit RC5_to_I2C_Fast_SoftMaster"
- LIT RECURSE IS WARM \ ; insert this routine between COLD and WARM...
- (WARM) ; ; ...and continue with WARM
- CODE STOP
- BIC.B #0x01,&0x23B ; Clear P4IE.0 IR_RC5 interrupt from TSOP32236
- ASM>FORTH
- ['] (WARM) IS WARM \ ; reconnect WARM to (WARM)
- -1 ABORT"
- ; ; above, ABORT" followed by CRLF allows to compile an empty string...
- ; DUP HERE SWAP - DUMP ; general minidump, part 2
- FORGET I2C_MTX FORGET IR_RC5 ; because not FORTH executable
- ECHO
- RST_HERE
- START