Alpha LED  Clock Display Code Picaxe Basic Program

Declarations and Data

#rem

AlphaLEDClockDispChk.bas This is the clock with the green line of LEDs in a wood cabinet

It is used with a PC keyboard with PS/2 connector

John Saunders 10/17/2014 This ran from 10/17/2014 to 1/10/2015 OK. Needs only different month timer and sounds

1/10/2015 Moved power out code to transmit RF

2/42015 Added transmit each min date and time++

3/12/2015 Corrected TXDate_Time call error. 3/13/2017 Added Checksum to time message

10/8/2018 added padding to SEROUT

3/14/2020 increased transmit prepulse to 20 from 15 ms

3/25/2020 Send command twice

4/21/2022  Turn off time transmission in line 200 percharacter 20 in the variable message


DS1307 address map:

0-7  maintained by the clock - see DS-1307 data sheet

8 = Page to display (0-8), 9 = Blinking Character position (0-22), 10 = Timer index (0-5),11 = IR Command.

12 - 39 = 7 Daily timers each having 4 bytes in this order.:

Hour, Minute, Rate and its  parameter in one byte & Type, also with a parameter in the last byte.

4 - 63 A variable message which may be re-written without reloading the Picaxe.


The 8 pages are selected by the ESC, F1-F9 buttons:


Page descriptions

0    Display Current time,day(string) month(string) date, temperature

1    Display fixed message 1

2    Display fixed message 2

3    Display fixed message 3

4    Display fixed message 4

5    Display variable message

6    Set hour minute day month date year

7    Display selected timer number, Set timer Hour Minute Rate Type

8    Edit variable message



Daily timer Rate codes:

Q = Every quarter hour. The parameter (1) may limit the active hours, or to daylight (2-15).

H = Every hour at the timer minute setting, paramerers as for Q.

D = Every day at the timer hour and minute settings. No parameter.

W = A specific day in the parameter (1=Sunday) at the timer hour and minute settings.

M = As for D but only for the date in the Yearly date setting.

    The parameter selects either the A (A) or B (B) yearly timer.

y = As for M but also including the month in the Yearly month setting..


Daily timer Type codes:

P = Change page. 0-5 parameter.

S = Make a sound selected by the parameter (0-7).

Hex (2A - 7F) = Send an ASCII coded RF transmission..

#endrem


#picaxe 18M2


rem variables

rem general

symbol    Iter       = b2

symbol    Mask       = b3

symbol    BitPos     = b4

symbol      Units      = b5

symbol    Tens       = b12

symbol    Scratch    = b6


rem Specific content

symbol    Request    = Bit1    'The command processor asks for RTC access

symbol    Phase      = bit2    'Current value of the 1 Hz square wave

symbol    OldPhase   = bit3    'Previous value of the 1 Hz square wave

symbol    PwrState   = bit4    'The state of the PwrOut port

symbol    NewInput   = bit5

symbol    TimeTxEn   = bit6    '1 enables time and date transmissions every minute

symbol      Page       = b1    '0=normal,1=set Time&date,2=set timers,3=Set year,4-7=messages

symbol    ADCData    = w13    'Temperature 

symbol    Template   = b7    'EEPROM entry defining a display code

symbol    Command    = b8    'Content of RTC Address $0B, IR code received

symbol    Bright     = b9    'Adjusted photocell reading


rem data

symbol    CharData   = b10    'A displayable value

symbol      DECData    = b11    'Binary value

symbol    BCDData    = b13    'Binary-coded decimal data

symbol    Chcksum    = b21

symbol    ChckHex    = b22


rem pointer

symbol    Seconds    = b14    'Selects the timer do check once a minute

symbol    DispAddr   = b15    'Position of the next character oon the display

symbol    NvAddr     = b16    'An address in the EEPROM

symbol    RTCAddr    = b17    'An address in the DS1307 real-time clock chip

symbol    DispIndex  = b18    'The position in the EEPROM of the next template code to be evaluated

symbol    TimerIndex = b19    'The selected timer 0-5

symbol    BlinkPos   = b20    'The character position to blink during setup



rem outputs

symbol    SRCLK  = B.0    'Shift register clock conn pin 2

symbol    DispWR = B.2    'Display write line - low active conn pin 6

