-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMegaController.ino
170 lines (151 loc) · 4.54 KB
/
MegaController.ino
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
/* Message parsing states */
const byte READ_NEW_COMMAND = 0x00;
const byte WRITE_DIGITAL_VAL = 0x01;
const byte WRITE_DIGITAL_MODE = 0x02;
const byte HEARTBEAT_REQUEST = 0x03;
const byte DUMP_VALUES_REQUEST = 0x04;
/* Message lengths */
const int WRITE_DIGITAL_VAL_LEN = 2;
const int WRITE_DIGITAL_MODE_LEN = 2;
/* Digital pin modes */
const byte INPUT_MODE = 0x01;
const byte OUTPUT_MODE = 0x02;
const byte INPUT_PULLUP_MODE = 0x03;
/* Message numerical meanings */
const byte START_BYTE = 0xAA;
const byte DIGITAL_CHANGE = 0x00;
const byte ANALOG_CHANGE = 0x01;
const byte HEARTBEAT = 0x02;
/* Device details */
const int DIGITAL_PIN_COUNT = 54;
const int ANALOG_PIN_COUNT = 16;
const int ANALOG_STEP = 20;
/* Maintains the current device state */
byte operationState = READ_NEW_COMMAND;
/* Digital pin information */
byte digitalPinChange[DIGITAL_PIN_COUNT];
byte digitalPins[DIGITAL_PIN_COUNT];
/* Analog pin information */
byte analogPinChange[ANALOG_PIN_COUNT];
short analogPins[ANALOG_PIN_COUNT];
void setup() {
forceValueChanges();
Serial.begin(115200);
}
void loop() {
processUserRequests();
readDigital();
readAnalog();
reportDigital();
reportAnalog();
Serial.flush();
}
void processUserRequests() {
while (Serial.available() > 0) {
if (operationState == READ_NEW_COMMAND) {
if (Serial.available() >= 2) {
if (Serial.read() == START_BYTE) {
operationState = Serial.read();
}
}
}
if (operationState == WRITE_DIGITAL_VAL) {
if (Serial.available() >= WRITE_DIGITAL_VAL_LEN) {
byte address = Serial.read();
byte value = Serial.read();
writeDigitalPinValue(address, value);
operationState = READ_NEW_COMMAND;
}
}
else if (operationState == WRITE_DIGITAL_MODE) {
if (Serial.available() >= WRITE_DIGITAL_MODE_LEN) {
byte address = Serial.read();
byte value = Serial.read();
writeDigitalPinMode(address, value);
operationState = READ_NEW_COMMAND;
}
}
else if (operationState == HEARTBEAT_REQUEST) {
Serial.write(START_BYTE);
Serial.write(HEARTBEAT);
Serial.write(1);
operationState = READ_NEW_COMMAND;
}
else if (operationState == DUMP_VALUES_REQUEST) {
forceValueChanges();
operationState = READ_NEW_COMMAND;
}
else {
operationState = READ_NEW_COMMAND;
break;
}
}
}
void forceValueChanges() {
for(int i = 0; i < DIGITAL_PIN_COUNT; i++) {
digitalPins[i] = -1;
}
for(int i = 0; i < ANALOG_PIN_COUNT; i++) {
analogPins[i] = -ANALOG_STEP - 1;
}
}
void writeDigitalPinValue(byte address, byte value) {
digitalWrite(address, value > 0 ? LOW : HIGH);
}
void writeDigitalPinMode(byte address, byte value) {
switch(value) {
case INPUT_MODE:
pinMode(address, INPUT);
break;
case OUTPUT_MODE:
pinMode(address, OUTPUT);
digitalWrite(address, HIGH);
break;
case INPUT_PULLUP_MODE:
pinMode(address, INPUT_PULLUP);
break;
default:
break;
}
}
void readDigital() {
for (int pin = 0; pin < DIGITAL_PIN_COUNT; pin++) {
byte value = digitalRead(pin);
digitalPinChange[pin] = value == digitalPins[pin] ? 0 : 1;
digitalPins[pin] = value;
}
}
void reportDigital() {
for (int pin = 0; pin < DIGITAL_PIN_COUNT; pin++) {
if(digitalPinChange[pin] != 0) {
Serial.write(START_BYTE);
Serial.write(DIGITAL_CHANGE);
Serial.write(pin);
Serial.write(digitalPins[pin]);
}
}
}
void readAnalog() {
for (int pin = 0; pin < ANALOG_PIN_COUNT; pin++) {
short value = analogRead(pin);
short diff = value - analogPins[pin];
if (diff < 0) {
diff = -diff;
}
analogPinChange[pin] = diff < ANALOG_STEP ? 0 : 1;
if (analogPinChange[pin]) {
analogPins[pin] = value;
}
}
}
void reportAnalog() {
for (int pin = 0; pin < ANALOG_PIN_COUNT; pin++) {
if(analogPinChange[pin] != 0) {
Serial.write(START_BYTE);
Serial.write(ANALOG_CHANGE);
Serial.write(pin);
Serial.write(highByte(analogPins[pin]));
Serial.write(lowByte(analogPins[pin]));
}
}
}