mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
atan
This commit is contained in:
parent
5da3abe6b4
commit
ff7f3484e4
@ -97,7 +97,7 @@ _sinecosR8 .char trunc(127.0 * sin(range(180+45) * rad(360.0/180.0)))
|
||||
}
|
||||
|
||||
|
||||
sub atan_coarse_sgn(byte x1, byte y1, byte x2, byte y2) -> ubyte {
|
||||
sub direction_sc(byte x1, byte y1, byte x2, byte y2) -> ubyte {
|
||||
; From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23 into A.
|
||||
cx16.r0L = 3 ; quadrant
|
||||
cx16.r1sL = x2-x1 ; xdelta
|
||||
@ -110,10 +110,10 @@ sub atan_coarse_sgn(byte x1, byte y1, byte x2, byte y2) -> ubyte {
|
||||
cx16.r0L-=2
|
||||
cx16.r2sL = -cx16.r2sL
|
||||
}
|
||||
return atan_coarse_qd(cx16.r0L, cx16.r1L, cx16.r2L)
|
||||
return direction_qd(cx16.r0L, cx16.r1L, cx16.r2L)
|
||||
}
|
||||
|
||||
sub atan_coarse(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
sub direction(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
; From a pair of positive coordinates, calculate discrete direction between 0 and 23 into A.
|
||||
cx16.r0L = 3 ; quadrant
|
||||
if x2>=x1 {
|
||||
@ -128,10 +128,10 @@ sub atan_coarse(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
cx16.r2L = y1-y2
|
||||
cx16.r0L -= 2
|
||||
}
|
||||
return atan_coarse_qd(cx16.r0L, cx16.r1L, cx16.r2L)
|
||||
return direction_qd(cx16.r0L, cx16.r1L, cx16.r2L)
|
||||
}
|
||||
|
||||
asmsub atan_coarse_qd(ubyte quadrant @A, ubyte xdelta @X, ubyte ydelta @Y) -> ubyte @A {
|
||||
asmsub direction_qd(ubyte quadrant @A, ubyte xdelta @X, ubyte ydelta @Y) -> ubyte @A {
|
||||
;Arctan https://github.com/dustmop/arctan24
|
||||
; From a pair of X/Y deltas (both >=0), and quadrant 0-3, calculate discrete direction between 0 and 23 into A.
|
||||
; .reg:a @in quadrant Number 0 to 3.
|
||||
@ -269,6 +269,7 @@ y2 = cx16.r3L
|
||||
octant = cx16.r4L ;; temporary zeropage variable
|
||||
|
||||
lda x1
|
||||
sec
|
||||
sbc x2
|
||||
bcs *+4
|
||||
eor #$ff
|
||||
@ -276,6 +277,7 @@ octant = cx16.r4L ;; temporary zeropage variable
|
||||
rol octant
|
||||
|
||||
lda y1
|
||||
sec
|
||||
sbc y2
|
||||
bcs *+4
|
||||
eor #$ff
|
||||
@ -283,6 +285,7 @@ octant = cx16.r4L ;; temporary zeropage variable
|
||||
rol octant
|
||||
|
||||
lda log2_tab,x
|
||||
sec
|
||||
sbc log2_tab,y
|
||||
bcc *+4
|
||||
eor #$ff
|
||||
|
@ -184,43 +184,46 @@ math {
|
||||
}
|
||||
|
||||
|
||||
sub atan_coarse_sgn(byte x1, byte y1, byte x2, byte y2) -> ubyte {
|
||||
; From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23 into A.
|
||||
cx16.r0L = 3 ; quadrant
|
||||
cx16.r1sL = x2-x1 ; xdelta
|
||||
if_neg {
|
||||
cx16.r0L--
|
||||
cx16.r1sL = -cx16.r1sL
|
||||
}
|
||||
cx16.r2sL = y2-y1 ; ydelta
|
||||
if_neg {
|
||||
cx16.r0L-=2
|
||||
cx16.r2sL = -cx16.r2sL
|
||||
}
|
||||
return atan_coarse_qd(cx16.r0L, cx16.r1L, cx16.r2L)
|
||||
}
|
||||
|
||||
sub atan_coarse(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
sub direction(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
; From a pair of positive coordinates, calculate discrete direction between 0 and 23 into A.
|
||||
cx16.r0L = 3 ; quadrant
|
||||
if x2>=x1 {
|
||||
cx16.r1L = x2-x1
|
||||
} else {
|
||||
cx16.r1L = x1-x2
|
||||
cx16.r0L--
|
||||
}
|
||||
if y2>=y1 {
|
||||
cx16.r2L = y2-y1
|
||||
} else {
|
||||
cx16.r2L = y1-y2
|
||||
cx16.r0L -= 2
|
||||
}
|
||||
return atan_coarse_qd(cx16.r0L, cx16.r1L, cx16.r2L)
|
||||
; This adjusts the atan() result so that the direction N is centered on the angle=N instead of having it as a boundary
|
||||
ubyte angle = atan(x1, y1, x2, y2) - 256/48
|
||||
return 23-lsb(mkword(angle,0) / 2730)
|
||||
}
|
||||
|
||||
sub atan_coarse_qd(ubyte quadrant, ubyte xdelta, ubyte ydelta) -> ubyte {
|
||||
sub direction_sc(byte x1, byte y1, byte x2, byte y2) -> ubyte {
|
||||
; From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23 into A.
|
||||
; shift the points into the positive quadrant
|
||||
ubyte px1
|
||||
ubyte py1
|
||||
ubyte px2
|
||||
ubyte py2
|
||||
if x1<0 or x2<0 {
|
||||
px1 = x1 as ubyte + 128
|
||||
px2 = x2 as ubyte + 128
|
||||
} else {
|
||||
px1 = x1 as ubyte
|
||||
px2 = x2 as ubyte
|
||||
}
|
||||
if y1<0 or y2<0 {
|
||||
py1 = y1 as ubyte + 128
|
||||
py2 = y2 as ubyte + 128
|
||||
} else {
|
||||
py1 = y1 as ubyte
|
||||
py2 = y2 as ubyte
|
||||
}
|
||||
|
||||
return direction(px1, py1, px2, py2)
|
||||
}
|
||||
|
||||
sub direction_qd(ubyte quadrant, ubyte xdelta, ubyte ydelta) -> ubyte {
|
||||
; From a pair of X/Y deltas (both >=0), and quadrant 0-3, calculate discrete direction between 0 and 23.
|
||||
return lsb(mkword(atan(0, 0, xdelta, ydelta), 0) / 2730)
|
||||
when quadrant {
|
||||
3 -> return direction(0, 0, xdelta, ydelta)
|
||||
2 -> return direction(xdelta, 0, 0, ydelta)
|
||||
1 -> return direction(0, ydelta, xdelta, 0)
|
||||
else -> return direction(xdelta, ydelta, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
sub atan(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
|
@ -372,21 +372,21 @@ but perhaps the provided ones can be of service too.
|
||||
Fast 8-bit byte cosine of angle 0..179 (each is a 2 degree step), result is in range -127..127
|
||||
Angles 180..255 will yield a garbage result!
|
||||
|
||||
``atan(ubyte x1, ubyte y1, ubyte x2, ubyte y2)``
|
||||
``atan (ubyte x1, ubyte y1, ubyte x2, ubyte y2)``
|
||||
Fast arctan routine that uses more memory because of large lookup tables.
|
||||
Calculate the angle, in a 256-degree circle, between two points in the positive quadrant.
|
||||
|
||||
``atan_coarse_sgn(byte x1, byte y1, byte x2, byte y2)``
|
||||
Small and fast, but imprecise, arctan routine
|
||||
From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23.
|
||||
|
||||
``atan_coarse(ubyte x1, ubyte y1, ubyte x2, ubyte y2)``
|
||||
Small and fast, but imprecise, arctan routine
|
||||
``direction (ubyte x1, ubyte y1, ubyte x2, ubyte y2)``
|
||||
From a pair of positive coordinates, calculate discrete direction between 0 and 23.
|
||||
This is a heavily optimized routine (small and fast).
|
||||
|
||||
``atan_coarse_qd(ubyte quadrant, ubyte xdelta, ubyte ydelta)``
|
||||
Small and fast, but imprecise, arctan routine
|
||||
``direction_sc (byte x1, byte y1, byte x2, byte y2)``
|
||||
From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23.
|
||||
This is a heavily optimized routine (small and fast).
|
||||
|
||||
``direction_qd (ubyte quadrant, ubyte xdelta, ubyte ydelta)``
|
||||
If you already know the quadrant and x/y deltas, calculate discrete direction between 0 and 23.
|
||||
This is a heavily optimized routine (small and fast).
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- vm: fix syscall.ATAN calculation
|
||||
- document some library modules better (diskio, etc)
|
||||
|
||||
...
|
||||
|
@ -2,43 +2,66 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
main {
|
||||
|
||||
const ubyte WIDTH=255
|
||||
const ubyte HEIGHT=240
|
||||
|
||||
sub start() {
|
||||
sys.gfx_enable(0) ; enable lo res screen
|
||||
;; gfx2.screen_mode(4)
|
||||
repeat {
|
||||
|
||||
const ubyte HEIGHT = 30 ; txt.DEFAULT_HEIGHT-1
|
||||
const ubyte WIDTH = 80 ; txt.DEFAULT_WIDTH-1
|
||||
const ubyte HALFWIDTH = 40 ; txt.DEFAULT_WIDTH/2
|
||||
const ubyte HALFHEIGHT = 15 ; txt.DEFAULT_HEIGHT/2
|
||||
ubyte xx
|
||||
ubyte yy
|
||||
|
||||
txt.print_ub(math.atan(0, 0, 10, 20))
|
||||
for yy in 0 to HEIGHT-1 {
|
||||
for xx in 0 to WIDTH-1 {
|
||||
ubyte value = math.direction(WIDTH/2, HEIGHT/2, xx, yy)
|
||||
;; gfx2.plot(xx,yy,value)
|
||||
sys.gfx_plot(xx, yy, value*10)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
;main {
|
||||
;
|
||||
; sub start() {
|
||||
;
|
||||
; const ubyte HEIGHT = txt.DEFAULT_HEIGHT
|
||||
; const ubyte WIDTH = txt.DEFAULT_WIDTH
|
||||
; const ubyte HALFWIDTH = txt.DEFAULT_WIDTH/2
|
||||
; const ubyte HALFHEIGHT = txt.DEFAULT_HEIGHT/2
|
||||
;
|
||||
; ubyte @zp value
|
||||
; ubyte xx
|
||||
; ubyte yy
|
||||
; for yy in 0 to HEIGHT {
|
||||
; for xx in 0 to WIDTH {
|
||||
; value = math.atan(HALFWIDTH, HALFHEIGHT, xx, yy)
|
||||
; txt.setchr(xx,yy,value)
|
||||
; }
|
||||
; }
|
||||
;; for yy in 0 to HEIGHT-1 {
|
||||
;; for xx in 0 to WIDTH-1 {
|
||||
;; value = math.atan(HALFWIDTH, HALFHEIGHT, xx, yy)
|
||||
;; txt.setchr(xx,yy,value)
|
||||
;; }
|
||||
;; }
|
||||
;;
|
||||
;; byte sx
|
||||
;; byte sy
|
||||
;; for sy in -HEIGHT/2 to HEIGHT/2 {
|
||||
;; for sx in -WIDTH/2 to WIDTH/2 {
|
||||
;; value = math.direction_sc(0, 0, sx, sy)
|
||||
;; txt.setchr(sx+WIDTH/2 as ubyte,sy+HEIGHT/2 as ubyte,value)
|
||||
;; }
|
||||
;; }
|
||||
;
|
||||
; byte sx
|
||||
; byte sy
|
||||
; for sy in 0 to HEIGHT as byte {
|
||||
; for sx in 0 to WIDTH as byte {
|
||||
; value = math.atan_coarse_sgn(0, 0, sx-HALFWIDTH, sy-HALFHEIGHT)
|
||||
; txt.setchr(sx as ubyte,sy as ubyte,value)
|
||||
; }
|
||||
; }
|
||||
;
|
||||
; for yy in 0 to HEIGHT {
|
||||
; for xx in 0 to WIDTH {
|
||||
; value = math.atan_coarse(HALFWIDTH, HALFHEIGHT, xx, yy)
|
||||
; for yy in 0 to HEIGHT-1 {
|
||||
; for xx in 0 to WIDTH-1 {
|
||||
; value = math.direction(HALFWIDTH, HALFHEIGHT, xx, yy)
|
||||
; txt.setchr(xx,yy,value)
|
||||
; }
|
||||
; }
|
||||
;
|
||||
; goto start
|
||||
}
|
||||
}
|
||||
; }
|
||||
;}
|
||||
|
@ -3,8 +3,7 @@ package prog8.vm
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.intermediate.FunctionCallArgs
|
||||
import prog8.intermediate.IRDataType
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.*
|
||||
|
||||
/*
|
||||
SYSCALLS:
|
||||
@ -479,12 +478,11 @@ object SysCalls {
|
||||
val y1f = (y1 as UByte).toDouble()
|
||||
val x2f = (x2 as UByte).toDouble()
|
||||
val y2f = (y2 as UByte).toDouble()
|
||||
val xd = x2f-x1f
|
||||
val yd = y2f-y1f
|
||||
TODO("calculate atan the same way as the 6502 routine does 0-255")
|
||||
// val radians = atan2(yd, xd) + PI // 0 to 2*PI
|
||||
// val result = floor(2*PI/radians*256.0)
|
||||
// returnValue(callspec.returns!!, result, vm)
|
||||
var radians = atan2(y2f-y1f, x2f-x1f)
|
||||
if(radians<0)
|
||||
radians+=2*PI
|
||||
val result = floor(radians/2.0/PI*256.0)
|
||||
returnValue(callspec.returns!!, result, vm)
|
||||
}
|
||||
else -> throw AssemblyError("missing syscall ${call.name}")
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ class VmProgramLoader {
|
||||
program.st.allVariables().forEach { variable ->
|
||||
var addr = allocations.allocations.getValue(variable.name)
|
||||
|
||||
// zero out uninitialized variables.
|
||||
// zero out uninitialized ('bss') variables.
|
||||
if(variable.uninitialized) {
|
||||
if(variable.dt in ArrayDatatypes) {
|
||||
repeat(variable.length!!) {
|
||||
|
Loading…
Reference in New Issue
Block a user