symbol    DispBL = B.3    'Display blanking PWM conn pin 4

symbol    SRIN   = B.5    'Shift register data in conn pin 9

symbol    CLR    = B.6    'Shift register & display clear - low active conn pins 3 & 8

symbol    Grant  = B.7    'Grants Control access to RTC

symbol    Audio  = C.3    'To RCa Jack on rear panel, AC only

symbol      PwrOut = C.0    'Controlled line output on rear panel

symbol    Tx_key = C.7    'Modulation for the transmitter


rem inputs

symbol    PCIN   = C.1    'Photocell analog input, conn pin 1

symbol    TempIn = C.2      'Temperature sensor analog input, 10mv per deg F

symbol      Rqst   = pinC.5    'Request to Control processor to grant RTC access

symbol    sqw    = pinC.6    'RTC square-wave output, conn pin 11


rem rate codes:

symbol    Dawn    = $07

symbol    Bedtime = $20


rem mask for shifting

DATA 0,(1,2,4,8,16,32,64)    'Mask of bits for DispChar


rem Day and month abbreviations

DATA 7,("SunMonTueWedThuFriSat")

DATA 28,("JanFebMarAprMayJunJulAugSepOctNovDec")


#rem 

page templates. 0=tenplate terminator;  3 = day code, 4=temperature, 5 = month code,6 = TimerIndex in ASCII

28 to 127 ASCII literals;

!28 - 150 NvAddresses of fixed strings 

228 - 243: Storage Addresses + 200 

#endrem


DATA 69,(230,":",229,":",228," ",3," ",5," ",232," ",4,$1C,0)      'Page 0 (Clock) template, length 15 

DATA 84,(128,230,":",229,":",228," ",231," ",233,"/",232,"/",234,0) 'Page 6 (Clock set) template  length 15

DATA 99,(133,6,"  ",240,":",241," ",242," "," ",243,0)                  'Page 7 (Timer set) template, length 15



rem variable length fixed strings

DATA 128,("Set:",0)        'length 5

DATA 133,("Timer#",0)        'length 7

DATA 141,("OFF",0)        'length 4



rem Fixed messases - each 25 length or less

DATA 155,("John Loves Elaine       ")

DATA 180,("Message #2              ")

DATA 205,("Bingo                   ")

DATA 230,("Take out all the trash! ")

Startup and Main

startup:

SETFREQ m16

HIGH CLR

LOW Tx_Key

HIGH SRCLK

HIGH DispWR

HIGH DispBL

LOW Audio

LOW PwrOut

LET Page = 0

ADCCONFIG %00000011

LOW Grant


main:

rem allow control processor access to the RTC when requested

LET Request = Rqst    'This is the handshake to permit the Control Processor to turn

IF Request = 1 THEN    'on the relay whih connects it to the RTC I2C lines at its request

    HIGH Grant

    DO

        LET Request = Rqst

        PAUSE 1

    LOOP WHILE Request = 1

    LOW Grant

    PAUSE 5

    LET NewInput = 1

ENDIF

rem Dim the display

FVRSETUP FVR4096        'To get temperature independent of supply voltage

ADCCONFIG %00000000

READADC PCIN,ADCData        'Dims the display according to ambient light    

LET ADCData = 255 - ADCData

IF ADCData < 12 THEN

    LET Bright = 35

ELSEIF ADCData > 43 THEN

    LET Bright = 128

ELSE 

    LET Bright = 3 * ADCData

ENDIF

PWMOUT DispBL,65,Bright


LET Phase = sqw


rem Blink processing and timer evaluation on phase 0 - Time update occurs now

IF Phase = 0 AND OldPhase = 1 THEN

    IF Page > 5  THEN   'Blinking is enabled

        LET CharData = " "

        LET DispAddr = BlinkPos & $1F

        GOSUB DispChar

        IF Page = 6 THEN

            GOSUB DispChar

        ENDIF

        IF Page = 7 AND  BlinkPos < 15 THEN 'The Timer hours and minute fields

            GOSUB DispChar

        ENDIF

    ENDIF    

    PEEK 28,BCDData        'Current seconds

    IF BCDData < 8 THEN

        GOSUB TimeCheck    'Minute processing

    ELSEIF BCDData = 8 AND TimeTxEn = 1 THEN

        GOSUB TXDate_Time

    ENDIF

