1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-08-08 13:25:12 +00:00
Files
kickc/src/test/ref/sinusgen8.asm
2019-04-02 02:28:13 -04:00

439 lines
8.0 KiB
NASM

.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// PI*2 in u[4.12] format
.const PI2_u4f12 = $6488
// PI in u[4.12] format
.const PI_u4f12 = $3244
// PI/2 in u[4.12] format
.const PI_HALF_u4f12 = $1922
.label print_line_cursor = $400
.label rem16u = 2
.label print_char_cursor = 5
main: {
.label wavelength = $c0
.label sb = 4
jsr sin8s_gen
jsr print_cls
lda #<print_line_cursor
sta print_char_cursor
lda #>print_line_cursor
sta print_char_cursor+1
ldx #0
b1:
lda sintab2,x
sec
sbc sintabref,x
sta sb
bmi b2
lda #<str1
sta print_str.str
lda #>str1
sta print_str.str+1
jsr print_str
b2:
jsr print_sbyte
lda #<str
sta print_str.str
lda #>str
sta print_str.str+1
jsr print_str
inx
cpx #$c0
bne b1
rts
str: .text " @"
str1: .text " @"
sintab2: .fill $c0, 0
// .fill $c0, round(127.5*sin(i*2*PI/$c0))
sintabref: .byte 0, 4, 8, $c, $11, $15, $19, $1d, $21, $25, $29, $2d, $31, $35, $38, $3c, $40, $43, $47, $4a, $4e, $51, $54, $57, $5a, $5d, $60, $63, $65, $68, $6a, $6c, $6e, $70, $72, $74, $76, $77, $79, $7a, $7b, $7c, $7d, $7e, $7e, $7f, $7f, $7f, $80, $7f, $7f, $7f, $7e, $7e, $7d, $7c, $7b, $7a, $79, $77, $76, $74, $72, $70, $6e, $6c, $6a, $68, $65, $63, $60, $5d, $5a, $57, $54, $51, $4e, $4a, $47, $43, $40, $3c, $38, $35, $31, $2d, $29, $25, $21, $1d, $19, $15, $11, $c, 8, 4, 0, $fc, $f8, $f4, $ef, $eb, $e7, $e3, $df, $db, $d7, $d3, $cf, $cb, $c8, $c4, $c0, $bd, $b9, $b6, $b2, $af, $ac, $a9, $a6, $a3, $a0, $9d, $9b, $98, $96, $94, $92, $90, $8e, $8c, $8a, $89, $87, $86, $85, $84, $83, $82, $82, $81, $81, $81, $81, $81, $81, $81, $82, $82, $83, $84, $85, $86, $87, $89, $8a, $8c, $8e, $90, $92, $94, $96, $98, $9b, $9d, $a0, $a3, $a6, $a9, $ac, $af, $b2, $b6, $b9, $bd, $c0, $c4, $c8, $cb, $cf, $d3, $d7, $db, $df, $e3, $e7, $eb, $ef, $f4, $f8, $fc
}
// Print a zero-terminated string
// print_str(byte* zeropage(2) str)
print_str: {
.label str = 2
b1:
ldy #0
lda (str),y
cmp #'@'
bne b2
rts
b2:
ldy #0
lda (str),y
sta (print_char_cursor),y
inc print_char_cursor
bne !+
inc print_char_cursor+1
!:
inc str
bne !+
inc str+1
!:
jmp b1
}
// Print a signed byte as HEX
// print_sbyte(signed byte zeropage(4) b)
print_sbyte: {
.label b = 4
lda b
bmi b1
lda #' '
jsr print_char
b2:
jsr print_byte
rts
b1:
lda #'-'
jsr print_char
lda b
eor #$ff
clc
adc #1
sta b
jmp b2
}
// Print a single char
// print_char(byte register(A) ch)
print_char: {
ldy #0
sta (print_char_cursor),y
inc print_char_cursor
bne !+
inc print_char_cursor+1
!:
rts
}
// Print a byte as HEX
print_byte: {
lda print_sbyte.b
lsr
lsr
lsr
lsr
tay
lda print_hextab,y
jsr print_char
lda #$f
and print_sbyte.b
tay
lda print_hextab,y
jsr print_char
rts
}
// Clear the screen. Also resets current line/char cursor.
print_cls: {
.label sc = 2
lda #<print_line_cursor
sta sc
lda #>print_line_cursor
sta sc+1
b1:
lda #' '
ldy #0
sta (sc),y
inc sc
bne !+
inc sc+1
!:
lda sc+1
cmp #>print_line_cursor+$3e8
bne b1
lda sc
cmp #<print_line_cursor+$3e8
bne b1
rts
}
// Generate signed byte sinus table - on the full -$7f - $7f range
// sintab - the table to generate into
// wavelength - the number of sinus points in a total sinus wavelength (the size of the table)
// sin8s_gen(signed byte* zeropage(5) sintab)
sin8s_gen: {
.label step = $e
.label sintab = 5
.label x = 2
.label i = 7
jsr div16u
lda #0
sta i
sta i+1
lda #<main.sintab2
sta sintab
lda #>main.sintab2
sta sintab+1
lda #0
sta x
sta x+1
// u[4.12]
b1:
lda x
sta sin8s.x
lda x+1
sta sin8s.x+1
jsr sin8s
ldy #0
sta (sintab),y
inc sintab
bne !+
inc sintab+1
!:
lda x
clc
adc step
sta x
lda x+1
adc step+1
sta x+1
inc i
bne !+
inc i+1
!:
lda i+1
cmp #>main.wavelength
bcc b1
bne !+
lda i
cmp #<main.wavelength
bcc b1
!:
rts
}
// Calculate signed byte sinus sin(x)
// x: unsigned word input u[4.12] in the interval $0000 - PI2_u4f12
// result: signed byte sin(x) s[0.7] - using the full range -$7f - $7f
// sin8s(word zeropage(9) x)
sin8s: {
// u[2.6] x^3
.const DIV_6 = $2b
.label _4 = 9
.label x = 9
.label x1 = $10
.label x3 = $11
.label usinx = $12
.label isUpper = 4
lda x+1
cmp #>PI_u4f12
bcc b5
bne !+
lda x
cmp #<PI_u4f12
bcc b5
!:
lda x
sec
sbc #<PI_u4f12
sta x
lda x+1
sbc #>PI_u4f12
sta x+1
lda #1
sta isUpper
jmp b1
b5:
lda #0
sta isUpper
b1:
lda x+1
cmp #>PI_HALF_u4f12
bcc b2
bne !+
lda x
cmp #<PI_HALF_u4f12
bcc b2
!:
sec
lda #<PI_u4f12
sbc x
sta x
lda #>PI_u4f12
sbc x+1
sta x+1
b2:
asl _4
rol _4+1
asl _4
rol _4+1
asl _4
rol _4+1
lda _4+1
sta x1
tax
tay
lda #0
sta mulu8_sel.select
jsr mulu8_sel
tax
ldy x1
lda #1
sta mulu8_sel.select
jsr mulu8_sel
sta x3
tax
lda #1
sta mulu8_sel.select
ldy #DIV_6
jsr mulu8_sel
eor #$ff
sec
adc x1
sta usinx
ldx x3
ldy x1
lda #0
sta mulu8_sel.select
jsr mulu8_sel
tax
ldy x1
lda #0
sta mulu8_sel.select
jsr mulu8_sel
lsr
lsr
lsr
lsr
clc
adc usinx
tax
cpx #$80
bcc b3
dex
b3:
lda isUpper
cmp #0
beq b14
txa
eor #$ff
clc
adc #1
rts
b14:
txa
rts
}
// Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result.
// The select parameter indicates how many of the highest bits of the 16-bit result to skip
// mulu8_sel(byte register(X) v1, byte register(Y) v2, byte zeropage($b) select)
mulu8_sel: {
.label _0 = 9
.label _1 = 9
.label select = $b
tya
jsr mul8u
ldy select
beq !e+
!:
asl _1
rol _1+1
dey
bne !-
!e:
lda _1+1
rts
}
// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word
// mul8u(byte register(X) a, byte register(A) b)
mul8u: {
.label mb = $c
.label res = 9
.label return = 9
sta mb
lda #0
sta mb+1
sta res
sta res+1
b1:
cpx #0
bne b2
rts
b2:
txa
and #1
cmp #0
beq b3
lda res
clc
adc mb
sta res
lda res+1
adc mb+1
sta res+1
b3:
txa
lsr
tax
asl mb
rol mb+1
jmp b1
}
// Performs division on two 16 bit unsigned words
// Returns the quotient dividend/divisor.
// The remainder will be set into the global variable rem16u
// Implemented using simple binary division
div16u: {
.label return = $e
jsr divr16u
rts
}
// Performs division on two 16 bit unsigned words and an initial remainder
// Returns the quotient dividend/divisor.
// The final remainder will be set into the global variable rem16u
// Implemented using simple binary division
// divr16u(word zeropage(5) dividend, word zeropage(2) rem)
divr16u: {
.label rem = 2
.label dividend = 5
.label quotient = $e
.label return = $e
ldx #0
txa
sta quotient
sta quotient+1
lda #<PI2_u4f12
sta dividend
lda #>PI2_u4f12
sta dividend+1
txa
sta rem
sta rem+1
b1:
asl rem
rol rem+1
lda dividend+1
and #$80
cmp #0
beq b2
lda #1
ora rem
sta rem
b2:
asl dividend
rol dividend+1
asl quotient
rol quotient+1
lda rem+1
cmp #>main.wavelength
bcc b3
bne !+
lda rem
cmp #<main.wavelength
bcc b3
!:
inc quotient
bne !+
inc quotient+1
!:
lda rem
sec
sbc #<main.wavelength
sta rem
lda rem+1
sbc #>main.wavelength
sta rem+1
b3:
inx
cpx #$10
bne b1
rts
}
print_hextab: .text "0123456789abcdef"