April 29, 2024, 06:11:03 AM

News:

Be sure to checkout our Vixen interfaces in the Library forum -- if you want PC automation at near zero cost, EFX-TEK and Vixen is a great combination of tools.


"Background" Serial -- Single Wire (OT mode)

Started by JonnyMac, June 30, 2008, 06:54:42 PM

Previous topic - Next topic

JonnyMac

June 30, 2008, 06:54:42 PM Last Edit: April 04, 2009, 08:34:40 AM by JonnyMac
This framework is useful when you want "background" serial communications and are dealing with single-wire devices like our accessories (RC-4, etc.).

Note: This is very advanced; you may need to update the ISR code for your specific project.

Edit: Updated to SX/B 2.0x

' =========================================================================
'
'   File...... Buffered_Sio-1W.SXB
'   Purpose... Buffered serial IO over one wire (open true mode)
'   Author.... Jon Williams, EFX-TEK
'              Copyright (c) 2007-2009 EFX-TEK
'              Some Rights Reserved
'              -- see http://creativecommons.org/licenses/by/3.0/
'   E-mail.... jwilliams@efx-tek.com
'   Started...
'   Updated... 04 APR 2009 (updated to SX/B 2.00.xx)
'
' =========================================================================


' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------


' -------------------------------------------------------------------------
' Conditional Compilation Symbols
' -------------------------------------------------------------------------


' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------

DEVICE          SX28, OSCXT2, BOR42
FREQ            20_000_000
ID              "Sio-1w"


' -------------------------------------------------------------------------
' I/O Pins
' -------------------------------------------------------------------------

Sio             PIN     RC.7 INPUT              ' No ULN, SETUP = UP


' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------

IsOn            CON     1
IsOff           CON     0

Yes             CON     1
No              CON     0


' Bit dividers for 6.51 uS interrupt

Baud2400        CON     64
Baud4800        CON     32
Baud9600        CON     16
Baud19K2        CON     8
Baud38K4        CON     4

Baud1x0         CON     Baud38K4                ' 1 bit period (ISR counts)
Baud1x5         CON     Baud1x0 * 3 / 2         ' 1.5 bit periods


SioDrive        CON     %01111111               ' make Sio pin an output
SioFloat        CON     %11111111               ' float Sio pin


LF              CON     10
FF              CON     12                      ' like CLS for terminals
CR              CON     13


' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------

flags           VAR     Byte
isrFlag        VAR     flags.0
rxReady        VAR     flags.1                 ' rx byte waiting

tmpB1           VAR     Byte                    ' work vars for subs/funcs
tmpB2           VAR     Byte
tmpW1           VAR     Word

rxSerial        VAR     Byte (16)
rxBuf          VAR     rxSerial(0)             ' 8-byte buffer
rxCount        VAR     rxSerial( 8 )           ' rx bit count
rxDivide       VAR     rxSerial(9)             ' bit divisor timer
rxByte         VAR     rxSerial(10)            ' recevied byte
rxHead         VAR     rxSerial(11)            ' buffer head (write to)
rxTail         VAR     rxSerial(12)            ' buffer tail (read from)
rxBufCnt       VAR     rxSerial(13)            ' # bytes in buffer

txSerial        VAR     Byte (16)               ' tx serial data
txBuf          VAR     txSerial(0)             ' eight-byte buffer
txCount        VAR     txSerial( 8 )           ' tx bit count
txDivide       VAR     txSerial(9)             ' bit divisor timer
txLo           VAR     txSerial(10)            ' holds start bit
txHi           VAR     txSerial(11)            ' tx output reg
txHead         VAR     txSerial(12)            ' buffer head (write to)
txTail         VAR     txSerial(13)            ' buffer tail (read from)
txBufCnt       VAR     txSerial(14)            ' # bytes in buffer


' =========================================================================
  INTERRUPT NOCODE 153_600                      ' (3)   6.51 uSecs
' =========================================================================


Mark_ISR:
  \ SETB  isrFlag                               ' (1)


