Difference between revisions of "Programming:Sin/Cos calculation"
From CPCWiki - THE Amstrad CPC encyclopedia!
PulkoMandy (Talk | contribs) |
m (Updated dead link to CORDIC algorithm) |
||
(One intermediate revision by one other user not shown) | |||
Line 1: | Line 1: | ||
+ | == Calculation using lookup table == | ||
+ | |||
+ | The calculation is based on a table from 0-90° and on values which are multiplicated by 32767. If you want to get the correct sinus value, you have to divide them by 32767 (you can use 32768 - not a big precision lost, but you can use bit shifting). | ||
+ | |||
+ | '''Input:''' HL = ''angle in degree (0-360°)'' | ||
+ | |||
+ | '''Output:''' HL = ''SIN(HL) * 32767'', A = ''sign flag (0 if positive, &FF if negative)'' | ||
+ | |||
+ | |||
+ | <pre> | ||
+ | INTSIN: LD BC, 360 | ||
+ | LOOP1: BIT 7, H ;angle positive? | ||
+ | JR Z, LOOP2 ;-> yes, ok | ||
+ | ADD HL, BC ;else add 360 | ||
+ | JR LOOP1 ;repeat until H>0 | ||
+ | |||
+ | LOOP2: OR A ;reset carry | ||
+ | SBC HL, BC ;angle - 360 | ||
+ | JR NC, LOOP2 ;->ok if >=0 | ||
+ | ADD HL, BC ;else correct value | ||
+ | |||
+ | LD E, L ;angle to DE | ||
+ | LD D, H | ||
+ | LD BC, 90 | ||
+ | XOR A ;sign flag = 0 | ||
+ | SBC HL, BC ;angle < 90? | ||
+ | JR NC, TEST2 ;-> no | ||
+ | EX DE, HL ;else HL = angle | ||
+ | JR GETTAB ;get table value | ||
+ | |||
+ | TEST2: SBC HL, BC ;angle < 180? | ||
+ | JR NC, TEST3 ;-> no | ||
+ | LD HL, 180 ;else HL = | ||
+ | OR A ;180 - angle | ||
+ | SBC HL, DE | ||
+ | JR GETTAB ;get table value | ||
+ | |||
+ | TEST3: DEC A ;sign flag &FF | ||
+ | SBC HL, BC ;angle < 270? | ||
+ | JR NC, TEST4 ;-> no | ||
+ | EX DE, HL ;else HL = | ||
+ | OR A ;clear carry | ||
+ | SBC HL, BC ;angle - 180 | ||
+ | SBC HL, BC | ||
+ | JR GETTAB ;get table value | ||
+ | |||
+ | TEST4: LD HL, 360 ;if angle >=270 | ||
+ | SBC HL, DE ;HL = 360 - angle | ||
+ | |||
+ | GETTAB: ADD HL, HL ;angle * 2 | ||
+ | LD DE, SINTAB ;+ start table | ||
+ | ADD HL, DE ;= tableaddress | ||
+ | LD E, (HL) ;lowbyte to E | ||
+ | INC HL | ||
+ | LD D, (HL) ;highbyte to D | ||
+ | EX DE, HL ;result to HL | ||
+ | RET | ||
+ | |||
+ | ;***** | ||
+ | ;Sinustable for angles between 0..90 degrees | ||
+ | ;***** | ||
+ | ;Values*32767 | ||
+ | |||
+ | SINTAB: | ||
+ | DW 0,572,1144,1715,2286 | ||
+ | DW 2856,3425,3993,4560,5126 | ||
+ | DW 5690,6252,6813,7371,7927 | ||
+ | DW 8481,9032,9580,10126,10668 | ||
+ | DW 11207,11743,12275,12803,13328 | ||
+ | DW 13848,14364,14876,15383,15886 | ||
+ | DW 16384,16876,17364,17846,18323 | ||
+ | DW 18794,19260,19720,20173,20621 | ||
+ | DW 21062,21497,21925,22347,22762 | ||
+ | DW 23170,23571,23964,24351,24730 | ||
+ | DW 25101,25465,25821,26169,26509 | ||
+ | DW 26841,27165,27481,27788,28087 | ||
+ | DW 28377,28659,28932,29196,29451 | ||
+ | DW 29697,29934,30162,30381,30591 | ||
+ | DW 30791,30982,31163,31335,31498 | ||
+ | DW 31650,31794,31927,32051,32165 | ||
+ | DW 32269,32364,32448,32523,32587 | ||
+ | DW 32642,32687,32722,32747,32762 | ||
+ | DW 32767 | ||
+ | </pre> | ||
+ | |||
== Calculation using the CORDIC algorithm == | == Calculation using the CORDIC algorithm == | ||
− | Andre Adrian wrote a paper about how to implement the calculation of sin/cos on Z80 CPUs. You can read the paper and find the implementation on his homepage http:// | + | Andre Adrian wrote a paper about how to implement the calculation of sin/cos on Z80 CPUs. You can read the paper and find the implementation on his homepage http://www.andreadrian.de/oldcpu/Z80_number_cruncher.html . |
[[Category:Programming]] | [[Category:Programming]] |
Latest revision as of 09:15, 24 February 2010
Calculation using lookup table
The calculation is based on a table from 0-90° and on values which are multiplicated by 32767. If you want to get the correct sinus value, you have to divide them by 32767 (you can use 32768 - not a big precision lost, but you can use bit shifting).
Input: HL = angle in degree (0-360°)
Output: HL = SIN(HL) * 32767, A = sign flag (0 if positive, &FF if negative)
INTSIN: LD BC, 360 LOOP1: BIT 7, H ;angle positive? JR Z, LOOP2 ;-> yes, ok ADD HL, BC ;else add 360 JR LOOP1 ;repeat until H>0 LOOP2: OR A ;reset carry SBC HL, BC ;angle - 360 JR NC, LOOP2 ;->ok if >=0 ADD HL, BC ;else correct value LD E, L ;angle to DE LD D, H LD BC, 90 XOR A ;sign flag = 0 SBC HL, BC ;angle < 90? JR NC, TEST2 ;-> no EX DE, HL ;else HL = angle JR GETTAB ;get table value TEST2: SBC HL, BC ;angle < 180? JR NC, TEST3 ;-> no LD HL, 180 ;else HL = OR A ;180 - angle SBC HL, DE JR GETTAB ;get table value TEST3: DEC A ;sign flag &FF SBC HL, BC ;angle < 270? JR NC, TEST4 ;-> no EX DE, HL ;else HL = OR A ;clear carry SBC HL, BC ;angle - 180 SBC HL, BC JR GETTAB ;get table value TEST4: LD HL, 360 ;if angle >=270 SBC HL, DE ;HL = 360 - angle GETTAB: ADD HL, HL ;angle * 2 LD DE, SINTAB ;+ start table ADD HL, DE ;= tableaddress LD E, (HL) ;lowbyte to E INC HL LD D, (HL) ;highbyte to D EX DE, HL ;result to HL RET ;***** ;Sinustable for angles between 0..90 degrees ;***** ;Values*32767 SINTAB: DW 0,572,1144,1715,2286 DW 2856,3425,3993,4560,5126 DW 5690,6252,6813,7371,7927 DW 8481,9032,9580,10126,10668 DW 11207,11743,12275,12803,13328 DW 13848,14364,14876,15383,15886 DW 16384,16876,17364,17846,18323 DW 18794,19260,19720,20173,20621 DW 21062,21497,21925,22347,22762 DW 23170,23571,23964,24351,24730 DW 25101,25465,25821,26169,26509 DW 26841,27165,27481,27788,28087 DW 28377,28659,28932,29196,29451 DW 29697,29934,30162,30381,30591 DW 30791,30982,31163,31335,31498 DW 31650,31794,31927,32051,32165 DW 32269,32364,32448,32523,32587 DW 32642,32687,32722,32747,32762 DW 32767
Calculation using the CORDIC algorithm
Andre Adrian wrote a paper about how to implement the calculation of sin/cos on Z80 CPUs. You can read the paper and find the implementation on his homepage http://www.andreadrian.de/oldcpu/Z80_number_cruncher.html .