base:generating_sines_with_basic
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | base:generating_sines_with_basic [2015-04-17 04:32] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Generating Sines through BASIC ====== | ||
+ | By Doynax | ||
+ | Generating sines in BASIC is slow, but might be suitable for programs that need to be small. Improve if you can! | ||
+ | |||
+ | The routine is currently 28 bytes long and takes 5.9 seconds to execute: | ||
+ | < | ||
+ | table = $0400 ;; The output is a set of negated (phase-shifted by 180°) | ||
+ | ;; sines between -128 and +127. | ||
+ | ;; Preferably a low page. Must be paged aligned! | ||
+ | |||
+ | loop lda #< | ||
+ | ldy #> | ||
+ | jsr $bba2 ;; However an integer bias is also added in order to fix | ||
+ | ;; the exponent and make hence it possible to increment the | ||
+ | ;; fraction as a normal binary byte, e.g. a version of the | ||
+ | ;; classic x86 float-to-int conversion trick. | ||
+ | |||
+ | jsr $e277 ;; Now calculate sine of FAC. Except skip the initial part | ||
+ | ;; of the BASIC function which divides by 2*PI to get | ||
+ | ;; a fraction out of radians since we've already got one. | ||
+ | ;; The integer bias is taken care by BASIC since sin() | ||
+ | ;; is supposed to be periodic. | ||
+ | |||
+ | lda #< | ||
+ | ldy #> | ||
+ | jsr $b867 ;; mantissa by employing the same trick as before of | ||
+ | lda $65 ;; adding a high integer bias. | ||
+ | |||
+ | index .byte $88 ;; This is both a float *and* a piece of code. The exponent | ||
+ | sta table ;; ($88 corresponds to 2^8) fixes our 8-bit fraction as the | ||
+ | ;; second byte of the mantissa and the STA address' | ||
+ | ;; (don't forget that BASIC floats are big-endian!). And $88 | ||
+ | ;; when interpreted as code corresponds to a harmless DEY. | ||
+ | ;; Note that the STA's opcode is an integer part which only | ||
+ | ;; has the effect of negating the index (the sign bit is set). | ||
+ | ;; However the table address' | ||
+ | ;; INC opcode *do* serve as a small offset, shifting the | ||
+ | ;; result by up to one index value. Some might even argue | ||
+ | ;; that placing the table at $8000 would produce the ' | ||
+ | ;; rounding. | ||
+ | inc *-2 | ||
+ | bne loop | ||
+ | |||
+ | bias = $befa ;; A float with an exponent of $99 (2^25) and an LSB of | ||
+ | ;; .byte $99 ;; zero is used to convert the output to binary. Such byte | ||
+ | ;; .byte $02 ;; sequences can be found in six places in the BASIC/ | ||
+ | ;; .byte $01 ;; ROMs, at $befa/ | ||
+ | ;; .byte $a9 ;; A version with an LSB of $80 would have been useful to | ||
+ | ;; .byte $00 ;; create unsigned output (e.g. between $00 and $ff with the | ||
+ | ;; origin at $80) but unfortunately doesn' | ||
+ | ;; Values with different exponents and offsets might be found | ||
+ | ;; to better suit your particular application.</ |
base/generating_sines_with_basic.txt · Last modified: 2015-04-17 04:32 by 127.0.0.1