Skip to content

Commit

Permalink
Refactored pin allocations and mapping to different boards
Browse files Browse the repository at this point in the history
index.js:
- add pinType const and var and func
- createHTML: pin type: preload select options with pins and send to changeHTML
- receiveHTML: add sysInfo
- previewBoard: use sysInfo, support s2 and s3, color from pinType, simplified buffer

AppModDemo: add blinking pin variables and blink in loop (wip)

SysModModel:
- setValue: store oldValue in model

SysModPins:
- add getPinType
- cleanup test code, only keep pin19 for relais
- bugfix showing pindetails
- simplified buffer (only one uint8_t per pin)

SysModWeb:
- wsEvent: connected: send sysInfo
  • Loading branch information
ewoudwijma committed Apr 11, 2024
1 parent 96c442f commit 84c1771
Show file tree
Hide file tree
Showing 8 changed files with 1,531 additions and 1,382 deletions.
98 changes: 77 additions & 21 deletions data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,24 @@ let jsonValues = {};
let uiFunCommands = [];
let model = []; //model.json (as send by the server), used by FindVar
let savedView = null;

//C++ equivalents
const UINT8_MAX = 255;
const UINT16_MAX = 256*256-1;

const pinTypeIO = 0;
const pinTypeReadOnly = 1;
const pinTypeReserved = 2;
const pinTypeSpi = 3;
const pinTypeInvalid = UINT8_MAX;
let sysInfo = {};
function getPinType(pinNr) {
if (sysInfo.pinTypes[pinNr] == pinTypeIO) return "🟢";
else if (sysInfo.pinTypes[pinNr] == pinTypeReadOnly) return "🟠";
else if (sysInfo.pinTypes[pinNr] == pinTypeReserved) return "🟣";
else return "🔴";
}

function gId(c) {return d.getElementById(c);}
function cE(e) { return d.createElement(e); }

