#include "buffered_peripheral.h"

typedef enum {
  MATRIX_SLOT0 = 0,
  MATRIX_SLOT1 = 1,
  MATRIX_SLOT_OTHER = 2,
} matrix_slot_t;

typedef enum {
  MATRIX_OFF,
  MATRIX_STABLE,
  MATRIX_ANIMATING,
} matrix_state_t;

typedef enum {
  MATRIX_REG_NO_OP = 0,
  MATRIX_REG_DIGIT0 = 1,
  MATRIX_REG_DIGIT1 = 2,
  MATRIX_REG_DIGIT2 = 3,
  MATRIX_REG_DIGIT3 = 4,
  MATRIX_REG_DIGIT4 = 5,
  MATRIX_REG_DIGIT5 = 6,
  MATRIX_REG_DIGIT6 = 7,
  MATRIX_REG_DIGIT7 = 8,
  MATRIX_REG_DECODE_MODE = 9,
  MATRIX_REG_INTENSITY = 10,
  MATRIX_REG_SCAN_LIMIT = 11,
  MATRIX_REG_SHUTDOWN = 12,
  MATRIX_REG_DISPLAY_TEST = 13,
} matrix_register_t;

typedef struct {
  buffered_transceiver_t* transceiver;
  uint32_t shift_period;

  matrix_slot_t slot;
  matrix_state_t state;

  uint8_t* buffers[2];

  uint32_t state_cycle;
  uint32_t cycle;

  uint8_t intensity;
} matrix_t;

void matrix_init(matrix_t* matrix, buffered_transceiver_t* transceiver, uint32_t shift_period);

void matrix_setup(matrix_t* matrix);
void matrix_enable(matrix_t* matrix, bool enable);

void matrix_increase_intensity(matrix_t *matrix);
void matrix_decrease_intensity(matrix_t *matrix);

void matrix_send(matrix_t* matrix, matrix_register_t reg, uint8_t value);
void matrix_set_buffer(matrix_t* matrix, matrix_slot_t slot, uint8_t* buffer);

void matrix_swap(matrix_t* matrix);
void matrix_animate_swap(matrix_t* matrix);

void matrix_update(matrix_t* matrix, buffered_transceiver_t* transceiver);
