Environmental Logger Controller Picaxe Basic Program

Declarations and Data

#rem

Controller.bas This program runs on the base unit of a system for displaying and logging environmental and security information.

This unit is the Environmental Display. It has the following connections:

*    A photocell, a temperature sensor, a pair of banana jacks no longer monitoring a gate via X-10

*    An output to the Logging Terminal, an input from the Adapter.

The Adapter has the following:

*    An RF receiver for messages from the Alpha LED Clock and the Solar Transmitter.

*    An interface for the receiver of the wireless-connected Driveway Patrol sensor pair

*    An interface to monitot the presence of line voltage (The system is run from a UPS)

*    An interface to measure DC voltage range 0 - 20

*    An interface to the Patio Sensor Box.

The Patio Sensor Box has the following"

*    Internal temperature and humidity sensors.

*    External connections for the Patio and Back photocells and the spa heater gas valve.

The Alpha LED Clock transmits date and tie values once a minute.

The Solar Transmitter transmits the following once per minute:

*    Thmperature and Humidity.

*    Solar panel charging current and battery voltage.

Program via the pigtail to the logger using Editor V5.

John Saunders 8/16/2016 RF gate switch 3/11/17 added checksum calculation

1/11/2019 Gate sense correction. 2021 send out keycode and comma

#endrem

#Picaxe 40X1

#rem

Controls:

1. The toggle switch at the rear controls power to the Controller, Adapter, Logging Terminal, Driveway Patrol receiver and the Sensor Box,

2. The rotary switch has 12 mechanical positions, but only the first 7 from CCW are decoded and can be used by the program.

   The first 5, labelled O,A B,C D affect only the items displayed, not the program operation.

   The next P, allows parameter setting.

   Position r is hard-wired to the 40X1 reset pin. Do not use any other positions.

3. The ENT and CLR buttons control backlighting in switch positions O - D. 

   In switch position P both advance the selected parameter to , the difference is that SET stores the parameter value in EEPROM before advancing.

4. The encoder in switch positions O - D turns pn backlighting.

   In switch position P it adjusts the selected parameter.


Timing:

* The main loop executes continuously about 40 times a secomd.

* It generates 14 phases, 13 of which are devoted to specific inputs.

* The 14th. generates a. Event message when one has ocurred.

* The controls are checked each loop. The 1/2 Hz clock is polled each loop to generate a separate seconds timebase.

* This is used to once a minute to send the Weather Message.

* The internal temperature sensor is also read only once a minute because it takes 700 ms.

* Incoming RF messages are stored temporally in the interrupt proflage generated.

* At the next main loop the message is copied to its specific location.

* The daylight flag and midnight operation are message-dependent and so are handles when the message arrives.

* Switch position 5 (P-setting) is handled every loop.


Memory Usage:

This program buffers analog values in Scratchpad; isolating acquisition from display and logging.

The measurements are stored in the scratchpad exaclly as they will be output to the Logging Terminal.

Each item is in ASCII and has a specific address in Scratchpad as follows:

SOLAR 85 - 99: Temperature,Humidity,Milliamperes,Voltage (each 3 characters plus a comma)

PATIO BOX: 101 - 112: Temperature, 101 - 103: Humidity, Patio Photocell, Back Photocell  (each 2)

INTERNAL: 114 - 127:Temperature, 114 - 116: Photocell, 118 - 119: External Voltage 121 - 125


The RAM is also used with binary values. It is allocated as follows:

80,81: word Patio Temperature accumulation, 82,83 word Ext BNC accumulation

84 byte Patio light value, 86 byte Back light value

90 Parameter while setting


Acquisition differs depending on the source:

*    The RF inputs need no engineering conversion. They are input in the interrupt procedure into scratchpad

    which is used brcause because it supports the @ptrinc designation. The data is transferred into scratchpad 

    just as it comes out of the interrupt sub-program.

*    The hard-wired analogs are sampled and accumulated multiple times in scratchpad,

    both to smooth noise and for engineering unit conversion.This is periodic.

