-
Notifications
You must be signed in to change notification settings - Fork 1
/
scantronic_arduino.ino
284 lines (233 loc) · 9.53 KB
/
scantronic_arduino.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#include <SPI.h>
/*
You will need to connect the 12V pin to the VIN of the Arduino board,
the GND pin to the GND of the Arduino board, and the DATA pin
to both the MOSI and MISO pins of the Arduino board.
You will also need a resistor (e.g. 10k ohm)
between the DATA pin and the GND pin to create a pull-down effect.
*/
// Define the pins used for SPI communication
#define CS_PIN 10 // Chip select pin
#define MOSI_PIN 11 // Master out slave in pin
#define MISO_PIN 12 // Master in slave out pin
#define SCK_PIN 13 // Serial clock pin
// Define the number of bytes to read from the alarm panel
#define DATA_LENGTH 21
// Define the timing parameters of the alarm panel in microseconds
#define T 500
// Clock signal period
#define TP 5000
// Pause time between messages
#define TRM 1000 // Transfer time between bytes
// Create a buffer to store the data
byte data[DATA_LENGTH];
void setup() { // Initialize serial communication at 9600 baud rate
Serial.begin(9600);
// Set the chip select pin as output and set it high
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
// Set the SPI settings: mode 0, MSB first, external clock
SPISettings settings(0, MSBFIRST, EXTERNAL);
// Initialize SPI communication with the settings
SPI.begin();
SPI.beginTransaction(settings);
}
void loop() {
// Set the chip select pin low to start communication
digitalWrite(CS_PIN, LOW);
// Wait for the clock line to go from high to low
while (digitalRead(SCK_PIN) == HIGH) {}
// Read DATA_LENGTH bytes from the alarm panel and store them in the buffer
for (int i = 0; i < DATA_LENGTH; i++) {
data[i] = SPI.transfer(0x00); // Send dummy byte to receive data
// Wait for TRM microseconds before reading the next byte
delayMicroseconds(TRM);
}
// Set the chip select pin high to end communication
digitalWrite(CS_PIN, HIGH);
if (check_checksum(data, DATA_LENGTH)) {
// Check if byte 0 is between 0x30 and 0x39 (text panel display update message)
if (data[0] >= B00110000 && data[0] <= B00111001) {
// Parse and print the text panel display update messages to the serial monitor
parse_text_panel_display_update(data, DATA_LENGTH);
} // Check if byte 0 is 0x00 (key press data)
else if (data[0] == B00000000) {
// Parse and print the key presses to the serial monitor
parse_key_presses(data, DATA_LENGTH);
} // Check if byte 0 is 0x3f (broadcast message to all panels)
else if (data[0] == B00111111) {
// Parse and print the broadcast message to all panels to the serial monitor
parse_broadcast_message(data, DATA_LENGTH);
}
else {
// Print a message to the serial monitor that this is an unknown message type
Serial.println("Unknown message type.");
}
} else {
// Print an error message to the serial monitor
Serial.println("Invalid checksum!");
}
// Wait for TP microseconds before reading again
delayMicroseconds(TP);
}
// A function that calculates and verifies the checksum of a given array of bytes
bool check_checksum(byte* array, int length) {
// Initialize variables to store the checksum values
byte chksum1 = array[length - 2]; // The first checksum byte is at index length - 2
byte chksum2 = array[length - 1]; // The second checksum byte is at index length - 1
// Calculate the expected checksum values based on the formula given by the user
byte expected_chksum2 = 0;
// Initialize expected_chksum2 as zero
for (int i = 0; i < length - 2; i++) {
// Loop through all bytes except the checksum bytes
expected_chksum2 += array[i];
// Add each byte to expected_chksum2
expected_chksum2 &= B01111111;
// Bitwise AND with B01111111 (0x7f) to keep only the lower seven bits
//(this is equivalent to modulo by B10000000 (128))
//(this is also equivalent to using a mask of B01111111)
}
byte expected_chksum1 = B01111111 - expected_chksum2; // Calculate expected_chksum1 as B01111111 (0x7f) minus expected_chksum2
// Compare the actual checksum values with the expected checksum values
if (chksum1 == expected_chksum1 && chksum2 == expected_chksum2) {
return true; // The checksum is valid
}
else
{
return false; // The checksum is invalid
}
}
// A function that parses and prints the key presses from a given array of bytes
void parse_key_presses(byte* array, int length) {
// Initialize variables to store the key press information
byte key_code = array[1]; // The second byte is the key type
byte key_data = array[2]; // The third byte is the key data
// Print the key press information to the serial monitor
Serial.print("Key press: ");
// Check the key code and print the corresponding message
switch (key_code) {
case 0x00: // Key code 0:
Serial.println("Key 0 pressed"); break;
case 0x01: // Key code 1:
Serial.println("Key 1 pressed"); break;
case 0x02: // Key code 2:
Serial.println("Key 2 pressed"); break;
case 0x03: // Key code 3:
Serial.println("Key 3 pressed"); break;
case 0x04: // Key code 4:
Serial.println("Key 4 pressed"); break;
case 0x05: // Key code 5:
Serial.println("Key 5 pressed"); break;
case 0x06: // Key code 6:
Serial.println("Key 6 pressed"); break;
case 0x07: // Key code 7:
Serial.println("Key 7 pressed"); break;
case 0x08: // Key code 8:
Serial.println("Key 8 pressed"); break;
case 0x09: // Key code 9:
Serial.println("Key 9 pressed"); break;
case 0x0A: // Key code A:
Serial.println("Key A pressed"); break;
case 0x0B: // Key code B:
Serial.println("Key B pressed"); break;
case 0x0C: // Key code C:
Serial.println("Key C pressed"); break;
case 0x0D: // Key code D:
Serial.println("Key D pressed"); break;
case 0x0E: // Key code E:
Serial.println("Key E pressed"); break;
case 0x0F: // Key code F:
Serial.println("Key F pressed"); break;
default: // Unknown key code
Serial.println("Unknown key code"); break;
}
/*switch (key_code) {
case B00000000: // Key code 0:
Serial.println("Key 0 pressed"); break;
case B00000001: // Key code 1:
Serial.println("Key 1 pressed"); break;
case B00000010: // Key code 2:
Serial.println("Key 2 pressed"); break;
case B00000011: // Key code 3:
Serial.println("Key 3 pressed"); break;
case B00000100: // Key code 4:
Serial.println("Key 4 pressed"); break;
case B00000101: // Key code 5:
Serial.println("Key 5 pressed"); break;
case B00000110: // Key code 6:
Serial.println("Key 6 pressed"); break;
case B00000111: // Key code 7:
Serial.println("Key 7 pressed"); break;
case B00001000: // Key code 8:
Serial.println("Key 8 pressed"); break;
case B00001001: // Key code 9:
Serial.println("Key 9 pressed"); break;
case B00001010: // Key code A:
Serial.println("Key A pressed"); break;
case B00001011: // Key code B:
Serial.println("Key B pressed"); break;
case B00001100: // Key code C:
Serial.println("Key C pressed"); break;
case B00001101: // Key code D:
Serial.println("Key D pressed"); break;
case B00001110: // Key code E:
Serial.println("Key E pressed"); break;
case B00001111: // Key code F:
Serial.println("Key F pressed"); break;
default: // Unknown key code
Serial.println("Unknown key code"); break;
}
*/
// Print the key data to the serial monitor in hexadecimal format
Serial.print("Key data: ");
if (key_data < 0x10) {
Serial.print("0"); // Add leading zero if necessary
}
Serial.println(key_data, HEX);
}
void parse_broadcast_message(byte* array, int length) {
// Initialize variables to store the broadcast message information
byte line = array[1];
// The second byte is the line number on all panels
char text[17]; // A character array to store the text on all panels
// Copy the text from the data buffer to the character array
for (int i = 0; i < 16; i++) {
// Loop through bytes 2 to 17 (16 bytes of ASCII data)
text[i] = char(array[i + 2]); // Convert each byte to a character and store it in the array
}
// Add a null terminator at the end of the character array
text[16] = '\0';
// Print the broadcast message information to the serial monitor
Serial.print("Broadcast message to all panels: ");
// Print the line number in decimal format
Serial.print("Line ");
Serial.print(line, DEC);
// Print the text in quotation marks
Serial.print("""");
Serial.print(text);
Serial.println("""");
}
void parse_text_panel_display_update(byte* array, int length) {
// Initialize variables to store the text panel display update information
byte dest = array[3]; // The fourth byte is the destination panel number
byte line = array[4]; // The fifth byte is the line number on the panel
char text[17]; // A character array to store the text on the panel
// Copy the text from the data buffer to the character array
for (int i = 0; i < 16; i++) { // Loop through bytes 5 to 20 (16 bytes of ASCII data)
text[i] = char(array[i + 5]); // Convert each byte to a character and store it in the array
}
// Add a null terminator at the end of the character array
text[16] = '\0';
// Print the text panel display update information to the serial monitor
Serial.print("Text panel display update: ");
// Print the destination panel number in decimal format
Serial.print("Panel ");
Serial.print(dest, DEC);
// Print the line number in decimal format
Serial.print(" Line ");
Serial.print(line, DEC);
// Print the text in quotation marks
Serial.print("");
Serial.print(text);
Serial.println("");
}