Files
TrainDecoder/main.cpp

129 lines
2.4 KiB
C++

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "writepin.h"
#include "decoder.h"
static constexpr uint8_t T0_A = PB0;
static constexpr uint8_t T0_B = PB1;
static constexpr uint8_t T1_A = PB3;
static constexpr uint8_t T1_B = PB4;
static volatile bool turnout0Flag = false;
static volatile bool turnout1Flag = false;
uint16_t oldData = 0;
constexpr bool debug = false;
void handler(uint16_t data, void *user_data)
{
(void)user_data;
if constexpr(debug)
{
writePin(&PORTB, T0_A, false);
_delay_ms(1);
for(uint8_t i = 0; i < 10; ++i)
{
writePin(&PORTB, T0_A, true);
_delay_us(25);
if(data & (1 << (9-i)))
_delay_us(75);
writePin(&PORTB, T0_A, false);
_delay_us(25);
if(!(data & (1 << (9-i))))
_delay_us(75);
}
}
if(data == oldData)
{
if(((bool)(data & (1 << 9))) != ((bool)(data & (1 << 8))) ||
((bool)(data & (1 << 7))) != ((bool)(data & (1 << 6))) ||
((bool)(data & (1 << 5))) != ((bool)(data & (1 << 4))))
return;
bool set = data & (1 << 9);
if(data & (1 << 7))
turnout0Flag = set;
if(data & (1 << 5))
turnout1Flag = set;
}
else
{
oldData = data;
}
}
static void setTurnout0(bool in)
{
writePin(&PORTB, T0_A, in);
writePin(&PORTB, T0_B, !in);
_delay_ms(150);
writePin(&PORTB, T0_A, false);
writePin(&PORTB, T0_B, false);
}
static void setTurnout1(bool in)
{
writePin(&PORTB, T1_A, in);
writePin(&PORTB, T1_B, !in);
_delay_ms(150);
writePin(&PORTB, T1_A, false);
writePin(&PORTB, T1_B, false);
}
Decoder decoder(&PINB, PB2, &TCNT1, &handler, nullptr, 0x01);
ISR(TIMER1_OVF_vect)
{
decoder.overflowInterrupt();
}
ISR(INT0_vect)
{
if constexpr(debug)
{
writePin(&PORTB, T1_A, !readPin(&PORTB, T1_A));
}
decoder.interrupt();
}
int main()
{
DDRB = (1 << PB0) | (1 << PB1) | (1 << PB3) | (1 << PB4);
bool turnout0 = turnout0Flag;
bool turnout1 = turnout1Flag;
_delay_ms(100);
setTurnout0(turnout0);
setTurnout1(turnout1);
MCUCR = (1 << ISC00); //enable rising and falling irq on INT0
GIMSK = (1 << INT0); //unmask INT0
TIMSK = (1 << TOIE1); //enable timer 1 overflow irq
TCCR1 = (1 << CS12) | (1 << CS10); //enable timer 1 with /16 timer
sei();
while(true)
{
if(turnout0 != turnout0Flag)
{
turnout0 = turnout0Flag;
setTurnout0(turnout0);
}
if(turnout1 != turnout1Flag)
{
turnout1 = turnout1Flag;
setTurnout1(turnout1);
}
}
}