From eb8643ddbef43547eb7bfe58789a3908926c7258 Mon Sep 17 00:00:00 2001 From: Vaino Kauppila Date: Sun, 19 Apr 2026 12:32:58 +0300 Subject: refactor dir structure, add fib.c --- fw/blink.c | 35 ++++++++++++++++++++++++ fw/fib.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fw/test_uart.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 fw/blink.c create mode 100644 fw/fib.c create mode 100644 fw/test_uart.c (limited to 'fw') diff --git a/fw/blink.c b/fw/blink.c new file mode 100644 index 0000000..6789b0a --- /dev/null +++ b/fw/blink.c @@ -0,0 +1,35 @@ +#include + +typedef unsigned char uint8_t; + +// Global volatile so sdcc cannot optimise the delay loops away. +static volatile uint8_t _d0, _d1, _d2; + +// Busy-wait ~500 ms at 50 MHz. +// 200 × 256 × 256 = 13 107 200 inner iterations. +// Each iteration ≈ 3 uint8_t instructions × 20 ns = 60 ns. +// Total ≈ 786 ms (tune outer count _d0 < N to taste). +static void delay(void) { + _d0 = 0; + do { + _d1 = 0; + do { + _d2 = 0; + do { _d2++; } while (_d2 != 0); + } while (++_d1 != 30); + _d0++; + } while (_d0 != 116); +} + +void main(void) { + // port_b(0) drives activity_led at E8 on the Tang Primer 25K. + // port_a(0) drives led at L6. Both ports are always outputs in this CPU. + while (1) { + PORTB = 0x01; // activity_led (E8) on + PORTA = 0x01; // led (L6) on + delay(); + PORTB = 0x00; // activity_led (E8) off + PORTA = 0x00; // led (L6) off + delay(); + } +} diff --git a/fw/fib.c b/fw/fib.c new file mode 100644 index 0000000..2ba9535 --- /dev/null +++ b/fw/fib.c @@ -0,0 +1,84 @@ +#include + +typedef unsigned char uint8_t; + +__sfr __at(0x70) UART_TX; +__sfr __at(0x71) UART_RX; +__sfr __at(0x72) UART_STATUS; + +static volatile uint8_t _d0, _d1, _d2; + +// Custom delay to make the output readable at 50MHz +static void delay(void) { + _d0 = 0; + do { + _d1 = 0; + do { + _d2 = 0; + do { _d2++; } while (_d2 != 0); + } while (++_d1 != 50); // Increased for 50MHz visibility + _d0++; + } while (_d0 != 20); +} + +static void uart_send(uint8_t byte) { + while (UART_STATUS & 0x01); + UART_TX = byte; +} + +static void uart_puts_rom(const char *s) { + while (*s) { + uart_send((uint8_t)*s); + s++; + } +} + +// Simple BCD printer for 8-bit numbers +void print_uint8(uint8_t v) { + uint8_t started = 0; + + // Hundreds + if (v >= 200) { uart_send('2'); v -= 200; started = 1; } + else if (v >= 100) { uart_send('1'); v -= 100; started = 1; } + + // Tens + uint8_t tens = '0'; + while (v >= 10) { v -= 10; tens++; } + if (started || tens != '0') { uart_send(tens); } + + // Units + uart_send(v + '0'); +} + +void main(void) { + uint8_t a, b, next; + + uart_puts_rom("\x1B[2J\x1B[H"); // Clear screen, Home cursor + uart_puts_rom("PIC16F84A @ 50MHz Fibonacci\r\n"); + uart_puts_rom("---------------------------\r\n"); + + while (1) { + a = 0; + b = 1; + + while (a <= 233) { // Max 8-bit Fib is 233 + print_uint8(a); + uart_puts_rom(", "); + + next = a + b; + a = b; + b = next; + + delay(); + + // Break before overflow + if (a == 233) { + print_uint8(a); + break; + } + } + + uart_puts_rom("\r\nRestarting...\r\n"); + delay(); + } +} diff --git a/fw/test_uart.c b/fw/test_uart.c new file mode 100644 index 0000000..4e18dc5 --- /dev/null +++ b/fw/test_uart.c @@ -0,0 +1,69 @@ +#include + +typedef unsigned char uint8_t; + +__sfr __at(0x70) UART_TX; +__sfr __at(0x71) UART_RX; +__sfr __at(0x72) UART_STATUS; + +static volatile uint8_t _d0, _d1, _d2; +static uint8_t counter; + +static void delay(void) { + _d0 = 0; + do { + _d1 = 0; + do { + _d2 = 0; + do { _d2++; } while (_d2 != 0); + } while (++_d1 != 30); + _d0++; + } while (_d0 != 10); +} + +static void uart_send(uint8_t byte) { + while (UART_STATUS & 0x01); + UART_TX = byte; +} + +// Keep this ONLY for literal strings (ROM) +static void uart_puts_rom(const char *s) { + while (*s) { + uart_send((uint8_t)*s); + s++; + } +} + +void main(void) { + counter = 0; + uart_puts_rom("counter\r\n"); + + while (1) { + uint8_t v = counter; + uint8_t started = 0; + + + uart_puts_rom("\r"); + uart_puts_rom("\x1B[K"); + + uart_send('C'); + uart_send(':'); + + // Hundreds + if (v >= 200) { uart_send('2'); v -= 200; started = 1; } + else if (v >= 100) { uart_send('1'); v -= 100; started = 1; } + + // Tens + { + uint8_t tens = '0'; + while (v >= 10) { v -= 10; tens++; } + if (started || tens != '0') { uart_send(tens); } + } + + // Units (always) + uart_send(v + '0'); + + counter++; + delay(); + } +} -- cgit v1.3