esp8266 ADC, EEPROM driver, max7219 simulator

* test

* Update workflow.yaml

* t

* makes

* Update drv_simpleEEPROM.c

* Update drv_simpleEEPROM.c

* ber

* Update workflow.yaml

* tt

* ber

* charts

* owm

* tt

* rem charts

* smaller

* test

* test

* fixes

* test

* charts

* comments

* test

* tt

* test

* add file to proj

* try to add pin 13 as ADC (testing in progress)

* test

* test

* MAX7219 simulator HACK

* final fixes

* Update drv_max72xx_internal.c

* restore

* fx
This commit is contained in:
openshwprojects
2025-11-23 14:01:04 +01:00
committed by GitHub
parent 9581b34b95
commit e9e20ed445
30 changed files with 543 additions and 16 deletions

View File

@ -544,3 +544,4 @@ jobs:
echo ${{ steps.semantic.outputs.new_release_major_version }}
echo ${{ steps.semantic.outputs.new_release_minor_version }}
echo ${{ steps.semantic.outputs.new_release_patch_version }}

View File

@ -202,6 +202,7 @@
<ClCompile Include="src\devicegroups\deviceGroups_write.c" />
<ClCompile Include="src\driver\drv_adcButton.c" />
<ClCompile Include="src\driver\drv_adcSmoother.c" />
<ClCompile Include="src\driver\drv_aht2x.c" />
<ClCompile Include="src\driver\drv_battery.c" />
<ClCompile Include="src\driver\drv_bkPartitions.c" />
<ClCompile Include="src\driver\drv_bl0937.c" />
@ -257,6 +258,7 @@
<ClCompile Include="src\driver\drv_sgp.c" />
<ClCompile Include="src\driver\drv_shiftRegister.c" />
<ClCompile Include="src\driver\drv_sht3x.c" />
<ClCompile Include="src\driver\drv_simpleEEPROM.c" />
<ClCompile Include="src\driver\drv_sm15155e.c" />
<ClCompile Include="src\driver\drv_sm16703P.c" />
<ClCompile Include="src\driver\drv_sm2135.c" />
@ -848,6 +850,7 @@
<ClCompile Include="src\sim\Controller_Bulb.cpp" />
<ClCompile Include="src\sim\Controller_Button.cpp" />
<ClCompile Include="src\sim\Controller_DHT11.cpp" />
<ClCompile Include="src\sim\Controller_MAX7219.cpp" />
<ClCompile Include="src\sim\Controller_Pot.cpp" />
<ClCompile Include="src\sim\Controller_SimulatorLink.cpp" />
<ClCompile Include="src\sim\Controller_Switch.cpp" />
@ -855,6 +858,7 @@
<ClCompile Include="src\sim\CursorManager.cpp" />
<ClCompile Include="src\sim\Junction.cpp" />
<ClCompile Include="src\sim\Line.cpp" />
<ClCompile Include="src\sim\Point.cpp" />
<ClCompile Include="src\sim\PrefabManager.cpp" />
<ClCompile Include="src\sim\RecentList.cpp" />
<ClCompile Include="src\sim\Rect.cpp" />

View File

@ -418,6 +418,10 @@
<ClCompile Include="src\selftest\selftest_max72xx.c" />
<ClCompile Include="src\driver\drv_multiPinI2CScanner.c" />
<ClCompile Include="src\selftest\selftest_openWeatherMap.c" />
<ClCompile Include="src\driver\drv_simpleEEPROM.c" />
<ClCompile Include="src\driver\drv_aht2x.c" />
<ClCompile Include="src\sim\Controller_MAX7219.cpp" />
<ClCompile Include="src\sim\Point.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\base64\base64.h" />

View File