Expand Down Expand Up @@ -295,6 +310,13 @@ function createHTML(json, parentNode = null, rowNr = UINT8_MAX) {
else {
varNode = cE("select");
varNode.addEventListener('change', (event) => {console.log("select change", event);sendValue(event.target);});
}

if (variable.type == "pin") {
variable.options = [];
for (let index = 0; index < 40; index++) {
variable.options.push(index + " " + getPinType(index));
}
}

} else if (variable.type == "canvas") {
Expand Down Expand Up @@ -487,6 +509,9 @@ function createHTML(json, parentNode = null, rowNr = UINT8_MAX) {
if (variable.value)
changeHTML(variable, {"value":variable.value, "chk":"gen1"}, rowNr); //set only the value

if (variable.options) // eg for pin type
changeHTML(variable, {"options":variable.options, "chk":"gen1"}, rowNr); //set only the options

//call ui Functionality, if defined (to set label, comment, select etc)
if (variable.fun >= 0) { //>=0 as element in var
uiFunCommands.push(variable.id);
Expand Down Expand Up @@ -564,9 +589,6 @@ function receiveData(json) {
if (key == "uiFun") {
console.log("receiveData no action", key, value); //should not happen anymore
}
else if (key == "aiButton") {
console.log("receiveData", key, value);
}
else if (key == "view") {
console.log("receiveData", key, value);
changeHTMLView(value);
Expand Down Expand Up @@ -653,6 +675,9 @@ function receiveData(json) {
colNr++;
}

} else if (key == "sysInfo") { //update the row of a table
console.log("receiveData", key, value);
sysInfo = value;
} else { //{variable:{label:value:options:comment:}}

let variable = findVar(key);
Expand Down Expand Up @@ -1492,13 +1517,13 @@ function saveModel(node) {

function setView(node) {
var command = {};
command["view"] = node.id;
command.view = node.id;
requestJson(command);
}

function setTheme(node) {
var command = {};
command["theme"] = node.value;
command.theme = node.value;
requestJson(command);
}

Expand All @@ -1508,10 +1533,15 @@ function getTheme() {
}

function previewBoard(canvasNode, buffer) {
let boardColor;
if (sysInfo.board == "esp32s2") boardColor = "purple";
else if (sysInfo.board == "esp32s3") boardColor = "blue";
else boardColor = "green";

let ctx = canvasNode.getContext('2d');
//assuming 20 pins
let mW = 2; // matrix width
let mH = 20; // matrix height
let mW = sysInfo.nrOfPins<=40?2:4; // nr of pin columns
let mH = sysInfo.nrOfPins / mW; // pins per column
let pPL = Math.min(canvasNode.width / mW, canvasNode.height / (mH+2)); // pixels per LED (width of circle)
let bW = pPL*10;
let bH = mH * pPL;
Expand All @@ -1525,50 +1555,76 @@ function previewBoard(canvasNode, buffer) {
pos.x = lOf; pos.y = pPL;
//board
ctx.beginPath();
ctx.fillStyle = "green";
ctx.fillStyle = boardColor;
ctx.fillRect(pos.x, pos.y, bW, bH);

//wifi
ctx.fillStyle = "darkBlue";
ctx.fillRect(pos.x + 1.5*pPL, 0, pPL * 7, pPL * 3);
if (mW == 2)
ctx.fillRect(pos.x + 1.5*pPL, 0, pPL * 7, pPL * 3);
else
ctx.fillRect(pos.x + 2.5*pPL, 0, pPL * 5, pPL * 3);

//cpu
ctx.fillStyle = "gray";
ctx.fillRect(pos.x + 1.5*pPL, pos.y + 3*pPL, pPL * 7, pPL * 7);
if (mW == 2)
ctx.fillRect(pos.x + 1.5*pPL, pos.y + 3*pPL, pPL * 7, pPL * 7);
else
ctx.fillRect(pos.x + 2.5*pPL, pos.y + 3*pPL, pPL * 5, pPL * 5);


//esp32 text
ctx.beginPath();
ctx.font = pPL *1.5 + "px serif";
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText("ESP32", pos.x + 5*pPL, pos.y + 6 * pPL);
ctx.fillText(sysInfo.board, pos.x + 5*pPL, pos.y + 6 * pPL);

//chip
ctx.fillStyle = "black";
ctx.fillRect(pos.x + 6 * pPL, pos.y + 12*pPL, pPL * 2, pPL * 5);
if (mW == 2) { //no space if 4 columns
ctx.fillStyle = "black";
ctx.fillRect(pos.x + 6 * pPL, pos.y + 12*pPL, pPL * 2, pPL * 5);
}

//usb
ctx.fillStyle = "grey";
ctx.fillRect(pos.x + 3.5 * pPL, bH - pPL, pPL * 3, pPL * 3);

let index = 0;
for (let x = 0.5; x < mW; x++) {
for (let y = 0.5; y < mH; y++) {
ctx.fillStyle = `rgb(${buffer[index*3 + 5]},${buffer[index*3 + 6]},${buffer[index*3 + 7]})`;
pos.y = y*pPL + pPL;
for (let x = 0; x < mW; x++) {
for (let y = 0; y < mH; y++) {
let pinType = sysInfo.pinTypes[index];
let pinColor = [];
switch (pinType) {
case pinTypeIO:
pinColor = [78,173,50]; // green
break;
case pinTypeReadOnly:
pinColor = [218,139,49];//"orange";
break;
case pinTypeReserved:
pinColor = [156,50,246];//"purple";
break;
default:
pinColor = [192,48,38];//"red";
}
ctx.fillStyle = `rgba(${pinColor[0]},${pinColor[1]},${pinColor[2]},${buffer[index + 5]})`;
pos.y = (y+0.5)*pPL + pPL;
ctx.beginPath();
if (x == 0.5)
pos.x = x*pPL + lOf;
if ((x == 0 && mW == 2) || (x <= 1 && mW == 4))
pos.x = (x+0.5)*pPL + lOf;
else if (mW == 2)
pos.x = (x+0.5)*pPL + lOf + 8 * pPL;
else
pos.x = lOf + bW - pPL / 2;
pos.x = (x+0.5)*pPL + lOf + 6 * pPL;
ctx.arc(pos.x, pos.y, pPL * 0.4, 0, 2 * Math.PI);
ctx.fill();

ctx.beginPath();
ctx.font = pPL*0.5 + "px serif";
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText(index+1, pos.x, pos.y + pPL / 4);
ctx.fillText(index, pos.x, pos.y + pPL / 4);

index++;
}
Expand Down
41 changes: 39 additions & 2 deletions src/App/AppModDemo.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class AppModDemo: public SysModule {

public:

unsigned long lastMillis;
uint16_t blinkPin = UINT16_MAX;
uint8_t frequency;

AppModDemo() :SysModule("AppMod Demo") {
};

Expand All @@ -22,12 +26,45 @@ class AppModDemo: public SysModule {

parentVar = ui->initAppMod(parentVar, name, 1100);

ui->initText(parentVar, "textField");
ui->initText(parentVar, "textField", "text");

ui->initPin(parentVar, "blinkPin", blinkPin, false, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_UIFun: {
ui->setLabel(var, "Blink Pin");
ui->setComment(var, "🚧 tbd: reserved and allocated pins");
return true; }
case f_ChangeFun: {
//deallocate old value...
pins->deallocatePin(var["oldValue"], "Blink");
if (!var["value"].isNull()) {
blinkPin = var["value"];
pins->allocatePin(blinkPin, "Blink", "On board led");
pinMode(blinkPin, OUTPUT); //tbd: part of allocatePin?
}
return true; }
default: return false;
}});

ui->initCheckBox(parentVar, "on");

ui->initSlider(parentVar, "frequency", frequency, 0, UINT8_MAX, false, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ChangeFun:
frequency = var["value"];
return true;
default: return false;
}});

}

void loop() {
void loop1s() {
// SysModule::loop();
if (blinkPin != UINT16_MAX && millis() - lastMillis >= frequency) {
lastMillis = millis();
// USER_PRINTF(" %d: %d", blinkPin, digitalRead(blinkPin));
int value = digitalRead(blinkPin);
digitalWrite(blinkPin, value == LOW?HIGH:LOW);
}

}

void onOffChanged() {
Expand Down
10 changes: 6 additions & 4 deletions src/Sys/SysModModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,16 +212,18 @@ class SysModModel:public SysModule {

if (rowNr == UINT8_MAX) { //normal situation
if (var["value"].isNull() || var["value"].as<Type>() != value) { //const char * will be JsonString so comparison works
JsonString oldValue = JsonString(var["value"], JsonString::Copied);
if (!var["value"].isNull() && !varRO(var)) var["oldValue"] = var["value"];
var["value"] = value;
//trick to remove null values
if (var["value"].isNull() || var["value"].as<unsigned16>() == UINT16_MAX) {
var.remove("value");
if (oldValue.size()>0)
USER_PRINTF("dev setValue value removed %s %s\n", varID(var), oldValue.c_str()); //old value
USER_PRINTF("dev setValue value removed %s %s\n", varID(var), var["oldValue"].as<String>().c_str());
}
else {
USER_PRINTF("setValue changed %s %s -> %s\n", varID(var), oldValue.c_str(), var["value"].as<String>().c_str()); //old value
if (varRO(var))
USER_PRINTF("setValue changed %s %s\n", varID(var), var["value"].as<String>().c_str());
else
USER_PRINTF("setValue changed %s %s -> %s\n", varID(var), var["oldValue"].as<String>().c_str(), var["value"].as<String>().c_str());
web->addResponse(var["id"], "value", var["value"]);
changed = true;
}
Expand Down
69 changes: 27 additions & 42 deletions src/Sys/SysModPins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@
#include "SysModWeb.h"

SysModPins::SysModPins() :SysModule("Pins") {
#if CONFIG_IDF_TARGET_ESP32
// softhack007: configuring these pins on S3/C3/S2 may cause major problems (crashes included)
// pinMode(2, OUTPUT); // softhack007 default LED pin on some boards, so don't play around with gpio2
pinMode(4, OUTPUT);
pinMode(19, OUTPUT);
pinMode(33, OUTPUT);
#endif

//start with no pins allocated
for (int i=0; i<NUM_DIGITAL_PINS; i++) {
deallocatePin(i, pinObjects[i].owner);
Expand Down Expand Up @@ -65,18 +57,17 @@ void SysModPins::setup() {

ui->initText(tableVar, "pinDetails", nullptr, 256, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ValueFun:
for (forUnsigned8 rowNr = 0; rowNr < getNrOfAllocatedPins(); rowNr++)
for (forUnsigned8 rowNr = 0; rowNr < getNrOfAllocatedPins(); rowNr++) {
USER_PRINTF("pinDetails[%d] d1:%s d2:%s\n", rowNr, getNthAllocatedPinObject(rowNr).details, pinObjects[0].details);
mdl->setValue(var, JsonString(getNthAllocatedPinObject(rowNr).details, JsonString::Copied), rowNr);
}
return true;
case f_UIFun:
ui->setLabel(var, "Details");
return true;
default: return false;
}});

#ifdef STARMOD_DEVMODE

ui->initCanvas(parentVar, "board", UINT16_MAX, true, [](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_UIFun:
ui->setLabel(var, "Pin viewer");
Expand All @@ -91,31 +82,45 @@ void SysModPins::setup() {
buffer = wsBuf->get();

// send pins to clients
for (size_t i = 0; i < 40; i++) //assuming 40 pins
for (size_t pinNr = 0; pinNr < NUM_DIGITAL_PINS; pinNr++)
{
buffer[i*3+5] = random(256);// (digitalRead(i)+1) * 50;
buffer[i*3+5+1] = random(256);
buffer[i*3+5+2] = random(256);
buffer[pinNr+5] = random(8);// digitalRead(pinNr) * 255; // is only 0 or 1
}
// USER_PRINTF("\n");
//new values
buffer[0] = 0; //userFun id

}, 40 * 3 + 5, true);
}, NUM_DIGITAL_PINS + 5, true);
return true;

default: return false;
}});

#endif //STARMOD_DEVMODE
// ui->initCheckBox(parentVar, "pin2", true, UINT8_MAX, false, nullptr, updateGPIO);
// ui->initCheckBox(parentVar, "pin4");
#if CONFIG_IDF_TARGET_ESP32
ui->initCheckBox(parentVar, "pin19", true, false, updateGPIO);
// softhack007: configuring these pins on S3/C3/S2 may cause major problems (crashes included)
// pinMode(2, OUTPUT); // softhack007 default LED pin on some boards, so don't play around with gpio2
allocatePin(19, "Pins", "Relais");
pinMode(19, OUTPUT); //tbd: part of allocatePin?

ui->initCheckBox(parentVar, "pin19", true, false, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_UIFun:
ui->setComment(var, "🚧 used for relais on Serg shields");
return true;
case f_ChangeFun: {
bool pinValue = var["value"];

USER_PRINTF("updateGPIO %s:=%d\n", mdl->varID(var), pinValue);

// softhack007: writing these pins on S3/C3/S2 may cause major problems (crashes included)
digitalWrite(19, pinValue?HIGH:LOW);
return true; }
default: return false;
}});
#endif
// ui->initCheckBox(parentVar, "pin33", true);
}

void SysModPins::loop1s() {
void SysModPins::loop() {

if (pinsChanged) {
pinsChanged = false;

Expand All @@ -124,26 +129,6 @@ void SysModPins::loop1s() {
}
}

bool SysModPins::updateGPIO(JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case f_ChangeFun:
if (var["value"].is<bool>()) {
bool pinValue = var["value"];
JsonString id = var["id"];

USER_PRINTF("updateGPIO %s:=%d\n", id.c_str(), pinValue);

#if CONFIG_IDF_TARGET_ESP32
// softhack007: writing these pins on S3/C3/S2 may cause major problems (crashes included)
// if (id == "pin2") digitalWrite(2, pinValue?HIGH:LOW); // softhack007 default LED pin on some boards, so don't play around with gpio2
if (id == "pin4") digitalWrite(4, pinValue?HIGH:LOW);
if (id == "pin19") digitalWrite(19, pinValue?HIGH:LOW);
if (id == "pin33") digitalWrite(33, pinValue?HIGH:LOW);
#endif
}
return true;
default: return false;
}};

void SysModPins::allocatePin(unsigned8 pinNr, const char * owner, const char * details) {
USER_PRINTF("allocatePin %d %s %s\n", pinNr, owner, details);
if ((pinNr < NUM_DIGITAL_PINS) && (digitalPinIsValid(pinNr))) {
Expand Down
Loading

0 comments on commit 84c1771

Please sign in to comment.