summaryrefslogtreecommitdiffstats
path: root/fw
diff options
context:
space:
mode:
authorVaino Kauppila <vaino@vke.fi>2026-04-19 12:32:58 +0300
committerVaino Kauppila <vaino@vke.fi>2026-04-19 12:32:58 +0300
commiteb8643ddbef43547eb7bfe58789a3908926c7258 (patch)
treefadfba88a1c71b266b8c67df166a3a6ead6b30d1 /fw
parent129a1c975dbd0c042576010b1f6eb40d19fc5733 (diff)
downloadvhdl_pic-eb8643ddbef43547eb7bfe58789a3908926c7258.tar.gz
vhdl_pic-eb8643ddbef43547eb7bfe58789a3908926c7258.zip
refactor dir structure, add fib.c
Diffstat (limited to 'fw')
-rw-r--r--fw/blink.c35
-rw-r--r--fw/fib.c84
-rw-r--r--fw/test_uart.c69
3 files changed, 188 insertions, 0 deletions
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 <pic16f84a.h>
+
+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 <pic16f84a.h>
+
+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 <pic16f84a.h>
+
+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();
+ }
+}