605 lines
25 KiB
Markdown
605 lines
25 KiB
Markdown
# TIPS and TRICKS
|
|
|
|
## Constants:
|
|
- The CONST keyword is a thing, it defines the thing following it as a literal thing that either takes up no memory space, (int vars), or is instanced, (strings).
|
|
- Use constants liberally, you can use expressions to evaluate constants making code more readable and easier to understand.
|
|
~~~
|
|
const fontStart = 0
|
|
const boingStart = fontStart + 27
|
|
load sprite, ../../images/gbas/Boing/Boing0.tga, boingStart + 0
|
|
load sprite, ../../images/gbas/Boing/Boing1.tga, boingStart + 1
|
|
|
|
' const allows you to easily reference an instanced copy of a literal string anywhere in your code
|
|
const NAME$ = "Insert Name Here"
|
|
|
|
print NAME$
|
|
if s$ = NAME$ then gosub blah
|
|
~~~
|
|
|
|
## Variables:
|
|
- Integer variable names MUST be alphanumeric, must begin with an alpha char and can use underscores everywhere except for the first and last char.
|
|
- Currently there are 40 int16_t, (2 byte signed integer), fast variables available for program use.
|
|
- These are always global, their lifetime spans from program start to program finish and across gosub subroutines.
|
|
- If you need more variables then you can use arrays, (DIM statement).
|
|
- If you need byte sized variables then you can use the DEF BYTE statement with POKE and PEEK.
|
|
- DEF WORD and DEEK/DOKE can be used as faster versions of arrays inside tight inner loops.
|
|
- Slow variables, (using main non zero page memory), will be added in the future.
|
|
- Local variables, procedures and the ability to easily recurse, *may* be added in the future.
|
|
- You can perform limited recursion right now with careful handling of variables/arrays inside subroutines.
|
|
- Arrays do not use any of page zero or fast variable space, so you may use as many as you like until you run out of RAM.
|
|
|
|
## Strings:
|
|
- String variable names MUST be alphanumeric, must begin with an alpha char, must end with a dollar sign and can use underscores everywhere except for the first and last char.
|
|
- The maximum length of a string is 94 bytes, (this allows the most efficient use of the Gigatron's fragmented memory architecture).
|
|
- Most of the string functions, (LEFT$, RIGHT$, MID$, HEX$, etc), respect the maximum length, but don't assume.
|
|
- You can assign and concatenate strings easily using '=' and '+'.
|
|
- Use STRCMP to compare two strings.
|
|
- Strings have a length byte preamble and a '0' terminator byte epilogue, this extra byte per string makes the runtime smaller and in some cases much faster.
|
|
- When PEEKing/POKEing strings, remember to skip the first length byte.
|
|
- A string length pragma that controls the maximum length of strings will be added at a future date.
|
|
- Constant/literal strings are instanced where possible, e.g. if you reference a space, " ", in multiple locations within your code there will only be 1 byte allocated for that space in memory.
|
|
- If you need non instanced copies of a string, then use string variables to represent that string, not constants or literals.
|
|
- String variables do not use any of page zero or fast variable space, so you may use as many as you like until you run out of RAM.
|
|
|
|
## Input:
|
|
- There are no INKEY or GETKEY funtions as it is trivial to perform any type of key/button processing you require using the GET function.
|
|
- e.g. you can use get("SERIALRAW") or get("BUTTONSTATE") and do your own edge/level and keyup/keydown detection.
|
|
~~~
|
|
kk = 255
|
|
|
|
loop:
|
|
k = get("SERIALRAW")
|
|
if kk &&= 255
|
|
if k&&<>255 then gosub k
|
|
endif
|
|
kk = k
|
|
goto &loop
|
|
|
|
49: print "1" : return
|
|
50: print "2" : return
|
|
51: print "3" : return
|
|
~~~
|
|
- General purpose input can be obtained through the INPUT command.
|
|
- INPUT is more powerful than ye old BASIC's INPUT and provides a number of extra and advanced features.
|
|
- It supports a heading string, multiple int/str variables, semi-colon formatting and field widths.
|
|
- Input text will automatically scroll when reaching the edge of the screen or be limited to a pre-defined field width.
|
|
~~~
|
|
' INPUT <heading string>, <int/str var0>, <prompt string0>, ... <int/str varN>, <prompt stringN>
|
|
input "Testing INPUT:", cat$,"Cats Name ?"32;, hours,"H ?"2;, minutes,"M ?"2;, seconds,"S ?"2;
|
|
~~~
|
|
|
|
## Delays:
|
|
- You can wait a predermined period of time using the WAIT command.
|
|
- WAIT without any parameters waits for one vertical blank, (use this to sync your fast inner loops to VSYNC).
|
|
- WAIT <n> will wait 'n' vertical blank periods, where 'n' can 1 to 32767.
|
|
|
|
## Assembler:
|
|
- The compiler always compiles and links to vCPU mnemonics, the assembler then assembles the mnemonics into vCPU code and a .GT1 file.
|
|
- This is a different order of operation to a traditional compiler because linker files, (the gtBASIC runtime), are not object/binary files, they are source/text files.
|
|
- The compiler will always produce a .GASM file that you may then view to determine how good/bad a job the compiler has performed.
|
|
- The assembly code is fully annotated and you can directly see which gtBASIC statements have produced which vCPU mnemonics.
|
|
- The following code is a complete assembled version of Blinky, you can see all the register/memory allocations, the annotated code and the gtBASIC runtime linked.
|
|
<details>
|
|
<summary>Summary</summary>
|
|
|
|
~~~
|
|
_startAddress_ EQU 0x0200
|
|
|
|
; Internal variables
|
|
serialRawPrev EQU 0x0081
|
|
register0 EQU 0x0082
|
|
register1 EQU register0 + 0x02
|
|
register2 EQU register0 + 0x04
|
|
register3 EQU register0 + 0x06
|
|
register4 EQU register0 + 0x08
|
|
register5 EQU register0 + 0x0A
|
|
register6 EQU register0 + 0x0C
|
|
register7 EQU register0 + 0x0E
|
|
register8 EQU register0 + 0x10
|
|
register9 EQU register0 + 0x12
|
|
register10 EQU register0 + 0x14
|
|
register11 EQU register0 + 0x16
|
|
register12 EQU register0 + 0x18
|
|
register13 EQU register0 + 0x1A
|
|
register14 EQU register0 + 0x1C
|
|
register15 EQU register0 + 0x1E
|
|
fgbgColour EQU register0 + 0x20
|
|
cursorXY EQU register0 + 0x22
|
|
midiStream EQU register0 + 0x24
|
|
midiDelay EQU register0 + 0x26
|
|
miscFlags EQU register0 + 0x28
|
|
fontLutId EQU 0x00e0
|
|
|
|
; Internal buffers
|
|
textWorkArea EQU 0x7fa0
|
|
|
|
; Includes
|
|
%includePath "../runtime"
|
|
%include gigatron.i
|
|
%include macros.i
|
|
|
|
; Labels
|
|
_entryPoint_ EQU 0x0200
|
|
_10 EQU 0x0239
|
|
_20 EQU 0x0239
|
|
_30 EQU 0x0239
|
|
_40 EQU 0x0245
|
|
_50 EQU 0x0239
|
|
_60 EQU 0x025b
|
|
_end_0x0271 EQU 0x0263
|
|
|
|
; Variables
|
|
_X EQU 0x0030
|
|
_Y EQU 0x0032
|
|
_I EQU 0x0034
|
|
_P EQU 0x0036
|
|
|
|
; Strings
|
|
|
|
; Define Bytes
|
|
|
|
; Define Words
|
|
|
|
; Define Images
|
|
|
|
; Define Sprites
|
|
|
|
; Define Fonts
|
|
|
|
; Lookup Tables
|
|
|
|
; Code
|
|
_entryPoint_ InitRealTimeProc
|
|
InitEqOp
|
|
InitNeOp
|
|
InitLeOp
|
|
InitGeOp
|
|
InitLtOp
|
|
InitGtOp
|
|
Initialise ; INIT
|
|
|
|
_20 LDI 80
|
|
STW _X
|
|
LDI 60
|
|
STW _Y
|
|
LDI 0
|
|
STW _I ; X=160/2:Y=120/2:I=0
|
|
|
|
_40 LDWI 256
|
|
ADDW _Y
|
|
ADDW _Y
|
|
PEEK
|
|
STW 0xc2
|
|
LD 0xc2
|
|
ST giga_vAC + 1
|
|
ORI 0xFF
|
|
XORI 0xFF
|
|
ADDW _X
|
|
STW _P ; P=(PEEK(256+Y+Y) LSL 8)+X
|
|
|
|
_60 LDW _I
|
|
POKE _P
|
|
INC _I
|
|
BRA _60 ; POKE P,I:INC I:GOTO &60
|
|
|
|
_end_0x0271 BRA _end_0x0271 ; END
|
|
|
|
|
|
|
|
;****************************************************************************************************************************************
|
|
;****************************************************************************************************************************************
|
|
;* Internal runtime, DO NOT MODIFY PAST THIS POINT, modifications must be made in the original include files *
|
|
;****************************************************************************************************************************************
|
|
;****************************************************************************************************************************************
|
|
|
|
realTimeProc EQU 0x7ef6
|
|
convertEqOp EQU 0x7eed
|
|
convertNeOp EQU 0x7ee4
|
|
convertLeOp EQU 0x7edb
|
|
convertGeOp EQU 0x7ed2
|
|
convertLtOp EQU 0x7ec9
|
|
convertGtOp EQU 0x7ec0
|
|
resetVideoTable EQU 0x7db5
|
|
initClearFuncs EQU 0x7ddd
|
|
realTimeProcAddr EQU 0x00dc
|
|
convertEqOpAddr EQU 0x00d0
|
|
convertNeOpAddr EQU 0x00d2
|
|
convertLeOpAddr EQU 0x00d4
|
|
convertGeOpAddr EQU 0x00d6
|
|
convertLtOpAddr EQU 0x00d8
|
|
convertGtOpAddr EQU 0x00da
|
|
|
|
|
|
; do *NOT* use register4 to register7 during time slicing if you call realTimeProc
|
|
numericLabel EQU register0
|
|
defaultLabel EQU register1
|
|
lutLabs EQU register2
|
|
lutAddrs EQU register3
|
|
lutIndex EQU register8
|
|
|
|
|
|
; runs real time, (time sliced), code at regular intervals
|
|
realTimeProc PUSH
|
|
LDWI realTimeStub ; realTimeStub gets replaced by MIDI routine
|
|
CALL giga_vAC
|
|
POP
|
|
RET
|
|
|
|
realTimeStub RET
|
|
|
|
|
|
; convert equal to into a boolean
|
|
convertEqOp BEQ convertEq_1
|
|
LDI 0
|
|
RET
|
|
convertEq_1 LDI 1
|
|
RET
|
|
|
|
|
|
; convert not equal to into a boolean
|
|
convertNeOp BNE convertNe_1
|
|
LDI 0
|
|
RET
|
|
convertNe_1 LDI 1
|
|
RET
|
|
|
|
|
|
; convert less than or equal to into a boolean
|
|
convertLeOp BLE convertLe_1
|
|
LDI 0
|
|
RET
|
|
convertLe_1 LDI 1
|
|
RET
|
|
|
|
|
|
; convert greater than or equal to into a boolean
|
|
convertGeOp BGE convertGe_1
|
|
LDI 0
|
|
RET
|
|
convertGe_1 LDI 1
|
|
RET
|
|
|
|
|
|
; convert less than into a boolean
|
|
convertLtOp BLT convertLt_1
|
|
LDI 0
|
|
RET
|
|
convertLt_1 LDI 1
|
|
RET
|
|
|
|
|
|
; convert greater than into boolean
|
|
convertGtOp BGT convertGt_1
|
|
LDI 0
|
|
RET
|
|
convertGt_1 LDI 1
|
|
RET
|
|
|
|
|
|
|
|
; do *NOT* use register4 to register7 during time slicing if you call realTimeProc
|
|
xreset EQU register0
|
|
xcount EQU register1
|
|
ycount EQU register2
|
|
treset EQU register3
|
|
breset EQU register8
|
|
top EQU register9
|
|
bot EQU register10
|
|
vramAddr EQU register11
|
|
evenAddr EQU register12
|
|
clsAddress EQU register13
|
|
|
|
|
|
; resets video table pointers
|
|
resetVideoTable PUSH
|
|
LDI 8
|
|
STW vramAddr
|
|
LDWI giga_videoTable
|
|
STW evenAddr
|
|
|
|
resetVT_loop CALL realTimeProcAddr
|
|
LDW vramAddr
|
|
DOKE evenAddr
|
|
INC evenAddr
|
|
INC evenAddr
|
|
INC vramAddr
|
|
LD vramAddr
|
|
SUBI giga_yres + 8
|
|
BLT resetVT_loop
|
|
|
|
LDWI giga_videoTop ; reset videoTop
|
|
STW register0
|
|
LDI 0
|
|
POKE register0
|
|
POP
|
|
RET
|
|
|
|
|
|
initClearFuncs PUSH
|
|
LDWI resetVideoTable
|
|
CALL giga_vAC
|
|
|
|
LDI 0x02 ; starting cursor position
|
|
STW cursorXY
|
|
LDWI 0x7FFF
|
|
ANDW miscFlags
|
|
STW miscFlags ; reset on bottom row flag
|
|
|
|
LD fgbgColour
|
|
ST giga_sysArg0
|
|
ST giga_sysArg0 + 1
|
|
ST giga_sysArg2
|
|
ST giga_sysArg2 + 1 ; 4 pixels of fg colour
|
|
|
|
LDWI SYS_Draw4_30 ; setup 4 pixel SYS routine
|
|
STW giga_sysFn
|
|
POP
|
|
RET
|
|
~~~
|
|
</details>
|
|
|
|
## Branching:
|
|
- Don't use 0 as a line number, 0 is used as a delimiter in GOTO/GOSUB LUT's.
|
|
- Line numbers are totally optional, (except for ON <VAR> GOTO/GOSUB and GOTO/GOSUB <VAR>).
|
|
- ON <VAR> GOTO/GOSUB <LINE#1>, <LINE#2>, ..... <LINE#n>, (no checks are performed so make sure your <VAR> does not send you off into lala land).
|
|
- GOTO/GOSUB <VAR>, <OPTIONAL DEFAULT LABEL>, allows for efficient switch type statements, e.g.
|
|
~~~
|
|
loop:
|
|
a = rnd(2) + 1
|
|
gosub a
|
|
|
|
b = rnd(2) + 3
|
|
goto b
|
|
goto &loop
|
|
|
|
' Numeric GOSUB identifies line numbers with ':'
|
|
1: print "1" : return
|
|
2: print "2" : return
|
|
|
|
' Numeric GOTO identifies line numbers with '!'
|
|
3! print "3" : goto loop
|
|
4! print "4" : goto loop
|
|
~~~
|
|
- Use GOTO to continue/break out of loops, (break and continue are not a thing in this compiler).
|
|
- Use labels and indentation abundantly and line numbers only when needed, e.g.
|
|
~~~
|
|
loop:
|
|
set SOUNDTIMER, 5
|
|
|
|
gosub vuMeter
|
|
|
|
k = get("SERIALRAW")
|
|
if kk &&= 255 then gosub k
|
|
gosub state
|
|
kk = k
|
|
goto &loop
|
|
|
|
midiOff:
|
|
set MIDISTREAM, &h0000
|
|
return
|
|
|
|
1: gosub midiOff
|
|
gosub siren
|
|
return
|
|
|
|
2: gosub midiOff
|
|
gosub crash
|
|
return
|
|
|
|
3: gosub midiOff
|
|
gosub beep
|
|
return
|
|
|
|
4: if get("MIDISTREAM") &= &h0000
|
|
play midiv, &h0AA0, 2
|
|
else
|
|
play midiv
|
|
endif
|
|
return
|
|
~~~
|
|
|
|
## Arithmetic:
|
|
- Multiply and especially divide/modulus are slow.
|
|
- Use shifts, masks, LUT's, cheats and hacks as much as possible, especially in your inner most or tightest loops.
|
|
~~~
|
|
' slow, rnd(<number>) performs a modulus with that number on the random result
|
|
' rnd(0) foregoes the modulus so that you can do the filtering yourself
|
|
x = rnd(160) : y = rnd(120)
|
|
|
|
' much faster, but gives a different type of noise that drastically drops off towards it's boundaries
|
|
x = (rnd(0) AND &h7F) + (rnd(0) AND &h1F) + (rnd(0) AND &h01)
|
|
y = (rnd(0) AND &h3F) + (rnd(0) AND &h1F) + (rnd(0) AND &h0F) + (rnd(0) AND &h07) + (rnd(0) AND &h03)
|
|
|
|
' x = 4 + 8*i : y = 3 + 6*i
|
|
math: sh = (i<<1)
|
|
x = sh + sh + sh + sh + 4
|
|
y = sh + sh + sh + 3
|
|
return
|
|
|
|
' samples a complex transcendental function into a 64 byte LUT, (use graphing calculators like Desmos to create your functions)
|
|
def byte(&h08A0, y, 0.0, 0.5, 64) = 63.0 - exp(-0.5*y)*(1.0-exp(-3.0*y))*1.6125*63.0
|
|
~~~
|
|
|
|
## Memory Manager:
|
|
- The host compiler, (your PC), has a fairly extensive memory manager that tracks every single byte on the Gigatron whilst compiling your code.
|
|
- There is no memory manager within the gtBASIC runtime, (i.e. on the Gigatron), so ALL memory allocations are static and happen BEFORE your code is run.
|
|
- This includes the following pragmas and commands:
|
|
~~~
|
|
_runTimeStart_
|
|
_spriteStripeChunks_
|
|
DIM
|
|
DEF
|
|
ALLOC
|
|
FREE
|
|
~~~
|
|
- These commands ALWAYS allocate memory before code and other commands gets access to memory, so you can choose the RAM addresses for the most efficient layout for your application. Everything else will fit around your high priority allocations.
|
|
- These commands can NOT be used in loops, branches or condition statements, they are read once each during an initial parse of the code and RAM is allocated accordingly.
|
|
- You can statically initialise arrays and defined areas without wasting precious memory and vCPU cycles using the following syntax.
|
|
~~~
|
|
' you can have less than the required initialisers, the missing values will be automatically zero'ed.
|
|
' DIM array elements are always 2 byte wide integers
|
|
dim colours(3) = &h3F, &h2A, &h15, &h00
|
|
' one initialiser fills the entire array
|
|
dim blah(20) = &hBEEF
|
|
|
|
def byte(&h10a0) = &h1e, &h90, &h4a, &h91, &h45, &h3d, &h80, &h81, &h1f, &h91, &h4a, &h90, &h45, &h3d, &h80
|
|
|
|
' you can use loops of complex floating point functions to initialise DEF BYTES and DEF WORDS areas of memory
|
|
' the y is a placeholder, use a variable name that does not clash with the transcendentals you are using
|
|
' <address> <var> <start> <end> <count>
|
|
' this fills the RAM starting at &h08A0 and ending at &h08FF, (offscreen memory), with the following decay function
|
|
def byte(&h08A0, y, 0.0, 0.5, 96) = 63.0 - exp(-0.5*y)*(1.0-exp(-3.0*y))*1.6125*63.0
|
|
~~~
|
|
|
|
## Address Of '@':
|
|
- Use the '@' symbol to obtain the address of any int, array or string variable, (works with constant strings as well).
|
|
~~~
|
|
dim arr(5) = 0
|
|
const cat$ = "cat"
|
|
dog$ = "dog"
|
|
|
|
a = 1
|
|
b = @a
|
|
c = @c + b + 1
|
|
d = @cat$ + @dog$ + @arr
|
|
~~~
|
|
|
|
## .LO and .HI:
|
|
- Use .LO/.HI when you want to access the low and high bytes of an integer or array variable.
|
|
~~~
|
|
a = 1
|
|
d = @a
|
|
a.hi = 1 : a.lo = 0
|
|
b = a.hi + 1
|
|
c = 0 : c.hi = 1
|
|
~~~
|
|
|
|
## LEN:
|
|
- Use the LEN function to obtain the length of any int, array or string variable, (works with constant strings as well).
|
|
|
|
## INC:
|
|
- Use the INC command when incrementing byte values.
|
|
|
|
## POKE and PEEK:
|
|
- You can POKE/PEEK the non parenthesis Gigatron system variables with complete freedom, (you shouldn't touch the ones in parenthesis noted in Marcel's main README.md as they are subject to change).
|
|
- Do not POKE/PEEK any of the gtBASIC variables as they will definitely change and sooner rather than later.
|
|
- Use the provided SET/GET functions, they cover all usable Gigatron and gtBASIC system variables.
|
|
|
|
## Optimisation Hints:
|
|
- The optimiser uses one or more '&' characters to control how branching and jumping is performed.
|
|
- When writing code you do not need to worry about page jumps and code spilling out of pages/sections, the compiler will automatically stitch all the fragmented areas of code together using page jumps and accumulator save/restore's.
|
|
- You can completely ignore these compiler hints and the code will work just fine, but if you want to, (sometimes drastically), reduce it's size and increase it's speed then you can use these hints as follows:
|
|
~~~
|
|
' No hints: allows full relational operator expressions, i.e. AND, OR, XOR, NOT, (use parenthesis so that order of precedence works correctly)
|
|
IF (a > 50) AND (b < 20) then gosub blah
|
|
|
|
' One hint: relational operator expressions will no longer work, jumping will be more efficient as it uses macros rather than subroutines
|
|
IF a &> 50
|
|
IF b &< 20 then gosub blah
|
|
ENDIF
|
|
|
|
' Two hints: relational operator expressions will no longer work, branches now instead of jumping, but will fail if branch destination is in another page, (validator will warn you if this occurs).
|
|
IF a &&> 50
|
|
IF b &&< 20 then gosub blah
|
|
ENDIF
|
|
|
|
' Uses a branch instead of a jump, which can fail as above
|
|
FOR i=0 &TO 10
|
|
PRINT i
|
|
NEXT i
|
|
|
|
' Uses a branch instead of a jump, which can fail as above
|
|
goto &blah
|
|
~~~
|
|
|
|
## Optimiser:
|
|
- The optimiser currently only spans single lines and multi statement lines, (it will be expanded in the future); so use it effectively or disable it by spreading your code out over multiple lines.
|
|
- There are many sequences of instructions that are matched/replaced/relocated by smaller more efficient sequences, check the source code for a full run down.
|
|
- Optimising causes var/label names to contain meaningless address values because of code relocation.
|
|
- Do not rely on the address values when reading vCPU assembly code, their purpose is only to provide unique names.
|
|
- When a line of code uses the result of a previous line's calculations, the optimiser may be able to save some LDW instructions if you spread the code over a multi-line statement.
|
|
~~~
|
|
' the LDW _p has been optimised out of this code sequence, it used to sit in between the STW _p and the 'SUBW _q'
|
|
LDW _p
|
|
ADDI 4
|
|
STW _p
|
|
SUBW _q
|
|
BLT _repeat_0x0414 ; p = p + 4 : until p &&>= q
|
|
~~~
|
|
|
|
## Variable Initialisation:
|
|
- Pack the initialisation of your variables into multi-statement lines if you can, your code will be smaller and faster.
|
|
|
|
### UNPACKED:
|
|
~~~
|
|
LDI 0
|
|
STW _x ; x = 0
|
|
|
|
LDI 0
|
|
STW _y ; y = 0
|
|
|
|
LDI 0
|
|
STW _z ; z = 0
|
|
~~~
|
|
|
|
### PACKED:
|
|
~~~
|
|
LDI 0
|
|
STW _x
|
|
STW _y
|
|
STW _z ; x = 0 : y = x : z = y
|
|
~~~
|
|
|
|
## Expression Handler:
|
|
- Short circuit complex literal calculations into simpler real instructions.
|
|
|
|
### BAD:
|
|
~~~
|
|
LDI 20
|
|
STW _x ; x = 20
|
|
|
|
LDW _x
|
|
STW mathX
|
|
LDI 20
|
|
STW mathY
|
|
LDWI multiply16bit
|
|
CALL giga_vAC
|
|
ADDI 53
|
|
SUBI 12
|
|
SUBI 9
|
|
STW _blah ; blah = x*20 + 53 - 12 - 9
|
|
~~~
|
|
|
|
### GOOD:
|
|
~~~
|
|
LDI 20
|
|
STW _x
|
|
STW mathX
|
|
LDI 20
|
|
STW mathY
|
|
LDWI multiply16bit
|
|
CALL giga_vAC
|
|
ADDI 32
|
|
STW _blah ; x = 20 : blah = x*20 + (53 - 12 - 9)
|
|
~~~
|
|
|
|
- Use as much floating point calculations with literals, (including transcendentals), as you want; it will all be calculated at full double floating point precision and then the final answer rounded down into int16_t, (the native vCPU 16 bit format).
|
|
- Remember to ALWAYS use parenthesis around your complex literal calculations or you will calculate garbage.
|
|
- No variables can be used within the parenthesis containing the floating point calculations.
|
|
- Transcendentals use Degrees, NOT Radians.
|
|
|
|
~~~
|
|
LDI 10
|
|
STW _x
|
|
STW mathX
|
|
LDI 2
|
|
STW mathY
|
|
LDWI multiply16bit
|
|
CALL giga_vAC
|
|
STW mathX
|
|
LDWI -995
|
|
STW mathY
|
|
LDWI multiply16bit
|
|
CALL giga_vAC
|
|
STW _blah ; x = 10 : blah = x*2*(50*exp(-1.232455)*sin(45)*cos(57.324786234) - 1000.342876324)
|
|
~~~ |