+++ /dev/null
-; wispcar.asm\r
-; David Rowe May 2008\r
-;\r
-; PIC12F510 Assembler program, MPLAB V8.10 IDE used to build.\r
-;\r
-; ********************************************************\r
-; * Wifi Station Power Controller And Reporter - WiSPCaR *\r
-; ********************************************************\r
-;\r
-;---------------------------------------------------------------------\r
-; Copyright (C) 2008 David Rowe\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License\r
-; along with this program; if not, write to the Free Software\r
-; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 \r
-; USA\r
-;---------------------------------------------------------------------\r
-;\r
-; FUNCTIONS\r
-; =========\r
-;\r
-; 1/ Monitor Voltage\r
-; 2/ Monitor Current\r
-; 3/ Watchdog timer\r
-; 4/ Sleep timer\r
-;\r
-;\r
-; PINOUT\r
-; ======\r
-; ____ ____\r
-; | \/ | \r
-; Vcc --| 1 8 |-- GND\r
-; | |\r
-; Spare I/O --| 2 7 |-- Vsense (in)\r
-; | |\r
-; RS232 Tx (out) --| 3 6 |-- PowerSwitch (out)\r
-; | |\r
-; RS232 Rx (in) --| 4 5 |-- Isense (in)\r
-; |__________|\r
-;\r
-;\r
-; Pin | Function | PIC Name\r
-; -----|-------------|---------\r
-; 2 | Spare I/O | GP5 \r
-; 3 | RS232 Tx | GP4\r
-; 4 | RS232 Rx | GP3\r
-; 5 | Isense | AN2\r
-; 6 | PowerSwitch | GP1\r
-; 7 | Vsense | AN0\r
-;\r
-; \r
-; PIC PROGRAMMING OPTIONS\r
-; =======================\r
-;\r
-; 8MHz clock, MCLRE=I/O, INTOSC\r
-;\r
-;\r
-; 4800 BAUD RS232 OUTPUT\r
-; ======================\r
-;\r
-; Vsense\r
-; | Isense\r
-; | | Last char received (ASCII)\r
-; | | | Last char received (decimal)\r
-; | | | | Watchdog timeout counter\r
-; | | | | | Watchdog fire counter\r
-; | | | | | | Sleep state machine state\r
-; | | | | | | | Sleep timeout counter\r
-; | | | | | | | | \r
-; 040 031 032 012 000 0 000 w---reason for last restart\r
-; b - Wispcar (re)booted \r
-; w - watchdog timer fired \r
-; s - we went to sleep\r
-;\r
-;\r
-; COMMANDS\r
-; ========\r
-;\r
-; 1/ Send a 'w' every WD_TIMEOUT seconds to prevent Watchdog timer\r
-; firing and cutting power.\r
-;\r
-; 2/ Send the string 'sleepxyz' to cut the power for xyz seconds,\r
-; where x,y and z are digits in the range 0-9. If any part of the\r
-; string is invalid it will be ignored. Wait 5 seconds and start\r
-; again.\r
-;\r
-; 3/ Wispcar cannot rx and tx RS232 at the same time. It is best to\r
-; wait until just after the output line is received by the host, then\r
-; send your command. If the command (such as sleep) gets messed up,\r
-; just wait 5 seconds and wispcar will reset it's internal state\r
-; machine. You can then try again.\r
-;\r
-; 4/ The final field is reset to a space when a 'w' is sent to\r
-; Wispcar. This field lets the host know just _why_ it was rebooted.\r
-\r
-#include <p12f510.inc>\r
-\r
-; VARIABLES ---------------------------------------------------------------------\r
-\r
-TEMP equ 0x10\r
-SERBUF equ 0x11 ; RS232 char to transmit\r
-count equ 0x12 ; temp reg used by "BIN2BCD" and "baud" routines\r
-BIN equ 0x13 \r
-huns equ 0x14\r
-tens equ 0x15\r
-ones equ 0x16\r
-thirty equ 0x17 ; constant set to (guess what) 30\r
-SERBUFI equ 0x18 ; last RS232 character we received\r
-wd_timeout equ 0x19 ; current watchdog timer value (in secs)\r
- ; when this hits zero we turn the power off\r
-wd_fire equ 0x1a ; count down timer when watchdog fires (in secs)\r
-restart_flag equ 0x1b ; tells host why we just restarted (WD or sleep)\r
-\r
-sleep_state equ 0x1c\r
-sleep_timeout equ 0x1d ; current value of sleep time out (in secs)\r
- ; measures time between rx-ed chars in\r
- ; s-l-e-e-p-x-y-z sequence.\r
- ; If this hits zero (like s-l- (BIG GAP))\r
- ; we assume sleep command\r
- ; was invalid and we reset the input state machine\r
-\r
- ; three digit sleep time (up to 999 secs)\r
- ; these count down to zero while we are sleeping\r
- ; when count down hits 0 power is switched back on\r
-\r
-sleeping equ 0x1e ; asserted if we are sleeping (power off)\r
-\r
-; following variables are in bank1, which makes life difficult....\r
-\r
-d1 equ 0x10\r
-d2 equ 0x11\r
-d3 equ 0x12\r
-\r
-x equ 0x13 ; sleep time (hundreds of secs)\r
-y equ 0x14 ; sleep time (tens of secs)\r
-z equ 0x15 ; sleep time (secs)\r
-\r
-; CONSTANTS ---------------------------------------------------------------------\r
-\r
-WD_TIMEOUT equ d'18' ; watchdog timeout in seconds\r
-WD_FIRE equ d'5' ; watchdog firing time in seconds\r
- ; how long power is cut off to host\r
-\r
-SLEEP_TIMEOUT equ d'5' ; timeout between rx-ed chars in sleep input\r
- ; sequence.\r
-\r
-; Values for restart_flag - tell host why we just cut power after we woke up\r
-\r
-BOOT_FLAG equ 'b' ; Wispcar just rebooted\r
-WD_FLAG equ 'w' ; Watchdog fired\r
-SLEEP_FLAG equ 's' ; We slept\r
-\r
-; START PROGRAM ----------------------------------------------------------------\r
-\r
-; set up osc cal (temp code just for experimenting)\r
-; TODO - FIX ME for general case\r
-\r
- movlw 16\r
- movwf OSCCAL\r
-\r
-; configure AN[1:0] as analog inputs\r
-\r
- movlw b'10110001'\r
- movwf ADCON0 \r
-\r
-; configure GP[3] as digital input (RS232 RX)\r
-; configure GP[4] as digital output (RS232 TX)\r
-; configure GP[1] as digital output (PowerSwitch)\r
-\r
-; disble the comparitor so we can use GP[1]\r
-\r
- bcf CM1CON0,3\r
-\r
- ; set up GPIO directions\r
-\r
- movlw b'00001101'\r
- tris GPIO\r
-\r
-; turn on PowerSwitch \r
-\r
- bsf GPIO,1 \r
-\r
-; set up a convenient constant\r
-\r
- movlw h'30'\r
- movwf thirty\r
-\r
-; init watchdog \r
-\r
- movlw WD_TIMEOUT\r
- movwf wd_timeout\r
- clrf wd_fire\r
-\r
-; init sleep\r
-\r
- clrf sleep_state\r
- clrf sleeping \r
- clrf sleep_timeout \r
- bsf FSR,5 ; x,y,z are in bank 1 (grumble)\r
- clrf x\r
- clrf y\r
- clrf z\r
- bcf FSR,5 ; x,y,z are in bank 1 (grumble)\r
-\r
-; init restart_flag\r
-\r
- movlw BOOT_FLAG\r
- movwf restart_flag\r
-\r
- goto main\r
-\r
-; START FUNCTIONS ------------------------------------------------------------\r
-\r
-; BIN2BCD\r
-;\r
-; Convert 8 bit value in BIN to a 3 digit decimal value.\r
-;\r
-; in.......: BIN\r
-; out......: huns, tens, ones\r
-; Reference: http://www.piclist.com/techref/microchip/math/radix/b2a-8b3d-ab.htm\r
-;\r
-; Uses temp reg 'count'\r
-\r
-; uses ADD-3 algorithm\r
-\r
-BIN2BCD\r
- movlw 8\r
- movwf count\r
- clrf huns\r
- clrf tens\r
- clrf ones\r
-BCDADD3\r
- movlw 5\r
- subwf huns, 0\r
- btfsc STATUS, C\r
- CALL ADD3HUNS\r
-\r
- movlw 5\r
- subwf tens, 0\r
- btfsc STATUS, C\r
- CALL ADD3TENS\r
-\r
- movlw 5\r
- subwf ones, 0\r
- btfsc STATUS, C\r
- CALL ADD3ONES\r
-\r
- decf count, 1\r
- bcf STATUS, C\r
- rlf BIN, 1\r
- rlf ones, 1\r
- btfsc ones,4 ; \r
- CALL CARRYONES\r
- rlf tens, 1\r
-\r
- btfsc tens,4 ; \r
- CALL CARRYTENS\r
- rlf huns,1\r
- bcf STATUS, C\r
-\r
- movf count, 0\r
- btfss STATUS, Z\r
- GOTO BCDADD3\r
-\r
- movf huns, 0 ; add ASCII Offset\r
- addwf thirty, 0\r
- movwf huns\r
-\r
- movf tens, 0 ; add ASCII Offset\r
- addwf thirty, 0\r
- movwf tens\r
-\r
- movf ones, 0 ; add ASCII Offset\r
- addwf thirty, 0\r
- movwf ones\r
-\r
- retlw 0\r
-\r
-ADD3HUNS\r
- movlw 3\r
- addwf huns,1\r
- retlw 0\r
-\r
-ADD3TENS\r
- movlw 3\r
- addwf tens,1\r
- retlw 0\r
-\r
-ADD3ONES\r
- movlw 3\r
- addwf ones,1\r
- retlw 0\r
-\r
-CARRYONES\r
- bcf ones, 4\r
- bsf STATUS, C\r
- retlw 0\r
-\r
-CARRYTENS\r
- bcf tens, 4\r
- bsf STATUS, C\r
- retlw 0 \r
-\r
-; INCH_N is from "PIC Software UART Routines"\r
-; John Massa, Datadog Systems (C) 2005\r
-\r
-; ********************************************************************\r
-; INCH_N\r
-; THIS ROUTINE INPUTS RS232 DATA USING AN INVERTER, LIKE THE MAX232.\r
-; THIS ROUTINE USES A 8-DATA BIT PER CHARACTER PROTOCOL\r
-; GPIO,0 = RX (MARK = 1, SPACE = 0).\r
-; TO RECIEVE A CHARACTER, CALL inch_n, THE RECEIVED CHARACTER IS PLACED\r
-; IN THE REG 'W' AND IN THE REG 'SERBUF'.\r
-; THE RECEIVED CHARACTER WILL ECHO IF 'RETLW 0' IS REM-ED OUT.\r
-; VARIABLES USED: REG 'TEMP' AND REG 'SERBUF' BOTH VARIABLES ARE\r
-; SHARED WITH THE 'outch_n' ROUTINE.\r
-; ROUTINES CALLED: 'half_baud'AND 'baud' TO SET THE BAUD-RATE\r
-; ********************************************************************\r
-\r
-; Modified by David Rowe May 2008 to combine a 1 second delay with\r
-; character reception.\r
-\r
-inch_n_delay\r
-\r
- ; clear previous rx char\r
-\r
- movlw ' '\r
- movwf SERBUFI\r
-\r
- ; init delay loop for 1999996 cycles\r
-\r
- bsf FSR,5 ; d1, d2, d3 in Bank 1 (groan)\r
- movlw 0x11\r
- movwf d1\r
- movlw 0x5D\r
- movwf d2\r
- movlw 0x05\r
- movwf d3\r
-\r
-wait_for_start\r
- bcf FSR,5 ; just in case goto below fires\r
- btfss GPIO,3 ; SKIP UNLESS WE GET A START BIT = 1 (A "MARK")\r
- goto start_serial ; start bit - process character\r
-\r
- ; process delay loop while we look for start bit\r
-\r
- bsf FSR,5\r
- decfsz d1, f\r
- goto $+2\r
- decfsz d2, f\r
- goto $+2\r
- decfsz d3, f\r
- goto wait_for_start\r
-\r
- ; delay finished\r
-\r
- bcf FSR,5 \r
- retlw 0\r
- \r
-start_serial\r
- bsf GPIO,5\r
- bcf GPIO,5\r
-\r
- movlw 8 ; START SERIAL INPUT SEQUENCE\r
- movwf TEMP ; COLLECT 8 DATA BITS\r
- clrf SERBUFI ; CLEAR SERIAL CHARACTER BUFFER\r
- call half_baud ; DELAY FOR ONE HALF BAUD TIME\r
- btfsc GPIO,3 ; FALL THRU IF START BIT STILL = 1 (A "MARK")\r
- goto wait_for_start ; ELSE IT WAS JUST A NOISE SPIKE, KEEP LOOKING\r
-inch_n1\r
- call baud ; DELAY ONE BAUD-BIT TIME ( = 1/BAUD-RATE)\r
- bcf STATUS,0 ; CLEAR THE CARRY BIT\r
- rrf SERBUFI,F ; ROTATE CRY -> MSB, ROTATE MSB RIGHT\r
- btfsc GPIO,3 ; IS IT A "MARK" ?\r
- bsf SERBUFI,7 ; ...SKIP IF YES, ELSE SET BIT TO LOGIC '1'\r
- decfsz TEMP,F ; EIGHT COUNTS YET?\r
- goto inch_n1 ; ...NO, GET ANOTHER BIT\r
- call baud ; DELAY FOR THE STOP BIT\r
- movf SERBUFI,W ; PUT THE RECEIVED CHARACTER IN REG 'W'\r
-\r
- ; process received character, this can be considered an "event\r
- ; handler" for rx-chars. We expect either a 'w' to reset the\r
- ; watchdog or a tightly defined sequence of sleep characters.\r
-\r
- movlw 'w' \r
- subwf SERBUFI,0 ; is it a 'w' for watchdog reset?\r
- btfss STATUS,Z ; skip if received char matches\r
- goto handle_sleepin ; only process sleep input if not a 'w'\r
-\r
- ; handle 'w' input \r
- \r
- ; Note if we are sleeping or WD is firing we will keep power\r
- ; off and receiving 'w' will have no effect. Unlikely unless\r
- ; device sending rx chars is powered indepednantly (ie during\r
- ; testing).\r
-\r
- movlw WD_TIMEOUT ; reset watchdog timer\r
- movwf wd_timeout\r
-\r
- movlw ' ' ; clear reboot flag\r
- movwf restart_flag\r
-\r
- clrf sleep_state ; reset sleep state machine for good measure\r
- clrf sleep_timeout ; just in case we get s-l-w-e-e-p or something\r
-\r
- goto wait_for_start\r
-\r
-handle_sleepin\r
- call sleep_input\r
- goto wait_for_start\r
-\r
-; OUTCH_N and BAUD are from "PIC Software UART Routines"\r
-; John Massa, Datadog Systems (C) 2005\r
-\r
-;*********************************************************************\r
-; OUTCH_N\r
-; THIS ROUTINE OUTPUTS RS232 DATA THROUGH AN INVERTER.\r
-; THIS ROUTINE USES AN 8-DATA BIT PER CHARACTER PROTOCOL.\r
-; TO PRINT A CHARACTER, LOAD BYTE INTO REG 'W' AND CALL outch_n.\r
-; GPIO,1 = TX (MARK = 1, SPACE = 0) ; USE INVERTER ON THE OUTPUT\r
-; VARIABLES USED: REG 'TEMP' AND SHARE REG 'SERBUF' WITH THE ROUTINE\r
-; 'inch_n'\r
-; CALLS THE ROUTINE 'baud' TO SET THE BAUD-RATE TIMING.\r
-;*********************************************************************\r
-\r
-outch_n ; THIS ROUTINE USES 8 DATA BITS\r
- movwf SERBUF ; SERBUF CONTAINS CHARACTER TO XMT\r
- movlw 8 ; THE CHARACTER HAS 8 BITS\r
- movwf TEMP\r
- bcf GPIO,4 ; SET START-BIT TO A "SPACE"\r
- call baud ; WAIT ONE BAUD TIME\r
-outch_n1\r
- rrf SERBUF,F ; ROTATE THE FIRST BIT INTO CARRY\r
- btfss STATUS,0 ; TEST THE CARRY BIT\r
- bcf GPIO,4 ; IF BIT IS 0 SET OUTPUT PIN TO A "0" (SPACE)\r
- btfsc STATUS,0 ; TEST THE CARRY BIT AGAIN\r
- bsf GPIO,4 ; IF BIT IS 1 SET OUTPUT PIN TO A "1" (MARK)\r
- call baud ; ONE BAUD-BIT DELAY\r
- decfsz TEMP,F ; IF COUNT IS ZERO THEN XMIT A STOP BIT\r
- goto outch_n1 ; ...ELSE XMIT NEXT BIT\r
- rrf SERBUF,F ; ROTATE CARRY, GET THE MSB BACK INTO BIT 7\r
- bsf GPIO,4 ; SET PIN TO A 1 (A "MARK") FOR THE STOP BIT\r
- call baud ; FIRST BAUD-BIT DELAY\r
- call baud ; SECOND BAUD-BIT DELAY\r
- retlw 0 ; RETURN WITH THE CHARACTER IN SERBUF\r
- \r
-; ********************************************************************\r
-; BAUD ROUTINE @ 4 MHz\r
-; BAUD RATE: CONSTANT:\r
-; 1200 Baud D'137'\r
-; 2400 Baud D'68'\r
-; 4800 Baud D'34'\r
-; 9600 Baud D'16'\r
-; 19200 Baud D'8'\r
-; 38400 Baud and up - use 'NOP' delays\r
-; VARIABLES USED: REG 'count'\r
-; ROUTINES CALLED: NONE\r
-; ********************************************************************\r
-\r
-baud ; AT 2400 BAUD THE PERIOD IS 416.6 US\r
- ; CLK = 4MHz\r
- movlw D'68' ; 1 US (BAUD RATE CONSTANT)\r
- movwf count ; 1 US\r
-baud1\r
- decfsz count,F ; 1 US (+ 1 US MORE IF SKIP)\r
- goto baud1 ; 2 US\r
- ; FALL THRU...AFTER 1+1+3x68+1 = 207 US\r
-half_baud\r
- movlw D'68' ; 1 US\r
- movwf count ; 1 US\r
-hbaud1\r
- decfsz count,F ; 1 US (+ 1 US MORE IF SKIP)\r
- goto hbaud1 ; 2 US\r
- retlw 0 ; ...AFTER 1+1+3x68+1 = 207 US (X2=414 US)\r
-\r
-; http://www.piclist.com/techref/piclist/codegen/delay.htm\r
-; Delay = 1 seconds\r
-; Clock frequency = 8 MHz\r
-\r
-; Actual delay = 1 seconds = 2000000 cycles\r
-; Error = 0 %\r
-\r
-delay\r
- ;1999996 cycles\r
- bsf FSR,5\r
- movlw 0x11\r
- movwf d1\r
- movlw 0x5D\r
- movwf d2\r
- movlw 0x05\r
- movwf d3\r
-Delay_0\r
- decfsz d1, f\r
- goto $+2\r
- decfsz d2, f\r
- goto $+2\r
- decfsz d3, f\r
- goto Delay_0\r
-\r
- ;4 cycles\r
- goto $+1\r
- goto $+1\r
-\r
- bcf FSR,5\r
- retlw 0\r
-\r
-; sleep input state machine\r
-; \r
-; we expect the chars s-l-e-e-p-x-y-z where xyz are digits\r
-; if wrong char received reset\r
-; if 5 sec timout between chars reset\r
-; if xyz are not digits reset\r
-\r
-sleep_input\r
-\r
- ; big case statement to work out what state we are in\r
-\r
- movlw 0\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 's'\r
- goto sleep_state_s\r
- movlw 1\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 'l'\r
- goto sleep_state_l\r
- movlw 2\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 'e1'\r
- goto sleep_state_e1\r
- movlw 3\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 'e2'\r
- goto sleep_state_e2\r
- movlw 4\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 'p'\r
- goto sleep_state_p\r
- movlw 5\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 'x'\r
- goto sleep_state_x\r
- movlw 6\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 'y'\r
- goto sleep_state_y\r
- movlw 7\r
- subwf sleep_state,0\r
- btfsc STATUS,Z ; Z set if in state 'z'\r
- goto sleep_state_z\r
-\r
- ; should never get here but just in case\r
-\r
- goto sleep_reset\r
-\r
- ; if we have rx-ed a 's' continue to next state\r
-sleep_state_s\r
- movlw 's'\r
- subwf SERBUFI,0\r
- btfss STATUS,Z ; Z set if we received a 's'\r
- goto sleep_reset\r
- goto sleep_cont\r
-\r
- ; if we have rx-ed a 'l' continue to next state\r
-sleep_state_l\r
- movlw 'l'\r
- subwf SERBUFI,0\r
- btfss STATUS,Z ; Z set if we received a 'l'\r
- goto sleep_reset\r
- goto sleep_cont\r
-\r
- ; if we have rx-ed a 'e' continue to next state\r
-sleep_state_e1\r
- movlw 'e'\r
- subwf SERBUFI,0\r
- btfss STATUS,Z ; Z set if we received a 'e'\r
- goto sleep_reset\r
- goto sleep_cont\r
-\r
- ; if we have rx-ed a 'e' continue to next state\r
-sleep_state_e2\r
- movlw 'e'\r
- subwf SERBUFI,0\r
- btfss STATUS,Z ; Z set if we received a 'e'\r
- goto sleep_reset\r
- goto sleep_cont\r
-\r
- ; if we have rx-ed a 'p' continue to next state\r
-sleep_state_p\r
- movlw 'p'\r
- subwf SERBUFI,0\r
- btfss STATUS,Z ; Z set if we received a 'p'\r
- goto sleep_reset\r
- goto sleep_cont\r
-\r
- ; if we have rx-ed a digit 0-9 continue to next state\r
-sleep_state_x\r
-\r
- ; check if >= '0'\r
- movlw '0'\r
- subwf SERBUFI,0\r
- btfss STATUS,C ; C set if valid\r
- goto sleep_reset\r
-\r
- ; check if x <= 9\r
- bsf FSR,5 ; x is in bank 1\r
- movwf x\r
- movlw d'10'\r
- subwf x,0\r
- bcf FSR,5\r
- btfsc STATUS,C ; C reset if valid\r
- goto sleep_reset\r
- goto sleep_cont\r
-\r
- ; if we have rx-ed a digit 0-9 continue to next state\r
-sleep_state_y\r
-\r
- ; check if >= '0'\r
- movlw '0'\r
- subwf SERBUFI,0\r
- btfss STATUS,C ; C set if valid\r
- goto sleep_reset\r
-\r
- ; check if y <= 9\r
- bsf FSR,5 ; y is in bank 1\r
- movwf y\r
- movlw d'10'\r
- subwf y,0\r
- bcf FSR,5\r
- btfsc STATUS,C ; C reset if valid\r
- goto sleep_reset\r
- goto sleep_cont\r
-\r
- ; if we have rx-ed a digit 0-9 continue to next state\r
-sleep_state_z\r
-\r
- ; check if >= '0'\r
- movlw '0'\r
- subwf SERBUFI,0\r
- btfss STATUS,C ; C set if valid\r
- goto sleep_reset\r
-\r
- ; check if z <= 9\r
- bsf FSR,5 ; z is in bank 1\r
- movwf z\r
- movlw d'10'\r
- subwf z,0\r
- bcf FSR,5\r
- btfsc STATUS,C ; C reset if valid\r
- goto sleep_reset\r
-\r
- ; OK we made it! Lets go to SLEEP, ZZZZZzzzzzzzzzz\r
-\r
- clrf sleep_state\r
- clrf sleep_timeout\r
- movlw 1\r
- movwf sleeping\r
- bcf GPIO,1 ; power switch off\r
-\r
- retlw 0\r
-\r
- ; we bombed out in rx-ing sleep string\r
-sleep_reset\r
- clrf sleep_state\r
- clrf sleep_timeout\r
- retlw 0\r
- \r
- ; increment to next state, and reset sleep timeout\r
-sleep_cont\r
- incf sleep_state,1\r
- movlw SLEEP_TIMEOUT\r
- movwf sleep_timeout\r
- retlw 0\r
-\r
-; START MAIN LOOP -----------------------------------------------\r
-\r
-main\r
-\r
- ; sample AN[0] (voltage)\r
-\r
- movlw b'10110001'\r
- movwf ADCON0 \r
- bsf ADCON0,1 ; start A/D conversion\r
-wait_adc_v\r
- btfsc ADCON0,1 ; skip if A/D conversion finished\r
- goto wait_adc_v\r
-\r
- ; print voltage to RS232\r
-\r
- movf ADRES, 0\r
- movwf BIN\r
- call BIN2BCD ; convert voltage to decimal ASCII \r
-\r
- movf huns, 0 \r
- call outch_n\r
- movf tens, 0\r
- call outch_n\r
- movf ones, 0\r
- call outch_n\r
-\r
- ; print space\r
-\r
- movlw ' '\r
- call outch_n\r
-\r
- ; sample AN[1] (current)\r
-\r
- movlw b'10111001'\r
- movwf ADCON0 \r
- bsf ADCON0,1 ; start A/D conversion\r
-wait_adc_i\r
- btfsc ADCON0,1 ; skip if A/D conversion finished\r
- goto wait_adc_i\r
-\r
- ; print current to RS232\r
-\r
- movf ADRES, 0\r
- movwf BIN\r
- call BIN2BCD ; convert current to decimal & ASCII \r
-\r
- movf huns, 0 \r
- call outch_n\r
- movf tens, 0\r
- call outch_n\r
- movf ones, 0\r
- call outch_n\r
-\r
- ; print rx char\r
-\r
- movlw ' '\r
- call outch_n\r
- movf SERBUFI, 0\r
- call outch_n\r
-\r
- ; print rx char in dec\r
-\r
- movlw ' '\r
- call outch_n\r
- movf SERBUFI, 0\r
- movwf BIN\r
- call BIN2BCD ; convert rx char to decimal & ASCII \r
-\r
- movf huns, 0 \r
- call outch_n\r
- movf tens, 0\r
- call outch_n\r
- movf ones, 0\r
- call outch_n\r
-\r
- ; print wd_timeout in dec\r
-\r
- movlw ' '\r
- call outch_n\r
- movf wd_timeout, 0\r
- movwf BIN\r
- call BIN2BCD \r
-\r
- movf huns, 0 \r
- call outch_n\r
- movf tens, 0\r
- call outch_n\r
- movf ones, 0\r
- call outch_n\r
-\r
- ; print wd_fire in dec\r
-\r
- movlw ' '\r
- call outch_n\r
- movf wd_fire, 0\r
- movwf BIN\r
- call BIN2BCD \r
-\r
- movf huns, 0 \r
- call outch_n\r
- movf tens, 0\r
- call outch_n\r
- movf ones, 0\r
- call outch_n\r
-\r
- ; print sleep_state \r
-\r
- movlw ' '\r
- call outch_n\r
- movlw '0' \r
- addwf sleep_state,0\r
- call outch_n\r
-\r
- ; print sleep timer in dec\r
-\r
- movlw ' '\r
- call outch_n\r
- movlw '0' ; print x\r
- bsf FSR,5\r
- addwf x,0\r
- bcf FSR,5\r
- call outch_n\r
- movlw '0' ; print y\r
- bsf FSR,5\r
- addwf y,0\r
- bcf FSR,5\r
- call outch_n\r
- movlw '0' ; print z\r
- bsf FSR,5\r
- addwf z,0\r
- bcf FSR,5\r
- call outch_n\r
-\r
- ; print restart_flag\r
-\r
- movlw ' '\r
- call outch_n\r
- movf restart_flag, 0\r
- call outch_n\r
-\r
- ; print CR-LF\r
-\r
- movlw '\r'\r
- call outch_n\r
- movlw '\n'\r
- call outch_n\r
-\r
- ; RS232 RX and 1 second delay\r
-\r
- call inch_n_delay \r
-\r
- ; has watchdog fired (wd_timeout == 0) ?\r
-\r
- movf wd_timeout,1\r
- btfsc STATUS,Z ; skip if not fired\r
- goto watchdog_firing ; Yes? Then goto watchdog firing code\r
- \r
- ; are we sleeping (sleeping == 1)?\r
-\r
- movf sleeping,1\r
- btfss STATUS,Z ; skip if not sleeping\r
- goto snooze ; Yes? Then goto sleeping code\r
-\r
- ; No? Then count down watchdog\r
-\r
- movlw 1\r
- subwf wd_timeout,1\r
-\r
- ; Has watchdog just fired (wd_timeout == 0)?\r
-\r
- btfss STATUS,Z ; skip if wd_countdown is zero\r
- goto dec_sleeptimeout ; No - continue\r
-\r
- ; Yes - start watchdog firing code\r
-\r
- bcf GPIO,1 ; PowerSwitch Off\r
- movlw WD_FIRE\r
- movwf wd_fire\r
- goto main\r
-\r
-dec_sleeptimeout\r
- ; has sleep state machine accepted a rx char?\r
-\r
- movf sleep_state,1\r
- btfsc STATUS,Z \r
- goto main ; No? Then continue processing\r
-\r
- decfsz sleep_timeout,1\r
- goto main\r
-\r
- ; sleep state machine timeout, reset state machine\r
- clrf sleep_state\r
- goto main\r
-\r
- ; watchdog firing code\r
-\r
-watchdog_firing\r
-\r
- movlw 1\r
- subwf wd_fire,1\r
-\r
- ; watchdog firing complete? (wd_fire == 0)?\r
-\r
- btfss STATUS,Z ; skip if wd_fire is zero\r
- goto main ; No - continue\r
-\r
- ; Yes - reset watchdog\r
-\r
- bsf GPIO,1 ; PowerSwitch On\r
- movlw WD_TIMEOUT\r
- movwf wd_timeout\r
-\r
- ; Indicate WD has fired since last 'w' sent by host. A rx of\r
- ; 'w' resets this flag.\r
- \r
- movlw WD_FLAG\r
- movwf restart_flag\r
- \r
- goto main\r
-\r
- ; sleeping code\r
- ; sleep for xyz seconds, need to count down in decimal\r
-snooze\r
- ; 3 digit decimal count down timer xyz, e.g. 999, 998,...001,000\r
- ; it's time's like these I wonder why I volunteered for this project!! :-)\r
- ; see countdown.c for C version of this algorithm\r
-\r
- bsf FSR,5\r
- movf z,1\r
- btfss STATUS,Z\r
- goto z_not_zero\r
- movf y,1\r
- btfss STATUS,Z\r
- goto y_not_zero\r
- movf x,1\r
- btfss STATUS,Z\r
- goto x_not_zero\r
- \r
- ; x=y=z=0 so we are finished\r
-\r
- bcf FSR,5\r
- goto sleep_finished\r
-\r
-z_not_zero\r
- decf z,1\r
- goto continue_sleep\r
-\r
-y_not_zero\r
- decf y,1\r
- movlw 9\r
- movwf z\r
- goto continue_sleep\r
-\r
-x_not_zero\r
- decf x,1\r
- movlw 9\r
- movwf y\r
- movwf z\r
- goto continue_sleep\r
-\r
- ; sleep finished\r
-\r
-sleep_finished\r
- bsf GPIO,1 ; PowerSwitch On\r
- movlw WD_TIMEOUT ; reset watchdog for good measure\r
- movwf wd_timeout\r
- clrf wd_fire\r
- clrf sleep_timeout ; clear sleep timeout counter\r
- clrf sleeping ; clear sleep flag\r
- \r
- ; Indicate we have just woken up from a sleep. A rx of 'w'\r
- ; resets this.\r
- \r
- movlw SLEEP_FLAG \r
- movwf restart_flag\r
- goto main\r
- \r
-continue_sleep\r
- bcf FSR,5\r
- goto main\r
- \r
-; END MAIN LOOP -----------------------------------------------\r
-\r
- end\r
-\r
-\r