233 lines
6.9 KiB
C
233 lines
6.9 KiB
C
#include "io.h"
|
|
// @todo We should probably add DATA_0... as defines
|
|
#define CLOCK_PIN GPIO_PIN_11
|
|
#define CLOCK_PORT GPIOB
|
|
|
|
#define RESET_PIN GPIO_PIN_3
|
|
#define RESET_PORT GPIOE
|
|
|
|
/* #define ADDRESS_PORT GPIOD */
|
|
GPIO_TypeDef* ADDRESS_PORT[] = {GPIOD, GPIOD, GPIOD, GPIOD, GPIOB, GPIOB, GPIOB, GPIOB,
|
|
GPIOB, GPIOE, GPIOE, GPIOA, GPIOA, GPIOD, GPIOD, GPIOD};
|
|
const uint16_t ADDRESS_PIN[] = {GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_8,
|
|
GPIO_PIN_9, GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_14, GPIO_PIN_15, GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_3};
|
|
|
|
GPIO_TypeDef* DATA_PORT[] = {GPIOD, GPIOD, GPIOD, GPIOD, GPIOC, GPIOC, GPIOA, GPIOA};
|
|
const uint16_t DATA_PIN[] = {GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_14, GPIO_PIN_15, GPIO_PIN_6, GPIO_PIN_7, GPIO_PIN_9, GPIO_PIN_10};
|
|
|
|
GPIO_TypeDef* DEV_SELECT_PORT[] = {GPIOD, GPIOD, GPIOD, GPIOD, GPIOB, GPIOB, GPIOB, GPIOB};
|
|
const uint16_t DEV_SELECT_PIN[] = {GPIO_PIN_11, GPIO_PIN_10, GPIO_PIN_9, GPIO_PIN_8, GPIO_PIN_15, GPIO_PIN_14, GPIO_PIN_13, GPIO_PIN_12};
|
|
|
|
#define READ_PIN GPIO_PIN_0
|
|
#define READ_PORT GPIOC
|
|
|
|
#define WRITE_PIN GPIO_PIN_13
|
|
#define WRITE_PORT GPIOC
|
|
|
|
#define MEMORY_REQUEST_PIN GPIO_PIN_0
|
|
#define MEMORY_REQUEST_PORT GPIOA
|
|
|
|
#define IO_REQUEST_PIN GPIO_PIN_1
|
|
#define IO_REQUEST_PORT GPIOA
|
|
|
|
#define M1_PIN GPIO_PIN_2
|
|
#define M1_PORT GPIOE
|
|
|
|
#define BUSRQ_PORT GPIOE
|
|
#define BUSRQ_PIN GPIO_PIN_4
|
|
|
|
#define BUSAK_PORT GPIOE
|
|
#define BUSAK_PIN GPIO_PIN_6
|
|
|
|
#define INT_PORT GPIOC
|
|
#define INT_PIN GPIO_PIN_1
|
|
|
|
uint16_t read_address() {
|
|
uint16_t address = 0;
|
|
address |= (GPIOD->IDR & (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7)) >> 4;
|
|
address |= (GPIOB->IDR & (GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5)) << 1;
|
|
address |= (GPIOB->IDR & (GPIO_PIN_8 | GPIO_PIN_9)) >> 1;
|
|
address |= (GPIOE->IDR & (GPIO_PIN_0 | GPIO_PIN_1)) << 9;
|
|
address |= (GPIOA->IDR & (GPIO_PIN_14 | GPIO_PIN_15)) >> 3;
|
|
address |= (GPIOD->IDR & (GPIO_PIN_0 | GPIO_PIN_1)) << 13;
|
|
address |= (GPIOD->IDR & GPIO_PIN_3) << 12;
|
|
|
|
return address;
|
|
}
|
|
|
|
void write_address(uint16_t address) {
|
|
for (int i = 0; i < 16; ++i) {
|
|
HAL_GPIO_WritePin(ADDRESS_PORT[i], ADDRESS_PIN[i], address & (1 << i) ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
|
}
|
|
}
|
|
|
|
void enable_address_out(uint8_t enable) {
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
|
|
for (int i = 0; i < 16; ++i) {
|
|
GPIO_InitStruct.Pin = ADDRESS_PIN[i];
|
|
GPIO_InitStruct.Mode = enable ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT;
|
|
HAL_GPIO_Init(ADDRESS_PORT[i], &GPIO_InitStruct);
|
|
}
|
|
}
|
|
|
|
uint8_t read_data() {
|
|
uint16_t data = 0;
|
|
|
|
data |= (GPIOD->IDR & (GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)) >> 12;
|
|
data |= (GPIOC->IDR & (GPIO_PIN_6 | GPIO_PIN_7)) >> 2;
|
|
data |= (GPIOA->IDR & (GPIO_PIN_9 | GPIO_PIN_10)) >> 3;
|
|
|
|
return data;
|
|
}
|
|
|
|
void write_data(uint8_t value) {
|
|
GPIOD->BSRR= ((value & 0xF) | ((~value & 0xF) << 16)) << 12;
|
|
GPIOC->BSRR= ((value & 0x30) | ((~value & 0x30) << 16)) << 2;
|
|
GPIOA->BSRR = ((value & 0xC0) | ((~value & 0xC0) << 16)) << 3;
|
|
}
|
|
|
|
void enable_data_out(uint8_t enable) {
|
|
static uint8_t cur = 2;
|
|
|
|
if (cur != enable) {
|
|
cur = enable;
|
|
|
|
if (enable) {
|
|
GPIOD->MODER |= (GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 | GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0);
|
|
GPIOC->MODER |= (GPIO_MODER_MODER6_0 | GPIO_MODER_MODER7_0);
|
|
GPIOA->MODER |= (GPIO_MODER_MODER9_0 | GPIO_MODER_MODER10_0);
|
|
} else {
|
|
// @todo We can optimze this in a similair manner as above
|
|
GPIOD->MODER &= ~(GPIO_MODER_MODER12);
|
|
GPIOD->MODER &= ~(GPIO_MODER_MODER13);
|
|
GPIOD->MODER &= ~(GPIO_MODER_MODER14);
|
|
GPIOD->MODER &= ~(GPIO_MODER_MODER15);
|
|
|
|
GPIOC->MODER &= ~(GPIO_MODER_MODER6);
|
|
GPIOC->MODER &= ~(GPIO_MODER_MODER7);
|
|
|
|
GPIOA->MODER &= ~(GPIO_MODER_MODER9);
|
|
GPIOA->MODER &= ~(GPIO_MODER_MODER10);
|
|
}
|
|
}
|
|
}
|
|
|
|
void select_device(uint8_t device) {
|
|
static uint8_t cur = 0xFF;
|
|
|
|
if (cur != device) {
|
|
cur = device;
|
|
|
|
GPIOB->BSRR = ((device & 0xF) | ((~device & 0xF) << 16)) << 12;
|
|
GPIOD->BSRR = ((device & 0xF0) | ((~device & 0xF0) << 16)) << 4;
|
|
}
|
|
}
|
|
|
|
|
|
void set_reset(uint8_t high) {
|
|
GPIOE->BSRR = ((~high & 1) | ((high & 1) << 16)) << 3;
|
|
}
|
|
|
|
void set_clock(uint8_t high) {
|
|
GPIOB->BSRR = ((high & 1) | ((~high & 1) << 16)) << 11;
|
|
}
|
|
|
|
uint8_t has_memrq() {
|
|
return !(MEMORY_REQUEST_PORT->IDR & MEMORY_REQUEST_PIN);
|
|
}
|
|
|
|
void send_memrq(uint8_t high) {
|
|
HAL_GPIO_WritePin(MEMORY_REQUEST_PORT, MEMORY_REQUEST_PIN, high ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
|
}
|
|
|
|
void enable_memrq_out(uint8_t enable) {
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
GPIO_InitStruct.Pin = MEMORY_REQUEST_PIN;
|
|
GPIO_InitStruct.Mode = enable ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT;
|
|
HAL_GPIO_Init(MEMORY_REQUEST_PORT, &GPIO_InitStruct);
|
|
}
|
|
|
|
uint8_t has_ioreq() {
|
|
return !(IO_REQUEST_PORT->IDR & IO_REQUEST_PIN);
|
|
}
|
|
|
|
uint8_t has_m1() {
|
|
return !(M1_PORT->IDR & M1_PIN);
|
|
}
|
|
|
|
uint8_t has_rd() {
|
|
return !(READ_PORT->IDR & READ_PIN);
|
|
}
|
|
|
|
void send_rd(uint8_t high) {
|
|
HAL_GPIO_WritePin(READ_PORT, READ_PIN, high ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
|
}
|
|
|
|
void enable_rd_out(uint8_t enable) {
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
GPIO_InitStruct.Pin = READ_PIN;
|
|
GPIO_InitStruct.Mode = enable ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT;
|
|
HAL_GPIO_Init(READ_PORT, &GPIO_InitStruct);
|
|
}
|
|
|
|
uint8_t has_wr() {
|
|
return !(WRITE_PORT->IDR & WRITE_PIN);
|
|
}
|
|
|
|
void send_wr(uint8_t high) {
|
|
HAL_GPIO_WritePin(WRITE_PORT, WRITE_PIN, high ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
|
}
|
|
|
|
void enable_wr_out(uint8_t enable) {
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
GPIO_InitStruct.Pin = WRITE_PIN;
|
|
GPIO_InitStruct.Mode = enable ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT;
|
|
HAL_GPIO_Init(WRITE_PORT, &GPIO_InitStruct);
|
|
}
|
|
|
|
uint8_t has_busak() {
|
|
return !(BUSAK_PORT->IDR & BUSAK_PIN);
|
|
}
|
|
|
|
void send_busrq(uint8_t control) {
|
|
if (control) {
|
|
// Set correct defaults
|
|
send_memrq(0);
|
|
send_wr(0);
|
|
send_rd(0);
|
|
}
|
|
|
|
// @todo This should not happen unitl busak
|
|
enable_memrq_out(control);
|
|
enable_rd_out(control);
|
|
enable_wr_out(control);
|
|
enable_address_out(control);
|
|
|
|
HAL_GPIO_WritePin(BUSRQ_PORT, BUSRQ_PIN, control ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
|
}
|
|
|
|
void send_int(uint8_t control) {
|
|
static uint8_t cur = 2;
|
|
|
|
if (cur != control) {
|
|
cur = control;
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
GPIO_InitStruct.Pin = INT_PIN;
|
|
GPIO_InitStruct.Mode = control ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT;
|
|
HAL_GPIO_Init(INT_PORT, &GPIO_InitStruct);
|
|
|
|
HAL_GPIO_WritePin(INT_PORT, INT_PIN, control ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
|
}
|
|
}
|