2023-02-12 05:53:41 +00:00
|
|
|
#include "bus.h"
|
|
|
|
#include "esp/gpio.h"
|
|
|
|
|
|
|
|
#include <esp/spi.h>
|
2023-02-19 12:36:53 +00:00
|
|
|
#include <cstdio>
|
2023-02-12 05:53:41 +00:00
|
|
|
#include "log.h"
|
|
|
|
|
|
|
|
uint32_t spi_transfer_32_duplex(uint8_t bus, uint32_t val) {
|
|
|
|
uint32_t out = val;
|
|
|
|
uint32_t in;
|
|
|
|
spi_transfer(bus, &out, &in, 1, SPI_32BIT);
|
|
|
|
return in;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t spi_transfer_16_duplex(uint8_t bus, uint32_t val) {
|
|
|
|
uint16_t out = val;
|
|
|
|
uint16_t in;
|
|
|
|
spi_transfer(bus, &out, &in, 1, SPI_16BIT);
|
|
|
|
return in;
|
|
|
|
}
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
typedef enum {
|
|
|
|
CMD_NONE = 0,
|
|
|
|
CMD_READ = 1,
|
|
|
|
CMD_WRITE = 2,
|
|
|
|
CMD_INIT = 3,
|
|
|
|
CMD_RESET = 4,
|
|
|
|
CMD_VERSION = 5,
|
|
|
|
CMD_CONFIG = 6,
|
|
|
|
CMD_PING = 7
|
|
|
|
} bus_cmd;
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
struct {
|
|
|
|
unsigned dat: 16;
|
|
|
|
unsigned addr: 8;
|
|
|
|
unsigned cmd: 8;
|
|
|
|
} __attribute__((packed));
|
|
|
|
uint32_t _;
|
|
|
|
} request_frame;
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
struct {
|
|
|
|
unsigned dat: 16;
|
|
|
|
unsigned addr: 8;
|
|
|
|
unsigned flags: 7;
|
|
|
|
unsigned: 1;
|
|
|
|
} __attribute__((packed));
|
|
|
|
uint32_t _;
|
|
|
|
} reply_frame;
|
|
|
|
|
|
|
|
uint8_t flags = 0;
|
|
|
|
|
|
|
|
reply_frame bus_transfer_msg(bus_cmd cmd, uint8_t addr, uint16_t dat) {
|
|
|
|
request_frame frame_out = {._=0};
|
|
|
|
reply_frame frame_in = {._=0};
|
|
|
|
|
|
|
|
frame_out.cmd = cmd;
|
|
|
|
frame_out.addr = addr;
|
|
|
|
frame_out.dat = dat;
|
|
|
|
spi_transfer_32_duplex(1, frame_out._);
|
2023-02-12 05:53:41 +00:00
|
|
|
for (volatile int k = 0; k < 512 * 2; ++k);
|
2023-02-19 12:36:53 +00:00
|
|
|
frame_in._ = spi_transfer_32_duplex(1, 0x0000);
|
|
|
|
for (volatile int k = 0; k < 512 * 2; ++k);
|
|
|
|
flags |= frame_in.flags;
|
|
|
|
return frame_in;
|
2023-02-12 05:53:41 +00:00
|
|
|
}
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
uint32_t bus_transfer_msg(uint8_t addr, uint16_t dat) {
|
|
|
|
return bus_transfer_msg(CMD_WRITE, addr, dat)._;
|
2023-02-12 05:53:41 +00:00
|
|
|
}
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
bool bus_transfer_msg_arr(uint8_t addr, uint16_t *dat, uint8_t len) {
|
|
|
|
request_frame frame_out = {._=0};
|
|
|
|
reply_frame frame_in = {._=0};
|
|
|
|
|
|
|
|
request_frame last_frame = {._=0};
|
2023-02-12 05:53:41 +00:00
|
|
|
uint8_t error_count = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < len; ++i) {
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
frame_out.cmd = CMD_WRITE;
|
|
|
|
frame_out.addr = addr;
|
|
|
|
frame_out.dat = dat[i];
|
2023-02-12 05:53:41 +00:00
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
frame_in._ = spi_transfer_32_duplex(1, frame_out._);
|
2023-02-12 05:53:41 +00:00
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
if(frame_in.dat != last_frame.dat && i != 0) {
|
2023-02-12 05:53:41 +00:00
|
|
|
error_count++;
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
if(0) {
|
|
|
|
syslog(" > ");
|
|
|
|
syslog_i32(frame_out._);
|
|
|
|
syslog(" < ");
|
|
|
|
syslog_i32(frame_in._);
|
|
|
|
syslog(" =? ");
|
|
|
|
syslog_i32(last_frame._);
|
|
|
|
syslog("\n");
|
|
|
|
}
|
|
|
|
printf(" > %08x < %08x =? %08x\n", frame_out._, frame_in._, last_frame._);
|
2023-02-12 05:53:41 +00:00
|
|
|
}
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
last_frame._ = frame_out._;
|
2023-02-12 05:53:41 +00:00
|
|
|
|
|
|
|
for (volatile int k = 0; k < 512 * 2; ++k);
|
|
|
|
}
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
frame_in._ = spi_transfer_32_duplex(1, 0x0000);
|
|
|
|
if(frame_in.dat != last_frame.dat) {
|
2023-02-12 05:53:41 +00:00
|
|
|
error_count++;
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
if(0) {
|
|
|
|
syslog(" > ");
|
|
|
|
syslog_i32(frame_out._);
|
|
|
|
syslog(" < ");
|
|
|
|
syslog_i32(frame_in._);
|
|
|
|
syslog(" =? ");
|
|
|
|
syslog_i32(last_frame._);
|
|
|
|
syslog("\n");
|
|
|
|
}
|
|
|
|
printf(" > %08x < %08x =? %08x\n", 0, frame_in._, last_frame._);
|
2023-02-12 05:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return error_count == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t bus_get_version() {
|
2023-02-19 12:36:53 +00:00
|
|
|
return bus_transfer_msg(15, 0) >> 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset_bus() {
|
|
|
|
gpio_write(4, false);
|
|
|
|
for (volatile int k = 0; k < 128; ++k);
|
|
|
|
gpio_write(4, true);
|
2023-02-12 05:53:41 +00:00
|
|
|
}
|
|
|
|
|
2023-02-19 12:36:53 +00:00
|
|
|
bool bus_init() {
|
|
|
|
gpio_enable(12, GPIO_INPUT);
|
|
|
|
gpio_set_pullup(12, true, true);
|
|
|
|
gpio_write(4, false);
|
|
|
|
for (volatile int k = 0; k < 512 * 2; ++k);
|
|
|
|
gpio_write(4, true);
|
|
|
|
gpio_enable(4, GPIO_OUT_OPEN_DRAIN);
|
|
|
|
gpio_write(4, true);
|
|
|
|
for (volatile int k = 0; k < 512 * 4; ++k);
|
|
|
|
|
|
|
|
bool miso_state = gpio_read(12);
|
|
|
|
|
|
|
|
if(miso_state) {
|
|
|
|
printf("MISO is high, bus is not reset\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
spi_init(1, SPI_MODE0, SPI_FREQ_DIV_8M, true, SPI_BIG_ENDIAN, false);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool bus_init_next() {
|
|
|
|
flags &= ~0x04;
|
|
|
|
auto reply = bus_transfer_msg(CMD_INIT, 1, 0);
|
|
|
|
//printf(" init: %08x \n", reply.flags);
|
|
|
|
printf(" init: %02x %02x %04x %08x \n", reply.flags, reply.addr, reply.dat, reply._);
|
|
|
|
return reply.flags & 0x04;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t ping_count = 0;
|
|
|
|
|
2023-02-12 05:53:41 +00:00
|
|
|
bool bus_ping() {
|
2023-02-19 12:36:53 +00:00
|
|
|
auto reply = bus_transfer_msg(CMD_PING, 1, ++ping_count);
|
|
|
|
if(reply.dat == ping_count)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
printf("ping %02x %04x =? %08x\n", 1, ping_count, reply._);
|
|
|
|
return false;
|
2023-02-12 05:53:41 +00:00
|
|
|
}
|