*    The local tmperature sensor is digital. Because it is very slow, it is input infrequently.


Displaying is split into pages. The items in the selected page are updated from scratchpad at the end of each acquisition cycle.

Logging is periodic at a selected interval in seconds. It does not include a time-tag - this is added in the Logging Terminal.

The discretes are checked frequently and displayed and logged at each change in a different file.

#endrem


rem Bit variables:


rem Specific flags

symbol tMesgFlag        = bit0    'A time message has been received

symbol sMesgFlag        = bit1    'A solar message has been received

symbol BacklightFlag    = bit2    'Backlight is on

symbol Pending        = bit3    'Backlight has been on for about a minute

symbol Phase        = bit4    'Flag indicates that clock interrupt has been detected

symbol Daylight        = bit5    'One if the solar cells are producing

symbol Midnight        = bit6    'One if the hour MSB is not 0

symbol TxFlag           = bit7    'A transmission is in process


rem Event Flags, also b1 A 1 in each is the asserted state, not necessarily the voltage level

symbol BackFlag        = bit8

symbol PatioFlag        = bit9

symbol GateFlag        = bit10    'From RF input, 1 = open, 0 = closed

symbol LineFlag        = bit11

symbol IRFlag        = bit12

symbol SpaFlag        = bit13

symbol BananaFlag        = bit14    'Used formally for the gate, now spare

symbol GateEvent        = bit15


rem word variables - uses bytes 27 down

symbol Remainder        = w13        'Output of an ADC read

symbol DECData        = w12        'Numeric value to be displayed


rem byte variables - uses bytes 2 and up

rem variables with specific meanings

symbol Seconds        = b2        'Incremented by the clock, not used except for output and DS18B20

symbol SwPos        = b3        'Position of rotary switch: 0..6

symbol OldSwPos        = b4        'To detect a change

symbol LoopCount        = b5        'The main loop is cyclic on this

symbol OldEvents        = b6        'To detect a change

symbol SettingIndex    = b7


rem pointer variables

symbol DataAddr        = b9        'Usually used to point to an EEPROM entry

symbol ScreenLoc        = b10        'A location on the screen or a command

symbol SPAddr        = b11        'Used to point to an address in scratchpad memory


rem Used only in interrupt

symbol I_Char        = b12

symbol Key_Code        = b13

symbol ChckHex        = b14

symbol I_Tmp        = b15

symbol ChckSum        = b16


rem Other variables

symbol DispMode        = b17        'Controls displaying a field. Bits 0,1:length 1-4, bits 2,3 Decimal pos from left

symbol Index        = b18        'Multi-use variable

symbol Iter            = b19        'Multi-use variable

symbol CharData        = b20        'Byte variable 

symbol Temp            = b21        'General use


rem EEPROM

rem Magic numbers

DATA 0,($30,$30,$30,$38,$0C,$01,$06,$14,$80)    'Display Init strings

rem Patio floodlight is 65 when on, Back is 85

DATA 9,(40,50,20)                        'Selectable: Patio min, Back min, hysteresis

rem Fixed strings for display formatting

rem Data values

DATA 12,("PATIO",0)

DATA 18,("BACK",0)

DATA 23,("SOLAR",0)

DATA 29,("GARAGE",0)

DATA 36,("EXT BNC",0)

rem Events

DATA 44,("IR",0)

DATA 47,("SPA",0)

DATA 51,("GATE",0)

DATA 56,("LINE",0)

rem page Headings

DATA 61,("SETTING",0)

DATA 69,("HUMIDITY",0)

DATA 78,("TEMPERATURE",0)

DATA 90,("LIGHT",0)

DATA 96,("VOLTS",0)

rem Units

DATA 102,(":",0)

DATA 104,($DF,"F",0)

DATA 107,("%",0)

DATA 109,("MA",0)

DATA 112,("V",0)

rem String locations and addresses First=location, second = EEPROM address

DATA 114,($8D,102,0)                                            'Page0="O" Colon

