Last active
July 17, 2024 21:11
-
-
Save cyfinfaza/dc6317e7009c6292c02e4d96eb366975 to your computer and use it in GitHub Desktop.
SIL MagTile Arduino Firmware
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <Wire.h> | |
#include <EEPROM.h> | |
#define MAX_ADDRESSES 32 | |
#define MAX_ROWS 6 | |
#define MAX_COLUMNS 6 | |
#define POWER_ARRAY_ROWS (MAX_ROWS * 3) | |
#define POWER_ARRAY_COLUMNS (MAX_COLUMNS * 3) | |
struct Config { | |
uint8_t width; | |
uint8_t height; | |
uint8_t addressCount; | |
uint8_t addressList[MAX_ADDRESSES]; | |
}; | |
Config config; | |
// uint16_t powerLevels[POWER_ARRAY_ROWS][POWER_ARRAY_COLUMNS]; | |
uint8_t scannedAddresses[MAX_ADDRESSES]; | |
uint8_t scannedAddressCount = 0; | |
bool blinkingEnabled = false; | |
unsigned long lastBlinkTime = 0; | |
bool blinkState = false; | |
void scanI2CAddresses(); | |
bool testLEDEnable(int address); | |
bool testLEDDisable(int address); | |
void setPower(int row, int col, uint16_t power); | |
void blinkAll(); | |
void enableBlinking(); | |
void disableBlinking(); | |
void setup() { | |
Serial.begin(115200); | |
Wire.begin(); | |
pinMode(LED_BUILTIN, OUTPUT); // Assuming the test LED is connected to the built-in LED pin | |
// // Initialize power levels to zero | |
// for (int i = 0; i < POWER_ARRAY_ROWS; i++) { | |
// for (int j = 0; j < POWER_ARRAY_COLUMNS; j++) { | |
// powerLevels[i][j] = 0; | |
// } | |
// } | |
// Read config from EEPROM | |
EEPROM.get(512, config); | |
Serial.println("Command Line Terminal Ready"); | |
} | |
void loop() { | |
if (Serial.available() > 0) { | |
String command = Serial.readStringUntil('\n'); | |
command.trim(); // Remove any trailing newline or whitespace | |
processCommand(command); | |
} | |
if (blinkingEnabled) { | |
unsigned long currentTime = millis(); | |
if (currentTime - lastBlinkTime >= 100) { | |
blinkAll(); | |
lastBlinkTime = currentTime; | |
} | |
} | |
} | |
void processCommand(String command) { | |
if (command.startsWith("read_width")) { | |
Serial.println("ok : " + String(config.width)); | |
} else if (command.startsWith("read_height")) { | |
Serial.println("ok : " + String(config.height)); | |
} else if (command.startsWith("write_width")) { | |
int value = command.substring(12).toInt(); | |
if (value >= 0 && value <= MAX_COLUMNS) { | |
config.width = value; | |
Serial.println("ok : Width set to " + String(config.width)); | |
} else { | |
Serial.println("error"); | |
} | |
} else if (command.startsWith("write_height")) { | |
int value = command.substring(13).toInt(); | |
if (value >= 0 && value <= MAX_ROWS) { | |
config.height = value; | |
Serial.println("ok : Height set to " + String(config.height)); | |
} else { | |
Serial.println("error"); | |
} | |
} else if (command.startsWith("write_address_list")) { | |
String list = command.substring(19); | |
config.addressCount = 0; | |
int index = 0; | |
bool valid = true; | |
while (index < list.length()) { | |
int spaceIndex = list.indexOf(' ', index); | |
if (spaceIndex == -1) { | |
spaceIndex = list.length(); | |
} | |
int value = list.substring(index, spaceIndex).toInt(); | |
if (config.addressCount < MAX_ADDRESSES && value >= 0) { | |
config.addressList[config.addressCount++] = value; | |
} else { | |
valid = false; | |
break; | |
} | |
index = spaceIndex + 1; | |
} | |
if (valid) { | |
Serial.println("ok : Address list updated"); | |
} else { | |
Serial.println("error"); | |
} | |
} else if (command.startsWith("read_address_list")) { | |
String response = "ok : "; | |
for (int i = 0; i < config.addressCount; i++) { | |
response += String(config.addressList[i]); | |
if (i < config.addressCount - 1) { | |
response += " "; | |
} | |
} | |
Serial.println(response); | |
} else if (command.startsWith("scan_addresses")) { | |
scanI2CAddresses(); | |
Serial.print("ok : "); | |
for (int i = 0; i < scannedAddressCount; i++) { | |
Serial.print(String(scannedAddresses[i], DEC)); | |
if (i < scannedAddressCount - 1) { | |
Serial.print(" "); | |
} | |
} | |
Serial.println(); | |
} else if (command.startsWith("test_led_enable")) { | |
int address = command.substring(16).toInt(); | |
if (testLEDEnable(address)) { | |
Serial.println("ok : LED enabled at address " + String(address)); | |
} else { | |
Serial.println("error"); | |
} | |
} else if (command.startsWith("test_led_disable")) { | |
int address = command.substring(17).toInt(); | |
if (testLEDDisable(address)) { | |
Serial.println("ok : LED disabled at address " + String(address)); | |
} else { | |
Serial.println("error"); | |
} | |
} else if (command.startsWith("store_config")) { | |
EEPROM.put(512, config); | |
Serial.println("ok : Configuration stored to EEPROM"); | |
} else if (command.startsWith("set_power")) { | |
int firstSpace = command.indexOf(' ', 10); | |
int secondSpace = command.indexOf(' ', firstSpace + 1); | |
int row = command.substring(10, firstSpace).toInt(); | |
int col = command.substring(firstSpace + 1, secondSpace).toInt(); | |
int power = command.substring(secondSpace + 1).toInt(); | |
if (row >= 0 && row < POWER_ARRAY_ROWS && col >= 0 && col < POWER_ARRAY_COLUMNS && power >= 0 && power <= 4096) { | |
setPower(row, col, power); | |
Serial.println("ok : Power set at (" + String(row) + "," + String(col) + ") to " + String(power)); | |
} else { | |
Serial.println("error"); | |
} | |
} else if (command.startsWith("get_power")) { | |
// int firstSpace = command.indexOf(' ', 10); | |
// int row = command.substring(10, firstSpace).toInt(); | |
// int col = command.substring(firstSpace + 1).toInt(); | |
// if (row >= 0 && row < POWER_ARRAY_ROWS && col >= 0 && col < POWER_ARRAY_COLUMNS) { | |
// Serial.println("ok : Power at (" + String(row) + "," + String(col) + ") is " + String(powerLevels[row][col])); | |
// } else { | |
// Serial.println("error"); | |
// } | |
Serial.println("error"); | |
} else if (command == "blinkall_start") { | |
enableBlinking(); | |
Serial.println("ok : Blinking started"); | |
} else if (command == "blinkall_stop") { | |
disableBlinking(); | |
Serial.println("ok : Blinking stopped"); | |
} else { | |
Serial.println("error"); | |
} | |
} | |
void scanI2CAddresses() { | |
scannedAddressCount = 0; | |
for (int address = 1; address <= 127; address++) { | |
Wire.beginTransmission(address); | |
if (Wire.endTransmission() == 0 && address != 112) { | |
scannedAddresses[scannedAddressCount++] = address; | |
Wire.beginTransmission(address); | |
Wire.write(0x00); | |
Wire.write(B00110001); // MODE 1 | |
Wire.endTransmission(); | |
Wire.beginTransmission(address); | |
Wire.write(0xFE); | |
Wire.write(8); // Timer Prescaler (3-255) | |
Wire.endTransmission(); | |
Wire.beginTransmission(address); | |
Wire.write(0x00); | |
Wire.write(B10100001); // MODE 1 | |
Wire.endTransmission(); | |
Wire.beginTransmission(address); | |
Wire.write(0x01); | |
Wire.write(B00000100); // MODE 2 | |
Wire.endTransmission(); | |
} | |
} | |
} | |
bool testLEDEnable(int address) { | |
Wire.beginTransmission(address); | |
Wire.write(0x2A); | |
Wire.write(0x00); | |
Wire.write(0x00); | |
Wire.write(0xFF); // On LS2B | |
Wire.write(0x0F); // On MSB | |
Wire.endTransmission(); | |
return true; | |
} | |
bool testLEDDisable(int address) { | |
Wire.beginTransmission(address); | |
Wire.write(0x2A); | |
Wire.write(0x00); | |
Wire.write(0x00); | |
Wire.write(0x00); // On LS2B | |
Wire.write(0x00); // On MSB | |
Wire.endTransmission(); | |
return true; | |
} | |
void setPower(int row, int col, uint16_t power) { | |
// powerLevels[row][col] = power; | |
uint8_t tileRow = row/3; | |
uint8_t tileCol = col/3; | |
uint8_t rowOnTile = row - tileRow*3; | |
uint8_t colOnTile = col - tileCol*3; | |
uint8_t tileAddr = config.addressList[tileRow*config.width+tileCol]; | |
uint8_t coilAddr = 0x06 + 4 * (rowOnTile * 3 + colOnTile); | |
// Serial.println(tileRow); | |
// Serial.println(tileCol); | |
// Serial.println(rowOnTile); | |
// Serial.println(colOnTile); | |
// Serial.println(tileAddr); | |
// Serial.println(coilAddr); | |
// Serial.println(power & 0x00FF); | |
// Serial.println((power & 0x0F00) >> 8); | |
Wire.beginTransmission(tileAddr); | |
Wire.write(coilAddr); | |
Wire.write(0x00); | |
Wire.write(0x00); | |
Wire.write(power & 0x00FF); // On LS2B | |
Wire.write((power & 0x0F00) >> 8); // On MSB | |
Wire.endTransmission(); | |
} | |
void blinkAll() { | |
blinkState = !blinkState; | |
// Serial.println("Blinking: " + String(blinkState ? "ON" : "OFF")); | |
for (int i = 0; i < scannedAddressCount; i++) { | |
Wire.beginTransmission(scannedAddresses[i]); | |
Wire.write(0xFA); // ALL_LED_ON_L register | |
Wire.write(0x00); | |
Wire.write(0x00); | |
if (blinkState) { | |
Wire.write(0xFF); | |
Wire.write(0x0F); // Set all LEDs fully on | |
} else { | |
Wire.write(0x00); | |
Wire.write(0x00); // Set all LEDs fully off | |
} | |
Wire.endTransmission(); | |
} | |
} | |
void enableBlinking() { | |
blinkingEnabled = true; | |
lastBlinkTime = millis(); | |
} | |
void disableBlinking() { | |
blinkingEnabled = false; | |
// Turn off all LEDs when stopping the blink | |
for (int i = 0; i < scannedAddressCount; i++) { | |
Wire.beginTransmission(scannedAddresses[i]); | |
Wire.write(0xFA); // ALL_LED_ON_L register | |
Wire.write(0x00); | |
Wire.write(0x00); | |
Wire.write(0x00); | |
Wire.write(0x00); // Set all LEDs fully off | |
Wire.endTransmission(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment