From b8ca4e495a810d1cc402f16f3b3ac6c2023c8f74 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 11 Apr 2021 12:53:18 +0200 Subject: [PATCH] added more QR code combinations & generator polygons improved code organization --- GenPoly.asm | 2 +- QRCodeGen.inc | 130 +++++++++++++++++++++++++++++++++++++++------- QRCodeGenDemo.asm | 67 +++++------------------- 3 files changed, 123 insertions(+), 76 deletions(-) diff --git a/GenPoly.asm b/GenPoly.asm index 145fa59..ea8471c 100644 --- a/GenPoly.asm +++ b/GenPoly.asm @@ -4,7 +4,7 @@ BASE_ADR = $f800 -DEGREE = 26 +DEGREE = 28 POLY = $11d ; GF(2^8) is based on 9 bit polynomial ; x^8 + x^4 + x^3 + x^2 + 1 = 0x11d diff --git a/QRCodeGen.inc b/QRCodeGen.inc index d48c904..8564b26 100644 --- a/QRCodeGen.inc +++ b/QRCodeGen.inc @@ -1,3 +1,72 @@ +;=============================================================================== +; Q R C O D E C O N S T A N T S +;=============================================================================== + + IF QR_VERSION = 1 ;{ +QR_SIZE = 21 ; 21x21 QR code +QR_CAPACITY = 26 + IF QR_LEVEL = 0 +QR_DEGREE = 7 ; for version 1, level L QR codes + ENDIF + IF QR_LEVEL = 1 +QR_DEGREE = 10 ; for version 1, level M QR codes + ENDIF + IF QR_LEVEL = 2 +QR_DEGREE = 13 ; for version 1, level Q QR codes + ENDIF + IF QR_LEVEL = 3 +QR_DEGREE = 17 ; for version 1, level H QR codes + ENDIF + ENDIF ;} + + IF QR_VERSION = 2 +QR_SIZE = 25 ; 25x25 QR code +QR_CAPACITY = 44 + IF QR_LEVEL = 0 +QR_DEGREE = 10 ; for version 2, level L QR codes + ENDIF + IF QR_LEVEL = 1 +QR_DEGREE = 16 ; for version 2, level M QR codes + ENDIF + IF QR_LEVEL = 2 +QR_DEGREE = 22 ; for version 2, level Q QR codes + ENDIF + IF QR_LEVEL = 3 +QR_DEGREE = 28 ; for version 2, level H QR codes + ENDIF + ENDIF + + IF QR_VERSION = 3 ;{ +QR_SIZE = 29 ; 29x29 QR code +QR_CAPACITY = 70 + IF QR_LEVEL = 0 +QR_DEGREE = 15 ; for version 3, level L QR codes + ENDIF + IF QR_LEVEL = 1 +QR_DEGREE = 26 ; for version 3, level M QR codes + ENDIF + IF QR_LEVEL = 2 || QR_LEVEL = 3 + ECHO "" + ECHO "ERROR: Version 3, Level", [QR_LEVEL]d, "not supported" + ERR + ENDIF + ENDIF ;} + +QR_MAX_DATA = QR_CAPACITY - QR_DEGREE + +QR_MODE = %0100 ; byte mode +QR_POLY = $11d ; GF(2^8) is based on 9 bit polynomial + ; x^8 + x^4 + x^3 + x^2 + 1 = 0x11d +QR_FORMATS = 15 ; 15 type information bits + +QR_MAX_MSG = QR_MAX_DATA - 2 +QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; 44 + + +;=============================================================================== +; Q R C O D E M A C R O S +;=============================================================================== + ; The following code has been partially converted from the C code of the ; QR code generator found at https://github.com/nayuki/QR-Code-generator @@ -9,15 +78,15 @@ ; memset(result, 0, 16); // done in START_TEXT ; for (int i = dataLen-1; i >= 0; i--) { // Polynomial division - ldx #MAX_DATA-1 + ldx #QR_MAX_DATA-1 .loopI stx .i ; uint8_t factor = data[i] ^ result[degree - 1]; lda msgData,x - eor remainder + DEGREE - 1 + eor remainder + QR_DEGREE - 1 sta .factor ; memmove(&result[1], &result[0], (size_t)(16 - 1) * sizeof(result[0])); - ldx #DEGREE-1 + ldx #QR_DEGREE-1 .loopMove lda remainder-1,x sta remainder,x @@ -27,7 +96,7 @@ lda #0 sta remainder ; for (int j = 16-1; j >= 0; j--) - ldx #DEGREE-1 + ldx #QR_DEGREE-1 .loopJ ; result[j] ^= reedSolomonMultiply(generator[j], factor); lda Generator,x @@ -65,7 +134,7 @@ ; z = (uint8_t)((z << 1) ^ ((z >> 7) * 0x11D)); asl bcc .skipEorPoly - eor #> i) & 1) * x; asl .y @@ -100,7 +169,7 @@ ; ldx #0 ; 2600 code has data in reversed order stx .iBit - lda #TOTAL_LEN-1 + lda #QR_TOTAL-1 sta .iByte ; // Do the funny zigzag scan ; Note: 2600 code has .right1 increased by 1 @@ -356,7 +425,7 @@ ;----------------------------------------------------------- .idx = tmpVars - ldy #NUM_FORMAT-1 + ldy #QR_FORMATS-1 .loopFormat sty .idx cpy #8 @@ -402,20 +471,20 @@ lsr lsr lsr - ora #(MODE << 4) -; (MODE << 4) | (MSG_LEN >> 4) - sta msgData + MAX_DATA - 1 + ora #(QR_MODE << 4) +; (QR_MODE << 4) | (MSG_LEN >> 4) + sta msgData + QR_MAX_DATA - 1 txa asl asl asl asl ; (MSG_LEN << 4) - sta msgData + MAX_DATA - 2 - lda #MAX_DATA - 3 + sta msgData + QR_MAX_DATA - 2 + lda #QR_MAX_DATA - 3 sta msgIdx ; clear the remaining data buffer - ldx #TOTAL_LEN-3 + ldx #QR_TOTAL-3 lda #0 .loopClear sta data,x @@ -450,7 +519,7 @@ IF QR_PADDING .msgLen = tmpVars ; pad with optional filler bytes (QR code works without too) - lda #MAX_MSG - 1 + lda #QR_MAX_MSG - 1 sec sbc .msgLen bcc .noPadding @@ -566,18 +635,22 @@ BitMask .byte $80, $40, $20, $10, $8, $4, $2, $1 Generator ; data in reversed order! - IF DEGREE = 7 + IF QR_DEGREE = 7 .byte $75, $44, $0b, $a4, $9a, $7a, $7f ENDIF - IF DEGREE = 10 + IF QR_DEGREE = 10 .byte $c1, $9d, $71, $5f, $5e, $c7, $6f, $9f .byte $c2, $d8 ENDIF - IF DEGREE = 15 + IF QR_DEGREE = 13 + .byte $87, $84, $53, $2b, $2e, $0d, $34, $11 + .byte $b1, $11, $e3, $49, $89 + ENDIF + IF QR_DEGREE = 15 .byte $1a, $86, $20, $97, $84, $8b, $69, $69 .byte $0a, $4a, $70, $a3, $6f, $c4, $1d ENDIF - IF DEGREE = 16 + IF QR_DEGREE = 16 ; Reed-Solomon ECC generator polynomial for degree 16 ; g(x)=(x+1)(x+?)(x+?^2)(x+?^3)...(x+?^15) ; = x^16+3bx^15+0dx^14+68x^13+bdx^12+44x^11+d1x^10+1e^x9+08x^8 @@ -585,13 +658,30 @@ Generator ; data in reversed order! .byte $3b, $24, $32, $62, $e5, $29, $41, $a3 .byte $08, $1e, $d1, $44, $bd, $68, $0d, $3b ENDIF - IF DEGREE = 26 + IF QR_DEGREE = 17 + .byte $4f, $63, $7d, $35, $55, $86, $8f, $29 + .byte $f9, $53, $c5, $16, $77, $78, $53, $42 + .byte $77 + ENDIF + IF QR_DEGREE = 22 + .byte $f5, $91, $1a, $e6, $da, $56, $fd, $43 + .byte $7b, $1d, $89, $1c, $28, $45, $bd, $13 + .byte $f4, $b6, $b0, $83, $b3, $59 + ENDIF + IF QR_DEGREE = 26 .byte $5e, $2b, $4d, $92, $90, $46, $44, $87 .byte $2a, $e9, $75, $d1, $28, $91, $18, $ce .byte $38, $4d, $98, $c7, $62, $88, $04, $b7 .byte $44, $f6 ENDIF -DEGREE = . - Generator ; verify data + IF QR_DEGREE = 28 + .byte $c5, $3a, $4a, $b0, $93, $79, $64, $b5 + .byte $7f, $e9, $77, $75, $38, $f7, $0c, $a7 + .byte $29, $64, $ae, $67, $96, $d0, $fb, $12 + .byte $0d, $1c, $09, $fc + ENDIF + +QR_DEGREE = . - Generator ; verify data ECHO "QR Code encoding data:", [. - QRCodeData]d, "bytes" _QR_TOTAL SET _QR_TOTAL + . - QRCodeData diff --git a/QRCodeGenDemo.asm b/QRCodeGenDemo.asm index 4cfeb2d..d39005d 100644 --- a/QRCodeGenDemo.asm +++ b/QRCodeGenDemo.asm @@ -34,67 +34,24 @@ BASE_ADR = $f000 NTSC = 1 -; QR Switches +; QR Code Generator Switches QR_VERSION = 2 ; 1, 2 or 3 (TODO 1 and 3) -QR_LEVEL = 1 ; 0 (L) or 1 (M) (TODO Q and H) +QR_LEVEL = 1 ; 0 (L), 1 (M), 2 (Q) and 3 (H) QR_OVERLAP = 1 ; overlaps input and output data to save RAM (0 not tested!) QR_SINGLE_MASK = 0 ; (-156) if 1 uses only 1 of the 8 mask pattern QR_PADDING = 1 ; (+22) add padding bytes - -;=============================================================================== -; C O N S T A N T S -;=============================================================================== - -; QR code constants - IF QR_VERSION = 1 ;{ -QR_SIZE = 21 ; 21x21 QR code - IF QR_LEVEL = 0 -DEGREE = 7 ; for version 1, level L QR codes -MAX_DATA = 17+2 - ELSE -DEGREE = 10 ; for version 1, level M QR codes -MAX_DATA = 14+2 - ENDIF - ENDIF ;} - IF QR_VERSION = 2 -QR_SIZE = 25 ; 25x25 QR code - IF QR_LEVEL = 0 -DEGREE = 10 ; for version 2, level L QR codes -MAX_DATA = 32+2 - ELSE -DEGREE = 16 ; for version 2, level M QR codes -MAX_DATA = 26+2 - ENDIF - ENDIF - IF QR_VERSION = 3 ;{ -QR_SIZE = 29 ; 29x29 QR code - IF QR_LEVEL = 0 -DEGREE = 15 ; for version 3, level L QR codes -MAX_DATA = 53+2 - ELSE -DEGREE = 26 ; for version 3, level M QR codes -MAX_DATA = 42+2 - ENDIF - ENDIF ;} - IF QR_VERSION = 1 || QR_VERSION = 3 ECHO "" ECHO "ERROR: Version", [QR_VERSION]d, "unsupported by demo code" ERR ENDIF -MODE = %0100 ; byte mode -POLY = $11d ; GF(2^8) is based on 9 bit polynomial - ; x^8 + x^4 + x^3 + x^2 + 1 = 0x11d -NUM_FORMAT = 15 ; 15 type information bits - -MAX_MSG = MAX_DATA - 2 -TOTAL_LEN = MAX_DATA + DEGREE ; 44 +;=============================================================================== +; C O N S T A N T S +;=============================================================================== NUM_FIRST = 1 ; left top 9 and bottom 8 bits are fixed! - -; other constants RND_EOR_VAL = $b4 _QR_TOTAL SET 0 @@ -119,14 +76,14 @@ msgIdx = tmpVars + 3 qrPattern .byte ENDIF ;--------------------------------------- -data ds TOTAL_LEN ; 44 bytes -remainder = data ; (DEGREE = 16 bytes) -msgData = data + DEGREE ; (MAX_DATA = 28 bytes) +data ds QR_TOTAL ; 44 bytes +remainder = data ; (QR_DEGREE = 16 bytes) +msgData = data + QR_DEGREE ; (QR_MAX_DATA = 28 bytes) ;- - - - - - - - - - - - - - - - - - - - ; The QR code overlaps the data! It overwrites the data while being drawn. IF QR_OVERLAP qrCodeLst = data + 6 ; all but 6 bytes overlap (version 2 only!) - ds NUM_FIRST + QR_SIZE*3 - TOTAL_LEN + 6 ; 38 bytes + ds NUM_FIRST + QR_SIZE*3 - QR_TOTAL + 6 ; 38 bytes ELSE qrCodeLst ds NUM_FIRST + QR_SIZE*3 ; 76 bytes ENDIF @@ -134,7 +91,7 @@ grp0LLst = qrCodeLst + QR_SIZE * 0 firstMsl = qrCodeLst + QR_SIZE * 1 grp1Lst = qrCodeLst + NUM_FIRST + QR_SIZE * 1 grp0RLst = qrCodeLst + NUM_FIRST + QR_SIZE * 2 -QR_LST_SIZE = . - qrCodeLst +CODE_LST_SIZE = . - qrCodeLst ;--------------------------------------- ; QR code total = 89/127 bytes @@ -188,7 +145,7 @@ QR_LST_SIZE = . - qrCodeLst ;----------------------------------------------------------- MAC _BLACK_FUNC ;----------------------------------------------------------- - ldx #QR_LST_SIZE-1 + ldx #CODE_LST_SIZE-1 .loopBlack lda BlackGfx,x sta qrCodeLst,x @@ -235,7 +192,7 @@ QR_LST_SIZE = . - qrCodeLst ;----------------------------------------------------------- MAC _DRAW_FUNC ;----------------------------------------------------------- - ldx #QR_LST_SIZE-1 + ldx #CODE_LST_SIZE-1 .loopBlack lda qrCodeLst,x ora BlackGfx,x