226 lines
8.0 KiB
C
226 lines
8.0 KiB
C
#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);
|
|
}
|
|
}
|