-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfirmware.c
194 lines (163 loc) · 4.77 KB
/
firmware.c
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
* Firmware.c
*
* Created: 1/17/2014 10:21:57 PM
* Author: Paul
*/
#include <avr/io.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "firmware.h"
void PWM_init(void);
void TWI_init(void);
void plex_init(void);
//define variables to store channel samples samples
uint_fast16_t channels[NUMCHANNELS];
uint8_t plex;
uint8_t updatedCount;
int main(void)
{
PWM_init();
TWI_init();
plex_init();
// allow interrupts
//sei();
SREG |= (1 << SREG_I);
while(1)
{
//loop
}
}
void plex_init(){
// do all the prep for multiplexer
plex = 0;
DDRD = 0xFF; //set port d for all output
// set portd pin that is driving the multiplexer
PORTD = (1 << PLEXE); // set port d to bit plex e on that disables multiplex
PORTD &= ~(1 << PLEXS0);
PORTD &= ~(1 << PLEXE); // turns on multiplexer
}
void PWM_init(void){
// initialize pwm reader on port b
// set pin 0 or port b as input pin
DDRB &= ~(1<<PINB0);
// set pin0 tri state
PORTB &= ~(1<<PINB0);
// enable pin change interrupt PCINT0-7
// PCICR |= (1<<PCIE0); // replace with input capture
// set pin 0 individually
// PCMSK0 |= (1<<PCINT0);
// enable input noise cancelling filter
TCCR1B |= (1<<ICNC1); // adds 4 clock cycle delay to sample over 4 additional cycles
// enable input capture on leading edge of ICP1
TCCR1B |= (1<<ICES1);
// set timer prescaler to 1 for 2ms pulse counter at 8mhz
TCCR1B |= (1<<CS10);
// enable interrupt
TIMSK1 |= (1<<ICIE1);
}
void TWI_init(void)
{
//set TWI address
TWAR = (0x01<<1); //using address 0x01
//enable TWI
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
}
void TWI_stop(void){
// clear acknowledge and enable bits
TWCR &= ~( (1<<TWEA) | (1<<TWEN) );
}
ISR(TIMER1_CAPT_vect){
// Input capture interrupt handler
// first time is triggered in leading edge
if(PINB & (0x01)){ // pin high
// clear counter and set to trailing edge
TCNT1 = 0;
TCCR1B &= ~(1<<ICES1);
}else{
// get counter from ICR1
// reset to look for leading edge
uint_fast16_t counter = ICR1 + 47; // add some counts for processor over head //
if(channels[plex] != counter){
updatedCount += 1;
}
channels[plex] = counter;
if(plex == NUMCHANNELS - 1){
if(updatedCount != 0){
PORTD |= (1 << PIEVENT);
}
updatedCount = 0;
plex = 0;
}else{
plex += 1;
}
switchMultiplex();
TCCR1B |= (1<<ICES1);
}
}
void switchMultiplex(){
uint8_t temp = PORTD & 0xF0;
PORTD = temp | plex;
}
ISR(TWI_vect){
// temporary stores the received data
uint8_t data;
// own address has been acknowledged
if( (TWSR & 0xF8) == TW_SR_SLA_ACK ){
buffer_address = 0xFF;
// clear TWI interrupt flag, prepare to receive next byte and acknowledge
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
}
else if( (TWSR & 0xF8) == TW_SR_DATA_ACK ){ // data has been received in slave receiver mode
// save the received byte inside data
data = TWDR;
// check wether an address has already been transmitted or not
if(buffer_address == 0xFF){
buffer_address = data;
// clear TWI interrupt flag, prepare to receive next byte and acknowledge
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
}
else{ // if a databyte has already been received
// store the data at the current address
rxbuffer[buffer_address] = data;
// increment the buffer address
buffer_address++;
// if there is still enough space inside the buffer
if(buffer_address < 0xFF){
// clear TWI interrupt flag, prepare to receive next byte and acknowledge
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
}
else{
// clear TWI interrupt flag, prepare to receive last byte and don't acknowledge
TWCR |= (1<<TWIE) | (1<<TWINT) | (0<<TWEA) | (1<<TWEN);
}
}
}
else if( (TWSR & 0xF8) == TW_ST_DATA_ACK ){ // device has been addressed to be a transmitter
// copy data from TWDR to the temporary memory
data = TWDR;
// if no buffer read address has been sent yet
if( buffer_address == 0xFF ){
buffer_address = data;
}
// copy the specified buffer address into the TWDR register for transmission
TWDR = txbuffer[buffer_address];
// increment buffer read address
buffer_address++;
// if there is another buffer address that can be sent
if(buffer_address < 0xFF){
// clear TWI interrupt flag, prepare to send next byte and receive acknowledge
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
}
else{
// clear TWI interrupt flag, prepare to send last byte and receive not acknowledge
TWCR |= (1<<TWIE) | (1<<TWINT) | (0<<TWEA) | (1<<TWEN);
}
}
else{
// if none of the above apply prepare TWI to be addressed again
TWCR |= (1<<TWIE) | (1<<TWEA) | (1<<TWEN);
}
}