/*########################################################################### qqqDali_ATMega328.h - copyright qqqlab.com / github.com/qqqlab This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ---------------------------------------------------------------------------- Changelog: 2020-11-10 Created & tested on ATMega328 @ 8Mhz ###########################################################################*/ #include "arduino.h" #include "qqqDali.h" #define DALI_HOOK_COUNT 3 class Dali_ATMega328 : public Dali { public: void begin(int8_t tx_pin, int8_t rx_pin); virtual void HAL_set_bus_low() const override; virtual void HAL_set_bus_high() const override; virtual uint8_t HAL_is_bus_low() const override; virtual uint32_t HAL_micros() const override; private: uint8_t tx_pin; //transmitter pin uint8_t rx_pin; //receiver pin }; //----------------------------------------- //Hardware Abstraction Layer void Dali_ATMega328::HAL_set_bus_low() const { digitalWrite(this->tx_pin,LOW); } void Dali_ATMega328::HAL_set_bus_high() const { digitalWrite(this->tx_pin,HIGH); } uint8_t Dali_ATMega328::HAL_is_bus_low() const { return (digitalRead(this->rx_pin) == LOW); } uint32_t Dali_ATMega328::HAL_micros() const { return micros(); } //----------------------------------------- // Transmitter ISR static Dali *IsrTimerHooks[DALI_HOOK_COUNT+1]; // timer compare interrupt service routine ISR(TIMER1_COMPA_vect) { for(uint8_t i=0;iISR_timer(); } } //----------------------------------------- // Receiver ISR //pin PCINT //0-7 PCINT2_vect PCINT16-23 //8-13 PCINT0_vect PCINT0-5 //14-19 PCINT1_vect PCINT8-13 static Dali *IsrPCINT0Hook; static Dali *IsrPCINT1Hook; static Dali *IsrPCINT2Hook; ISR(PCINT0_vect) { if(IsrPCINT0Hook!=NULL) IsrPCINT0Hook->ISR_pinchange(); } ISR(PCINT1_vect) { if(IsrPCINT1Hook!=NULL) IsrPCINT1Hook->ISR_pinchange(); } ISR(PCINT2_vect) { if(IsrPCINT2Hook!=NULL) IsrPCINT2Hook->ISR_pinchange(); } //----------------------------------------- // begin void Dali_ATMega328::begin(int8_t tx_pin, int8_t rx_pin) { this->tx_pin = tx_pin; this->rx_pin = rx_pin; //setup tx if(this->tx_pin>=0) { //setup tx pin pinMode(this->tx_pin, OUTPUT); this->HAL_set_bus_high(); this->tx_bus_low=0; //setup tx timer interrupt TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = (F_CPU+(DALI_BAUD))/(2*(DALI_BAUD)); // compare match register at baud rate * 2 TCCR1B |= (1 << WGM12); // CTC mode TCCR1B |= (1 << CS10); // 1:1 prescaler TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt //setup timer interrupt hooks for(uint8_t i=0;irx_pin>=0) { //setup rx pin pinMode(this->rx_pin, INPUT); //setup rx pinchange interrupt // 0- 7 PCINT2_vect PCINT16-23 // 8-13 PCINT0_vect PCINT0-5 //14-19 PCINT1_vect PCINT8-13 if(this->rx_pin <= 7){ PCICR |= (1 << PCIE2); PCMSK2 |= (1 << (this->rx_pin)); IsrPCINT2Hook = this; //setup pinchange interrupt hook }else if(this->rx_pin <= 13) { PCICR |= (1 << PCIE0); PCMSK0 |= (1 << (this->rx_pin - 8)); IsrPCINT0Hook = this; //setup pinchange interrupt hook }else if(this->rx_pin <= 19) { PCICR |= (1 << PCIE1); PCMSK1 |= (1 << (this->rx_pin - 14)); IsrPCINT1Hook = this; //setup pinchange interrupt hook } } }