DATA 117,($82,78,$C0,23,$C9,104,$94,12,$9D,104,$D4,29,$DE,104,0)                'Page1="A' temperatures

DATA 132,($84,69,$C0,23,$C9,107,$94,12,$9C,107,0)                        'Page2="B" humidity

DATA 143,($86,90,$C0,12,$C8,107,$CB,18,$D2,107,$94,29,$9D,107,$D4,23,$DD,109,0)    'Page3="C" Light

DATA 162,($88,96,$C0,23,$C9,112,$94,36,$A1,112,0)                        'Page4="D" Volts

DATA 173,("DELTA=",0)

                                    

rem Field locations and scratchpad addresses

DATA 180,($C6,85,$9A,101,$DB,114,0)                    'Page1="A' temperatures

DATA 187,($C6,89,$9A,105,0)                         'page2="B" humidity

DATA 192,($C6,108,$D0,111,$9B,118,$DA,93,0)            'Page3="C" Light

DATA 201,($C6,97,$9C,121,0)                         'Page4="D" Volts

rem Field locations and EEPROM addresses

DATA 206,($C9,18,$C0,12,$94,51,$9D,56,$D4,44,$DD,47,0)     'Page0="O" Events

DATA 219,($86,61,$C0,12,$94,18,$D4,173,0)                 'Page5="P" Setting

DATA 228,("     ",0)

Init and Looping

Init:

SetFREQ m8

LOW portc 7            'LCD Enable

HIGH Portc 5        'backlight on

rem Initialize Display

FOR DataAddr = 0 TO 8

    READ DataAddr,ScreenLoc

    GOSUB DispCmd

    PAUSE 100

NEXT

GOSUB ClearScreen

rem Prepare the scratchpad for transmission

LET CharData = "0"

FOR SPAddr = 41 TO 67

    PUT SPAddr, CharData

NEXT

rem Put commas into the scratchpad for recording

LET CharData = ","

FOR Iter = 0 TO 7

    LOOKUP Iter,(100,104,107,110,113,117,120,126),SPAddr

    PUT SPAddr, CharData

NEXT

LET Seconds = 0

LET OldSwPos = $FF

LET SettingIndex = 0

LET GateFlag = 0

LET GateEvent = 0

READ 9, CharData

POKE 90,CharData

PUT 33,"1"

rem Set initial interrupt on either RF or encoder

SETINT OR  %01000001,%01000001            


looping:                        'Main loop is asynchronous, 320 ms


IF tMesgFlag = 1 THEN                'A message has been received from the Green LED Clock.                

    IF SwPos = 0 THEN

        LET ScreenLoc = $82        'It's not stored, only displated in switch position O

        GOSUB DispCmd

        FOR SPAddr = 2 TO 12 

            LET Index = 8

            LOOKDOWN SPAddr,(4,7,10),Index    'Locations of commas to be converted

            IF Index < 8 THEN

                LOOKUP Index,("/"," ",":"),CharData

            ELSE

                GET SPAddr,CharData

            ENDIF

            GOSUB DispChar 

        NEXT

    ENDIF

    GET 8, Index                'The hour MS digit to determine midnight

    IF Index = "0" and Midnight = 1 THEN

        GOSUB TxHeading

    ENDIF

    IF Index = "0" THEN 

        LET Midnight = 0

    ELSE

        LET Midnight = 1

    ENDIF

    LET tMesgFlag = 0

ENDIF    

IF sMesgFlag = 1 THEN                'Transfer the Solar Transmitter message to the scratchpad at 25

    FOR SPAddr = 2 TO 16            'First character is 2 of the incoming message

        GET SPAddr,CharData

        LET Index = SPAddr + 83

        LET CharData = CharData & $7F

        PUT Index,CharData

    NEXT

    LET Daylight = 0                'Used in getting light events

    FOR SPAddr = 93 TO 95            'Solar panel charging current

        GET SPAddr, Chardata

        IF CharData > "0" THEN

            LET Daylight = 1

        ENDIF

    NEXT

    LET sMesgFlag = 0    

