Skip to content

Instantly share code, notes, and snippets.

@Zeda
Last active February 4, 2022 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zeda/98aab98fd32a231b878772a435ffb306 to your computer and use it in GitHub Desktop.
Save Zeda/98aab98fd32a231b878772a435ffb306 to your computer and use it in GitHub Desktop.
8-bit Sine Approximation using bit twiddling
#!/usr/bin/python3
# This is ported from:
# https://www.omnimaga.org/asm-language/sine-approximation-(z80)/
# (Xeda112358 a.k.a. Zeda a.k.a. ZedaZ80)
#
from math import sin
def sineb(x):
"""Approximates 128*sin(x*2*pi/256)"""
a1 = int(x)
a0 = a1 << 1
a2 = a1 >> 1
# iteration 1
if a1 & 64:
l = ~a0 & 127
else:
l = a0 & 127
# iteration 2
if a1 & 32:
l += ~a1 & 31 # 30 will have better overall accuracy, but a more jagged curve
else:
l += a1 & 31 # 30
# iteration 3
if a1 & 16:
l += ~a2 & 7 # 6 will have better overall accuracy, but a more jagged curve
else:
l += a2 & 7 # 6
# check if it needs to be negated
if a1 & 128:
return -l
else:
return l
# Plot a graph of the approximation vs the actual
for x in range(0, 256, 2):
y = sineb(x)
z = int(sin(x*3.1415926535/128)*128)
# translate and scale for "graphing"
y += 128
z += 128
y >>= 1
z >>= 1
# "graph"
# X - Approximation
# O - Actual
# 8 - used when the graphs overlap
if y == z:
print(" "*y + "8")
elif y > z:
print(" "*z + "O" + " "*(y-z-1) + "X")
else:
print(" "*y + "X" + " "*(z-y-1) + "O")
cosine:
; same inputs/outputs as sine
add a,64 ; cos(x) = sin(x + pi/2)
sine:
;Approximates 128*sin(A*2*pi/256)
;Input:
; A is the input, [0, 256) map to [0, 2pi)
;Output:
; A is the result
; C is a copy of the input
;Destroys:
; B, L
;
;Speed: 137cc or 149cc (if the input is >= 128)
;Size: 37 bytes
;
ld c,a ; a1
add a,a
add a,a
ld b,a ; a2
sbc a,a
xor b
rra
ld l,a
ld a,c
and 32
add a,-32
sbc a,a
xor c
and 31 ; Change to `30` for a jagged curve, but better average performance
add a,l
ld l,a
ld a,c
rra
ld b,a
and 8
add a,-8
sbc a,a
xor b
and 7 ; Change to `6` for a jagged curve, but better average performance
add a,l
bit 7,c
ret z
neg
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment