Skip to content

Instantly share code, notes, and snippets.

@ganlhi

ganlhi/apu.ino Secret

Created January 4, 2021 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ganlhi/95886230c3c18cb1d0371dddfefaec12 to your computer and use it in GitHub Desktop.
Save ganlhi/95886230c3c18cb1d0371dddfefaec12 to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <Button.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
/****************
* Pins numbers *
****************/
#define BTN_APU_PWR 2
#define BTN_APU_STARTER 3
#define BTN_APU_GEN 4
#define BTN_APU_BLAIR 5
#define LED_APU_RUN 6
#define LED_APU_FAIL 7
#define LED_APU_STARTER 8
#define LED_APU_GENON 9
#define LED_APU_GENWARN 10
#define LED_APU_BLEEDOPEN 11
#define LED_APU_OHT 12
/**********************
* Q400 UDP variables *
**********************/
#define VAR_APU_PWR 0x1046
#define VAR_APU_STARTER 0x1047
#define VAR_APU_GEN 0x1048
#define VAR_APU_BLAIR 0x1049
#define VAR_APU_RUN_LT 0x104A
#define VAR_APU_FAIL_LT 0x104B
#define VAR_APU_STARTER_LT 0x104C
#define VAR_APU_GENON_LT 0x104D
#define VAR_APU_GENWARN_LT 0x104E
#define VAR_APU_BLEEDOPEN_LT 0x104F
#define VAR_APU_OHT_LT 0x1050
/*****************
* Network setup *
*****************/
#define NET_PORT_LOCAL 8888
#define NET_PORT_REMOTE 8888
// Uncomment line below to use DHCP
//#define USE_DHCP
byte NET_IP_LOCAL[] = {192, 168, 0, 200};
byte NET_IP_REMOTE[] = {192, 168, 0, 178};
byte NET_MAC[] = {0x90, 0xA2, 0xDA, 0x0D, 0x5C, 0x18};
EthernetUDP Udp;
byte content[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet
/************************
* Buttons and switches *
************************/
Button btn_apu_pwr(BTN_APU_PWR);
Button btn_apu_starter(BTN_APU_STARTER);
Button btn_apu_gen(BTN_APU_GEN);
Button btn_apu_blair(BTN_APU_BLAIR);
/**************************
* Main Arduino functions *
**************************/
void setup()
{
Serial.begin(9600);
setup_network();
setup_inputs();
setup_outputs();
}
void loop()
{
// send buttons states
handle_button(btn_apu_pwr, VAR_APU_PWR);
handle_button(btn_apu_starter, VAR_APU_STARTER);
handle_button(btn_apu_gen, VAR_APU_GEN);
handle_button(btn_apu_blair, VAR_APU_BLAIR);
// handle incoming messages
handle_messages();
}
/**************************
* Module logic functions *
**************************/
void setup_network()
{
#ifdef USE_DHCP
Ethernet.begin(NET_MAC);
#else
Ethernet.begin(NET_MAC, NET_IP_LOCAL);
#endif
Serial.print("IP : ");
Serial.println(Ethernet.localIP());
Udp.begin(NET_PORT_LOCAL);
}
void setup_inputs()
{
btn_apu_pwr.begin();
btn_apu_starter.begin();
btn_apu_gen.begin();
btn_apu_blair.begin();
}
void setup_outputs()
{
pinMode(LED_APU_RUN, OUTPUT);
digitalWrite(LED_APU_RUN, LOW);
pinMode(LED_APU_FAIL, OUTPUT);
digitalWrite(LED_APU_FAIL, LOW);
pinMode(LED_APU_STARTER, OUTPUT);
digitalWrite(LED_APU_STARTER, LOW);
pinMode(LED_APU_GENON, OUTPUT);
digitalWrite(LED_APU_GENON, LOW);
pinMode(LED_APU_GENWARN, OUTPUT);
digitalWrite(LED_APU_GENWARN, LOW);
pinMode(LED_APU_BLEEDOPEN, OUTPUT);
digitalWrite(LED_APU_BLEEDOPEN, LOW);
pinMode(LED_APU_OHT, OUTPUT);
digitalWrite(LED_APU_OHT, LOW);
}
void handle_button(Button btn, word var_id)
{
if (btn.toggled())
{
byte *msg = build_message_byte(var_id, btn.read() == Button::PRESSED ? 0x01 : 0x00);
send_message(msg);
free(msg);
}
}
void handle_messages()
{
byte packetSize = Udp.parsePacket();
if (packetSize)
{
Serial.print("Received packet of size");
Serial.println(packetSize);
Udp.read(content, UDP_TX_PACKET_MAX_SIZE);
byte *msg_data;
word var_id = decode_message(content, msg_data);
int status = msg_data[0] > 0 ? HIGH : LOW;
int pin;
switch (var_id)
{
case VAR_APU_RUN_LT:
pin = LED_APU_RUN;
break;
case VAR_APU_FAIL_LT:
pin = LED_APU_FAIL;
break;
case VAR_APU_STARTER_LT:
pin = LED_APU_STARTER;
break;
case VAR_APU_GENON_LT:
pin = LED_APU_GENON;
break;
case VAR_APU_GENWARN_LT:
pin = LED_APU_GENWARN;
break;
case VAR_APU_BLEEDOPEN_LT:
pin = LED_APU_BLEEDOPEN;
break;
case VAR_APU_OHT_LT:
pin = LED_APU_OHT;
break;
default:
break;
}
digitalWrite(pin, status);
free(msg_data);
}
}
/*********************
* Utility functions *
*********************/
void send_message(byte *msg)
{
Udp.beginPacket(NET_IP_REMOTE, NET_PORT_REMOTE);
Udp.write(msg, get_size(msg));
Udp.endPacket();
}
byte *build_message(word var_id, byte *data_in)
{
word data_size = sizeof data_in / sizeof data_in[0];
byte var_id_bytes[2];
word_to_bytes(var_id, var_id_bytes);
word msg_size = 8 + data_size;
byte msg_size_bytes[2];
word_to_bytes(msg_size, msg_size_bytes);
byte *msg = (byte *)malloc(msg_size * sizeof(byte));
msg[0] = 0x21;
msg[1] = 0x52;
msg[2] = 0xff;
msg[3] = 0xff;
msg[4] = var_id_bytes[0];
msg[5] = var_id_bytes[1];
msg[6] = msg_size_bytes[0];
msg[7] = msg_size_bytes[1];
for (int i = 0; i < data_size; i++)
{
msg[8 + i] = data_in[i];
}
return msg;
}
byte *build_message_byte(word var_id, byte value)
{
byte data_in[1] = {value};
return build_message(var_id, data_in);
}
byte *build_message_word(word var_id, byte valueLow, byte valueHigh)
{
byte data_in[2] = {valueLow, valueHigh};
return build_message(var_id, data_in);
}
int get_size(byte *data)
{
return sizeof data / sizeof data[0];
}
word decode_message(byte *msg, byte *data_out)
{
byte var_id_bytes[2] = {msg[4], msg[5]};
word var_id = bytes_to_word(var_id_bytes);
byte data_size_bytes[2] = {msg[6], msg[7]};
word data_size = bytes_to_word(data_size_bytes);
data_out = (byte *)malloc(data_size * sizeof(byte));
for (int i = 0; i < data_size; i++)
{
data_out[i] = msg[8 + i];
}
return var_id;
}
void word_to_bytes(word value, byte *bytes)
{
bytes[1] = value & 0xff;
bytes[0] = (value >> 8) & 0xff;
}
word bytes_to_word(byte *bytes)
{
word value = (word)bytes[0] << 8 | (word)bytes[1];
return value;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment