velxio/test/test_custom_chips/sdk/examples/eeprom-24c01.c

91 lines
2.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* eeprom-24c01.c — Velxio custom chip implementing a 24C01-class I2C EEPROM.
*
* 128 bytes (datasheet says 1 Kbit = 128 × 8). Address pins A0..A2 set the
* three low bits of the 7-bit I2C address (base 0x50).
*
* Protocol on the I2C bus:
* write 1 byte → set the read/write address pointer
* write 2+ bytes → first sets address pointer, rest stores data sequentially
* read → returns memory at pointer, autoincrements
*
* Build:
* bash scripts/compile-chip.sh sdk/examples/eeprom-24c01.c fixtures/eeprom-24c01.wasm
*/
#include "velxio-chip.h"
#include <stdlib.h>
#include <string.h>
#define EEPROM_BASE_ADDR 0x50
#define EEPROM_SIZE 128
typedef enum {
ST_IDLE, /* before any byte after addressing */
ST_HAS_POINTER, /* received the pointer byte; further writes are data */
} ee_state;
typedef struct {
vx_pin a0, a1, a2;
uint8_t pointer;
uint8_t mem[EEPROM_SIZE];
ee_state state;
} chip_state_t;
static bool i2c_connect(void* ud, uint8_t address, bool is_read) {
chip_state_t* s = (chip_state_t*)ud;
/* On a fresh transaction, reads use the existing pointer; writes restart. */
if (!is_read) s->state = ST_IDLE;
return true; /* ACK */
}
static uint8_t i2c_read(void* ud) {
chip_state_t* s = (chip_state_t*)ud;
uint8_t b = s->mem[s->pointer & (EEPROM_SIZE - 1)];
s->pointer = (s->pointer + 1) & (EEPROM_SIZE - 1);
return b;
}
static bool i2c_write(void* ud, uint8_t byte) {
chip_state_t* s = (chip_state_t*)ud;
if (s->state == ST_IDLE) {
s->pointer = byte & (EEPROM_SIZE - 1);
s->state = ST_HAS_POINTER;
} else {
s->mem[s->pointer & (EEPROM_SIZE - 1)] = byte;
s->pointer = (s->pointer + 1) & (EEPROM_SIZE - 1);
}
return true; /* ACK */
}
static void i2c_stop(void* ud) {
chip_state_t* s = (chip_state_t*)ud;
s->state = ST_IDLE;
}
void chip_setup(void) {
chip_state_t* s = (chip_state_t*)calloc(1, sizeof(chip_state_t));
s->a0 = vx_pin_register("A0", VX_INPUT);
s->a1 = vx_pin_register("A1", VX_INPUT);
s->a2 = vx_pin_register("A2", VX_INPUT);
uint8_t addr = EEPROM_BASE_ADDR
| ((vx_pin_read(s->a2) & 1) << 2)
| ((vx_pin_read(s->a1) & 1) << 1)
| ((vx_pin_read(s->a0) & 1));
vx_i2c_config cfg = {
.address = addr,
.scl = vx_pin_register("SCL", VX_INPUT),
.sda = vx_pin_register("SDA", VX_INPUT),
.on_connect = i2c_connect,
.on_read = i2c_read,
.on_write = i2c_write,
.on_stop = i2c_stop,
.user_data = s,
};
vx_i2c_attach(&cfg);
vx_log("24C01 EEPROM ready");
}