ENDIF


rem Update display on phase 1    

IF Phase = 1 AND OldPhase = 0 THEN 'Get all required DS1307 RTC contents

    I2CSLAVE %11010000,i2cslow,i2cbyte

    LET bptr = 28

    READI2C 0,(@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptr,Page,BlinkPos,TimerIndex,Command)

    WRITEI2C $0B,(0)        'Clear the command in the RTC

rem some checks

    IF Page > 8 THEN

        LET Page = 0

    ENDIF

    IF BlinkPos > 23 THEN

        LET BlinkPos = 0

    ENDIF

    IF TimerIndex > 6 THEN

        LET TimerIndex = 0

    ENDIF

rem Is this a direct command?

    IF Command > $2A THEN    'Transmit a RF command

        GOSUB TransmitRF

    ENDIF

    LET Command = 0

rem Store data of the timer being edited if in page 7

    IF Page = 7 THEN

        LET RTCAddr = 4 * TimerIndex + 12

        LET bptr = 40

        READI2C RTCAddr,(@bptrinc,@bptrinc,@bptrinc,@bptr)    'Hour,minute,rate,type

    ENDIF

rem Store the data of the timer selected by the first 7 seconds of the minute

    PEEK 28,BCDData        'Seconds

    LET RTCAddr = 0

    LOOKUP BCDData,(12,16,20,24,28,32,36),RTCAddr

    LET bptr = 44

    IF RTCAddr <> 0 THEN 'Spread out the timers checks over the first 6 seconds of each minute

        READI2C RTCAddr,(@bptrinc,@bptrinc,@bptrinc,@bptr)  'Hour,minute,rate,type

    ENDIF

rem Store the variable message if in pages 5 or 8

    IF Page = 5 or Page = 8 THEN

        LET bptr = 48

        READI2C $28,(@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptr)

    ENDIF

rem Check fot time and date transmission update status

    READI2C 60,(Chardata)            'Position 20 of the variable message, should be N or F

    IF Chardata = "F" THEN

        timeTxEn = 0

    ELSE

        timeTxEn = 1

    ENDIF

    GOSUB Update

ENDIF

    

LET OldPhase = Phase


goto main


END

Sub-programs

TransmitRF:

IF Command = "+" THEN        'Q sends =/+

    HIGH PwrOut

ENDIF

IF Command = "-" THEN

    LOW PwrOut

ENDIF

SETFREQ m8

HIGH Tx_Key     'This pulse unlocks the receiver

PAUSE 40

LOW Tx_Key

PAUSE 20

SEROUT TX_Key,N2400_8,("14L1776",Command,13,10)        'The CR,LF is for debugging

PAUSE 200

HIGH Tx_Key     'This pulse unlocks the receiver

PAUSE 40

LOW Tx_Key

PAUSE 20

SEROUT TX_Key,N2400_8,("14L1776",Command,13,10)    

SETFREQ m16

RETURN


DispChar:    'shifts 8 bits address then 8 bits character LSB first, then load display 

'Input is Chardata and DispAddr

'At 8MHz with no rewrite, time is 3.2 ms, with rewrite 33.4 ms, total 206 ms, 1 rewrite

'At 32MHz with no rewrite, time is 2.3 ms, with rewrite 10 ms, total 209 ms, 1 rewrite

'Gap between characters = 5.8 ms

LET BitPos = $50 + DispAddr

PEEK BitPos,Mask

IF Mask = CharData OR DispAddr > 23 OR CharData < $1B THEN

    GOTO ItsSame

ELSE

    POKE BitPos,CharData

ENDIF

FOR BitPos = 0 TO 4

    READ BitPos,Mask

    LET Mask = DispAddr & Mask 

     LOW SRIN

     IF Mask = 0 then Addrbitislow

    HIGH SRIN

Addrbitislow:

     PULSOUT SRCLK,1

NEXT

LOW SRIN

PULSOUT SRCLK,1

HIGH SRIN                'CU is high

PULSOUT SRCLK,1

PULSOUT SRCLK,1

FOR BitPos = 0 TO 6

    READ BitPos,Mask

    LET Mask = CharData & Mask 

     LOW SRIN

    IF Mask = 0 then Charbitislow

    HIGH SRIN

