| |
Flavioweb
Registered: Nov 2011 Posts: 466 |
assembly sin gen code request
i need a code (assembly) to gen sin table. I need to set start, end and step value. Someone could help? |
|
| |
iAN CooG
Registered: May 2002 Posts: 3204 |
http://codebase64.org/doku.php?id=base:6502_6510_maths
anyway I'd use wixbouncer or other sintable generators and include the generated table, unless you're going to make a 256byte intro |
| |
Style
Registered: Jun 2004 Posts: 498 |
wouldnt you be better off generating the table in BASIC before running the demo or whatever?
|
| |
Flavioweb
Registered: Nov 2011 Posts: 466 |
is better to have pre-calculated sin, but i want to write my own routine first for learning purpose then to make my code stand alone easy reusable simply changing some bytes... |
| |
tlr
Registered: Sep 2003 Posts: 1791 |
You could use the kernal routines to implement basic-like generation of sine.
Faster would be to use a fixed point implementation of the MacLaurin series of sin(x).
Faster yet would be something like this: http://codebase64.org/doku.php?id=base:generating_approximate_s..
|
| |
iAN CooG
Registered: May 2002 Posts: 3204 |
I already linked the section on codebase64, but went unnoticed I think =) |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
CORDIC might be an interesting way to go.
There's a decent article on Wikipedia, but basically you start with a vector pointing along the X axis and perform a set series of rotation+scales using matrices whose components are all either 1 or a power of two. Each step you accumulate the angle you've rotated so far (fixed point addition of constant from very small table), and step either CW or CCW, depending if you've currently overshot. The angles get successively smaller, so it's close to a binary search. Total scale factor is a constant, so you can prescale your start vector by the inverse.
You could get away with only two or three distinct step sizes (and hence just hard code 2 or 3 shift amounts) if you were willing to do some extra iterations (say 20 large steps, 20 small).
Thoughts? |
| |
Achim Account closed
Registered: Jan 2010 Posts: 28 |
If you only need some sin-tables: Sinus Creator V2.0 |
| |
Skate
Registered: Jul 2003 Posts: 495 |
I usually choose one of the suggestions above but maybe bresenham's circle algorithm, mid point algorithm or a mixture like below may help you to generate a sine table. if you can draw a circle, you can generate a sine table using one of the x or y coordinates, right? The only problem I see here is not being able to get a certain table length but maybe this can be solved somehow.
http://willperone.net/Code/codecircle.php
Edit: @ChristopherJam: I just checked CORDIC and it looks like a good fit. I didn't know about it before. Thanks for sharing. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
@Skate You're welcome.
I've a feeling it was John West (he who co-authored 64doc with Marko Mäkelä) who originally suggested I check it out, some 20 years ago now. I'd forgotten how it worked until I looked it up again for this post. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Hmm, the problem with using Bresenham is each pixel generated is at a constant x-increment from the one before, rather than a constant theta-increment.
However, I was wondering if perhaps you could use something Bresehnham-like to normalise the result of repeatedly doing a fixed rotation, that might otherwise drift in scale? |
| |
Glasnost Account closed
Registered: Aug 2011 Posts: 26 |
There is a fast and simple approximation.
Calculate first the hyperbolic approximated sine described earlier (sinH)
Then correct with this:
sin = 0.225 * (sinH * sinH - sinH) + sinH;
0.1% error in worst case compared to the real sinus..
Found it on...
http://lab.polygonal.de/2007/07/18/fast-and-accurate-sinecosine..
...but the link is not working anymore.. |
| |
Skate
Registered: Jul 2003 Posts: 495 |
Thanks Glasnost, nice article there.
P.S: You can reach the page using the archive.org's link below. (takes a while to load, be patient)
http://web.archive.org/web/20101229221122/http://lab.polygonal... |
| |
SIDWAVE Account closed
Registered: Apr 2002 Posts: 2238 |
i havent really ever seen a C64 sine gen in asm.
i use a basic line we made 25 years ago, then mod it for moves.
another way is to use excell spreadsheet, and generate curves from formulas there, and export to c64.
what i want to say really, is, why dont someone make a c64 tool ? if its so important, then make a c64 generator. ?
:) |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
SIDWave: Nowadays you can just use an assembler script to generate stuff like that. E.g. KickAss where you have access to all the basic math functions from Java. What this discussion is about is generating it in machine code, in order to avoid having to load it from disk. |
| |
iAN CooG
Registered: May 2002 Posts: 3204 |
Jan: are you joking? apart that it's explained on codbase how to do it in asm, there is a plethora of native sinus table generators, I even mentioned one in my 1st post (wix bouncer), and if in doubt just search sinus:
http://csdb.dk/search/?seinsel=releases&search=sinus&all=1 |
| |
Wisdom
Registered: Dec 2001 Posts: 90 |
Working link for the article Glasnost referred to:
http://lab.polygonal.de/?p=205
|
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Might be an interesting challenge to make a 'fewest bytes' sine table generator, criteria "can generate a 256 entry table for floor(128.5+127*sin(i*pi/128.0))", with errors of no more than +-1, at least 170 entries exact.
Of course, it's possible a delta compression scheme might end up winning out over a calculation.. and any entry of more than 256 bytes of code is pretty much an automatic fail! |
| |
Graham Account closed
Registered: Dec 2002 Posts: 990 |
Small sin?
10 FORI=0TO255:POKE4096+I,SIN(I*π/128)*127.5+128:NEXT
Is probably the shortest :)
Other than that a 65 bytes table + small mirror routine will probably be smaller than any real calculation or compression routine:
LDX #$40
LDY #$00
lp LDA sinsrc,X
STA sin,X
STA sin+64,Y
EOR #$FF
STA sin+128,X
STA sin+192,Y
INY
DEX
BPL lp
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
I'm also usually using Graham's mirror trick in bigger productions, even with only a 64 byte table. :)
For 256b'ers I have this extremely inaccurate but only 46 bytes long polynomial pseudo sine generator...
.var sineAmp = $100
.var loStart
.var loAddAdd
.if (sineAmp == $40) {
.eval loStart = $1c
.eval loAddAdd = $03
}
.if (sineAmp == $80) {
.eval loStart = $18
.eval loAddAdd = $07
}
.if (sineAmp == $100) {
.eval loStart = $14
.eval loAddAdd = $0f
}
lda #$00
pha
tax
ldy #$40
loop:
loAdd: lda #loStart
adc #loAddAdd
sta loAdd+1
bcc lo
inc hiAdd+1
clc
lo: adc #$00
sta lo+1
pla
hiAdd: adc #$00
pha
sta sine,x
sta sine+$bf,y
eor #sineAmp-1
sta sine+$80,x
sta sine-$80+$bf,y
inx
dey
bne loop
For an amplitude of $100 the max deviation is 7, with an avg of about 2.5. So it doesn't quite comply with Christopher's requirements, but it produces a smooth curve, which is usually good enough for plasmas, DYCP's, etc. For 3D calculations it probably needs to be more accureate though. |
| |
Skate
Registered: Jul 2003 Posts: 495 |
I use a very similar routine with Cruzer's. Mine is shorter in a way but there are some initialization rules! :)
this part is taken from my Little Circles of Life product's source code.
...
tSin = $5f00
...
value = $3c ; 16 bits
delta = $3e ; 16 bits
...
* = $0326
!word codeStartAddress
codeStartAddress
; fill&clear memory
- lda #$f6 : setByte = *-1 ; !word $f6a9
sta ($2b),y
iny
bne -
inc $2c
ldx $2c
cpx #$10
bcc -
sty setByte
bpl -
;sinus calculation
ldx #$40
- pha
clc
adc value
sta value
lda tSin+$c0-1,y
adc delta+1
sta tSin+$c0,y
sta tSin+$80-1,x
eor #$ff
sta tSin+$00-1,x
sta tSin+$40,y
pla
adc #$10
bcc +
inc delta+1
+ iny
dex
bne -
very dirty trick at the beginning, i admit it. :) but since this start-up routine fills $1000-$7fff with zero and sinus tables are placed in that area, sinus calculation routine takes only 39 bytes. but of course, if we try to make a stand alone sinus generator, it would take more bytes just like Cruzer's routine.
My point is, you can always use the benefit of your "already required" parts of your effect for shorter sine gen routines. This applies to almost every routine of course, this is just a little example.
For instance, i had to clean up the bitmap area for my effect, anyway. Why not using the same routine for cleaning up the sinus tables area and make an optimization like above without spending any extra bytes?
P.S: This $f6 (or $ff) is a must if you use the $0326 start up trick. I use $f6 to fill the video ram to use as background and foreground colors for my effect and gain 2 more bytes. This is the real "coder colors" case i guess. :) |
| |
Graham Account closed
Registered: Dec 2002 Posts: 990 |
Quoting CruzerI'm also usually using Graham's mirror trick in bigger productions, even with only a 64 byte table. :)
Yes, if you add an offset of 0.5 to the sinus index (0.5 to 255.5 instead of 0 to 255), you can use a 64 byte table. This works nice for plasmas, sinus movements etc. However for "real maths" like 3D rotation or similar, it's better to use a sinus wave without that 0.5 index.
|
| |
Wisdom
Registered: Dec 2001 Posts: 90 |
Quoting ChristopherJamOf course, it's possible a delta compression scheme might end up winning out over a calculation.. and any entry of more than 256 bytes of code is pretty much an automatic fail!
In Tied, there is a simple delta encoded sinus table, consisting of only 8 bytes, but the decoder itself is around 38 bytes (might change due to initialization in a different perspective). Extends a full sinus for 00-3F values to a 256 bytes table.
There is also a second one, which has a more complex shape, consisting of a 32 bytes table and a separate 40 bytes decoder (again, might be different a byte or two in a different initialization scenario). Again, extends to a 256 bytes table with values between 00-3F.
|
| |
Adam
Registered: Jul 2009 Posts: 323 |
Quoting SIDwave... what i want to say really, is, why dont someone make a c64 tool ? if its so important, then make a c64 generator? :)
Hi Jan, Here is a tool that will allow you to generate sine waves using MS-Windows:
Sinus Creator V3 by 'The Gang'
http://www.thegang.nu/get_data.php?type=attachment&id=160
The website says version 2.x but the program in the zip archive is version 3. This program is very useful ;)
Output: Binary, Assembler, BASIC, C, C Source and WAV Audio samples =D
|
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
This routine has an accuracy ±3 (should be able to improve that by tweaking the table a little), but relies on interrupts being clear, character DMA disabled, and voice 3 of SID being fully decayed with a release rate of zero! 58 bytes including table, piecewise linear using env3 to select one of 13 segments:
sin=$4000
v3ctrl = $d40e+4
v3AD = $d40e+5
v3SR = $d40e+6
env3 = $d41c
initSin
ldx#$50
stx v3AD
inc v3ctrl
lda#127
clc
lp
ly ldy#63
eor#$ff
sta sin-$50,x
sta sin+64,y
eor#$ff
sta sin+128-$50,x
sta sin+192,y ;26 cycles
rol ; note this will clear carry
ldy env3 ; increases by 1 every 208 cycles for attack=5,
sbc dt,y
lsr
inx
dec ly+1
bpl lp ; 22+26 =48 for entire loop
rts
dt
.byt 5,5,5,5,5, 4,4,3,3,2, 2,1,0,255
CIA would probably be a better bet than SID, but I'm not very familiar with it, and it's less of an evil hack :) |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Generating sines with the SID, now that's what I call a hack! Is it based on sine-like waveforms, or is the SID just used as a counter as the comments imply? |
| |
chatGPZ
Registered: Dec 2001 Posts: 11391 |
the envelope generator uses some sort of spline approximation, so its linear steps and the slope changes at a few points. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Much simpler than all that; I just needed a value that increased by one every four or five iterations through the loop. The sin table generated is a linear approximation calculated in 8.1 fixed point, with a new slope value for each envelope increment.
Envelope generation is itself piecewise linear in the decay and release phases, but attack (as used here) just increases at a constant rate. |