mirror of https://github.com/radex/radmatrix.git
extract config.h
parent
0c2f64a973
commit
a2f703c2e1
|
@ -5,8 +5,6 @@
|
|||
#include "hardware/gpio.h"
|
||||
#include "audio.h"
|
||||
|
||||
// #include "audio_sample.h"
|
||||
|
||||
// Adapted from https://github.com/rgrosset/pico-pwm-audio
|
||||
|
||||
#define MAX_PWM_POS (BUFFER_LEN << 3)
|
||||
|
@ -42,9 +40,8 @@ void pwm_interrupt_handler() {
|
|||
}
|
||||
|
||||
// 11 KHz is fine for speech. Phone lines generally sample at 8 KHz
|
||||
#define SYS_CLOCK 125000000.0f
|
||||
#define AUDIO_WRAP 256.0f
|
||||
#define AUDIO_CLK_DIV (SYS_CLOCK / AUDIO_WRAP / 8.0f / AUDIO_RATE)
|
||||
#define AUDIO_CLK_DIV (CPU_CLOCK_HZ / AUDIO_WRAP / 8.0f / AUDIO_RATE)
|
||||
|
||||
void init_audio() {
|
||||
gpio_set_function(AUDIO_PIN, GPIO_FUNC_PWM);
|
||||
|
|
|
@ -3,11 +3,7 @@
|
|||
#ifndef _audio_h
|
||||
#define _audio_h
|
||||
|
||||
#define AUDIO_PIN 8
|
||||
|
||||
#define AUDIO_RATE 44000.0f
|
||||
#define BUFFER_LEN 512*16
|
||||
#define BUFFER_LEN_MS (BUFFER_LEN / AUDIO_RATE) * 1000.0f
|
||||
#include "config.h"
|
||||
|
||||
extern uint8_t wav_buffer_0[BUFFER_LEN];
|
||||
extern uint8_t wav_buffer_1[BUFFER_LEN];
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
|
||||
#define CPU_MHZ ((uint32_t) CPU_CLOCK_HZ / 1000000)
|
||||
#define NS_PER_CYCLE (1000 / CPU_MHZ)
|
||||
#define NS_TO_DELAY(ns) (ns / NS_PER_CYCLE / LEDS_PIO_CLKDIV)
|
||||
|
||||
// delays in nanoseconds per brightness phase (i.e. depth bit index)
|
||||
uint32_t brightnessPhaseDelays[COLOR_BITS] = {
|
||||
// NOTE: 100ns seems to be the minimum that's (barely) visible on current hardware
|
||||
/* 1 */ NS_TO_DELAY(170),
|
||||
/* 2 */ NS_TO_DELAY(180),
|
||||
/* 4 */ NS_TO_DELAY(210),
|
||||
/* 8 */ NS_TO_DELAY(540),
|
||||
/* 16 */ NS_TO_DELAY(2300), // x2
|
||||
/* 32 */ NS_TO_DELAY(3000), // x4
|
||||
/* 64 */ NS_TO_DELAY(2500), // x10
|
||||
/* 128 */ NS_TO_DELAY(3300), // x20
|
||||
};
|
||||
|
||||
uint8_t brightnessPhaseDithering[COLOR_BITS] = {
|
||||
// Out of DITHERING_PHASES, how many of these should a given
|
||||
// brightness phase be displayed?
|
||||
// NOTE: This is done brecause for small delays, pixel pushing dominates the time, making
|
||||
// the display's duty cycle (and hence brightness) low. But since these less significant bits
|
||||
// contribute little to the overall brightness, and overall displaying time is short (a fraction of
|
||||
// a framerate), we can skip displaying these small brightness levels most of the time.
|
||||
/* 1 */ 1,
|
||||
/* 2 */ 1,
|
||||
/* 4 */ 1,
|
||||
/* 8 */ 1,
|
||||
/* 16 */ 2,
|
||||
/* 32 */ 4,
|
||||
/* 64 */ 10,
|
||||
/* 128 */ 20,
|
||||
};
|
|
@ -0,0 +1,95 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef _config_h
|
||||
#define _config_h
|
||||
|
||||
// --- pinout ---
|
||||
|
||||
#define AUDIO_PIN 8
|
||||
|
||||
#define SD_PIN_SS 1
|
||||
#define SD_PIN_SCK 2
|
||||
#define SD_PIN_MOSI 3
|
||||
#define SD_PIN_MISO 0
|
||||
#define SD_HAS_DETECTION true
|
||||
#define SD_DET_PIN 4
|
||||
|
||||
#define CAN_ENABLED false
|
||||
#define CAN_PIN_RX 5
|
||||
#define CAN_PIN_TX 7
|
||||
#define CAN_PIN_SILENT 6
|
||||
|
||||
#define UART_TX_PIN 16
|
||||
#define UART_RX_PIN 17
|
||||
|
||||
// NOTE: with current layout, 9-15 are free GPIOs (14, 15 only when using shared SER, SRCLR)
|
||||
#define NEXT_PIN 9
|
||||
|
||||
#define CC1_PIN 26
|
||||
#define CC2_PIN 27
|
||||
#define V_SENSE_PIN 28
|
||||
#define I_SENSE_PIN 29
|
||||
|
||||
// --- pinout - screen ---
|
||||
|
||||
#define COMMON_SER 21
|
||||
// #define COMMON_RCLK 23
|
||||
#define COMMON_SRCLR 25
|
||||
|
||||
// #define COL_SER 21
|
||||
#define COL_OE 22
|
||||
#define COL_RCLK 23
|
||||
#define COL_SRCLK 24
|
||||
// #define COL_SRCLR 25
|
||||
|
||||
// #define ROW_SER 14
|
||||
#define ROW_OE 13
|
||||
#define ROW_RCLK 20
|
||||
#define ROW_SRCLK 18
|
||||
// #define ROW_SRCLR 15
|
||||
|
||||
// --- screen settings ---
|
||||
|
||||
#define ROW_MODULES 2
|
||||
#define COL_MODULES 2
|
||||
|
||||
#define COLOR_BITS 8
|
||||
|
||||
#define MAX_FPS 30
|
||||
#define MAX_LENGTH_MIN 10
|
||||
|
||||
#define ROW_COUNT ROW_MODULES * 20
|
||||
#define COL_COUNT COL_MODULES * 20
|
||||
|
||||
// --- audio settings ---
|
||||
|
||||
#define AUDIO_RATE 44000.0f
|
||||
#define BUFFER_LEN 512*16
|
||||
|
||||
// --- other settings ---
|
||||
|
||||
#define CPU_CLOCK_HZ 125000000.0f
|
||||
#define SD_CARD_BAUD_RATE 10 * 1000 * 1000
|
||||
#define REFERENCE_VOLTAGE 3.3f // for ADC
|
||||
|
||||
// --- debug settings ---
|
||||
|
||||
#define DEBUG_TEST_FRAME false
|
||||
#define DEBUG_FIRST_FRAME false
|
||||
#define DEBUG_FRAMEBUFFER false
|
||||
|
||||
// --- screen - performance ---
|
||||
// NOTE: In case of screen glitching, these may need to be tweaked to decrease
|
||||
// data rate to the display and stay within the limits of the hardware/electrical connection
|
||||
#define LEDS_PIO_CLKDIV 1
|
||||
// Also see leds.pio where delays may be adjusted (need manual compilation)
|
||||
|
||||
// --- screen - color correction ---
|
||||
// I do not understand color correction, gamma, it's all black magic to me
|
||||
// This was manually tuned using DEBUG_TEST_FRAME=true test pattern
|
||||
// See config.cpp
|
||||
extern uint32_t brightnessPhaseDelays[COLOR_BITS];
|
||||
extern uint8_t brightnessPhaseDithering[COLOR_BITS];
|
||||
#define DITHERING_PHASES 20;
|
||||
|
||||
#endif
|
|
@ -3,10 +3,10 @@
|
|||
#include "lodepng.h"
|
||||
#include "leds.h"
|
||||
|
||||
uint16_t gfxFrameLengthsBuffer[24000] = {0};
|
||||
uint16_t gfxFrameLengthsBuffer[GFX_DECODER_LENGTH_BUFFER_SIZE] = {0};
|
||||
uint16_t frameCount = 0;
|
||||
|
||||
uint8_t gfxFrameBuffer[6400] = {0};
|
||||
uint8_t gfxFrameBuffer[GFX_DECODER_FRAME_BUFFER_SIZE] = {0};
|
||||
|
||||
int32_t gfx_decoder_loadNextFrame() {
|
||||
// load frame from SD card
|
||||
|
|
|
@ -3,10 +3,14 @@
|
|||
#define GFX_DECODER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
|
||||
extern uint16_t gfxFrameLengthsBuffer[24000];
|
||||
#define GFX_DECODER_LENGTH_BUFFER_SIZE MAX_LENGTH_MIN * 60 * MAX_FPS
|
||||
#define GFX_DECODER_FRAME_BUFFER_SIZE ROW_COUNT * COL_COUNT * 4
|
||||
|
||||
extern uint16_t gfxFrameLengthsBuffer[GFX_DECODER_LENGTH_BUFFER_SIZE];
|
||||
extern uint16_t frameCount;
|
||||
extern uint8_t gfxFrameBuffer[6400];
|
||||
extern uint8_t gfxFrameBuffer[GFX_DECODER_FRAME_BUFFER_SIZE];
|
||||
|
||||
int32_t gfx_decoder_loadNextFrame();
|
||||
int32_t gfx_decoder_handleLoop();
|
||||
|
|
|
@ -11,12 +11,9 @@ uint pusher_sm = 255; // invalid
|
|||
uint delay_sm = 255; // invalid
|
||||
uint row_sm = 255; // invalid
|
||||
|
||||
#define LEDS_PIO_CLKDIV 1
|
||||
|
||||
// NOTE: RCLK, SRCLK capture on *rising* edge
|
||||
inline void pulsePin(uint8_t pin) {
|
||||
gpio_put(pin, HIGH);
|
||||
// there are glitches without this (maybe just due to breadboard...)
|
||||
asm volatile("nop \n nop \n nop");
|
||||
gpio_put(pin, LOW);
|
||||
}
|
||||
|
@ -34,42 +31,11 @@ inline void outputEnable(uint8_t pin, bool enable) {
|
|||
// we have COLOR_BITS-bit color depth, so 2^COLOR_BITS levels of brightness
|
||||
// we go from phase 0 to phase (COLOR_BITS-1)
|
||||
uint8_t brightnessPhase = 0;
|
||||
|
||||
// delays in nanoseconds
|
||||
#define NS_TO_DELAY(ns) (ns / NS_PER_CYCLE / LEDS_PIO_CLKDIV)
|
||||
uint32_t brightnessPhaseDelays[COLOR_BITS] = {
|
||||
// NOTE: 100ns seems to be the minimum that's (barely) visible
|
||||
/* 1 */ NS_TO_DELAY(170),
|
||||
/* 2 */ NS_TO_DELAY(180),
|
||||
/* 4 */ NS_TO_DELAY(210),
|
||||
/* 8 */ NS_TO_DELAY(540),
|
||||
/* 16 */ NS_TO_DELAY(2300), // x2
|
||||
/* 32 */ NS_TO_DELAY(3000), // x4
|
||||
/* 64 */ NS_TO_DELAY(2500), // x10
|
||||
/* 128 */ NS_TO_DELAY(3300), // x20
|
||||
};
|
||||
|
||||
#define DITHERING_PHASES 20;
|
||||
uint8_t ditheringPhase = 0;
|
||||
uint8_t brightnessPhaseDithering[COLOR_BITS] = {
|
||||
// Out of DITHERING_PHASES, how many of these should a given
|
||||
// brightness phase be displayed?
|
||||
// NOTE: This is done brecause for small delays, pixel pushing dominates the time, making
|
||||
// the display's duty cycle (and hence brightness) low. But since these less significant bits
|
||||
// contribute little to the overall brightness, and overall displaying time is short (a fraction of
|
||||
// a framerate), we can skip displaying these small brightness levels most of the time.
|
||||
/* 1 */ 1,
|
||||
/* 2 */ 1,
|
||||
/* 4 */ 1,
|
||||
/* 8 */ 1,
|
||||
/* 16 */ 2,
|
||||
/* 32 */ 4,
|
||||
/* 64 */ 10,
|
||||
/* 128 */ 20,
|
||||
};
|
||||
|
||||
// NOTE: Alignment required to allow 4-byte reads
|
||||
uint8_t framebuffer[ROW_COUNT * COL_COUNT] __attribute__((aligned(32))) = {0};
|
||||
#if DEBUG_FRAMEBUFFER
|
||||
uint8_t framebuffer[ROW_COUNT * COL_COUNT] = {0};
|
||||
#endif
|
||||
|
||||
// Framebuffer encoded for fast PIO pixel pushing
|
||||
// There's one buffer for each of pixel's bit indices (aka brightness phases),
|
||||
|
@ -81,13 +47,14 @@ uint8_t framebuffer[ROW_COUNT * COL_COUNT] __attribute__((aligned(32))) = {0};
|
|||
// 1 bit (LSB) to indicate start of frame (1) or not (0)
|
||||
// remaining bits to indicate a number of shift register pulses
|
||||
// (again, 24 shift register stages per 20 rows, so there are placeholders)
|
||||
uint32_t ledBuffer[8][ROW_COUNT * (COL_MODULES + 1)] = {0};
|
||||
uint32_t ledBuffer[COLOR_BITS][ROW_COUNT * (COL_MODULES + 1)] = {0};
|
||||
bool ledBufferReady = false;
|
||||
|
||||
void leds_set_framebuffer(uint8_t *buffer) {
|
||||
// TODO: Use a separate buffer, then copy to ledsBuffer to avoid tearing
|
||||
for (int bi = 0; bi < 8; bi++) {
|
||||
uint8_t bitPosition = 1 << bi;
|
||||
#define UNUSED_BITS 8 - COLOR_BITS
|
||||
for (int bi = 0; bi < COLOR_BITS; bi++) {
|
||||
uint8_t bitPosition = 1 << (bi + UNUSED_BITS);
|
||||
|
||||
for (int yModule = 0; yModule < ROW_MODULES; yModule++) {
|
||||
for (int moduleY = 0; moduleY < 20; moduleY++) {
|
||||
|
@ -142,13 +109,17 @@ void leds_set_framebuffer(uint8_t *buffer) {
|
|||
}
|
||||
ledBufferReady = true;
|
||||
|
||||
#if DEBUG_FRAMEBUFFER
|
||||
// copy to framebuffer
|
||||
// TODO: mutex? double buffer? or something...
|
||||
memcpy(framebuffer, buffer, ROW_COUNT * COL_COUNT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void leds_init() {
|
||||
#if DEBUG_FRAMEBUFFER
|
||||
memset(framebuffer, 0, sizeof(framebuffer));
|
||||
#endif
|
||||
|
||||
// disable output
|
||||
outputEnable(COL_OE, false);
|
||||
|
@ -192,14 +163,9 @@ void main2() {
|
|||
}
|
||||
}
|
||||
|
||||
void leds_initPusher();
|
||||
void leds_initRowSelector();
|
||||
void leds_initDelay();
|
||||
void leds_initPIO();
|
||||
|
||||
void leds_initRenderer() {
|
||||
leds_initPusher();
|
||||
leds_initRowSelector();
|
||||
leds_initDelay();
|
||||
multicore_reset_core1();
|
||||
multicore_launch_core1(main2);
|
||||
}
|
||||
|
@ -341,3 +307,9 @@ void leds_initDelay() {
|
|||
pio_sm_init(pio, sm, offset, &config);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
void leds_initPIO() {
|
||||
leds_initPusher();
|
||||
leds_initRowSelector();
|
||||
leds_initDelay();
|
||||
}
|
||||
|
|
|
@ -1,24 +1,8 @@
|
|||
#pragma once
|
||||
#ifndef LEDS_H
|
||||
#define LEDS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define COMMON_SER 21
|
||||
// #define COMMON_RCLK 23
|
||||
#define COMMON_SRCLR 25
|
||||
|
||||
// #define COL_SER 21
|
||||
#define COL_OE 22
|
||||
#define COL_RCLK 23
|
||||
#define COL_SRCLK 24
|
||||
// #define COL_SRCLR 25
|
||||
|
||||
// #define ROW_SER 14
|
||||
#define ROW_OE 13
|
||||
#define ROW_RCLK 20
|
||||
#define ROW_SRCLK 18
|
||||
// #define ROW_SRCLR 15
|
||||
#include "config.h"
|
||||
|
||||
#if defined(COMMON_SER) && (defined(ROW_SER) || defined(COL_SER))
|
||||
#error "COMMON_SER and ROW_SER/COL_SER cannot be defined at the same time"
|
||||
|
@ -47,17 +31,9 @@
|
|||
#define ROW_SRCLR COMMON_SRCLR
|
||||
#endif
|
||||
|
||||
#define ROW_MODULES 2
|
||||
#define ROW_COUNT ROW_MODULES * 20
|
||||
#define COL_MODULES 2
|
||||
#define COL_COUNT COL_MODULES * 20
|
||||
|
||||
#define COLOR_BITS 8
|
||||
#define FPS 30
|
||||
#define FPS MAX_FPS
|
||||
#define MS_PER_FRAME (1000 / FPS)
|
||||
|
||||
#define CPU_MHZ 125
|
||||
#define NS_PER_CYCLE (1000 / CPU_MHZ)
|
||||
|
||||
void leds_init();
|
||||
void leds_initRenderer();
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
|
||||
#define CELLS_X 40
|
||||
#define CELLS_Y 40
|
||||
#define CELLS_X COL_MODULES * 20
|
||||
#define CELLS_Y ROW_MODULES * 20
|
||||
#define CELL_COUNT (CELLS_X * CELLS_Y)
|
||||
|
||||
bool cells[CELL_COUNT] = {0};
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
#include "leds.h"
|
||||
#include "gfx_decoder.h"
|
||||
#include "can2040.h"
|
||||
#include "config.h"
|
||||
|
||||
void loadVideo(size_t index);
|
||||
|
||||
void setup() {
|
||||
leds_init();
|
||||
setupSDPins();
|
||||
pinMode(9, INPUT_PULLUP);
|
||||
pinMode(NEXT_PIN, INPUT_PULLUP);
|
||||
|
||||
delay(2000);
|
||||
Serial.begin(115200);
|
||||
|
@ -20,24 +20,32 @@ void setup() {
|
|||
init_audio();
|
||||
leds_initRenderer();
|
||||
|
||||
// while (!isSDCardInserted()) {
|
||||
// Serial.println("SD card not connected, waiting...");
|
||||
// delay(1000);
|
||||
// }
|
||||
// delay(100);
|
||||
#if SD_HAS_DETECTION
|
||||
while (!isSDCardInserted()) {
|
||||
Serial.println("SD card not connected, waiting...");
|
||||
delay(1000);
|
||||
}
|
||||
delay(100);
|
||||
#endif
|
||||
|
||||
setupSD();
|
||||
sd_loadPlaylist();
|
||||
|
||||
#if DEBUG_TEST_FRAME
|
||||
gfx_decoder_setTestFrame();
|
||||
#else
|
||||
loadVideo(0);
|
||||
|
||||
// gfx_decoder_setTestFrame();
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t currentVideoIndex = 0;
|
||||
bool isLoaded = false;
|
||||
|
||||
void loadVideo(size_t index) {
|
||||
#if DEBUG_TEST_FRAME
|
||||
return;
|
||||
#endif
|
||||
|
||||
audio_stop();
|
||||
|
||||
sd_loadAudio(index);
|
||||
|
@ -62,7 +70,7 @@ void nextSong() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
if (digitalRead(9) == LOW) {
|
||||
if (digitalRead(NEXT_PIN) == LOW) {
|
||||
delay(100);
|
||||
nextSong();
|
||||
delay(50);
|
||||
|
|
|
@ -3,24 +3,18 @@
|
|||
#include "sd.h"
|
||||
#include "audio.h"
|
||||
#include "gfx_decoder.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "hw_config.h"
|
||||
#include "ff.h"
|
||||
#include "f_util.h"
|
||||
|
||||
#define SD_DET_PIN 4
|
||||
|
||||
#define SD_PIN_SS 1
|
||||
#define SD_PIN_SCK 2
|
||||
#define SD_PIN_MOSI 3
|
||||
#define SD_PIN_MISO 0
|
||||
|
||||
static spi_t spi = {
|
||||
.hw_inst = spi0,
|
||||
.miso_gpio = SD_PIN_MISO,
|
||||
.mosi_gpio = SD_PIN_MOSI,
|
||||
.sck_gpio = SD_PIN_SCK,
|
||||
.baud_rate = 10 * 1000 * 1000,
|
||||
.baud_rate = SD_CARD_BAUD_RATE,
|
||||
};
|
||||
|
||||
static sd_spi_if_t spi_if = {
|
||||
|
@ -31,6 +25,10 @@ static sd_spi_if_t spi_if = {
|
|||
static sd_card_t sd_card = {
|
||||
.type = SD_IF_SPI,
|
||||
.spi_if_p = &spi_if,
|
||||
#if SD_HAS_DETECTION
|
||||
.use_card_detect = true,
|
||||
.card_detect_gpio = SD_DET_PIN,
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t sd_get_num() {
|
||||
|
@ -45,10 +43,6 @@ sd_card_t *sd_get_by_num(size_t num) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void setupSDPins() {
|
||||
// TODO: Is that even needed if we use built-in SPI?
|
||||
}
|
||||
|
||||
bool isSDCardInserted() {
|
||||
return digitalRead(SD_DET_PIN) == LOW;
|
||||
}
|
||||
|
@ -296,9 +290,11 @@ bool sd_loadGfxBlob(size_t index) {
|
|||
|
||||
// Returns size of frame read or -1 if error
|
||||
int32_t sd_loadNextFrame() {
|
||||
#if DEBUG_FIRST_FRAME
|
||||
if (frameIdx > 0) {
|
||||
// return -1;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!gfxFile) {
|
||||
Serial.println("Gfx file not available");
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
void setupSDPins();
|
||||
void setupSD();
|
||||
|
||||
bool isSDCardInserted();
|
||||
|
|
Loading…
Reference in New Issue