From 849fbc44fd4fa24ec15a6f73cf4848927dfabc23 Mon Sep 17 00:00:00 2001 From: Jelmer Date: Tue, 31 Jan 2023 11:46:16 +0100 Subject: [PATCH] cleanup, rewrote epd-print method --- tag_fw/board/zbs154v033/board.h | 27 +- tag_fw/board/zbs154v033/screen.h | 4 +- tag_fw/board/zbs29v033/board.h | 27 +- tag_fw/board/zbs29v033/screen.h | 25 +- tag_fw/board/zbs42v033/board.h | 27 +- tag_fw/board/zbs42v033/screen.h | 27 +- tag_fw/comms.h | 4 +- tag_fw/cpu/8051/printf.c | 1550 +++++++++++++++--------------- tag_fw/epd.c | 9 +- tag_fw/epd.h | 4 +- tag_fw/printf.h | 3 + tag_fw/soc/radioCommon.h | 8 +- tag_fw/soc/zbs243/uart.c | 3 - tag_fw/userinterface.c | 46 +- 14 files changed, 816 insertions(+), 948 deletions(-) diff --git a/tag_fw/board/zbs154v033/board.h b/tag_fw/board/zbs154v033/board.h index 6e9a87ee..b5683d58 100644 --- a/tag_fw/board/zbs154v033/board.h +++ b/tag_fw/board/zbs154v033/board.h @@ -4,27 +4,11 @@ #include #include "spi.h" -#include "uart.h" - -//colors for ui messages -#define UI_MSG_MAGNIFY1 1 -#define UI_MSG_MAGNIFY2 1 -#define UI_MSG_MAGNIFY3 1 -#define UI_MSG_BACK_COLOR 4 -#define UI_MSG_FORE_COLOR_1 0 -#define UI_MSG_FORE_COLOR_2 5 -#define UI_MSG_FORE_COLOR_3 5 -#define UI_BARCODE_VERTICAL #define eepromByte spiByte #define eepromPrvSelect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 0; __asm__("nop\nnop\nnop\n"); } while(0) #define eepromPrvDeselect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 1; __asm__("nop\nnop\nnop\n"); } while(0) -//debug uart (enable only when needed, on some boards it inhibits eeprom access) -#define dbgUartOn() -#define dbgUartOff() -#define dbgUartByte uartTx - //eeprom map #define EEPROM_SETTINGS_AREA_START (0x01000UL) #define EEPROM_SETTINGS_AREA_LEN (0x03000UL) @@ -35,19 +19,10 @@ //till end of eeprom really. do not put anything after - it will be erased at pairing time!!! #define EEPROM_PROGRESS_BYTES (128) -//radio cfg -#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11 -#define RADIO_NUM_CHANNELS (1) - //hw types #define HW_TYPE_NORMAL HW_TYPE_154_INCH_ZBS_033 -#define HW_TYPE_CYCLING HW_TYPE_154_INCH_ZBS_033_FRAME_MODE - - - #include "../boardCommon.h" - -#endif +#endif \ No newline at end of file diff --git a/tag_fw/board/zbs154v033/screen.h b/tag_fw/board/zbs154v033/screen.h index 2dd805b3..034fd430 100644 --- a/tag_fw/board/zbs154v033/screen.h +++ b/tag_fw/board/zbs154v033/screen.h @@ -22,6 +22,4 @@ #define SCREEN_DATA_PASSES 2 -#endif - - +#endif \ No newline at end of file diff --git a/tag_fw/board/zbs29v033/board.h b/tag_fw/board/zbs29v033/board.h index 8951cd17..e63b5e11 100644 --- a/tag_fw/board/zbs29v033/board.h +++ b/tag_fw/board/zbs29v033/board.h @@ -4,27 +4,11 @@ #include #include "spi.h" -#include "uart.h" - -//colors for ui messages -#define UI_MSG_MAGNIFY1 1 -#define UI_MSG_MAGNIFY2 1 -#define UI_MSG_MAGNIFY3 1 -#define UI_MSG_BACK_COLOR 4 -#define UI_MSG_FORE_COLOR_1 0 -#define UI_MSG_FORE_COLOR_2 5 -#define UI_MSG_FORE_COLOR_3 5 -#define UI_BARCODE_VERTICAL #define eepromByte spiByte #define eepromPrvSelect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 0; __asm__("nop\nnop\nnop\n"); } while(0) #define eepromPrvDeselect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 1; __asm__("nop\nnop\nnop\n"); } while(0) -//debug uart (enable only when needed, on some boards it inhibits eeprom access) -#define dbgUartOn() -#define dbgUartOff() -#define dbgUartByte uartTx - //eeprom map #define EEPROM_SETTINGS_AREA_START (0x01000UL) #define EEPROM_SETTINGS_AREA_LEN (0x03000UL) @@ -35,19 +19,10 @@ //till end of eeprom really. do not put anything after - it will be erased at pairing time!!! #define EEPROM_PROGRESS_BYTES (128) -//radio cfg -#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11 -#define RADIO_NUM_CHANNELS (1) - //hw types #define HW_TYPE_NORMAL HW_TYPE_29_INCH_ZBS_026 -#define HW_TYPE_CYCLING HW_TYPE_29_INCH_ZBS_026_FRAME_MODE - - - #include "../boardCommon.h" - -#endif +#endif \ No newline at end of file diff --git a/tag_fw/board/zbs29v033/screen.h b/tag_fw/board/zbs29v033/screen.h index 576238d5..26f70666 100644 --- a/tag_fw/board/zbs29v033/screen.h +++ b/tag_fw/board/zbs29v033/screen.h @@ -4,12 +4,6 @@ #include #include - -//i hate globals, but for 8051 this makes life a lot easier, sorry :( -extern uint8_t __xdata mScreenVcom; -extern int8_t __xdata mCurTemperature; - - #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 296 @@ -27,22 +21,5 @@ extern int8_t __xdata mCurTemperature; #define SCREEN_DATA_PASSES 2 -void screenShutdown(void); - -void screenTest(void); - -__bit screenTxStart(__bit forPartial); - -void screenEndPass(void); //at end of each pass - -#pragma callee_saves screenByteTx -void screenByteTx(uint8_t byte); -void screenTxEnd(void); - -void screenSleep(void); - -extern uint8_t __xdata mScreenRow[]; //320 bytes used as temp by many on cc where memory is tight - -#endif - +#endif \ No newline at end of file diff --git a/tag_fw/board/zbs42v033/board.h b/tag_fw/board/zbs42v033/board.h index b23787ee..0cf71379 100644 --- a/tag_fw/board/zbs42v033/board.h +++ b/tag_fw/board/zbs42v033/board.h @@ -4,27 +4,11 @@ #include #include "spi.h" -#include "uart.h" - -//colors for ui messages -#define UI_MSG_MAGNIFY1 1 -#define UI_MSG_MAGNIFY2 1 -#define UI_MSG_MAGNIFY3 1 -#define UI_MSG_BACK_COLOR 4 -#define UI_MSG_FORE_COLOR_1 0 -#define UI_MSG_FORE_COLOR_2 5 -#define UI_MSG_FORE_COLOR_3 5 -#define UI_BARCODE_VERTICAL #define eepromByte spiByte #define eepromPrvSelect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 0; __asm__("nop\nnop\nnop\n"); } while(0) #define eepromPrvDeselect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 1; __asm__("nop\nnop\nnop\n"); } while(0) -//debug uart (enable only when needed, on some boards it inhibits eeprom access) -#define dbgUartOn() -#define dbgUartOff() -#define dbgUartByte uartTx - //eeprom map #define EEPROM_SETTINGS_AREA_START (0x01000UL) #define EEPROM_SETTINGS_AREA_LEN (0x03000UL) @@ -35,19 +19,10 @@ //till end of eeprom really. do not put anything after - it will be erased at pairing time!!! #define EEPROM_PROGRESS_BYTES (128) -//radio cfg -#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11 -#define RADIO_NUM_CHANNELS (1) - //hw types #define HW_TYPE_NORMAL HW_TYPE_42_INCH_ZBS_026 -#define HW_TYPE_CYCLING HW_TYPE_42_INCH_ZBS_026_FRAME_MODE - - - #include "../boardCommon.h" - -#endif +#endif \ No newline at end of file diff --git a/tag_fw/board/zbs42v033/screen.h b/tag_fw/board/zbs42v033/screen.h index e02a55d8..96501a0e 100644 --- a/tag_fw/board/zbs42v033/screen.h +++ b/tag_fw/board/zbs42v033/screen.h @@ -4,12 +4,6 @@ #include #include - -//i hate globals, but for 8051 this makes life a lot easier, sorry :( -extern uint8_t __xdata mScreenVcom; -extern int8_t __xdata mCurTemperature; - - #define SCREEN_WIDTH 400 #define SCREEN_HEIGHT 300 @@ -27,24 +21,5 @@ extern int8_t __xdata mCurTemperature; #define SCREEN_DATA_PASSES 2 -void screenShutdown(void); - - -void screenTest(void); - -__bit screenTxStart(__bit forPartial); - -void screenEndPass(void); //at end of each pass - -#pragma callee_saves screenByteTx -void screenByteTx(uint8_t byte); -void screenTxEnd(void); - -void screenSleep(void); - - -extern uint8_t __xdata mScreenRow[]; //320 bytes used as temp by many on cc where memory is tight - -#endif - +#endif \ No newline at end of file diff --git a/tag_fw/comms.h b/tag_fw/comms.h index 7c1c67b9..1753c45a 100644 --- a/tag_fw/comms.h +++ b/tag_fw/comms.h @@ -3,13 +3,11 @@ #include -#define COMMS_MAX_RADIO_WAIT_MSEC 200 -#define COMMS_IV_SIZE (4) //zeroes except these 4 counter bytes +#define COMMS_MAX_RADIO_WAIT_MSEC 200 #define COMMS_RX_ERR_NO_PACKETS (-1) #define COMMS_RX_ERR_INVALID_PACKET (-2) -#define COMMS_RX_ERR_MIC_FAIL (-3) #define COMMS_MAX_PACKET_SZ (127) diff --git a/tag_fw/cpu/8051/printf.c b/tag_fw/cpu/8051/printf.c index 93246c9c..be6dc10c 100644 --- a/tag_fw/cpu/8051/printf.c +++ b/tag_fw/cpu/8051/printf.c @@ -1,795 +1,799 @@ -#include -#include -#include #include "printf.h" -#include "zbs243.h" + +#include +#include +#include + #include "board.h" +#include "epd.h" +#include "uart.h" +#include "zbs243.h" typedef void (*StrFormatOutputFunc)(uint32_t param /* low byte is data, bits 24..31 is char */) __reentrant; -static __idata __at (0x00) unsigned char R0; -static __idata __at (0x01) unsigned char R1; -static __idata __at (0x02) unsigned char R2; -static __idata __at (0x03) unsigned char R3; -static __idata __at (0x04) unsigned char R4; -static __idata __at (0x05) unsigned char R5; -static __idata __at (0x06) unsigned char R6; -static __idata __at (0x07) unsigned char R7; +static __idata __at(0x00) unsigned char R0; +static __idata __at(0x01) unsigned char R1; +static __idata __at(0x02) unsigned char R2; +static __idata __at(0x03) unsigned char R3; +static __idata __at(0x04) unsigned char R4; +static __idata __at(0x05) unsigned char R5; +static __idata __at(0x06) unsigned char R6; +static __idata __at(0x07) unsigned char R7; static uint8_t __xdata mCvtBuf[18]; - -//callback must be reentrant and callee_saves +// callback must be reentrant and callee_saves #pragma callee_saves prvPrintFormat -void prvPrintFormat(StrFormatOutputFunc formatF, uint16_t formatD, const char __code *fmt, va_list vl) __reentrant __naked -{ - //formatF is in DPTR - //sp[0..-1] is return addr - //sp[-2..-3] is formatD - //sp[-4..-5] is fmt - //sp[-6] is vl - - __asm__ ( - " push _R7 \n" - " push DPH \n" //push formatF - " push DPL \n" - " mov _R7, sp \n" //save place on stack where we stashed it so we can call it easily - " push _R4 \n" - " push _R3 \n" - " push _R2 \n" - " push _R1 \n" - " push _R0 \n" - - " mov A, #-12 \n" - " add A, sp \n" - " mov R0, A \n" - //R0 now points to pushed params, for large values, we see high bytes first - // to get next byte, we need to DECEREMENT R0 - - " mov DPH, @R0 \n" - " dec R0 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " mov _R0, @R0 \n" - " dec R0 \n" - - //now format string is in DPTR, and R0 points to the top byte of whatever was in the first param - - //main loop: get a byte of the format string - "00001$: \n" - " clr A \n" - " movc A, @A + DPTR \n" - " inc DPTR \n" - //if zero, we're done - " jz 00098$ \n" - //if not '%', print it - " cjne A, #'%', 00097$ \n" - - //we got a percent sign - init state for format processing - " mov R4, #0 \n" //bit flags: - // 0x01 = '*' = pointer provided instead of value (integers only) - // 0x02 = '0' = zero-pad (for numbers only) - // 0x04 = have pad-to length - // 0x08 = long - // 0x10 = long long - // 0x20 = signed print requested. also: need to print a negative (used to reuse hex printing for decimal once converted to bcd) - " mov R2, #0 \n" //padLen - - //loop for format string ingestion - "00002$: \n" - " clr A \n" - " movc A, @A + DPTR \n" - " inc DPTR \n" - //if zero, we're done - " jz 00098$ \n" - //check for percent sign - " cjne A, #'%', 00003$ \n" - //fallthrough to print it and go read next non-format byte - //print a char in A, go read next format byte - "00097$: \n" - " lcall 00060$ \n" - " sjmp 00001$ \n" - - //exit label - placed for easy jumping to - "00098$: \n" - " pop _R0 \n" - " pop _R1 \n" - " pop _R2 \n" - " pop _R3 \n" - " pop _R4 \n" - " pop DPL \n" - " pop DPH \n" - " pop _R7 \n" - " ret \n" - - //continue to process format string - handle %c - "00003$: \n" - " cjne A, #'c', 00004$ \n" - " dec R0 \n" //param is pushed as int (16 bits) - " mov A, @R0 \n" - " dec R0 \n" - " sjmp 00097$ \n" //print and go read next non-format byte - - //continue to process format string - handle %m - "00004$: \n" - " mov R3, A \n" - " orl A, #0x20 \n" - " cjne A, #'m', 00008$ \n" - - //sort out which hexch charset to use - " mov A, R3 \n" - " anl A, #0x20 \n" - " rr A \n" - " mov R1, A \n" - - //go, do - " push DPH \n" - " push DPL \n" - " lcall 00090$ \n" //read the short (__xdata) pointer - >DPTR - " mov R4, #8 \n" //byteSel - "00005$: \n" - " push DPH \n" - " push DPL \n" - " mov A, R4 \n" - " dec A \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0 \n" - " mov DPH, A \n" - " movx A, @DPTR \n" - " mov R2, A \n" - " swap A \n" - " mov R3, #2 \n" - "00006$: \n" - " anl A, #0x0f \n" - " add A, R1 \n" - " mov DPTR, #00099$ \n" - " movc A, @A + DPTR \n" - " lcall 00060$ \n" - " mov A, R2 \n" - " djnz R3, 00006$ \n" - " pop DPL \n" - " pop DPH \n" - " djnz R4, 00007$ \n" - //done with mac addr - - "00055$: \n" - " pop DPL \n" - " pop DPH \n" - " sjmp 00001$ \n" - //print colon and contimue mac addr printing - "00007$: \n" - " mov A, #':' \n" - " lcall 00060$ \n" - " sjmp 00005$ \n" - - //continue to process format string - handle '*' - "00008$: \n" - " mov A, R3 \n" - " cjne A, #'*', 00009$ \n" - " cjne R2, #0, 00097$ \n" //only valid when no length/padding has been specified yet, else invalid specifier - " mov A, #0x01 \n" //"pointer mode" - "00010$: \n" - " orl A, R4 \n" - " mov R4, A \n" - " sjmp 00002$ \n" //get next format specifier now - - //continue to process format string - handle '0' - "00009$: \n" - " cjne A, #'0', 00011$ \n" - " cjne R2, #0, 00011$ \n" //setting "zero pad" is only valid when pad length is zero - " mov A, #0x06 \n" //"have pad length" | "zero-pad" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - - //continue to process format string - handle '1'...'9' - "00011$: \n" - " mov R3, A \n" - " add A, #-'0' \n" - " jnc 00012$ \n" //now 0..9 are valid - " add A, #-10 \n" - " jc 00012$ \n" - " add A, #10 \n" //get it back into 1..9 range - " mov R3, A \n" - " mov A, #10 \n" - " mov B, R2 \n" - " mul AB \n" - " add A, R3 \n" - " mov R2, A \n" - " mov A, #0x04 \n" //"have pad length" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - - //continue to process format string - handle 'l' - "00012$: \n" - " cjne R3, #'l', 00014$ \n" - " mov A, R4 \n" - " anl A, #0x08 \n" - " jz 00013$ \n" //no "long" yet? set that - //have long - set long log - " mov A, #0x10 \n" //"long long" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - //first 'l' - set long - "00013$: \n" - " mov A, #0x08 \n" //"long" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - - //continue to process format string - handle 's' - "00014$: \n" - " cjne R3, #'s', 00025$ \n" - " mov A, R4 \n" - " anl A, #0x08 \n" - " push DPH \n" - " push DPL \n" - " jnz 00015$ \n" - " lcall 00091$ \n" //get and resolve generic pointer into DPTR - " sjmp 00016$ \n" - "00015$: \n" //get short pointer into DPTR, record that it is to XRAM - " clr PSW.5 \n" - " clr PSW.1 \n" - " lcall 00090$ \n" - "00016$: \n" //pointer to string now in DPTR - //we have the string pointer in {DPTR,PSW}, let's see if we have padding to do - " mov A, R4 \n" - " anl A, #0x04 \n" - " jnz 00018$ \n" - //print string with no length restrictions - "00017$: \n" - " lcall 00095$ \n" - " jz 00055$ \n" - " lcall 00060$ \n" - " sjmp 00017$ \n" - - //print string with length restrictions and/or padding - "00018$: \n" - " cjne R2, #0, 00019$ \n" //verify reqested len was not zero - " sjmp 00055$ \n" - - "00019$: \n" - " lcall 00095$ \n" - " jz 00020$ \n" - " lcall 00060$ \n" - " djnz R2, 00019$ \n" - //we get here if we ran out of allowable bytes - we're done then - " ljmp 00055$ \n" - - //just a trampoline for range issues - "00035$: \n" - " ljmp 00036$ \n" - - //we need to pad with spaces - "00020$: \n" - " mov A, #' ' \n" - " lcall 00060$ \n" - " djnz R2, 00020$ \n" - " ljmp 00055$ \n" - - //continue to process format string - handle 'x'/'X' - "00025$: \n" - " mov A, R3 \n" - " orl A, #0x20 \n" - " cjne A, #'x', 00035$ \n" - " push DPH \n" - " push DPL \n" - " lcall 00080$ \n" //get pointer to the number in DPTR, length in bytes in B - //save it - - "00070$: \n" - " push DPH \n" - " push DPL \n" - - //sort out how long it would be if printed, first get a pointer to the highest - " mov A, B \n" - " rl A \n" - " mov R1, A \n" - " rr A \n" - " add A, #0xff \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0x00 \n" - " mov DPH, A \n" - "00026$: \n" - " lcall 00079$ \n" - " anl A, #0xf0 \n" - " jnz 00028$ \n" - " dec R1 \n" - " lcall 00079$ \n" - " jnz 00028$ \n" - " dec R1 \n" - //dec DPTR - " dec DPL \n" - " mov A, DPL \n" - " cjne A, #0xff, 00027$ \n" - " dec DPH \n" - "00027$: \n" - " djnz B, 00026$ \n" - - //we now know how many digits the number is (in R1), except that it has "0" if the number if zero, we cannot have that - "00028$: \n" - " cjne R1, #0, 00029$ \n" - " inc R1 \n" - "00029$: \n" //we now finally have the full length of the digits - - //if the number is negative (happens when we're printing decimals) - // the length of it is one more, also in case of zero-padding, we need to print the minus sign here now - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00051$ \n" - " inc R1 \n" //the length is one more - " mov A, R4 \n" - " anl A, #02 \n" //if zero-padding, the negative comes now - " jz 00051$ \n" - " mov A, #'-' \n" - " lcall 00060$ \n" - "00051$: \n" - - //sort out if we need padding at all and if there is space - " mov A, R4 \n" - " anl A, #0x04 \n" - " jz 00031$ \n" //no padding requested - //padding was requested len is in R2 - " mov A, R2 \n" - " clr C \n" - " subb A, R1 \n" - " jc 00031$ \n" //pad-to len < number_len -> no padding needed - " jz 00031$ \n" //pad-to len == number_len -> no padding needed - " mov R2, A \n" - - //sort out which character to use -> DPL - " mov A, R4 \n" //fancy way to create space/zero as needed - " anl A, #0x02 \n" - " swap A \n" - " rr A \n" - " add A, #0x20 \n" - " mov DPL, A \n" - - //pad! - "00030$: \n" - " mov A, DPL \n" - " lcall 00060$ \n" - " djnz R2, 00030$ \n" - "00031$: \n" - - //if the number is negative (happens when we're printing decimals) - // we made the length of it is one more, which we need to undo - // also in case of space-padding, we need to print the minus sign here now - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00052$ \n" - " dec R1 \n" //the length is one less than we had increased it to - " mov A, R4 \n" - " anl A, #02 \n" //if space-padding, the negative comes now - " jnz 00052$ \n" - " mov A, #'-' \n" - " lcall 00060$ \n" - "00052$: \n" - - //time to print the number itself - //sort out which hexch charset to use -> R2 - " mov A, R3 \n" - " anl A, #0x20 \n" - " rr A \n" - " mov R2, A \n" - //re-get the number pointer - " pop DPL \n" - " pop DPH \n" - //currently DPTR points to the number low byte, R1 is now many digits we expect to print, R2 is the charset selection, R4 and R3 are free - //let's calculate how many bytes we expect to process -> R4 - " mov A, R1 \n" - " inc A \n" - " clr C \n" - " rrc A \n" - " mov R4, A \n" - //let's repoint DPTR to the first byte we'll print in (remember we print 2 digits per byte) - " dec A \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0x00 \n" - " mov DPH, A \n" - - //decide if we need to print just a nibble of the high byte or the whole thing. Free up R1 - " mov A, R1 \n" - " anl A, #0x01 \n" - " jz 00032$ \n" - - //we're printing just the low nibble of the first byte - set up for it - " lcall 00079$ \n" - " mov R1, #1 \n" - " sjmp 00033$ \n" - - //print loop - "00032$: \n" - " lcall 00079$ \n" - " mov R1, #2 \n" - " mov R3, A \n" - " swap A \n" - "00033$: \n" - " anl A, #0x0f \n" - " add A, R2 \n" - " push DPH \n" - " push DPL \n" - " mov DPTR, #00099$ \n" - " movc A, @A + DPTR \n" - " pop DPL \n" - " pop DPH \n" - " lcall 00060$ \n" - " mov A, R3 \n" - " djnz R1, 00033$ \n" - - //dec DPTR - " dec DPL \n" - " mov A, DPL \n" - " cjne A, #0xff, 00034$ \n" - " dec DPH \n" - "00034$: \n" - " djnz R4, 00032$ \n" - - //done! - " ljmp 00055$ \n" - - //continue to process format string - handle 'd' - "00036$: \n" - " cjne R3, #'d', 00037$ \n" - " mov A, #0x20 \n" - " orl A, R4 \n" - " mov R4, A \n" - " sjmp 00040$ \n" - - //continue to process format string - handle 'u' - "00037$: \n" - " cjne R3, #'u', 00038$ \n" - " sjmp 00040$ \n" - - //no more format strings exist that we can handle - bail - "00038$: \n" - " ljmp 00001$ \n" - - //handle decimal printing - "00040$: \n" - " push DPH \n" - " push DPL \n" - " lcall 00080$ \n" //get pointer to the number in DPTR, length in bytes in B - " push B \n" - - //copy the number to the double-dabble storage at proper offset (0 for u64, 4 for u32, 6 for u16) - //we do this so that the dabble area always starts at the same place... - " mov A, #8 \n" - " clr C \n" - " subb A, B \n" - " add A, #_mCvtBuf \n" - " mov R1, A \n" - " clr A \n" - " addc A, #(_mCvtBuf >> 8) \n" - " mov R3, A \n" - "00041$: \n" - " lcall 00079$ \n" - " inc DPTR \n" - " lcall 00086$ \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " lcall 00086$ \n" - " djnz B, 00041$ \n" - //leave DPTR pointing to dabble storage, past the number - " lcall 00086$ \n" - - //we now have the top byte of the number in A, good time to check for negatives, if needed - " mov B, A \n" - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00050$ \n" //unsigned printing requested - " mov A, B \n" - " anl A, #0x80 \n" - " jnz 00043$ \n" //is negative - we need to invert, 0x20 bit in R1 stays - //positive - 0x20 bit in R1 needs to go - " mov A, R4 \n" - " anl A, #~0x20 \n" - " mov R4, A \n" - " sjmp 00050$ \n" - - //we need to negate the number - // but first we need a pointer to it, and its size - "00043$: \n" - " pop B \n" - " push B \n" - " mov A, #8 \n" - " clr C \n" - " subb A, B \n" - " add A, #_mCvtBuf \n" - " mov DPL, A \n" - " clr A \n" - " addc A, #(_mCvtBuf >> 8) \n" - " mov DPH, A \n" - - //ok, now we are ready to negate it - " clr C \n" - "00049$: \n" - " movx A, @DPTR \n" - " mov R1, A \n" - " clr A \n" - " subb A, R1 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00049$ \n" - - //zero out the rest of the storage (10 bytes) - "00050$: \n" - " mov B, #10 \n" - " clr A \n" - "00042$: \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00042$ \n" - - //calculate number of dabble steps - " pop A \n" - " swap A \n" - " rr A \n" - " mov R3, A \n" - - //do the thing - "00044$: \n" - - //dabble (10 iters for simplicity) - " mov DPTR, #(_mCvtBuf + 8) \n" - " mov B, #10 \n" - "00046$: \n" - " movx A, @DPTR \n" - " mov R1, A \n" - " anl A, #0x0f \n" - " add A,#-0x05 \n" - " mov A, R1 \n" - " jnc 00047$ \n" - " add A, #0x03 \n" - "00047$: \n" - " mov R1, A \n" - " anl A, #0xf0 \n" - " add A,#-0x50 \n" - " mov A, R1 \n" - " jnc 00048$ \n" - " add A, #0x30 \n" - "00048$: \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00046$ \n" - - //double (18 iters for simplicity) - " mov DPTR, #_mCvtBuf \n" - " clr C \n" - " mov B, #18 \n" - "00045$: \n" - " movx A, @DPTR \n" - " rlc A \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00045$ \n" - - " djnz R3, 00044$ \n" - - //dabbling is done, print it now using hex routine - " mov DPTR, #(_mCvtBuf + 8) \n" - " mov B, #10 \n" - " clr PSW.5 \n" //it is now for sure in XRAM - " ljmp 00070$ \n" - - //read short pointer from param stack - "00090$: \n" - " mov DPH, @R0 \n" - "00093$: \n" - " dec R0 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " ret \n" - - //read and increment pointer of the type provided by 00091$ (in {DPTR,PSW}) into A. clobber nothing - "00095$: \n" - " jb PSW.5, 00066$ \n" - " jb PSW.1, 00067$ \n" - //XRAM - " movx A, @DPTR \n" - " inc DPTR \n" - " ret \n" - //CODE - "00066$: \n" - " clr A \n" - " movc A, @A+DPTR \n" - " inc DPTR \n" - " ret \n" - //IRAM - "00067$: \n" - " mov DPH, R0 \n" - " mov R0, DPL \n" - " mov A, @R0 \n" - " mov R0, DPH \n" - " inc DPL \n" - " ret \n" - - //resolve generic pointer on param stack to an pointer in DPTR and flags in PSW.5 and PSW.1 - //PSW.5 will be 0 and PSW.1 will be 0 for XRAM (PDATA goes here too) - //PSW.5 will be 1 and PSW.1 will be 0 for CODE - //PSW.5 will be 0 and PSW.1 will be 1 for IRAM - "00091$: \n" - " clr PSW.5 \n" - " clr PSW.1 \n" - " mov A, @R0 \n" - " dec R0 \n" - " jz 00090$ \n" //0x00: pointer type: xdata - " xrl A, #0x80 \n" - " jz 00094$ \n" //0x80: pointer type: code - " xrl A, #0xc0 \n" - " jz 00092$ \n" //0x40: pointer type: idata - //pdata - " mov DPH, _XPAGE \n" - " sjmp 00093$ \n" - //idata - "00092$: \n" - " setb PSW.1 \n" - " sjmp 00093$ \n" - //code - "00094$: \n" - " setb PSW.5 \n" - " sjmp 00090$ \n" - - //read the pointer of the type that 00080$ returns (in DPTR) into A. clobber nothing - "00079$: \n" - " jnb PSW.5, 00078$ \n" - " push _R0 \n" - " mov R0, DPL \n" - " mov A, @R0 \n" - " pop _R0 \n" - " ret \n" - "00078$: \n" - " movx A, @DPTR \n" - " ret \n" - - //get pointer to a number, might be pushed or might be pointed to, size might vary. return pointer to number's LOW byte in DPTR - "00080$: \n" - " mov A, R4 \n" - " anl A, #0x01 \n" - " jnz 00083$ \n" - //param is itself on stack - now we care about size, but either way, PSW.5 will be 1 - " setb PSW.5 \n" - " mov B, #0 \n" - " mov A, R4 \n" - " anl A, #0x18 \n" - " jz 00081$ \n" - " anl A, #0x10 \n" - " jz 00082$ \n" - //long long (8 bytes) \n" - " setb B.2 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - //long (4 bytes) - "00082$: \n" - " setb B.1 \n" - " dec R0 \n" - " dec R0 \n" - //int (2 bytes) \n" - "00081$: \n" - " setb B.0 \n" - " dec R0 \n" - " mov DPL, R0 \n" - " dec R0 \n" - " inc B \n" - " ret \n" - //pointer it on stack itself, number is in xram, but we still need to provide the length - "00083$: \n" - " clr PSW.5 \n" //mark as "in xram" - " mov A, R4 \n" - " anl A, #0x18 \n" - " jz 00084$ \n" - " anl A, #0x10 \n" - " jz 00085$ \n" - //long long - " mov B, #8 \n" - " ljmp 00090$ \n" - //long - "00085$: \n" - " mov B, #4 \n" - " ljmp 00090$ \n" - //int - "00084$: \n" - " mov B, #2 \n" - " ljmp 00090$ \n" +void prvPrintFormat(StrFormatOutputFunc formatF, uint16_t formatD, const char __code *fmt, va_list vl) __reentrant __naked { + // formatF is in DPTR + // sp[0..-1] is return addr + // sp[-2..-3] is formatD + // sp[-4..-5] is fmt + // sp[-6] is vl - //swap R3:R1 <-> DPH:DPL - "00086$: \n" - " xch A, DPH \n" - " xch A, R3 \n" - " xch A, DPH \n" - " xch A, DPL \n" - " xch A, R1 \n" - " xch A, DPL \n" - " ret \n" + __asm__( + " push _R7 \n" + " push DPH \n" // push formatF + " push DPL \n" + " mov _R7, sp \n" // save place on stack where we stashed it so we can call it easily + " push _R4 \n" + " push _R3 \n" + " push _R2 \n" + " push _R1 \n" + " push _R0 \n" - /* putchar func - called via call. char is in A, R7 has pointer to stack as needed - can clobber B, CANNOT clobber DPTR - a mess because...8051 - */ - "00060$: \n" - " push DPH \n" - " push DPL \n" - " push _R1 \n" - " push _R0 \n" - " mov _R0, R7 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " mov DPH, @R0 \n" //DPTR is now func ptr - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " mov _R1, @R0 \n" - " dec R0 \n" - " mov _R0, @R0 \n" //R1:R0 is now "formatD" - " lcall 00061$ \n" //to set ret addr - " pop _R0 \n" - " pop _R1 \n" - " pop DPL \n" - " pop DPH \n" - " ret \n" - "00061$: \n" - " push DPL \n" - " push DPH \n" - " mov DPL, _R0 \n" - " mov DPH, _R1 \n" - " ret \n" - - "00099$: \n" - " .ascii \"01234567\" \n" - " .ascii \"89ABCDEF\" \n" - " .ascii \"01234567\" \n" - " .ascii \"89abcdef\" \n" - ); - (void)fmt; - (void)vl; - (void)formatF; - (void)formatD; + " mov A, #-12 \n" + " add A, sp \n" + " mov R0, A \n" + // R0 now points to pushed params, for large values, we see high bytes first + // to get next byte, we need to DECEREMENT R0 + + " mov DPH, @R0 \n" + " dec R0 \n" + " mov DPL, @R0 \n" + " dec R0 \n" + " mov _R0, @R0 \n" + " dec R0 \n" + + // now format string is in DPTR, and R0 points to the top byte of whatever was in the first param + + // main loop: get a byte of the format string + "00001$: \n" + " clr A \n" + " movc A, @A + DPTR \n" + " inc DPTR \n" + // if zero, we're done + " jz 00098$ \n" + // if not '%', print it + " cjne A, #'%', 00097$ \n" + + // we got a percent sign - init state for format processing + " mov R4, #0 \n" // bit flags: + // 0x01 = '*' = pointer provided instead of value (integers only) + // 0x02 = '0' = zero-pad (for numbers only) + // 0x04 = have pad-to length + // 0x08 = long + // 0x10 = long long + // 0x20 = signed print requested. also: need to print a negative (used to reuse hex printing for decimal once converted to bcd) + " mov R2, #0 \n" // padLen + + // loop for format string ingestion + "00002$: \n" + " clr A \n" + " movc A, @A + DPTR \n" + " inc DPTR \n" + // if zero, we're done + " jz 00098$ \n" + // check for percent sign + " cjne A, #'%', 00003$ \n" + // fallthrough to print it and go read next non-format byte + // print a char in A, go read next format byte + "00097$: \n" + " lcall 00060$ \n" + " sjmp 00001$ \n" + + // exit label - placed for easy jumping to + "00098$: \n" + " pop _R0 \n" + " pop _R1 \n" + " pop _R2 \n" + " pop _R3 \n" + " pop _R4 \n" + " pop DPL \n" + " pop DPH \n" + " pop _R7 \n" + " ret \n" + + // continue to process format string - handle %c + "00003$: \n" + " cjne A, #'c', 00004$ \n" + " dec R0 \n" // param is pushed as int (16 bits) + " mov A, @R0 \n" + " dec R0 \n" + " sjmp 00097$ \n" // print and go read next non-format byte + + // continue to process format string - handle %m + "00004$: \n" + " mov R3, A \n" + " orl A, #0x20 \n" + " cjne A, #'m', 00008$ \n" + + // sort out which hexch charset to use + " mov A, R3 \n" + " anl A, #0x20 \n" + " rr A \n" + " mov R1, A \n" + + // go, do + " push DPH \n" + " push DPL \n" + " lcall 00090$ \n" // read the short (__xdata) pointer - >DPTR + " mov R4, #8 \n" // byteSel + "00005$: \n" + " push DPH \n" + " push DPL \n" + " mov A, R4 \n" + " dec A \n" + " add A, DPL \n" + " mov DPL, A \n" + " mov A, DPH \n" + " addc A, #0 \n" + " mov DPH, A \n" + " movx A, @DPTR \n" + " mov R2, A \n" + " swap A \n" + " mov R3, #2 \n" + "00006$: \n" + " anl A, #0x0f \n" + " add A, R1 \n" + " mov DPTR, #00099$ \n" + " movc A, @A + DPTR \n" + " lcall 00060$ \n" + " mov A, R2 \n" + " djnz R3, 00006$ \n" + " pop DPL \n" + " pop DPH \n" + " djnz R4, 00007$ \n" + // done with mac addr + + "00055$: \n" + " pop DPL \n" + " pop DPH \n" + " sjmp 00001$ \n" + // print colon and contimue mac addr printing + "00007$: \n" + " mov A, #':' \n" + " lcall 00060$ \n" + " sjmp 00005$ \n" + + // continue to process format string - handle '*' + "00008$: \n" + " mov A, R3 \n" + " cjne A, #'*', 00009$ \n" + " cjne R2, #0, 00097$ \n" // only valid when no length/padding has been specified yet, else invalid specifier + " mov A, #0x01 \n" //"pointer mode" + "00010$: \n" + " orl A, R4 \n" + " mov R4, A \n" + " sjmp 00002$ \n" // get next format specifier now + + // continue to process format string - handle '0' + "00009$: \n" + " cjne A, #'0', 00011$ \n" + " cjne R2, #0, 00011$ \n" // setting "zero pad" is only valid when pad length is zero + " mov A, #0x06 \n" //"have pad length" | "zero-pad" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + + // continue to process format string - handle '1'...'9' + "00011$: \n" + " mov R3, A \n" + " add A, #-'0' \n" + " jnc 00012$ \n" // now 0..9 are valid + " add A, #-10 \n" + " jc 00012$ \n" + " add A, #10 \n" // get it back into 1..9 range + " mov R3, A \n" + " mov A, #10 \n" + " mov B, R2 \n" + " mul AB \n" + " add A, R3 \n" + " mov R2, A \n" + " mov A, #0x04 \n" //"have pad length" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + + // continue to process format string - handle 'l' + "00012$: \n" + " cjne R3, #'l', 00014$ \n" + " mov A, R4 \n" + " anl A, #0x08 \n" + " jz 00013$ \n" // no "long" yet? set that + // have long - set long log + " mov A, #0x10 \n" //"long long" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + // first 'l' - set long + "00013$: \n" + " mov A, #0x08 \n" //"long" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + + // continue to process format string - handle 's' + "00014$: \n" + " cjne R3, #'s', 00025$ \n" + " mov A, R4 \n" + " anl A, #0x08 \n" + " push DPH \n" + " push DPL \n" + " jnz 00015$ \n" + " lcall 00091$ \n" // get and resolve generic pointer into DPTR + " sjmp 00016$ \n" + "00015$: \n" // get short pointer into DPTR, record that it is to XRAM + " clr PSW.5 \n" + " clr PSW.1 \n" + " lcall 00090$ \n" + "00016$: \n" // pointer to string now in DPTR + // we have the string pointer in {DPTR,PSW}, let's see if we have padding to do + " mov A, R4 \n" + " anl A, #0x04 \n" + " jnz 00018$ \n" + // print string with no length restrictions + "00017$: \n" + " lcall 00095$ \n" + " jz 00055$ \n" + " lcall 00060$ \n" + " sjmp 00017$ \n" + + // print string with length restrictions and/or padding + "00018$: \n" + " cjne R2, #0, 00019$ \n" // verify reqested len was not zero + " sjmp 00055$ \n" + + "00019$: \n" + " lcall 00095$ \n" + " jz 00020$ \n" + " lcall 00060$ \n" + " djnz R2, 00019$ \n" + // we get here if we ran out of allowable bytes - we're done then + " ljmp 00055$ \n" + + // just a trampoline for range issues + "00035$: \n" + " ljmp 00036$ \n" + + // we need to pad with spaces + "00020$: \n" + " mov A, #' ' \n" + " lcall 00060$ \n" + " djnz R2, 00020$ \n" + " ljmp 00055$ \n" + + // continue to process format string - handle 'x'/'X' + "00025$: \n" + " mov A, R3 \n" + " orl A, #0x20 \n" + " cjne A, #'x', 00035$ \n" + " push DPH \n" + " push DPL \n" + " lcall 00080$ \n" // get pointer to the number in DPTR, length in bytes in B + // save it + + "00070$: \n" + " push DPH \n" + " push DPL \n" + + // sort out how long it would be if printed, first get a pointer to the highest + " mov A, B \n" + " rl A \n" + " mov R1, A \n" + " rr A \n" + " add A, #0xff \n" + " add A, DPL \n" + " mov DPL, A \n" + " mov A, DPH \n" + " addc A, #0x00 \n" + " mov DPH, A \n" + "00026$: \n" + " lcall 00079$ \n" + " anl A, #0xf0 \n" + " jnz 00028$ \n" + " dec R1 \n" + " lcall 00079$ \n" + " jnz 00028$ \n" + " dec R1 \n" + // dec DPTR + " dec DPL \n" + " mov A, DPL \n" + " cjne A, #0xff, 00027$ \n" + " dec DPH \n" + "00027$: \n" + " djnz B, 00026$ \n" + + // we now know how many digits the number is (in R1), except that it has "0" if the number if zero, we cannot have that + "00028$: \n" + " cjne R1, #0, 00029$ \n" + " inc R1 \n" + "00029$: \n" // we now finally have the full length of the digits + + // if the number is negative (happens when we're printing decimals) + // the length of it is one more, also in case of zero-padding, we need to print the minus sign here now + " mov A, R4 \n" + " anl A, #0x20 \n" + " jz 00051$ \n" + " inc R1 \n" // the length is one more + " mov A, R4 \n" + " anl A, #02 \n" // if zero-padding, the negative comes now + " jz 00051$ \n" + " mov A, #'-' \n" + " lcall 00060$ \n" + "00051$: \n" + + // sort out if we need padding at all and if there is space + " mov A, R4 \n" + " anl A, #0x04 \n" + " jz 00031$ \n" // no padding requested + // padding was requested len is in R2 + " mov A, R2 \n" + " clr C \n" + " subb A, R1 \n" + " jc 00031$ \n" // pad-to len < number_len -> no padding needed + " jz 00031$ \n" // pad-to len == number_len -> no padding needed + " mov R2, A \n" + + // sort out which character to use -> DPL + " mov A, R4 \n" // fancy way to create space/zero as needed + " anl A, #0x02 \n" + " swap A \n" + " rr A \n" + " add A, #0x20 \n" + " mov DPL, A \n" + + // pad! + "00030$: \n" + " mov A, DPL \n" + " lcall 00060$ \n" + " djnz R2, 00030$ \n" + "00031$: \n" + + // if the number is negative (happens when we're printing decimals) + // we made the length of it is one more, which we need to undo + // also in case of space-padding, we need to print the minus sign here now + " mov A, R4 \n" + " anl A, #0x20 \n" + " jz 00052$ \n" + " dec R1 \n" // the length is one less than we had increased it to + " mov A, R4 \n" + " anl A, #02 \n" // if space-padding, the negative comes now + " jnz 00052$ \n" + " mov A, #'-' \n" + " lcall 00060$ \n" + "00052$: \n" + + // time to print the number itself + // sort out which hexch charset to use -> R2 + " mov A, R3 \n" + " anl A, #0x20 \n" + " rr A \n" + " mov R2, A \n" + // re-get the number pointer + " pop DPL \n" + " pop DPH \n" + // currently DPTR points to the number low byte, R1 is now many digits we expect to print, R2 is the charset selection, R4 and R3 are free + // let's calculate how many bytes we expect to process -> R4 + " mov A, R1 \n" + " inc A \n" + " clr C \n" + " rrc A \n" + " mov R4, A \n" + // let's repoint DPTR to the first byte we'll print in (remember we print 2 digits per byte) + " dec A \n" + " add A, DPL \n" + " mov DPL, A \n" + " mov A, DPH \n" + " addc A, #0x00 \n" + " mov DPH, A \n" + + // decide if we need to print just a nibble of the high byte or the whole thing. Free up R1 + " mov A, R1 \n" + " anl A, #0x01 \n" + " jz 00032$ \n" + + // we're printing just the low nibble of the first byte - set up for it + " lcall 00079$ \n" + " mov R1, #1 \n" + " sjmp 00033$ \n" + + // print loop + "00032$: \n" + " lcall 00079$ \n" + " mov R1, #2 \n" + " mov R3, A \n" + " swap A \n" + "00033$: \n" + " anl A, #0x0f \n" + " add A, R2 \n" + " push DPH \n" + " push DPL \n" + " mov DPTR, #00099$ \n" + " movc A, @A + DPTR \n" + " pop DPL \n" + " pop DPH \n" + " lcall 00060$ \n" + " mov A, R3 \n" + " djnz R1, 00033$ \n" + + // dec DPTR + " dec DPL \n" + " mov A, DPL \n" + " cjne A, #0xff, 00034$ \n" + " dec DPH \n" + "00034$: \n" + " djnz R4, 00032$ \n" + + // done! + " ljmp 00055$ \n" + + // continue to process format string - handle 'd' + "00036$: \n" + " cjne R3, #'d', 00037$ \n" + " mov A, #0x20 \n" + " orl A, R4 \n" + " mov R4, A \n" + " sjmp 00040$ \n" + + // continue to process format string - handle 'u' + "00037$: \n" + " cjne R3, #'u', 00038$ \n" + " sjmp 00040$ \n" + + // no more format strings exist that we can handle - bail + "00038$: \n" + " ljmp 00001$ \n" + + // handle decimal printing + "00040$: \n" + " push DPH \n" + " push DPL \n" + " lcall 00080$ \n" // get pointer to the number in DPTR, length in bytes in B + " push B \n" + + // copy the number to the double-dabble storage at proper offset (0 for u64, 4 for u32, 6 for u16) + // we do this so that the dabble area always starts at the same place... + " mov A, #8 \n" + " clr C \n" + " subb A, B \n" + " add A, #_mCvtBuf \n" + " mov R1, A \n" + " clr A \n" + " addc A, #(_mCvtBuf >> 8) \n" + " mov R3, A \n" + "00041$: \n" + " lcall 00079$ \n" + " inc DPTR \n" + " lcall 00086$ \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " lcall 00086$ \n" + " djnz B, 00041$ \n" + // leave DPTR pointing to dabble storage, past the number + " lcall 00086$ \n" + + // we now have the top byte of the number in A, good time to check for negatives, if needed + " mov B, A \n" + " mov A, R4 \n" + " anl A, #0x20 \n" + " jz 00050$ \n" // unsigned printing requested + " mov A, B \n" + " anl A, #0x80 \n" + " jnz 00043$ \n" // is negative - we need to invert, 0x20 bit in R1 stays + // positive - 0x20 bit in R1 needs to go + " mov A, R4 \n" + " anl A, #~0x20 \n" + " mov R4, A \n" + " sjmp 00050$ \n" + + // we need to negate the number + // but first we need a pointer to it, and its size + "00043$: \n" + " pop B \n" + " push B \n" + " mov A, #8 \n" + " clr C \n" + " subb A, B \n" + " add A, #_mCvtBuf \n" + " mov DPL, A \n" + " clr A \n" + " addc A, #(_mCvtBuf >> 8) \n" + " mov DPH, A \n" + + // ok, now we are ready to negate it + " clr C \n" + "00049$: \n" + " movx A, @DPTR \n" + " mov R1, A \n" + " clr A \n" + " subb A, R1 \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00049$ \n" + + // zero out the rest of the storage (10 bytes) + "00050$: \n" + " mov B, #10 \n" + " clr A \n" + "00042$: \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00042$ \n" + + // calculate number of dabble steps + " pop A \n" + " swap A \n" + " rr A \n" + " mov R3, A \n" + + // do the thing + "00044$: \n" + + // dabble (10 iters for simplicity) + " mov DPTR, #(_mCvtBuf + 8) \n" + " mov B, #10 \n" + "00046$: \n" + " movx A, @DPTR \n" + " mov R1, A \n" + " anl A, #0x0f \n" + " add A,#-0x05 \n" + " mov A, R1 \n" + " jnc 00047$ \n" + " add A, #0x03 \n" + "00047$: \n" + " mov R1, A \n" + " anl A, #0xf0 \n" + " add A,#-0x50 \n" + " mov A, R1 \n" + " jnc 00048$ \n" + " add A, #0x30 \n" + "00048$: \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00046$ \n" + + // double (18 iters for simplicity) + " mov DPTR, #_mCvtBuf \n" + " clr C \n" + " mov B, #18 \n" + "00045$: \n" + " movx A, @DPTR \n" + " rlc A \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00045$ \n" + + " djnz R3, 00044$ \n" + + // dabbling is done, print it now using hex routine + " mov DPTR, #(_mCvtBuf + 8) \n" + " mov B, #10 \n" + " clr PSW.5 \n" // it is now for sure in XRAM + " ljmp 00070$ \n" + + // read short pointer from param stack + "00090$: \n" + " mov DPH, @R0 \n" + "00093$: \n" + " dec R0 \n" + " mov DPL, @R0 \n" + " dec R0 \n" + " ret \n" + + // read and increment pointer of the type provided by 00091$ (in {DPTR,PSW}) into A. clobber nothing + "00095$: \n" + " jb PSW.5, 00066$ \n" + " jb PSW.1, 00067$ \n" + // XRAM + " movx A, @DPTR \n" + " inc DPTR \n" + " ret \n" + // CODE + "00066$: \n" + " clr A \n" + " movc A, @A+DPTR \n" + " inc DPTR \n" + " ret \n" + // IRAM + "00067$: \n" + " mov DPH, R0 \n" + " mov R0, DPL \n" + " mov A, @R0 \n" + " mov R0, DPH \n" + " inc DPL \n" + " ret \n" + + // resolve generic pointer on param stack to an pointer in DPTR and flags in PSW.5 and PSW.1 + // PSW.5 will be 0 and PSW.1 will be 0 for XRAM (PDATA goes here too) + // PSW.5 will be 1 and PSW.1 will be 0 for CODE + // PSW.5 will be 0 and PSW.1 will be 1 for IRAM + "00091$: \n" + " clr PSW.5 \n" + " clr PSW.1 \n" + " mov A, @R0 \n" + " dec R0 \n" + " jz 00090$ \n" // 0x00: pointer type: xdata + " xrl A, #0x80 \n" + " jz 00094$ \n" // 0x80: pointer type: code + " xrl A, #0xc0 \n" + " jz 00092$ \n" // 0x40: pointer type: idata + // pdata + " mov DPH, _XPAGE \n" + " sjmp 00093$ \n" + // idata + "00092$: \n" + " setb PSW.1 \n" + " sjmp 00093$ \n" + // code + "00094$: \n" + " setb PSW.5 \n" + " sjmp 00090$ \n" + + // read the pointer of the type that 00080$ returns (in DPTR) into A. clobber nothing + "00079$: \n" + " jnb PSW.5, 00078$ \n" + " push _R0 \n" + " mov R0, DPL \n" + " mov A, @R0 \n" + " pop _R0 \n" + " ret \n" + "00078$: \n" + " movx A, @DPTR \n" + " ret \n" + + // get pointer to a number, might be pushed or might be pointed to, size might vary. return pointer to number's LOW byte in DPTR + "00080$: \n" + " mov A, R4 \n" + " anl A, #0x01 \n" + " jnz 00083$ \n" + // param is itself on stack - now we care about size, but either way, PSW.5 will be 1 + " setb PSW.5 \n" + " mov B, #0 \n" + " mov A, R4 \n" + " anl A, #0x18 \n" + " jz 00081$ \n" + " anl A, #0x10 \n" + " jz 00082$ \n" + // long long (8 bytes) \n" + " setb B.2 \n" + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + // long (4 bytes) + "00082$: \n" + " setb B.1 \n" + " dec R0 \n" + " dec R0 \n" + // int (2 bytes) \n" + "00081$: \n" + " setb B.0 \n" + " dec R0 \n" + " mov DPL, R0 \n" + " dec R0 \n" + " inc B \n" + " ret \n" + // pointer it on stack itself, number is in xram, but we still need to provide the length + "00083$: \n" + " clr PSW.5 \n" // mark as "in xram" + " mov A, R4 \n" + " anl A, #0x18 \n" + " jz 00084$ \n" + " anl A, #0x10 \n" + " jz 00085$ \n" + // long long + " mov B, #8 \n" + " ljmp 00090$ \n" + // long + "00085$: \n" + " mov B, #4 \n" + " ljmp 00090$ \n" + // int + "00084$: \n" + " mov B, #2 \n" + " ljmp 00090$ \n" + + // swap R3:R1 <-> DPH:DPL + "00086$: \n" + " xch A, DPH \n" + " xch A, R3 \n" + " xch A, DPH \n" + " xch A, DPL \n" + " xch A, R1 \n" + " xch A, DPL \n" + " ret \n" + + /* putchar func + called via call. char is in A, R7 has pointer to stack as needed + can clobber B, CANNOT clobber DPTR + a mess because...8051 + */ + "00060$: \n" + " push DPH \n" + " push DPL \n" + " push _R1 \n" + " push _R0 \n" + " mov _R0, R7 \n" + " mov DPL, @R0 \n" + " dec R0 \n" + " mov DPH, @R0 \n" // DPTR is now func ptr + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + " mov _R1, @R0 \n" + " dec R0 \n" + " mov _R0, @R0 \n" // R1:R0 is now "formatD" + " lcall 00061$ \n" // to set ret addr + " pop _R0 \n" + " pop _R1 \n" + " pop DPL \n" + " pop DPH \n" + " ret \n" + "00061$: \n" + " push DPL \n" + " push DPH \n" + " mov DPL, _R0 \n" + " mov DPH, _R1 \n" + " ret \n" + + "00099$: \n" + " .ascii \"01234567\" \n" + " .ascii \"89ABCDEF\" \n" + " .ascii \"01234567\" \n" + " .ascii \"89abcdef\" \n"); + (void)fmt; + (void)vl; + (void)formatF; + (void)formatD; } #pragma callee_saves prPrvPutchar -static void prPrvPutchar(uint32_t data) __reentrant -{ - char ch = data >> 24; - - if (ch == '\n') - dbgUartByte('\r'); - dbgUartByte(ch); +static void prPrvPutchar(uint32_t data) __reentrant { + char ch = data >> 24; + if (ch == '\n') + uartTx('\r'); + uartTx(ch); +} +#pragma callee_saves epdPutchar +static void epdPutchar(uint32_t data) __reentrant { + char ch = data >> 24; + writeCharEPD(ch); } -void pr(const char __code *fmt, ...) __reentrant -{ - va_list vl; - - va_start(vl, fmt); - dbgUartOn(); - prvPrintFormat(prPrvPutchar, 0, fmt, vl); - dbgUartOff(); - va_end(vl); +void pr(const char __code *fmt, ...) __reentrant { + va_list vl; + va_start(vl, fmt); + prvPrintFormat(prPrvPutchar, 0, fmt, vl); + va_end(vl); +} + +void epdpr(const char __code *fmt, ...) __reentrant { + va_list vl; + va_start(vl, fmt); + prvPrintFormat(epdPutchar, 0, fmt, vl); + va_end(vl); } #pragma callee_saves prPrvPutS -static void prPrvPutS(uint32_t data) __reentrant -{ - char __xdata * __idata *strPP = (char __xdata * __idata *)data; - char ch = data >> 24; - - *(*strPP)++ = ch; +static void prPrvPutS(uint32_t data) __reentrant { + char __xdata *__idata *strPP = (char __xdata *__idata *)data; + char ch = data >> 24; + + *(*strPP)++ = ch; } -void spr(char __xdata* out, const char __code *fmt, ...) __reentrant -{ - char __xdata* outStart = out; - - va_list vl; - - va_start(vl, fmt); - prvPrintFormat(prPrvPutS, (uint16_t)&out, fmt, vl); - va_end(vl); - - *out = 0; -} +void spr(char __xdata *out, const char __code *fmt, ...) __reentrant { + char __xdata *outStart = out; + va_list vl; + + va_start(vl, fmt); + prvPrintFormat(prPrvPutS, (uint16_t)&out, fmt, vl); + va_end(vl); + + *out = 0; +} diff --git a/tag_fw/epd.c b/tag_fw/epd.c index f4334dd4..48388629 100644 --- a/tag_fw/epd.c +++ b/tag_fw/epd.c @@ -66,7 +66,6 @@ extern void dump(uint8_t* __xdata a, uint16_t __xdata l); // remove me when done -static bool __idata epdPr = false; // wheter or not we copy the pr("") output to the EPD static uint8_t __xdata epdCharSize = 1; // character size, 1 or 2 (doubled) static bool __xdata directionY = true; // print direction, X or Y (true) static uint8_t __xdata rbuffer[32]; // used to rotate bits around @@ -303,9 +302,8 @@ void selectLUT(uint8_t lut) { if (SCREEN_WIDTH == 152) { sendCustomLut(lut154, 100); } else { - sendCustomLut(lut154, 70); + sendCustomLut(lutorig, 70); } - return; readLut(); // dump((uint8_t*)&waveform, 96); dump(blockXferBuffer, 512); @@ -524,9 +522,6 @@ static void pushYFontBytesToEPD(uint8_t byte1, uint8_t byte2) { } } void writeCharEPD(uint8_t c) { - if (!epdPr) { - return; - } // Writes a single character to the framebuffer bool empty = true; for (uint8_t i = 0; i < 20; i++) { @@ -611,7 +606,6 @@ void epdPrintBegin(uint16_t x, uint16_t y, bool direction, bool fontsize, bool c memset(rbuffer, 0, 32); } - epdPr = true; if (color) { commandBegin(CMD_WRITE_FB_RED); } else { @@ -625,7 +619,6 @@ void epdPrintEnd() { } } commandEnd(); - epdPr = false; } extern uint8_t __xdata blockXferBuffer[]; diff --git a/tag_fw/epd.h b/tag_fw/epd.h index 5cdb9edf..52c62f46 100644 --- a/tag_fw/epd.h +++ b/tag_fw/epd.h @@ -54,10 +54,12 @@ void ByteDecode(uint8_t byte); void epdPrintBegin(uint16_t x, uint16_t y, bool direction, bool fontsize, bool red); void epdPrintEnd(); - void beginFullscreenImage(); void beginWriteFramebuffer(bool color); void lutTest(); +// for printf.c +void writeCharEPD(uint8_t c); + #endif \ No newline at end of file diff --git a/tag_fw/printf.h b/tag_fw/printf.h index b04e0590..8ca2eea5 100644 --- a/tag_fw/printf.h +++ b/tag_fw/printf.h @@ -19,6 +19,9 @@ #pragma callee_saves pr void pr(const char __code *fmt, ...) __reentrant; +#pragma callee_saves epdpr +void epdpr(const char __code *fmt, ...) __reentrant; + #pragma callee_saves spr void spr(char __xdata* out, const char __code *fmt, ...) __reentrant; diff --git a/tag_fw/soc/radioCommon.h b/tag_fw/soc/radioCommon.h index b38f5186..9c931a86 100644 --- a/tag_fw/soc/radioCommon.h +++ b/tag_fw/soc/radioCommon.h @@ -5,6 +5,10 @@ #include +//radio cfg +#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11 +#define RADIO_NUM_CHANNELS (1) + #define RADIO_MAX_PACKET_LEN (125) //useful payload, not including the crc @@ -20,10 +24,6 @@ #define SHORT_MAC_UNUSED (0x10000000UL) //for radioRxFilterCfg's myShortMac - - - - void radioInit(void); bool radioTx(const void __xdata* packet); //waits for tx end diff --git a/tag_fw/soc/zbs243/uart.c b/tag_fw/soc/zbs243/uart.c index c41514c5..5b0c8199 100644 --- a/tag_fw/soc/zbs243/uart.c +++ b/tag_fw/soc/zbs243/uart.c @@ -12,10 +12,7 @@ void uartInit(void) { UARTSTA = 0x12; // also set the "empty" bit else we wait forever for it to go up } -extern void writeCharEPD(uint8_t c); - void uartTx(uint8_t val) { - writeCharEPD(val); while (!(UARTSTA & (1 << 1))) ; UARTSTA &= ~(1 << 1); diff --git a/tag_fw/userinterface.c b/tag_fw/userinterface.c index 4edfcc6b..42bb44c0 100644 --- a/tag_fw/userinterface.c +++ b/tag_fw/userinterface.c @@ -31,21 +31,21 @@ void showSplashScreen() { setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); selectLUT(1); epdPrintBegin(12, 2, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - pr("Starting!"); + epdpr("Starting!"); epdPrintEnd(); loadRawBitmap(solum, 8, 34, EPD_COLOR_BLACK); loadRawBitmap(hacked, 32, 46, EPD_COLOR_RED); epdPrintBegin(5, 136, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED); - pr("%02X%02X", mSelfMac[7], mSelfMac[6]); - pr("%02X%02X", mSelfMac[5], mSelfMac[4]); - pr("%02X%02X", mSelfMac[3], mSelfMac[2]); - pr("%02X%02X", mSelfMac[1], mSelfMac[0]); + epdpr("%02X%02X", mSelfMac[7], mSelfMac[6]); + epdpr("%02X%02X", mSelfMac[5], mSelfMac[4]); + epdpr("%02X%02X", mSelfMac[3], mSelfMac[2]); + epdpr("%02X%02X", mSelfMac[1], mSelfMac[0]); epdPrintEnd(); epdPrintBegin(2, 120, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); - pr("zbs154v033 %d.%d.%d%s", fwVersion/100, (fwVersion%100)/10, (fwVersion%10),fwVersionSuffix); + epdpr("zbs154v033 %d.%d.%d%s", fwVersion/100, (fwVersion%100)/10, (fwVersion%10),fwVersionSuffix); epdPrintEnd(); draw(); #endif @@ -57,18 +57,18 @@ void showSplashScreen() { setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); epdPrintBegin(0, 295, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - pr("Starting!"); + epdpr("Starting!"); epdPrintEnd(); epdPrintBegin(115, 295, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_RED); - pr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]); - pr(":%02X:%02X", mSelfMac[5], mSelfMac[4]); - pr(":%02X:%02X", mSelfMac[3], mSelfMac[2]); - pr(":%02X:%02X", mSelfMac[1], mSelfMac[0]); + epdpr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]); + epdpr(":%02X:%02X", mSelfMac[5], mSelfMac[4]); + epdpr(":%02X:%02X", mSelfMac[3], mSelfMac[2]); + epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]); epdPrintEnd(); epdPrintBegin(96, 295, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); - pr("zbs29v033 %d.%d.%d%s", fwVersion/100, (fwVersion%100)/10, (fwVersion%10),fwVersionSuffix); + epdpr("zbs29v033 %d.%d.%d%s", fwVersion/100, (fwVersion%100)/10, (fwVersion%10),fwVersionSuffix); epdPrintEnd(); loadRawBitmap(solum, 0, 0, EPD_COLOR_BLACK); @@ -84,27 +84,23 @@ void showSplashScreen() { clearScreen(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); - epdPrintBegin(64, 150, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - pr("TEST"); - epdPrintEnd(); - epdPrintBegin(300, 296, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_RED); - pr("Booting!Y"); - epdPrintEnd(); + epdpr("Booting!Y"); + epdpr(); epdPrintBegin(0, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - pr("BootingX!"); + epdpr("Starting!"); epdPrintEnd(); epdPrintBegin(16, 252, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); - pr("zbs42v033 %d.%d.%d%s", fwVersion/100, (fwVersion%100)/10, (fwVersion%10),fwVersionSuffix); + epdpr("zbs42v033 %d.%d.%d%s", fwVersion/100, (fwVersion%100)/10, (fwVersion%10),fwVersionSuffix); epdPrintEnd(); epdPrintBegin(16, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED); - pr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]); - pr(":%02X:%02X", mSelfMac[5], mSelfMac[4]); - pr(":%02X:%02X", mSelfMac[3], mSelfMac[2]); - pr(":%02X:%02X", mSelfMac[1], mSelfMac[0]); + epdpr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]); + epdpr(":%02X:%02X", mSelfMac[5], mSelfMac[4]); + epdpr(":%02X:%02X", mSelfMac[3], mSelfMac[2]); + epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]); epdPrintEnd(); loadRawBitmap(solum, 256, 10, EPD_COLOR_BLACK); @@ -123,7 +119,7 @@ void showApplyUpdate() { clearScreen(); setColorMode(EPD_MODE_IGNORE, EPD_MODE_NORMAL); epdPrintBegin(8, 60, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - pr("Updating!"); + epdpr("Updating!"); epdPrintEnd(); drawNoWait(); } \ No newline at end of file