From 46dac909ef16617e2104fd62f418ca0e3d67c940 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 22 Sep 2022 15:49:19 +0200 Subject: [PATCH] vm/math.p8: complete the sin and cos routines --- compiler/res/prog8lib/virtual/math.p8 | 74 ++++++++++++++- compiler/res/prog8lib/virtual/syslib.p8 | 7 ++ compiler/res/version.txt | 2 +- docs/source/todo.rst | 2 - examples/cx16/sincos.p8 | 12 +-- examples/vm/sincos.p8 | 117 ++++++++++++++++++++++++ 6 files changed, 201 insertions(+), 13 deletions(-) create mode 100644 examples/vm/sincos.p8 diff --git a/compiler/res/prog8lib/virtual/math.p8 b/compiler/res/prog8lib/virtual/math.p8 index 00882523a..317402ea5 100644 --- a/compiler/res/prog8lib/virtual/math.p8 +++ b/compiler/res/prog8lib/virtual/math.p8 @@ -44,11 +44,49 @@ math { } sub sin8(ubyte angle) -> byte { - return 42 ; TODO + ubyte[256] sintab = [ + $00, $03, $06, $09, + $0c, $0f, $12, $15, $18, $1b, $1e, $21, $24, $27, $2a, $2d, $30, $33, $36, $39, + $3b, $3e, $41, $43, $46, $49, $4b, $4e, $50, $52, $55, $57, $59, $5b, $5e, $60, + $62, $64, $66, $67, $69, $6b, $6c, $6e, $70, $71, $72, $74, $75, $76, $77, $78, + $79, $7a, $7b, $7b, $7c, $7d, $7d, $7e, $7e, $7e, $7e, $7e, $7f, $7e, $7e, $7e, + $7e, $7e, $7d, $7d, $7c, $7b, $7b, $7a, $79, $78, $77, $76, $75, $74, $72, $71, + $70, $6e, $6c, $6b, $69, $67, $66, $64, $62, $60, $5e, $5b, $59, $57, $55, $52, + $50, $4e, $4b, $49, $46, $43, $41, $3e, $3b, $39, $36, $33, $30, $2d, $2a, $27, + $24, $21, $1e, $1b, $18, $15, $12, $0f, $0c, $09, $06, $03, $00, $fd, $fa, $f7, + $f4, $f1, $ee, $eb, $e8, $e5, $e2, $df, $dc, $d9, $d6, $d3, $d0, $cd, $ca, $c7, + $c5, $c2, $bf, $bd, $ba, $b7, $b5, $b2, $b0, $ae, $ab, $a9, $a7, $a5, $a2, $a0, + $9e, $9c, $9a, $99, $97, $95, $94, $92, $90, $8f, $8e, $8c, $8b, $8a, $89, $88, + $87, $86, $85, $85, $84, $83, $83, $82, $82, $82, $82, $82, $81, $82, $82, $82, + $82, $82, $83, $83, $84, $85, $85, $86, $87, $88, $89, $8a, $8b, $8c, $8e, $8f, + $90, $92, $94, $95, $97, $99, $9a, $9c, $9e, $a0, $a2, $a5, $a7, $a9, $ab, $ae, + $b0, $b2, $b5, $b7, $ba, $bd, $bf, $c2, $c5, $c7, $ca, $cd, $d0, $d3, $d6, $d9, + $dc, $df, $e2, $e5, $e8, $eb, $ee, $f1, $f4, $f7, $fa, $fd + ] + return sintab[angle] as byte } sub cos8(ubyte angle) -> byte { - return 42 ; TODO + ubyte[256] costab = [ + $7f, $7e, $7e, $7e, + $7e, $7e, $7d, $7d, $7c, $7b, $7b, $7a, $79, $78, $77, $76, $75, $74, $72, $71, + $70, $6e, $6c, $6b, $69, $67, $66, $64, $62, $60, $5e, $5b, $59, $57, $55, $52, + $50, $4e, $4b, $49, $46, $43, $41, $3e, $3b, $39, $36, $33, $30, $2d, $2a, $27, + $24, $21, $1e, $1b, $18, $15, $12, $0f, $0c, $09, $06, $03, $00, $fd, $fa, $f7, + $f4, $f1, $ee, $eb, $e8, $e5, $e2, $df, $dc, $d9, $d6, $d3, $d0, $cd, $ca, $c7, + $c5, $c2, $bf, $bd, $ba, $b7, $b5, $b2, $b0, $ae, $ab, $a9, $a7, $a5, $a2, $a0, + $9e, $9c, $9a, $99, $97, $95, $94, $92, $90, $8f, $8e, $8c, $8b, $8a, $89, $88, + $87, $86, $85, $85, $84, $83, $83, $82, $82, $82, $82, $82, $81, $82, $82, $82, + $82, $82, $83, $83, $84, $85, $85, $86, $87, $88, $89, $8a, $8b, $8c, $8e, $8f, + $90, $92, $94, $95, $97, $99, $9a, $9c, $9e, $a0, $a2, $a5, $a7, $a9, $ab, $ae, + $b0, $b2, $b5, $b7, $ba, $bd, $bf, $c2, $c5, $c7, $ca, $cd, $d0, $d3, $d6, $d9, + $dc, $df, $e2, $e5, $e8, $eb, $ee, $f1, $f4, $f7, $fa, $fd, $00, $03, $06, $09, + $0c, $0f, $12, $15, $18, $1b, $1e, $21, $24, $27, $2a, $2d, $30, $33, $36, $39, + $3b, $3e, $41, $43, $46, $49, $4b, $4e, $50, $52, $55, $57, $59, $5b, $5e, $60, + $62, $64, $66, $67, $69, $6b, $6c, $6e, $70, $71, $72, $74, $75, $76, $77, $78, + $79, $7a, $7b, $7b, $7c, $7d, $7d, $7e, $7e, $7e, $7e, $7e + ] + return costab[angle] as byte } sub sinr8u(ubyte radians) -> ubyte { @@ -86,11 +124,39 @@ math { } sub sinr8(ubyte radians) -> byte { - return 42 ; TODO + ubyte[180] sintab = [ + $00, $04, $08, $0d, + $11, $16, $1a, $1e, $23, $27, $2b, $2f, $33, $37, $3b, $3f, $43, $47, $4a, $4e, + $51, $54, $58, $5b, $5e, $61, $64, $66, $69, $6b, $6d, $70, $72, $74, $75, $77, + $78, $7a, $7b, $7c, $7d, $7d, $7e, $7e, $7e, $7f, $7e, $7e, $7e, $7d, $7d, $7c, + $7b, $7a, $78, $77, $75, $74, $72, $70, $6d, $6b, $69, $66, $64, $61, $5e, $5b, + $58, $54, $51, $4e, $4a, $47, $43, $3f, $3b, $37, $33, $2f, $2b, $27, $23, $1e, + $1a, $16, $11, $0d, $08, $04, $00, $fc, $f8, $f3, $ef, $ea, $e6, $e2, $dd, $d9, + $d5, $d1, $cd, $c9, $c5, $c1, $bd, $b9, $b6, $b2, $af, $ac, $a8, $a5, $a2, $9f, + $9c, $9a, $97, $95, $93, $90, $8e, $8c, $8b, $89, $88, $86, $85, $84, $83, $83, + $82, $82, $82, $81, $82, $82, $82, $83, $83, $84, $85, $86, $88, $89, $8b, $8c, + $8e, $90, $93, $95, $97, $9a, $9c, $9f, $a2, $a5, $a8, $ac, $af, $b2, $b6, $b9, + $bd, $c1, $c5, $c9, $cd, $d1, $d5, $d9, $dd, $e2, $e6, $ea, $ef, $f3, $f8, $fc + ] + return sintab[radians] as byte } sub cosr8(ubyte radians) -> byte { - return 42 ; TODO + ubyte[180] costab = [ + $7f, $7e, $7e, $7e, $7d, $7d, $7c, + $7b, $7a, $78, $77, $75, $74, $72, $70, $6d, $6b, $69, $66, $64, $61, $5e, $5b, + $58, $54, $51, $4e, $4a, $47, $43, $3f, $3b, $37, $33, $2f, $2b, $27, $23, $1e, + $1a, $16, $11, $0d, $08, $04, $00, $fc, $f8, $f3, $ef, $ea, $e6, $e2, $dd, $d9, + $d5, $d1, $cd, $c9, $c5, $c1, $bd, $b9, $b6, $b2, $af, $ac, $a8, $a5, $a2, $9f, + $9c, $9a, $97, $95, $93, $90, $8e, $8c, $8b, $89, $88, $86, $85, $84, $83, $83, + $82, $82, $82, $81, $82, $82, $82, $83, $83, $84, $85, $86, $88, $89, $8b, $8c, + $8e, $90, $93, $95, $97, $9a, $9c, $9f, $a2, $a5, $a8, $ac, $af, $b2, $b6, $b9, + $bd, $c1, $c5, $c9, $cd, $d1, $d5, $d9, $dd, $e2, $e6, $ea, $ef, $f3, $f8, $fc, + $00, $04, $08, $0d, $11, $16, $1a, $1e, $23, $27, $2b, $2f, $33, $37, $3b, $3f, + $43, $47, $4a, $4e, $51, $54, $58, $5b, $5e, $61, $64, $66, $69, $6b, $6d, $70, + $72, $74, $75, $77, $78, $7a, $7b, $7c, $7d, $7d, $7e, $7e, $7e + ] + return costab[radians] as byte } } diff --git a/compiler/res/prog8lib/virtual/syslib.p8 b/compiler/res/prog8lib/virtual/syslib.p8 index f2ab7d541..2734a6b5b 100644 --- a/compiler/res/prog8lib/virtual/syslib.p8 +++ b/compiler/res/prog8lib/virtual/syslib.p8 @@ -87,6 +87,13 @@ sys { }} } + sub gfx_clear(ubyte color) { + %asm {{ + loadm.b r0,sys.gfx_clear.color + syscall 9 + }} + } + sub gfx_plot(uword xx, uword yy, ubyte color) { %asm {{ loadm.w r0,sys.gfx_plot.xx diff --git a/compiler/res/version.txt b/compiler/res/version.txt index 6f18ed183..188c40921 100644 --- a/compiler/res/version.txt +++ b/compiler/res/version.txt @@ -1 +1 @@ -8.5-dev +8.5 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 499a55bd8..7a7033704 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,8 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: implement remaining sin/cos functions in virtual/math.p8 and merge tables - ... diff --git a/examples/cx16/sincos.p8 b/examples/cx16/sincos.p8 index 92ea4d1d6..096967658 100644 --- a/examples/cx16/sincos.p8 +++ b/examples/cx16/sincos.p8 @@ -47,9 +47,9 @@ main { for pixelxb in 0 to 255 { pixelys = math.cos8(pixelxb) / 2 - graphics.plot(pixelxb, pixelys+90 as uword) + graphics.plot(pixelxb, pixelys as uword + 90) pixelys = math.sin8(pixelxb) / 2 - graphics.plot(pixelxb, pixelys+90 as uword) + graphics.plot(pixelxb, pixelys as uword + 90) } } @@ -69,9 +69,9 @@ main { for pixelxb in 0 to 179 { pixelys = math.cosr8(pixelxb) / 2 - graphics.plot(pixelxb, pixelys+90 as uword) + graphics.plot(pixelxb, pixelys as uword + 90) pixelys = math.sinr8(pixelxb) / 2 - graphics.plot(pixelxb, pixelys+90 as uword) + graphics.plot(pixelxb, pixelys as uword + 90) } } @@ -82,8 +82,8 @@ main { ; circle with "degrees" from 0 to 255 for r in 0 to 255 { - pixelxw = ((math.sin8(r)/2 as word) + 80) as uword - pixelyb = (math.cos8(r)/2 + height/2) as ubyte + pixelxw = (math.sin8(r)/2 as uword) + 80 + pixelyb = (math.cos8(r)/2 as uword + height/2) as ubyte graphics.plot(pixelxw, pixelyb) } diff --git a/examples/vm/sincos.p8 b/examples/vm/sincos.p8 new file mode 100644 index 000000000..348bc732c --- /dev/null +++ b/examples/vm/sincos.p8 @@ -0,0 +1,117 @@ +%import math +%import textio + +; Draw sine and cosine graphs. The sine and cosine functions are table lookups +; where the tables are generated by 64tass list functions. + +; Note: this program is compatible with CX16 only. +; it doesn't work correctly on C64 because the bitmap screen data overlaps +; the program itself in memory $2000-... + + +main { + const uword width = 320 + const ubyte height = 200 + + sub start() { + sys.gfx_enable(0) ; enable lo res screen + + sincos255() + sys.wait(120) + + sys.gfx_clear(0) + + sincos180() + sys.wait(120) + + sys.gfx_clear(0) + circles() + + repeat { + } + } + + sub sincos255() { + graphics_line(256) + + ubyte pixelyb + ubyte pixelxb + byte pixelys + + for pixelxb in 0 to 255 { + pixelyb = math.cos8u(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelyb+20, 255) + pixelyb = math.sin8u(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelyb+20, 255) + } + + for pixelxb in 0 to 255 { + pixelys = math.cos8(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelys as uword + 90, 255) + pixelys = math.sin8(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelys as uword + 90, 255) + } + } + + sub sincos180() { + graphics_line(180) + + ubyte pixelyb + ubyte pixelxb + byte pixelys + + for pixelxb in 0 to 179 { + pixelyb = math.cosr8u(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelyb+20, 255) + pixelyb = math.sinr8u(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelyb+20, 255) + } + + for pixelxb in 0 to 179 { + pixelys = math.cosr8(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelys as uword + 90, 255) + pixelys = math.sinr8(pixelxb) / 2 + sys.gfx_plot(pixelxb, pixelys as uword + 90, 255) + } + } + + sub circles() { + ubyte pixelyb + uword pixelxw + ubyte r + + ; circle with "degrees" from 0 to 255 + for r in 0 to 255 { + pixelxw = (math.sin8(r)/2 as uword) + 80 + pixelyb = (math.cos8(r)/2 as uword + height/2) as ubyte + sys.gfx_plot(pixelxw, pixelyb, 255) + } + + for r in 0 to 255 { + pixelxw = math.sin8u(r)/2 + pixelyb = math.cos8u(r)/2 + sys.gfx_plot(pixelxw + 16, pixelyb+50, 255) + } + + ; circle with half-degrees from 0 to 179 (=full degrees 0..358 with steps of 2 degrees) + for r in 0 to 179 { + pixelxw = (math.sinr8(r) as word /2 + 220) as uword + pixelyb = (math.cosr8(r)/2 + height/2) as ubyte + sys.gfx_plot(pixelxw, pixelyb, 255) + } + + for r in 0 to 179 { + pixelxw = math.sinr8u(r)/2 + pixelyb = math.cosr8u(r)/2 + sys.gfx_plot(pixelxw + 156, pixelyb+50, 255) + } + } + + sub graphics_line(uword x) { + uword y + for y in 0 to height-1 { + sys.gfx_plot(x, y, 100) + } + } + +}