mirror of https://github.com/arendst/Tasmota.git
Merge remote-tracking branch 'upstream/development' into development
This commit is contained in:
commit
a10095217c
|
@ -1,7 +1,13 @@
|
||||||
## OS specific ########
|
## OS specific ########
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.fuse_hidden*
|
.fuse_hidden*
|
||||||
|
|
||||||
|
## Compilation artefacts ########
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.d
|
||||||
|
*.o
|
||||||
|
*.gcno
|
||||||
|
*.gcda
|
||||||
|
|
||||||
## Project files ######
|
## Project files ######
|
||||||
.platformio
|
.platformio
|
||||||
|
|
|
@ -17,6 +17,8 @@ All notable changes to this project will be documented in this file.
|
||||||
- Berry add ``gpio`` module
|
- Berry add ``gpio`` module
|
||||||
- Berry add ``light`` module
|
- Berry add ``light`` module
|
||||||
- Support for dummy energy monitor using user values set by commands ``VoltageSet``, ``CurrentSet``, ``PowerSet`` and ``FrequencySet``. Enable by selecting any GPIO as ``Option A2`` (#10640)
|
- Support for dummy energy monitor using user values set by commands ``VoltageSet``, ``CurrentSet``, ``PowerSet`` and ``FrequencySet``. Enable by selecting any GPIO as ``Option A2`` (#10640)
|
||||||
|
- Command ``Backlog0`` to allow execution of following commands without delay
|
||||||
|
- Tasmota discovery as alternative to Home Assistant discovery using define ``USE_TASMOTA_DISCOVERY``
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- PubSubClient library from EspEasy v2.7.12 to Tasmota v2.8.12
|
- PubSubClient library from EspEasy v2.7.12 to Tasmota v2.8.12
|
||||||
|
@ -25,6 +27,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- Limit number of relay/button columns in GUI to 8 (#11546)
|
- Limit number of relay/button columns in GUI to 8 (#11546)
|
||||||
- ADC range result from int to float using command ``FreqRes`` for decimal resolution selection (#11545)
|
- ADC range result from int to float using command ``FreqRes`` for decimal resolution selection (#11545)
|
||||||
- Teleinfo, if raw mode selected also return telemety values in SENSOR data
|
- Teleinfo, if raw mode selected also return telemety values in SENSOR data
|
||||||
|
- Removed overtemp detection on external energy monitoring devices (#11628)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- HC-SR04 on ESP32 release serial interface if not used (#11507)
|
- HC-SR04 on ESP32 release serial interface if not used (#11507)
|
||||||
|
|
|
@ -83,6 +83,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||||
- Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) [#11073](https://github.com/arendst/Tasmota/issues/11073)
|
- Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) [#11073](https://github.com/arendst/Tasmota/issues/11073)
|
||||||
- Command ``SerialBuffer 256..520`` to change hardware serial receive buffer size from default (256) to max local buffer size (520) [#11448](https://github.com/arendst/Tasmota/issues/11448)
|
- Command ``SerialBuffer 256..520`` to change hardware serial receive buffer size from default (256) to max local buffer size (520) [#11448](https://github.com/arendst/Tasmota/issues/11448)
|
||||||
- Command ``SetOption126 1`` to enable DS18x20 arithmetic mean over teleperiod for JSON temperature based on [#11472](https://github.com/arendst/Tasmota/issues/11472)
|
- Command ``SetOption126 1`` to enable DS18x20 arithmetic mean over teleperiod for JSON temperature based on [#11472](https://github.com/arendst/Tasmota/issues/11472)
|
||||||
|
- Command ``Backlog0`` to allow execution of following commands without delay
|
||||||
- Commands ``MqttKeepAlive 1..100`` to set Mqtt Keep Alive timer (default 30) and ``MqttTimeout 1..100`` to set Mqtt Socket Timeout (default 4) [#5341](https://github.com/arendst/Tasmota/issues/5341)
|
- Commands ``MqttKeepAlive 1..100`` to set Mqtt Keep Alive timer (default 30) and ``MqttTimeout 1..100`` to set Mqtt Socket Timeout (default 4) [#5341](https://github.com/arendst/Tasmota/issues/5341)
|
||||||
- Commands ``DisplayType`` to select sub-modules where implemented and ``DisplayInvert`` to select inverted display where implemented
|
- Commands ``DisplayType`` to select sub-modules where implemented and ``DisplayInvert`` to select inverted display where implemented
|
||||||
- Support for SML VBUS [#11125](https://github.com/arendst/Tasmota/issues/11125)
|
- Support for SML VBUS [#11125](https://github.com/arendst/Tasmota/issues/11125)
|
||||||
|
@ -103,6 +104,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||||
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
||||||
- ESP32 support for secondary I2C controller
|
- ESP32 support for secondary I2C controller
|
||||||
- ESP32 support for internal Hall Effect sensor connected to both GPIO36 and GPIO39 only
|
- ESP32 support for internal Hall Effect sensor connected to both GPIO36 and GPIO39 only
|
||||||
|
- Tasmota discovery as alternative to Home Assistant discovery using define ``USE_TASMOTA_DISCOVERY``
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- TasmotaSerial library from v3.2.0 to v3.3.0
|
- TasmotaSerial library from v3.2.0 to v3.3.0
|
||||||
|
@ -114,6 +116,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||||
- DeepSleep announcement topic [#11223](https://github.com/arendst/Tasmota/issues/11223)
|
- DeepSleep announcement topic [#11223](https://github.com/arendst/Tasmota/issues/11223)
|
||||||
- Limit number of relay/button columns in GUI to 8 [#11546](https://github.com/arendst/Tasmota/issues/11546)
|
- Limit number of relay/button columns in GUI to 8 [#11546](https://github.com/arendst/Tasmota/issues/11546)
|
||||||
- ADC range result from int to float using command ``FreqRes`` for decimal resolution selection [#11545](https://github.com/arendst/Tasmota/issues/11545)
|
- ADC range result from int to float using command ``FreqRes`` for decimal resolution selection [#11545](https://github.com/arendst/Tasmota/issues/11545)
|
||||||
|
- Removed overtemp detection on external energy monitoring devices [#11628](https://github.com/arendst/Tasmota/issues/11628)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- PN532 on ESP32 Serial flush both Tx and Rx buffers [#10910](https://github.com/arendst/Tasmota/issues/10910)
|
- PN532 on ESP32 Serial flush both Tx and Rx buffers [#10910](https://github.com/arendst/Tasmota/issues/10910)
|
||||||
|
|
|
@ -1243,6 +1243,16 @@ void Adafruit_GFX::setTextSize(uint8_t s_x, uint8_t s_y) {
|
||||||
textsize_y = (s_y > 0) ? s_y : 1;
|
textsize_y = (s_y > 0) ? s_y : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Adafruit_GFX::setwidth(uint16_t w) {
|
||||||
|
WIDTH = w;
|
||||||
|
_width = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_GFX::setheight(uint16_t h) {
|
||||||
|
HEIGHT = h;
|
||||||
|
_height = h;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Set rotation setting for display
|
@brief Set rotation setting for display
|
||||||
|
|
|
@ -187,6 +187,10 @@ virtual void
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
int16_t height(void) const { return _height; }
|
int16_t height(void) const { return _height; }
|
||||||
|
|
||||||
|
void setwidth(uint16_t w);
|
||||||
|
|
||||||
|
void setheight(uint16_t h);
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Get rotation setting for display
|
@brief Get rotation setting for display
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
ST7789 KEYWORD1
|
||||||
|
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
setRotation KEYWORD2
|
||||||
|
setAddrWindow KEYWORD2
|
||||||
|
pushColor KEYWORD2
|
||||||
|
drawPixel KEYWORD2
|
||||||
|
drawFastVLine KEYWORD2
|
||||||
|
drawFastHLine KEYWORD2
|
||||||
|
fillRect KEYWORD2
|
||||||
|
setRotation KEYWORD2
|
||||||
|
setRotation KEYWORD2
|
||||||
|
height KEYWORD2
|
||||||
|
width KEYWORD2
|
||||||
|
invertDisplay KEYWORD2
|
||||||
|
drawImage KEYWORD2
|
||||||
|
setScrollArea KEYWORD2
|
||||||
|
scroll KEYWORD2
|
|
@ -0,0 +1,9 @@
|
||||||
|
name=universal display Library
|
||||||
|
version=0.1
|
||||||
|
author=Gerhard Mutz
|
||||||
|
maintainer=Gerhard Mutz
|
||||||
|
sentence=This is a library a couple of displays.
|
||||||
|
paragraph=This is a library a couple of displays.
|
||||||
|
category=Display
|
||||||
|
url=https://github.com/arendst/Tasmota
|
||||||
|
architectures=*
|
|
@ -0,0 +1,607 @@
|
||||||
|
/*
|
||||||
|
uDisplay.cpp - universal display driver support for Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2021 Gerhard Mutz and Theo Arends
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include "uDisplay.h"
|
||||||
|
|
||||||
|
|
||||||
|
const uint16_t udisp_colors[]={UDISP_BLACK,UDISP_WHITE,UDISP_RED,UDISP_GREEN,UDISP_BLUE,UDISP_CYAN,UDISP_MAGENTA,\
|
||||||
|
UDISP_YELLOW,UDISP_NAVY,UDISP_DARKGREEN,UDISP_DARKCYAN,UDISP_MAROON,UDISP_PURPLE,UDISP_OLIVE,\
|
||||||
|
UDISP_LIGHTGREY,UDISP_DARKGREY,UDISP_ORANGE,UDISP_GREENYELLOW,UDISP_PINK};
|
||||||
|
|
||||||
|
uint16_t uDisplay::GetColorFromIndex(uint8_t index) {
|
||||||
|
if (index >= sizeof(udisp_colors) / 2) index = 0;
|
||||||
|
return udisp_colors[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uint8_t *buffer;
|
||||||
|
|
||||||
|
uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
|
||||||
|
// analyse decriptor
|
||||||
|
uint8_t section = 0;
|
||||||
|
dsp_ncmds = 0;
|
||||||
|
char linebuff[128];
|
||||||
|
while (*lp) {
|
||||||
|
|
||||||
|
uint16_t llen = strlen_ln(lp);
|
||||||
|
strncpy(linebuff, lp, llen);
|
||||||
|
linebuff[llen] = 0;
|
||||||
|
lp += llen;
|
||||||
|
char *lp1 = linebuff;
|
||||||
|
|
||||||
|
if (*lp1 == '#') break;
|
||||||
|
if (*lp1 == '\n') lp1++;
|
||||||
|
while (*lp1 == ' ') lp1++;
|
||||||
|
//Serial.printf(">> %s\n",lp1);
|
||||||
|
if (*lp1 != ';') {
|
||||||
|
// check ids:
|
||||||
|
if (*lp1 == ':') {
|
||||||
|
// id line
|
||||||
|
lp1++;
|
||||||
|
section = *lp1++;
|
||||||
|
} else {
|
||||||
|
switch (section) {
|
||||||
|
case 'H':
|
||||||
|
// header line
|
||||||
|
// SD1306,128,64,1,I2C,5a,*,*,*
|
||||||
|
str2c(&lp1, dname, sizeof(dname));
|
||||||
|
char ibuff[16];
|
||||||
|
gxs = next_val(&lp1);
|
||||||
|
setwidth(gxs);
|
||||||
|
gys = next_val(&lp1);
|
||||||
|
setheight(gys);
|
||||||
|
bpp = next_val(&lp1);
|
||||||
|
str2c(&lp1, ibuff, sizeof(ibuff));
|
||||||
|
if (!strncmp(ibuff, "I2C", 3)) {
|
||||||
|
interface = _UDSP_I2C;
|
||||||
|
i2caddr = next_hex(&lp1);
|
||||||
|
i2c_scl = next_val(&lp1);
|
||||||
|
i2c_sda = next_val(&lp1);
|
||||||
|
reset = next_val(&lp1);
|
||||||
|
section = 0;
|
||||||
|
} else if (!strncmp(ibuff, "SPI", 3)) {
|
||||||
|
interface = _UDSP_SPI;
|
||||||
|
spi_nr = next_val(&lp1);
|
||||||
|
spi_cs = next_val(&lp1);
|
||||||
|
spi_clk = next_val(&lp1);
|
||||||
|
spi_mosi = next_val(&lp1);
|
||||||
|
spi_dc = next_val(&lp1);
|
||||||
|
bpanel = next_val(&lp1);
|
||||||
|
reset = next_val(&lp1);
|
||||||
|
spi_miso = next_val(&lp1);
|
||||||
|
spi_speed = next_val(&lp1);
|
||||||
|
|
||||||
|
section = 0;
|
||||||
|
Serial.printf("%d %d %d %d %d %d %d %d\n", spi_cs, spi_clk, spi_mosi, spi_dc, bpanel, reset, spi_miso, spi_speed);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
splash_font = next_val(&lp1);
|
||||||
|
splash_size = next_val(&lp1);
|
||||||
|
fg_col = next_val(&lp1);
|
||||||
|
if (bpp == 16) {
|
||||||
|
fg_col = GetColorFromIndex(fg_col);
|
||||||
|
}
|
||||||
|
bg_col = next_val(&lp1);
|
||||||
|
if (bpp == 16) {
|
||||||
|
bg_col = GetColorFromIndex(bg_col);
|
||||||
|
}
|
||||||
|
splash_xp = next_val(&lp1);
|
||||||
|
splash_yp = next_val(&lp1);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
// init data
|
||||||
|
if (interface == _UDSP_I2C) {
|
||||||
|
dsp_cmds[dsp_ncmds++] = next_hex(&lp1);
|
||||||
|
if (!str2c(&lp1, ibuff, sizeof(ibuff))) {
|
||||||
|
dsp_cmds[dsp_ncmds++] = strtol(ibuff, 0, 16);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (1) {
|
||||||
|
if (!str2c(&lp1, ibuff, sizeof(ibuff))) {
|
||||||
|
dsp_cmds[dsp_ncmds++] = strtol(ibuff, 0, 16);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dsp_ncmds >= sizeof(dsp_cmds)) break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
str2c(&lp1, ibuff, sizeof(ibuff));
|
||||||
|
dsp_off = strtol(ibuff, 0, 16);
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
str2c(&lp1, ibuff, sizeof(ibuff));
|
||||||
|
dsp_on = strtol(ibuff, 0, 16);
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
rot_0 = next_hex(&lp1);
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
rot_1 = next_hex(&lp1);
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
rot_2 = next_hex(&lp1);
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
rot_3 = next_hex(&lp1);
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
saw_1 = next_hex(&lp1);
|
||||||
|
saw_2 = next_hex(&lp1);
|
||||||
|
saw_3 = next_hex(&lp1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*lp == '\n') {
|
||||||
|
lp++;
|
||||||
|
} else {
|
||||||
|
lp = strchr(lp, '\n');
|
||||||
|
if (!lp) break;
|
||||||
|
lp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Renderer *uDisplay::Init(void) {
|
||||||
|
|
||||||
|
|
||||||
|
if (reset >= 0) {
|
||||||
|
pinMode(reset, OUTPUT);
|
||||||
|
digitalWrite(reset, HIGH);
|
||||||
|
delay(50);
|
||||||
|
digitalWrite(reset, LOW);
|
||||||
|
delay(50);
|
||||||
|
digitalWrite(reset, HIGH);
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interface == _UDSP_I2C) {
|
||||||
|
Wire.begin(i2c_sda, i2c_scl);
|
||||||
|
if (bpp < 16) {
|
||||||
|
if (buffer) free(buffer);
|
||||||
|
buffer = (uint8_t*)calloc((width()*height()*bpp)/8, 1);
|
||||||
|
|
||||||
|
for (uint32_t cnt = 0; cnt < dsp_ncmds; cnt++) {
|
||||||
|
i2c_command(dsp_cmds[cnt]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (interface == _UDSP_SPI) {
|
||||||
|
if (bpanel >= 0) {
|
||||||
|
#ifdef ESP32
|
||||||
|
ledcSetup(ESP32_PWM_CHANNEL, 4000, 8);
|
||||||
|
ledcAttachPin(bpanel, ESP32_PWM_CHANNEL);
|
||||||
|
ledcWrite(ESP32_PWM_CHANNEL, 128);
|
||||||
|
#else
|
||||||
|
pinMode(bpanel, OUTPUT);
|
||||||
|
digitalWrite(bpanel, HIGH);
|
||||||
|
#endif // ESP32
|
||||||
|
}
|
||||||
|
if (spi_dc >= 0) {
|
||||||
|
pinMode(spi_dc, OUTPUT);
|
||||||
|
digitalWrite(spi_dc, HIGH);
|
||||||
|
}
|
||||||
|
if (spi_cs >= 0) {
|
||||||
|
pinMode(spi_cs, OUTPUT);
|
||||||
|
digitalWrite(spi_cs, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
spiSettings = SPISettings(spi_speed, MSBFIRST, SPI_MODE3);
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
SPI.begin();
|
||||||
|
uspi = &SPI;
|
||||||
|
#else
|
||||||
|
if (spi_nr != 1) {
|
||||||
|
uspi = new SPIClass(HSPI);
|
||||||
|
} else {
|
||||||
|
uspi = &SPI;
|
||||||
|
}
|
||||||
|
uspi->begin(spi_clk, spi_miso, spi_mosi, -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t index = 0;
|
||||||
|
|
||||||
|
SPI_BEGIN_TRANSACTION
|
||||||
|
while (1) {
|
||||||
|
uint8_t iob;
|
||||||
|
SPI_CS_LOW
|
||||||
|
SPI_DC_LOW
|
||||||
|
iob = dsp_cmds[index++];
|
||||||
|
uspi->write(iob);
|
||||||
|
SPI_DC_HIGH
|
||||||
|
uint8_t args = dsp_cmds[index++];
|
||||||
|
//Serial.printf("cmd, args %x, %d ", iob, args&0x7f);
|
||||||
|
for (uint32_t cnt = 0; cnt < (args & 0x7f); cnt++) {
|
||||||
|
iob = dsp_cmds[index++];
|
||||||
|
//Serial.printf("%02x ", iob );
|
||||||
|
uspi->write(iob);
|
||||||
|
}
|
||||||
|
SPI_CS_HIGH
|
||||||
|
//Serial.printf("\n");
|
||||||
|
if (args & 0x80) delay(120);
|
||||||
|
if (index >= dsp_ncmds) break;
|
||||||
|
}
|
||||||
|
SPI_END_TRANSACTION
|
||||||
|
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||||
|
setRotation(rot);
|
||||||
|
invertDisplay(false);
|
||||||
|
setTextWrap(false);
|
||||||
|
cp437(true);
|
||||||
|
setTextFont(font);
|
||||||
|
setTextSize(size);
|
||||||
|
setTextColor(fg_col, bg_col);
|
||||||
|
setCursor(0,0);
|
||||||
|
fillScreen(bg_col);
|
||||||
|
Updateframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::spi_command(uint8_t val) {
|
||||||
|
SPI_BEGIN_TRANSACTION
|
||||||
|
SPI_DC_LOW
|
||||||
|
SPI_CS_LOW
|
||||||
|
uspi->write(val);
|
||||||
|
SPI_CS_HIGH
|
||||||
|
SPI_DC_HIGH
|
||||||
|
SPI_END_TRANSACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::i2c_command(uint8_t val) {
|
||||||
|
//Serial.printf("%02x\n",val );
|
||||||
|
Wire.beginTransmission(i2caddr);
|
||||||
|
Wire.write(0);
|
||||||
|
Wire.write(val);
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SH1106_SETLOWCOLUMN 0
|
||||||
|
#define SH1106_SETHIGHCOLUMN 0x10
|
||||||
|
#define SH1106_SETSTARTLINE 0x40
|
||||||
|
|
||||||
|
|
||||||
|
void uDisplay::Updateframe(void) {
|
||||||
|
|
||||||
|
if (interface == _UDSP_I2C) {
|
||||||
|
i2c_command(SH1106_SETLOWCOLUMN | 0x0); // low col = 0
|
||||||
|
i2c_command(SH1106_SETHIGHCOLUMN | 0x0); // hi col = 0
|
||||||
|
i2c_command(SH1106_SETSTARTLINE | 0x0); // line #0
|
||||||
|
|
||||||
|
uint8_t ys = gys >> 3;
|
||||||
|
uint8_t xs = gxs >> 3;
|
||||||
|
//uint8_t xs = 132 >> 3;
|
||||||
|
uint8_t m_row = 0;
|
||||||
|
uint8_t m_col = 2;
|
||||||
|
|
||||||
|
uint16_t p = 0;
|
||||||
|
|
||||||
|
uint8_t i, j, k = 0;
|
||||||
|
|
||||||
|
for ( i = 0; i < ys; i++) {
|
||||||
|
// send a bunch of data in one xmission
|
||||||
|
i2c_command(0xB0 + i + m_row);//set page address
|
||||||
|
i2c_command(m_col & 0xf);//set lower column address
|
||||||
|
i2c_command(0x10 | (m_col >> 4));//set higher column address
|
||||||
|
|
||||||
|
for( j = 0; j < 8; j++){
|
||||||
|
Wire.beginTransmission(i2caddr);
|
||||||
|
Wire.write(0x40);
|
||||||
|
for ( k = 0; k < xs; k++, p++) {
|
||||||
|
Wire.write(buffer[p]);
|
||||||
|
}
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||||
|
|
||||||
|
if (interface != _UDSP_SPI) {
|
||||||
|
Renderer::drawFastVLine(x, y, h, color);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Rudimentary clipping
|
||||||
|
if ((x >= _width) || (y >= _height)) return;
|
||||||
|
if ((y + h - 1) >= _height) h = _height - y;
|
||||||
|
|
||||||
|
SPI_BEGIN_TRANSACTION
|
||||||
|
|
||||||
|
SPI_CS_LOW
|
||||||
|
|
||||||
|
setAddrWindow_int(x, y, 1, h);
|
||||||
|
|
||||||
|
while (h--) {
|
||||||
|
uspi->write16(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI_CS_HIGH
|
||||||
|
|
||||||
|
SPI_END_TRANSACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||||
|
|
||||||
|
if (interface != _UDSP_SPI) {
|
||||||
|
Renderer::drawFastHLine(x, y, w, color);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rudimentary clipping
|
||||||
|
if((x >= _width) || (y >= _height)) return;
|
||||||
|
if((x+w-1) >= _width) w = _width-x;
|
||||||
|
|
||||||
|
|
||||||
|
SPI_BEGIN_TRANSACTION
|
||||||
|
|
||||||
|
SPI_CS_LOW
|
||||||
|
|
||||||
|
setAddrWindow_int(x, y, w, 1);
|
||||||
|
|
||||||
|
|
||||||
|
while (w--) {
|
||||||
|
uspi->write16(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI_CS_HIGH
|
||||||
|
|
||||||
|
SPI_END_TRANSACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::fillScreen(uint16_t color) {
|
||||||
|
fillRect(0, 0, gxs, gys, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill a rectangle
|
||||||
|
void uDisplay::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
|
||||||
|
|
||||||
|
if (interface != _UDSP_SPI) {
|
||||||
|
Renderer::fillRect(x, y, w, h, color);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rudimentary clipping (drawChar w/big text requires this)
|
||||||
|
if((x >= gxs) || (y >= gys)) return;
|
||||||
|
if((x + w - 1) >= gxs) w = gxs - x;
|
||||||
|
if((y + h - 1) >= gys) h = gys - y;
|
||||||
|
|
||||||
|
|
||||||
|
SPI_BEGIN_TRANSACTION
|
||||||
|
SPI_CS_LOW
|
||||||
|
|
||||||
|
setAddrWindow_int(x, y, w, h);
|
||||||
|
|
||||||
|
for (y = h; y > 0; y--) {
|
||||||
|
for (x = w; x > 0; x--) {
|
||||||
|
uspi->write16(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SPI_CS_HIGH
|
||||||
|
SPI_END_TRANSACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uDisplay::Splash(void) {
|
||||||
|
setTextFont(splash_font);
|
||||||
|
setTextSize(splash_size);
|
||||||
|
DrawStringAt(splash_xp, splash_yp, dname, fg_col, 0);
|
||||||
|
Updateframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||||
|
|
||||||
|
if (!x0 && !y0 && !x1 && !y1) {
|
||||||
|
SPI_CS_HIGH
|
||||||
|
SPI_END_TRANSACTION
|
||||||
|
} else {
|
||||||
|
SPI_CS_LOW
|
||||||
|
SPI_BEGIN_TRANSACTION
|
||||||
|
setAddrWindow_int(x0, y0, x1 - x0, y1 - y0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||||
|
uint32_t xa = ((uint32_t)x << 16) | (x+w-1);
|
||||||
|
uint32_t ya = ((uint32_t)y << 16) | (y+h-1);
|
||||||
|
|
||||||
|
SPI_DC_LOW
|
||||||
|
uspi->write(saw_1);
|
||||||
|
SPI_DC_HIGH
|
||||||
|
|
||||||
|
uspi->write32(xa);
|
||||||
|
|
||||||
|
SPI_DC_LOW
|
||||||
|
uspi->write(saw_2);
|
||||||
|
SPI_DC_HIGH
|
||||||
|
|
||||||
|
uspi->write32(ya);
|
||||||
|
|
||||||
|
SPI_DC_LOW
|
||||||
|
uspi->write(saw_3); // write to RAM
|
||||||
|
SPI_DC_HIGH
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean first) {
|
||||||
|
uint16_t color;
|
||||||
|
|
||||||
|
while (len--) {
|
||||||
|
color = *data++;
|
||||||
|
uspi->write16(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||||
|
|
||||||
|
if (interface != _UDSP_SPI) {
|
||||||
|
Renderer::drawPixel(x, y, color);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
|
||||||
|
|
||||||
|
|
||||||
|
SPI_BEGIN_TRANSACTION
|
||||||
|
|
||||||
|
SPI_CS_LOW
|
||||||
|
|
||||||
|
setAddrWindow_int(x, y, 1, 1);
|
||||||
|
|
||||||
|
uspi->write16(color);
|
||||||
|
|
||||||
|
SPI_CS_HIGH
|
||||||
|
|
||||||
|
SPI_END_TRANSACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::setRotation(uint8_t m) {
|
||||||
|
if (interface != _UDSP_SPI) {
|
||||||
|
Renderer::setRotation(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (rotation) {
|
||||||
|
case 0:
|
||||||
|
if (interface == _UDSP_SPI) spi_command(rot_0);
|
||||||
|
_width = gxs;
|
||||||
|
_height = gys;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (interface == _UDSP_SPI) spi_command(rot_1);
|
||||||
|
_width = gys;
|
||||||
|
_height = gxs;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (interface == _UDSP_SPI) spi_command(rot_2);
|
||||||
|
_width = gxs;
|
||||||
|
_height = gys;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (interface == _UDSP_SPI) spi_command(rot_3);
|
||||||
|
_width = gys;
|
||||||
|
_height = gxs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::DisplayOnff(int8_t on) {
|
||||||
|
|
||||||
|
if (interface == _UDSP_I2C) {
|
||||||
|
if (on) {
|
||||||
|
i2c_command(dsp_on);
|
||||||
|
} else {
|
||||||
|
i2c_command(dsp_off);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (on) {
|
||||||
|
spi_command(dsp_on);
|
||||||
|
if (bpanel >= 0) {
|
||||||
|
#ifdef ESP32
|
||||||
|
ledcWrite(ESP32_PWM_CHANNEL, dimmer);
|
||||||
|
#else
|
||||||
|
digitalWrite(bpanel, HIGH);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
spi_command(dsp_off);
|
||||||
|
if (bpanel >= 0) {
|
||||||
|
#ifdef ESP32
|
||||||
|
ledcWrite(ESP32_PWM_CHANNEL, 0);
|
||||||
|
#else
|
||||||
|
digitalWrite(bpanel, LOW);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uDisplay::dim(uint8_t dim) {
|
||||||
|
dimmer = dim;
|
||||||
|
if (dimmer > 15) dimmer = 15;
|
||||||
|
dimmer = ((float)dimmer / 15.0) * 255.0;
|
||||||
|
#ifdef ESP32
|
||||||
|
ledcWrite(ESP32_PWM_CHANNEL, dimmer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t uDisplay::strlen_ln(char *str) {
|
||||||
|
for (uint32_t cnt = 0; cnt < 256; cnt++) {
|
||||||
|
if (!str[cnt] || str[cnt] == '\n') return cnt;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *uDisplay::devname(void) {
|
||||||
|
return dname;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uDisplay::str2c(char **sp, char *vp, uint32_t len) {
|
||||||
|
char *lp = *sp;
|
||||||
|
if (len) len--;
|
||||||
|
char *cp = strchr(lp, ',');
|
||||||
|
if (cp) {
|
||||||
|
while (1) {
|
||||||
|
if (*lp == ',') {
|
||||||
|
*vp = 0;
|
||||||
|
*sp = lp + 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
*vp++ = *lp++;
|
||||||
|
len--;
|
||||||
|
} else {
|
||||||
|
lp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint8_t slen = strlen(lp);
|
||||||
|
if (slen) {
|
||||||
|
strlcpy(vp, *sp, len);
|
||||||
|
*sp = lp + slen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t uDisplay::next_val(char **sp) {
|
||||||
|
char ibuff[16];
|
||||||
|
str2c(sp, ibuff, sizeof(ibuff));
|
||||||
|
return atoi(ibuff);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uDisplay::next_hex(char **sp) {
|
||||||
|
char ibuff[16];
|
||||||
|
str2c(sp, ibuff, sizeof(ibuff));
|
||||||
|
return strtol(ibuff, 0, 16);
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef _UDISP_
|
||||||
|
#define _UDISP_
|
||||||
|
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <renderer.h>
|
||||||
|
|
||||||
|
#define _UDSP_I2C 1
|
||||||
|
#define _UDSP_SPI 2
|
||||||
|
|
||||||
|
#define UDISP1_WHITE 1
|
||||||
|
#define UDISP1_BLACK 0
|
||||||
|
|
||||||
|
|
||||||
|
// Color definitions
|
||||||
|
#define UDISP_BLACK 0x0000 /* 0, 0, 0 */
|
||||||
|
#define UDISP_NAVY 0x000F /* 0, 0, 128 */
|
||||||
|
#define UDISP_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||||
|
#define UDISP_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||||
|
#define UDISP_MAROON 0x7800 /* 128, 0, 0 */
|
||||||
|
#define UDISP_PURPLE 0x780F /* 128, 0, 128 */
|
||||||
|
#define UDISP_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||||
|
#define UDISP_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||||
|
#define UDISP_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||||
|
#define UDISP_BLUE 0x001F /* 0, 0, 255 */
|
||||||
|
#define UDISP_GREEN 0x07E0 /* 0, 255, 0 */
|
||||||
|
#define UDISP_CYAN 0x07FF /* 0, 255, 255 */
|
||||||
|
#define UDISP_RED 0xF800 /* 255, 0, 0 */
|
||||||
|
#define UDISP_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||||
|
#define UDISP_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||||
|
#define UDISP_WHITE 0xFFFF /* 255, 255, 255 */
|
||||||
|
#define UDISP_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||||
|
#define UDISP_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||||
|
#define UDISP_PINK 0xF81F
|
||||||
|
|
||||||
|
#define SPI_BEGIN_TRANSACTION uspi->beginTransaction(spiSettings);
|
||||||
|
#define SPI_END_TRANSACTION uspi->endTransaction();
|
||||||
|
#define SPI_CS_LOW if (spi_cs >= 0) digitalWrite(spi_cs, LOW);
|
||||||
|
#define SPI_CS_HIGH if (spi_cs >= 0) digitalWrite(spi_cs, HIGH);
|
||||||
|
#define SPI_DC_LOW if (spi_dc >= 0) digitalWrite(spi_dc, LOW);
|
||||||
|
#define SPI_DC_HIGH if (spi_dc >= 0) digitalWrite(spi_dc, HIGH);
|
||||||
|
|
||||||
|
#define ESP32_PWM_CHANNEL 1
|
||||||
|
|
||||||
|
class uDisplay : public Renderer {
|
||||||
|
public:
|
||||||
|
uDisplay(char *);
|
||||||
|
Renderer *Init(void);
|
||||||
|
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||||
|
void Updateframe();
|
||||||
|
void DisplayOnff(int8_t on);
|
||||||
|
void Splash(void);
|
||||||
|
char *devname(void);
|
||||||
|
uint16_t fgcol(void) const { return fg_col; };
|
||||||
|
uint16_t bgcol(void) const { return bg_col; };
|
||||||
|
void dim(uint8_t dim);
|
||||||
|
uint16_t GetColorFromIndex(uint8_t index);
|
||||||
|
void setRotation(uint8_t m);
|
||||||
|
void fillScreen(uint16_t color);
|
||||||
|
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||||
|
void pushColors(uint16_t *data, uint16_t len, boolean first);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||||
|
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||||
|
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||||
|
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||||
|
uint32_t str2c(char **sp, char *vp, uint32_t len);
|
||||||
|
void i2c_command(uint8_t val);
|
||||||
|
void spi_command(uint8_t val);
|
||||||
|
uint8_t strlen_ln(char *str);
|
||||||
|
int32_t next_val(char **sp);
|
||||||
|
uint32_t next_hex(char **sp);
|
||||||
|
void setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||||
|
char dname[16];
|
||||||
|
int8_t bpp;
|
||||||
|
uint8_t interface;
|
||||||
|
uint8_t i2caddr;
|
||||||
|
int8_t i2c_scl;
|
||||||
|
int8_t i2c_sda;
|
||||||
|
int8_t reset;
|
||||||
|
uint8_t dsp_cmds[128];
|
||||||
|
uint8_t dsp_ncmds;
|
||||||
|
uint8_t dsp_on;
|
||||||
|
uint8_t dsp_off;
|
||||||
|
uint16_t splash_font;
|
||||||
|
uint16_t splash_size;
|
||||||
|
uint16_t splash_xp;
|
||||||
|
uint16_t splash_yp;
|
||||||
|
uint16_t fg_col;
|
||||||
|
uint16_t bg_col;
|
||||||
|
uint16_t gxs;
|
||||||
|
uint16_t gys;
|
||||||
|
int8_t spi_cs;
|
||||||
|
int8_t spi_clk;
|
||||||
|
int8_t spi_mosi;
|
||||||
|
int8_t spi_dc;
|
||||||
|
int8_t bpanel;
|
||||||
|
int8_t spi_miso;
|
||||||
|
uint8_t dimmer;
|
||||||
|
SPIClass *uspi;
|
||||||
|
SPISettings spiSettings;
|
||||||
|
uint32_t spi_speed;
|
||||||
|
uint8_t spi_nr = 1;
|
||||||
|
uint8_t rot_0;
|
||||||
|
uint8_t rot_1;
|
||||||
|
uint8_t rot_2;
|
||||||
|
uint8_t rot_3;
|
||||||
|
uint8_t saw_1;
|
||||||
|
uint8_t saw_2;
|
||||||
|
uint8_t saw_3;
|
||||||
|
uint8_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _UDISP_
|
|
@ -1,7 +0,0 @@
|
||||||
name=Berry
|
|
||||||
version=0.1.10
|
|
||||||
author=Guan Wenliang <skiars@qq.com>,
|
|
||||||
maintainer=Stephan Hadinger <stephan.hadinger@gmail.com>
|
|
||||||
sentence=Berry scripting language for Tasmota32
|
|
||||||
paragraph=Berry is a ultra-lightweight dynamically typed embedded scripting language.
|
|
||||||
architectures=esp32
|
|
|
@ -1 +0,0 @@
|
||||||
#include "port/berry_conf.h"
|
|
|
@ -1,34 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
* Tasmota lib
|
|
||||||
*
|
|
||||||
* To use: `d = Driver()`
|
|
||||||
*
|
|
||||||
*******************************************************************/
|
|
||||||
#include "be_object.h"
|
|
||||||
|
|
||||||
// #if !BE_USE_PRECOMPILED_OBJECT
|
|
||||||
#if 1 // TODO we will do pre-compiled later
|
|
||||||
void be_load_driverlib(bvm *vm)
|
|
||||||
{
|
|
||||||
static const bnfuncinfo members[] = {
|
|
||||||
{ "every_second", NULL },
|
|
||||||
{ "every_100ms", NULL },
|
|
||||||
{ "web_add_button", NULL },
|
|
||||||
{ "web_add_main_button", NULL },
|
|
||||||
{ "save_before_restart", NULL },
|
|
||||||
{ "web_sensor", NULL },
|
|
||||||
{ "json_append", NULL },
|
|
||||||
{ "button_pressed", NULL },
|
|
||||||
|
|
||||||
{ NULL, NULL }
|
|
||||||
};
|
|
||||||
be_regclass(vm, "Driver", members);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* @const_object_info_begin
|
|
||||||
module tasmota (scope: global, depend: 1) {
|
|
||||||
get_free_heap, func(l_getFreeHeap)
|
|
||||||
}
|
|
||||||
@const_object_info_end */
|
|
||||||
#include "../generate/be_fixed_tasmota.h"
|
|
||||||
#endif
|
|
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,110 @@
|
||||||
|
/********************************************************************
|
||||||
|
* Tasmota lib
|
||||||
|
*
|
||||||
|
* To use: `d = Driver()`
|
||||||
|
*
|
||||||
|
*******************************************************************/
|
||||||
|
#include "be_object.h"
|
||||||
|
#include "be_string.h"
|
||||||
|
#include "be_gc.h"
|
||||||
|
|
||||||
|
extern int d_getTasmotaGlob(bvm *vm);
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
"class Driver2 : Driver "
|
||||||
|
"def add_cmd(c, f) "
|
||||||
|
"var tasmota = self.get_tasmota() "
|
||||||
|
"tasmota.add_cmd(c, / cmd, idx, payload, payload_json -> f(self, cmd, idx, payload, payload_json)) "
|
||||||
|
"end "
|
||||||
|
"end "
|
||||||
|
"Driver = Driver2 "
|
||||||
|
********************************************************************/
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: add_cmd
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
/********** Solidified proto: add_cmd_0 */
|
||||||
|
static const bupvaldesc add_cmd_0_upvals[2] = {
|
||||||
|
be_local_const_upval(1, 2),
|
||||||
|
be_local_const_upval(1, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
be_define_local_const_str(add_cmd_0_str_name, "add_cmd_0", 607256038, 0, 8, 0);
|
||||||
|
be_define_local_const_str(add_cmd_0_str_source, "input", -103256197, 0, 5, 0);
|
||||||
|
|
||||||
|
static const uint32_t add_cmd_0_code[8] = {
|
||||||
|
0x68100000, // 0000 GETUPV R4 U0
|
||||||
|
0x68140001, // 0001 GETUPV R5 U1
|
||||||
|
0x5C180000, // 0002 MOVE R6 R0
|
||||||
|
0x5C1C0200, // 0003 MOVE R7 R1
|
||||||
|
0x5C200400, // 0004 MOVE R8 R2
|
||||||
|
0x5C240600, // 0005 MOVE R9 R3
|
||||||
|
0x7C100A00, // 0006 CALL R4 5
|
||||||
|
0x80040800, // 0007 RET 1 R4
|
||||||
|
};
|
||||||
|
|
||||||
|
be_define_local_proto(add_cmd_0, 10, 4, 0, 0, 1);
|
||||||
|
|
||||||
|
/********** Solidified proto: add_cmd */
|
||||||
|
static const bproto *add_cmd_subproto[1] = {
|
||||||
|
&add_cmd_0_proto,
|
||||||
|
};
|
||||||
|
|
||||||
|
be_define_local_const_str(add_cmd_str_name, "add_cmd", -933336417, 0, 7, 0);
|
||||||
|
be_define_local_const_str(add_cmd_str_source, "input", -103256197, 0, 5, 0);
|
||||||
|
be_define_local_const_str(add_cmd_str_0, "get_tasmota", 334356779, 0, 11, 0);
|
||||||
|
be_define_local_const_str(add_cmd_str_1, "add_cmd", -933336417, 0, 7, 0);
|
||||||
|
|
||||||
|
static const bvalue add_cmd_ktab[2] = {
|
||||||
|
{ { .s=be_local_const_str(add_cmd_str_0) }, BE_STRING},
|
||||||
|
{ { .s=be_local_const_str(add_cmd_str_1) }, BE_STRING},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t add_cmd_code[8] = {
|
||||||
|
0x8C0C0100, // 0000 GETMET R3 R0 R256
|
||||||
|
0x7C0C0200, // 0001 CALL R3 1
|
||||||
|
0x8C100701, // 0002 GETMET R4 R3 R257
|
||||||
|
0x5C180200, // 0003 MOVE R6 R1
|
||||||
|
0x841C0000, // 0004 CLOSURE R7 P0
|
||||||
|
0x7C100600, // 0005 CALL R4 3
|
||||||
|
0xA0000000, // 0006 CLOSE 0
|
||||||
|
0x80000000, // 0007 RET 0 R0
|
||||||
|
};
|
||||||
|
|
||||||
|
be_define_local_proto(add_cmd, 8, 3, 1, 1, 0);
|
||||||
|
be_define_local_closure(add_cmd);
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
// #if !BE_USE_PRECOMPILED_OBJECT
|
||||||
|
#if 1 // TODO we will do pre-compiled later
|
||||||
|
void be_load_driverlib(bvm *vm)
|
||||||
|
{
|
||||||
|
static const bnfuncinfo members[] = {
|
||||||
|
{ "every_second", NULL },
|
||||||
|
{ "every_100ms", NULL },
|
||||||
|
{ "web_add_button", NULL },
|
||||||
|
{ "web_add_main_button", NULL },
|
||||||
|
{ "save_before_restart", NULL },
|
||||||
|
{ "web_sensor", NULL },
|
||||||
|
{ "json_append", NULL },
|
||||||
|
{ "button_pressed", NULL },
|
||||||
|
|
||||||
|
{ "get_tasmota", d_getTasmotaGlob },
|
||||||
|
|
||||||
|
{ NULL, (bntvfunc) BE_CLOSURE }, /* mark section for berry closures */
|
||||||
|
{ "add_cmd", (bntvfunc) &add_cmd_closure },
|
||||||
|
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
be_regclass(vm, "Driver", members);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* @const_object_info_begin
|
||||||
|
module tasmota (scope: global, depend: 1) {
|
||||||
|
get_free_heap, func(l_getFreeHeap)
|
||||||
|
}
|
||||||
|
@const_object_info_end */
|
||||||
|
#include "../generate/be_fixed_tasmota.h"
|
||||||
|
#endif
|
|
@ -0,0 +1,20 @@
|
||||||
|
# anonymous function and closure
|
||||||
|
def count(x)
|
||||||
|
var arr = []
|
||||||
|
for i : 0 .. x
|
||||||
|
arr.push(
|
||||||
|
def (n) # loop variable cannot be used directly as free variable
|
||||||
|
return def ()
|
||||||
|
return n * n
|
||||||
|
end
|
||||||
|
end (i) # define and call anonymous function
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return arr
|
||||||
|
end
|
||||||
|
|
||||||
|
for xx : count(6)
|
||||||
|
print(xx()) # 0, 1, 4 ... n * n
|
||||||
|
end
|
||||||
|
|
||||||
|
return count
|
|
@ -0,0 +1,15 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
c = time.clock()
|
||||||
|
do
|
||||||
|
i = 0
|
||||||
|
while i < 100000000
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print('while iteration 100000000 times', time.clock() - c, 's')
|
||||||
|
|
||||||
|
c = time.clock()
|
||||||
|
for i : 1 .. 100000000
|
||||||
|
end
|
||||||
|
print('for iteration 100000000 times', time.clock() - c, 's')
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Reference from https://github.com/BerryMathDevelopmentTeam/BerryMath/blob/master/testscript/BinaryTree.bm
|
||||||
|
|
||||||
|
class node
|
||||||
|
var v, l, r
|
||||||
|
def init(v, l, r)
|
||||||
|
self.v = v
|
||||||
|
self.l = l
|
||||||
|
self.r = r
|
||||||
|
end
|
||||||
|
def insert(v)
|
||||||
|
if v < self.v
|
||||||
|
if self.l
|
||||||
|
self.l.insert(v)
|
||||||
|
else
|
||||||
|
self.l = node(v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if self.r
|
||||||
|
self.r.insert(v)
|
||||||
|
else
|
||||||
|
self.r = node (v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def sort(l)
|
||||||
|
if (self.l) self.l.sort(l) end
|
||||||
|
l.push(self.v)
|
||||||
|
if (self.r) self.r.sort(l) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class btree
|
||||||
|
var root
|
||||||
|
def insert(v)
|
||||||
|
if self.root
|
||||||
|
self.root.insert(v)
|
||||||
|
else
|
||||||
|
self.root = node(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def sort()
|
||||||
|
var l = []
|
||||||
|
if self.root
|
||||||
|
self.root.sort(l)
|
||||||
|
end
|
||||||
|
return l
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
var tree = btree()
|
||||||
|
tree.insert(-100)
|
||||||
|
tree.insert(5);
|
||||||
|
tree.insert(3);
|
||||||
|
tree.insert(9);
|
||||||
|
tree.insert(10);
|
||||||
|
tree.insert(10000000);
|
||||||
|
tree.insert(1);
|
||||||
|
tree.insert(-1);
|
||||||
|
tree.insert(-10);
|
||||||
|
print(tree.sort());
|
|
@ -0,0 +1,16 @@
|
||||||
|
def cpi(n)
|
||||||
|
i = 2
|
||||||
|
pi = 3
|
||||||
|
while i <= n
|
||||||
|
term = 4.0 / (i * (i + 1) * (i + 2))
|
||||||
|
if i % 4
|
||||||
|
pi = pi + term
|
||||||
|
else
|
||||||
|
pi = pi - term
|
||||||
|
end
|
||||||
|
i = i + 2
|
||||||
|
end
|
||||||
|
return pi
|
||||||
|
end
|
||||||
|
|
||||||
|
print("pi =", cpi(100))
|
|
@ -0,0 +1,12 @@
|
||||||
|
import debug
|
||||||
|
|
||||||
|
def test_func()
|
||||||
|
try
|
||||||
|
compile('def +() end')()
|
||||||
|
except .. as e, v
|
||||||
|
print('catch execption:', str(e) + ' >>>\n ' + str(v))
|
||||||
|
debug.traceback()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test_func()
|
|
@ -0,0 +1,12 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
def fib(x)
|
||||||
|
if x <= 2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
return fib(x - 1) + fib(x - 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
c = time.clock()
|
||||||
|
print("fib:", fib(38)) # minimum stack size: 78!!
|
||||||
|
print("time:", time.clock() - c, 's')
|
|
@ -0,0 +1,26 @@
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
|
||||||
|
math.srand(time.time())
|
||||||
|
res = math.rand() % 100
|
||||||
|
max_test = 7
|
||||||
|
test = -1
|
||||||
|
idx = 1
|
||||||
|
print('Guess a number between 0 and 99. You have', max_test, 'chances.')
|
||||||
|
while test != res && idx <= max_test
|
||||||
|
test = number(input(str(idx) + ': enter the number you guessed: '))
|
||||||
|
if type(test) != 'int'
|
||||||
|
print('This is not an integer. Continue!')
|
||||||
|
continue
|
||||||
|
elif test > res
|
||||||
|
print('This number is too large.')
|
||||||
|
elif test < res
|
||||||
|
print('This number is too small.')
|
||||||
|
end
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
if test == res
|
||||||
|
print('You win!')
|
||||||
|
else
|
||||||
|
print('You failed, the correct answer is', res)
|
||||||
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
import json
|
||||||
|
print(json.load('{"key": "value"}'))
|
||||||
|
print(json.dump({'test key': nil}))
|
||||||
|
print(json.dump({'key1': nil, 45: true}, 'format'))
|
|
@ -0,0 +1,8 @@
|
||||||
|
# simple lambda example
|
||||||
|
print((/a b c-> a * b + c)(2, 3, 4))
|
||||||
|
|
||||||
|
# Y-Combinator and factorial functions
|
||||||
|
Y = /f-> (/x-> f(/n-> x(x)(n)))(/x-> f(/n-> x(x)(n)))
|
||||||
|
F = /f-> /x-> x ? f(x - 1) * x : 1
|
||||||
|
fact = Y(F)
|
||||||
|
print('fact(10) == ' .. fact(10))
|
|
@ -0,0 +1,16 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
def scandir(path)
|
||||||
|
print('path: ' + path)
|
||||||
|
for name : os.listdir(path)
|
||||||
|
var fullname = os.path.join(path, name)
|
||||||
|
if os.path.isfile(fullname)
|
||||||
|
print('file: ' + fullname)
|
||||||
|
else
|
||||||
|
print('path: ' + fullname)
|
||||||
|
scandir(fullname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scandir('.')
|
|
@ -0,0 +1,42 @@
|
||||||
|
def qsort(data)
|
||||||
|
# do once sort
|
||||||
|
def once(left, right)
|
||||||
|
var pivot = data[left] # use the 0th value as the pivot
|
||||||
|
while left < right # check if sort is complete
|
||||||
|
# put the value less than the pivot to the left
|
||||||
|
while left < right && data[right] >= pivot
|
||||||
|
right -= 1 # skip values greater than pivot
|
||||||
|
end
|
||||||
|
data[left] = data[right]
|
||||||
|
# put the value greater than the pivot on the right
|
||||||
|
while left < right && data[left] <= pivot
|
||||||
|
left += 1 # skip values less than pivot
|
||||||
|
end
|
||||||
|
data[right] = data[left]
|
||||||
|
end
|
||||||
|
# now we have the index of the pivot, store it
|
||||||
|
data[left] = pivot
|
||||||
|
return left # return the index of the pivot
|
||||||
|
end
|
||||||
|
# recursive quick sort algorithm
|
||||||
|
def _sort(left, right)
|
||||||
|
if left < right # executed when the array is not empty
|
||||||
|
var index = once(left, right) # get index of pivot for divide and conquer
|
||||||
|
_sort(left, index - 1) # sort the data on the left
|
||||||
|
_sort(index + 1, right) # sort the data on the right
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# start quick sort
|
||||||
|
_sort(0, data.size() - 1)
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
import time, math
|
||||||
|
math.srand(time.time()) # sse system time as a random seed
|
||||||
|
data = []
|
||||||
|
# put 20 random numbers into the array
|
||||||
|
for i : 1 .. 20
|
||||||
|
data.push(math.rand() % 100)
|
||||||
|
end
|
||||||
|
# sort and print
|
||||||
|
print(qsort(data))
|
|
@ -0,0 +1,61 @@
|
||||||
|
do
|
||||||
|
def ismult(msg)
|
||||||
|
import string
|
||||||
|
return string.split(msg, -5)[1] == '\'EOS\''
|
||||||
|
end
|
||||||
|
|
||||||
|
def multline(src, msg)
|
||||||
|
if !ismult(msg)
|
||||||
|
print('syntax_error: ' + msg)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
while true
|
||||||
|
try
|
||||||
|
src += '\n' + input('>> ')
|
||||||
|
return compile(src)
|
||||||
|
except 'syntax_error' as e, m
|
||||||
|
if !ismult(m)
|
||||||
|
print('syntax_error: ' + m)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse()
|
||||||
|
var fun, src = input('> ')
|
||||||
|
try
|
||||||
|
fun = compile('return (' + src + ')')
|
||||||
|
except 'syntax_error' as e, m
|
||||||
|
try
|
||||||
|
fun = compile(src)
|
||||||
|
except 'syntax_error' as e, m
|
||||||
|
fun = multline(src, m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return fun
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(fun)
|
||||||
|
try
|
||||||
|
var res = fun()
|
||||||
|
if res print(res) end
|
||||||
|
except .. as e, m
|
||||||
|
import debug
|
||||||
|
print(e .. ': ' .. m)
|
||||||
|
debug.traceback()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def repl()
|
||||||
|
while true
|
||||||
|
var fun = parse()
|
||||||
|
if fun != nil
|
||||||
|
run(fun)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Berry Berry REPL!")
|
||||||
|
repl()
|
||||||
|
end
|
|
@ -0,0 +1,32 @@
|
||||||
|
s = "This is a long string test. 0123456789 abcdefg ABCDEFG"
|
||||||
|
print(s)
|
||||||
|
|
||||||
|
a = .5
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
import string as s
|
||||||
|
|
||||||
|
print(s.hex(0x45678ABCD, 16))
|
||||||
|
|
||||||
|
def bin(x, num)
|
||||||
|
assert(type(x) == 'int', 'the type of \'x\' must be integer')
|
||||||
|
# test the 'x' bits
|
||||||
|
var bits = 1
|
||||||
|
for i : 0 .. 62
|
||||||
|
if x & (1 << 63 - i)
|
||||||
|
bits = 64 - i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if type(num) == 'int' && num > 0 && num <= 64
|
||||||
|
bits = bits < num ? num : bits
|
||||||
|
end
|
||||||
|
var result = ''
|
||||||
|
bits -= 1
|
||||||
|
for i : 0 .. bits
|
||||||
|
result += x & (1 << (bits - i)) ? '1' : '0'
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
print(bin(33))
|
|
@ -0,0 +1,7 @@
|
||||||
|
import string
|
||||||
|
|
||||||
|
print(string.format('%.3d', 12))
|
||||||
|
print(string.format('%.3f', 12))
|
||||||
|
print(string.format('%20.7f', 14.5))
|
||||||
|
print(string.format('-- %-40s ---', 'this is a string format test'))
|
||||||
|
print(string.format('-- %40s ---', 'this is a string format test'))
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name":"Berry",
|
||||||
|
"description":"Berry scripting language for Tasmota32",
|
||||||
|
"keywords":"berry, script",
|
||||||
|
"authors":
|
||||||
|
{
|
||||||
|
"name": "Guan Wenliang <skiars@qq.com>, ",
|
||||||
|
"maintainer": true
|
||||||
|
},
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Skiars/berry"
|
||||||
|
},
|
||||||
|
"version": "7.0",
|
||||||
|
"license": "MIT License",
|
||||||
|
"frameworks": "*",
|
||||||
|
"platforms": "*",
|
||||||
|
"build": {
|
||||||
|
"srcFilter": [
|
||||||
|
"+<*.c>",
|
||||||
|
"+<../default/*.c>",
|
||||||
|
"+<../default/*.cpp>",
|
||||||
|
"+<../default/*.hpp>",
|
||||||
|
"+<*.cpp>",
|
||||||
|
"+<*.h>"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue