0
mirror of https://github.com/torvalds/GuitarPedal.git synced 2026-05-15 09:37:36 +00:00
Files
Linus Torvalds 61810e36e6 Bring in the rest of the project
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>
2026-05-13 14:55:56 -07:00

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