mirror of
https://github.com/thrust26/6502-QR-code-generator.git
synced 2024-12-27 04:29:36 +00:00
added instructions.txt
refined constants and variables
This commit is contained in:
parent
d387dcc095
commit
8c04c30b55
158
QRCodeGen.inc
158
QRCodeGen.inc
@ -1,8 +1,26 @@
|
||||
;===============================================================================
|
||||
; Q R C O D E C O N S T A N T S
|
||||
; U S E R - D E F I N E D Q R C O D E C O N S T A N T S
|
||||
;===============================================================================
|
||||
|
||||
; Do NOT change these constants!
|
||||
IFNCONST QR_VERSION
|
||||
QR_VERSION = 2 ; 1..3, QR code size (21, 25, 29)
|
||||
ENDIF
|
||||
IFNCONST QR_LEVEL
|
||||
QR_LEVEL = 0 ; 0..4, error correction levels L, M, Q, H
|
||||
ENDIF
|
||||
IFNCONST QR_PADDING
|
||||
QR_PADDING = 1 ; 0|1, add padding bytes add the end of test message text
|
||||
ENDIF
|
||||
IFNCONST QR_GENERATE
|
||||
QR_GENERATE = 0 ; 0|1, generate Reed-Solomon ECC generator polynomial on-the-fly
|
||||
ENDIF
|
||||
|
||||
|
||||
;===============================================================================
|
||||
; C A L C U L A T E D Q R C O D E C O N S T A N T S
|
||||
;===============================================================================
|
||||
|
||||
; Do NOT change the following constants!
|
||||
|
||||
IFNCONST QR_OVERLAP
|
||||
QR_OVERLAP = 0
|
||||
@ -14,8 +32,7 @@ QR_SINGLE_MASK = 0
|
||||
QR_DIRECT_DRAW = 0
|
||||
ENDIF
|
||||
|
||||
IF QR_VERSION = 1 ;{
|
||||
; 21x21 QR code
|
||||
IF QR_VERSION = 1 ; 21x21 QR code
|
||||
IF QR_LEVEL = 0
|
||||
QR_DEGREE = 7 ; for version 1, level L QR codes
|
||||
ENDIF
|
||||
@ -28,10 +45,9 @@ QR_DEGREE = 13 ; for version 1, level Q QR codes
|
||||
IF QR_LEVEL = 3
|
||||
QR_DEGREE = 17 ; for version 1, level H QR codes
|
||||
ENDIF
|
||||
ENDIF ;}
|
||||
ENDIF
|
||||
|
||||
IF QR_VERSION = 2
|
||||
; 25x25 QR code
|
||||
IF QR_VERSION = 2 ; 25x25 QR code
|
||||
IF QR_LEVEL = 0
|
||||
QR_DEGREE = 10 ; for version 2, level L QR codes
|
||||
ENDIF
|
||||
@ -46,8 +62,7 @@ QR_DEGREE = 28 ; for version 2, level H QR codes
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
IF QR_VERSION = 3 ;{
|
||||
; 29x29 QR code
|
||||
IF QR_VERSION = 3 ; 29x29 QR code
|
||||
IF QR_LEVEL = 0
|
||||
QR_DEGREE = 15 ; for version 3, level L QR codes
|
||||
ENDIF
|
||||
@ -59,7 +74,7 @@ QR_DEGREE = 26 ; for version 3, level M QR codes
|
||||
ECHO "ERROR: Version 3, Level", [QR_LEVEL]d, "not supported"
|
||||
ERR
|
||||
ENDIF
|
||||
ENDIF ;}
|
||||
ENDIF
|
||||
|
||||
QR_SIZE = 17 + QR_VERSION * 4
|
||||
|
||||
@ -82,7 +97,16 @@ QR_POLY = $11d ; GF(2^8) is based on 9 bit polynomial
|
||||
QR_FORMATS = 15 ; 15 type information bits
|
||||
|
||||
QR_MAX_MSG = QR_MAX_DATA - 2
|
||||
QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; 44
|
||||
QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; e.g. 44
|
||||
|
||||
|
||||
;===============================================================================
|
||||
; V A R I A B L E S
|
||||
;===============================================================================
|
||||
|
||||
qrRemainder = qrData ; (QR_DEGREE = e.g. 16 bytes)
|
||||
qrMsgData = qrData + QR_DEGREE ; (QR_MAX_DATA = e.g. 28 bytes)
|
||||
qrMsgIdx = qrTmpVars + 3
|
||||
|
||||
|
||||
;===============================================================================
|
||||
@ -100,8 +124,8 @@ QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; 44
|
||||
; Russian peasant multiplication (x * y)
|
||||
; Input: A = x, Y = y
|
||||
; Result: A
|
||||
.x = tmpVars
|
||||
.y = tmpVars+1
|
||||
.x = qrTmpVars
|
||||
.y = qrTmpVars+1
|
||||
|
||||
sta .x
|
||||
sty .y
|
||||
@ -134,8 +158,8 @@ QR_TOTAL = QR_MAX_DATA + QR_DEGREE ; 44
|
||||
; 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
|
||||
.root = qrTmpVars+2
|
||||
.i = qrTmpVars+3
|
||||
|
||||
; memset(qrGenerator, 1, 16);
|
||||
ldx #QR_DEGREE-1
|
||||
@ -188,32 +212,32 @@ RSMult SUBROUTINE
|
||||
;-----------------------------------------------------------
|
||||
MAC _RS_REMAINDER
|
||||
;-----------------------------------------------------------
|
||||
.i = tmpVars+2
|
||||
.factor = tmpVars+3
|
||||
.i = qrTmpVars+2
|
||||
.factor = qrTmpVars+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
|
||||
; uint8_t factor = qrMsgData[i] ^ qrRemainder[degree - 1];
|
||||
lda qrMsgData,x
|
||||
eor qrRemainder + QR_DEGREE - 1
|
||||
sta .factor
|
||||
; memmove(&result[1], &result[0], (size_t)(16 - 1) * sizeof(result[0]));
|
||||
; memmove(&qrRemainder[1], &qrRemainder[0], (size_t)(16 - 1) * sizeof(qrRemainder[0]));
|
||||
ldx #QR_DEGREE-1
|
||||
.loopMove
|
||||
lda remainder-1,x
|
||||
sta remainder,x
|
||||
lda qrRemainder-1,x
|
||||
sta qrRemainder,x
|
||||
dex
|
||||
bne .loopMove
|
||||
; result[0] = 0;
|
||||
; qrRemainder[0] = 0;
|
||||
lda #0
|
||||
sta remainder
|
||||
sta qrRemainder
|
||||
; for (int j = 16-1; j >= 0; j--)
|
||||
ldx #QR_DEGREE-1
|
||||
.loopJ
|
||||
; result[j] ^= reedSolomonMultiply(generator[j], factor);
|
||||
; qrRemainder[j] ^= reedSolomonMultiply(generator[j], factor);
|
||||
ldy .factor
|
||||
IF QR_GENERATE
|
||||
lda qrGenerator,x
|
||||
@ -222,8 +246,8 @@ RSMult SUBROUTINE
|
||||
lda Generator,x
|
||||
_RS_MULT
|
||||
ENDIF
|
||||
eor remainder,x
|
||||
sta remainder,x
|
||||
eor qrRemainder,x
|
||||
sta qrRemainder,x
|
||||
; }
|
||||
dex
|
||||
bpl .loopJ
|
||||
@ -293,12 +317,12 @@ BlackFunc SUBROUTINE
|
||||
DrawPattern SUBROUTINE
|
||||
;---------------------------------------------------------------
|
||||
; Y = index, A = fill
|
||||
.index = tmpVars
|
||||
.width = tmpVars+1
|
||||
.height = tmpVars+2
|
||||
.offset = tmpVars+3
|
||||
.tmpPat = tmpVars+4
|
||||
.fill = tmpVars+5
|
||||
.index = qrTmpVars
|
||||
.width = qrTmpVars+1
|
||||
.height = qrTmpVars+2
|
||||
.offset = qrTmpVars+3
|
||||
.tmpPat = qrTmpVars+4
|
||||
.fill = qrTmpVars+5
|
||||
|
||||
sty .index
|
||||
sta .fill
|
||||
@ -328,10 +352,10 @@ DrawPattern SUBROUTINE
|
||||
.invert
|
||||
jsr InvertPixel
|
||||
.skipInvert
|
||||
iny
|
||||
iny ; x++
|
||||
dec .width
|
||||
bne .loopBit
|
||||
dex
|
||||
dex ; y--
|
||||
ldy .offset
|
||||
iny
|
||||
dec .height
|
||||
@ -353,18 +377,18 @@ DrawPattern SUBROUTINE
|
||||
MAC _DRAW_CODEWORDS
|
||||
;-----------------------------------------------------------
|
||||
; Note: This part has the maximum RAM usage
|
||||
.vert = tmpVars+0
|
||||
.j = tmpVars+1
|
||||
.y = tmpVars+2
|
||||
.vert = qrTmpVars+0
|
||||
.j = qrTmpVars+1
|
||||
.y = qrTmpVars+2
|
||||
IF QR_DIRECT_DRAW
|
||||
.iBit = tmpVars+3
|
||||
.iByte = tmpVars+4
|
||||
.right1 = tmpVars+5
|
||||
.iBit = qrTmpVars+3
|
||||
.iByte = qrTmpVars+4
|
||||
.right1 = qrTmpVars+5
|
||||
ELSE
|
||||
; must not overlap with DrawPattern space
|
||||
.iBit = tmpVars+6
|
||||
.iByte = tmpVars+7
|
||||
.right1 = tmpVars+8
|
||||
.iBit = qrTmpVars+6
|
||||
.iByte = qrTmpVars+7
|
||||
.right1 = qrTmpVars+8
|
||||
ENDIF
|
||||
|
||||
; blacken the (right) function modules in the bitmap
|
||||
@ -441,9 +465,9 @@ DrawPattern SUBROUTINE
|
||||
ldx .y
|
||||
jsr CheckPixel
|
||||
bne .skipPixel
|
||||
; bool black = getBit(data[i >> 3], 7 - (i & 7));
|
||||
; bool black = getBit(qrData[i >> 3], 7 - (i & 7));
|
||||
ldx .iByte
|
||||
lda data,x
|
||||
lda qrData,x
|
||||
ldx .iBit
|
||||
and BitMask,x
|
||||
beq .skipInv
|
||||
@ -485,7 +509,7 @@ DrawPattern SUBROUTINE
|
||||
MAC _APPLY_MASK
|
||||
;-----------------------------------------------------------
|
||||
IF QR_SINGLE_MASK
|
||||
.y = tmpVars
|
||||
.y = qrTmpVars
|
||||
ldx #QR_SIZE - 1
|
||||
.loopY
|
||||
stx .y
|
||||
@ -503,12 +527,12 @@ DrawPattern SUBROUTINE
|
||||
dex
|
||||
bpl .loopY
|
||||
ELSE
|
||||
.y = tmpVars
|
||||
;.x = tmpVars+2
|
||||
.xMod3 = tmpVars+1
|
||||
.yMod3 = tmpVars+2
|
||||
.xDiv3 = tmpVars+3
|
||||
.tmp = tmpVars+4
|
||||
.y = qrTmpVars
|
||||
;.x = qrTmpVars+2
|
||||
.xMod3 = qrTmpVars+1
|
||||
.yMod3 = qrTmpVars+2
|
||||
.xDiv3 = qrTmpVars+3
|
||||
.tmp = qrTmpVars+4
|
||||
|
||||
lda #0
|
||||
sta .yMod3
|
||||
@ -641,7 +665,7 @@ DrawPattern SUBROUTINE
|
||||
MAC _DRAW_FORMAT
|
||||
;-----------------------------------------------------------
|
||||
IF QR_SINGLE_MASK = 0 || QR_DIRECT_DRAW = 0
|
||||
.idx = tmpVars
|
||||
.idx = qrTmpVars
|
||||
|
||||
ldy #QR_FORMATS-1
|
||||
.loopFormat
|
||||
@ -689,21 +713,21 @@ DrawPattern SUBROUTINE
|
||||
lsr
|
||||
ora #(QR_MODE << 4)
|
||||
; (QR_MODE << 4) | (MSG_LEN >> 4)
|
||||
sta msgData + QR_MAX_DATA - 1
|
||||
sta qrMsgData + QR_MAX_DATA - 1
|
||||
txa
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
; (MSG_LEN << 4)
|
||||
sta msgData + QR_MAX_DATA - 2
|
||||
sta qrMsgData + QR_MAX_DATA - 2
|
||||
lda #QR_MAX_DATA - 3
|
||||
sta msgIdx
|
||||
sta qrMsgIdx
|
||||
; clear the remaining data buffer
|
||||
ldx #QR_TOTAL-3
|
||||
lda #0
|
||||
.loopClear
|
||||
sta data,x
|
||||
sta qrData,x
|
||||
dex
|
||||
bpl .loopClear
|
||||
ENDM
|
||||
@ -712,28 +736,28 @@ DrawPattern SUBROUTINE
|
||||
MAC ADD_MSG_BYTE
|
||||
;---------------------------------------------------------------
|
||||
; A = byte to add
|
||||
ldx msgIdx
|
||||
ldx qrMsgIdx
|
||||
pha
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
ora msgData + 1,x
|
||||
sta msgData + 1,x
|
||||
ora qrMsgData + 1,x
|
||||
sta qrMsgData + 1,x
|
||||
pla
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
sta msgData,x
|
||||
dec msgIdx
|
||||
sta qrMsgData,x
|
||||
dec qrMsgIdx
|
||||
ENDM
|
||||
|
||||
;-----------------------------------------------------------
|
||||
MAC STOP_MSG
|
||||
;-----------------------------------------------------------
|
||||
IF QR_PADDING
|
||||
.msgLen = tmpVars
|
||||
.msgLen = qrTmpVars
|
||||
; pad with optional filler bytes (QR code works without too)
|
||||
lda #QR_MAX_MSG - 1
|
||||
sec
|
||||
@ -742,11 +766,11 @@ DrawPattern SUBROUTINE
|
||||
tax
|
||||
.loopPadding
|
||||
lda #$ec ; defined by QR standard
|
||||
sta msgData,x
|
||||
sta qrMsgData,x
|
||||
dex
|
||||
bmi .noPadding
|
||||
lda #$11 ; defined by QR standard
|
||||
sta msgData,x
|
||||
sta qrMsgData,x
|
||||
dex
|
||||
bpl .loopPadding
|
||||
.noPadding
|
||||
|
@ -88,19 +88,16 @@ random .byte
|
||||
; QR code variables
|
||||
; all byte counts based on version 2, level M QR code
|
||||
IF QR_DIRECT_DRAW
|
||||
tmpVars ds 6
|
||||
qrTmpVars ds 6
|
||||
ELSE
|
||||
tmpVars ds 9
|
||||
qrTmpVars ds 9
|
||||
ENDIF
|
||||
|
||||
msgIdx = tmpVars + 3
|
||||
IF QR_SINGLE_MASK = 0
|
||||
qrPattern .byte
|
||||
ENDIF
|
||||
;---------------------------------------
|
||||
data ds QR_TOTAL ; 44 bytes
|
||||
remainder = data ; (QR_DEGREE = 16 bytes)
|
||||
msgData = data + QR_DEGREE ; (QR_MAX_DATA = 28 bytes)
|
||||
qrData ds QR_TOTAL ; 44 bytes
|
||||
;- - - - - - - - - - - - - - - - - - - -
|
||||
; The QR code overlaps the data! It overwrites the data while being drawn.
|
||||
IF QR_OVERLAP
|
||||
@ -109,7 +106,7 @@ QR_NON_OVER = 6
|
||||
ELSE
|
||||
QR_NON_OVER = 8
|
||||
ENDIF
|
||||
qrCodeLst = data + QR_NON_OVER ; all but 6/8 bytes overlap (version 2 only!)
|
||||
qrCodeLst = qrData + QR_NON_OVER ; all but 6/8 bytes overlap (version 2 only!)
|
||||
ds NUM_FIRST + QR_SIZE*3 - QR_TOTAL + QR_NON_OVER ; 38/40 bytes
|
||||
ELSE
|
||||
qrCodeLst ds NUM_FIRST + QR_SIZE*3 ; 76 bytes
|
||||
@ -120,7 +117,7 @@ grp1Lst = qrCodeLst + NUM_FIRST + QR_SIZE * 1
|
||||
grp0RLst = qrCodeLst + NUM_FIRST + QR_SIZE * 2
|
||||
CODE_LST_SIZE = . - qrCodeLst
|
||||
IF QR_GENERATE
|
||||
qrGenerator ds QR_DEGREE
|
||||
qrGenerator = . - QR_DEGREE
|
||||
ENDIF
|
||||
;---------------------------------------
|
||||
; QR code total = 89/127 bytes
|
||||
@ -333,7 +330,7 @@ DrawScreen SUBROUTINE
|
||||
sta VBLANK
|
||||
stx TIM64T
|
||||
;---------------------------------------------------------------
|
||||
.tmpFirst = tmpVars
|
||||
.tmpFirst = qrTmpVars
|
||||
|
||||
IF QR_SPRITE_GFX
|
||||
BLOCK_H = 2
|
||||
@ -600,8 +597,8 @@ GenerateQR SUBROUTINE
|
||||
|
||||
MessageCode
|
||||
; convert the message into a data stream
|
||||
.msgLen = tmpVars
|
||||
.msgPtr = tmpVars+1
|
||||
.msgLen = qrTmpVars
|
||||
.msgPtr = qrTmpVars+1
|
||||
lda random
|
||||
lsr
|
||||
lsr
|
||||
@ -639,7 +636,7 @@ _QR_TOTAL SET _QR_TOTAL + . - MessageCode
|
||||
; |PF0 | PF1 | PF2 |PF0 | PF1 | PF2 |
|
||||
; | |7......0|0......7|4..7|7......0| |
|
||||
; |....|...XXXXX|XXXXXXXX|XXXX|XXXXXXXX|........|
|
||||
.tmpLeft = tmpVars
|
||||
.tmpLeft = qrTmpVars
|
||||
|
||||
ldx #QR_SIZE-1
|
||||
.loopRows
|
||||
@ -857,7 +854,7 @@ Message14
|
||||
Message15
|
||||
.byte "1996 - Stella Emulator"
|
||||
MessageEnd
|
||||
; .byte "..the single hardest thing"
|
||||
; .byte "the single hardest thing.."
|
||||
|
||||
MessagePtrLo
|
||||
.byte <Message0, <Message1, <Message2, <Message3
|
||||
|
36
instructions.txt
Normal file
36
instructions.txt
Normal file
@ -0,0 +1,36 @@
|
||||
6502 QR Code Generator - (C)2021 Thomas Jentzsch
|
||||
|
||||
Instructions:
|
||||
|
||||
1. Include QRCodeGen.inc into the code area of your own code
|
||||
|
||||
2. Define the following constants:
|
||||
- QR_VERSION = 1..3 ; QR code size (21, 25, 29)
|
||||
- QR_LEVEL = 0..3 ; error correction levels L, M, Q, H
|
||||
- QR_PADDING = 0|1 ; add padding bytes add the end of test message text
|
||||
- QR_GENERATE = 0|1 ; generate Reed-Solomon ECC generator polynomial on-the-fly
|
||||
; else use built-in table
|
||||
|
||||
3. Define memory for code generation and displayed bitmap:
|
||||
- qrTmpVars ds 9
|
||||
- qrData ds QR_TOTAL
|
||||
- qrPattern ds 1
|
||||
- qrGenerator ds QR_DEGREE (only required if QR_GENERATE = 1)
|
||||
- bitmap depends on platform
|
||||
|
||||
4. Implement two subroutines:
|
||||
- GetPixel: checks the pixel at position x (Y), y (X), returns Z = 1 if not set
|
||||
- InvertPixel: inverts the pixel at position x (Y), y (X)
|
||||
|
||||
5. Add the macros GEN_QR_CODE and QR_CODE_DATA to your code area
|
||||
|
||||
6. Add message text using the START_MSG, n x ADD_MSG_BYTE, STOP_MSG
|
||||
|
||||
7. Set qrPattern to 0..15 (chosing a mask pattern)
|
||||
|
||||
8. Call the GEN_QR_CODE macro
|
||||
|
||||
9. Draw the generated QR code bitmap
|
||||
|
||||
That's all! :)
|
||||
|
Loading…
Reference in New Issue
Block a user