ENDIF

IF LoopCount >= 13 THEN

    LET LoopCount = 0

ELSE

    INC LoopCount

ENDIF

GOSUB ReadSwitch

GOSUB ReadAnalogs

GOSUB ReadDigitals

GOSUB BacklightControl


IF Pin4 <> Phase THEN                'A clock pulse has been detected, each second

    IF Seconds >= 59 THEN

        LET Seconds = 0

    ELSE

        INC Seconds

    ENDIF

rem Display the seconds in switch position 0

    IF SwPos = 0 THEN

        LET ScreenLoc = $8E        'After the date and time

        GOSUB DispCmd

        LET CharData = Seconds/10 + "0"

        GOSUB DispChar

        LET CharData = Seconds//10 + "0"

        GOSUB DispChar

    ENDIF

    IF Seconds = 41 THEN

        GOSUB TxWeather

    ENDIF

    IF Seconds = 5 THEN

        READTEMP12 1,Remainder

        PAUSE 10

        LET DecData = 9*Remainder/80 + 32         'Convert to Farenheit

        LET DispMode = 2

        LET SPAddr = 114

        GOSUB StoreAnalog

    ENDIF

    LET Phase = Pin4

ENDIF


rem Display the selected parameter and blank the other in switch position 5 every loop

IF SwPos = 5 THEN

    FOR Iter = 0 TO 2

        IF Iter <> SettingIndex THEN            'Blank it out

            LET Index = 2 * Iter + 221        'Using indirect addressing

            READ Index,ScreenLoc

            LET ScreenLoc = ScreenLoc + 6

            GOSUB DispCmd

            LET ChaRData = " "

            GOSUB DispChar

            LET ChaRData = " "

            GOSUB DispChar

        ENDIF

    NEXT

    LET Index = 2 * SettingIndex + 221        'Using indirect addressing

    READ Index, ScreenLoc

    LET ScreenLoc = ScreenLoc + 6

    GOSUB DispCmd

    PEEK 90,Temp                    'Volatile: adjusted in interrupt by the encoder

    LET CharData = Temp/10 + "0"

    GOSUB DispChar

    LET CharData = Temp//10 + "0"

    GOSUB DispChar

ENDIF


GOTO looping

Sub-programs

#rem Classification of Subprograms:

Group A: Modify no variables

Group B. Modify only Chardata and Index

Group C: Modify only CharData & Iter & temp

#endrem



rem Group C


ReadAnalogs:

SELECT LoopCount

    CASE 0

        GOSUB DispData                    'Depends on page

    CASE 1

        READADC10 6,DecData                'Patio Temperature, 1st of 3

        READADC10 7,Remainder                'Ground reference

        LET DecData = DecData - Remainder

        POKE 80, WORD DecData

    CASE 2 

        READADC10 3,DecData                'Ext BNC, 1st of 2

        POKE 82, WORD DecData

    CASE 3 

        READADC10    5,DecData                'Garage Photocell

        LET DecData = DecData / 10

        LET DispMode = 1

        LET SPAddr = 118

        GOSUB StoreAnalog

    CASE 4 

        READADC10 2,DecData                'Patio Humidity

        READADC10 7,Remainder                'Ground reference

        LET DecData = DecData - Remainder        LET DecData = DecData / 10

        LET DispMode = 1

        LET SPAddr = 105

        GOSUB StoreAnalog

    CASE 5

        READADC10 6,DecData                'Patio Temperature, 2nd of 3

        READADC10 7,Remainder                'Ground reference

        LET DecData = DecData - Remainder

        PEEK 80, WORD Remainder

        LET DecData = Decdata + Remainder

        POKE 80, DecData

    CASE 6

        READADC10 0,DecData                'Patio Photocell

    '    READADC10 7,Remainder                'Ground reference

    '    LET DecData = DecData - Remainder        'Commented out-was going negative on interference

        LET DecData = DecData / 10

        POKE 84,DecData                    'Save for flag determination

        LET DispMode = 1

        LET SPAddr = 108

        GOSUB StoreAnalog

    CASE 7

        READADC10 1,DecData                'Back Photocell

    '    READADC10 7,Remainder                'Ground reference

    '    LET DecData = DecData - Remainder        'Commented out-was going negative

        LET DecData = DecData / 10

        POKE 86,DecData                    'Save for flag determination

        LET DispMode = 1

        LET SPAddr = 111

        GOSUB StoreAnalog

    CASE 8

        PEEK 82, WORD Remainder

        READADC10 3,DecData                'Ext BNC #2 0f 2

        LET DecData = Decdata + Remainder            

        LET DispMode = 11

        LET SPAddr = 121

        GOSUB StoreAnalog

    CASE 9

        READADC10 6,DecData                'Patio Temperature, 3rd of 3

        READADC10 7,Remainder                'Ground reference

        LET DecData = DecData - Remainder

        PEEK 80, WORD Remainder

        LET DecData = Decdata + Remainder

        LET DecData = DecData /20 + 12        '1 count per deg F

        LET DispMode = 2

        LET SPAddr = 101

        GOSUB StoreAnalog

