	!to "hamming.prg",cbm
	!convtab scr

	* = $0801
	!byte $0c,$08,$0a,$00,$9e,$32,$30,$36,$31,$00,$00,$00

	dataword = $b0
	tmp = $b3
	parity = $b4
	rxparity = $b5

	lda #'m'
	sta dataword
	lda #'a'
	sta dataword+1
	lda #'t'
	sta dataword+2

	jsr calc_parity
	lda parity
	sta rxparity

	lda #'m'
	eor #$01
	sta dataword
	lda #'a'
	sta dataword+1
	lda #'t'
	sta dataword+2

	jsr calc_parity
	lda parity
	eor rxparity
	beq noerror
	pha

	lda #'m'
	eor #$01
	sta dataword
	lda #'a'
	sta dataword+1
	lda #'t'
	sta dataword+2

	pla
	tax
	jsr correct_word
noerror

	lda dataword+0
	sta $0400
	lda dataword+1
	sta $0401
	lda dataword+2
	sta $0402

loop
	jmp loop

; Correct a bit in the 3-byte dataword. The received parity bits XOR the
; correct ones go in X. Only call this if the XOR is non-zero. If a parity bit
; was corrupted no action is taken.

!zone correct_word
correct_word
	dex
	lda .table,x		; Check which bit the error occured in
	bmi .done			; Negative value means a parity bit, so just return
	tay
	and #$07			; A = corrupt bit number within byte
	tax
	tya
	lsr
	lsr
	lsr
	tay					; Y = byte with corrupt bit
	lda dataword,y
	eor .shift,x		; Invert bit in dataword, and we're done
	sta dataword,y
.done
	rts
.shift
	!byte $01, $02, $04, $08, $10, $20, $40, $80
.table
	!byte $ff
	!byte $ff
	!byte $00
	!byte $ff
	!byte $01
	!byte $02
	!byte $03
	!byte $ff
	!byte $04
	!byte $05
	!byte $06
	!byte $07
	!byte $08
	!byte $09
	!byte $0a
	!byte $ff
	!byte $0b
	!byte $0c
	!byte $0d
	!byte $0e
	!byte $0f
	!byte $10
	!byte $11
	!byte $12
	!byte $13
	!byte $14
	!byte $15
	!byte $16
	!byte $17

; Calculate 5 Hamming code parity bits from the 3-byte word in dataword.
; Upon return, the parity bits are stored in the low 5 bits of parity (and A).
; Note that dataword is destroyed.

!zone calc_parity
calc_parity
	lda dataword+0
	eor #$ff
	sta dataword+0
	lda dataword+1
	eor #$ff
	sta dataword+1
	lda dataword+2
	eor #$ff
	sta dataword+2
	ldx #0
	stx parity
.loop
	lda #0				; 2
	lsr dataword+0		; 7
	sbc #0				; 9		A <- $00 if CF = 1, $ff if CF = 0
	and .table,x		; 13	Only XOR with relevant bits
	eor parity			; 16
	sta parity			; 19

	lda #0
	lsr dataword+1
	sbc #0
	and .table+8,x
	eor parity
	sta parity

	lda #0
	lsr dataword+2
	sbc #0
	and .table+16,x
	eor parity
	sta parity

	inx
	cpx #8
	bne .loop
	rts

.table
	!byte $03
	!byte $05
	!byte $06
	!byte $07
	!byte $09
	!byte $0a
	!byte $0b
	!byte $0c
	!byte $0d
	!byte $0e
	!byte $0f
	!byte $11
	!byte $12
	!byte $13
	!byte $14
	!byte $15
	!byte $16
	!byte $17
	!byte $18
	!byte $19
	!byte $1a
	!byte $1b
	!byte $1c
	!byte $1d


