-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathPaulCommand.cpp
More file actions
202 lines (180 loc) · 5.91 KB
/
Copy pathPaulCommand.cpp
File metadata and controls
202 lines (180 loc) · 5.91 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
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
#include <Arduino.h>
#include "PaulCommand.h"
/*
* PaulCommand.cpp
*
* functions
* listens on bus
* reads control panel messages
* saves register values
* injects responses to bus
*/
//
#define SerialDeControl 46 //RS485 Direction control
#define RelayControl1 44 // Relay Open Closed control
#define RelayControl2 45 // Relay Open Closed control
#define RS485Transmit HIGH
#define RS485Receive LOW
//
// Constructor
//
PaulCommand::PaulCommand()
{
}
void PaulCommand::init() {
//init rs485, relay
pinMode(SerialDeControl, OUTPUT);
pinMode(RelayControl1, OUTPUT);
pinMode(RelayControl2, OUTPUT);
rs485receive();
relayOff();
}
// process one word/byte from serial
void PaulCommand::addWordToMessage(word messageWord) {
if (messageWord == 0x102) // 0x102 = start of new message for control panel
{
//Serial.write("start message for 0x102;");
this->commandIndex = 0; //reset input buffer
this->commandStarted = true; //start of comm found
}
if (this->commandStarted && this->commandIndex < COMMAND_MAX_SIZE) //do not overflow
{
this->commandBuffer[this->commandIndex++] = messageWord; //save word, increment index
//is message for 0x102 completed?
if ((this->commandIndex>1) && (this->commandIndex == this->commandBuffer[1] + 4)) { // 4 bytes extra: adress, lenght, command, checksum
//logCommand();
//is it a page to save?
if (this->commandBuffer[2] == 4 && this->commandBuffer[3] >=0 && this->commandBuffer[3] <MAXPAGES*16 && this->commandBuffer[1] == 0x11) { // saves pages 0x00 - 0x50, length should be 0x11
//check checksum!
if (this->commandBuffer[20] == xorFE(this->commandBuffer,20)) { //xorFE of positions 0 till 19 (20 bytes) should be same as value date of 21st byte (position 20)
int page = this->commandBuffer[3] / 16;
memcpy(this->pages[page], this->commandBuffer, 21*2); //save page 0xxx (params: dest, source, length)
if (page == 2) {
detectControlPanel();
}
Serial.print(F("-savePage"));
Serial.print(this->commandBuffer[3], HEX);
Serial.println(F("-"));
}
}
//request for fan speed change in progess?
if (this->requestChangeFanSpeed) {
//injects reply to bus
injectReply();
}
}
}
}
void PaulCommand::detectControlPanel() {
this->controlPanelDetected = true;
if (this->pages[2][4+14]==1) { //data 14 - 1=LED,0=TFT
//LCD panel
FANSPEED_PAGE = 2; //LED
FANSPEED_POSITION = 12; //LED
} else {
//TFT
FANSPEED_PAGE = 0; //TFT
FANSPEED_POSITION = 8; //TFT
}
}
void PaulCommand::injectReply() {
//master asks whether there is something new from control panel
if (this->commandBuffer[2] == 1) {
rs485transmitOn();
if (FANSPEED_PAGE==0) {
reply0x00HasChanged(); // tft - yes, something has changed
} else {
reply0x20HasChanged(); // led - yes, something has changed
}
Serial1.flush();
rs485receive();
return;
}
//master asks for changed values on PAGE)
if (this->commandBuffer[2] == 3 && this->commandBuffer[3]==FANSPEED_PAGE*16) { //data query on PAGE?
rs485transmitOn();
replyPage(); // reply changed value
Serial1.flush();
rs485receive();
this->requestChangeFanSpeed = false;
relayOff(); //we are done, set shield back to passive mode
return;
}
}
void PaulCommand::reply0x00HasChanged() {
Serial1.write(0x101);
Serial1.write(0x02);
Serial1.write(0x02);
Serial1.write(0x82); //change on adress 0x00 (tft)
Serial1.write(0x10);
Serial1.write(0x6D);
Serial.write("-reply0x00HasChanged-");
}
void PaulCommand::reply0x20HasChanged() {
Serial1.write(0x101);
Serial1.write(0x02);
Serial1.write(0x02);
Serial1.write(0x92); //change on adress 0x20 (lcd)
Serial1.write(0x10);
Serial1.write(0x7D);
Serial.write("-reply0x20HasChanged-");
}
void PaulCommand::replyPage() {
//manipulate destadress and fanspeed, xor
this->pages[FANSPEED_PAGE][0] = 0x101; //to master
this->pages[FANSPEED_PAGE][4+FANSPEED_POSITION] = this->fanSpeed; //1st data byte is on address 0x04
this->pages[FANSPEED_PAGE][20] = xorFE(this->pages[FANSPEED_PAGE],20);
for(int i=0; i<21; i++) {
Serial1.write(this->pages[FANSPEED_PAGE][i]);
}
Serial.write("-replyPage0x"); Serial.print(FANSPEED_PAGE*16, HEX); Serial.write("-");
}
//helper methods
void PaulCommand::logCommand() {
Serial.print("commandlog:");
for (int i = 0; i < this->commandIndex; i++) {
Serial.print(this->commandBuffer[i], HEX);
Serial.print(" ");
}
Serial.println();
}
//xor - computes 0xFE XOR on given array[0 to length-1]
byte PaulCommand::xorFE(word arrayXor[], int arrayLength) {
byte checksum = 0xFE;
for(int i=0; i<arrayLength; i++) {
checksum = checksum ^ (arrayXor[i] & 0xFF); //checkum on lower 8 bit!
}
return checksum;
}
void PaulCommand::changeFanSpeed(int fanSpeed) {
Serial.print(F("changeFanSpeed"));
this->requestChangeFanSpeed = true; //start
relayOn();
this->fanSpeed = fanSpeed;
}
word PaulCommand::getPageData(int page, int data) {
if (page>=0 && page<MAXPAGES && data>=0 && data< COMMAND_MAX_SIZE) {
return this->pages[page][data];
}
return 0;
}
// arduino will acts as a led/tft panel
void PaulCommand::relayOn() {
//Serial.print("relayOn");
digitalWrite(RelayControl1, false); // false = open, led/tft panel is disconnected from rs485 bus
digitalWrite(RelayControl2, false);
}
// arduino goes in passive mode
void PaulCommand::relayOff() {
//Serial.print("relayOff");
digitalWrite(RelayControl1, true); // true = closed, led/tft is again on bus
digitalWrite(RelayControl2, true);
}
//set rs485 to transmit on, no other should transmit in thss time!
void PaulCommand::rs485transmitOn() {
digitalWrite(SerialDeControl, RS485Transmit);
}
// end transmit mode. master can then transmit
void PaulCommand::rs485receive() {
digitalWrite(SerialDeControl, RS485Receive);
}