Charbitislow:

     PULSOUT SRCLK,1

NEXT

PULSOUT SRCLK,1

PULSOUT DispWR,1

ItsSame:

IF CharData <> 0 THEN

    INC DispAddr

ENDIF

RETURN


DispDec: 'Displays DECData (byte) at current address position in Digital as 3 characters        

LET Tens = DECData / 100

LET Units = DECData // 100

IF Tens = 0 THEN

    LET CharData = " "

ELSE

    LET CharData = Tens + "0"

ENDIF

GOSUB DispChar

LET CharData = Units / 10 + "0"

GOSUB DispChar

LET CharData = Units // 10 + "0"

GOSUB DispChar

RETURN


DispBCD:

BCDTOASCII BCDData,Tens,Units

IF Tens <> "0" OR Page <> 0 THEN 'Omit leading 0 only in page 0

    LET CharData = Tens

    GOSUB DispChar

ENDIF

LET CharData = Units

GOSUB DispChar

RETURN


DispHex:                'Input is in Units

IF Units < 10 THEN

    LET Chardata = Units + "0"

ELSE                    

    LET Chardata = Units + "7"

ENDIF

GOSUB DispChar

RETURN


DispString:                'Displays a null-terminated string at EEPROM address NVAddr at DispAddr

DO

    READ NvAddr,CharData

    INC NvAddr

    GOSUB DispChar

LOOP    WHILE CharData <> 0 AND DispAddr < 24

RETURN


DispFixed:                'Displays a 24 character string at EEPROM address NVAddr at beginning

DO

    READ NvAddr,CharData

    INC NvAddr

    GOSUB DispChar

LOOP WHILE DispAddr < 24

RETURN


DispVariable:

LET DispAddr = 0

FOR Iter = 48 TO 71

    PEEK Iter,Chardata

    GOSUB DispChar

NEXT Iter

RETURN


BlankEOL:

DO WHILE DispAddr < 24

    LET CharData = " "

    GOSUB DispChar

LOOP

RETURN


DispDOW:    'Day of week as a string

PEEK 31, BCDData        'Bits 0-2 are day of week

LET NVAddr = 3 * BCDData + 4    'Day of week strings start at 7, Sunday is day 1

FOR Iter = 0 to 2

    LET Scratch = NVAddr + Iter

    READ Scratch,CharData

    GOSUB DispChar

NEXT Iter

RETURN


DispMonth:    'Month as a string

PEEK 33,BCDData        'Bits 0-3 are month, 4 is tens of month

LET Units = BCDData & $0F

LET Tens = BCDData & $10

IF Tens = 0 THEN

    LET NvAddr = 3* Units + 25     'Date strings start at 28, January is 1

ELSE

    LET NvAddr = 3* Units + 55     'Oct-Dec strings start at 55, October is $10

ENDIF

FOR Iter = 0 to 2

    LET Scratch = NVAddr + Iter

    READ Scratch,CharData

    GOSUB DispChar

NEXT Iter

RETURN


DispTemperature:        'Right-justified at position 20, pos 23 is for deg F character ($1C)

rem first write spaces to position 20

DO WHILE DispAddr < 20

    LET CharData = " "

    GOSUB DispChar

LOOP

FVRSETUP FVR4096        'To get temperature independent of supply voltage

READADC10 TempIn,ADCData

LET DecData = ADCData / 4

GOSUB DispDec

RETURN


Update:

