;; ************************************************************************* */ ;; */ ;; power.a51: Power Supply Monitor assembly code */ ;; */ ;; Copyright (C) 2010 Len Bayles, TMD Innovations */ ;; */ ;; 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 58 and 65 -> 90 ; ASCII 0 -> : A -> Z CJNE A, #47, BTEST1 ; A == 47 RET BTEST1: JNC BTEST2 ; A < 47 RET BTEST2: CJNE A, #59, BTEST3 ; A == 59 RET BTEST3: JC BSTORE ; A < 59 CJNE A, #64, BTEST4 ; A == 64 RET BTEST4: JNC BTEST5 ; A < 64 RET BTEST5: CJNE A, #91, BTEST6 ; A == 91 RET BTEST6: JC BSTORE ; A < 91 RET BSTORE: MOV @R0,A ; Put Char in Buffer INC R0 ; Increment buffer pointer INC R7 ; Increment buffer length BDONE: ACALL SEND ; Echo character BFDONE: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; DO_CMD - Process command ; ; D:XX - Dispaly ADC values every XX seconds ; Q ; S:XX - Shutdown in XX seconds ; TCXX - Set LED channel threshholds - C = 0/1 - XX = value ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DO_CMD: MOV R0, #40H ; Set pointer to front of buffer DISPLAY: CJNE @R0, #68, QUERY ; Dispaly Command - D:XX where XX = seconds INC R0 ; Dont care about the colon INC R0 ; Point to High Ascii char MOV A, @R0 ; Move it to A ACALL FROM_HEX ; Convert to binary value JNZ UNKNOWN ; Error on conversion MOV TMP, B ; Move converted value to TMP INC R0 ; Point to Low Ascii char MOV A, @R0 ; Move it to A ACALL FROM_HEX ; Convert to binary value JNZ UNKNOWN ; Error on conversion MOV A, TMP ; Move High value to A SWAP A ; Put High value in High nibble MOV TMP, B ; Move low converted value to TMP ORL A, TMP ; Or high and low nibble together MOV EVNT0_P, A ; New Event 0 Preload value MOV EVNT0, EVNT0_P ; Copy Event 0 preload value SJMP CMD_DONE QUERY: CJNE @R0, #81, SHUTD ; Query Command ACALL PRINT_ADC SJMP CMD_DONE SHUTD: CJNE @R0, #83, THRESH ; Shutdown Command - S:XX where XX = seconds INC R0 ; Dont care about the colon INC R0 ; Point to High Ascii char MOV A, @R0 ; Move it to A ACALL FROM_HEX ; Convert to binary value JNZ UNKNOWN ; Error on conversion MOV TMP, B ; Move converted value to TMP INC R0 ; Point to Low Ascii char MOV A, @R0 ; Move it to A ACALL FROM_HEX ; Convert to binary value JNZ UNKNOWN ; Error on conversion MOV A, TMP ; Move High value to A SWAP A ; Put High value in High nibble MOV TMP, B ; Move low converted value to TMP ORL A, TMP ; Or high and low nibble together MOV EVNT1_P, A ; New Event 1 Preload value MOV EVNT1, EVNT1_P ; Copy Event 1 preload value SJMP CMD_DONE THRESH: CJNE @R0, #84, UNKNOWN ; Threshold Command - TCXX where C = Channel ; where XX = seconds INC R0 ; Point to Channel Ascii char MOV A, @R0 ; Move it to A ACALL FROM_HEX ; Convert to binary value JNZ UNKNOWN ; Error on conversion PUSH B ; Store Channel on stack INC R0 ; Point to High Ascii char MOV A, @R0 ; Move it to A ACALL FROM_HEX ; Convert to binary value JNZ CLEANUP ; Error on conversion - clean up stack first MOV TMP, B ; Move converted value to TMP INC R0 ; Point to Low Ascii char MOV A, @R0 ; Move it to A ACALL FROM_HEX ; Convert to binary value JNZ CLEANUP ; Error on conversion - clean up stack first MOV A, TMP ; Move High value to A SWAP A ; Put High value in High nibble MOV TMP, B ; Move low converted value to TMP ORL A, TMP ; Or high and low nibble together MOV TMP, A ; Store value back in TMP POP ACC ; Get our channel value back in A JNZ CHAN1 ; Value for channel 1 MOV LOW0, B ; Copy value for ADC channel 0 mon SJMP CMD_DONE CHAN1: MOV LOW1, B ; Copy value for ADC channel 1 mon SJMP CMD_DONE CLEANUP: POP B ; Clean up from push UNKNOWN: MOV A, #63 ; Print '?' for unknown commands ACALL SEND ACALL CRLF CMD_DONE: MOV R0, #40H ; Set pointer to front of buffer MOV R7, #0H ; Clear buffer length MOV 40H, #0H ; Clear command buffer MOV 41H, #0H ; Clear command buffer MOV 42H, #0H ; Clear command buffer MOV 43H, #0H ; Clear command buffer RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; PRINT_ADC ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PRINT_ADC: MOV B, #48 ; 0 for Channel 0 ACALL HEAD MOV A, ADC0 ; Put value from ADC Channel 0 in A ACALL PRINT_HEX ; Print HEX value to Serial Port ACALL CRLF MOV B, #49 ; 1 for Channel 1 ACALL HEAD MOV A, ADC1 ; Put value from ADC Channel 1 in A ACALL PRINT_HEX ; Print HEX value to Serial Port ACALL CRLF RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; READ_ADC ; ; B = 0x00 for CHannel 0 ; B = 0x01 for CHannel 1 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; READ_ADC: CLR CS ; Lower Chip Select SETB DIN ; Set Start Bit SETB CLOCK ; Pulse Clock Line CLR CLOCK ; DIN Set High for Single Mode SETB CLOCK ; Pulse Clock Line CLR CLOCK MOV C, 0F0h ; Get bit vale from B.0 for Channel Select MOV DIN, C ; Set DIN for Channel 0/1 SETB CLOCK ; Pulse Clock Line CLR CLOCK SETB CLOCK ; Extra Clock Pulse for conversion CLR CLOCK MOV R2, #8h ; Loop for 8 data bits READ_ADC_LOOP: MOV C, DOUT ; Get Data Bit RLC A ; Rotate Bit left into Acc - MSB First SETB CLOCK ; Clock Pulse for next bit CLR CLOCK DJNZ R2, READ_ADC_LOOP ; Loop for all 8 bits SETB CS ; Raise Chip Select MOV C, 0F0h ; Get bit vale from B.0 for Channel JC READ_ADC_CH1 ; Is this value Channel 0 or 1 MOV ADC0, A ; Store Channel 0 ADC value SJMP READ_ADC_END READ_ADC_CH1: MOV ADC1, A READ_ADC_END: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; GETCH - A == 1 if character available - char returend in B ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GETCH: CLR EA ; Disable Interupts SETB RS0 ; Use bank 1 registers MOV A, R0 ; Get Write ptr CJNE A, 09H, GETCH_HAS ; Check buffer for data with Read ptr SJMP GETCH_EMPTY ; If equal buffer is empty GETCH_HAS: MOV B, @R1 ; Copy buffer data to B MOV A, #01H ; Return with 1 for data read CJNE R1, #3FH, GETCH_INC ; Not at end of buffer yet MOV R1, #2FH GETCH_INC: INC R1 ; Increment read ptr SJMP GETCH_DONE GETCH_EMPTY: MOV A, #00H ; Return with 0 for no data GETCH_DONE: CLR RS0 ; Set back to Bank 0 Registers SETB ES ; Enable Serial Interupt SETB EA ; Enable Global Interupt RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; SEND - Send Char in A out Serial Port ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SEND: SETB XMIT_FLG ; Set Xmit Flag MOV SBUF, A ; Send out a character SLOOP: JB XMIT_FLG, SLOOP ; Wait for character to be sent RET ; Return to caller ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; PRINT_HEX - Char in A ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PRINT_HEX: MOV B, A ; Keep copy of value in B MOV A, B ; Get value SWAP A ; DO High Nibble First ANL A, #0FH ; Mask Nibble ACALL TO_HEX ; Make Printable ACALL SEND ; Print what is in A MOV A, B ; Get value ANL A, #0FH ; Mask Nibble ACALL TO_HEX ; Make Printable ACALL SEND ; Print what is in A RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; TO_HEX - Convert Nibble to ASCII ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TO_HEX: PUSH ACC ; Save A on stack CLR C ; Clear carry flag SUBB A, #0AH ; Subtract 10 JNC TO_HEX_BIG ; Is great than 10 POP ACC ADD A, #30H ; Add Ascii 0 SJMP TO_HEX_DONE TO_HEX_BIG: POP ACC ADD A, #37H ; Add Ascii F - 9 TO_HEX_DONE: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; FROM_HEX - Convert ASCII Hex value to nibble ; ; ASCII Value in A ; Nibble returned in B ; On success A = 0 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FROM_HEX: CLR C ; Clear carry SUBB A, #48 ; Subtract Ascii 0 from A. JC HEX_ERROR ; Value smaller than Ascii 0 CJNE A, #10, HEX_HL ; If Equal to 10 we have an error SJMP HEX_ERROR HEX_HL: JC HEX_OK ; Value in A < 10 SUBB A, #07 ; Subtract 7 to get to Ascii A or higher JC HEX_ERROR ; Value smaller than Ascii A CJNE A, #10H, HEX_H ; If Equal to 10H our number is greter then F SJMP HEX_ERROR HEX_H: JNC HEX_ERROR ; If C = 0 A > F HEX_OK: MOV B, A ; Put converted hex value in B MOV A, #00H ; Clear A for successful conversion SJMP HEX_DONE HEX_ERROR: MOV A, #01 ; Set error for return code HEX_DONE: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; CRLF ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CRLF: MOV A, #13 ACALL SEND MOV A, #10 ACALL SEND RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; HEAD - Prints header for ADC values ; ; ADC channel # in B ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HEAD: MOV A, #67 ACALL SEND MOV A, #72 ACALL SEND MOV A, B ACALL SEND MOV A, #58 ACALL SEND RET END