Files
barnum/barnumbak.c

226 lines
8.0 KiB
C
Raw Permalink Normal View History

2025-07-26 21:48:13 -04:00
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/i2c.h"
#include "hardware/dma.h"
#include "hardware/pio.h"
#include "hardware/interp.h"
#include "hardware/timer.h"
#include "hardware/watchdog.h"
#include "hardware/uart.h"
// RP2040-ETH board CH9120 ethernet chip defines
#define CH9120_UART_ID uart0
#define CH9120_RXD_PIN 21 // Serial data input to CH9120
#define CH9120_TXD_PIN 20 // Serial data output from CH9120
#define CH9120_TCPCS_PIN 17 // TCP client connection status
#define CH9120_CFG0_PIN 18 // Network configuration pin
#define CH9120_RSTI_PIN 19 // Reset pin (active LOW)
// SPI Defines for RP2040-ETH
// Using available pins that don't conflict with CH9120 ethernet chip
// CH9120 uses pins 17-21, so we avoid those
#define SPI_PORT spi0
#define PIN_MISO 0
#define PIN_CS 1
#define PIN_SCK 2
#define PIN_MOSI 3
// I2C defines for RP2040-ETH
// Using I2C0 on available pins that don't conflict with CH9120
#define I2C_PORT i2c0
#define I2C_SDA 4
#define I2C_SCL 5
// Data will be copied from src to dst
const char src[] = "Hello, world! (from DMA)";
char dst[count_of(src)];
#include "blink.pio.h"
#include "ws2812.pio.h"
void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq) {
blink_program_init(pio, sm, offset, pin);
pio_sm_set_enabled(pio, sm, true);
printf("Blinking pin %d at %d Hz\n", pin, freq);
// PIO counter program takes 3 more cycles in total than we pass as
// input (wait for n + 1; mov; jmp)
pio->txf[sm] = (125000000 / (2 * freq)) - 3;
}
void put_pixel(uint32_t pixel_grb) {
pio_sm_put_blocking(pio0, 0, pixel_grb << 8u); // Use state machine 0
}
void put_rgb(uint8_t red, uint8_t green, uint8_t blue) {
uint32_t mask = (green << 16) | (red << 8) | (blue << 0);
put_pixel(mask);
}
int64_t alarm_callback(alarm_id_t id, void *user_data) {
// Put your timeout handler code in here
return 0;
}
// UART defines for RP2040-ETH
// By default the stdout UART is `uart0`, so we will use the second one
// Note: CH9120 ethernet chip uses UART0 on pins 20-21
#define UART_ID uart1
#define BAUD_RATE 115200
// Use pins 8 and 9 for UART1 (avoiding CH9120 pins)
#define UART_TX_PIN 8
#define UART_RX_PIN 9
int main()
{
stdio_init_all();
// SPI initialisation. This example will use SPI at 1MHz.
spi_init(SPI_PORT, 1000*1000);
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(PIN_CS, GPIO_FUNC_SIO);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
// Chip select is active-low, so we'll initialise it to a driven-high state
gpio_set_dir(PIN_CS, GPIO_OUT);
gpio_put(PIN_CS, 1);
// For more examples of SPI use see https://github.com/raspberrypi/pico-examples/tree/master/spi
// I2C Initialisation. Using it at 400Khz.
i2c_init(I2C_PORT, 400*1000);
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(I2C_SDA);
gpio_pull_up(I2C_SCL);
// For more examples of I2C use see https://github.com/raspberrypi/pico-examples/tree/master/i2c
// Get a free channel, panic() if there are none
int chan = dma_claim_unused_channel(true);
// 8 bit transfers. Both read and write address increment after each
// transfer (each pointing to a location in src or dst respectively).
// No DREQ is selected, so the DMA transfers as fast as it can.
dma_channel_config c = dma_channel_get_default_config(chan);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, true);
dma_channel_configure(
chan, // Channel to be configured
&c, // The configuration we just created
dst, // The initial write address
src, // The initial read address
count_of(src), // Number of transfers; in this case each is 1 byte.
true // Start immediately.
);
// We could choose to go and do something else whilst the DMA is doing its
// thing. In this case the processor has nothing else to do, so we just
// wait for the DMA to finish.
dma_channel_wait_for_finish_blocking(chan);
// The DMA has now copied our text from the transmit buffer (src) to the
// receive buffer (dst), so we can print it out from there.
puts(dst);
// PIO Blinking example
PIO pio = pio0;
uint offset = pio_add_program(pio, &blink_program);
printf("Loaded blink program at %d\n", offset);
// WS2812B RGB LED on pin 25 (RP2040-ETH board)
uint ws2812_offset = pio_add_program(pio, &ws2812_program);
printf("Loaded WS2812B program at %d\n", ws2812_offset);
ws2812_program_init(pio, 0, ws2812_offset, 25, 800000, false); // Use state machine 0
printf("WS2812B RGB LED initialized on pin 25\n");
// For more pio examples see https://github.com/raspberrypi/pico-examples/tree/master/pio
// Interpolator example code
interp_config cfg = interp_default_config();
// Now use the various interpolator library functions for your use case
// e.g. interp_config_clamp(&cfg, true);
// interp_config_shift(&cfg, 2);
// Then set the config
interp_set_config(interp0, 0, &cfg);
// For examples of interpolator use see https://github.com/raspberrypi/pico-examples/tree/master/interp
// Timer example code - This example fires off the callback after 2000ms
add_alarm_in_ms(2000, alarm_callback, NULL, false);
// For more examples of timer use see https://github.com/raspberrypi/pico-examples/tree/master/timer
// Watchdog example code
if (watchdog_caused_reboot()) {
printf("Rebooted by Watchdog!\n");
// Whatever action you may take if a watchdog caused a reboot
}
// Enable the watchdog, requiring the watchdog to be updated every 100ms or the chip will reboot
// second arg is pause on debug which means the watchdog will pause when stepping through code
watchdog_enable(100, 1);
// You need to call this function at least more often than the 100ms in the enable call to prevent a reboot
watchdog_update();
// Set up our UART
uart_init(UART_ID, BAUD_RATE);
// Set the TX and RX pins by using the function select on the GPIO
// Set datasheet for more information on function select
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
// Use some the various UART functions to send out data
// In a default system, printf will also output via the default UART
// Send out a string, with CR/LF conversions
uart_puts(UART_ID, " Hello, UART!\n");
// For more examples of UART use see https://github.com/raspberrypi/pico-examples/tree/master/uart
// Initialize CH9120 ethernet chip
uart_init(CH9120_UART_ID, 115200);
gpio_set_function(CH9120_TXD_PIN, GPIO_FUNC_UART);
gpio_set_function(CH9120_RXD_PIN, GPIO_FUNC_UART);
// Configure CH9120 control pins
gpio_init(CH9120_TCPCS_PIN);
gpio_set_dir(CH9120_TCPCS_PIN, GPIO_IN);
gpio_init(CH9120_CFG0_PIN);
gpio_set_dir(CH9120_CFG0_PIN, GPIO_OUT);
gpio_put(CH9120_CFG0_PIN, 0); // Normal operation mode
gpio_init(CH9120_RSTI_PIN);
gpio_set_dir(CH9120_RSTI_PIN, GPIO_OUT);
gpio_put(CH9120_RSTI_PIN, 1); // Release reset (active LOW)
printf("CH9120 ethernet chip initialized\\n");
uint8_t state = 0;
while (true) {
printf("Hello, world!\n");
// Simple color cycling - solid colors
switch(state % 6) {
case 0: put_rgb(255, 0, 0); break; // Red
case 1: put_rgb(255, 128, 0); break; // Orange
case 2: put_rgb(255, 255, 0); break; // Yellow
case 3: put_rgb(0, 255, 0); break; // Green
case 4: put_rgb(0, 0, 255); break; // Blue
case 5: put_rgb(128, 0, 255); break; // Purple
}
state++;
sleep_ms(1000);
}
}