Implement parallel host and peripheral tests
This commit is contained in:
@ -8,21 +8,17 @@
|
|||||||
|
|
||||||
void init(void) {
|
void init(void) {
|
||||||
uart_stdio_init(0, __CONSOLE_BAUD__);
|
uart_stdio_init(0, __CONSOLE_BAUD__);
|
||||||
i2c_init(50000);
|
// Disable SPI
|
||||||
}
|
SPCR = 0;
|
||||||
|
|
||||||
static void i2c_slave_new() {}
|
|
||||||
|
|
||||||
static void i2c_slave_recv(uint8_t data) {
|
|
||||||
printf("%c", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t i2c_slave_send() {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Gpio LED = GPIO(B, 7);
|
struct Gpio LED = GPIO(B, 7);
|
||||||
|
|
||||||
|
//TODO: .h file
|
||||||
|
void parallel_host(void);
|
||||||
|
void parallel_peripheral(void);
|
||||||
|
void parallel_spy(void);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
@ -30,17 +26,16 @@ int main(void) {
|
|||||||
gpio_set(&LED, false);
|
gpio_set(&LED, false);
|
||||||
printf("Hello from System76 EC for the Arduino Mega 2560!\n");
|
printf("Hello from System76 EC for the Arduino Mega 2560!\n");
|
||||||
|
|
||||||
battery_debug();
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i2c_slave_init(0x76, i2c_slave_new, i2c_slave_recv, i2c_slave_send);
|
printf("Press a key to select parallel mode:\n");
|
||||||
|
printf(" h = host, p = peripheral, s = spy\n");
|
||||||
int c = getchar();
|
int c = getchar();
|
||||||
i2c_slave_stop();
|
if (c == 'h') {
|
||||||
if (c == '\r') {
|
parallel_host();
|
||||||
putchar('\n');
|
} else if (c == 'p') {
|
||||||
battery_debug();
|
parallel_peripheral();
|
||||||
} else if (c > 0) {
|
} else if (c == 's') {
|
||||||
putchar(c);
|
parallel_spy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,41 @@
|
|||||||
/* 1K-Ohm pull-down resistor */ \
|
/* 1K-Ohm pull-down resistor */ \
|
||||||
PIN(strap_1, 12)
|
PIN(strap_1, 12)
|
||||||
|
|
||||||
|
#define DATA_BITS \
|
||||||
|
DATA_BIT(0) \
|
||||||
|
DATA_BIT(1) \
|
||||||
|
DATA_BIT(2) \
|
||||||
|
DATA_BIT(3) \
|
||||||
|
DATA_BIT(4) \
|
||||||
|
DATA_BIT(5) \
|
||||||
|
DATA_BIT(6) \
|
||||||
|
DATA_BIT(7)
|
||||||
|
|
||||||
|
// Flip odd and even pins
|
||||||
|
//#define FLIP
|
||||||
|
|
||||||
|
#ifdef FLIP
|
||||||
|
|
||||||
|
// Mapping of 24-pin ribbon cable to GPIOs (flipped)
|
||||||
|
static struct Gpio GPIOS[24] = {
|
||||||
|
GPIO(B, 0), GPIO(B, 1),
|
||||||
|
GPIO(B, 2), GPIO(B, 3),
|
||||||
|
GPIO(L, 0), GPIO(L, 1),
|
||||||
|
GPIO(L, 2), GPIO(L, 3),
|
||||||
|
GPIO(L, 4), GPIO(L, 5),
|
||||||
|
GPIO(L, 6), GPIO(L, 7),
|
||||||
|
GPIO(G, 0), GPIO(G, 1),
|
||||||
|
GPIO(G, 2), GPIO(D, 7),
|
||||||
|
GPIO(C, 0), GPIO(C, 1),
|
||||||
|
GPIO(C, 2), GPIO(C, 3),
|
||||||
|
GPIO(C, 4), GPIO(C, 5),
|
||||||
|
GPIO(C, 6), GPIO(C, 7)
|
||||||
|
};
|
||||||
|
|
||||||
|
#else // FLIP
|
||||||
|
|
||||||
// Mapping of 24-pin ribbon cable to GPIOs
|
// Mapping of 24-pin ribbon cable to GPIOs
|
||||||
static struct Gpio gpios[24] = {
|
static struct Gpio GPIOS[24] = {
|
||||||
GPIO(B, 1), GPIO(B, 0),
|
GPIO(B, 1), GPIO(B, 0),
|
||||||
GPIO(B, 3), GPIO(B, 2),
|
GPIO(B, 3), GPIO(B, 2),
|
||||||
GPIO(L, 1), GPIO(L, 0),
|
GPIO(L, 1), GPIO(L, 0),
|
||||||
@ -57,6 +90,9 @@ static struct Gpio gpios[24] = {
|
|||||||
GPIO(C, 7), GPIO(C, 6)
|
GPIO(C, 7), GPIO(C, 6)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FLIP
|
||||||
|
|
||||||
// Parallel struct definition
|
// Parallel struct definition
|
||||||
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
|
// See http://efplus.com/techref/io/parallel/1284/eppmode.htm
|
||||||
struct Parallel {
|
struct Parallel {
|
||||||
@ -65,6 +101,13 @@ struct Parallel {
|
|||||||
#undef PIN
|
#undef PIN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Parallel struct instance
|
||||||
|
static struct Parallel PORT = {
|
||||||
|
#define PIN(N, P) .N = &GPIOS[P - 1],
|
||||||
|
PINS
|
||||||
|
#undef PIN
|
||||||
|
};
|
||||||
|
|
||||||
// Set port to all high-impedance inputs
|
// Set port to all high-impedance inputs
|
||||||
void parallel_hiz(struct Parallel * port) {
|
void parallel_hiz(struct Parallel * port) {
|
||||||
#define PIN(N, P) \
|
#define PIN(N, P) \
|
||||||
@ -106,17 +149,7 @@ void parallel_reset(struct Parallel * port) {
|
|||||||
gpio_set(port->reset_n, true);
|
gpio_set(port->reset_n, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DATA_BITS \
|
//TODO: timeout
|
||||||
DATA_BIT(0) \
|
|
||||||
DATA_BIT(1) \
|
|
||||||
DATA_BIT(2) \
|
|
||||||
DATA_BIT(3) \
|
|
||||||
DATA_BIT(4) \
|
|
||||||
DATA_BIT(5) \
|
|
||||||
DATA_BIT(6) \
|
|
||||||
DATA_BIT(7)
|
|
||||||
|
|
||||||
//TODO: address cycle, read cycle, timeout
|
|
||||||
int parallel_transaction(struct Parallel * port, uint8_t * data, int length, bool read, bool addr) {
|
int parallel_transaction(struct Parallel * port, uint8_t * data, int length, bool read, bool addr) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
@ -184,14 +217,153 @@ int parallel_transaction(struct Parallel * port, uint8_t * data, int length, boo
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parallel struct instance
|
void parallel_host(void) {
|
||||||
static struct Parallel PORT = {
|
printf("Parallel host. Reset to exit\n");
|
||||||
#define PIN(N, P) .N = &gpios[P - 1],
|
|
||||||
PINS
|
|
||||||
#undef PIN
|
|
||||||
};
|
|
||||||
|
|
||||||
void parallel(void) {
|
|
||||||
struct Parallel * port = &PORT;
|
struct Parallel * port = &PORT;
|
||||||
|
parallel_reset(port);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int c = getchar();
|
||||||
|
if (c < 0) break;
|
||||||
|
|
||||||
|
putchar(c);
|
||||||
|
if (c == '\r') {
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t byte = (uint8_t)c;
|
||||||
|
parallel_transaction(port, &byte, 1, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
parallel_hiz(port);
|
parallel_hiz(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parallel_peripheral(void) {
|
||||||
|
printf("Parallel peripheral (WIP, writes only). Reset to exit\n");
|
||||||
|
|
||||||
|
struct Parallel * port = &PORT;
|
||||||
|
parallel_hiz(port);
|
||||||
|
|
||||||
|
// Set wait line to low output
|
||||||
|
gpio_set_dir(port->wait_n, true);
|
||||||
|
|
||||||
|
// Strobes are high when inactive
|
||||||
|
bool last_data_n = true;
|
||||||
|
bool last_addr_n = true;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// Read data strobe and edge detect
|
||||||
|
bool data_n = gpio_get(port->data_n);
|
||||||
|
bool data_edge = last_data_n && !data_n;
|
||||||
|
|
||||||
|
// Read address strobe and edge detect
|
||||||
|
bool addr_n = gpio_get(port->addr_n);
|
||||||
|
bool addr_edge = last_addr_n && !addr_n;
|
||||||
|
|
||||||
|
// If not in reset
|
||||||
|
if (gpio_get(port->reset_n)) {
|
||||||
|
// On the falling edge of either strobe
|
||||||
|
if (data_edge || addr_edge) {
|
||||||
|
// Check if read or write cycle
|
||||||
|
bool read = gpio_get(port->write_n);
|
||||||
|
|
||||||
|
// Read data
|
||||||
|
uint8_t byte = 0;
|
||||||
|
#define DATA_BIT(B) \
|
||||||
|
if (gpio_get(port->d ## B)) byte |= (1 << B);
|
||||||
|
DATA_BITS
|
||||||
|
#undef DATA_BIT
|
||||||
|
|
||||||
|
//TODO: Check if strobe fell while reading
|
||||||
|
|
||||||
|
// Set wait line high
|
||||||
|
gpio_set(port->wait_n, true);
|
||||||
|
|
||||||
|
if (data_edge) {
|
||||||
|
putchar('d');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr_edge) {
|
||||||
|
putchar('a');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read) {
|
||||||
|
putchar('<');
|
||||||
|
} else {
|
||||||
|
putchar('>');
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%02X\n", byte);
|
||||||
|
|
||||||
|
// Delay 5 usecs
|
||||||
|
_delay_us(5);
|
||||||
|
|
||||||
|
// Set wait line low
|
||||||
|
gpio_set(port->wait_n, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_data_n = data_n;
|
||||||
|
last_addr_n = addr_n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parallel_spy(void) {
|
||||||
|
printf("Parallel spy. Reset to exit\n");
|
||||||
|
|
||||||
|
struct Parallel * port = &PORT;
|
||||||
|
parallel_hiz(port);
|
||||||
|
|
||||||
|
// Strobes are high when inactive
|
||||||
|
bool last_data_n = true;
|
||||||
|
bool last_addr_n = true;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// Read data strobe and edge detect
|
||||||
|
bool data_n = gpio_get(port->data_n);
|
||||||
|
bool data_edge = last_data_n && !data_n;
|
||||||
|
|
||||||
|
// Read address strobe and edge detect
|
||||||
|
bool addr_n = gpio_get(port->addr_n);
|
||||||
|
bool addr_edge = last_addr_n && !addr_n;
|
||||||
|
|
||||||
|
// If not in reset
|
||||||
|
if (gpio_get(port->reset_n)) {
|
||||||
|
// On the falling edge of either strobe
|
||||||
|
if (data_edge || addr_edge) {
|
||||||
|
// Check if read or write cycle
|
||||||
|
bool read = gpio_get(port->write_n);
|
||||||
|
|
||||||
|
// Read data
|
||||||
|
uint8_t byte = 0;
|
||||||
|
#define DATA_BIT(B) \
|
||||||
|
if (gpio_get(port->d ## B)) byte |= (1 << B);
|
||||||
|
DATA_BITS
|
||||||
|
#undef DATA_BIT
|
||||||
|
|
||||||
|
//TODO: Check if strobe fell while reading
|
||||||
|
|
||||||
|
if (data_edge) {
|
||||||
|
putchar('d');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr_edge) {
|
||||||
|
putchar('a');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read) {
|
||||||
|
putchar('<');
|
||||||
|
} else {
|
||||||
|
putchar('>');
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%02X\n", byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_data_n = data_n;
|
||||||
|
last_addr_n = addr_n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user