Lissajous, showing floating point arithmetic

This commit is contained in:
Toby Jaffey 2025-12-08 21:20:57 +00:00
parent de689bdeaf
commit ebb6518ec3
5 changed files with 148 additions and 0 deletions

View file

@ -21,6 +21,7 @@ Although based on a fully fledged CPU emulator, uvm32 is intended for executing
* [host-arduino](host-arduino) vm host as Arduino sketch (tested on Arduino Uno ATmega328P, uses 9950 bytes of flash/1254 bytes RAM)
* [apps/helloworld](apps/helloworld) C hello world program
* [apps/conio](apps/conio) C console IO demo
* [apps/lissajous](apps/lissajour) C console lissajous curve (showing softfp, floating point)
* [apps/hello-asm](apps/hello-asm) Minimal hello world assembly
* [apps/fib](apps/fib) C fibonacci series program (iterative and recursive)
* [apps/sketch](apps/sketch) C Arduino/Wiring/Processing type program in `setup()` and `loop()` style

View file

@ -4,6 +4,7 @@ all:
docker build -t ${DOCKER_IMAGE} .
(cd sketch && make)
(cd helloworld && make)
(cd lissajous && make)
(cd conio && make)
(cd zig-mandel && make)
(cd zigtris && make)
@ -13,6 +14,7 @@ all:
clean:
(cd sketch && make clean)
(cd helloworld && make clean)
(cd lissajous && make clean)
(cd conio && make clean)
(cd zig-mandel && make clean)
(cd zigtris && make clean)

27
apps/lissajous/Makefile Normal file
View file

@ -0,0 +1,27 @@
PROJECT:=lissajous
DOCKER_IMAGE=riscv-dev
DOCKER_CMD:=docker run --rm -v ${PWD}../../../:/data -w /data/apps/${PROJECT} ${DOCKER_IMAGE}
PREFIX:=${DOCKER_CMD} riscv64-unknown-elf-
CFLAGS+=-I../../common
CFLAGS+=-fno-stack-protector
CFLAGS+=-static-libgcc -fdata-sections -ffunction-sections
CFLAGS+=-g -Os -march=rv32ima_zicsr -mabi=ilp32 -static
LDFLAGS:= -T ../linker.ld -nostdlib -Wl,--gc-sections
LIBS:= -lgcc # needed for softfp
SRCS=${PROJECT}.c ../crt0.S
all:
${PREFIX}gcc -o ${PROJECT}.elf ${CFLAGS} ${LDFLAGS} ${SRCS} ${LIBS}
$(PREFIX)objcopy ${PROJECT}.elf -O binary ${PROJECT}.bin
disasm: all
$(PREFIX)objdump -S -d -f ${PROJECT}.elf
test: all
../../host/host ${PWD}/${PROJECT}.bin
clean:
rm -f ${PROJECT}.o ${PROJECT}.elf ${PROJECT}.bin

118
apps/lissajous/lissajous.c Normal file
View file

@ -0,0 +1,118 @@
#define USE_MAIN
#include "uvm32_target.h"
// https://github.com/shastro/CodeGolf-Lissajous/blob/master/lissa.c
// https://github.com/nicbk/donut-embedded/blob/ad8061ece9a2c156694c39af12f109ea6778da52/donut.c#L57
#define PI 3.14159265358979323846 // First 21 digits of pi
void movecursor(int x, int y) {
print("\033[");
printdec(y);
print(";");
printdec(x);
print("f");
}
void sleep(uint32_t ms) {
uint32_t start = millis();
while (millis() < start + ms) {
yield();
}
}
// Absolute value function for doubles
double abs_c(double x) {
if (x < 0) {
return -x;
} else {
return x;
}
}
// Recursive factorial capable of calculating a max of approximately 10^18 in size
unsigned long long fac(unsigned char x) {
if (x == 0) {
return 1;
} else {
return x * fac(x - 1);
}
}
// Exponential function
// Ignores edge cases such as indeterminate forms for simplicity
double pow_c(double x, unsigned char n) {
if (n == 0) {
return 1;
} else {
double product = x;
for (int i = 1; i < n; ++i) {
product *= x;
}
return product;
}
}
// MacLaurin series approximation of sin(x) from -PI/2 to PI/2
// with eight terms, and extended to the domain of all
// real numbers with modular arithmetic.
double sin(double x) {
double translation = 0;
if (x > -PI / 2) {
translation = (int)((x + PI / 2) / PI);
} else {
translation = (int)((x - PI / 2) / PI);
}
x -= PI * translation;
if ((int)abs_c(translation) % 2 == 1) {
x = -x;
}
double sum = 0;
for (int i = 0; i < 9; ++i) {
sum += pow_c(-1, i) * pow_c(x, 2 * i + 1) / fac(2 * i + 1);
}
return sum;
}
// cos(x) function derived from sin(x)
double cos(double x) {
return sin(PI / 2 - x);
}
void main(void) {
int freq1 = 45;
int freq2 = 90;
for (int i = 0; i < 300; i++) {
putc('\n');
}
print("\033[H"); // Cursor at Corner of Screen
float x = 0;
float y = 0;
float angle = 0;
float beta = 0.0;
while (1) {
uint32_t framestart = millis();
for (angle = 0; angle < 2 * PI; angle += 0.15) {
movecursor(x, y);
x = 40 * cos(freq1 * angle + beta) + 60;
y = 20 * sin(freq2 * angle) + 30;
print("#");
}
// wait for next frame
while (millis() < framestart + 20) {
yield();
}
beta += 0.05;
print("\033[2J");
}
}

BIN
precompiled/lissajous.bin Executable file

Binary file not shown.