ENDSELECT

RETURN


ReadDigitals:

SELECT LOOPCOUNT

    CASE 10

        PEEK 84,Decdata                'Patio Analog photocell volts

        READ 9,CharData                'Less than the value when the floodlights are on

        READ 11,Temp                'This will stabilize the operation

        LET Temp = CharData + Temp        

        IF DecData > Temp THEN

            LET PatioFlag = 1

        ENDIF

        IF DecData < CharData OR Daylight = 1 THEN

            LET PatioFlag = 0        

        ENDIF

    CASE 11

        PEEK 86,Decdata                'Back Analog photocell volts

        READ 10,CharData

        READ 11,Temp

        LET Temp = CharData + Temp

        IF DecData > Temp THEN

            LET BackFlag = 1

        ENDIF

        IF DecData < CharData OR Daylight = 1 THEN

            LET BackFlag = 0

        ENDIF

    CASE 12

        IF Portc pin4 = 0 THEN            'Get the events to the scratchpad for both messages

            LET BananaFlag = 0

        ELSE

            LET BananaFlag = 1

        ENDIF

        IF Portc pin0 = 0 THEN

            LET LineFlag = 1

        ELSE

            LET LineFlag = 0

        ENDIF

        LOW 7

        LET SpaFlag = Pin3

        IF Portc pin2 = 0 THEN

            LET IRFlag = 1

        ELSE 

            LET IRFlag = 0

        ENDIF

    CASE 13                

        IF OldEvents <> b1 THEN                'Transmit an event message

            GOSUB TxEvent

        ENDIF

        LET OldEvents = b1 

ENDSELECT

RETURN


ReadSwitch:                 

HIGH 7                        'B selection: Clear PB, Set PB, Mode 0

LET Iter    = Pin7

LOW 7                            'A selection: pin 4,Mode1,Mode2

LET CharData = 2 * Pin2 + Iter

LET SwPos = 4 * Pin7 + CharData

IF OldSwPos <> SwPos THEN            'Display the headings. This uses indirect addressing

    GOSUB ClearScreen

    LOOKUP SwPos,(114,117,132,143,162,219,219),Iter    'Location of the first string location

    DO

        READ Iter,ScreenLoc

        IF ScreenLoc = 0 THEN EXIT

        INC Iter

        READ Iter,DataAddr

        GOSUB DispFixed

        INC Iter

    LOOP     

    HIGH Portc 5    

    LET BacklightFlag = 1

ENDIF

LET OldSwPos  = SwPos

RETURN


DispData:                            '68 ms

