You've already forked torvalds-GuitarPedal
mirror of
https://github.com/torvalds/GuitarPedal.git
synced 2026-05-15 09:37:36 +00:00
This brings in the actual real code: the "drivers" for the SH1107 display module, the i2c EEPROM chip, the actual UI for the thing, and the code "blink.c" program. Why is it called "blink.c"? Because all MCU projects start as a simple LED blinking thing. Including this one. And the name just never changes. The CMakeList.txt file then really brings the room together. Doing cd Software make prep make make flash should be more or less sufficient to build the thing and flash the end result (you'll need to have the standard arm cross-build tools available etc, of course) Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
90 lines
2.2 KiB
C
90 lines
2.2 KiB
C
#ifndef EEPROM_H
|
|
#define EEPROM_H
|
|
|
|
#include "hardware/i2c.h"
|
|
#include "board.h"
|
|
#include <string.h>
|
|
|
|
struct effect_state {
|
|
signed char pots[10];
|
|
unsigned char enabled;
|
|
unsigned char magic;
|
|
unsigned char reserved[4]; // Pad to 16 bytes
|
|
};
|
|
|
|
static inline uint8_t effect_checksum(struct effect *effect, struct effect_state *state)
|
|
{
|
|
uint8_t sum = 0;
|
|
|
|
if (effect->name) {
|
|
for (const char *p = effect->name; *p; p++) {
|
|
sum += (uint8_t)*p;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
sum += (uint8_t)effect->pots[i].def_val;
|
|
sum += (uint8_t)state->pots[i];
|
|
}
|
|
|
|
sum += (uint8_t)state->enabled;
|
|
return sum;
|
|
}
|
|
|
|
static inline bool load_effect_state(int effect_idx, struct effect *effect)
|
|
{
|
|
struct effect_state state;
|
|
uint8_t addr = effect_idx * 32; // 2 pages (32 bytes) per effect
|
|
|
|
// The EEPROM may not be ready immediately at boot. Retry for up to ~50ms.
|
|
int retries = 10;
|
|
while (retries-- > 0) {
|
|
// Write the memory address we want to read from (with nostop = true)
|
|
if (i2c_write_blocking(MC24C02_I2C, &addr, 1, true) >= 0) {
|
|
break;
|
|
}
|
|
sleep_ms(5);
|
|
}
|
|
|
|
if (retries < 0) {
|
|
return false;
|
|
}
|
|
|
|
// Read 16 bytes sequentially
|
|
int read_res = i2c_read_blocking(MC24C02_I2C, (uint8_t *)&state, sizeof(state), false);
|
|
if (read_res == sizeof(state)) {
|
|
if (state.magic == effect_checksum(effect, &state)) {
|
|
int seq = effect->seq & 1;
|
|
memcpy(effect->pot_values[seq], state.pots, 10);
|
|
effect->target = state.enabled ? EFF_ENABLE_STEPS : 0;
|
|
effect->mix = effect->target; // Apply immediately on load
|
|
if (effect->load)
|
|
effect->load(effect, state.pots);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static inline void save_effect_state(int effect_idx, struct effect *effect)
|
|
{
|
|
struct effect_state state = { };
|
|
int seq = effect->seq & 1;
|
|
|
|
if (effect->save)
|
|
effect->save(effect, effect->pot_values[seq]);
|
|
memcpy(state.pots, effect->pot_values[seq], 10);
|
|
|
|
state.enabled = effect->target ? 1 : 0;
|
|
state.magic = effect_checksum(effect, &state);
|
|
|
|
// Prepare the I2C transaction: [Address byte] + [16 bytes data]
|
|
uint8_t buf[1 + sizeof(state)];
|
|
buf[0] = effect_idx * 32; // Page aligned address
|
|
memcpy(buf + 1, &state, sizeof(state));
|
|
|
|
i2c_write_blocking(MC24C02_I2C, buf, sizeof(buf), false);
|
|
}
|
|
|
|
#endif
|