Added mock master
Fixed communication bugs
This commit is contained in:
parent
ff315ae20e
commit
da09f40443
263
module/mockmaster/mockmaster.ino
Normal file
263
module/mockmaster/mockmaster.ino
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
/*
|
||||||
|
* Stairs lighting
|
||||||
|
* Copyright 2017 (c) Mark van Renswoude
|
||||||
|
*
|
||||||
|
* https://git.x2software.net/pub/Stairs
|
||||||
|
*/
|
||||||
|
#include <RS485_non_blocking.h>
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
#define SERIAL_COMMANDS_DEBUG
|
||||||
|
#include <SerialCommands.h>
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t PinRS485Receive = 2;
|
||||||
|
const uint8_t PinRS485Transmit = 3;
|
||||||
|
const uint8_t PinRS485WriteEnable = 4;
|
||||||
|
|
||||||
|
const uint32_t RS485BaudRate = 76800;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RS485 communication
|
||||||
|
*/
|
||||||
|
SoftwareSerial rs485(PinRS485Receive, PinRS485Transmit);
|
||||||
|
|
||||||
|
size_t doWrite(const byte what)
|
||||||
|
{
|
||||||
|
return rs485.write (what);
|
||||||
|
}
|
||||||
|
|
||||||
|
int doAvailable()
|
||||||
|
{
|
||||||
|
return rs485.available ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int doRead()
|
||||||
|
{
|
||||||
|
return rs485.read ();
|
||||||
|
}
|
||||||
|
|
||||||
|
RS485 comm(doRead, doAvailable, doWrite, 20);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Serial communication (user input)
|
||||||
|
*/
|
||||||
|
SerialCommand cmdPing("ping", handlePingCommand);
|
||||||
|
SerialCommand cmdDisplay("display", handleDisplayCommand);
|
||||||
|
SerialCommand cmdLink("link", handleLinkCommand);
|
||||||
|
SerialCommand cmdLinkAssign("assign", handleLinkAssignCommand);
|
||||||
|
SerialCommand cmdLinkStop("stop", handleLinkStopCommand);
|
||||||
|
SerialCommand cmdSetPWM("setPWM", handlesetPWMCommand);
|
||||||
|
SerialCommand cmdGetSensors("getSensors", handlegetSensorsCommand);
|
||||||
|
|
||||||
|
|
||||||
|
char commandBuffer[32];
|
||||||
|
SerialCommands serialCommands(&Serial, commandBuffer, sizeof(commandBuffer), "\r\n", " ");
|
||||||
|
|
||||||
|
void cmdUnrecognized(SerialCommands* sender, const char* cmd)
|
||||||
|
{
|
||||||
|
sender->GetSerial()->print("ERROR: Unrecognized command [");
|
||||||
|
sender->GetSerial()->print(cmd);
|
||||||
|
sender->GetSerial()->println("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool inLink = false;
|
||||||
|
|
||||||
|
|
||||||
|
void showCommands()
|
||||||
|
{
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println("Available commands:");
|
||||||
|
Serial.println(" ping [moduleIndex]");
|
||||||
|
Serial.println(" display");
|
||||||
|
Serial.println(" link");
|
||||||
|
Serial.println(" setPWM [moduleIndex] [flags] [value1] [value2]");
|
||||||
|
Serial.println(" getSensors [moduleIndex]");
|
||||||
|
Serial.println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
pinMode(PinRS485WriteEnable, OUTPUT);
|
||||||
|
|
||||||
|
rs485.begin(RS485BaudRate);
|
||||||
|
comm.begin();
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
serialCommands.AddCommand(&cmdPing);
|
||||||
|
serialCommands.AddCommand(&cmdDisplay);
|
||||||
|
serialCommands.AddCommand(&cmdLink);
|
||||||
|
serialCommands.AddCommand(&cmdLinkAssign);
|
||||||
|
serialCommands.AddCommand(&cmdLinkStop);
|
||||||
|
serialCommands.AddCommand(&cmdSetPWM);
|
||||||
|
serialCommands.AddCommand(&cmdGetSensors);
|
||||||
|
serialCommands.SetDefaultHandler(&cmdUnrecognized);
|
||||||
|
|
||||||
|
Serial.println("Stairs module Mock Master ready");
|
||||||
|
showCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop ()
|
||||||
|
{
|
||||||
|
serialCommands.ReadSerial();
|
||||||
|
|
||||||
|
if (comm.update())
|
||||||
|
handleCommMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sendCommMessage(const byte* data, size_t len)
|
||||||
|
{
|
||||||
|
digitalWrite(PinRS485WriteEnable, HIGH);
|
||||||
|
comm.sendMsg(data, len);
|
||||||
|
digitalWrite(PinRS485WriteEnable, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handlePingCommand(SerialCommands* sender)
|
||||||
|
{
|
||||||
|
if (inLink) return;
|
||||||
|
|
||||||
|
int moduleIndex = atoi(sender->Next());
|
||||||
|
|
||||||
|
sender->GetSerial()->println("> Ping");
|
||||||
|
const byte msg[] = { CommandPing, moduleIndex };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleDisplayCommand(SerialCommands* sender)
|
||||||
|
{
|
||||||
|
if (inLink) return;
|
||||||
|
|
||||||
|
sender->GetSerial()->println("> DisplayModuleIndex");
|
||||||
|
const byte msg[] = { CommandDisplayModuleIndex };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleLinkCommand(SerialCommands* sender)
|
||||||
|
{
|
||||||
|
if (inLink) return;
|
||||||
|
|
||||||
|
sender->GetSerial()->println("> Link");
|
||||||
|
const byte msg[] = { CommandStartLink };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
|
||||||
|
sender->GetSerial()->println("");
|
||||||
|
sender->GetSerial()->println("Available commands:");
|
||||||
|
sender->GetSerial()->println(" assign [moduleIndex]");
|
||||||
|
sender->GetSerial()->println(" stop");
|
||||||
|
sender->GetSerial()->println("");
|
||||||
|
|
||||||
|
inLink = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleLinkAssignCommand(SerialCommands* sender)
|
||||||
|
{
|
||||||
|
if (!inLink) return;
|
||||||
|
|
||||||
|
int moduleIndex = atoi(sender->Next());
|
||||||
|
|
||||||
|
sender->GetSerial()->println("> LinkRequest response");
|
||||||
|
const byte msg[] = { ResponseRequestLink, moduleIndex };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleLinkStopCommand(SerialCommands* sender)
|
||||||
|
{
|
||||||
|
if (!inLink) return;
|
||||||
|
|
||||||
|
sender->GetSerial()->println("> StopLink");
|
||||||
|
const byte msg[] = { CommandStopLink };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
|
||||||
|
inLink = false;
|
||||||
|
showCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handlesetPWMCommand(SerialCommands* sender)
|
||||||
|
{
|
||||||
|
if (inLink) return;
|
||||||
|
|
||||||
|
int flags = atoi(sender->Next());
|
||||||
|
int value1 = atoi(sender->Next());
|
||||||
|
int value2 = atoi(sender->Next());
|
||||||
|
|
||||||
|
sender->GetSerial()->println("> Ping");
|
||||||
|
const byte msg[] = { CommandSetPWM, (uint8_t)flags, (uint16_t)value1, (uint16_t)value2 };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handlegetSensorsCommand(SerialCommands* sender)
|
||||||
|
{
|
||||||
|
if (inLink) return;
|
||||||
|
|
||||||
|
int moduleIndex = atoi(sender->Next());
|
||||||
|
|
||||||
|
sender->GetSerial()->println("> GetSensors");
|
||||||
|
const byte msg[] = { CommandGetSensors, moduleIndex };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleCommMessage()
|
||||||
|
{
|
||||||
|
uint8_t* data = comm.getData();
|
||||||
|
uint8_t length = comm.getLength();
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t command = *data; data++; length--;
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case ResponsePing:
|
||||||
|
if (length > 0)
|
||||||
|
Serial.println("< Ping response, module index = " + String(*data));
|
||||||
|
else
|
||||||
|
Serial.println("< Ping response, module index = <missing>");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CommandRequestLink:
|
||||||
|
Serial.println("< Request link");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ResponseSetPWM:
|
||||||
|
Serial.println("< Set PWM response, module index = " + String(*data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ResponseGetSensors:
|
||||||
|
Serial.println("< Get sensors response, module index = " + String(*data)); data++; length--;
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
Serial.println(" Sensor 1 value: " + String(*data)); data++; length--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Serial.println(" Sensor 1 value: <missing>");
|
||||||
|
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
Serial.println(" Sensor 2 value: " + String(*data)); data++; length--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Serial.println(" Sensor 2 value: <missing>");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ResponseUhmWhat:
|
||||||
|
Serial.println("< Uhm, what? module index = " + String(*data));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
155
module/mockmaster/protocol.h
Normal file
155
module/mockmaster/protocol.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Stairs lighting
|
||||||
|
* Copyright 2017 (c) Mark van Renswoude
|
||||||
|
*
|
||||||
|
* https://git.x2software.net/pub/Stairs
|
||||||
|
*/
|
||||||
|
#ifndef __protocol
|
||||||
|
#define __protocol
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are three classes of messages, these masks provide a way to identify
|
||||||
|
* unknown messages if the protocol ever changes.
|
||||||
|
*
|
||||||
|
* MaskBroadcastCommand: commands which do not expect a response
|
||||||
|
* MaskModuleCommand: commands which do expect a command. respond with ResponseUhmWhat to satisfy the response requirement.
|
||||||
|
* MaskResponse: responses to commands
|
||||||
|
*/
|
||||||
|
const uint8_t MaskMessageType = 0b11000000;
|
||||||
|
|
||||||
|
const uint8_t MaskBroadcastCommand = 0b10000000;
|
||||||
|
const uint8_t MaskModuleCommand = 0b11000000;
|
||||||
|
const uint8_t MaskResponse = 0b01000000;
|
||||||
|
|
||||||
|
const uint8_t ResponseUhmWhat = 0x00 | MaskResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ping:
|
||||||
|
* Aimed at a specific module, which must respond with a
|
||||||
|
* ResponsePing message.
|
||||||
|
*
|
||||||
|
* Request:
|
||||||
|
* [0] CommandPing
|
||||||
|
* [1] Module index
|
||||||
|
*
|
||||||
|
* Response:
|
||||||
|
* [0] ResponsePing
|
||||||
|
* [1] Module index
|
||||||
|
*/
|
||||||
|
const uint8_t BasePing = 0x01;
|
||||||
|
const uint8_t CommandPing = BasePing | MaskModuleCommand;
|
||||||
|
const uint8_t ResponsePing = BasePing | MaskResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display module index:
|
||||||
|
* Broadcast to all modules which should turn on their display
|
||||||
|
* and show the current settings. No response is expected.
|
||||||
|
*
|
||||||
|
* Request:
|
||||||
|
* [0] CommandDisplayModuleIndex
|
||||||
|
*/
|
||||||
|
const uint8_t CommandDisplayModuleIndex = 0x02 | MaskBroadcastCommand;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start linking:
|
||||||
|
* Broadcast to all modules which should change to link mode.
|
||||||
|
* During link mode the master will disable all other communication,
|
||||||
|
* allowing the module to respond at will in response to user input.
|
||||||
|
*
|
||||||
|
* Each module should send a CommandRequestLink message when user input
|
||||||
|
* is provided.
|
||||||
|
*
|
||||||
|
* Request:
|
||||||
|
* [0] CommandStartLink
|
||||||
|
*
|
||||||
|
* Response (eventually):
|
||||||
|
* See CommandRequestLink
|
||||||
|
*/
|
||||||
|
const uint8_t CommandStartLink = 0x10 | MaskBroadcastCommand;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request link:
|
||||||
|
* Sent by a module when user input is provided to link this module
|
||||||
|
* as the next in line. All other modules should disable sending this
|
||||||
|
* message until the currently requesting module receives a response.
|
||||||
|
*
|
||||||
|
* The master must respond with the new module index, which the
|
||||||
|
* module must apply and store immediately.
|
||||||
|
*
|
||||||
|
* Request:
|
||||||
|
* [0] CommandRequestLink
|
||||||
|
*
|
||||||
|
* Response:
|
||||||
|
* [0] ResponseRequestLink
|
||||||
|
* [1] New module index
|
||||||
|
*/
|
||||||
|
const uint8_t BaseRequestLink = 0x11;
|
||||||
|
const uint8_t CommandRequestLink = BaseRequestLink | MaskBroadcastCommand;
|
||||||
|
const uint8_t ResponseRequestLink = BaseRequestLink | MaskResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop linking:
|
||||||
|
* Broadcast to all modules when the master takes back control
|
||||||
|
* over the communication line. No response is expected.
|
||||||
|
*
|
||||||
|
* Request:
|
||||||
|
* [0] CommandStopLink
|
||||||
|
*/
|
||||||
|
const uint8_t CommandStopLink = 0x12 | MaskBroadcastCommand;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set PWM value:
|
||||||
|
* Aimed at a specific module, which must apply the specified
|
||||||
|
* PWM values to the LED strips and respond with a
|
||||||
|
* ResponseSetPWM message.
|
||||||
|
*
|
||||||
|
* Request:
|
||||||
|
* [0] CommandSetPWM
|
||||||
|
* [1] Module index
|
||||||
|
* [2] Flags, see below
|
||||||
|
* [3,4] PWM value for step 1 (0-4095, uint16_t)
|
||||||
|
* [5,6] PWM value for step 2 (0-4095, uint16_t)
|
||||||
|
*
|
||||||
|
* Response:
|
||||||
|
* [0] ResponseSetPWM
|
||||||
|
* [1] Module index
|
||||||
|
*/
|
||||||
|
const uint8_t BaseSetPWM = 0x20;
|
||||||
|
const uint8_t CommandSetPWM = BaseSetPWM | MaskModuleCommand;
|
||||||
|
const uint8_t ResponseSetPWM = BaseSetPWM | MaskResponse;
|
||||||
|
|
||||||
|
// If included, the on-board verification LEDs should light up with
|
||||||
|
// the specified PWM values as well. Otherwise they should be off.
|
||||||
|
const uint8_t SetPWMFlagModuleLEDs = 0x01;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get sensor values:
|
||||||
|
* Aimed at a specific module, which must response with a
|
||||||
|
* ResponseGetSensors message containing the current sensor states.
|
||||||
|
*
|
||||||
|
* Request:
|
||||||
|
* [0] CommandGetSensors
|
||||||
|
* [1] Module index
|
||||||
|
*
|
||||||
|
* Response:
|
||||||
|
* [0] ResponseGetSensors
|
||||||
|
* [1] Module index
|
||||||
|
* [2] Analog (0-255) or digital (0, 255) value for sensor 1
|
||||||
|
* [3] Analog (0-255) or digital (0, 255) value for sensor 2
|
||||||
|
*/
|
||||||
|
const uint8_t BaseGetSensors = 0x30;
|
||||||
|
const uint8_t CommandGetSensors = BaseGetSensors | MaskModuleCommand;
|
||||||
|
const uint8_t ResponseGetSensors = BaseGetSensors | MaskResponse;
|
||||||
|
|
||||||
|
#endif
|
@ -15,7 +15,7 @@
|
|||||||
// Source: http://www.robotroom.com/Asynchronous-Serial-Communication-2.html
|
// Source: http://www.robotroom.com/Asynchronous-Serial-Communication-2.html
|
||||||
const uint32_t CommBaudRate = 76800;
|
const uint32_t CommBaudRate = 76800;
|
||||||
|
|
||||||
// Pin connected to the MAX485's Receiver and Driver Output Enable pins
|
// Arduino pin number connected to the MAX485's Receiver and Driver Output Enable pins
|
||||||
const uint8_t CommWriteEnablePin = 2;
|
const uint8_t CommWriteEnablePin = 2;
|
||||||
|
|
||||||
// How long the display should stay on once it's idle and showing the
|
// How long the display should stay on once it's idle and showing the
|
||||||
@ -28,4 +28,10 @@ const uint32_t DisplayIdleTimeout = 5000;
|
|||||||
// so no need to panic immediately.
|
// so no need to panic immediately.
|
||||||
const uint32_t CommIdleTimeout = 1000;
|
const uint32_t CommIdleTimeout = 1000;
|
||||||
|
|
||||||
|
// Arduino pin number connected to the push button.
|
||||||
|
const uint8_t PinButton = 8;
|
||||||
|
|
||||||
|
// Debounce time for the push button. Since it is not used for fast operations, this can be relatively high.
|
||||||
|
const uint32_t ButtonDebounceTime = 500;
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -30,6 +30,7 @@ void Display::update()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case State::Linking:
|
case State::Linking:
|
||||||
|
case State::LinkingRequest:
|
||||||
drawLinking();
|
drawLinking();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ void Display::update()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case State::DisplayModuleIndex:
|
case State::DisplayModuleIndex:
|
||||||
if (currentTime - mLastStateChange >= DisplayIdleTimeout)
|
if (mLastDrawnState == state && currentTime - mLastStateChange >= DisplayIdleTimeout)
|
||||||
{
|
{
|
||||||
state = State::DisplayOff;
|
state = State::DisplayOff;
|
||||||
off();
|
off();
|
||||||
@ -140,15 +141,27 @@ void Display::setLastDrawnState()
|
|||||||
void Display::off()
|
void Display::off()
|
||||||
{
|
{
|
||||||
if (mLastDrawnState != State::DisplayOff)
|
if (mLastDrawnState != State::DisplayOff)
|
||||||
|
{
|
||||||
|
// I've had trouble waking the display up again, so just clear it for now
|
||||||
mDisplay->ssd1306_command(SSD1306_DISPLAYOFF);
|
mDisplay->ssd1306_command(SSD1306_DISPLAYOFF);
|
||||||
|
mDisplay->ssd1306_command(SSD1306_CHARGEPUMP);
|
||||||
|
mDisplay->ssd1306_command(0x10); // disable charge pump
|
||||||
|
//mDisplay->clearDisplay();
|
||||||
|
//mDisplay->display();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Display::checkOn()
|
void Display::checkOn()
|
||||||
{
|
{
|
||||||
if (mLastDrawnState == State::DisplayOff)
|
if (mLastDrawnState == State::DisplayOff)
|
||||||
|
{
|
||||||
|
mDisplay->ssd1306_command(SSD1306_CHARGEPUMP);
|
||||||
|
mDisplay->ssd1306_command(0x14); // enable charge pump
|
||||||
|
|
||||||
mDisplay->ssd1306_command(SSD1306_DISPLAYON);
|
mDisplay->ssd1306_command(SSD1306_DISPLAYON);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Display::drawTitle(const char* title)
|
void Display::drawTitle(const char* title)
|
||||||
|
@ -26,6 +26,8 @@ void setup()
|
|||||||
Serial.begin(CommBaudRate);
|
Serial.begin(CommBaudRate);
|
||||||
pinMode(CommWriteEnablePin, OUTPUT);
|
pinMode(CommWriteEnablePin, OUTPUT);
|
||||||
comm.begin();
|
comm.begin();
|
||||||
|
|
||||||
|
pinMode(PinButton, INPUT_PULLUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -40,6 +42,8 @@ void handleStopLink(uint8_t* data, uint8_t length);
|
|||||||
void handleSetPWM(uint8_t* data, uint8_t length);
|
void handleSetPWM(uint8_t* data, uint8_t length);
|
||||||
void handleGetSensors(uint8_t* data, uint8_t length);
|
void handleGetSensors(uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
void checkButtonPress();
|
||||||
|
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
@ -48,6 +52,7 @@ void loop()
|
|||||||
if (comm.update())
|
if (comm.update())
|
||||||
handleCommMessage();
|
handleCommMessage();
|
||||||
|
|
||||||
|
checkButtonPress();
|
||||||
display.update();
|
display.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +62,18 @@ void sendCommMessage(const uint8_t* data, uint8_t size)
|
|||||||
{
|
{
|
||||||
digitalWrite(CommWriteEnablePin, HIGH);
|
digitalWrite(CommWriteEnablePin, HIGH);
|
||||||
comm.sendMsg(data, size);
|
comm.sendMsg(data, size);
|
||||||
|
|
||||||
|
|
||||||
|
// Wait for the hardware buffer to clear before turning
|
||||||
|
// off the write enable pin, or we'll cut off the message too early
|
||||||
|
// Straight from: http://www.gammon.com.au/forum/?id=11428
|
||||||
|
|
||||||
|
while (!(UCSR0A & (1 << UDRE0))) // Wait for empty transmit buffer
|
||||||
|
UCSR0A |= 1 << TXC0; // mark transmission not complete
|
||||||
|
|
||||||
|
while (!(UCSR0A & (1 << TXC0))); // Wait for the transmission to complete
|
||||||
|
|
||||||
|
|
||||||
digitalWrite(CommWriteEnablePin, LOW);
|
digitalWrite(CommWriteEnablePin, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +92,7 @@ void handleCommMessage()
|
|||||||
uint8_t command = *data; data++; length--;
|
uint8_t command = *data; data++; length--;
|
||||||
uint8_t moduleIndex = ModuleIndexUndefined;
|
uint8_t moduleIndex = ModuleIndexUndefined;
|
||||||
|
|
||||||
if (command & MaskModuleCommand)
|
if ((command & MaskMessageType) == MaskModuleCommand)
|
||||||
{
|
{
|
||||||
if (!settings.hasModuleIndex())
|
if (!settings.hasModuleIndex())
|
||||||
// We're not linked yet
|
// We're not linked yet
|
||||||
@ -99,7 +116,7 @@ void handleCommMessage()
|
|||||||
case CommandGetSensors: handleGetSensors(data, length); break;
|
case CommandGetSensors: handleGetSensors(data, length); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (command & MaskModuleCommand)
|
if ((command & MaskMessageType) == MaskModuleCommand)
|
||||||
{
|
{
|
||||||
// Sender expects a response from us
|
// Sender expects a response from us
|
||||||
const uint8_t msg[] = { ResponseUhmWhat, moduleIndex };
|
const uint8_t msg[] = { ResponseUhmWhat, moduleIndex };
|
||||||
@ -134,7 +151,7 @@ void handleRequestLinkResponse(uint8_t* data, uint8_t length)
|
|||||||
if (length == 0)
|
if (length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (state != State::Linking)
|
if (state != State::LinkingRequest)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
settings.setModuleIndex(*data);
|
settings.setModuleIndex(*data);
|
||||||
@ -144,7 +161,7 @@ void handleRequestLinkResponse(uint8_t* data, uint8_t length)
|
|||||||
|
|
||||||
void handleStopLink(uint8_t* data, uint8_t length)
|
void handleStopLink(uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (state == State::Linking || state == State::LinkingSet)
|
if (state == State::Linking || state == State::LinkingRequest || state == State::LinkingSet)
|
||||||
state = State::DisplayModuleIndex;
|
state = State::DisplayModuleIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,3 +204,21 @@ void handleGetSensors(uint8_t* data, uint8_t length)
|
|||||||
const uint8_t msg[] = { ResponseSetPWM, settings.getModuleIndex(), sensor1, sensor2 };
|
const uint8_t msg[] = { ResponseSetPWM, settings.getModuleIndex(), sensor1, sensor2 };
|
||||||
sendCommMessage(msg, sizeof(msg));
|
sendCommMessage(msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t lastButtonPress = 0;
|
||||||
|
|
||||||
|
void checkButtonPress()
|
||||||
|
{
|
||||||
|
if ((state == State::Linking || state == State::LinkingRequest) &&
|
||||||
|
digitalRead(PinButton) == HIGH &&
|
||||||
|
currentTime - lastButtonPress >= ButtonDebounceTime)
|
||||||
|
{
|
||||||
|
state = State::LinkingRequest;
|
||||||
|
|
||||||
|
const uint8_t msg[] = { CommandRequestLink };
|
||||||
|
sendCommMessage(msg, sizeof(msg));
|
||||||
|
|
||||||
|
lastButtonPress = currentTime;
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,8 @@
|
|||||||
* MaskModuleCommand: commands which do expect a command. respond with ResponseUhmWhat to satisfy the response requirement.
|
* MaskModuleCommand: commands which do expect a command. respond with ResponseUhmWhat to satisfy the response requirement.
|
||||||
* MaskResponse: responses to commands
|
* MaskResponse: responses to commands
|
||||||
*/
|
*/
|
||||||
|
const uint8_t MaskMessageType = 0b11000000;
|
||||||
|
|
||||||
const uint8_t MaskBroadcastCommand = 0b10000000;
|
const uint8_t MaskBroadcastCommand = 0b10000000;
|
||||||
const uint8_t MaskModuleCommand = 0b11000000;
|
const uint8_t MaskModuleCommand = 0b11000000;
|
||||||
const uint8_t MaskResponse = 0b01000000;
|
const uint8_t MaskResponse = 0b01000000;
|
||||||
@ -38,8 +40,9 @@ const uint8_t ResponseUhmWhat = 0x00 | MaskResponse;
|
|||||||
* [0] ResponsePing
|
* [0] ResponsePing
|
||||||
* [1] Module index
|
* [1] Module index
|
||||||
*/
|
*/
|
||||||
const uint8_t CommandPing = 0x01 | MaskModuleCommand;
|
const uint8_t BasePing = 0x01;
|
||||||
const uint8_t ResponsePing = CommandPing | MaskResponse;
|
const uint8_t CommandPing = BasePing | MaskModuleCommand;
|
||||||
|
const uint8_t ResponsePing = BasePing | MaskResponse;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -88,8 +91,9 @@ const uint8_t CommandStartLink = 0x10 | MaskBroadcastCommand;
|
|||||||
* [0] ResponseRequestLink
|
* [0] ResponseRequestLink
|
||||||
* [1] New module index
|
* [1] New module index
|
||||||
*/
|
*/
|
||||||
const uint8_t CommandRequestLink = 0x11 | MaskBroadcastCommand;
|
const uint8_t BaseRequestLink = 0x11;
|
||||||
const uint8_t ResponseRequestLink = CommandRequestLink | MaskResponse;
|
const uint8_t CommandRequestLink = BaseRequestLink | MaskBroadcastCommand;
|
||||||
|
const uint8_t ResponseRequestLink = BaseRequestLink | MaskResponse;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -120,8 +124,9 @@ const uint8_t CommandStopLink = 0x12 | MaskBroadcastCommand;
|
|||||||
* [0] ResponseSetPWM
|
* [0] ResponseSetPWM
|
||||||
* [1] Module index
|
* [1] Module index
|
||||||
*/
|
*/
|
||||||
const uint8_t CommandSetPWM = 0x20 | MaskModuleCommand;
|
const uint8_t BaseSetPWM = 0x20;
|
||||||
const uint8_t ResponseSetPWM = CommandSetPWM | MaskResponse;
|
const uint8_t CommandSetPWM = BaseSetPWM | MaskModuleCommand;
|
||||||
|
const uint8_t ResponseSetPWM = BaseSetPWM | MaskResponse;
|
||||||
|
|
||||||
// If included, the on-board verification LEDs should light up with
|
// If included, the on-board verification LEDs should light up with
|
||||||
// the specified PWM values as well. Otherwise they should be off.
|
// the specified PWM values as well. Otherwise they should be off.
|
||||||
@ -143,7 +148,8 @@ const uint8_t SetPWMFlagModuleLEDs = 0x01;
|
|||||||
* [2] Analog (0-255) or digital (0, 255) value for sensor 1
|
* [2] Analog (0-255) or digital (0, 255) value for sensor 1
|
||||||
* [3] Analog (0-255) or digital (0, 255) value for sensor 2
|
* [3] Analog (0-255) or digital (0, 255) value for sensor 2
|
||||||
*/
|
*/
|
||||||
const uint8_t CommandGetSensors = 0x30 | MaskModuleCommand;
|
const uint8_t BaseGetSensors = 0x30;
|
||||||
const uint8_t ResponseGetSensors = CommandGetSensors | MaskResponse;
|
const uint8_t CommandGetSensors = BaseGetSensors | MaskModuleCommand;
|
||||||
|
const uint8_t ResponseGetSensors = BaseGetSensors | MaskResponse;
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -54,5 +54,5 @@ void Settings::setModuleIndex(uint8_t index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
mModuleIndex = index;
|
mModuleIndex = index;
|
||||||
// ToDo re-enable: EEPROM.put(EEPROMAddressModuleIndex, mModuleIndex);
|
EEPROM.put(EEPROMAddressModuleIndex, mModuleIndex);
|
||||||
}
|
}
|
@ -11,6 +11,7 @@ enum struct State: uint8_t
|
|||||||
{
|
{
|
||||||
WaitingForComm,
|
WaitingForComm,
|
||||||
Linking,
|
Linking,
|
||||||
|
LinkingRequest,
|
||||||
LinkingSet,
|
LinkingSet,
|
||||||
DisplayModuleIndex,
|
DisplayModuleIndex,
|
||||||
DisplayOff
|
DisplayOff
|
||||||
|
Loading…
Reference in New Issue
Block a user