IF SwPos < 5 THEN

    LOOKUP SwPos,(206,180,187,192,201),Iter    'Location of the first field location

    LET Temp = 1

    DO

        READ Iter,ScreenLoc

        IF ScreenLoc = 0 THEN EXIT

        INC Iter

        IF SwPos = 0 THEN                'Display the string only if the flag is 1

            LET CharData = b1 & Temp    'Read the event flage in sequence LS first

            IF Chardata > 0 THEN        'Flag is set

                READ Iter,DataAddr    'Correspomding name of event

            ELSE

                LET DataAddr = 228    'Blank string

            ENDIF

            GOSUB DispFixed

            LET Temp = 2 * Temp

        ELSE

            READ Iter,SPAddr

            GOSUB DispField

        ENDIF

        INC Iter

    LOOP         

ENDIF

RETURN


rem Group B


rem Did not wish to use BINTOASCII - slow and needs more variables

StoreAnalog:         'Stores DecData in the scratchpad starting at SPAddr

BRANCH DispMode,(OneDigit,TwoDigit,ThreeDigit)

rem 4 digit by default

LET Chardata = DecData / 1000 + "0" MAX "9"

PUT SPAddr,Chardata

INC SPAddr

LET Remainder = DecData // 1000

LET DecData = Remainder

ThreeDigit:

LET Chardata = DecData / 100 + "0"

PUT SPAddr,Chardata

INC SPAddr

LET Remainder = DecData // 100

LET DecData = Remainder

IF DispMode = %00001011 OR DispMode = %00001010 THEN    '11 or 10

    LET CharData = "."

    PUT SPAddr,Chardata

    INC SPAddr

ENDIF

TwoDigit:

LET Chardata = DecData / 10 + "0" MAX "9"

PUT SPAddr,Chardata

INC SPAddr

LET Remainder = DecData // 10

LET DecData = Remainder

OneDigit:

LET Chardata = DECData // 10 + "0"  MAX "9"

PUT SPAddr,Chardata

IF SPAddr < 127 THEN

    INC SPAddr

    LET Chardata = ","

    PUT SPAddr,Chardata

ENDIF

RETURN


ClearScreen:            'There is a Hitachi command but I did not want to use it

LET ScreenLoc = $80

GOSUB DispCmd

LET Chardata = " "

FOR Iter = 0 TO 39

    GOSUB DispChar    

NEXT Iter

LET ScreenLoc = $C0

GOSUB DispCmd

LET Chardata = " "

FOR Iter = 0 TO 39

    GOSUB DispChar    

NEXT Iter

RETURN


TxDigital:                'Spa,IR,Line,Gate,Patio,Back

LET Temp = 32            'Store MS first $20 bit 5= 13 - 8 (spa Flag)

FOR Iter = 0 TO 5

    LET CharData = b1 & Temp

    IF CharData > 0 THEN

        LOOKUP Iter,("S","I","L","G","P","B"),CharData

    ELSE

        LET Chardata = "0"

    ENDIF

    LET Temp = Temp / 2

    SERTXD (",",CharData)

NEXT Iter

RETURN


DispFixed:                'Displays  the zero-terminated string in EEPROM at DataAddr at ScreenLoc

GOSUB DispCmd

LET Index = DataAddr

DO 

    Read Index,CharData

    INC Index

    IF CharData > $1F THEN 

        GOSUB DispChar 

    ENDIF

LOOP WHILE CharData > $1F

IF SwPos > 0 AND DataAddr < 44 THEN

    LET CharData = "="

    GOSUB DispChar

ENDIF

RETURN


DispField:                'Displays the field at SPAddr at CharData until a ",".

GOSUB DispCmd

LET Index = SPAddr

DO 

    GET Index,CharData

    INC Index

    IF CharData > "," THEN 

        GOSUB DispChar 

    ENDIF

LOOP WHILE CharData > ","

RETURN


rem Group A


BacklightControl:

HIGH 7

IF Pin2 = 0 THEN                    'ENT pushbutton Turn on backlight

    IF SwPos < 5 THEN

        HIGH Portc 5

        LET BacklightFlag = 1

    ELSE                        'Cycle through the parameters

        PEEK 90, CharData

        LET Index = 9 + SettingIndex

        WRITE Index,CharData

        IF SettingIndex >= 2 THEN

            LET SettingIndex = 0

        ELSE

            INC SettingIndex

        ENDIF

        LET Index = 9 + SettingIndex

        READ Index,CharData

        POKE 90, CharData

        DO

            PAUSE 1

        LOOP UNTIL Pin2 = 1

    ENDIF

