added option to generate RS polynomial on-the-fly

This commit is contained in:
thrust26 2021-04-12 16:33:25 +02:00
parent 731550443b
commit d150cbc5af
2 changed files with 125 additions and 47 deletions

View File

@ -78,49 +78,6 @@ QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; 44
; The following code has been partially converted from the C code of the ; 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 ; QR code generator found at https://github.com/nayuki/QR-Code-generator
;-----------------------------------------------------------
MAC _RS_REMAINDER
;-----------------------------------------------------------
.i = tmpVars+2
.factor = tmpVars+3
; memset(result, 0, 16); // done in START_TEXT
; for (int i = dataLen-1; i >= 0; i--) { // Polynomial division
ldx #QR_MAX_DATA-1
.loopI
stx .i
; uint8_t factor = data[i] ^ result[degree - 1];
lda msgData,x
eor remainder + QR_DEGREE - 1
sta .factor
; memmove(&result[1], &result[0], (size_t)(16 - 1) * sizeof(result[0]));
ldx #QR_DEGREE-1
.loopMove
lda remainder-1,x
sta remainder,x
dex
bne .loopMove
; result[0] = 0;
lda #0
sta remainder
; for (int j = 16-1; j >= 0; j--)
ldx #QR_DEGREE-1
.loopJ
; result[j] ^= reedSolomonMultiply(generator[j], factor);
lda Generator,x
ldy .factor
_RS_MULT
eor remainder,x
sta remainder,x
; }
dex
bpl .loopJ
; }
ldx .i
dex
bpl .loopI
ENDM
;----------------------------------------------------------- ;-----------------------------------------------------------
; Returns the product of the two given field elements modulo GF(2^8/0x11D). ; Returns the product of the two given field elements modulo GF(2^8/0x11D).
; All inputs are valid. ; All inputs are valid.
@ -154,6 +111,114 @@ QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; 44
bpl .loopI bpl .loopI
ENDM ENDM
IF QR_GENERATE
; Computes a Reed-Solomon ECC generator polynomial for degree 16, storing in result[0 : 16-1].
; This is implemented as a lookup table too (Generator)
;-----------------------------------------------------------
MAC _RS_DIVISOR
;-----------------------------------------------------------
; E.g. 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
; +A3x^7+41x^6+29x^5+E5x^4+62x^3+32x^2+24x+3B
.root = tmpVars+2
.i = tmpVars+3
; memset(qrGenerator, 1, 16);
ldx #QR_DEGREE-1
stx .i
ldy #0
.loopClear
sty qrGenerator,x
dex
bne .loopClear
; qrGenerator[0] = 1; // Start off with the monomial x^0
iny
sty qrGenerator
; uint8_t root = 1;
sty .root
; for (int i = 0; i < degree; i++) {
.loopI
; // Multiply the current product by (x - r^i)
; for (int j = degree-1; j >= 0; j--) {
ldx #QR_DEGREE-1
.loopJ
; qrGenerator[j] = reedSolomonMultiply(qrGenerator[j], root);
lda qrGenerator,x
ldy .root
jsr RSMult
; if (j)
dex
bmi .skipEor
; qrGenerator[j] ^= qrGenerator[j - 1];
eor qrGenerator,x
.skipEor
sta qrGenerator+1,x
txa
bpl .loopJ
; root = reedSolomonMultiply(root, 0x02);
lda .root
ldy #$02
jsr RSMult
sta .root
dec .i
bpl .loopI
ENDM
;-----------------------------------------------------------
RSMult SUBROUTINE
_RS_MULT
rts
;-----------------------------------------------------------
ENDIF ; /QR_GENERATE
;-----------------------------------------------------------
MAC _RS_REMAINDER
;-----------------------------------------------------------
.i = tmpVars+2
.factor = tmpVars+3
; memset(result, 0, 16); // done in START_TEXT
; for (int i = dataLen-1; i >= 0; i--) { // Polynomial division
ldx #QR_MAX_DATA-1
.loopI
stx .i
; uint8_t factor = data[i] ^ result[degree - 1];
lda msgData,x
eor remainder + QR_DEGREE - 1
sta .factor
; memmove(&result[1], &result[0], (size_t)(16 - 1) * sizeof(result[0]));
ldx #QR_DEGREE-1
.loopMove
lda remainder-1,x
sta remainder,x
dex
bne .loopMove
; result[0] = 0;
lda #0
sta remainder
; for (int j = 16-1; j >= 0; j--)
ldx #QR_DEGREE-1
.loopJ
; result[j] ^= reedSolomonMultiply(generator[j], factor);
ldy .factor
IF QR_GENERATE
lda qrGenerator,x
jsr RSMult
ELSE
lda Generator,x
_RS_MULT
ENDIF
eor remainder,x
sta remainder,x
; }
dex
bpl .loopJ
; }
ldx .i
dex
bpl .loopI
ENDM
;----------------------------------------------------------- ;-----------------------------------------------------------
; Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of ; Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of
; the QR Code to be black at function modules and white at codeword modules (including unused remainder bits). ; the QR Code to be black at function modules and white at codeword modules (including unused remainder bits).
@ -546,6 +611,11 @@ QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; 44
; This is the main macro to use! ; This is the main macro to use!
QRCodeCode QRCodeCode
IF QR_GENERATE
; generate the Reed-Solomon ECC generator polynomial
RSDevisor
_RS_DIVISOR
ENDIF
; calculate the ECC ; calculate the ECC
RSRemainder RSRemainder
_RS_REMAINDER _RS_REMAINDER
@ -677,6 +747,7 @@ FormatX2
BitMask BitMask
.byte $80, $40, $20, $10, $8, $4, $2, $1 .byte $80, $40, $20, $10, $8, $4, $2, $1
IF QR_GENERATE = 0
Generator ; data in reversed order! Generator ; data in reversed order!
IF QR_DEGREE = 7 IF QR_DEGREE = 7
.byte $75, $44, $0b, $a4, $9a, $7a, $7f .byte $75, $44, $0b, $a4, $9a, $7a, $7f
@ -726,6 +797,8 @@ Generator ; data in reversed order!
QR_DEGREE = . - Generator ; verify data size QR_DEGREE = . - Generator ; verify data size
ENDIF ; /QR_GENERATE
ECHO "QR Code encoding data:", [. - QRCodeData]d, "bytes" ECHO "QR Code encoding data:", [. - QRCodeData]d, "bytes"
_QR_TOTAL SET _QR_TOTAL + . - QRCodeData _QR_TOTAL SET _QR_TOTAL + . - QRCodeData

View File

@ -39,11 +39,13 @@ NTSC = 1 ; 0 = PAL50
; QR Code Generator Switches ; QR Code Generator Switches
QR_VERSION = 2 ; 1, 2 or 3 (TODO 1 and 3) QR_VERSION = 2 ; 1, 2 or 3 (TODO 1 and 3)
QR_LEVEL = 1 ; 0 (L), 1 (M), 2 (Q) and 3 (H)) QR_LEVEL = 1 ; 0 (L), 1 (M), 2 (Q) and 3 (H))
QR_PADDING = 1 ; (+22) add padding bytes QR_PADDING = 1 ; (+22 bytes) add padding bytes (optional)
QR_GENERATE = 1 ; (+~12 bytes) generates Reed-Solomon ECC generator polynomial on-the-fly
; else uses built-in table
; Atari 2600 specific QR settings (set to 0 for other platforms) ; Atari 2600 specific QR settings (set to 0 for other platforms)
QR_OVERLAP = 1 ; overlaps input and output data to save RAM (defined for version 2 only!) QR_OVERLAP = 1 ; overlaps input and output data to save RAM (defined for version 2 only!)
QR_SINGLE_MASK = 0 ; (-255) if 1 uses only 1 of the 8 mask pattern QR_SINGLE_MASK = 0 ; (-255 bytes) if 1 uses only 1 of the 8 mask pattern
IF QR_VERSION = 1 || QR_VERSION = 3 IF QR_VERSION = 1 || QR_VERSION = 3
ECHO "" ECHO ""
@ -97,6 +99,9 @@ firstMsl = qrCodeLst + QR_SIZE * 1
grp1Lst = qrCodeLst + NUM_FIRST + QR_SIZE * 1 grp1Lst = qrCodeLst + NUM_FIRST + QR_SIZE * 1
grp0RLst = qrCodeLst + NUM_FIRST + QR_SIZE * 2 grp0RLst = qrCodeLst + NUM_FIRST + QR_SIZE * 2
CODE_LST_SIZE = . - qrCodeLst CODE_LST_SIZE = . - qrCodeLst
IF QR_GENERATE
qrGenerator ds QR_DEGREE
ENDIF
;--------------------------------------- ;---------------------------------------
; QR code total = 89/127 bytes ; QR code total = 89/127 bytes
@ -218,8 +223,6 @@ CODE_LST_SIZE = . - qrCodeLst
ENDIF ENDIF
ENDM ENDM
include QRCodeGen.inc
;=============================================================================== ;===============================================================================
; R O M - C O D E ; R O M - C O D E
@ -308,6 +311,8 @@ DrawScreen SUBROUTINE
rts rts
; DrawScreen ; DrawScreen
include QRCodeGen.inc
;--------------------------------------------------------------- ;---------------------------------------------------------------
Start SUBROUTINE Start SUBROUTINE
;--------------------------------------------------------------- ;---------------------------------------------------------------