Initialize git
This commit is contained in:
2850
hal/esp32/app_hal.cpp
Normal file
2850
hal/esp32/app_hal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
88
hal/esp32/app_hal.h
Normal file
88
hal/esp32/app_hal.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
#ifdef NO_WATCHFACES
|
||||
|
||||
|
||||
#elif ESPS3_1_69
|
||||
// 240x280 watchfaces
|
||||
|
||||
#define ENABLE_FACE_174 // (174)
|
||||
// #define ENABLE_FACE_228 // (228)
|
||||
#define ENABLE_FACE_1041 // (1041)
|
||||
// #define ENABLE_FACE_1167 // (1167)
|
||||
// #define ENABLE_FACE_1169 // (1169)
|
||||
// #define ENABLE_FACE_2051 // (2051)
|
||||
#define ENABLE_FACE_2151 // (2151)
|
||||
// #define ENABLE_FACE_3589 // (3589)
|
||||
|
||||
|
||||
#elif defined(VIEWE_SMARTRING) || defined(VIEWE_KNOB_15) || defined(ESPS3_1_75) || defined(ESPS3_2_06)
|
||||
|
||||
#define ENABLE_FACE_756_2_466 // (Red)
|
||||
#define ENABLE_FACE_RADAR_466 // (Radar)
|
||||
#define ENABLE_FACE_75_2 // (Analog)
|
||||
#define ENABLE_FACE_34_2 // (Shadow)
|
||||
|
||||
#else
|
||||
// 240x240 watchfaces
|
||||
|
||||
// #define ENABLE_FACE_ELECROW // elecrow analog
|
||||
// #define ENABLE_FACE_34_2 // (Shadow)
|
||||
// #define ENABLE_FACE_75_2 // (Analog)
|
||||
// #define ENABLE_FACE_79_2 // (Blue)
|
||||
// #define ENABLE_FACE_116_2 // (Outline)
|
||||
// #define ENABLE_FACE_756_2 // (Red)
|
||||
// #define ENABLE_FACE_B_W_RESIZED // (B & W)
|
||||
// #define ENABLE_FACE_KENYA // (Kenya)
|
||||
// #define ENABLE_FACE_PIXEL_RESIZED // (Pixel)
|
||||
// #define ENABLE_FACE_RADAR // (Radar)
|
||||
// #define ENABLE_FACE_SMART_RESIZED // (Smart)
|
||||
// #define ENABLE_FACE_TIX_RESIZED // (Tix)
|
||||
// #define ENABLE_FACE_WFB_RESIZED // (WFB)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ESPS3_1_69) || defined(ESPS3_1_28) || defined(VIEWE_SMARTRING) || defined(ESPS3_1_75) || defined(ESPS3_2_06)
|
||||
#define ENABLE_APP_QMI8658C
|
||||
#define ENABLE_APP_ATTITUDE
|
||||
#endif
|
||||
|
||||
#if defined(ELECROW_C3)
|
||||
#define ENABLE_RTC
|
||||
#endif
|
||||
|
||||
#if defined(M5_STACK_DIAL) || defined(VIEWE_KNOB_15)
|
||||
#define ENABLE_APP_RANGE
|
||||
#endif
|
||||
|
||||
// #define ENABLE_APP_CALENDAR
|
||||
// #define ENABLE_APP_SAMPLE
|
||||
// #define ENABLE_GAME_TASK
|
||||
// #define ENABLE_GAME_RACING
|
||||
|
||||
// #define ENABLE_GAME_SIMON
|
||||
|
||||
// #define ENABLE_APP_NAVIGATION
|
||||
// #define ENABLE_APP_CONTACTS
|
||||
#define ENABLE_APP_TIMER
|
||||
#define ENABLE_APP_NOTES
|
||||
#define ENABLE_WIFI_SERVER
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void hal_setup(void);
|
||||
void hal_loop(void);
|
||||
|
||||
|
||||
void vibratePin(bool state);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*DRIVER_H*/
|
||||
106
hal/esp32/displays/generic.hpp
Normal file
106
hal/esp32/displays/generic.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define LGFX_USE_V1
|
||||
#include "Arduino.h"
|
||||
#include <LovyanGFX.hpp>
|
||||
|
||||
#include "pins.h"
|
||||
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
|
||||
lgfx::Panel_GC9A01 _panel_instance;
|
||||
lgfx::Light_PWM _light_instance;
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
lgfx::Touch_CST816S _touch_instance;
|
||||
|
||||
public:
|
||||
LGFX(void)
|
||||
{
|
||||
{
|
||||
auto cfg = _bus_instance.config();
|
||||
|
||||
// SPI bus settings
|
||||
cfg.spi_host = SPI; // Select the SPI to use ESP32-S2,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
|
||||
// * Due to the ESP-IDF version upgrade, VSPI_HOST, The HSPI_HOST specification is deprecated, so if you get an error, use SPI2_HOST or SPI3_HOST instead.
|
||||
cfg.spi_mode = 0; // Set SPI communication mode (0 ~ 3)
|
||||
cfg.freq_write = 80000000; // SPI time (up to 80MHz, four or five inputs divided by 80MHz to get an integer)
|
||||
cfg.freq_read = 20000000; // SPI time when connected cfg.spi_3wire = true; // Set true if receiving is done via MOSI pin
|
||||
cfg.use_lock = true; // Usage lock time setting true
|
||||
cfg.dma_channel = SPI_DMA_CH_AUTO; // Set the DMA channel to use (0=DMA not used / 1=1ch / 2=ch / SPI_DMA_CH_AUTO=automatic setting) // * Due to the ESP-IDF version upgrade, SPI_DMA_CH_AUTO (automatic setting) is now recommended for the DMA channel. Specifying 1ch or 2ch is no longer recommended.
|
||||
cfg.pin_sclk = SCLK; // Set the SPI SCLK pin number
|
||||
cfg.pin_mosi = MOSI; // Set the SPI CLK pin number
|
||||
cfg.pin_miso = MISO; // Set the SPI MISO pin number (-1 = disable)
|
||||
cfg.pin_dc = DC; // Set the SPI D/C pin number (-1 = disable)
|
||||
_bus_instance.config(cfg); // Reflect the setting value to the bus.
|
||||
_panel_instance.setBus(&_bus_instance); // Set the bus to the panel.
|
||||
}
|
||||
|
||||
{ // Set the display panel control.
|
||||
auto cfg = _panel_instance.config(); // Get the structure for display panel settings.
|
||||
|
||||
cfg.pin_cs = CS; // Pin number to which CS is connected (-1 = disable)
|
||||
cfg.pin_rst = RST; // Pin number to which RST is connected (-1 = disable)
|
||||
cfg.pin_busy = -1; // Pin number to which BUSY is connected (-1 = disable)
|
||||
|
||||
/* The following settings are set to general initial values for each panel, so try commenting out any items you are unsure of. */
|
||||
|
||||
cfg.memory_width = SCREEN_WIDTH; // Maximum width supported by driver IC
|
||||
cfg.memory_height = SCREEN_HEIGHT; // Maximum height supported by driver IC
|
||||
cfg.panel_width = SCREEN_WIDTH; // Actual displayable width
|
||||
cfg.panel_height = SCREEN_HEIGHT; // Actual displayable height
|
||||
cfg.offset_x = OFFSET_X; // Panel offset in X direction
|
||||
cfg.offset_y = OFFSET_Y; // Panel offset in Y direction
|
||||
cfg.offset_rotation = 0; // Value 0~7 in rotation direction (4~7 is inverted)
|
||||
cfg.dummy_read_pixel = 8; // Virtual number of positions read before reading image
|
||||
cfg.dummy_read_bits = 1; // The number of imaginary words other than the image element
|
||||
cfg.readable = false; // As long as the number of acquisitions is as high as possible, the setting is true
|
||||
cfg.invert = true; // As a result, the brightness and darkness of the face plate is reversed, and the setting is true
|
||||
cfg.rgb_order = RGB_ORDER; // As a result, the red color and the blue color are replaced on the face plate, and the setting is true
|
||||
cfg.dlen_16bit = false; // From 16th position to 16th position, the length of the number of transfers is set to true
|
||||
cfg.bus_shared = false; // How to use drawJpgFile (e.g. summary control)
|
||||
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
{ // Set backlight control. (delete if not necessary)
|
||||
|
||||
auto cfg = _light_instance.config(); // Get the structure for backlight configuration.
|
||||
|
||||
cfg.pin_bl = BL; // pin number to which the backlight is connected
|
||||
cfg.invert = false; // true to invert backlight brightness
|
||||
cfg.freq = 44100; // backlight PWM frequency
|
||||
cfg.pwm_channel = 1; // PWM channel number to use
|
||||
|
||||
_light_instance.config(cfg);
|
||||
_panel_instance.setLight(&_light_instance); // Sets the backlight to the panel.
|
||||
}
|
||||
|
||||
{ // Sets touchscreen control. (Delete if not needed)
|
||||
|
||||
auto cfg = _touch_instance.config();
|
||||
cfg.x_min = 0; // Minimum X value obtained from touch screen (raw value)
|
||||
cfg.x_max = SCREEN_WIDTH; // Maximum X value obtained from touch screen (raw value)
|
||||
cfg.y_min = 0; // Minimum Y value obtained from touch screen (raw value)
|
||||
cfg.y_max = SCREEN_HEIGHT; // Maximum Y value obtained from touch screen (raw value)
|
||||
cfg.pin_int = TP_INT; // Pin number to which INT is connected
|
||||
cfg.pin_rst = TP_RST;
|
||||
cfg.bus_shared = true; // Set true if using a common bus with the screen
|
||||
cfg.offset_rotation = 0; // Adjust if display and touch orientation do not match. Set to a value between 0 and 7
|
||||
|
||||
cfg.i2c_port = 0; // Select the I2C to use (0 or 1)
|
||||
cfg.i2c_addr = 0x15; // I2C device address number
|
||||
cfg.pin_sda = I2C_SDA; // Pin number to which SDA is connected
|
||||
cfg.pin_scl = I2C_SCL; // Pin number to which SCL is connected
|
||||
cfg.freq = 400000; // Set the I2C clock
|
||||
_touch_instance.config(cfg);
|
||||
_panel_instance.setTouch(&_touch_instance); // Set the touch screen to the panel.
|
||||
}
|
||||
|
||||
setPanel(&_panel_instance); // Set the panel to use.
|
||||
}
|
||||
};
|
||||
|
||||
LGFX tft;
|
||||
294
hal/esp32/displays/pins.h
Normal file
294
hal/esp32/displays/pins.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Felix Biego
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
______________ _____
|
||||
___ __/___ /_ ___(_)_____ _______ _______
|
||||
__ /_ __ __ \__ / _ _ \__ __ `/_ __ \
|
||||
_ __/ _ /_/ /_ / / __/_ /_/ / / /_/ /
|
||||
/_/ /_.___/ /_/ \___/ _\__, / \____/
|
||||
/____/
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef ELECROW_C3
|
||||
|
||||
// screen configs
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 240
|
||||
#define OFFSET_X 0
|
||||
#define OFFSET_Y 0
|
||||
#define RGB_ORDER false
|
||||
|
||||
// touch
|
||||
#define I2C_SDA 4
|
||||
#define I2C_SCL 5
|
||||
#define TP_INT 0
|
||||
#define TP_RST -1
|
||||
|
||||
// display
|
||||
#define SPI SPI2_HOST
|
||||
|
||||
#define SCLK 6
|
||||
#define MOSI 7
|
||||
#define MISO -1
|
||||
#define DC 2
|
||||
#define CS 10
|
||||
#define RST -1
|
||||
|
||||
#define BL -1 // unused (connected on IO extender)
|
||||
#define VIBRATION_PIN 0 // dummy (connected on IO extender)
|
||||
|
||||
#define BUZZER_PIN 3
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
#elif ESPC3
|
||||
|
||||
// screen configs
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 240
|
||||
#define OFFSET_X 0
|
||||
#define OFFSET_Y 0
|
||||
#define RGB_ORDER false
|
||||
|
||||
// touch
|
||||
#define I2C_SDA 4
|
||||
#define I2C_SCL 5
|
||||
#define TP_INT 0
|
||||
#define TP_RST 1
|
||||
|
||||
// display
|
||||
#define SPI SPI2_HOST
|
||||
|
||||
#define SCLK 6
|
||||
#define MOSI 7
|
||||
#define MISO -1
|
||||
#define DC 2
|
||||
#define CS 10
|
||||
#define RST -1
|
||||
|
||||
#define BL 3
|
||||
|
||||
#define BUZZER_PIN -1
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
#elif ESPS3_1_28
|
||||
|
||||
// screen configs
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 240
|
||||
#define OFFSET_X 0
|
||||
#define OFFSET_Y 0
|
||||
#define RGB_ORDER false
|
||||
|
||||
// touch
|
||||
#define I2C_SDA 6
|
||||
#define I2C_SCL 7
|
||||
#define TP_INT 5
|
||||
#define TP_RST 13
|
||||
|
||||
// display
|
||||
#define SPI SPI2_HOST
|
||||
|
||||
#define SCLK 10
|
||||
#define MOSI 11
|
||||
#define MISO 12
|
||||
#define DC 8
|
||||
#define CS 9
|
||||
#define RST 14
|
||||
|
||||
#define BL 2
|
||||
|
||||
#define BUZZER_PIN -1
|
||||
|
||||
#define MAX_FILE_OPEN 50
|
||||
|
||||
#elif ESPS3_1_69
|
||||
|
||||
// screen configs
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 280
|
||||
#define OFFSET_X 0
|
||||
#define OFFSET_Y 20
|
||||
#define RGB_ORDER true
|
||||
|
||||
// touch
|
||||
#define I2C_SDA 11
|
||||
#define I2C_SCL 10
|
||||
#define TP_INT 14
|
||||
#define TP_RST 13
|
||||
|
||||
// display
|
||||
#define SPI SPI2_HOST
|
||||
|
||||
#define SCLK 6
|
||||
#define MOSI 7
|
||||
#define MISO -1
|
||||
#define DC 4
|
||||
#define CS 5
|
||||
#define RST 8
|
||||
|
||||
#define BL 15
|
||||
|
||||
#define BUZZER_PIN -1 //33
|
||||
|
||||
#define MAX_FILE_OPEN 20
|
||||
|
||||
#elif ESPS3_2_06
|
||||
|
||||
#define SCREEN_WIDTH 410
|
||||
#define SCREEN_HEIGHT 502
|
||||
|
||||
#define LCD_CS 12
|
||||
#define LCD_SCK 11
|
||||
#define LCD_SD0 4
|
||||
#define LCD_SD1 5
|
||||
#define LCD_SD2 6
|
||||
#define LCD_SD3 7
|
||||
#define LCD_RST 8
|
||||
|
||||
#define TOUCH_SDA 15
|
||||
#define TOUCH_SCL 14
|
||||
#define TOUCH_RST 9
|
||||
#define TOUCH_IRQ 38
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
#elif M5_STACK_DIAL
|
||||
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 240
|
||||
|
||||
#define BUZZER_PIN 3
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
#elif ESPS3_1_75
|
||||
|
||||
#define SCREEN_WIDTH 466
|
||||
#define SCREEN_HEIGHT 466
|
||||
|
||||
#define LCD_CS 12
|
||||
#define LCD_SCK 38
|
||||
#define LCD_SD0 4
|
||||
#define LCD_SD1 5
|
||||
#define LCD_SD2 6
|
||||
#define LCD_SD3 7
|
||||
#define LCD_RST 39
|
||||
|
||||
#define TOUCH_SDA 15
|
||||
#define TOUCH_SCL 14
|
||||
#define TOUCH_RST 40
|
||||
#define TOUCH_IRQ 11
|
||||
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
|
||||
#elif M5_STACK_DIAL
|
||||
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 240
|
||||
|
||||
#define BUZZER_PIN 3
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
#elif VIEWE_SMARTRING
|
||||
#define SCREEN_WIDTH 466
|
||||
#define SCREEN_HEIGHT 466
|
||||
|
||||
#define LCD_CS 7
|
||||
#define LCD_SCK 13
|
||||
#define LCD_SD0 12
|
||||
#define LCD_SD1 8
|
||||
#define LCD_SD2 14
|
||||
#define LCD_SD3 9
|
||||
#define LCD_RST 11
|
||||
|
||||
#define TOUCH_SDA 41
|
||||
#define TOUCH_SCL 45
|
||||
#define TOUCH_RST 46
|
||||
#define TOUCH_IRQ 42
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
#elif VIEWE_KNOB_15
|
||||
#define SCREEN_WIDTH 466
|
||||
#define SCREEN_HEIGHT 466
|
||||
|
||||
#define LCD_CS 12
|
||||
#define LCD_SCK 10
|
||||
#define LCD_SD0 13
|
||||
#define LCD_SD1 11
|
||||
#define LCD_SD2 14
|
||||
#define LCD_SD3 9
|
||||
#define LCD_RST 8
|
||||
#define LCD_EN 17
|
||||
|
||||
#define TOUCH_SDA 1
|
||||
#define TOUCH_SCL 3
|
||||
#define TOUCH_RST 2
|
||||
#define TOUCH_IRQ 4
|
||||
|
||||
#define ENCODER_A 6
|
||||
#define ENCODER_B 5
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
|
||||
#else
|
||||
|
||||
// screen configs
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 240
|
||||
#define OFFSET_X 0
|
||||
#define OFFSET_Y 0
|
||||
#define RGB_ORDER false
|
||||
|
||||
// touch
|
||||
#define I2C_SDA 21
|
||||
#define I2C_SCL 22
|
||||
#define TP_INT 14
|
||||
#define TP_RST 5
|
||||
|
||||
// display
|
||||
#define SPI VSPI_HOST
|
||||
|
||||
#define SCLK 18
|
||||
#define MOSI 23
|
||||
#define MISO -1
|
||||
#define DC 4
|
||||
#define CS 15
|
||||
#define RST 13
|
||||
|
||||
#define BL 2
|
||||
|
||||
#define BUZZER_PIN -1
|
||||
|
||||
#define MAX_FILE_OPEN 10
|
||||
|
||||
#endif
|
||||
123
hal/esp32/displays/viewe.hpp
Normal file
123
hal/esp32/displays/viewe.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "Arduino_GFX_Library.h"
|
||||
#ifdef ESPS3_2_06
|
||||
#include "TouchDrvFT6X36.hpp"
|
||||
#else
|
||||
#include "TouchDrvCSTXXX.hpp"
|
||||
#endif
|
||||
#include "pins.h"
|
||||
|
||||
#define TFT_BLACK 0x00000
|
||||
|
||||
class DisplayWrapper
|
||||
{
|
||||
public:
|
||||
Arduino_GFX *gfx;
|
||||
|
||||
#ifdef ESPS3_2_06
|
||||
TouchDrvFT6X36 touch;
|
||||
#else
|
||||
TouchDrvCSTXXX touch;
|
||||
#endif
|
||||
|
||||
DisplayWrapper()
|
||||
{
|
||||
|
||||
static Arduino_DataBus *bus = new Arduino_ESP32QSPI(
|
||||
LCD_CS /* CS */, LCD_SCK /* SCK */, LCD_SD0 /* SDIO0 */, LCD_SD1 /* SDIO1 */,
|
||||
LCD_SD2 /* SDIO2 */, LCD_SD3 /* SDIO3 */);
|
||||
|
||||
gfx = new Arduino_CO5300(
|
||||
bus,
|
||||
LCD_RST /* RST */,
|
||||
0 /* rotation */,
|
||||
false /* IPS */,
|
||||
SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT,
|
||||
#ifdef ESPS3_2_06
|
||||
22 /* col_offset1 */,
|
||||
#else
|
||||
6 /* col_offset1 */,
|
||||
#endif
|
||||
0 /* row_offset1 */,
|
||||
0 /* col_offset2 */,
|
||||
0 /* row_offset2 */
|
||||
);
|
||||
}
|
||||
|
||||
bool init(void)
|
||||
{
|
||||
#ifdef LCD_EN
|
||||
pinMode(LCD_EN, OUTPUT);
|
||||
digitalWrite(LCD_EN, HIGH);
|
||||
#endif
|
||||
bool state = gfx->begin();
|
||||
touch.setPins(TOUCH_RST, TOUCH_IRQ);
|
||||
|
||||
#if defined(ESPS3_1_75)
|
||||
touch.begin(Wire, 0x5A, TOUCH_SDA, TOUCH_SCL);
|
||||
touch.setMaxCoordinates(466, 466);
|
||||
touch.setMirrorXY(true, true);
|
||||
#elif defined(ESPS3_2_06)
|
||||
touch.begin(Wire, 0x38, TOUCH_SDA, TOUCH_SCL);
|
||||
#else
|
||||
touch.begin(Wire, 0x15, TOUCH_SDA, TOUCH_SCL);
|
||||
#endif
|
||||
return state;
|
||||
}
|
||||
|
||||
void initDMA(void) {}
|
||||
|
||||
void fillScreen(uint16_t color)
|
||||
{
|
||||
gfx->fillScreen(color);
|
||||
}
|
||||
|
||||
void setRotation(uint8_t rotation)
|
||||
{
|
||||
// gfx->setRotation(rotation); // Not supported in CO5300
|
||||
}
|
||||
|
||||
void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
|
||||
{
|
||||
gfx->draw16bitBeRGBBitmap(x, y, data, w, h);
|
||||
}
|
||||
|
||||
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
|
||||
{
|
||||
gfx->draw16bitBeRGBBitmap(x, y, data, w, h);
|
||||
}
|
||||
|
||||
void startWrite(void) {}
|
||||
|
||||
uint32_t getStartCount(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void endWrite(void) {}
|
||||
|
||||
void setBrightness(uint8_t brightness)
|
||||
{
|
||||
((Arduino_CO5300 *)gfx)->setBrightness(brightness);
|
||||
}
|
||||
|
||||
void writePixel(int32_t x, int32_t y, const uint16_t color)
|
||||
{
|
||||
gfx->writePixel(x, y, color);
|
||||
}
|
||||
|
||||
bool getTouch(uint16_t *x, uint16_t *y)
|
||||
{
|
||||
int16_t x_arr[5], y_arr[5];
|
||||
uint8_t touched = touch.getPoint(x_arr, y_arr, touch.getSupportTouchPoint());
|
||||
*x = x_arr[0];
|
||||
*y = y_arr[0];
|
||||
return touched;
|
||||
}
|
||||
};
|
||||
|
||||
DisplayWrapper tft;
|
||||
333
hal/esp32/feedback.cpp
Normal file
333
hal/esp32/feedback.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "feedback.h"
|
||||
#include "app_hal.h"
|
||||
#include "displays/pins.h"
|
||||
|
||||
// A struct to hold a sequence of notes
|
||||
struct NoteSequence
|
||||
{
|
||||
Note notes[MAX_NOTES_PER_SEQUENCE];
|
||||
int count;
|
||||
int repeat;
|
||||
};
|
||||
|
||||
struct VibPattern
|
||||
{
|
||||
Vibration steps[MAX_VIB_PATTERN_LENGTH];
|
||||
int count;
|
||||
};
|
||||
|
||||
QueueHandle_t noteQueue;
|
||||
TaskHandle_t toneTaskHandle = nullptr;
|
||||
volatile bool playing = false;
|
||||
volatile ToneType currentToneType = T_USER;
|
||||
volatile bool forceInterrupt = false;
|
||||
|
||||
QueueHandle_t vibQueue;
|
||||
TaskHandle_t vibTaskHandle = nullptr;
|
||||
volatile bool vibrating = false;
|
||||
|
||||
Note tone_melody[] = {
|
||||
{440, 300}, // A4
|
||||
{0, 150}, // Rest
|
||||
{494, 300}, // B4
|
||||
{0, 150}, // Rest
|
||||
{523, 300}, // C5
|
||||
{0, 300}, // Longer rest
|
||||
{587, 300} // D5
|
||||
};
|
||||
|
||||
Note tone_startup[] = {
|
||||
{TONE_EN * 2, 170},
|
||||
{TONE_FS * 2, 170},
|
||||
{TONE_GN * 2, 170}};
|
||||
|
||||
// 📩 Notification Received (Double Beep)
|
||||
Note tone_notification[] = {
|
||||
{1000, 100},
|
||||
{0, 100},
|
||||
{1200, 100},
|
||||
};
|
||||
|
||||
// 📞 Call Received (Melody)
|
||||
Note tone_call[] = {
|
||||
{880, 200},
|
||||
{988, 200},
|
||||
{1046, 200},
|
||||
{0, 100},
|
||||
{1046, 300},
|
||||
{880, 200},
|
||||
{988, 200},
|
||||
{0, 200},
|
||||
};
|
||||
|
||||
// ⏰ Alarm Ring
|
||||
Note tone_alarm[] = {
|
||||
{1500, 150},
|
||||
{0, 100},
|
||||
{1500, 150},
|
||||
{0, 100},
|
||||
{1500, 150},
|
||||
{0, 100},
|
||||
{2000, 300},
|
||||
};
|
||||
|
||||
Note tone_off[] = {
|
||||
{0, 50}};
|
||||
|
||||
// ⏲️ Timer Ended
|
||||
Note tone_timer[] = {
|
||||
{880, 200},
|
||||
{0, 100},
|
||||
{660, 200},
|
||||
{0, 100},
|
||||
{880, 200},
|
||||
{0, 100},
|
||||
};
|
||||
|
||||
// 🔘 Button Press
|
||||
Note tone_button[] = {
|
||||
{1000, 50},
|
||||
};
|
||||
|
||||
// 🎮 Simon Says - Intro
|
||||
Note tone_simonsays_intro[] = {
|
||||
{659, 150},
|
||||
{784, 150},
|
||||
{987, 150},
|
||||
{1319, 200},
|
||||
};
|
||||
|
||||
// 🎮 Simon Says - Game Over
|
||||
Note tone_simonsays_gameover[] = {
|
||||
{659, 300},
|
||||
{622, 300},
|
||||
{587, 300},
|
||||
{554, 400},
|
||||
};
|
||||
|
||||
Vibration v_notif[] = {
|
||||
{true, 100}, // ON for 200ms
|
||||
{false, 50}, // OFF for 100ms
|
||||
};
|
||||
|
||||
Vibration pattern[] = {
|
||||
{true, 200}, // ON for 200ms
|
||||
{false, 100}, // OFF for 100ms
|
||||
{true, 300}, // ON for 300ms
|
||||
{false, 200}, // OFF for 200ms
|
||||
};
|
||||
|
||||
void toneTask(void *param)
|
||||
{
|
||||
#if defined(BUZZER_PIN) && (BUZZER_PIN != -1)
|
||||
|
||||
NoteSequence sequence;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (xQueueReceive(noteQueue, &sequence, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
playing = true;
|
||||
|
||||
ledcAttachPin(BUZZER_PIN, BUZZER_CHANNEL);
|
||||
|
||||
if (sequence.repeat == 0)
|
||||
{
|
||||
sequence.repeat = 1;
|
||||
}
|
||||
|
||||
for (int r = 0; r < sequence.repeat; r++)
|
||||
{
|
||||
for (int n = 0; n < sequence.count; n++)
|
||||
{
|
||||
if (forceInterrupt)
|
||||
{
|
||||
forceInterrupt = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int pitch = sequence.notes[n].pitch;
|
||||
int duration = sequence.notes[n].duration;
|
||||
|
||||
if (pitch > 0)
|
||||
{
|
||||
ledcWriteTone(BUZZER_CHANNEL, pitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
ledcWriteTone(BUZZER_CHANNEL, 0); // Rest
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(duration));
|
||||
}
|
||||
}
|
||||
|
||||
ledcDetachPin(BUZZER_PIN);
|
||||
|
||||
playing = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void vibrationTask(void *param)
|
||||
{
|
||||
#if defined(VIBRATION_PIN) && (VIBRATION_PIN != -1)
|
||||
#ifndef ELECROW_C3
|
||||
pinMode(VIBRATION_PIN, OUTPUT);
|
||||
#endif
|
||||
VibPattern pattern;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (xQueueReceive(vibQueue, &pattern, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
vibrating = true;
|
||||
|
||||
#ifdef ELECROW_C3
|
||||
vibratePin(true);
|
||||
for (int i = 0; i < pattern.count; i++)
|
||||
{
|
||||
delay(pattern.steps[i].duration);
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < pattern.count; i++)
|
||||
{
|
||||
vibratePin(pattern.steps[i].on);
|
||||
delay(pattern.steps[i].duration);
|
||||
}
|
||||
#endif
|
||||
|
||||
vibratePin(false);
|
||||
vibrating = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void startToneSystem()
|
||||
{
|
||||
#if defined(BUZZER_PIN) && (BUZZER_PIN != -1)
|
||||
|
||||
if (!noteQueue)
|
||||
{
|
||||
noteQueue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(NoteSequence));
|
||||
}
|
||||
if (!toneTaskHandle)
|
||||
{
|
||||
xTaskCreatePinnedToCore(toneTask, "toneTask", 2048, nullptr, 1, &toneTaskHandle, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void startVibrationSystem()
|
||||
{
|
||||
#if defined(VIBRATION_PIN) && (VIBRATION_PIN != -1)
|
||||
if (!vibQueue)
|
||||
{
|
||||
vibQueue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(VibPattern));
|
||||
}
|
||||
if (!vibTaskHandle)
|
||||
{
|
||||
xTaskCreatePinnedToCore(vibrationTask, "vibrationTask", 2048, nullptr, 1, &vibTaskHandle, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void feedbackTone(Note *notes, int count, ToneType type, int repeat)
|
||||
{
|
||||
#if defined(BUZZER_PIN) && (BUZZER_PIN != -1)
|
||||
if (check_alert_state(ALERT_SOUND))
|
||||
{
|
||||
if (!noteQueue)
|
||||
startToneSystem();
|
||||
|
||||
if (count > MAX_NOTES_PER_SEQUENCE)
|
||||
count = MAX_NOTES_PER_SEQUENCE;
|
||||
|
||||
if (playing && currentToneType >= type)
|
||||
{
|
||||
// If the current tone is of the same or higher priority, reset the queue
|
||||
forceInterrupt = true;
|
||||
xQueueReset(noteQueue);
|
||||
}
|
||||
|
||||
NoteSequence sequence;
|
||||
sequence.count = count;
|
||||
sequence.repeat = repeat;
|
||||
memcpy(sequence.notes, notes, count * sizeof(Note));
|
||||
|
||||
xQueueSend(noteQueue, &sequence, 0);
|
||||
currentToneType = type;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void feedbackVibrate(Vibration *steps, int count, bool force)
|
||||
{
|
||||
#if defined(VIBRATION_PIN) && (VIBRATION_PIN != -1)
|
||||
if (check_alert_state(ALERT_VIBRATE))
|
||||
{
|
||||
if (!vibQueue)
|
||||
startVibrationSystem();
|
||||
|
||||
if (count > MAX_VIB_PATTERN_LENGTH)
|
||||
count = MAX_VIB_PATTERN_LENGTH;
|
||||
|
||||
if (force && vibrating)
|
||||
{
|
||||
xQueueReset(vibQueue);
|
||||
}
|
||||
|
||||
VibPattern pattern;
|
||||
pattern.count = count;
|
||||
memcpy(pattern.steps, steps, count * sizeof(Vibration));
|
||||
|
||||
xQueueSend(vibQueue, &pattern, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void feedbackRun(ToneType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T_CALLS:
|
||||
feedbackTone(tone_call, 8, T_CALLS, 3);
|
||||
feedbackVibrate(pattern, 4, true);
|
||||
break;
|
||||
case T_NOTIFICATION:
|
||||
feedbackTone(tone_notification, 3, T_NOTIFICATION, 2);
|
||||
feedbackVibrate(v_notif, 2, true);
|
||||
break;
|
||||
case T_TIMER:
|
||||
feedbackTone(tone_alarm, 7, T_TIMER);
|
||||
feedbackVibrate(pattern, 4, true);
|
||||
break;
|
||||
case T_ALARM:
|
||||
feedbackTone(tone_timer, 6, T_TIMER, 3);
|
||||
feedbackVibrate(pattern, 4, true);
|
||||
break;
|
||||
case T_SYSTEM:
|
||||
feedbackTone(tone_button, 1, T_SYSTEM);
|
||||
feedbackVibrate(pattern, 2, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (check_alert_state(ALERT_SCREEN))
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T_CALLS:
|
||||
screen_on(50);
|
||||
break;
|
||||
default:
|
||||
screen_on();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
82
hal/esp32/feedback.h
Normal file
82
hal/esp32/feedback.h
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
|
||||
#ifndef FEEDBACK_H
|
||||
#define FEEDBACK_H
|
||||
|
||||
#define TONE_AN 220 // 440 Hz
|
||||
#define TONE_AS 233 // 466 Hz
|
||||
#define TONE_BN 247 // 493 Hz
|
||||
#define TONE_CN 261 // 523 Hz
|
||||
#define TONE_CS 277 // 554 Hz
|
||||
#define TONE_DN 294 // 588 Hz
|
||||
#define TONE_DS 311 // 622 Hz
|
||||
#define TONE_EN 330 // 658 Hz
|
||||
#define TONE_FN 349 // 698 Hz
|
||||
#define TONE_FS 370 // 740 Hz
|
||||
#define TONE_GN 392 // 784 Hz
|
||||
#define TONE_GS 415 // 830 Hz
|
||||
|
||||
#define BUZZER_CHANNEL 0
|
||||
|
||||
#define MAX_QUEUE_SIZE 8
|
||||
#define MAX_NOTES_PER_SEQUENCE 16
|
||||
|
||||
#define MAX_VIB_PATTERN_LENGTH 16
|
||||
|
||||
enum ToneType
|
||||
{
|
||||
T_ALARM = 0,
|
||||
T_TIMER,
|
||||
T_CALLS,
|
||||
T_NOTIFICATION,
|
||||
T_SYSTEM,
|
||||
T_USER
|
||||
};
|
||||
|
||||
struct Note
|
||||
{
|
||||
int pitch;
|
||||
int duration;
|
||||
};
|
||||
|
||||
struct Vibration
|
||||
{
|
||||
bool on;
|
||||
int duration;
|
||||
};
|
||||
|
||||
enum AlertType
|
||||
{
|
||||
ALERT_POPUP = 0x01,
|
||||
ALERT_SCREEN = 0x02,
|
||||
ALERT_SOUND = 0x04,
|
||||
ALERT_VIBRATE = 0x08
|
||||
};
|
||||
|
||||
extern Vibration pattern[];
|
||||
extern Vibration v_notif[];
|
||||
|
||||
extern Note tone_startup[];
|
||||
extern Note tone_off[];
|
||||
extern Note tone_notification[];
|
||||
extern Note tone_call[];
|
||||
extern Note tone_alarm[];
|
||||
extern Note tone_timer[];
|
||||
extern Note tone_button[];
|
||||
|
||||
extern Note tone_simonsays_intro[];
|
||||
extern Note tone_simonsays_gameover[];
|
||||
|
||||
void startToneSystem();
|
||||
void startVibrationSystem();
|
||||
|
||||
void feedbackTone(Note *notes, int count, ToneType type, int repeat = 0);
|
||||
void feedbackVibrate(Vibration *steps, int count, bool force = false);
|
||||
|
||||
void screen_on(long extra = 0);
|
||||
|
||||
void feedbackRun(ToneType type);
|
||||
|
||||
bool check_alert_state(AlertType type);
|
||||
|
||||
#endif
|
||||
355
hal/esp32/wifi_server.cpp
Normal file
355
hal/esp32/wifi_server.cpp
Normal file
@@ -0,0 +1,355 @@
|
||||
/**
|
||||
* @file wifi_server.cpp
|
||||
* @brief WiFi Access Point + HTTP WebServer for ESP32 Watch
|
||||
* Provides time sync and notes management via web interface
|
||||
*/
|
||||
|
||||
#include "app_hal.h"
|
||||
|
||||
#ifdef ENABLE_WIFI_SERVER
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <WebServer.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <ChronosESP32.h>
|
||||
#include "wifi_server.h"
|
||||
#include "../src/apps/notes/notes_storage.h"
|
||||
|
||||
/* WiFi AP Configuration */
|
||||
#define WIFI_SSID "ESP32-Watch"
|
||||
#define WIFI_PASS "12345678"
|
||||
|
||||
/* External references */
|
||||
extern ChronosESP32 watch;
|
||||
|
||||
static WebServer server(80);
|
||||
static bool serverRunning = false;
|
||||
|
||||
/* ──────────────────────────────────────────────
|
||||
* Embedded HTML Page (PROGMEM)
|
||||
* ────────────────────────────────────────────── */
|
||||
|
||||
static const char index_html[] PROGMEM = R"rawliteral(
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ESP32 Watch Manager</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0}
|
||||
body{font-family:'Segoe UI',system-ui,sans-serif;background:#0a0a1a;color:#e0e0e0;min-height:100vh;padding:16px}
|
||||
.container{max-width:600px;margin:0 auto}
|
||||
h1{text-align:center;color:#ffcc00;margin-bottom:24px;font-size:1.5em}
|
||||
h2{color:#ffcc00;margin-bottom:12px;font-size:1.1em;border-bottom:1px solid #333;padding-bottom:6px}
|
||||
.card{background:#1a1a2e;border-radius:12px;padding:16px;margin-bottom:16px}
|
||||
.btn{background:#ffcc00;color:#0a0a1a;border:none;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600;font-size:0.95em;transition:background 0.2s}
|
||||
.btn:hover{background:#ffd633}
|
||||
.btn-danger{background:#cc3333;color:#fff}
|
||||
.btn-danger:hover{background:#ff4444}
|
||||
.btn-sm{padding:6px 12px;font-size:0.85em}
|
||||
input,textarea{width:100%;padding:10px;border-radius:8px;border:1px solid #333;background:#0d0d20;color:#e0e0e0;font-size:0.95em;margin-bottom:8px;font-family:inherit}
|
||||
input:focus,textarea:focus{outline:none;border-color:#ffcc00}
|
||||
textarea{resize:vertical;min-height:80px}
|
||||
.note-item{background:#0d0d20;border-radius:8px;padding:12px;margin-bottom:8px;position:relative}
|
||||
.note-item h3{color:#ffcc00;font-size:0.95em;margin-bottom:4px}
|
||||
.note-item p{color:#aaa;font-size:0.9em;white-space:pre-wrap;word-break:break-word}
|
||||
.note-item .del-btn{position:absolute;top:8px;right:8px}
|
||||
.status{text-align:center;padding:8px;color:#88ff88;font-size:0.9em;min-height:28px}
|
||||
.status.error{color:#ff8888}
|
||||
.info{display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px;font-size:0.9em;color:#888;margin-bottom:8px}
|
||||
.sync-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
|
||||
.sync-row .btn{flex-shrink:0}
|
||||
#clock{font-size:1.2em;color:#ffcc00;font-weight:600}
|
||||
.note-count{color:#888;font-size:0.85em;margin-bottom:8px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>ESP32 Watch Manager</h1>
|
||||
|
||||
<div class="card">
|
||||
<h2>Czas</h2>
|
||||
<div class="sync-row">
|
||||
<span id="clock">--:--:--</span>
|
||||
<button class="btn" onclick="syncTime()">Synchronizuj czas</button>
|
||||
</div>
|
||||
<div class="status" id="timeStatus"></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Notatki</h2>
|
||||
<div class="note-count" id="noteCount"></div>
|
||||
<div id="notesList"></div>
|
||||
<hr style="border-color:#333;margin:12px 0">
|
||||
<h3 style="color:#ccc;font-size:0.95em;margin-bottom:8px">Dodaj notatke</h3>
|
||||
<input type="text" id="newTitle" placeholder="Tytul" maxlength="63">
|
||||
<textarea id="newContent" placeholder="Tresc notatki..." maxlength="511"></textarea>
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||||
<button class="btn" onclick="addNote()">Dodaj</button>
|
||||
<button class="btn btn-danger" onclick="clearAll()">Usun wszystkie</button>
|
||||
</div>
|
||||
<div class="status" id="notesStatus"></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Status</h2>
|
||||
<div class="info">
|
||||
<span>IP: 192.168.4.1</span>
|
||||
<span id="batteryInfo">Bateria: --</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let notes = [];
|
||||
|
||||
async function fetchJson(url, opts) {
|
||||
try {
|
||||
const r = await fetch(url, opts);
|
||||
return await r.json();
|
||||
} catch(e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadNotes() {
|
||||
const data = await fetchJson('/api/notes');
|
||||
if (data) {
|
||||
notes = data;
|
||||
renderNotes();
|
||||
}
|
||||
}
|
||||
|
||||
function renderNotes() {
|
||||
const el = document.getElementById('notesList');
|
||||
const cnt = document.getElementById('noteCount');
|
||||
cnt.textContent = notes.length + ' notatek';
|
||||
if (notes.length === 0) {
|
||||
el.innerHTML = '<p style="color:#666;text-align:center;padding:12px">Brak notatek</p>';
|
||||
return;
|
||||
}
|
||||
el.innerHTML = notes.map((n, i) =>
|
||||
'<div class="note-item"><h3>' + esc(n.title) + '</h3><p>' + esc(n.content) + '</p>' +
|
||||
'<button class="btn btn-danger btn-sm del-btn" onclick="delNote(' + i + ')">X</button></div>'
|
||||
).join('');
|
||||
}
|
||||
|
||||
function esc(s) {
|
||||
const d = document.createElement('div');
|
||||
d.textContent = s;
|
||||
return d.innerHTML;
|
||||
}
|
||||
|
||||
async function saveNotes() {
|
||||
const r = await fetch('/api/notes', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(notes)
|
||||
});
|
||||
const j = await r.json();
|
||||
showStatus('notesStatus', j.ok ? 'Zapisano!' : 'Blad zapisu', !j.ok);
|
||||
}
|
||||
|
||||
async function addNote() {
|
||||
const t = document.getElementById('newTitle').value.trim();
|
||||
const c = document.getElementById('newContent').value.trim();
|
||||
if (!t && !c) { showStatus('notesStatus', 'Wpisz tytul lub tresc', true); return; }
|
||||
notes.push({title: t || 'Notatka', content: c});
|
||||
await saveNotes();
|
||||
loadNotes();
|
||||
document.getElementById('newTitle').value = '';
|
||||
document.getElementById('newContent').value = '';
|
||||
}
|
||||
|
||||
async function delNote(i) {
|
||||
notes.splice(i, 1);
|
||||
await saveNotes();
|
||||
renderNotes();
|
||||
}
|
||||
|
||||
async function clearAll() {
|
||||
if (!confirm('Usunac wszystkie notatki?')) return;
|
||||
notes = [];
|
||||
await saveNotes();
|
||||
renderNotes();
|
||||
}
|
||||
|
||||
async function syncTime() {
|
||||
const now = new Date();
|
||||
const body = {
|
||||
h: now.getHours(), m: now.getMinutes(), s: now.getSeconds(),
|
||||
d: now.getDate(), mo: now.getMonth() + 1, y: now.getFullYear()
|
||||
};
|
||||
const r = await fetch('/api/time', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
const j = await r.json();
|
||||
showStatus('timeStatus', j.ok ? 'Czas zsynchronizowany!' : 'Blad synchronizacji', !j.ok);
|
||||
if (j.ok) updateClock();
|
||||
}
|
||||
|
||||
function showStatus(id, msg, isErr) {
|
||||
const el = document.getElementById(id);
|
||||
el.textContent = msg;
|
||||
el.className = 'status' + (isErr ? ' error' : '');
|
||||
setTimeout(() => { el.textContent = ''; }, 3000);
|
||||
}
|
||||
|
||||
async function updateClock() {
|
||||
const data = await fetchJson('/api/status');
|
||||
if (data) {
|
||||
document.getElementById('clock').textContent =
|
||||
String(data.h).padStart(2,'0') + ':' +
|
||||
String(data.m).padStart(2,'0') + ':' +
|
||||
String(data.s).padStart(2,'0');
|
||||
document.getElementById('batteryInfo').textContent = 'Bateria: ' + data.bat + '%';
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(updateClock, 2000);
|
||||
updateClock();
|
||||
loadNotes();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
)rawliteral";
|
||||
|
||||
/* ──────────────────────────────────────────────
|
||||
* API Handlers
|
||||
* ────────────────────────────────────────────── */
|
||||
|
||||
static void handleRoot()
|
||||
{
|
||||
server.send(200, "text/html", index_html);
|
||||
}
|
||||
|
||||
static void handleGetNotes()
|
||||
{
|
||||
char *json = notes_storage_get_json();
|
||||
if (json) {
|
||||
server.send(200, "application/json", json);
|
||||
free(json);
|
||||
} else {
|
||||
server.send(200, "application/json", "[]");
|
||||
}
|
||||
}
|
||||
|
||||
static void handlePostNotes()
|
||||
{
|
||||
if (!server.hasArg("plain")) {
|
||||
server.send(400, "application/json", "{\"ok\":false,\"error\":\"no body\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
String body = server.arg("plain");
|
||||
bool ok = notes_storage_save(body.c_str());
|
||||
|
||||
if (ok) {
|
||||
server.send(200, "application/json", "{\"ok\":true}");
|
||||
} else {
|
||||
server.send(500, "application/json", "{\"ok\":false,\"error\":\"write failed\"}");
|
||||
}
|
||||
}
|
||||
|
||||
static void handlePostTime()
|
||||
{
|
||||
if (!server.hasArg("plain")) {
|
||||
server.send(400, "application/json", "{\"ok\":false,\"error\":\"no body\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
String body = server.arg("plain");
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, body);
|
||||
|
||||
if (error) {
|
||||
server.send(400, "application/json", "{\"ok\":false,\"error\":\"invalid json\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
int h = doc["h"] | 0;
|
||||
int m = doc["m"] | 0;
|
||||
int s = doc["s"] | 0;
|
||||
int d = doc["d"] | 1;
|
||||
int mo = doc["mo"] | 1;
|
||||
int y = doc["y"] | 2025;
|
||||
|
||||
watch.setTime(s, m, h, d, mo, y);
|
||||
|
||||
server.send(200, "application/json", "{\"ok\":true}");
|
||||
}
|
||||
|
||||
static void handleGetStatus()
|
||||
{
|
||||
JsonDocument doc;
|
||||
doc["h"] = watch.getHour(true);
|
||||
doc["m"] = watch.getMinute();
|
||||
doc["s"] = watch.getSecond();
|
||||
doc["d"] = watch.getDay();
|
||||
doc["mo"] = watch.getMonth() + 1;
|
||||
doc["y"] = watch.getYear();
|
||||
doc["bat"] = watch.getPhoneBattery();
|
||||
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
server.send(200, "application/json", output);
|
||||
}
|
||||
|
||||
static void handleNotFound()
|
||||
{
|
||||
server.send(404, "text/plain", "Not Found");
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────
|
||||
* Public API
|
||||
* ────────────────────────────────────────────── */
|
||||
|
||||
extern "C" {
|
||||
|
||||
void wifi_server_start(void)
|
||||
{
|
||||
if (serverRunning) return;
|
||||
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAP(WIFI_SSID, WIFI_PASS);
|
||||
|
||||
/* Register endpoints */
|
||||
server.on("/", HTTP_GET, handleRoot);
|
||||
server.on("/api/notes", HTTP_GET, handleGetNotes);
|
||||
server.on("/api/notes", HTTP_POST, handlePostNotes);
|
||||
server.on("/api/time", HTTP_POST, handlePostTime);
|
||||
server.on("/api/status", HTTP_GET, handleGetStatus);
|
||||
server.onNotFound(handleNotFound);
|
||||
|
||||
server.begin();
|
||||
serverRunning = true;
|
||||
}
|
||||
|
||||
void wifi_server_stop(void)
|
||||
{
|
||||
if (!serverRunning) return;
|
||||
|
||||
server.stop();
|
||||
WiFi.softAPdisconnect(true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
serverRunning = false;
|
||||
}
|
||||
|
||||
void wifi_server_handle(void)
|
||||
{
|
||||
if (serverRunning) {
|
||||
server.handleClient();
|
||||
}
|
||||
}
|
||||
|
||||
bool wifi_server_is_running(void)
|
||||
{
|
||||
return serverRunning;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
#endif /* ENABLE_WIFI_SERVER */
|
||||
22
hal/esp32/wifi_server.h
Normal file
22
hal/esp32/wifi_server.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @file wifi_server.h
|
||||
* @brief WiFi Access Point + WebServer for time sync and notes management
|
||||
*/
|
||||
|
||||
#ifndef WIFI_SERVER_H
|
||||
#define WIFI_SERVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void wifi_server_start(void);
|
||||
void wifi_server_stop(void);
|
||||
void wifi_server_handle(void);
|
||||
bool wifi_server_is_running(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WIFI_SERVER_H */
|
||||
Reference in New Issue
Block a user