' -------
' RX UART
' -------
'
' UART code by C. Gracey, A. Williams, et al
' -- buffer mods by Jon Williams
'
Receive:
  ASM
    BANK  txSerial                              ' (1)
    TEST  txCount                               ' (1)   transmitting now?
    JNZ   RX_Done                               ' (2/4) exit if yes
    BANK  rxSerial                              ' (1)
    JB    rxBufCnt.4, RX_Done                   ' (2/4) skip if buffer is full
    MOVB  C, Sio                                ' (4)   sample serial input
    TEST  rxCount                               ' (1)   receiving now?
    JNZ   RX_Bit                                ' (2/4) yes, get next bit
    MOV   W, #9                                 ' (1)   no, prep for next byte
    SC                                          ' (1/2)
     MOV  rxCount, W                            ' (1)   if start, load  bit count
    MOV   rxDivide, #Baud1x5                    ' (2)   prep for 1.5 bit periods

RX_Bit:
    DJNZ  rxDivide, RX_Done                     ' (2/4) complete bit cycle?
    MOV   rxDivide, #Baud1x0                    ' (2)   yes, reload bit timer
    DEC   rxCount                               ' (1)   update bit count
    SZ                                          ' (1/2)
     RR   rxByte                                ' (1)   position for next bit
    SZ                                          ' (1/2)
    JMP   RX_Done                               ' (3)

RX_Buffer:
    MOV   W, #rxBuf                             ' (1)   point to buffer head
    ADD   W, rxHead                             ' (1)
    MOV   FSR, W                                ' (1)
    MOV   IND, rxByte                           ' (2)   move rxByte to head
    INC   rxHead                                ' (1)   update head
    CLRB  rxHead.3                              ' (1)   keep 0..7
    INC   rxBufCnt                              ' (1)   update buffer count
    SETB  rxReady                               ' (1)   set ready flag

RX_Done:
  ENDASM


' -------
' TX UART
' -------
'
' UART code by C. Gracey, A. Williams, et al
' -- buffer mods by Jon Williams
'
Transmit:
  ASM
    BANK  rxSerial                              ' (1)
    TEST  rxCount                               ' (1)   receiving now?
    JNZ   TX_Done                               ' (2/4) exit if yes
    BANK  txSerial                              ' (1)
    TEST  txCount                               ' (1)   transmitting now?
    JZ    TX_Buffer                             ' (2/4) if txCount = 0, no
    DEC   txDivide                              ' (1)   update bit timer
    JNZ   TX_Done                               ' (2/4) time for new bit?
    MOV   txDivide, #Baud1x0                    ' (2)   yes, reload timer
    STC                                         ' (1)   set for stop bit
    RR    txHi                                  ' (1)   rotate TX buf
    RR    txLo                                  ' (1)
    DEC   txCount                               ' (1)   update the bit count
    JB    txLo.6, TX_Bit1

TX_Bit0:
    MODE  $0F                                   ' (1)
    MOV   !RC, #SioDrive                        ' (2)   make Sio output
    CLRB  Sio                                   ' (1)   output 0
    JMP   TX_Done                               ' (3)

TX_Bit1:
    MODE  $0F                                   ' (1)
    MOV   !RC, #SioFloat                        ' (2)   make Sio float
    JMP   TX_Done                               ' (3)

TX_Buffer:
    TEST  txBufCnt                              ' (1)   anything in buffer?
    JZ    TX_Done                               ' (2/4) exit if empty
    MOV   W, #txBuf                             ' (2)   point to buffer tail
    ADD   W, txTail                             ' (1)
    MOV   FSR, W                                ' (1)
    MOV   txHi, IND                             ' (2)   move byte to TX reg
    CLR   txLo                                  ' (1)   clear for start bit
    MOV   txCount, #10                          ' (2)   start + 8 + 1 stop
    INC   txTail                                ' (1)   update tail pointer
    CLRB  txTail.3                              ' (1)   keep 0..7
    DEC   txBufCnt                              ' (1)   update buffer count

TX_Done:
  ENDASM

  RETURNINT                                     ' (4)


' -------------------------------------------------------------------------
' Subroutine / Function Declarations
' -------------------------------------------------------------------------

DELAY_TIX       SUB     2, 2, Word              ' delay in 6.51us units
DELAY_MS        SUB     2, 2, Word              ' replaces PAUSE

RX_BYTE         FUNC    1, 0                    ' receive a byte

TX_STR          SUB     2, 2, Word              ' transmit a string
TX_BYTE         SUB     1                       ' transmit a byte

UCASE           FUNC    1, 1                    ' convert to uppercase


' =========================================================================
  PROGRAM Start
' =========================================================================

Start:
  PLP_A = %0000                                 ' pull-up unused pins
  PLP_B = %00000000
  PLP_C = %10000000

  DELAY_MS 5                                    ' clear device RX buffer


Main:

  GOTO Main


