-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
193 lines (165 loc) · 5.89 KB
/
main.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
/*
Adc is a command line controled demonstration of Interrupt Driven Analog Conversion
Copyright (C) 2016 Ronald Sutherland
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 2
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.
For a copy of the GNU General Public License use
http://www.gnu.org/licenses/gpl-2.0.html
*/
#include <avr/pgmspace.h>
#include <util/atomic.h>
#include "../lib/timers.h"
#include "../lib/uart.h"
#include "../lib/parse.h"
#include "../lib/adc.h"
#include "../lib/twi.h"
#include "../lib/rpu_mgr.h"
#include "../lib/pin_num.h"
#include "../lib/pins_board.h"
#include "../Uart/id.h"
#include "analog.h"
#include "calibrate.h"
#define ADC_DELAY_MILSEC 200UL
static unsigned long adc_started_at;
// 22mA current source enabled with CS0_EN which are defined in ../lib/pins_board.h
#define STATUS_LED CS0_EN
#define BLINK_DELAY 1000UL
static unsigned long blink_started_at;
static unsigned long blink_delay;
static char rpu_addr;
void ProcessCmd()
{
if ( (strcmp_P( command, PSTR("/id?")) == 0) && ( (arg_count == 0) || (arg_count == 1)) )
{
Id("Adc");
}
if ( (strcmp_P( command, PSTR("/analog?")) == 0) && ( (arg_count >= 1 ) && (arg_count <= 5) ) )
{
Analog(2000UL); // analog.c: show every 2 sec until terminated
}
if ( (strcmp_P( command, PSTR("/avcc")) == 0) && (arg_count == 1) )
{
CalibrateAVCC();
}
if ( (strcmp_P( command, PSTR("/onevone")) == 0) && (arg_count == 1) )
{
Calibrate1V1();
}
if ( (strcmp_P( command, PSTR("/reftoee")) == 0) && (arg_count == 0) )
{
Ref2Ee();
}
if ( (strcmp_P( command, PSTR("/reffrmee")) == 0) && (arg_count == 0) )
{
ReFmEe();
}
}
void setup(void)
{
pinMode(STATUS_LED,OUTPUT);
digitalWrite(STATUS_LED,HIGH);
// Initialize Timers, ADC, and clear bootloader, Arduino does these with init() in wiring.c
initTimers(); //Timer0 Fast PWM mode, Timer1 & Timer2 Phase Correct PWM mode.
init_ADC_single_conversion(EXTERNAL_AVCC); // warning AREF must not be connected to anything
init_uart0_after_bootloader(); // bootloader may have the UART setup
// put ADC in Auto Trigger mode and fetch an array of channels
enable_ADC_auto_conversion(BURST_MODE);
adc_started_at = millis();
/* Initialize UART, it returns a pointer to FILE so redirect of stdin and stdout works*/
stdout = stdin = uartstream0_init(BAUD);
/* Initialize I2C, with the internal pull-up
note: I2C scan will stop without a pull-up on the bus */
twi_init(TWI_PULLUP);
/* Clear and setup the command buffer, (probably not needed at this point) */
initCommandBuffer();
// Enable global interrupts to start TIMER0 and UART ISR's
sei();
blink_started_at = millis();
rpu_addr = get_Rpu_address();
blink_delay = BLINK_DELAY;
// blink fast if a default address from RPU manager not found
if (rpu_addr == 0)
{
rpu_addr = '0';
blink_delay = BLINK_DELAY/4;
}
}
void blink(void)
{
unsigned long kRuntime = millis() - blink_started_at;
if ( kRuntime > blink_delay)
{
digitalToggle(STATUS_LED);
// next toggle
blink_started_at += blink_delay;
}
}
void adc_burst(void)
{
unsigned long kRuntime= millis() - adc_started_at;
if ((kRuntime) > ((unsigned long)ADC_DELAY_MILSEC))
{
enable_ADC_auto_conversion(BURST_MODE);
adc_started_at += ADC_DELAY_MILSEC;
}
}
int main(void)
{
setup();
while(1)
{
// use LED to show if I2C has a bus manager
blink();
// check if character is available to assemble a command, e.g. non-blocking
if ( (!command_done) && uart0_available() ) // command_done is an extern from parse.h
{
// get a character from stdin and use it to assemble a command
AssembleCommand(getchar());
// address is an ascii value, warning: a null address would terminate the command string.
StartEchoWhenAddressed(rpu_addr);
}
// check if a character is available, and if so flush transmit buffer and nuke the command in process.
// A multi-drop bus can have another device start transmitting after getting an address byte so
// the first byte is used as a warning, it is the onlly chance to detect a possible collision.
if ( command_done && uart0_available() )
{
// dump the transmit buffer to limit a collision
uart0_flush();
initCommandBuffer();
}
// delay between ADC burst
adc_burst();
// finish echo of the command line befor starting a reply (or the next part of a reply)
if ( command_done && (uart0_availableForWrite() == UART_TX0_BUFFER_SIZE) )
{
if ( !echo_on )
{ // this happons when the address did not match
initCommandBuffer();
}
else
{
if (command_done == 1)
{
findCommand();
command_done = 10;
}
// do not overfill the serial buffer since that blocks looping, e.g. process a command in 32 byte chunks
if ( (command_done >= 10) && (command_done < 250) )
{
ProcessCmd();
}
else
{
initCommandBuffer();
}
}
}
}
return 0;
}