qqqDali_ATMega328.h
4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*###########################################################################
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 <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
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;i<DALI_HOOK_COUNT;i++) {
if(IsrTimerHooks[i]==NULL) {return;}
IsrTimerHooks[i]->ISR_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;i<DALI_HOOK_COUNT;i++) {
if(IsrTimerHooks[i] == NULL) {
IsrTimerHooks[i] = this;
break;
}
}
}
//setup rx
if(this->rx_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
}
}
}