ENDIF

IF Pin3 = 0 THEN                    'CLR Poshbutton Turn off backlight

    IF SwPos < 5 THEN

        LOW Portc 5

        LET BacklightFlag = 0

        LET Pending = 0

    ELSE

        IF SettingIndex >= 2 THEN

            LET SettingIndex = 0

        ELSE

            INC SettingIndex

        ENDIF

        LET Index = 9 + SettingIndex

        READ Index,CharData

        POKE 90, CharData

        DO

            PAUSE 1

        LOOP UNTIL Pin3 = 1

    ENDIF

ENDIF

rem The backlight turns off in less than 2 minutes

IF Seconds < 5 AND BacklightFlag = 1 THEN

    LET Pending = 1

ENDIF

IF Seconds > 50 AND Pending = 1 AND SwPos < 5 THEN

    LOW Portc 5

    LET Pending = 0

    LET BacklightFlag = 0

ENDIF

RETURN


DispCmd:                      'Puts a command into the display

LOW portc 6             'instruction function is low,

LET outpins = ScreenLoc

IF ScreenLoc < $80 THEN            'It seems necessary to make sure bit 7 is set correctly

    LOW 7

ELSE

    HIGH 7

ENDIF

HIGH portc 7            'clocks the instruction and the function into the display

LOW portc 7

RETURN


DispChar:                'writes CharData to the display

HIGH portc 6              'data function is high

LET outpins = CharData

HIGH portc 7             'clocks the character into the display

LOW portc 7    

RETURN


TxWeather:                '53 chars + w, and 10, 13

LET TxFlag = 1

LET GateFlag = GateEvent

LET ptr = 85

SETFREQ K500

SERTXD (0)                'Makes a positive pulse

SETFREQ M8

PAUSE 12

rem scratchpad locations

rem                 85     86      87      88      89      90      91      92      93      94      95      96      97      98       99     100     101     102     103    104     105     106     107     108      109    110      111     112     113     114     115    116     117     118     119     120     121     122     123     124    125           

SERTXD ("n",",",@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptr)

GOSUB TxDigital

SERTXD (13,10)

LET TxFlag = 0

LET GateFlag = 0

LET GateEvent = 0

RETURN



TxEvent:

LET TxFlag = 1

SETFREQ K500

SERTXD (0)                'Makes a positive pulse

SETFREQ M8

PAUSE 12

SERTXD ("o")

GOSUB TxDigital

SERTXD (",")

rem Add the string for the changed event

LET Temp = OldEvents ^ b1            'Will have a 1 bit for each changed event

LET Index = NCD Temp - 1            'Identifies the changed event (0 = patio flag)

LET DataAddr = 47

LOOKUP Index, (18,12,51,56,44,47),DataAddr

LET Index = DataAddr

DO 

    READ Index,CharData

    IF CharData > $1F THEN 

        SERTXD (CharData)

    ENDIF

    INC Index 

LOOP WHILE CharData > $1F

SERTXD (13,10)

LET TxFlag = 0

RETURN


TxHeading:

LET TxFlag = 1

SETFREQ K500

SERTXD (0)                'Makes a positive pulse

SETFREQ M8

PAUSE 12

SERTXD ("n,STemp,SHum,MA,Batt,PTemp,PHum,PLight,BLight,GTemp,GLight,EXT,Spa,IR,Line,Gate,PF,BF",13,10)

LET TxFlag = 0

RETURN


interrupt:

IF Pin0 = 1 THEN                'Receiver interrupt, from hardware integrate and dump circuit

    LET I_Tmp = 0

    DO WHILE Pin0 = 1    AND I_Tmp < 28        'Noise interrupts are nearly always shorter

        LET I_Tmp = I_Tmp + 1    'Twice as fast as INC Usual count is 15

    LOOP

