diff --git a/man/rgbasm.5 b/man/rgbasm.5 index e751f9ec..e75e36f6 100644 --- a/man/rgbasm.5 +++ b/man/rgbasm.5 @@ -57,8 +57,8 @@ and ending with .Ql */ . It can be split across multiple lines, or occur in the middle of an expression: .Bd -literal -offset indent -X = /* the value of x - should be 3 */ 3 +DEF X = /* the value of x + should be 3 */ 3 .Ed .Pp Sometimes lines can be too long and it may be necessary to split them. @@ -168,20 +168,20 @@ Valid print types are: Examples: .Bd -literal -offset indent SECTION "Test", ROM0[2] -X: ;\ This works with labels **whose address is known** -Y = 3 ;\ This also works with variables -SUM equ X + Y ;\ And likewise with numeric constants +X: ;\ This works with labels **whose address is known** +DEF Y = 3 ;\ This also works with variables +DEF SUM EQU X + Y ;\ And likewise with numeric constants ; Prints "%0010 + $3 == 5" PRINTLN "{#05b:X} + {#x:Y} == {d:SUM}" rsset 32 -PERCENT rb 1 ;\ Same with offset constants -VALUE = 20 -RESULT = MUL(20.0, 0.32) +DEF PERCENT rb 1 ;\ Same with offset constants +DEF VALUE = 20 +DEF RESULT = MUL(20.0, 0.32) ; Prints "32% of 20 = 6.40" PRINTLN "{d:PERCENT}% of {d:VALUE} = {f:RESULT}" -WHO equs STRLWR("WORLD") +DEF WHO EQUS STRLWR("WORLD") ; Prints "Hello world!" PRINTLN "Hello {s:WHO}!" .Ed @@ -350,18 +350,18 @@ The trigonometry functions ( .Ic SIN , .Ic COS , .Ic TAN , -etc) are defined in terms of a circle divided into 65535.0 degrees. +etc) are defined in terms of a circle divided into 1.0 "turns" (equal to 2pi radians or 360 degrees). .Pp These functions are useful for automatic generation of various tables. For example: .Bd -literal -offset indent -; Generate a 256-byte sine table with values in the range [0, 128] -; (shifted and scaled from the range [-1.0, 1.0]) -ANGLE = 0.0 - REPT 256 - db (MUL(64.0, SIN(ANGLE)) + 64.0) >> 16 -ANGLE = ANGLE + 256.0 ; 256.0 = 65536 degrees / 256 entries - ENDR +; Generate a table of sine values from sin(0.0) to sin(1.0), with +; amplitude scaled from [-1.0, 1.0] to [0.0, 128.0] +DEF turns = 0.0 +REPT 256 + db MUL(64.0, SIN(turns) + 1.0) >> 16 + DEF turns += 1.0 / 256 +ENDR .Ed .Ss String expressions The most basic string expression is any number of characters contained in double quotes @@ -1011,7 +1011,7 @@ DEF ARRAY_SIZE EQU 4 DEF COUNT = 2 DEF COUNT = 3 DEF COUNT = ARRAY_SIZE + COUNT -COUNT = COUNT*2 +DEF COUNT *= 2 ;\ COUNT now has the value 14 .Ed .Pp @@ -1753,13 +1753,12 @@ You can also use .Ic REPT to generate tables on the fly: .Bd -literal -offset indent -; Generate a 256-byte sine table with values in the range [0, 128] -; (shifted and scaled from the range [-1.0, 1.0]) -ANGLE = 0.0 - REPT 256 - db (MUL(64.0, SIN(ANGLE)) + 64.0) >> 16 -ANGLE = ANGLE + 256.0 ; 256.0 = 65536 degrees / 256 entries - ENDR +; Generate a table of square values from 0**2 = 0 to 100**2 = 10000 +DEF x = 0 +REPT 101 + dw x * x + DEF x += 1 +ENDR .Ed .Pp As in macros, you can also use the escape sequence diff --git a/src/asm/fixpoint.c b/src/asm/fixpoint.c index 4c12b5da..7c54ed0e 100644 --- a/src/asm/fixpoint.c +++ b/src/asm/fixpoint.c @@ -24,9 +24,9 @@ #define fix2double(i) ((double)((i) / fix_PrecisionFactor())) #define double2fix(d) ((int32_t)round((d) * fix_PrecisionFactor())) -// pi*2 radians == 2**fixPrecision fixed-point "degrees" -#define fdeg2rad(f) ((f) * (M_PI * 2) / fix_PrecisionFactor()) -#define rad2fdeg(r) ((r) * fix_PrecisionFactor() / (M_PI * 2)) +// 2*pi radians == 1 turn +#define turn2rad(f) ((f) * (M_PI * 2)) +#define rad2turn(r) ((r) / (M_PI * 2)) uint8_t fixPrecision; @@ -51,37 +51,37 @@ void fix_Print(int32_t i) int32_t fix_Sin(int32_t i) { - return double2fix(sin(fdeg2rad(fix2double(i)))); + return double2fix(sin(turn2rad(fix2double(i)))); } int32_t fix_Cos(int32_t i) { - return double2fix(cos(fdeg2rad(fix2double(i)))); + return double2fix(cos(turn2rad(fix2double(i)))); } int32_t fix_Tan(int32_t i) { - return double2fix(tan(fdeg2rad(fix2double(i)))); + return double2fix(tan(turn2rad(fix2double(i)))); } int32_t fix_ASin(int32_t i) { - return double2fix(rad2fdeg(asin(fix2double(i)))); + return double2fix(rad2turn(asin(fix2double(i)))); } int32_t fix_ACos(int32_t i) { - return double2fix(rad2fdeg(acos(fix2double(i)))); + return double2fix(rad2turn(acos(fix2double(i)))); } int32_t fix_ATan(int32_t i) { - return double2fix(rad2fdeg(atan(fix2double(i)))); + return double2fix(rad2turn(atan(fix2double(i)))); } int32_t fix_ATan2(int32_t i, int32_t j) { - return double2fix(rad2fdeg(atan2(fix2double(i), fix2double(j)))); + return double2fix(rad2turn(atan2(fix2double(i), fix2double(j)))); } int32_t fix_Mul(int32_t i, int32_t j) diff --git a/test/asm/trigonometry.asm b/test/asm/trigonometry.asm new file mode 100644 index 00000000..e9669fcd --- /dev/null +++ b/test/asm/trigonometry.asm @@ -0,0 +1,38 @@ +for Q, 2, 31 + OPT Q.{d:Q} + + assert sin(0.25) == 1.0 + assert asin(1.0) == 0.25 + + assert sin(0.0) == 0.0 + assert asin(0.0) == 0.0 + + assert cos(0.0) == 1.0 + assert acos(1.0) == 0.0 + + if Q > 2 ; can't represent 0.125 in Q.2 + assert tan(0.125) == 1.0 + assert atan(1.0) == 0.125 + else + assert tan(0.0) == 0.0 + assert atan(0.0) == 0.0 + endc +endr + +SECTION "sine", ROM0[0] +OPT Q.16 +; Generate a table of sine values from sin(0.0) to sin(1.0), with +; amplitude scaled from [-1.0, 1.0] to [0.0, 128.0] +DEF turns = 0.0 +REPT 256 + db MUL(64.0, SIN(turns) + 1.0) >> 16 + DEF turns += 1.0 / 256 +ENDR + + +SECTION "cosine", ROM0[256] +OPT Q.8 +; 32 samples of cos(x) from x=0 to x=pi radians=0.5 turns +for x, 0.0, 0.5, 0.5 / 32 + dw cos(x) +endr diff --git a/test/asm/trigonometry.err b/test/asm/trigonometry.err new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/trigonometry.out b/test/asm/trigonometry.out new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/trigonometry.out.bin b/test/asm/trigonometry.out.bin new file mode 100644 index 00000000..93e41368 Binary files /dev/null and b/test/asm/trigonometry.out.bin differ