' -------------------------------------------------------------------------
' Subroutine / Function Code
' -------------------------------------------------------------------------

' Use: DELAY_TIX duration
' -- delay in ISR "ticks"
' -- 6.51us if ISR rate is 153_600

SUB DELAY_TIX
  '{$IFUSED DELAY_TIX}
  tixDuration   VAR     __WPARAM12

  DO WHILE tixDuration > 0
    ASM
      CLRB  isrFlag                             ' clear isr flag
      JNB   isrFlag, @$                         ' wait for next
    ENDASM
    DEC tixDuration                             ' update duration timer
  LOOP
  '{$ENDIF}
  ENDSUB

' -------------------------------------------------------------------------

' Use: DELAY_MS duration
' -- replaces PAUSE
' -- assumes ISR rate of 153_600

SUB DELAY_MS
  '{$IFUSED DELAY_MS}
  msDuration    VAR     __WPARAM12
  msTimer       VAR     __PARAM3

  DO WHILE msDuration > 0
    msTimer = 153 + msDuration.0                ' (re)load 1ms timer
    DO WHILE msTimer > 0
      ASM
        CLRB  isrFlag                           ' clear isr flag
        JNB   isrFlag, @$                       ' wait for next
        DEC   msTimer                           ' update 1ms timer
      ENDASM
    LOOP
    DEC msDuration                              ' update duration timer
  LOOP
  '{$ENDIF}
  ENDSUB

' -------------------------------------------------------------------------

' Use: aByte = RX_BYTE
' -- returns "aByte" from 8-byte circular buffer
' -- will wait if buffer is presently empty
' -- rxBufCnt holds byte count of receive buffer (0 to 8)

FUNC RX_BYTE
  '{$IFUSED RX_BYTE}
  ASM
    JNB   rxReady, @$                           ' wait if empty
    BANK  rxSerial
    MOV   FSR, #rxBuf                           ' point to rxBuf(rxTail)
    ADD   FSR, rxTail
    MOV   __PARAM1, IND                         ' get byte at tail
    INC   rxTail                                ' update tail
    CLRB  rxTail.3                              ' keep 0..7
    DEC   rxBufCnt                              ' update buffer count
    SNZ                                         ' exit if not zero
     CLRB rxReady                               ' else clear ready flag
    BANk  $00
  ENDASM
  '{$ENDIF}
  ENDFUNC

' -------------------------------------------------------------------------

' Use: TX_STR [String | Label]
' -- pass embedded string or DATA label

SUB TX_STR
  '{$IFUSED TX_STR}
  strAddr       VAR     tmpW1
  strChar       VAR     __PARAM1

  strAddr = __WPARAM12                          ' get string address

  DO
    READINC strAddr, strChar                    ' read a character
    IF strChar = 0 THEN EXIT                    ' if 0, string complete
    TX_BYTE strChar                             ' send the byte
  LOOP
  '{$ENDIF}
  ENDSUB

' -------------------------------------------------------------------------

' Use: TX_BYTE aByte
' -- moves "aByte" to 8-byte circular buffer (when space is available)
' -- will wait if buffer is presently full
' -- txBufCnt holds byte count of transmit buffer (0 to 8)

SUB TX_BYTE
  '{$IFUSED TX_BYTE}
  ASM
    BANK  txSerial
    JB    txBufCnt.3, @$                        ' prevent buffer overrun
    MOV   W, #txBuf                             ' point to buffer head
    ADD   W, txHead
    MOV   FSR, W
    MOV   IND, __PARAM1                         ' move byte to tx buf
    INC   txHead                                ' update head pointer
    CLRB  txHead.3                              ' keep 0..7
    INC   txBufCnt                              ' update buffer count
    BANK  $00
  ENDASM
  '{$ENDIF}
  ENDSUB

' -------------------------------------------------------------------------

' Use: result = UCASE char
' -- if char is lowercase alpha it is converted to uppercase

FUNC UCASE
  '{$IFUSED UCASE}
  ASM
    CJB   __PARAM1, #"a", @UC_Exit
    CJA   __PARAM1, #"z", @UC_EXIT
    CLRB  __PARAM1.5

UC_Exit:
  ENDASM
  '{$ENDIF}
  ENDFUNC



' -------------------------------------------------------------------------
' User Data
' -------------------------------------------------------------------------

CrLf:
  DATA  CR, LF, 0                               ' CR + LF
Jon McPhalen
EFX-TEK Hollywood Office