IF NewInput=1 THEN

    SERTXD ("Page=",#Page,",BlinkPos=",#BlinkPos,",TimerIndex=",#TimerIndex,",Command=",#Command,13,10)

    LET NewInput = 0

ENDIF

LET DispAddr = 0

LET DispIndex = 0

LOOKUP Page,(69,155,180,205,230,5,84,99,8),DispIndex

IF DispIndex = 0 THEN

    RETURN

ENDIF

IF DispIndex = 5 OR DispIndex = 8 THEN        'variable message

    GOSUB DispVariable

    RETURN

ENDIF

IF DispIndex > 150 AND DispIndex < 250 THEN

    LET NvAddr = DispIndex

    GOSUB DispFixed

    RETURN

ENDIF

DO

    READ DispIndex,Template  

    SELECT Template  

        CASE 0

            GOSUB BlankEOL

        CASE 4

            GOSUB DispTemperature

        CASE 3

            GOSUB DispDOW         'as a 3-character string

        CASE 5

            GOSUB DispMonth         'as a 3-character string

        CASE 6                'The current timer

            LET CharData = TimerIndex + $31

            GOSUB DispChar

        CASE 28 TO 127            'An ASCII displayable character

            LET CharData = Template

            GOSUB DispChar

        CASE 128 TO 141

            LET NvAddr = Template

            GOSUB DispString

        CASE 228 TO 243

            LET Scratch = Template - 200    'Address in storage

            PEEK Scratch,BCDData        'The value

            rem Specials

            IF Scratch = 42 OR Scratch = 43 THEN            'Timer rate and type 

                LET Tens = BCDData / 16

                LET Units = BCDData & $0F

                IF Scratch = 42 THEN    'The Rate setting

                    IF Tens = 0 THEN    'OFF

                        LET NvAddr = 141

                        GOSUB DispString

                        GOSUB BlankEOL

                    ELSE

                        LET CharData = " "

                        LOOKUP Tens,("X","T","H","D","W","M","N","Y"),Chardata

                        IF CharData <> " " THEN

                            GOSUB DispChar

                        ENDIF

                        LET Chardata = Units

                        GOSUB DispHex

                    ENDIF

                ENDIF

                IF Scratch = 43 AND DispAddr < 22 THEN    'The Type setting, if not OFF

                    LET CharData = " "

                    LOOKUP Tens,("P","S","2","3","4","5","6","7"),Chardata

                    IF Chardata <> " "  THEN

                        GOSUB DispChar

                    ENDIF

                    LET Chardata = Units

                    GOSUB DispHex

                ENDIF

            ELSE

                GOSUB DispBCD

            ENDIF

        ELSE

            LET CharData = " "

            GOSUB DispChar

    ENDSELECT

    INC DispIndex

LOOP WHILE  DispAddr < 24 AND Template <> 0

RETURN


TimeCheck:

#rem

The second of detection and immediate action is when this subroutine is called

Each of the 6 timers (0-6) has a base RTC address of 12,16.20,24, 28 and 32. These contain BCD numbers

Each Timer has 4 bytes at at these 4 base addresses.

Some timers use the Month in 12 or 14 and the date in 13 or 15, as "A' (12,13) or "B" (14,15)

The 4 bytes are Hour, Minute, Rate and Type. They are in locations 28 - 31


Rate. Its upper 4 bits (MSN) is the rate interval as follows (using the displayed value)

The least significant is a parameter.

Disabled (0="X")

Ten Minutes (1="T") every ten minutes at the given minute. Parameter may limit hours

Hourly (2="H") every hour at the minute setting Parameter may limit hours 

Daily  (3="D") every day at the hour and the minute, Parameter not used

Weekly (4="W") every week at the hour and the minute and the day in the Parameter (1-7), displayed as the ASCII number 

Monthly1 (5="M") every month at the hour and the minute  and the  date 1 - 15 in the parameter as 1 - 15

Monthly2 (6="N") every month at the hour and the minute  and the  date 16 - 31 in the parameter as 0-15

Yearly  (7="Y") every year at the month in the parameter, the date in the hours field and the hour in the minutes field 

#endrem


rem Split up the rate byte of the indicated timer

PEEK 46,BCDData                'Seconds Timer Rate byte 

LET Tens = BCDData / 16

IF BCDData =0 THEN NoMatch            'This Timer is OFF


LET Units = BCDData & $0F        'Parameter of rate


rem First test those modes which check minutes


IF Tens < 7 THEN             'T,H,D,W,N,M

    PEEK 29,BCDData        'Current Minutes

    IF Tens = 1    THEN        'Special for T

        LET BCDData = BCDData & $0F        '0-9

    ENDIF

    PEEK 45,Chardata        'Timer minutes

    IF BCDData <> CharData THEN NoMatch

ENDIF


rem T and H have restrictions

IF Tens = 1 OR Tens = 2 THEN

    IF Units = 0 THEN Pass

    PEEK 30,CharData            'Hours        

    IF Units = 1 AND CharData > Dawn AND CharData < Bedtime THEN Pass

    LET Scratch = 6 * Units    + 35    'Range of bright is 16 to 120

    IF Units > 1 AND Bright > Scratch THEN Pass

    GOTO NoMatch

ENDIF


rem Finished with T and H


IF Tens > 2 AND Tens < 7 THEN 'D,W,M & N - Check hour match next

    PEEK    30,BCDData        'Current Hours

    PEEK  44,CharData        'Timer hours

    IF BCDData <> CharData THEN NoMatch

ENDIF

IF Tens = 3 THEN Pass        'Finished with Daily


IF Tens = 4 THEN            'W only Check the day of week

    PEEK 31,BCDData        'Current Day of week

    IF BCDData = Units THEN Pass

    GOTO NoMatch

ENDIF

rem Finished with weekly


IF Tens = 5 OR Tens = 6 THEN    'M or N - Check the date

    PEEK 32,BCDData        'Current Date

    IF Tens = 6 THEN

        LET Chardata = Units + 16

    ENDIF

    IF BCDData = CharData THEN Pass

ENDIF


rem Finished with monthly


rem Yearly, 7

rem Check Month

PEEK 33, BCDData            'Current Month

IF BCDData <> Units THEN NoMatch

rem Check Date

PEEK 32, BCDData            'Current date

PEEK 44, CharData            'Timer Hours field contains the date

IF BCDData <> Chardata THEN NoMatch

rem Check Hour

PEEK 31, BCDData            'Current hour

PEEK 45, CharData            'Timer minutes field contains the hour

IF BCDData <> Chardata THEN NoMatch

rem We only want one, at minute 0

PEEK 29,BCDData        'Current Minutes

IF BCDData <> 0 THEN NoMatch


Pass:

GOSUB TakeAction


NoMatch:

RETURN


TakeAction:

#rem

The action to be taken on a timer (per seconds) detection is determined by the byte in 19 (Type), which also has a MSN and a LSN

The choices at the MSN are displayed as::

0=Change page if not in a setting and not to a setting

1=Audio (1="A") Plays a sound as specified in the LSN (0 - 5) to the rear RCA speaker jack, displayed as the ASCII number

2 to 7 Transmit Sends a command using the ASCII code given by the action as hex

#endrem


rem Split up the type byte of the indicated timer

PEEK 47,BCDDAta            'The seconds timer Type byte

LET Tens = BCDData / 16    

LET Units = BCDData // 16    'The parameter

IF Tens = 0 AND Units < 6 THEN    'Change page if not in a setting

    LET Page = Units

    WRITEI2C $08,(Page)

ENDIF

IF Tens = 1 THEN            'Audio

    LET Scratch = 4 * Units

    SOUND Audio,(56,Scratch)

ENDIF

IF Tens > 1 AND Tens < 8 THEN            'RF Transmission

    LET Command = BCDData

    GOSUB TransmitRF

    LET Command = 0

ENDIF

RETURN


TXDate_Time:

LET Chcksum = 132                '3 commas

SETFREQ m8

HIGH Tx_Key     'This pulse unlocks the receiver

PAUSE 40

LOW Tx_Key

PAUSE 20

SEROUT TX_Key,N2400_8,("14L1776t,G,")            'G is code for 11 characters

FOR Scratch = 33 TO 29 STEP -1

    IF Scratch <> 31 THEN                    'Day of week not needed

        PEEK Scratch, BCDData

        LET Tens = BCDData / 16 + 48            'BCD data

        LET Units = BCDData & $0F + 48        'Parameter of rate

        SEROUT TX_Key,N2400_8,(Tens,Units,",")

        LET Chcksum = Chcksum + Tens + Units

    ENDIF

NEXT

LET ChckHex = ChckSum / 16

IF ChckHex < 10 THEN

    LET Tens = ChckHex + "0"

ELSE

    LET Tens = ChckHex + "7"

ENDIF

LET ChckHex = ChckSum & $F

IF ChckHex < 10 THEN

    LET Units = ChckHex + "0"

ELSE

    LET Units = ChckHex + "7"

ENDIF

'SEROUT TX_Key,N2400_8,(Tens,Units,13,10)                'The CR,LF is for debugging

SEROUT TX_Key,N2400_8,(Tens,Units,13,10,4,4,4,4,4,4,4,4,4,4)    'PADDING ADDED 10/8/2018

RETURN