rem Avoid messing up ptr and bad copy if messages are too close together

    IF I_Tmp < 8 OR tMesgFlag = 1 OR sMesgFlag = 1 OR TxFlag = 1 THEN EndInterrupt    'Minimises the time to recover from a noise interrupt

    LET ptr=0

    PUT 0,"z"

    PUT 2,0

rem                                               0      1        2       3      4        5       6       7       8       9       10      11     12       13     14       15      16     17       18     19       20      21     22       23     24      25      26      27       28     29       30      31      32      33      34     35      36      37      38       39     40       41      42      43      44      45      46      47      48      49      50      51      52      53       54      55     56      57      58      59      60      61      62      63      64     65       66      67      68      69      70      71      72      73      74     75       76      77      78      79      80      81      82    83        84      85      86      

    SERIN [40,timeout],5,N2400_8,("14L1776"),@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc

    GOTO EndInterrupt            'A long message from an intefering device

    timeout:

    GET 0,Key_Code

    IF Key_Code = "z" THEN 

        LET ptr = 0

        GOTO EndInterrupt

    ENDIF

    GET 2,I_tmp    

    IF I_tmp < 61 OR I_tmp > 110 THEN NoChecksum    'Can be a message, get the checksum

    LET ChckSum = 0

    LET ChckHex = I_tmp - 57                'Address of the last message byte 

    FOR I_tmp = 4 TO ChckHex

        LET ptr = I_tmp

        LET I_Char = @ptr    

        LET ChckSum = ChckSum + I_Char

        LET ptr = I_tmp - 2                'Move message back for compatinility

        LET @ptr = I_Char     

    NEXT

    LET I_tmp = ChckHex - 1                    

    PUT I_tmp,13,10                        'Replace comma with newline

    LET ptr = ChckHex + 2                    'Address of first checksun byte

    LET ChckHex = ChckSum / 16

    IF ChckHex  < 10 THEN

        LET ChckHex = ChckHex + "0"

    ELSE

        LET ChckHex = ChckHex + "7"

    ENDIF

    LET I_Char = @ptrinc                    'first Checksum character

    IF ChckHex <> I_Char THEN EndInterrupt

    LET ChckHex = ChckSum & $F

    IF ChckHex  < 10 THEN

        LET ChckHex = Chckhex + "0"

    ELSE

        LET ChckHex = ChckHex + "7"

    ENDIF

    LET I_Char = @ptr

    IF ChckHex <> I_Char THEN EndInterrupt

    LET ptr = 0                        'To enable recording on different filenames 3/30/2021

NoChecksum:

    GET 0,Key_Code

    SELECT Key_Code

    CASE "t" 

        LET tMesgFlag = 1

        IF Seconds > 1 AND Seconds < 58 THEN        'Synchronize

            LET Seconds = 0

        ENDIF

    CASE "s"

        LET sMesgFlag = 1

    CASE "Q" 

        LET GateFlag = 1

        LET GateEvent = 1

    CASE "B"

        LET GateFlag = 0

    ELSE                         ;Re-transmit the message

        SETFREQ K500

        SERTXD (0)                'Makes a positive pulse

        SETFREQ M8

        PAUSE 12

        DO

            LET I_tmp = @ptrinc

            LET I_tmp = I_tmp & $7F

            SERTXD(I_tmp)

        LOOP WHILE I_tmp > 10

    ENDSELECT

    LET Key_Code = "z"

ELSE                                        'An encoder 1ms interupt

    IF SwPos = 5 THEN

        PEEK 90,I_tmp

        IF Portc Pin3 = 0 THEN    'Direction

            INC I_tmp

        ELSE

            DEC I_tmp

        ENDIF

        POKE 90,I_tmp

    ELSE

        HIGH Portc 5        'Turn on backlight

        LET BacklightFlag = 1

    ENDIF

ENDIF

EndInterrupt:

SETINT OR %01000001,%01000001    'Re-enable the encoder and receiver interrupts again

RETURN