2020-05-22 07:55:24 +00:00
|
|
|
#ifndef F_CPU
|
|
|
|
#define F_CPU 16000000UL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define BAUD 9600
|
|
|
|
|
|
|
|
#include <avr/io.h>
|
|
|
|
#include <avr/interrupt.h>
|
|
|
|
#include <util/setbaud.h>
|
|
|
|
|
|
|
|
#define DATA_READ_LINE PB0
|
|
|
|
#define DATA_WRITE_LINE PD7
|
|
|
|
#define STATUS PD6
|
|
|
|
|
|
|
|
#define DATA0 PB1
|
|
|
|
#define DATA1 PB2
|
|
|
|
#define DATA2 PB3
|
|
|
|
#define DATA3 PB4
|
|
|
|
#define DATA4 PB5
|
|
|
|
#define DATA5 PD2
|
|
|
|
#define DATA6 PD3
|
|
|
|
#define DATA7 PD4
|
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
#define BUFFER_SIZE 8
|
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
typedef enum {NONE, READ, WRITE} mode_t;
|
|
|
|
mode_t mode = NONE;
|
|
|
|
|
|
|
|
uint8_t data = 0x00;
|
|
|
|
uint8_t upper_part = 0x00;
|
|
|
|
uint8_t lower_part = 0x00;
|
|
|
|
|
|
|
|
uint8_t data_write_interrupt_count = 0;
|
|
|
|
uint8_t data_read_interrupt_count = 0;
|
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
// receive buffer
|
|
|
|
uint8_t receive_buffer[BUFFER_SIZE];
|
|
|
|
int8_t receive_index = -1;
|
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// Registers: PCMSK0, PCMSK1, PCMSK2 :registers that enable or disable pin-change interrupts
|
|
|
|
// on individual pins
|
|
|
|
|
|
|
|
// PCICR : a register where the three least significant bits enable or disable pin change interrupts
|
|
|
|
// on a range of pins, i.e. {0,0,0,0,0,PCIE2,PCIE1,PCIE0}, where PCIE2 maps to PCMSK2, PCIE1 maps to PCMSK1,
|
|
|
|
// and PCIE0 maps to PCMSK0.
|
|
|
|
|
|
|
|
inline void ready() {
|
|
|
|
PORTD |= _BV(STATUS);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void not_ready() {
|
|
|
|
PORTD &= ~(_BV(STATUS));
|
|
|
|
}
|
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
inline void put_data() {
|
|
|
|
upper_part = (PORTD & 0xe3) | ((0xe0 & receive_buffer[0])>>3);
|
|
|
|
lower_part = (PORTB & 0xc1) | ((0x1f & receive_buffer[0])<<1);
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
PORTD = upper_part;
|
|
|
|
PORTB = lower_part;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// set input on DATA_READ_LINE
|
|
|
|
DDRB &= ~(_BV(DATA_READ_LINE));
|
|
|
|
// interrupt on DATA_READ_LINE change
|
|
|
|
PCMSK0 |= _BV(PCINT0);
|
|
|
|
PCICR |= _BV(PCIE0);
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// set input on DATA_WRITE_LINE
|
|
|
|
DDRD &= ~(_BV(DATA_WRITE_LINE));
|
|
|
|
// interrupt on DATA_WRITE_LINE change
|
|
|
|
PCMSK2 |= _BV(PCINT23);
|
|
|
|
PCICR |= _BV(PCIE2);
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
UBRR0H = UBRRH_VALUE;
|
|
|
|
UBRR0L = UBRRL_VALUE;
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
UCSR0A = 0x00;
|
|
|
|
UCSR0C = 0x00;
|
|
|
|
// 8 bits of data, 1 stop bit, no parity
|
|
|
|
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
|
|
|
|
// TXD pullup
|
|
|
|
PORTD |= _BV(PD1);
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// interrupt on DATA_READ_LINE change
|
|
|
|
PCMSK0 |= _BV(PCINT0);
|
|
|
|
PCICR |= _BV(PCIE0);
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// set output on status
|
|
|
|
DDRD |= _BV(STATUS);
|
|
|
|
not_ready();
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// enable global interrupts
|
|
|
|
sei();
|
|
|
|
}
|
|
|
|
|
|
|
|
// data read line
|
|
|
|
ISR(PCINT0_vect) {
|
|
|
|
if (data_read_interrupt_count == 0) {
|
|
|
|
if (mode != READ) {
|
|
|
|
mode = READ;
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// enable RXD and it's interrupt
|
|
|
|
UCSR0B = _BV(RXEN0) | _BV(RXCIE0);
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// set output on data pins
|
|
|
|
DDRD |= _BV(DATA5) | _BV(DATA6) | _BV(DATA7);
|
|
|
|
DDRB |= _BV(DATA0) | _BV(DATA1) | _BV(DATA2) | _BV(DATA3) | _BV(DATA4);
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
receive_index = -1;
|
|
|
|
not_ready();
|
|
|
|
data_read_interrupt_count = 1;
|
|
|
|
return;
|
|
|
|
}
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
if (receive_index > -1) {
|
|
|
|
uint8_t i;
|
|
|
|
for (i = 1; i <= receive_index; i++) {
|
|
|
|
receive_buffer[i - 1] = receive_buffer[i];
|
|
|
|
}
|
|
|
|
receive_index--;
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
if (receive_index == -1) {
|
|
|
|
not_ready();
|
|
|
|
} else {
|
|
|
|
// put next byte from receive buffer
|
|
|
|
put_data();
|
|
|
|
}
|
2020-05-22 07:55:24 +00:00
|
|
|
}
|
|
|
|
data_read_interrupt_count = 1;
|
|
|
|
} else {
|
|
|
|
data_read_interrupt_count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// data write line
|
|
|
|
ISR(PCINT2_vect) {
|
|
|
|
upper_part = PINB;
|
|
|
|
lower_part = PIND;
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
if (data_write_interrupt_count == 0) {
|
|
|
|
if (mode == WRITE) {
|
|
|
|
upper_part = upper_part >> 1;
|
|
|
|
upper_part &= 0x1f;
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
lower_part = lower_part << 3;
|
|
|
|
lower_part &= 0xe0;
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// set status to not ready
|
|
|
|
PORTD &= ~(_BV(STATUS));
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// send byte
|
|
|
|
loop_until_bit_is_set(UCSR0A, UDRE0);
|
|
|
|
UDR0 = upper_part | lower_part;
|
|
|
|
} else {
|
|
|
|
if (mode == READ) {
|
|
|
|
// zero all outputs
|
|
|
|
PORTD &= 0xe3;
|
|
|
|
PORTB &= 0xc1;
|
|
|
|
}
|
|
|
|
mode = WRITE;
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// enable TXD interrupt and it's interrupt
|
|
|
|
UCSR0B = _BV(TXEN0) | _BV(TXCIE0);
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
// set input on data pins
|
|
|
|
DDRD &= ~(_BV(DATA5) | _BV(DATA6) | _BV(DATA7));
|
|
|
|
DDRB &= ~(_BV(DATA0) | _BV(DATA1) | _BV(DATA2) | _BV(DATA3) | _BV(DATA4));
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
ready();
|
|
|
|
}
|
|
|
|
data_write_interrupt_count = 1;
|
|
|
|
} else {
|
|
|
|
data_write_interrupt_count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ISR(USART_RX_vect)
|
|
|
|
{
|
|
|
|
if (mode == READ) {
|
|
|
|
data = UDR0;
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
if (receive_index >= BUFFER_SIZE - 1) {
|
|
|
|
receive_index = -1;
|
|
|
|
}
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
receive_buffer[++receive_index] = data;
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-06-07 22:21:16 +00:00
|
|
|
// always put first byte from receive buffer
|
|
|
|
put_data();
|
2020-07-03 13:51:53 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
ready();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ISR(USART_TX_vect)
|
|
|
|
{
|
|
|
|
if (mode == WRITE) {
|
|
|
|
ready();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void) {
|
|
|
|
setup();
|
2020-06-07 22:21:16 +00:00
|
|
|
|
2020-05-22 07:55:24 +00:00
|
|
|
for(;;){
|
|
|
|
// only interrupt driven
|
|
|
|
}
|
|
|
|
return 0; /* never reached */
|
|
|
|
}
|