@ -117,6 +117,7 @@ set(OBKM_SRC
${OBK_SRCS}driver/drv_soft_spi.c
${OBK_SRCS}driver/drv_sm15155e.c
${OBK_SRCS}driver/drv_sm16703P.c
${OBK_SRCS}driver/drv_simpleEEPROM.c
${OBK_SRCS}driver/drv_leds_shared.c
${OBK_SRCS}driver/drv_spi.c
${OBK_SRCS}driver/drv_spiLED.c

View File

@ -133,6 +133,7 @@ OBKM_SRC += $(OBK_SRCS)driver/drv_shiftRegister.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sht3x.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm15155e.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm16703P.c
OBKM_SRC += $(OBK_SRCS)driver/drv_simpleEEPROM.c
OBKM_SRC += $(OBK_SRCS)driver/drv_leds_shared.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm2135.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm2235.c

View File

@ -948,7 +948,12 @@ float CMD_EvaluateExpression(const char *s, const char *stop) {
c = a / b;
break;
case OP_MODULO:
c = ((int)a) % ((int)b);
if (b == 0) {
c = 0;
}
else {
c = ((int)a) % ((int)b);
}
break;
default:
c = 0;

View File

@ -183,6 +183,7 @@ commandResult_t AHT2X_Reinit(const void* context, const char* cmd, const char* a
return CMD_RES_OK;
}
// startDriver AHT2X 4 5 3 4
void AHT2X_Init()
{
g_softI2C.pin_clk = Tokenizer_GetPin(1, 9);

View File

@ -174,6 +174,10 @@ void DRV_MAX72XX_Shutdown();
int MAX72XXSingle_CountPixels(bool bOn);
int MAX72XXSingle_GetScrollCount();
void EEPROM_Init();
void EEPROM_OnEverySecond();
void EEPROM_AppendInformationToHTTPIndexPage(http_request_t*r, int pre);
void apply_smart_light();
void WEMO_Init();

View File

@ -130,7 +130,6 @@ static driver_t g_drivers[] = {
//drvdetail:"requires":""}
{ "TCL", TCL_Init, TCL_UART_RunEverySecond, TCL_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, TCL_DoDiscovery, false },
#endif
#if ENABLE_DRIVER_OPENWEATHERMAP
//drvdetail:{"name":"OpenWeatherMap",
//drvdetail:"title":"TODO",
@ -201,6 +200,13 @@ static driver_t g_drivers[] = {
//drvdetail:"requires":""}
{ "Test", Test_Init, NULL, Test_AppendInformationToHTTPIndexPage, Test_RunQuickTick, NULL, NULL, NULL, false },
#endif
#if ENABLE_SIMPLEEEPROM
//drvdetail:{"name":"SimpleEEPROM",
//drvdetail:"title":"TODO",
//drvdetail:"descr":"SimpleEEPROM",
//drvdetail:"requires":""}
{ "SimpleEEPROM", EEPROM_Init, NULL, EEPROM_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, NULL, false },
#endif
#if ENABLE_MULTIPINI2CSCANNER
//drvdetail:{"name":"MultiPinI2CScanner",
//drvdetail:"title":"TODO",

View File

@ -104,9 +104,10 @@ void Run_NoAnimation() {
else {
Clock_SendTemperature();
}
CMD_ExecuteCommandArgs("MAX72XX_Show", "", 0);
CMD_ExecuteCommandArgs("MAX72XX_refresh", "", 0);
cycle %= 40;
}
static int g_del = 0;
void Run_Animated() {
cycle++;
if (cycle < 4) {
@ -125,7 +126,7 @@ void Run_Animated() {
}
int scroll = MAX72XXSingle_GetScrollCount();
//scroll_cycle = 0;
if (scroll == 0) {
if (scroll == 0 && g_del == 0) {
time[0] = 0;
p = time;
p = my_strcat(p, " ");
@ -145,9 +146,15 @@ void Run_Animated() {
CMD_ExecuteCommandArgs("MAX72XX_Clear", NULL, 0);
CMD_ExecuteCommandArgs("MAX72XX_Print", time, 0);
CMD_ExecuteCommandArgs("MAX72XX_refresh", "", 0);
g_del = 10;
}
if (g_del > 0) {
g_del--;
return;
}
CMD_ExecuteCommandArgs("MAX72XX_Scroll", "-1", 0);
CMD_ExecuteCommandArgs("MAX72XX_Show", "", 0);
CMD_ExecuteCommandArgs("MAX72XX_refresh", "", 0);
}
bool g_animated = false;
void DRV_MAX72XX_Clock_OnEverySecond() {

View File

@ -60,6 +60,7 @@ void PORT_shiftOut(int dataPin, int clockPin, int bitOrder, int val, int totalBy
}
}
void SIM_SetMAX7219Pixels(byte *data, int size);
void MAX72XX_spiTransfer(max72XX_t *led, int adddr, unsigned char opcode, byte datta) {
if (led == 0) {
return;
@ -79,6 +80,9 @@ void MAX72XX_spiTransfer(max72XX_t *led, int adddr, unsigned char opcode, byte d
MAX72XX_DELAY
for (i = maxbytes; i > 0; i--)
PORT_shiftOut(led->port_mosi, led->port_clk, MSBFIRST, led->spidata[i - 1], 1);
#if WINDOWS && !LINUX
SIM_SetMAX7219Pixels(led->led_status, led->maxDevices);
#endif
MAX72XX_DELAY
HAL_PIN_SetOutputValue(led->port_cs, HIGH);
}
@ -198,6 +202,26 @@ byte Byte_ReverseBits(byte num)
}
return reversed;
}
void MAX72XX_setPixel(max72XX_t* led, int x, int y, int b)
{
if (led == 0) return;
if (x < 0 || y < 0) return;
int totalWidth = led->maxDevices * 8;
if (x >= totalWidth || y > 7) return;
int addr = x / 8;
int column = x % 8;
column = 7 - column;
int offset = addr * 8;
byte mask = (byte)(0x80 >> column);
if (b)
led->led_status[offset + y] |= mask;
else
led->led_status[offset + y] &= (byte)(~mask);
MAX72XX_spiTransfer(led, addr, y + 1, led->led_status[offset + y]);
}
void MAX72XX_displayArray(max72XX_t* led, byte *p, int devs, int ofs)
{
if (led == 0) {
@ -343,7 +367,7 @@ void MAX72XX_init(max72XX_t *led) {
int i;
HAL_PIN_SetOutputValue(led->port_cs, HIGH);
for (i = 0; i < 64; i++)
for (i = 0; i < led->maxDevices * 8; i++)
led->led_status[i] = 0x00;
for (i = 0; i < led->maxDevices; i++) {
MAX72XX_spiTransfer(led, i, OP_DISPLAYTEST, 0);

View File

@ -20,6 +20,7 @@ void MAX72XX_clearDisplayFullNoSend(max72XX_t *led);
void MAX72XX_rotate90CW(max72XX_t *led);
void MAX72XX_setIntensity(max72XX_t *led,int addr, int intensity) ;
void MAX72XX_displayArray(max72XX_t* led, byte *p, int devs, int ofs) ;
void MAX72XX_setPixel(max72XX_t* led, int x, int y, int b);
void MAX72XX_shift(max72XX_t *led,int d);
void MAX72XX_setLed(max72XX_t *led,int addr, int row, int column, bool state) ;
void MAX72XX_init(max72XX_t *led);

View File

@ -412,6 +412,23 @@ static commandResult_t DRV_MAX72XX_Clear(const void *context, const char *cmd, c
}
return CMD_RES_OK;
}
static commandResult_t DRV_MAX72XX_SetPixel(const void *context, const char *cmd, const char *args, int flags) {
if (g_max == 0)
return CMD_RES_ERROR;
Tokenizer_TokenizeString(args, 0);
int x, y, b;
x = Tokenizer_GetArgInteger(0);
y = Tokenizer_GetArgInteger(1);
b = Tokenizer_GetArgInteger(2);
MAX72XX_setPixel(g_max, x, y, b);
return CMD_RES_OK;
}
static commandResult_t DRV_MAX72XX_Print(const void *context, const char *cmd, const char *args, int flags) {
int ofs;
//const char *s;
@ -484,6 +501,7 @@ void DRV_MAX72XX_Init() {
//cmddetail:"fn":"DRV_DRV_MAX72XX_Clear","file":"driver/drv_max72xx_single.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MAX72XX_Clear", DRV_MAX72XX_Clear, NULL);
CMD_RegisterCommand("MAX72XX_SetPixel", DRV_MAX72XX_SetPixel, NULL);
}

View File

@ -212,7 +212,7 @@ void startWeatherThread() {
err = rtos_create_thread(&g_weather_thread, BEKEN_APPLICATION_PRIORITY,
"OWM",
(beken_thread_function_t)weather_thread,
8192,
4096,
(beken_thread_arg_t)0);
if (err != kNoErr)
{

View File

@ -0,0 +1,177 @@
/*
startDriver SimpleEEPROM 5 4
EEPROM_WriteHex 0 AABBCCDDEEFFBAADF00DAABB
EEPROM_Read 0 32
*/
#include "../new_common.h"
#include "../new_pins.h"
#include "../new_cfg.h"
#include "../cmnds/cmd_public.h"
#include "../mqtt/new_mqtt.h"
#include "../logging/logging.h"
#include "drv_local.h"
#include "drv_uart.h"
#include "../httpserver/new_http.h"
#include "../hal/hal_pins.h"
#define EEPROM_ADDR (0x50<<1)
#define EEPROM_PAGE 16
#define EEPROM_ADDR_BITS 2
static softI2C_t g_eepI2C;
static int g_eepBusy = 0;
static int EEP_WritePage(uint16_t addr, const uint8_t*data, int len) {
if (len <= 0)return 0;
Soft_I2C_Start(&g_eepI2C, EEPROM_ADDR);
if (EEPROM_ADDR_BITS == 2) {
Soft_I2C_WriteByte(&g_eepI2C, (addr >> 8) & 0xFF);
}
Soft_I2C_WriteByte(&g_eepI2C, addr & 0xFF);
for (int i = 0; i < len; i++)Soft_I2C_WriteByte(&g_eepI2C, data[i]);
Soft_I2C_Stop(&g_eepI2C);
rtos_delay_milliseconds(5);
return len;
}
static int EEPROM_Write(uint16_t addr, const uint8_t*data, int len) {
int w = 0;
while (len > 0) {
int p = EEPROM_PAGE - (addr%EEPROM_PAGE);
if (p > len)p = len;
int r = EEP_WritePage(addr, data, p);
if (r <= 0)break;
addr += r;
data += r;
len -= r;
w += r;
}
return w;
}
static int EEPROM_Read(uint16_t addr, uint8_t*data, int len) {
Soft_I2C_Start(&g_eepI2C, EEPROM_ADDR);
if (EEPROM_ADDR_BITS == 2) {
Soft_I2C_WriteByte(&g_eepI2C, (addr >> 8) & 0xFF);
}
Soft_I2C_WriteByte(&g_eepI2C, addr & 0xFF);
Soft_I2C_Stop(&g_eepI2C);
rtos_delay_milliseconds(1);
Soft_I2C_Start(&g_eepI2C, EEPROM_ADDR | 1);
Soft_I2C_ReadBytes(&g_eepI2C, data, len);
Soft_I2C_Stop(&g_eepI2C);
return len;
}
commandResult_t EEPROM_ReadCmd(const void*ctx, const char*cmd, const char*args, int f) {
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES);
if (Tokenizer_GetArgsCount() < 2) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
uint16_t addr = Tokenizer_GetArgInteger(0);
int len = Tokenizer_GetArgInteger(1);
uint8_t *buf = (uint8_t*)malloc(len);
if (!buf) return CMD_RES_ERROR;
EEPROM_Read(addr, buf, len);
int outLen = len * 3 + 1;
char *out = (char*)malloc(outLen);
if (!out) {
free(buf);
return CMD_RES_ERROR;
}
int p = 0;
for (int i = 0; i < len; i++) p += sprintf(out + p, "%02X ", buf[i]);
ADDLOG_INFO(LOG_FEATURE_CMD, "EEPROM_Read %s", out);
free(buf);
free(out);
return CMD_RES_OK;
}
commandResult_t EEPROM_WriteHexCmd(const void*ctx, const char*cmd, const char*args, int f) {
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES);
if (Tokenizer_GetArgsCount() < 2)
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
uint16_t addr = Tokenizer_GetArgInteger(0);
const char* hex = args+strlen(Tokenizer_GetArg(0));
while (*hex == ' ')
hex++;
const char* p = hex;
int count = 0;
while (p[0] && p[1]) {
unsigned int b;
if (sscanf(p, "%02x", &b) != 1) break;
count++;
p += 2;
while (*p == ' ')
p++;
}
if (count == 0)
return CMD_RES_BAD_ARGUMENT;
uint8_t* buf = (uint8_t*)malloc(count);
if (!buf)
return CMD_RES_ERROR;
p = hex;
int len = 0;
while (p[0] && p[1] && len < count) {
unsigned int b;
if (sscanf(p, "%02x", &b) != 1) break;
buf[len++] = b;
p += 2;
while (*p == ' ')
p++;
}
EEPROM_Write(addr, buf, len);
free(buf);
ADDLOG_INFO(LOG_FEATURE_CMD, "EEPROM_Write %d bytes", len);
return CMD_RES_OK;
}
commandResult_t EEPROM_DumpCmd(const void*ctx, const char*cmd, const char*args, int f) {
Tokenizer_TokenizeString(args, 0);
if (Tokenizer_GetArgsCount() < 2)return CMD_RES_NOT_ENOUGH_ARGUMENTS;
uint16_t addr = Tokenizer_GetArgInteger(0);
int len = Tokenizer_GetArgInteger(1);
if (len <= 0 || len > 512)return CMD_RES_BAD_ARGUMENT;
uint8_t buf[512];
EEPROM_Read(addr, buf, len);
for (int i = 0; i < len; i += 16) {
char out[128]; int p = 0;
p += sprintf(out + p, "%04X: ", addr + i);
for (int j = 0; j < 16 && i + j < len; j++)p += sprintf(out + p, "%02X ", buf[i + j]);
ADDLOG_INFO(LOG_FEATURE_CMD, "%s", out);
}
return CMD_RES_OK;
}
// startDriver SimpleEEPROM 5 4
// EEPROM_Write 0 AABBCC
// EEPROM_Read 0 16
void EEPROM_Init() {
g_eepI2C.pin_clk = Tokenizer_GetArgIntegerDefault(1, g_eepI2C.pin_clk);
g_eepI2C.pin_data = Tokenizer_GetArgIntegerDefault(2, g_eepI2C.pin_data);
Soft_I2C_PreInit(&g_eepI2C);
CMD_RegisterCommand("EEPROM_Read", EEPROM_ReadCmd, NULL);
CMD_RegisterCommand("EEPROM_WriteHex", EEPROM_WriteHexCmd, NULL);
CMD_RegisterCommand("EEPROM_Dump", EEPROM_DumpCmd, NULL);
}
void EEPROM_OnEverySecond() {
}
void EEPROM_AppendInformationToHTTPIndexPage(http_request_t*r, int pre) {
if (pre)return;
hprintf255(r, "<h2>EEPROM driver active</h2>");
}

View File

@ -106,5 +106,25 @@ int HAL_ADC_Read(int pinNumber)
}
return raw;
}
#elif PLATFORM_ESP8266
#endif // PLATFORM_ESPIDF
#include "../hal_adc.h"
#include "../../logging/logging.h"
extern unsigned short system_adc_read(void);
void HAL_ADC_Init(int pinNumber)
{
}
int HAL_ADC_Read(int pinNumber)
{
// system_adc_read() returns 10-bit value (01023)
int raw = system_adc_read();
return raw;
}
#endif

View File

@ -326,6 +326,8 @@ espPinMapping_t g_pins[] = {
{ "IO14", GPIO_NUM_14, false }, // 10
{ "IO15", GPIO_NUM_15, false }, // 11
{ "IO16", GPIO_NUM_16, false }, // 12
// ADC only I guess (no GPIO)
{ "ADC", GPIO_NUM_NC, false }, // 13
};

View File

@ -1137,7 +1137,8 @@ typedef enum channelType_e {
#define PLATFORM_GPIO_MAX 0
#endif
#elif PLATFORM_ESP8266
#define PLATFORM_GPIO_MAX 13
// 2025-11-22 - I added ADC, so bump from 13 to 14
#define PLATFORM_GPIO_MAX 14
#elif PLATFORM_TR6260
#define PLATFORM_GPIO_MAX 25
#elif PLATFORM_RTL87X0C

View File

@ -525,6 +525,14 @@
//#define ENABLE_MULTIPINI2CSCANNER 1
//#define ENABLE_DRIVER_MAX72XX 1
//#define ENABLE_SIMPLEEEPROM 1
//#define ENABLE_OBK_BERRY 1
//#define ENABLE_DRIVER_CHARTS 1
//#define ENABLE_DRIVER_OPENWEATHERMAP 1
//#define ENABLE_DRIVER_DHT 1
#define ENABLE_SEND_POSTANDGET 1
#define NO_CHIP_TEMPERATURE 1

View File

@ -11,8 +11,13 @@ void Test_MAX72XX() {
CMD_ExecuteCommand("MAX72XX_Print 1232132131212", 0);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("MAX72XX_Setup 10 8 9 4", 0);
CMD_ExecuteCommand("MAX72XX_Print 1232132131212", 0);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("MAX72XX_Setup 10 8 9 16", 0);
CMD_ExecuteCommand("MAX72XX_Clear", 0);
@ -101,6 +106,21 @@ void Test_MAX72XX() {
}
}
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("MAX72XX_Setup 10 8 9 16", 0);
CMD_ExecuteCommand("MAX72XX_Clear", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 0);
CMD_ExecuteCommand("MAX72XX_SetPixel 1 1 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 1);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 1);
CMD_ExecuteCommand("MAX72XX_SetPixel 1 1 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2);
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
}

View File

@ -6,6 +6,11 @@
class CControllerBase {
public:
class CShape *baseShape;
CControllerBase() {
baseShape = 0;
}
virtual void onDrawn() { }
virtual void sendEvent(int code, const class Coord &mouseOfs) { }
virtual void rotateDegreesAround(float f, const class Coord &p) { }

View File

@ -0,0 +1,54 @@
#ifdef WINDOWS
#include "Simulator.h"
#include "Simulation.h"
#include "Junction.h"
#include "Solver.h"
#include "sim_local.h"
#include "Controller_MAX7219.h"
#include "Controller_SimulatorLink.h"
#include "Shape.h"
#include "Junction.h"
#include "Text.h"
#include "../cJSON/cJSON.h"
static CControllerMAX7219 *g_hack = 0;
// backlog startDriver MAX72XX; MAX72XX_Setup 10 8 9 16; MAX72XX_Clear; MAX72XX_Print 12345; MAX72XX_refresh;
void CControllerMAX7219::saveTo(struct cJSON *j_obj) {
}
void CControllerMAX7219::loadFrom(struct cJSON *j_obj) {
}
void CControllerMAX7219::onDrawn() {
g_hack = this;
//int devices = 4;
//int single = 8 * 8;
for (int i = 0; i < 8 * 8 * 4; i++) {
int idx = i / 8; // byte index (row)
int bit = i % 8; // bit index
// reverse bit to match MSB-left
bool bOn = (pixels[idx] & (0x80 >> bit)) != 0;
CShape *s = baseShape->getShape(i);
s->setActive(bOn);
}
}
class CControllerBase *CControllerMAX7219::cloneController(class CShape *origOwner, class CShape *newOwner) {
CControllerMAX7219 *c = new CControllerMAX7219();
return c;
}
extern "C" void SIM_SetMAX7219Pixels(byte *data, int numDevices) {
if (g_hack == 0) {
return;
}
int totalRows = 8 * numDevices; // 4 cascaded devices, 8 rows each
g_hack->numDevices = numDevices;
for (int i = 0; i < totalRows; i++) {
g_hack->pixels[i] = data[i]; // MSB-left
}
}
#endif

View File

@ -0,0 +1,33 @@
#ifndef __CONTROLLER_MAX7219_H__
#define __CONTROLLER_MAX7219_H__
#include "sim_local.h"
#include "Controller_Base.h"
#include "Coord.h"
class CControllerMAX7219 : public CControllerBase {
void setShapesActive(bool b);
void setShapesFillColor(const CColor &c);
float realTemperature;
float realHumidity;
public:
byte pixels[512]; // TODO
int numDevices;
CControllerMAX7219() {
}
virtual void onDrawn();
virtual class CControllerBase *cloneController(class CShape *origOwner, class CShape *newOwner);
virtual void saveTo(struct cJSON *j_obj);
virtual void loadFrom(struct cJSON *j_obj);
float getTemperature() const {
return realTemperature;
}
float getHumidity() const {
return realHumidity;
}
};
#endif // __CONTROLLER_MAX7219_H__

32
src/sim/Point.cpp Normal file
View File

@ -0,0 +1,32 @@
#ifdef WINDOWS
#include "Point.h"
CShape *CPoint::cloneShape() {
CPoint *n = new CPoint();
n->pos = this->pos;
this->cloneShapeTo(n);
return n;
}
void CPoint::drawShape() {
g_style_shapes.apply();
glBegin(GL_POINTS);
glVertex2f(getX(), getY());
glEnd();
}
void CPoint::rotateDegreesAround_internal(float f, const Coord &p) {
Coord a = getPosition();
a = a.rotateDegreesAround(f, p);
setPosition(a);
}
void CPoint::recalcBoundsSelf() {
bounds.clear();
bounds.addPoint(Coord(0, 0));
}
#endif

23
src/sim/Point.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __POINT_H__
#define __POINT_H__
#include "sim_local.h"
#include "Shape.h"
class CPoint : public CShape {
virtual void recalcBoundsSelf();
void rotateDegreesAround_internal(float f, const Coord &p);
public:
CPoint() {
}
CPoint(float _x, float _y) {
this->setPosition(_x, _y);
}
virtual CShape *cloneShape();
virtual const char *getClassName() const {
return "CPoint";
}
virtual void drawShape();
};
#endif // __POINT_H__

View File

@ -11,6 +11,7 @@
#include "Controller_Pot.h"
#include "Controller_WS2812.h"
#include "Controller_DHT11.h"
#include "Controller_MAX7219.h"
#include "Junction.h"
class CShape *PrefabManager::generateVDD() {
@ -118,6 +119,64 @@ class CShape *PrefabManager::generateBL0942() {
o->setController(cntr);
return o;
}
class CShape *PrefabManager::generateMAX7219x4() {
CShape *o = new CShape();
o->setName("MAX7219x4");
int cols = 8*4; // 4 * 8
int rows = 8;
int cellSize = 20;
int w = cols * cellSize;
int sh = rows * cellSize;
int margin = 2; // margin between cells
for (int i = 0; i < 4; i++) {
for (int y = 7; y >= 0; y--) {
for (int x = 0; x < 8; x++) {
int cx = -w / 2 + (i*8 + 7-x) * cellSize + margin;
int cy = -sh / 2 + y * cellSize + margin;
int rw = cellSize - 2 * margin;
int rh = cellSize - 2 * margin;
//o->addRect(cx, cy, rw, rh)->setFill(false)->
// setFillColor(CColor(1, 0, 0,1));
o->addPoint(cx + rw / 2, cy + rh / 2)->setActive(true);
}
}
}
o->addText(-w / 2 - 5, -sh / 2 - 5, "MAX7219x4");
o->addRect(-w / 2, -sh / 2, w, sh);
int h = -40;
w /= 2;
CJunction *gnd = o->addJunction(w + 20, h, "GND");
o->addLine(w + 20, h, w, h);
gnd->setName("GND");
gnd->addText(-5, -5, "GND");
h += 20;
CJunction *CS = o->addJunction(w + 20, h, "CS");
o->addLine(w + 20, h, w, h);
CS->setName("CS");
CS->addText(-5, -5, "CS");
h += 20;
CJunction *DIN = o->addJunction(w + 20, h, "DIN");
o->addLine(w + 20, h, w, h);
DIN->setName("DIN");
DIN->addText(-5, -5, "DIN");
h += 20;
CJunction *CLK = o->addJunction(w + 20, h, "CLK");
o->addLine(w + 20, h, w, h);
CLK->setName("CLK");
CLK->addText(-5, -5, "CLK");
h += 20;
CJunction *vdd = o->addJunction(w + 20, h, "VDD");
o->addLine(w + 20, h, w, h);
vdd->setName("VDD");
vdd->addText(-5, -5, "VDD");
CControllerMAX7219 *cntr = new CControllerMAX7219();
o->setController(cntr);
return o;
}
class CShape *PrefabManager::generateDHT11() {
CShape *o = new CShape();
@ -544,6 +603,7 @@ void PrefabManager::createDefaultPrefabs() {
addPrefab(generatePot());
addPrefab(generateWS2812B());
addPrefab(generateDHT11());
addPrefab(generateMAX7219x4());
}

View File

@ -23,7 +23,8 @@ class PrefabManager {
class CShape *generateVDD();
class CShape *generatePot();
class CShape *generateWS2812B();
class CShape *generateDHT11();
class CShape *generateDHT11();
class CShape *generateMAX7219x4();
public:
PrefabManager(CSimulator *ps) {
sim = ps;

View File

@ -15,6 +15,7 @@ CShape *CRect::cloneShape() {
void CRect::drawShape() {
if (bFill) {
glColor3fv(getFillColor());
glDisable(GL_CULL_FACE);
glBegin(GL_QUADS);
glVertex2f(getX(), getY());
glVertex2f(getX() + w, getY());

View File

@ -3,6 +3,7 @@
#include "Circle.h"
#include "Rect.h"
#include "Line.h"
#include "Point.h"
#include "Text.h"
#include "Junction.h"
#include "Controller_Base.h"
@ -50,6 +51,7 @@ void CShape::cloneShapeTo(CShape *o) {
if (this->controller != 0) {
o->setController(this->controller->cloneController(this,o));
}
o->setActive(this->isActive());
}
CShape *CShape::cloneShape() {
CShape *r = new CShape();
@ -132,6 +134,11 @@ class CShape* CShape::addCircle(float x, float y, float r) {
addShape(n);
return n;
}
class CShape* CShape::addPoint(float x, float y) {
CPoint *n = new CPoint(x, y);
addShape(n);
return n;
}
class CShape* CShape::addRect(float x, float y, float w, float h) {
CRect *n = new CRect(x, y, w, h);
addShape(n);
@ -144,6 +151,12 @@ class CShape* CShape::addText(float x, float y, const char *s, bool bDeepText, b
addShape(n);
return n;
}
void CShape::setController(CControllerBase *c) {
controller = c;
if (controller) {
controller->baseShape = this;
}
}
Coord CShape::getAbsPosition() const {
Coord ofs = this->getPosition();
const CShape *p = this->getParent();

View File

@ -54,8 +54,9 @@ public:
virtual bool isWireJunction() const {
return false;
}
void setFill(bool b) {
CShape *setFill(bool b) {
bFill = b;
return this;
}
void setActive(bool b) {
bActive = b;
@ -100,9 +101,7 @@ public:
return getAbsPosition().dist(o->getAbsPosition());
}
virtual float moveTowards(const Coord &tg, float dt);
void setController(CControllerBase *c) {
controller = c;
}
void setController(CControllerBase *c);
CControllerBase *getController() {
return controller;
}
@ -149,6 +148,7 @@ public:
void rotateDegreesAroundSelf(float f);
class CShape* addLine(float x, float y, float x2, float y2);
class CShape* addRect(float x, float y, float w, float h);
class CShape* addPoint(float x, float y);
class CShape* addCircle(float x, float y, float r);
class CShape* addText(float x, float y, const char *s, bool bDeepText = false, bool bAllowNewLine = true);
class CJunction* addJunction(float x, float y, const char *name = "", int gpio = -1);