Browse Source

init

master
marius 6 months ago
parent
commit
e6511016fc
  1. BIN
      maddius/3d_models/maddius-next.FCStd
  2. 5
      maddius/maddius_button8/.gitignore
  3. 10
      maddius/maddius_button8/.vscode/extensions.json
  4. 39
      maddius/maddius_button8/include/README
  5. 46
      maddius/maddius_button8/lib/README
  6. 14
      maddius/maddius_button8/platformio.ini
  7. 162
      maddius/maddius_button8/src/MaddiusClient.cpp
  8. 11
      maddius/maddius_button8/test/README
  9. 2
      maddius/maddius_fade9/.gitignore
  10. 39
      maddius/maddius_fade9/include/README
  11. 46
      maddius/maddius_fade9/lib/README
  12. 15
      maddius/maddius_fade9/platformio.ini
  13. 290
      maddius/maddius_fade9/src/MaddiusClient.cpp
  14. 11
      maddius/maddius_fade9/test/README
  15. 4
      maddius/maddius_matrix_control/.gitignore
  16. 6
      maddius/maddius_matrix_control/CMakeLists.txt
  17. 83
      maddius/maddius_matrix_control/README.md
  18. 1
      maddius/maddius_matrix_control/components/Adafruit_Keypad/.component_hash
  19. 217
      maddius/maddius_matrix_control/components/Adafruit_Keypad/Adafruit_Keypad.cpp
  20. 63
      maddius/maddius_matrix_control/components/Adafruit_Keypad/Adafruit_Keypad.h
  21. 126
      maddius/maddius_matrix_control/components/Adafruit_Keypad/Adafruit_Keypad_Ringbuffer.h
  22. 5
      maddius/maddius_matrix_control/components/Adafruit_Keypad/CMakeLists.txt
  23. 10
      maddius/maddius_matrix_control/components/Adafruit_Keypad/README.md
  24. 100
      maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/Ortho5x6Demo/Ortho5x6Demo.ino
  25. 36
      maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/keypad_generic/keypad_generic.ino
  26. 43
      maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/keypad_test/keypad_config.h
  27. 47
      maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/keypad_test/keypad_test.ino
  28. 36
      maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/trellis_keypad_test/trellis_keypad_test.ino
  29. 10
      maddius/maddius_matrix_control/components/Adafruit_Keypad/library.properties
  30. 5
      maddius/maddius_matrix_control/components/ESPRotary/CMakeLists.txt
  31. 435
      maddius/maddius_matrix_control/components/ESPRotary/ESPRotary.cpp
  32. 136
      maddius/maddius_matrix_control/components/ESPRotary/ESPRotary.h
  33. 5
      maddius/maddius_matrix_control/components/esp_lan/CMakeLists.txt
  34. 0
      maddius/maddius_matrix_control/components/esp_lan/esp_lan.c
  35. 51
      maddius/maddius_matrix_control/components/esp_lan/esp_lan.h
  36. 17
      maddius/maddius_matrix_control/components/esp_server/CMakeLists.txt
  37. 39
      maddius/maddius_matrix_control/components/esp_server/Kconfig.projbuild
  38. 28
      maddius/maddius_matrix_control/components/esp_server/certs/prvtkey.pem
  39. 19
      maddius/maddius_matrix_control/components/esp_server/certs/servercert.pem
  40. 559
      maddius/maddius_matrix_control/components/esp_server/esp_server.c
  41. 21
      maddius/maddius_matrix_control/components/esp_server/esp_server.h
  42. 15
      maddius/maddius_matrix_control/components/esp_server/esp_vue/.eslintrc.cjs
  43. 28
      maddius/maddius_matrix_control/components/esp_server/esp_vue/.gitignore
  44. 8
      maddius/maddius_matrix_control/components/esp_server/esp_vue/.prettierrc.json
  45. 46
      maddius/maddius_matrix_control/components/esp_server/esp_vue/README.md
  46. 1
      maddius/maddius_matrix_control/components/esp_server/esp_vue/env.d.ts
  47. 13
      maddius/maddius_matrix_control/components/esp_server/esp_vue/index.html
  48. 7973
      maddius/maddius_matrix_control/components/esp_server/esp_vue/package-lock.json
  49. 39
      maddius/maddius_matrix_control/components/esp_server/esp_vue/package.json
  50. BIN
      maddius/maddius_matrix_control/components/esp_server/esp_vue/public/favicon.ico
  51. 134
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/App.vue
  52. 86
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/assets/base.css
  53. 1
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/assets/logo.svg
  54. 35
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/assets/main.css
  55. 41
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/HelloWorld.vue
  56. 88
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/TheWelcome.vue
  57. 87
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/WelcomeItem.vue
  58. 7
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconCommunity.vue
  59. 7
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconDocumentation.vue
  60. 7
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconEcosystem.vue
  61. 7
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconSupport.vue
  62. 19
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconTooling.vue
  63. 23
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/main.ts
  64. 60
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/plugins/WebsocketPlugin/index.ts
  65. 25
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/router/index.ts
  66. 55
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/stores/controlStore.ts
  67. 12
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/stores/counter.ts
  68. 0
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/stores/settingsStore.ts
  69. 86
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/HomeView.vue
  70. 29
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/QlcIframeView.vue
  71. 0
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/QlcWsView.vue
  72. 116
      maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/SettingsView.vue
  73. 12
      maddius/maddius_matrix_control/components/esp_server/esp_vue/tsconfig.app.json
  74. 11
      maddius/maddius_matrix_control/components/esp_server/esp_vue/tsconfig.json
  75. 16
      maddius/maddius_matrix_control/components/esp_server/esp_vue/tsconfig.node.json
  76. 24
      maddius/maddius_matrix_control/components/esp_server/esp_vue/vite.config.ts
  77. 229
      maddius/maddius_matrix_control/components/esp_server/keep_alive.c
  78. 106
      maddius/maddius_matrix_control/components/esp_server/keep_alive.h
  79. 194
      maddius/maddius_matrix_control/components/esp_server/udp_server.c
  80. 11
      maddius/maddius_matrix_control/components/esp_server/udp_server.h
  81. 157
      maddius/maddius_matrix_control/components/esp_server/websocket_client.c
  82. 11
      maddius/maddius_matrix_control/components/esp_server/websocket_client.h
  83. 1
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/.component_hash
  84. 271
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/CMakeLists.txt
  85. 412
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/Kconfig.projbuild
  86. 239
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Arduino.h
  87. 48
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Client.h
  88. 471
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Esp.cpp
  89. 122
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Esp.h
  90. 426
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FirmwareMSC.cpp
  91. 70
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FirmwareMSC.h
  92. 44
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FunctionalInterrupt.cpp
  93. 21
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FunctionalInterrupt.h
  94. 447
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HWCDC.cpp
  95. 114
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HWCDC.h
  96. 627
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HardwareSerial.cpp
  97. 260
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HardwareSerial.h
  98. 125
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/IPAddress.cpp
  99. 96
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/IPAddress.h
  100. 90
      maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/IPv6Address.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

BIN
maddius/3d_models/maddius-next.FCStd

Binary file not shown.

5
maddius/maddius_button8/.gitignore vendored

@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

10
maddius/maddius_button8/.vscode/extensions.json vendored

@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

39
maddius/maddius_button8/include/README

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
maddius/maddius_button8/lib/README

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

14
maddius/maddius_button8/platformio.ini

@ -0,0 +1,14 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:nanoatmega328new]
platform = atmelavr
board = nanoatmega328new
framework = arduino

162
maddius/maddius_button8/src/MaddiusClient.cpp

@ -0,0 +1,162 @@
#include <Wire.h> // I2C
#include <Arduino.h>
#define CHIPSET ARDUINO_NANO
#define DEVMODE true
#define I2C_SCL 19 // A5
#define I2C_SDA 18 // A4
#define I2C_INTERRUPT_REQUEST 2 // D2 // D3?
#define BUTTON_PIN0 12 // D12 S10
#define BUTTON_PIN1 13 // D13 S11
#define BUTTON_PIN2 14 // A0 S12
#define BUTTON_PIN3 15 // A1 S13
#define BUTTON_PIN4 16 // A2 S14
#define BUTTON_PIN5 17 // A3 S15
#define BUTTON_PIN6 20 // A6 S16
#define BUTTON_PIN7 21 // A7 S17
#define LED_PIN0 4 // D4 S10
#define LED_PIN1 5 // D5 S11
#define LED_PIN2 6 // D6 S12
#define LED_PIN3 7 // D7 S13
#define LED_PIN4 8 // D8 S14
#define LED_PIN5 9 // D9 S15
#define LED_PIN6 10 // D10 S16
#define LED_PIN7 11 // D11 S17
#define I2C_SLAVE1_ADR 56
uint8_t ledPins[8] = {LED_PIN0, LED_PIN1, LED_PIN2, LED_PIN3, LED_PIN4, LED_PIN5, LED_PIN6, LED_PIN7};
uint8_t buttonLastState[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t buttonNextState[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t buttonExternalState[8] = {0};
bool changeDetected = false;
void requestEvent()
{
Serial.print("requestEvent");
Wire.write(buttonLastState, 8); // respond with message of 8 bytes
// as expected by master
changeDetected = false;
}
void setup()
{
// put your setup code here, to run once:
if (DEVMODE)
{
// pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600); // start serial for output
}
// initialize the LED pin as an output:
pinMode(LED_PIN0, OUTPUT);
pinMode(LED_PIN1, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
pinMode(LED_PIN3, OUTPUT);
pinMode(LED_PIN4, OUTPUT);
pinMode(LED_PIN5, OUTPUT);
pinMode(LED_PIN6, OUTPUT);
pinMode(LED_PIN7, OUTPUT);
// initialize the pushbutton pin as an input:
// pinMode(BUTTON_PIN0, INPUT);
pinMode(BUTTON_PIN0, INPUT_PULLUP);
pinMode(BUTTON_PIN1, INPUT_PULLUP);
pinMode(BUTTON_PIN2, INPUT_PULLUP);
pinMode(BUTTON_PIN3, INPUT_PULLUP);
pinMode(BUTTON_PIN4, INPUT_PULLUP);
pinMode(BUTTON_PIN5, INPUT_PULLUP);
pinMode(BUTTON_PIN6, INPUT);
pinMode(BUTTON_PIN7, INPUT);
// digitalWrite(BUTTON_PIN6, INPUT_PULLUP);
// digitalWrite(BUTTON_PIN7, INPUT_PULLUP);
// Interrupt line open drain
pinMode(I2C_INTERRUPT_REQUEST, INPUT);
digitalWrite(I2C_INTERRUPT_REQUEST, LOW);
Wire.begin(I2C_SLAVE1_ADR); // join i2c bus
// Write to low for voltage compatibility
digitalWrite(SDA, LOW);
digitalWrite(SCL, LOW);
Wire.onRequest(requestEvent); // register event
}
int resetIRQCount = 0;
void loop()
{
buttonNextState[0] = digitalRead(BUTTON_PIN0) ? 0 : 255;
buttonNextState[1] = digitalRead(BUTTON_PIN1) ? 0 : 255;
buttonNextState[2] = digitalRead(BUTTON_PIN2) ? 0 : 255;
buttonNextState[3] = digitalRead(BUTTON_PIN3) ? 0 : 255;
buttonNextState[4] = digitalRead(BUTTON_PIN4) ? 0 : 255;
buttonNextState[5] = digitalRead(BUTTON_PIN5) ? 0 : 255;
int buttonNextState6 = analogRead(BUTTON_PIN6);
int buttonNextState7 = analogRead(BUTTON_PIN7);
if (buttonNextState6 > 500)
{
buttonNextState[6] = 0;
}
else
{
buttonNextState[6] = 255;
}
if (buttonNextState7 > 500)
{
buttonNextState[7] = 0;
}
else
{
buttonNextState[7] = 255;
}
// WIRE I2C
// better only on change?
for (int i = 0; i < 8; i++)
{
if (buttonNextState[i] != buttonLastState[i])
{
buttonLastState[i] = buttonNextState[i];
Serial.print("B");
Serial.print(i);
Serial.print(": ");
Serial.println(buttonNextState[i]);
changeDetected = true;
}
if (buttonLastState[i] == 255 || buttonExternalState[i] == 255)
{
digitalWrite(ledPins[i], HIGH);
}
else
{
digitalWrite(ledPins[i], LOW);
}
}
if (changeDetected)
{
pinMode(I2C_INTERRUPT_REQUEST, OUTPUT);
resetIRQCount++;
}
else
{
pinMode(I2C_INTERRUPT_REQUEST, INPUT);
resetIRQCount = 0;
}
if (resetIRQCount > 1000)
{
changeDetected = false;
resetIRQCount = 0;
}
delayMicroseconds(5);
}

11
maddius/maddius_button8/test/README

@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html

2
maddius/maddius_fade9/.gitignore vendored

@ -0,0 +1,2 @@
.pio
.vscode

39
maddius/maddius_fade9/include/README

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
maddius/maddius_fade9/lib/README

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

15
maddius/maddius_fade9/platformio.ini

@ -0,0 +1,15 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:teensy36]
platform = teensy
board = teensy36
framework = arduino
lib_deps = arduinogetstarted/ezButton@^1.0.4

290
maddius/maddius_fade9/src/MaddiusClient.cpp

@ -0,0 +1,290 @@
/* Belegung Pin Name Pin Number Spice Number
VBAT 1 1
5V 2 2
USBD2- 3 3
USBD2+ 4 4
USBD1- 5 5
USBD1+ 6 6
Fader 5 64/A10 7 7
Fader 6 65/A11 8 8
GND 9 9
Btn 1 0 10 10
Btn 2 1 11 11
Btn LED 1 2 12 12
Btn LED 2 3 13 13
Btn LED 3 4 14 14
Btn LED 4 5 15 15
Btn LED 5 6 16 16
Btn LED 6 7 17 17
Btn LED 7 8 18 18
Btn LED 8 9 19 19
Btn LED 9 10 20 20
Motor 1 B 11 21 21
Motor 1 A 12 22 22
Motor 5 B 40 23 23
Motor 2 B 24 24 24
Motor 3 B 25 25 25
Motor 3 A 26 26 26
Motor 4 A 27 27 27
Motor 4 B 28 28 28
Touch 8 29 29 29
Touch 9 30 30 30
Fader 1 31/A12 31 31
Fader 2 32/A13 32 32
Motor 5 A 41 33 33
Motor 6 A 42 34 34
Motor 6 B 43 35 35
Motor 7 B 44 36 36
Motor 7 B 45 37 37
Motor 8 A 46 38 38
Motor 8 B 47 39 39
Motor 9 B 48 40 40
Btn 3 49/A23 41 41
Btn 4 50/A24 42 42
Motor 9 A 51 43 43
Btn 5 52 44 44
Btn 6 53 45 45
Btn 7 54 46 46
Btn 8 55 47 47
I2C 56 48 48
Standby 33/A14 49 49
Motor 2 A 34/A15 50 50
35/A16 51 51
Motor Speed 36/A17 52 52
I2C 37/A18 53 53
I2C 38/A19 54 54
Fader 7 39/A20 55 55
Fader 3 66/A21 56 56
Fader 4 67/A22 57 57
I2C 57 58 58
Sys LED 13 (LED) 59 59
Fader 8 14/A0 60 60
Touch 1 15/A1 61 61
Touch 2 16/A2 62 62
Touch 3 17/A3 63 63
Touch 4 18/A4 64 64
Touch 5 19/A5 65 65
Fader 9 20/A6 66 66
Btn 9 21/A7 67 67
Touch 6 22/A8 68 68
Touch 7 23/A9 69 69
3V3 70 70
AGND 71 71
VIN 72 72
GND 73 73
VUSB 74 74
PRGM 75 75
RESET 76 76
AREF 77 77
DBGEN 78 78
SWCLK 79 79
SWDIO 80 80
MT1 81 81
MT2 82 82
*/
#include <Wire.h> // I2C
#include <Arduino.h>
#include <ezButton.h>
#define CHIPSET ARDUINO_NANO
#define DEVMODE true
// #define I2C_SCL 37 //
// #define I2C_SDA 38 //
#define I2C_INTERRUPT_REQUEST 57 //
#define FADER_PIN0 31
#define FADER_PIN1 32
#define FADER_PIN2 66
#define FADER_PIN3 67
#define FADER_PIN4 64 //
#define FADER_PIN5 65 //
#define FADER_PIN6 39 //
#define FADER_PIN7 14 //
#define FADER_PIN8 20 //
// sensibility 0 is highest
// fader 4 has problems so i need to set to 3 to not getting signals all the time the others worked good with 1 // todo invetigate
#define FADER_SENIBILITY 3 //
#define BUTTON_PIN0 0
#define BUTTON_PIN1 1
#define BUTTON_PIN2 49
#define BUTTON_PIN3 50
#define BUTTON_PIN4 52 //
#define BUTTON_PIN5 53 //
#define BUTTON_PIN6 54 //
#define BUTTON_PIN7 55 //
#define BUTTON_PIN8 21 //
#define BUTTON_DEBOUNCE 20
#define LED_PIN0 2 //
#define LED_PIN1 3 //
#define LED_PIN2 4 //
#define LED_PIN3 5 //
#define LED_PIN4 6 //
#define LED_PIN5 7 //
#define LED_PIN6 8 //
#define LED_PIN7 9 //
#define LED_PIN8 10 //
#define SYS_LED 13 //
#define I2C_SLAVE1_ADR 55
uint8_t ledPins[9] = {LED_PIN0, LED_PIN1, LED_PIN2, LED_PIN3, LED_PIN4, LED_PIN5, LED_PIN6, LED_PIN7, LED_PIN8};
uint8_t faderPins[9] = {FADER_PIN0, FADER_PIN1, FADER_PIN2, FADER_PIN3, FADER_PIN4, FADER_PIN5, FADER_PIN6, FADER_PIN7, FADER_PIN8};
uint8_t buttonPins[9] = {BUTTON_PIN0, BUTTON_PIN1, BUTTON_PIN2, BUTTON_PIN3, BUTTON_PIN4, BUTTON_PIN5, BUTTON_PIN6, BUTTON_PIN7, BUTTON_PIN8};
uint8_t faderLastState[9] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t faderNextState[9] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t buttonLastState[9] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t buttonNextState[9] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t buttonExternalState[9] = {0};
bool changeDetected = false;
ezButton button[9] = {{BUTTON_PIN0}, {BUTTON_PIN1}, {BUTTON_PIN2}, {BUTTON_PIN3}, {BUTTON_PIN4}, {BUTTON_PIN5}, {BUTTON_PIN6}, {BUTTON_PIN7}, {BUTTON_PIN8}};
void requestEvent()
{
Serial.print("requestEvent");
Wire1.write(faderLastState, 9); // respond with message of 8 bytes
Wire1.write(buttonLastState, 9); // respond with message of 8 bytes
// as expected by master
changeDetected = false;
}
void setup()
{
// put your setup code here, to run once:
if (DEVMODE)
{
Serial.begin(9600); // start serial for output
}
// INIT PINS
// SYS LED
pinMode(SYS_LED, OUTPUT);
digitalWrite(SYS_LED, HIGH);
for (int i = 0; i < 9; i++)
{
// BTN LED
pinMode(ledPins[i], OUTPUT);
// BTN PIN
// pinMode(buttonPins[i], INPUT_PULLUP);
// button[i] = *new ezButton(buttonPins[i]);
button[i].setDebounceTime(BUTTON_DEBOUNCE);
// FADER
pinMode(faderPins[i], INPUT);
}
// Interrupt line open drain
pinMode(I2C_INTERRUPT_REQUEST, INPUT);
digitalWrite(I2C_INTERRUPT_REQUEST, LOW);
// I2C
Wire1.begin(I2C_SLAVE1_ADR);
// INTERUPTTRIGGER
// Write to low for voltage compatibility
// digitalWrite(SDA, LOW);
// digitalWrite(SCL, LOW);
Wire1.onRequest(requestEvent); // register event
}
int resetIRQCount = 0;
void loop()
{
for (int i = 0; i < 9; i++)
{
// uint8_t buttonValue = digitalRead(buttonPins[i]);
// buttonNextState[i] = buttonValue ? 0 : 255;
button[i].loop();
if (button[i].isPressed())
{
buttonNextState[i] = 255;
}
else if (button[i].isReleased())
{
buttonNextState[i] = 0;
}
int read = analogRead(faderPins[i]);
faderNextState[i] = read >> 2;
// Serial.print("r");
// Serial.print(read);
// Serial.print(": ");
// Serial.println(faderNextState[i]);
}
// WIRE I2C
bool nextChangeDetected = false;
// better only on change?
for (int i = 0; i < 9; i++)
{
// FADERS
if (abs(faderNextState[i] - faderLastState[i]) > 3) // > 3
{
if (faderNextState[i] <= 3)
{
faderNextState[i] = 0;
}
else if (faderNextState[i] >= (255 - 3))
{
faderNextState[i] = 255;
}
faderLastState[i] = faderNextState[i];
Serial.print("F");
Serial.print(i);
Serial.print(": ");
Serial.println(faderNextState[i]);
// Serial.println(analogRead(faderPins[i]));
nextChangeDetected = true;
}
// Buttons
if (buttonNextState[i] != buttonLastState[i])
{
buttonLastState[i] = buttonNextState[i];
Serial.print("B");
Serial.print(i);
Serial.print(": ");
Serial.println(buttonNextState[i]);
nextChangeDetected = true;
}
if (buttonLastState[i] == 255 || buttonExternalState[i] == 255)
{
digitalWrite(ledPins[i], HIGH);
}
else
{
digitalWrite(ledPins[i], LOW);
}
}
if (nextChangeDetected && !changeDetected)
{
changeDetected = nextChangeDetected;
pinMode(I2C_INTERRUPT_REQUEST, OUTPUT);
// resetIRQCount++;
}
else if (!changeDetected)
{
pinMode(I2C_INTERRUPT_REQUEST, INPUT);
}
// else
// {
// // resetIRQCount = 0;
// }
// if (resetIRQCount > 1000)
// {
// changeDetected = false;
// resetIRQCount = 0;
// Serial.println(buttonNextState[i]);
// }
// delayMicroseconds(5);
}

11
maddius/maddius_fade9/test/README

@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html

4
maddius/maddius_matrix_control/.gitignore vendored

@ -0,0 +1,4 @@
.pio
.vscode
build
managed_components

6
maddius/maddius_matrix_control/CMakeLists.txt

@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(tusb_midi)

83
maddius/maddius_matrix_control/README.md

@ -0,0 +1,83 @@
| Supported Targets | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- |
# TinyUSB MIDI Device Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example shows how to set up ESP chip to work as a USB MIDI Device.
It outputs a MIDI note sequence via the native USB port.
As a USB stack, a TinyUSB component is used.
## How to use example
### Hardware Required
Any ESP board that have USB-OTG supported.
#### Pin Assignment
_Note:_ In case your board doesn't have micro-USB connector connected to USB-OTG peripheral, you may have to DIY a cable and connect **D+** and **D-** to the pins listed below.
See common pin assignments for USB Device examples from [upper level](../../README.md#common-pin-assignments).
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```bash
idf.py -p PORT flash monitor
```
(Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## MIDI output
You can use several programs on your computer to listen to the ESP's MIDI output depending on your operating system, e.g.:
* Windows: `MIDI-OX`
* Linux: `qsynth` with `qjackctl`
* macOS: `SimpleSynth`
## Example Output
After the flashing you should see the output at idf monitor:
```
I (285) example: USB initialization
I (285) tusb_desc:
┌─────────────────────────────────┐
│ USB Device Descriptor Summary │
├───────────────────┬─────────────┤
│bDeviceClass │ 0 │
├───────────────────┼─────────────┤
│bDeviceSubClass │ 0 │
├───────────────────┼─────────────┤
│bDeviceProtocol │ 0 │
├───────────────────┼─────────────┤
│bMaxPacketSize0 │ 64 │
├───────────────────┼─────────────┤
│idVendor │ 0x303a │
├───────────────────┼─────────────┤
│idProduct │ 0x4008 │
├───────────────────┼─────────────┤
│bcdDevice │ 0x100 │
├───────────────────┼─────────────┤
│iManufacturer │ 0x1 │
├───────────────────┼─────────────┤
│iProduct │ 0x2 │
├───────────────────┼─────────────┤
│iSerialNumber │ 0x3 │
├───────────────────┼─────────────┤
│bNumConfigurations │ 0x1 │
└───────────────────┴─────────────┘
I (455) TinyUSB: TinyUSB Driver installed
I (465) example: USB initialization DONE
```
Disconnect UART-to-USB port and connect the native USB port to a computer then the device should show up as a USB MIDI Device while outputting notes.

1
maddius/maddius_matrix_control/components/Adafruit_Keypad/.component_hash

@ -0,0 +1 @@
3f3297a0c07a511d5b455c3806d53f23fa65cf75833270daa89f35564e9375a3

217
maddius/maddius_matrix_control/components/Adafruit_Keypad/Adafruit_Keypad.cpp

@ -0,0 +1,217 @@
#include "Adafruit_Keypad.h"
#define _KEY_PRESSED_POS (1)
#define _KEY_PRESSED (1UL << _KEY_PRESSED_POS)
#define _JUST_PRESSED_POS (2)
#define _JUST_PRESSED (1UL << _JUST_PRESSED_POS)
#define _JUST_RELEASED_POS (3)
#define _JUST_RELEASED (1UL << _JUST_RELEASED_POS)
#define _KEYPAD_SETTLING_DELAY 20
/**************************************************************************/
/*!
@brief default constructor
@param userKeymap a multidimensional array of key characters
@param row an array of GPIO pins that are connected to each row of the
keypad
@param col an array of GPIO pins that are connected to each column of the
keypad
@param numRows the number of rows on the keypad
@param numCols the number of columns on the keypad
*/
/**************************************************************************/
Adafruit_Keypad::Adafruit_Keypad(byte *userKeymap, byte *row, byte *col,
int numRows, int numCols) {
_userKeymap = userKeymap;
_row = row;
_col = col;
_numRows = numRows;
_numCols = numCols;
_keystates = NULL;
}
/**************************************************************************/
/*!
@brief default destructor
*/
/**************************************************************************/
Adafruit_Keypad::~Adafruit_Keypad() {
if (_keystates != NULL) {
free((void *)_keystates);
}
}
/**************************************************************************/
/*!
@brief get the state of a key with the given name
@param key the name of the key to be checked
*/
/**************************************************************************/
volatile byte *Adafruit_Keypad::getKeyState(byte key) {
for (int i = 0; i < _numRows * _numCols; i++) {
if (_userKeymap[i] == key) {
return _keystates + i;
}
}
return NULL;
}
/**************************************************************************/
/*!
@brief read the array of switches and place any events in the buffer.
*/
/**************************************************************************/
void Adafruit_Keypad::tick() {
uint8_t evt;
for (int i = 0; i < _numCols; i++) {
digitalWrite(_col[i], HIGH);
}
int i = 0;
for (int c = 0; c < _numCols; c++) {
digitalWrite(_col[c], LOW);
delayMicroseconds(_KEYPAD_SETTLING_DELAY);
for (int r = 0; r < _numRows; r++) {
i = r * _numCols + c;
bool pressed = !digitalRead(_row[r]);
// Serial.print((int)pressed);
volatile byte *state = _keystates + i;
byte currentState = *state;
if (pressed && !(currentState & _KEY_PRESSED)) {
currentState |= (_JUST_PRESSED | _KEY_PRESSED);
evt = KEY_JUST_PRESSED;
_eventbuf.store_char(evt);
_eventbuf.store_char(*(_userKeymap + i));
_eventbuf.store_char(r);
_eventbuf.store_char(c);
} else if (!pressed && (currentState & _KEY_PRESSED)) {
currentState |= _JUST_RELEASED;
currentState &= ~(_KEY_PRESSED);
evt = KEY_JUST_RELEASED;
_eventbuf.store_char(evt);
_eventbuf.store_char(*(_userKeymap + i));
_eventbuf.store_char(r);
_eventbuf.store_char(c);
}
*state = currentState;
}
// Serial.println("");
digitalWrite(_col[c], HIGH);
}
}
/**************************************************************************/
/*!
@brief set all the pin modes and set up variables.
*/
/**************************************************************************/
void Adafruit_Keypad::begin() {
_keystates = (volatile byte *)malloc(_numRows * _numCols);
memset((void *)_keystates, 0, _numRows * _numCols);
for (int i = 0; i < _numCols; i++) {
pinMode(_col[i], OUTPUT);
digitalWrite(_col[i], HIGH);
}
for (int i = 0; i < _numRows; i++) {
pinMode(_row[i], INPUT_PULLUP);
}
}
/**************************************************************************/
/*!
@brief check if the given key has just been pressed since the last tick.
@param key the name of the key to be checked
@param clear whether to reset the state (default yes) post-check
@returns true if it has been pressed, false otherwise.
*/
/**************************************************************************/
bool Adafruit_Keypad::justPressed(byte key, bool clear) {
volatile byte *state = getKeyState(key);
bool val = (*state & _JUST_PRESSED) != 0;
if (clear)
*state &= ~(_JUST_PRESSED);
return val;
}
/**************************************************************************/
/*!
@brief check if the given key has just been released since the last tick.
@param key the name of the key to be checked
@returns true if it has been released, false otherwise.
*/
/**************************************************************************/
bool Adafruit_Keypad::justReleased(byte key) {
volatile byte *state = getKeyState(key);
bool val = (*state & _JUST_RELEASED) != 0;
*state &= ~(_JUST_RELEASED);
return val;
}
/**************************************************************************/
/*!
@brief check if the given key is currently pressed
@param key the name of the key to be checked
@returns true if it is currently pressed, false otherwise.
*/
/**************************************************************************/
bool Adafruit_Keypad::isPressed(byte key) {
return (*getKeyState(key) & _KEY_PRESSED) != 0;
}
/**************************************************************************/
/*!
@brief check if the given key is currently released
@param key the name of the key to be checked
@returns true if it is currently released, false otherwise.
*/
/**************************************************************************/
bool Adafruit_Keypad::isReleased(byte key) {
return (*getKeyState(key) & _KEY_PRESSED) == 0;
}
/**************************************************************************/
/*!
@brief check how many events are in the keypads buffer
@returns the number of events currently in the buffer
*/
/**************************************************************************/
int Adafruit_Keypad::available() {
return (_eventbuf.available() / sizeof(keypadEvent));
}
/**************************************************************************/
/*!
@brief pop the next event off of the FIFO
@returns the next event in the FIFO
*/
/**************************************************************************/
keypadEvent Adafruit_Keypad::read() {
keypadEvent k;
k.bit.EVENT = _eventbuf.read_char();
k.bit.KEY = _eventbuf.read_char();
k.bit.ROW = _eventbuf.read_char();
k.bit.COL = _eventbuf.read_char();
return k;
}
/**************************************************************************/
/*!
@brief Clear out the event buffer and all the key states
*/
/**************************************************************************/
void Adafruit_Keypad::clear() {
_eventbuf.clear();
for (int i = 0; i < _numRows * _numCols; i++)
*(_keystates + i) = 0;
}

63
maddius/maddius_matrix_control/components/Adafruit_Keypad/Adafruit_Keypad.h

@ -0,0 +1,63 @@
#ifndef _ADAFRUIT_KEYPAD_H_
#define _ADAFRUIT_KEYPAD_H_
#include "Adafruit_Keypad_Ringbuffer.h"
#include "Arduino.h"
#include <string.h>
#define makeKeymap(x) ((byte *)x) ///< cast the passed key characters to bytes
#define KEY_JUST_RELEASED (0) ///< key has been released
#define KEY_JUST_PRESSED (1) ///< key has been pressed
/**************************************************************************/
/*!
@brief key event structure
*/
/**************************************************************************/
union keypadEvent {
struct {
uint8_t KEY : 8; ///< the keycode
uint8_t EVENT : 8; ///< the edge
uint8_t ROW : 8; ///< the row number
uint8_t COL : 8; ///< the col number
} bit; ///< bitfield format
uint32_t reg; ///< register format
};
/**************************************************************************/
/*!
@brief Class for interfacing GPIO with a diode-multiplexed keypad
*/
/**************************************************************************/
class Adafruit_Keypad {
public:
Adafruit_Keypad(byte *userKeymap, byte *row, byte *col, int numRows,
int numCols);
~Adafruit_Keypad();
void begin();
void tick();
bool justPressed(byte key, bool clear = true);
bool justReleased(byte key);
bool isPressed(byte key);
bool isReleased(byte key);
int available();
keypadEvent read();
void clear();
private:
byte *_userKeymap;
byte *_row;
byte *_col;
volatile byte *_keystates;
Adafruit_Keypad_Ringbuffer _eventbuf;
int _numRows;
int _numCols;
volatile byte *getKeyState(byte key);
};
#endif

126
maddius/maddius_matrix_control/components/Adafruit_Keypad/Adafruit_Keypad_Ringbuffer.h

@ -0,0 +1,126 @@
/*
Copyright (c) 2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef __cplusplus
#ifndef _ADAFRUIT_KEYPAD_RING_BUFFER_
#define _ADAFRUIT_KEYPAD_RING_BUFFER_
#include <stdint.h>
#include <string.h>
// Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which head is the index of the location
// to which to write the next incoming character and tail is the index of the
// location from which to read.
#ifndef SERIAL_BUFFER_SIZE
#define SERIAL_BUFFER_SIZE 256
#endif
template <int N> class Adafruit_Keypad_RingbufferN {
public:
uint8_t _aucBuffer[N];
volatile int _iHead;
volatile int _iTail;
public:
Adafruit_Keypad_RingbufferN(void);
void store_char(uint8_t c);
void clear();
int read_char();
int available();
int availableForStore();
int peek();
bool isFull();
private:
int nextIndex(int index);
};
typedef Adafruit_Keypad_RingbufferN<SERIAL_BUFFER_SIZE>
Adafruit_Keypad_Ringbuffer;
template <int N>
Adafruit_Keypad_RingbufferN<N>::Adafruit_Keypad_RingbufferN(void) {
memset(_aucBuffer, 0, N);
clear();
}
template <int N> void Adafruit_Keypad_RingbufferN<N>::store_char(uint8_t c) {
int i = nextIndex(_iHead);
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if (i != _iTail) {
_aucBuffer[_iHead] = c;
_iHead = i;
}
}
template <int N> void Adafruit_Keypad_RingbufferN<N>::clear() {
_iHead = 0;
_iTail = 0;
}
template <int N> int Adafruit_Keypad_RingbufferN<N>::read_char() {
if (_iTail == _iHead)
return -1;
uint8_t value = _aucBuffer[_iTail];
_iTail = nextIndex(_iTail);
return value;
}
template <int N> int Adafruit_Keypad_RingbufferN<N>::available() {
int delta = _iHead - _iTail;
if (delta < 0)
return N + delta;
else
return delta;
}
template <int N> int Adafruit_Keypad_RingbufferN<N>::availableForStore() {
if (_iHead >= _iTail)
return N - 1 - _iHead + _iTail;
else
return _iTail - _iHead - 1;
}
template <int N> int Adafruit_Keypad_RingbufferN<N>::peek() {
if (_iTail == _iHead)
return -1;
return _aucBuffer[_iTail];
}
template <int N> int Adafruit_Keypad_RingbufferN<N>::nextIndex(int index) {
return (uint32_t)(index + 1) % N;
}
template <int N> bool Adafruit_Keypad_RingbufferN<N>::isFull() {
return (nextIndex(_iHead) == _iTail);
}
#endif /* _ADAFRUIT_KEYPAD_RING_BUFFER_ */
#endif /* __cplusplus */

5
maddius/maddius_matrix_control/components/Adafruit_Keypad/CMakeLists.txt

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.5)
idf_component_register(SRCS "Adafruit_Keypad.cpp"
REQUIRES "arduino-esp32" "spi_flash" "esp_partition"
INCLUDE_DIRS ".")
project(Adafruit_Keypad)

10
maddius/maddius_matrix_control/components/Adafruit_Keypad/README.md

@ -0,0 +1,10 @@
# Adafruit Keypad Library [![Build Status](https://github.com/adafruit/Adafruit_Keypad/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_Keypad/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_Keypad/html/index.html)
<img src="https://cdn-shop.adafruit.com/970x728/4020-04.jpg" height="300"/>
This is a library for using diode multiplexed keypads with GPIO pins on Arduino.
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Written by Dean Miller for Adafruit Industries.
MIT license, all text above must be included in any redistribution

100
maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/Ortho5x6Demo/Ortho5x6Demo.ino

@ -0,0 +1,100 @@
#include <Adafruit_NeoPixel.h>
#include "Adafruit_Keypad.h"
#define ROWS 5 // rows
#define COLS 6 // columns
#define NEOPIXEL_PIN A0
#define NUM_PIXELS (ROWS * COLS)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
{'1','2','3','4','5','6'},
{'7','8','9','A','B','C'},
{'D','E','F','G','H','I'},
{'J','K','L','M','N','O'},
{'P','Q','R','S','T','U'}
};
uint8_t rowPins[ROWS] = {6, 5, 4, 3, 2}; //connect to the row pinouts of the keypad
uint8_t colPins[COLS] = {7, 8, 9, 10, 11, 12}; //connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
bool lit[ROWS*COLS] = {0};
void setup() {
Serial.begin(115200);
//while (!Serial);
Serial.println("Ortho 5x6 keypad demo");
strip.begin();
strip.setBrightness(40);
strip.show(); // Initialize all pixels to 'off'
customKeypad.begin();
for (int i=0; i<ROWS*COLS; i++) {
lit[i] = false;
}
}
uint8_t j=0; // color ticker
void loop() {
//Serial.println("Test NeoPixels");
customKeypad.tick();
while(customKeypad.available()){
keypadEvent e = customKeypad.read();
Serial.print((char)e.bit.KEY);
if (e.bit.EVENT == KEY_JUST_PRESSED) {
Serial.println(" pressed");
uint8_t row = e.bit.ROW;
uint8_t col = e.bit.COL;
Serial.print("Row: "); Serial.print(row);
Serial.print(" col: "); Serial.print(col);
Serial.print(" -> ");
uint16_t keynum;
if (row % 2 == 0) { // even row
keynum = row * COLS + col;
} else { // odd row the neopixels go BACKWARDS!
keynum = row * COLS + (5 - col);
}
Serial.println(keynum);
lit[keynum] = !lit[keynum]; // invert neopixel status
}
else if(e.bit.EVENT == KEY_JUST_RELEASED) {
Serial.println(" released");
}
}
for(int i=0; i< strip.numPixels(); i++) {
if (lit[i]) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
} else {
strip.setPixelColor(i, 0);
}
}
strip.show();
j++;
delay(10);
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}

36
maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/keypad_generic/keypad_generic.ino

@ -0,0 +1,36 @@
#include "Adafruit_Keypad.h"
const byte ROWS = 4; // rows
const byte COLS = 4; // columns
//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {11, 10, 9, 8}; //connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void setup() {
Serial.begin(9600);
customKeypad.begin();
}
void loop() {
// put your main code here, to run repeatedly:
customKeypad.tick();
while(customKeypad.available()){
keypadEvent e = customKeypad.read();
Serial.print((char)e.bit.KEY);
if(e.bit.EVENT == KEY_JUST_PRESSED) Serial.println(" pressed");
else if(e.bit.EVENT == KEY_JUST_RELEASED) Serial.println(" released");
}
delay(10);
}

43
maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/keypad_test/keypad_config.h

@ -0,0 +1,43 @@
// This file contains predefined setup for various Adafruit Matrix Keypads.
#ifndef __KEYPAD_CONFIG_H__
#define __KEYPAD_CONFIG_H__
#if defined(KEYPAD_PID3844)
const byte ROWS = 4; // rows
const byte COLS = 4; // columns
// define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}};
byte rowPins[ROWS] = {R1, R2, R3,
R4}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {C1, C2, C3,
C4}; // connect to the column pinouts of the keypad
#endif
#if defined(KEYPAD_PID1824) || defined(KEYPAD_PID3845) || defined(KEYPAD_PID419)
const byte ROWS = 4; // rows
const byte COLS = 3; // columns
// define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
{'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'}, {'*', '0', '#'}};
byte rowPins[ROWS] = {R1, R2, R3,
R4}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {C1, C2, C3}; // connect to the column pinouts of the
// keypad
#endif
#if defined(KEYPAD_PID1332)
const byte ROWS = 1; // rows
const byte COLS = 4; // columns
// define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
{'1', '2', '3', '4'},
};
byte rowPins[ROWS] = {R1}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {C1, C2, C3,
C4}; // connect to the column pinouts of the keypad
#endif
#endif

47
maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/keypad_test/keypad_test.ino

@ -0,0 +1,47 @@
// Use this example with the Adafruit Keypad products.
// You'll need to know the Product ID for your keypad.
// Here's a summary:
// * PID3844 4x4 Matrix Keypad
// * PID3845 3x4 Matrix Keypad
// * PID1824 3x4 Phone-style Matrix Keypad
// * PID1332 Membrane 1x4 Keypad
// * PID419 Membrane 3x4 Matrix Keypad
#include "Adafruit_Keypad.h"
// define your specific keypad here via PID
#define KEYPAD_PID3844
// define your pins here
// can ignore ones that don't apply
#define R1 2
#define R2 3
#define R3 4
#define R4 5
#define C1 8
#define C2 9
#define C3 10
#define C4 11
// leave this import after the above configuration
#include "keypad_config.h"
//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void setup() {
Serial.begin(9600);
customKeypad.begin();
}
void loop() {
// put your main code here, to run repeatedly:
customKeypad.tick();
while(customKeypad.available()){
keypadEvent e = customKeypad.read();
Serial.print((char)e.bit.KEY);
if(e.bit.EVENT == KEY_JUST_PRESSED) Serial.println(" pressed");
else if(e.bit.EVENT == KEY_JUST_RELEASED) Serial.println(" released");
}
delay(10);
}

36
maddius/maddius_matrix_control/components/Adafruit_Keypad/examples/trellis_keypad_test/trellis_keypad_test.ino

@ -0,0 +1,36 @@
#include "Adafruit_Keypad.h"
const byte ROWS = 4; // four rows
const byte COLS = 8; // eight columns
//define the symbols on the buttons of the keypads
byte trellisKeys[ROWS][COLS] = {
{1, 2, 3, 4, 5, 6, 7, 8},
{9, 10, 11, 12, 13, 14, 15, 16},
{17, 18, 19, 20, 21, 22, 23, 24},
{25, 26, 27, 28, 29, 30, 31, 32}
};
byte rowPins[ROWS] = {14, 15, 16, 17}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {2, 3, 4, 5, 6, 7, 8, 9}; //connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(trellisKeys), rowPins, colPins, ROWS, COLS);
void setup() {
Serial.begin(115200);
customKeypad.begin();
}
void loop() {
// put your main code here, to run repeatedly:
customKeypad.tick();
while(customKeypad.available()){
keypadEvent e = customKeypad.read();
Serial.print((int)e.bit.KEY);
if(e.bit.EVENT == KEY_JUST_PRESSED) Serial.println(" pressed");
else if(e.bit.EVENT == KEY_JUST_RELEASED) Serial.println(" released");
}
delay(10);
}

10
maddius/maddius_matrix_control/components/Adafruit_Keypad/library.properties

@ -0,0 +1,10 @@
name=Adafruit Keypad
version=1.3.2
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Diode-multiplexed keypad support for Arduino
paragraph=Diode-multiplexed keypad support for Arduino
category=Signal Input/Output
url=https://github.com/adafruit/Adafruit_Keypad
architectures=*
depends=Adafruit NeoPixel

5
maddius/maddius_matrix_control/components/ESPRotary/CMakeLists.txt

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.5)
idf_component_register(SRCS "ESPRotary.cpp"
REQUIRES "arduino-esp32" "spi_flash" "esp_partition"
INCLUDE_DIRS ".")
project(ESPRotary)

435
maddius/maddius_matrix_control/components/ESPRotary/ESPRotary.cpp

@ -0,0 +1,435 @@
/////////////////////////////////////////////////////////////////
/*
ESP8266/Arduino Library for reading rotary encoder values.
Copyright 2017-2022 Lennart Hennigs.
*/
/////////////////////////////////////////////////////////////////
#include "ESPRotary.h"
/////////////////////////////////////////////////////////////////
// initialize static counter
int ESPRotary::_nextID = 0;
/////////////////////////////////////////////////////////////////
void ESPRotary::_setID()
{
id = _nextID;
_nextID++;
}
/////////////////////////////////////////////////////////////////
ESPRotary::ESPRotary()
{
_setID();
}
/////////////////////////////////////////////////////////////////
ESPRotary::ESPRotary(byte pin1, byte pin2, byte steps_per_click /* = 1 */, int lower_bound /* = INT16_MIN */, int upper_bound /* = INT16_MAX */, int inital_pos /* = 0 */, int increment /* = 1 */)
{
ESPRotary();
begin(pin1, pin2, steps_per_click, lower_bound, upper_bound, inital_pos, increment);
}
/////////////////////////////////////////////////////////////////
void ESPRotary::begin(byte pin1, byte pin2, byte steps_per_click /* = 1 */, int lower_bound /* = INT16_MIN */, int upper_bound /* = INT16_MAX */, int inital_pos /* = 0 */, int increment /* = 1 */)
{
this->pin1 = pin1;
this->pin2 = pin2;
pinMode(pin1, INPUT_PULLUP);
pinMode(pin2, INPUT_PULLUP);
setUpperBound(upper_bound);
setLowerBound(lower_bound);
setIncrement(increment);
setStepsPerClick(steps_per_click);
loop();
steps = inital_pos * steps_per_click;
last_event = rotary_event::none;
dir = rotary_direction::undefined;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setUpperBound(int upper)
{
upper_bound = (lower_bound < upper) ? upper : lower_bound;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setLowerBound(int lower)
{
lower_bound = (lower < upper_bound) ? lower : upper_bound;
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getUpperBound() const
{
return upper_bound;
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getLowerBound() const
{
return lower_bound;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setChangedHandler(CallbackFunction f)
{
change_cb = f;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setRightRotationHandler(CallbackFunction f)
{
right_cb = f;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setLeftRotationHandler(CallbackFunction f)
{
left_cb = f;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setUpperOverflowHandler(CallbackFunction f)
{
upper_cb = f;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setLowerOverflowHandler(CallbackFunction f)
{
lower_cb = f;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setSpeedupStartedHandler(CallbackFunction f)
{
speedup_start_cb = f;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setSpeedupEndedHandler(CallbackFunction f)
{
speedup_end_cb = f;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::resetPosition(int p /* = 0 */, bool fireCallback /* = true */)
{
// change position?
if (p == getPosition())
return;
// yes...
steps = p * steps_per_click;
_isWithinBounds();
if (fireCallback)
_callCallback(change_cb);
last_event = rotary_event::none;
dir = rotary_direction::undefined;
in_speedup = false;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setIncrement(int increment)
{
this->increment = increment;
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getIncrement() const
{
return increment;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setStepsPerClick(int steps)
{
steps_per_click = (steps < 1) ? 1 : steps;
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getStepsPerClick() const
{
return steps_per_click;
}
/////////////////////////////////////////////////////////////////
rotary_direction ESPRotary::getDirection() const
{
return dir;
}
/////////////////////////////////////////////////////////////////
String ESPRotary::directionToString(rotary_direction dir) const
{
return (dir == rotary_direction::right) ? "right" : "left";
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getPosition() const
{
return steps / steps_per_click;
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getID() const
{
return id;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setID(int newID)
{
id = newID;
}
/////////////////////////////////////////////////////////////////
bool ESPRotary::operator==(ESPRotary &rhs)
{
return (this == &rhs);
}
/////////////////////////////////////////////////////////////////
void ESPRotary::loop()
{
unsigned long now = millis();
// did it change (enough)?
if (!_wasRotated())
return;
dir = (steps > last_steps) ? rotary_direction::right : rotary_direction::left;
// shall I speedup things
if (enable_speedup)
_checkForSpeedup(now);
// are we out of bounds?
if (_isWithinBounds(true))
{
// trigger rotation event
_setEvent((dir == rotary_direction::right) ? rotary_event::right_rotation : rotary_event::left_rotation);
last_turn = now;
}
last_steps = steps;
}
/////////////////////////////////////////////////////////////////
bool ESPRotary::_wasRotated()
{
static const int8_t factors[] = {0, 1, -1, 2, -1, 0, -2, 1, 1, -2, 0, -1, 2, -1, 1, 0};
int encoderState = (state & 3) | digitalRead(pin1) << 2 | digitalRead(pin2) << 3;
steps += factors[encoderState] * increment;
state = (encoderState >> 2);
int stepDifference = abs(steps - last_steps);
return stepDifference >= (steps_per_click * increment);
}
/////////////////////////////////////////////////////////////////
void ESPRotary::_checkForSpeedup(unsigned long now)
{
if (now - last_turn > speedup_interval)
{
if (in_speedup)
_setEvent(rotary_event::speedup_ended);
return;
}
steps += ((dir == rotary_direction::right ? 1 : -1) * (speedup_increment - increment) * steps_per_click);
int pos = getPosition();
// only trigger speedup when you are not "on a wall"
if (pos > lower_bound && pos < upper_bound)
{
if (!in_speedup)
_setEvent(rotary_event::speedup_started);
}
}
/////////////////////////////////////////////////////////////////
void ESPRotary::triggerOnBounds(bool triggerEvents /* = true */)
{
boundsTrigger = triggerEvents;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::_callCallback(CallbackFunction callback)
{
if (callback != NULL)
callback(*this);
}
/////////////////////////////////////////////////////////////////
bool ESPRotary::_isWithinBounds(bool triggerAlerts /* = false */)
{
int pos = getPosition();
if (pos > lower_bound && pos < upper_bound)
return true;
if (pos >= upper_bound)
{
steps = upper_bound * steps_per_click;
if (in_speedup)
_setEvent(rotary_event::speedup_ended);
if (triggerAlerts)
_setEvent(rotary_event::upper_bound_hit);
}
else if (pos <= lower_bound)
{
steps = lower_bound * steps_per_click;
if (in_speedup)
_setEvent(rotary_event::speedup_ended);
if (triggerAlerts)
_setEvent(rotary_event::lower_bound_hit);
}
return false;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::_setEvent(rotary_event event)
{
switch (event)
{
case rotary_event::left_rotation:
_callCallback(left_cb);
_callCallback(change_cb);
break;
case rotary_event::right_rotation:
_callCallback(right_cb);
_callCallback(change_cb);
break;
case rotary_event::speedup_started:
_callCallback(speedup_start_cb);
in_speedup = true;
break;
case rotary_event::speedup_ended:
_callCallback(speedup_end_cb);
in_speedup = false;
break;
case rotary_event::upper_bound_hit:
if (last_event == rotary_event::upper_bound_hit && !retrigger_event)
return;
if (boundsTrigger)
{
_callCallback(right_cb);
_callCallback(change_cb);
}
_callCallback(upper_cb);
break;
case rotary_event::lower_bound_hit:
if (last_event == rotary_event::lower_bound_hit && !retrigger_event)
return;
if (boundsTrigger)
{
_callCallback(left_cb);
_callCallback(change_cb);
}
_callCallback(lower_cb);
break;
case rotary_event::none:
break;
}
last_event = event;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setSpeedupInterval(int interval)
{
speedup_interval = interval;
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getSpeedupInterval() const
{
return speedup_interval;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::setSpeedupIncrement(int increment)
{
speedup_increment = increment;
}
/////////////////////////////////////////////////////////////////
int ESPRotary::getSpeedupIncrement() const
{
return speedup_increment;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::enableSpeedup(bool enable)
{
enable_speedup = enable;
}
/////////////////////////////////////////////////////////////////
bool ESPRotary::isSpeedupEnabled() const
{
return enable_speedup;
}
/////////////////////////////////////////////////////////////////
rotary_event ESPRotary::getLastEvent() const
{
return last_event;
}
/////////////////////////////////////////////////////////////////
void ESPRotary::retriggerEvent(bool retrigger)
{
retrigger_event = retrigger;
}
/////////////////////////////////////////////////////////////////
bool ESPRotary::isInSpeedup() const
{
return in_speedup;
}
/////////////////////////////////////////////////////////////////

136
maddius/maddius_matrix_control/components/ESPRotary/ESPRotary.h

@ -0,0 +1,136 @@
/////////////////////////////////////////////////////////////////
/*
ESP8266/Arduino Library for reading rotary encoder values.
Copyright 2017-2022 Lennart Hennigs
*/
/////////////////////////////////////////////////////////////////
#pragma once
#ifndef ESPRotary_h
#define ESPRotary_h
/////////////////////////////////////////////////////////////////
#include "Arduino.h"
/////////////////////////////////////////////////////////////////
enum class rotary_direction
{
undefined = 0,
right = 1,
left = 255
};
enum class rotary_event
{
left_rotation,
right_rotation,
speedup_started,
speedup_ended,
upper_bound_hit,
lower_bound_hit,
none
};
/////////////////////////////////////////////////////////////////
class ESPRotary
{
protected:
int id;
byte pin1, pin2;
byte steps_per_click;
int lower_bound;
int upper_bound;
byte state;
int increment;
int steps = 0;
int last_steps = 0;
rotary_event last_event;
rotary_direction dir;
bool boundsTrigger = true;
bool retrigger_event = true;
bool enable_speedup = false;
unsigned int speedup_increment = 5;
unsigned int speedup_interval = 75;
int in_speedup = false;
unsigned long last_turn = 0;
using CallbackFunction = void (*)(ESPRotary &);
CallbackFunction change_cb = NULL;
CallbackFunction right_cb = NULL;
CallbackFunction left_cb = NULL;
CallbackFunction lower_cb = NULL;
CallbackFunction upper_cb = NULL;
CallbackFunction speedup_start_cb = NULL;
CallbackFunction speedup_end_cb = NULL;
public:
ESPRotary();
ESPRotary(byte pin1, byte pin2, byte steps_per_click = 1, int lower_bound = INT16_MIN, int upper_bound = INT16_MAX, int inital_pos = 0, int increment = 1);
void begin(byte pin1, byte pin2, byte steps_per_click = 1, int lower_bound = INT16_MIN, int upper_bound = INT16_MAX, int inital_pos = 0, int increment = 1);
int getPosition() const;
void resetPosition(int p = 0, bool fireCallback = true);
void triggerOnBounds(bool triggerEvents = true);
rotary_direction getDirection() const;
String directionToString(rotary_direction dir) const;
void setIncrement(int increment);
int getIncrement() const;
void enableSpeedup(bool enable);
void setSpeedupInterval(int interval);
void setSpeedupIncrement(int increment);
bool isSpeedupEnabled() const;
int getSpeedupInterval() const;
int getSpeedupIncrement() const;
bool isInSpeedup() const;
rotary_event getLastEvent() const;
void retriggerEvent(bool retrigger);
void setUpperBound(int upper_bound);
void setLowerBound(int lower_bound);
int getUpperBound() const;
int getLowerBound() const;
void setStepsPerClick(int steps);
int getStepsPerClick() const;
void setChangedHandler(CallbackFunction f);
void setRightRotationHandler(CallbackFunction f);
void setLeftRotationHandler(CallbackFunction f);
void setUpperOverflowHandler(CallbackFunction f);
void setLowerOverflowHandler(CallbackFunction f);
void setSpeedupStartedHandler(CallbackFunction f);
void setSpeedupEndedHandler(CallbackFunction f);
int getID() const;
void setID(int newID);
bool operator==(ESPRotary &rhs);
void loop();
private:
static int _nextID;
void _callCallback(CallbackFunction callback);
void _setEvent(rotary_event e);
bool _wasRotated();
bool _isWithinBounds(bool triggerAlerts = false);
void _checkForSpeedup(unsigned long now);
void _setID();
};
/////////////////////////////////////////////////////////////////
#endif
/////////////////////////////////////////////////////////////////

5
maddius/maddius_matrix_control/components/esp_lan/CMakeLists.txt

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.5)
idf_component_register(SRCS "esp_lan.c"
PRIV_REQUIRES esp_netif driver esp_wifi vfs
INCLUDE_DIRS ".")
project(esp_lan)

0
maddius/maddius_matrix_control/components/esp_lan/esp_lan.c

51
maddius/maddius_matrix_control/components/esp_lan/esp_lan.h

@ -0,0 +1,51 @@
#include <stdlib.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef enum
{
W5500,
DM9051
} lan_eth_driver;
typedef struct
{
bool enabled;
uint16_t reset_io;
uint16_t miso_io;
uint16_t mosi_io;
uint16_t sclk_io;
uint16_t cs_io;
uint16_t phy_addr;
uint16_t spi_host;
uint16_t spi_mhz;
uint16_t stack_size;
uint16_t driver;
} lan_eth_config;
typedef struct
{
int rssi;
uint16_t authmode;
} wifi_config_threshold;
typedef struct {
bool enabled;
char *ssid;
char *password;
uint16_t scan_method;
uint16_t sort_method;
struct wifi_config_threshold *threshold;
} wifi_config;
typedef struct
{
struct lan_eth_config *eth;
struct wifi_config *wifi;
} network_config;
#ifdef __cplusplus
}
#endif

17
maddius/maddius_matrix_control/components/esp_server/CMakeLists.txt

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.5)
# set(COMPONENT_REQUIRES "esp_timer")
# set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
set(COMPONENT_REQUIRES "protocol_examples_common")
idf_component_register(SRCS "esp_server.c" "keep_alive.c" "udp_server.c" "websocket_client.c"
REQUIRES "esp_timer" "esp_event" "nvs_flash" "esp_netif" "esp_eth" "esp_wifi" "protocol_examples_common" "esp_https_server" "json_parser" "esp_websocket_client"
INCLUDE_DIRS "."
EMBED_TXTFILES "certs/servercert.pem"
"certs/prvtkey.pem"
"esp_vue/dist/index.html"
"esp_vue/dist/favicon.ico"
"esp_vue/dist/assets/SettingsView.css"
"esp_vue/dist/assets/SettingsView.js"
"esp_vue/dist/assets/index.css"
"esp_vue/dist/assets/index.js")
project(server)

39
maddius/maddius_matrix_control/components/esp_server/Kconfig.projbuild

@ -0,0 +1,39 @@
menu "Example Configuration"
config EXAMPLE_IPV4
bool "IPV4"
default y
config EXAMPLE_IPV6
bool "IPV6"
default n
select EXAMPLE_CONNECT_IPV6
config EXAMPLE_PORT
int "Port"
range 0 65535
default 9003
help
Local port the example server will listen on.
choice WEBSOCKET_URI_SOURCE
prompt "Websocket URI source"
default WEBSOCKET_URI_FROM_STRING
help
Selects the source of the URI used in the example.
config WEBSOCKET_URI_FROM_STRING
bool "From string"
config WEBSOCKET_URI_FROM_STDIN
bool "From stdin"
endchoice
config WEBSOCKET_URI
string "Websocket endpoint URI"
depends on WEBSOCKET_URI_FROM_STRING
default "ws://localhost:9999/qlcplusWS"
help
URL of websocket endpoint this example connects to and sends echo
endmenu

28
maddius/maddius_matrix_control/components/esp_server/certs/prvtkey.pem

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCwYp7epz++0QkH
JioMD7U7BitLgpcYPi8Cid1l7snt6Kp546iQsDBJ3l8xnRtPU7ANEsjT8KxIHmyw
h/NGp94FlOKRw3ahh3yUGtowS9vdHv+S+TAfuj07NjSnKIyv5KnGZJ+fDFl4Q1tT
aQJybY1Z4itirL6/2CGEm8g/iYhLNDBsRMfpDpfXe4URyWiM3Rhf7ztqZdveb9al
3pAJZIDTLWCFQI1MvQjKamkAQkES/gZj0iUZFwbGJPBj54nkuLFLKedw7DbwgrVg
0+n3fQ9b/gQepw5PxQjyobY2DsDgGZV+MFjUmaUTa+XX68SrG4wJ+DwrkdmpHReB
vFi1Hg1hAgMBAAECggEAaTCnZkl/7qBjLexIryC/CBBJyaJ70W1kQ7NMYfniWwui
f0aRxJgOdD81rjTvkINsPp+xPRQO6oOadjzdjImYEuQTqrJTEUnntbu924eh+2D9
Mf2CAanj0mglRnscS9mmljZ0KzoGMX6Z/EhnuS40WiJTlWlH6MlQU/FDnwC6U34y
JKy6/jGryfsx+kGU/NRvKSru6JYJWt5v7sOrymHWD62IT59h3blOiP8GMtYKeQlX
49om9Mo1VTIFASY3lrxmexbY+6FG8YO+tfIe0tTAiGrkb9Pz6tYbaj9FjEWOv4Vc
+3VMBUVdGJjgqvE8fx+/+mHo4Rg69BUPfPSrpEg7sQKBgQDlL85G04VZgrNZgOx6
pTlCCl/NkfNb1OYa0BELqWINoWaWQHnm6lX8YjrUjwRpBF5s7mFhguFjUjp/NW6D
0EEg5BmO0ePJ3dLKSeOA7gMo7y7kAcD/YGToqAaGljkBI+IAWK5Su5yldrECTQKG
YnMKyQ1MWUfCYEwHtPvFvE5aPwKBgQDFBWXekpxHIvt/B41Cl/TftAzE7/f58JjV
MFo/JCh9TDcH6N5TMTRS1/iQrv5M6kJSSrHnq8pqDXOwfHLwxetpk9tr937VRzoL
CuG1Ar7c1AO6ujNnAEmUVC2DppL/ck5mRPWK/kgLwZSaNcZf8sydRgphsW1ogJin
7g0nGbFwXwKBgQCPoZY07Pr1TeP4g8OwWTu5F6dSvdU2CAbtZthH5q98u1n/cAj1
noak1Srpa3foGMTUn9CHu+5kwHPIpUPNeAZZBpq91uxa5pnkDMp3UrLIRJ2uZyr8
4PxcknEEh8DR5hsM/IbDcrCJQglM19ZtQeW3LKkY4BsIxjDf45ymH407IQKBgE/g
Ul6cPfOxQRlNLH4VMVgInSyyxWx1mODFy7DRrgCuh5kTVh+QUVBM8x9lcwAn8V9/
nQT55wR8E603pznqY/jX0xvAqZE6YVPcw4kpZcwNwL1RhEl8GliikBlRzUL3SsW3
q30AfqEViHPE3XpE66PPo6Hb1ymJCVr77iUuC3wtAoGBAIBrOGunv1qZMfqmwAY2
lxlzRgxgSiaev0lTNxDzZkmU/u3dgdTwJ5DDANqPwJc6b8SGYTp9rQ0mbgVHnhIB
jcJQBQkTfq6Z0H6OoTVi7dPs3ibQJFrtkoyvYAbyk36quBmNRjVh6rc8468bhXYr
v/t+MeGJP/0Zw8v/X2CFll96
-----END PRIVATE KEY-----

19
maddius/maddius_matrix_control/components/esp_server/certs/servercert.pem

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL
BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx
MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ
UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T
sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k
qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd
GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4
sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb
jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/
ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3
emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY
W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx
bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN
ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl
hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=
-----END CERTIFICATE-----

559
maddius/maddius_matrix_control/components/esp_server/esp_server.c

@ -0,0 +1,559 @@
/* Simple HTTP + SSL + WS Server Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_event.h>
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_wifi.h"
#include "protocol_examples_common.h"
#include "lwip/sockets.h"
#include <esp_https_server.h>
#include "keep_alive.h"
#include "sdkconfig.h"
#include "json_parser.h"
#if !CONFIG_HTTPD_WS_SUPPORT
#error This example cannot be used unless HTTPD_WS_SUPPORT is enabled in esp-http-server component configuration
#endif
struct async_resp_arg
{
httpd_handle_t hd;
int fd;
};
static const char *TAG_SERVER = "wss_echo_server";
static const size_t max_clients = 4;
/* An HTTP GET handler */
extern const uint8_t file_index_html_start[] asm("_binary_index_html_start");
// extern const uint8_t file_index_html_end[] asm("_binary_index_html_end");
// static esp_err_t index_html_handler(httpd_req_t *req)
// {
// httpd_resp_set_type(req, "text/html");
// httpd_resp_send(req, (char *)file_index_html_start, HTTPD_RESP_USE_STRLEN);
// return ESP_OK;
// }
// static const httpd_uri_t index_html = {
// .uri = "/",
// .method = HTTP_GET,
// .handler = index_html_handler};
httpd_handle_t *gserver = NULL;
int parse_json(char *payload, int length)
{
jparse_ctx_t jctx;
int ret = json_parse_start(&jctx, payload, length);
if (ret != OS_SUCCESS)
{
printf("Parser failed\n");
return -1;
}
int bf00, bf01;
if (json_obj_get_object(&jctx, "controls") == OS_SUCCESS)
{
printf("Found controls\n");
if (json_obj_get_int(&jctx, "bf00", &bf00) == OS_SUCCESS)
printf("bf00 %d\n", bf00);
if (json_obj_get_int(&jctx, "bf01", &bf01) == OS_SUCCESS)
printf("bf01 %d\n", bf01);
json_obj_leave_object(&jctx);
}
// char str_val[64];
// int int_val, num_elem;
// int64_t int64_val;
// bool bool_val;
// float float_val;
// if (json_obj_get_string(&jctx, "str_val", str_val, sizeof(str_val)) == OS_SUCCESS)
// printf("str_val %s\n", str_val);
// if (json_obj_get_float(&jctx, "float_val", &float_val) == OS_SUCCESS)
// printf("float_val %f\n", float_val);
// if (json_obj_get_int(&jctx, "int_val", &int_val) == OS_SUCCESS)
// printf("int_val %d\n", int_val);
// if (json_obj_get_bool(&jctx, "bool_val", &bool_val) == OS_SUCCESS)
// printf("bool_val %s\n", bool_val ? "true" : "false");
// if (json_obj_get_array(&jctx, "supported_el", &num_elem) == OS_SUCCESS)
// {
// printf("Array has %d elements\n", num_elem);
// int i;
// for (i = 0; i < num_elem; i++)
// {
// json_arr_get_string(&jctx, i, str_val, sizeof(str_val));
// printf("index %d: %s\n", i, str_val);
// }
// json_obj_leave_array(&jctx);
// }
// if (json_obj_get_object(&jctx, "features") == OS_SUCCESS)
// {
// printf("Found object\n");
// if (json_obj_get_bool(&jctx, "objects", &bool_val) == OS_SUCCESS)
// printf("objects %s\n", bool_val ? "true" : "false");
// if (json_obj_get_string(&jctx, "arrays", str_val, sizeof(str_val)) == OS_SUCCESS)
// printf("arrays %s\n", str_val);
// json_obj_leave_object(&jctx);
// }
// if (json_obj_get_int64(&jctx, "int_64", &int64_val) == OS_SUCCESS)
// printf("int64_val %lld\n", int64_val);
json_parse_end(&jctx);
return 0;
}
static esp_err_t all_to_index_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, (char *)file_index_html_start, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t all_to_index = {
.uri = "*",
.method = HTTP_GET,
.handler = all_to_index_handler};
extern const uint8_t file_favicon_ico_start[] asm("_binary_favicon_ico_start");
static esp_err_t favicon_ico_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "image/x-icon");
httpd_resp_send(req, (char *)file_favicon_ico_start, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t favicon_ico = {
.uri = "/favicon.ico",
.method = HTTP_GET,
.handler = favicon_ico_handler};
extern const uint8_t file_SettingsView_css_start[] asm("_binary_SettingsView_css_start");
static esp_err_t SettingsView_css_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/css");
httpd_resp_send(req, (char *)file_SettingsView_css_start, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t SettingsView_css = {
.uri = "/assets/SettingsView.css",
.method = HTTP_GET,
.handler = SettingsView_css_handler};
//
extern const uint8_t file_SettingsView_js_start[] asm("_binary_SettingsView_js_start"); // application/javascript
static esp_err_t SettingsView_js_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/javascript");
httpd_resp_send(req, (char *)file_SettingsView_js_start, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t SettingsView_js = {
.uri = "/assets/SettingsView.js",
.method = HTTP_GET,
.handler = SettingsView_js_handler};
//
extern const uint8_t file_index_css_start[] asm("_binary_index_css_start");
static esp_err_t index_css_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/css");
httpd_resp_send(req, (char *)file_index_css_start, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t index_css = {
.uri = "/assets/index.css",
.method = HTTP_GET,
.handler = index_css_handler};
//
extern const uint8_t file_index_js_start[] asm("_binary_index_js_start");
static esp_err_t index_js_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/javascript");
httpd_resp_send(req, (char *)file_index_js_start, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t index_js = {
.uri = "/assets/index.js",
.method = HTTP_GET,
.handler = index_js_handler};
//
// extern const uint8_t file_logo_svg_start[] asm("_binary_logo_svg_start");
// static esp_err_t logo_svg_handler(httpd_req_t *req)
// {
// httpd_resp_set_type(req, "image/svg");
// httpd_resp_send(req, (char *)file_logo_svg_start, HTTPD_RESP_USE_STRLEN);
// return ESP_OK;
// }
// static const httpd_uri_t logo_svg = {
// .uri = "/assets/logo.svg",
// .method = HTTP_GET,
// .handler = logo_svg_handler};
static void send_hello(void *arg)
{
static const char *data = "Hello client";
struct async_resp_arg *resp_arg = arg;
httpd_handle_t hd = resp_arg->hd;
int fd = resp_arg->fd;
httpd_ws_frame_t ws_pkt;
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
ws_pkt.payload = (uint8_t *)data;
ws_pkt.len = strlen(data);
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
httpd_ws_send_frame_async(hd, fd, &ws_pkt);
free(resp_arg);
}
static esp_err_t ws_handler(httpd_req_t *req)
{
if (req->method == HTTP_GET)
{
ESP_LOGI(TAG_SERVER, "Handshake done, the new connection was opened");
return ESP_OK;
}
httpd_ws_frame_t ws_pkt;
uint8_t *buf = NULL;
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
// First receive the full ws message
/* Set max_len = 0 to get the frame len */
esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 0);
if (ret != ESP_OK)
{
ESP_LOGE(TAG_SERVER, "httpd_ws_recv_frame failed to get frame len with %d", ret);
return ret;
}
ESP_LOGI(TAG_SERVER, "frame len is %d", ws_pkt.len);
if (ws_pkt.len)
{
/* ws_pkt.len + 1 is for NULL termination as we are expecting a string */
buf = calloc(1, ws_pkt.len + 1);
if (buf == NULL)
{
ESP_LOGE(TAG_SERVER, "Failed to calloc memory for buf");
return ESP_ERR_NO_MEM;
}
ws_pkt.payload = buf;
/* Set max_len = ws_pkt.len to get the frame payload */
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
if (ret != ESP_OK)
{
ESP_LOGE(TAG_SERVER, "httpd_ws_recv_frame failed with %d", ret);
free(buf);
return ret;
}
}
// If it was a PONG, update the keep-alive
if (ws_pkt.type == HTTPD_WS_TYPE_PONG)
{
ESP_LOGD(TAG_SERVER, "Received PONG message");
free(buf);
return wss_keep_alive_client_is_active(httpd_get_global_user_ctx(req->handle),
httpd_req_to_sockfd(req));
// If it was a TEXT message, just echo it back
}
else if (ws_pkt.type == HTTPD_WS_TYPE_TEXT || ws_pkt.type == HTTPD_WS_TYPE_PING || ws_pkt.type == HTTPD_WS_TYPE_CLOSE)
{
if (ws_pkt.type == HTTPD_WS_TYPE_TEXT)
{
ESP_LOGI(TAG_SERVER, "Received packet with message: %s", ws_pkt.payload);
parse_json((char *)ws_pkt.payload, strlen((char *)ws_pkt.payload));
if (*gserver)
{ // httpd might not have been created by now
size_t clients = max_clients;
int client_fds[max_clients];
if (httpd_get_client_list(*gserver, &clients, client_fds) == ESP_OK)
{
for (size_t i = 0; i < clients; ++i)
{
int sock = client_fds[i];
if (httpd_ws_get_fd_info(*gserver, sock) == HTTPD_WS_CLIENT_WEBSOCKET)
{
ESP_LOGI(TAG_SERVER, "Active client (fd=%d) -> sending async message", sock);
// struct async_resp_arg *resp_arg = malloc(sizeof(struct async_resp_arg));
// resp_arg->hd = *gserver;
// resp_arg->fd = sock;
// if (httpd_queue_work(resp_arg->hd, send_hello, resp_arg) != ESP_OK)
// {
// ESP_LOGE(TAG_SERVER, "httpd_queue_work failed!");
// // send_messages = false;
// break;
// }
}
}
}
else
{
ESP_LOGE(TAG_SERVER, "httpd_get_client_list failed!");
}
}
}
else if (ws_pkt.type == HTTPD_WS_TYPE_PING)
{
// Response PONG packet to peer
ESP_LOGI(TAG_SERVER, "Got a WS PING frame, Replying PONG");
ws_pkt.type = HTTPD_WS_TYPE_PONG;
}
else if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE)
{
// Response CLOSE packet with no payload to peer
ws_pkt.len = 0;
ws_pkt.payload = NULL;
}
ret = httpd_ws_send_frame(req, &ws_pkt);
if (ret != ESP_OK)
{
ESP_LOGE(TAG_SERVER, "httpd_ws_send_frame failed with %d", ret);
}
ESP_LOGI(TAG_SERVER, "ws_handler: httpd_handle_t=%p, sockfd=%d, client_info:%d", req->handle,
httpd_req_to_sockfd(req), httpd_ws_get_fd_info(req->handle, httpd_req_to_sockfd(req)));
free(buf);
return ret;
}
free(buf);
return ESP_OK;
}
esp_err_t wss_open_fd(httpd_handle_t hd, int sockfd)
{
ESP_LOGI(TAG_SERVER, "New client connected %d", sockfd);
wss_keep_alive_t h = httpd_get_global_user_ctx(hd);
return wss_keep_alive_add_client(h, sockfd);
}
void wss_close_fd(httpd_handle_t hd, int sockfd)
{
ESP_LOGI(TAG_SERVER, "Client disconnected %d", sockfd);
wss_keep_alive_t h = httpd_get_global_user_ctx(hd);
wss_keep_alive_remove_client(h, sockfd);
close(sockfd);
}
static const httpd_uri_t ws = {
.uri = "/ws",
.method = HTTP_GET,
.handler = ws_handler,
.user_ctx = NULL,
.is_websocket = true,
.handle_ws_control_frames = true};
static void send_ping(void *arg)
{
struct async_resp_arg *resp_arg = arg;
httpd_handle_t hd = resp_arg->hd;
int fd = resp_arg->fd;
httpd_ws_frame_t ws_pkt;
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
ws_pkt.payload = NULL;
ws_pkt.len = 0;
ws_pkt.type = HTTPD_WS_TYPE_PING;
httpd_ws_send_frame_async(hd, fd, &ws_pkt);
free(resp_arg);
}
bool client_not_alive_cb(wss_keep_alive_t h, int fd)
{
ESP_LOGE(TAG_SERVER, "Client not alive, closing fd %d", fd);
httpd_sess_trigger_close(wss_keep_alive_get_user_ctx(h), fd);
return true;
}
bool check_client_alive_cb(wss_keep_alive_t h, int fd)
{
ESP_LOGD(TAG_SERVER, "Checking if client (fd=%d) is alive", fd);
struct async_resp_arg *resp_arg = malloc(sizeof(struct async_resp_arg));
resp_arg->hd = wss_keep_alive_get_user_ctx(h);
resp_arg->fd = fd;
if (httpd_queue_work(resp_arg->hd, send_ping, resp_arg) == ESP_OK)
{
return true;
}
return false;
}
static httpd_handle_t start_wss_echo_server(void)
{
// Prepare keep-alive engine
wss_keep_alive_config_t keep_alive_config = KEEP_ALIVE_CONFIG_DEFAULT();
keep_alive_config.max_clients = max_clients;
keep_alive_config.client_not_alive_cb = client_not_alive_cb;
keep_alive_config.check_client_alive_cb = check_client_alive_cb;
wss_keep_alive_t keep_alive = wss_keep_alive_start(&keep_alive_config);
// Start the httpd server
httpd_handle_t server = NULL;
ESP_LOGI(TAG_SERVER, "Starting server");
httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();
conf.transport_mode = HTTPD_SSL_TRANSPORT_INSECURE;
conf.httpd.max_open_sockets = max_clients;
conf.httpd.global_user_ctx = keep_alive;
conf.httpd.open_fn = wss_open_fd;
conf.httpd.close_fn = wss_close_fd;
// wildcard matcher
conf.httpd.uri_match_fn = httpd_uri_match_wildcard;
// Certificates
extern const unsigned char servercert_start[] asm("_binary_servercert_pem_start");
extern const unsigned char servercert_end[] asm("_binary_servercert_pem_end");
conf.servercert = servercert_start;
conf.servercert_len = servercert_end - servercert_start;
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
conf.prvtkey_pem = prvtkey_pem_start;
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
esp_err_t ret = httpd_ssl_start(&server, &conf);
if (ESP_OK != ret)
{
ESP_LOGI(TAG_SERVER, "Error starting server!");
return NULL;
}
// Set URI handlers
ESP_LOGI(TAG_SERVER, "Registering URI handlers");
httpd_register_uri_handler(server, &ws);
wss_keep_alive_set_user_ctx(keep_alive, server);
ESP_LOGI(TAG_SERVER, "Registering site URI handlers");
// httpd_register_uri_handler(server, &index_html);
httpd_register_uri_handler(server, &SettingsView_css);
httpd_register_uri_handler(server, &SettingsView_js);
httpd_register_uri_handler(server, &index_css);
// httpd_register_uri_handler(server, &logo_svg);
httpd_register_uri_handler(server, &index_js);
httpd_register_uri_handler(server, &favicon_ico);
httpd_register_uri_handler(server, &all_to_index);
return server;
}
static esp_err_t stop_wss_echo_server(httpd_handle_t server)
{
// Stop keep alive thread
wss_keep_alive_stop(httpd_get_global_user_ctx(server));
// Stop the httpd server
return httpd_ssl_stop(server);
}
void disconnect_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
httpd_handle_t *server = (httpd_handle_t *)arg;
if (*server)
{
if (stop_wss_echo_server(*server) == ESP_OK)
{
*server = NULL;
}
else
{
ESP_LOGE(TAG_SERVER, "Failed to stop https server");
}
}
}
void connect_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
httpd_handle_t *server = (httpd_handle_t *)arg;
ESP_LOGI(TAG_SERVER, "server %i", *server == NULL);
if (*server == NULL)
{
*server = start_wss_echo_server();
gserver = server;
ESP_LOGI(TAG_SERVER, "start_wss_echo_server started");
}
}
// Get all clients and send async message
static void wss_server_send_messages(httpd_handle_t *server)
{
bool send_messages = true;
// Send async message to all connected clients that use websocket protocol every 10 seconds
while (send_messages)
{
vTaskDelay(10000 / portTICK_PERIOD_MS);
if (!*server)
{ // httpd might not have been created by now
continue;
}
size_t clients = max_clients;
int client_fds[max_clients];
if (httpd_get_client_list(*server, &clients, client_fds) == ESP_OK)
{
for (size_t i = 0; i < clients; ++i)
{
int sock = client_fds[i];
if (httpd_ws_get_fd_info(*server, sock) == HTTPD_WS_CLIENT_WEBSOCKET)
{
ESP_LOGI(TAG_SERVER, "Active client (fd=%d) -> sending async message", sock);
struct async_resp_arg *resp_arg = malloc(sizeof(struct async_resp_arg));
resp_arg->hd = *server;
resp_arg->fd = sock;
if (httpd_queue_work(resp_arg->hd, send_hello, resp_arg) != ESP_OK)
{
ESP_LOGE(TAG_SERVER, "httpd_queue_work failed!");
send_messages = false;
break;
}
}
}
}
else
{
ESP_LOGE(TAG_SERVER, "httpd_get_client_list failed!");
return;
}
}
}
// void app_main(void)
// {
// static httpd_handle_t server = NULL;
// ESP_ERROR_CHECK(nvs_flash_init());
// ESP_ERROR_CHECK(esp_netif_init());
// ESP_ERROR_CHECK(esp_event_loop_create_default());
// /* Register event handlers to start server when Wi-Fi or Ethernet is connected,
// * and stop server when disconnection happens.
// */
// #ifdef CONFIG_EXAMPLE_CONNECT_WIFI
// ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server));
// ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server));
// #endif // CONFIG_EXAMPLE_CONNECT_WIFI
// #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
// ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server));
// ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server));
// #endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
// /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
// * Read "Establishing Wi-Fi or Ethernet Connection" section in
// * examples/protocols/README.md for more information about this function.
// */
// ESP_ERROR_CHECK(example_connect());
// /* This function demonstrates periodic sending Websocket messages
// * to all connected clients to this server
// */
// wss_server_send_messages(&server);
// }

21
maddius/maddius_matrix_control/components/esp_server/esp_server.h

@ -0,0 +1,21 @@
#pragma once
// #include "lwip/sys.h"
// #include <lwip/netdb.h>
// #include <arpa/inet.h>
#include <esp_event.h>
#ifdef __cplusplus
extern "C"
{
#endif
void disconnect_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data);
void connect_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data);
#ifdef __cplusplus
}
#endif

15
maddius/maddius_matrix_control/components/esp_server/esp_vue/.eslintrc.cjs

@ -0,0 +1,15 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

28
maddius/maddius_matrix_control/components/esp_server/esp_vue/.gitignore vendored

@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

8
maddius/maddius_matrix_control/components/esp_server/esp_vue/.prettierrc.json

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

46
maddius/maddius_matrix_control/components/esp_server/esp_vue/README.md

@ -0,0 +1,46 @@
# esp-vue
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```
### Lint with [ESLint](https://eslint.org/)
```sh
npm run lint
```

1
maddius/maddius_matrix_control/components/esp_server/esp_vue/env.d.ts vendored

@ -0,0 +1 @@
/// <reference types="vite/client" />

13
maddius/maddius_matrix_control/components/esp_server/esp_vue/index.html

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

7973
maddius/maddius_matrix_control/components/esp_server/esp_vue/package-lock.json generated

File diff suppressed because it is too large Load Diff

39
maddius/maddius_matrix_control/components/esp_server/esp_vue/package.json

@ -0,0 +1,39 @@
{
"name": "esp-vue",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"@kyvg/vue3-notification": "^3.0.2",
"pinia": "^2.1.6",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
"@types/node": "^18.18.7",
"@vitejs/plugin-vue": "^4.3.4",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.4.0",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"naive-ui": "^2.35.0",
"npm-run-all2": "^6.0.6",
"prettier": "^3.0.3",
"typescript": "~5.2.0",
"vfonts": "^0.0.3",
"vite": "^4.4.9",
"vue-tsc": "^1.8.11"
}
}

BIN
maddius/maddius_matrix_control/components/esp_server/esp_vue/public/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

134
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/App.vue

@ -0,0 +1,134 @@
<script lang="ts">
import { useNotification } from '@kyvg/vue3-notification'
import { RouterLink, RouterView } from 'vue-router'
const { notify } = useNotification()
// const connect = () => {
// console.log(this)
// }
export default {
test: console.log(this),
data() {
return {
ws: this.$ws,
notify
}
},
methods: {
// toggleWs() {
// this.$ws.connected ? this.$ws.connect() : this.$ws.disconnect()
// console.log(this)
// }
}
}
</script>
<template>
<header>
<!-- <img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" /> -->
<!-- <div class="wrapper"> -->
<!-- <HelloWorld msg="You did it!" /> -->
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/settings">Settings</RouterLink>
<RouterLink to="/qlc">qlc Iframe</RouterLink>
<RouterLink to="/qlc-ws">qlc Websocket</RouterLink>
<button @click="ws.connected ? ws.disconnect() : ws.connect()">
{{ ws.connected ? 'disconnect' : 'connect' }}
</button>
<button @click="ws.sendMessage({ controls: { bf00: 0 }, action: 'setControls' })">
setControl
</button>
<button @click="ws.sendMessage({ settings: { ssid: '', pass: '' }, action: 'setSettings' })">
setSettings
</button>
<button
@click="ws.sendMessage({ settings: { ssid: '', pass: '' }, action: 'applyAndReload' })"
>
applyAndReload
</button>
<button
@click="
notify({
title: 'Authorization',
text: 'You have been logged in!'
})
"
>
show note
</button>
<!-- { title: 'testTitle', text: 'testText' } -->
</nav>
<!-- </div> -->
</header>
<main>
<!-- <TheWelcome /> -->
<RouterView />
</main>
<notifications position="bottom right" />
</template>
<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
nav {
height: 24px;
font-size: 12px;
text-align: center;
/* margin-top: 2rem; */
}
nav a.router-link-exact-active {
color: var(--color-text);
}
nav a.router-link-exact-active:hover {
background-color: transparent;
}
nav a {
display: inline-block;
padding: 0 1rem;
border-left: 1px solid var(--color-border);
}
nav a:first-of-type {
border: 0;
}
/* @media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
nav {
text-align: left;
margin-left: -1rem;
font-size: 1rem;
padding: 1rem 0;
margin-top: 1rem;
}
} */
</style>

86
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/assets/base.css

@ -0,0 +1,86 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

1
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/assets/logo.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

After

Width:  |  Height:  |  Size: 276 B

35
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/assets/main.css

@ -0,0 +1,35 @@
@import './base.css';
#app {
/* max-width: 1280px; */
/* margin: 0 auto; */
/* padding: 2rem; */
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
/* @media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
} */

41
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/HelloWorld.vue

@ -0,0 +1,41 @@
<script setup lang="ts">
defineProps<{
msg: string
}>()
</script>
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
Youve successfully created a project with
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>. What's next?
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
position: relative;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>

88
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/TheWelcome.vue

@ -0,0 +1,88 @@
<script setup lang="ts">
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>Documentation</template>
Vues
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
provides you with all information you need to get started.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<ToolingIcon />
</template>
<template #heading>Tooling</template>
This project is served and bundled with
<a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
recommended IDE setup is
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
<a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
you need to test your components and web pages, check out
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
<a href="https://on.cypress.io/component" target="_blank" rel="noopener"
>Cypress Component Testing</a
>.
<br />
More instructions are available in <code>README.md</code>.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<EcosystemIcon />
</template>
<template #heading>Ecosystem</template>
Get official tools and libraries for your project:
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
you need more resources, we suggest paying
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
a visit.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<CommunityIcon />
</template>
<template #heading>Community</template>
Got stuck? Ask your question on
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
Discord server, or
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
>StackOverflow</a
>. You should also subscribe to
<a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
the official
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
twitter account for latest news in the Vue world.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<SupportIcon />
</template>
<template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help
us by
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
</WelcomeItem>
</template>

87
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/WelcomeItem.vue

@ -0,0 +1,87 @@
<template>
<div class="item">
<i>
<slot name="icon"></slot>
</i>
<div class="details">
<h3>
<slot name="heading"></slot>
</h3>
<slot></slot>
</div>
</div>
</template>
<style scoped>
.item {
margin-top: 2rem;
display: flex;
position: relative;
}
.details {
flex: 1;
margin-left: 1rem;
}
i {
display: flex;
place-items: center;
place-content: center;
width: 32px;
height: 32px;
color: var(--color-text);
}
h3 {
font-size: 1.2rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--color-heading);
}
@media (min-width: 1024px) {
.item {
margin-top: 0;
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
}
i {
top: calc(50% - 25px);
left: -26px;
position: absolute;
border: 1px solid var(--color-border);
background: var(--color-background);
border-radius: 8px;
width: 50px;
height: 50px;
}
.item:before {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
bottom: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:after {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
top: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:first-of-type:before {
display: none;
}
.item:last-of-type:after {
display: none;
}
}
</style>

7
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconCommunity.vue

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
/>
</svg>
</template>

7
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconDocumentation.vue

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
<path
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
/>
</svg>
</template>

7
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconEcosystem.vue

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
<path
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
/>
</svg>
</template>

7
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconSupport.vue

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
/>
</svg>
</template>

19
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/components/icons/IconTooling.vue

@ -0,0 +1,19 @@
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--mdi"
width="24"
height="24"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
>
<path
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
fill="currentColor"
></path>
</svg>
</template>

23
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/main.ts

@ -0,0 +1,23 @@
import './assets/main.css'
import Notifications from '@kyvg/vue3-notification'
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
import { WebsocketPlugin, type WebsocketPlugInterface } from './plugins/WebsocketPlugin'
import router from './router'
//declare the property so that it can be used by ts
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$ws: WebsocketPlugInterface
}
}
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(Notifications)
app.use(WebsocketPlugin)
app.mount('#app')

60
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/plugins/WebsocketPlugin/index.ts

@ -0,0 +1,60 @@
import { useNotification } from '@kyvg/vue3-notification'
import { reactive, type App, type Plugin } from 'vue'
const { notify } = useNotification()
// plugins/mebsocket.js
// const ws: Ref<WebSocket | undefined> = ref()
export interface WebsocketPluginOptions {
retryDelayTime?: string
addNotification?(): void
}
export interface WebsocketPlugInterface {
connected: boolean
socket?: WebSocket
connect(): void
disconnect(): void
sendMessage(payload: Object): void
}
export const WebsocketPlugin: Plugin = {
install(app: App, options: WebsocketPluginOptions) {
app.config.globalProperties.$ws = reactive({
connected: false,
socket: undefined,
connect: () => {
const url = 'ws://' + window.location.host + '/ws'
// if (process.env.NODE_ENV === 'development') {
// url = 'ws://192.168.1.206/ws'
// }
console.log('Starting connection to WebSocket Server', url)
const websocket = new WebSocket(url)
websocket.onmessage = (event) => {
console.log('onmessage', event)
}
websocket.onopen = (event) => {
notify({ text: 'Successfully connected', type: 'success' })
console.log(event)
app.config.globalProperties.$ws.connected = true
console.log('Successfully connected to the echo websocket server...')
}
websocket.onclose = () => {
app.config.globalProperties.$ws.connected = false
console.log('onclose')
}
addEventListener('unload', (event) => {
websocket.close()
console.log('unload')
})
app.config.globalProperties.$ws.socket = websocket
},
disconnect: () => {
console.log('disconnect WebSocket Server')
app.config.globalProperties.$ws.socket?.close()
},
sendMessage: (payload: Object) => {
console.log('sendMessage')
app.config.globalProperties.$ws.socket?.send(JSON.stringify(payload))
}
})
}
}

25
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/router/index.ts

@ -0,0 +1,25 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/settings',
name: 'settings',
component: () => import('../views/SettingsView.vue')
},
{
path: '/qlc',
name: 'qlc',
component: () => import('../views/QlcIframeView.vue')
}
]
})
export default router

55
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/stores/controlStore.ts

@ -0,0 +1,55 @@
import { defineStore } from 'pinia'
export const useControlStore = defineStore({
id: 'control',
state: () => ({
buttons: [],
faders: [],
constrols: {
bf00: 255,
bf01: 255,
bf02: 255,
bf03: 255,
bf04: 0,
bf05: 0,
bf06: 0,
bf07: 0,
bf08: 0,
bf09: 0,
bf10: 0,
bf11: 0,
bf12: 0,
bf13: 0,
bf14: 0,
bf15: 0,
bf16: 0,
bf17: 0,
bf18: 0,
bf19: 0,
bf20: 0,
bf21: 0,
bf22: 0,
bf23: 0,
bf24: 0,
bf25: 0,
bf26: 0,
bf27: 0,
bf28: 0,
bf29: 0,
fc00: 0,
fc01: 0,
fc02: 0,
fc03: 0,
fb00: 0,
fb01: 0,
fb02: 0,
fb03: 0,
fb04: 0,
fb05: 0,
fb06: 0,
fb07: 0
}
})
})

12
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/stores/counter.ts

@ -0,0 +1,12 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})

0
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/stores/settingsStore.ts

86
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/HomeView.vue

@ -0,0 +1,86 @@
<template>
<div class="about">
<h1>This is an about page</h1>
<canvas
id="myCanvas"
ref="canvasElement"
width="255"
height="255"
style="border: 1px solid grey; background-color: bisque"
></canvas>
<!-- <button @click="sendMessage()">send</button> -->
<button @click="ws.sendMessage({ action: 'subscribe' }), render()">subscribe</button>
</div>
</template>
<script lang="ts">
import { useNotification } from '@kyvg/vue3-notification'
import { ref, type Ref } from 'vue'
const { notify } = useNotification()
// const canvasElement: Ref<HTMLCanvasElement | undefined> = ref()
// const context: Ref<CanvasRenderingContext2D | undefined> = ref()
export default {
setup(): {
canvasElement: Ref<HTMLCanvasElement | undefined>
context: Ref<CanvasRenderingContext2D | undefined>
} {
const canvasElement = ref()
const context = ref()
// ...
console.log('canvasElement', canvasElement, canvasElement.value?.getContext('2d'))
return {
canvasElement,
context
}
},
mounted() {
console.log('mounted', this, this.canvasElement, this.canvasElement?.getContext('2d'))
this.context = this.canvasElement?.getContext('2d') || undefined
console.log('this.context', this.context)
this.render()
},
data() {
return {
ws: this.$ws
}
},
methods: {
// toggleWs() {
// this.$ws.connected ? this.$ws.connect() : this.$ws.disconnect()
// console.log(this)
// }
render() {
console.log('context', this.context)
if (!this.context) {
return
}
// this.context.fillText('jelledev.com', 50, 50)
this.context.beginPath()
// Define a start point
this.context.moveTo(128, 0)
// Define an end point
this.context.lineTo(128, 255)
// Define a start point
this.context.moveTo(0, 128)
// Define an end point
this.context.lineTo(255, 128)
this.context.stroke()
}
}
}
</script>
<style>
/* @media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
} */
</style>

29
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/QlcIframeView.vue

@ -0,0 +1,29 @@
<template>
<iframe id="qlciframe" src="http://localhost:9999/" title="qlc+"></iframe>
</template>
<script lang="ts">
import { useNotification } from '@kyvg/vue3-notification'
import { defineComponent } from 'vue'
import { useControlStore } from '../stores/controlStore'
const controlStore = useControlStore()
const { notify } = useNotification()
export default defineComponent({
data() {
return {
innerWidth: innerWidth,
innerHeight: innerHeight
}
},
mounted() {
console.log('mounted', this)
}
})
</script>
<style>
#qlciframe {
width: 100%;
height: calc(100vh - 30px);
}
</style>

0
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/QlcWsView.vue

116
maddius/maddius_matrix_control/components/esp_server/esp_vue/src/views/SettingsView.vue

@ -0,0 +1,116 @@
<template>
<!-- <div class="about">
<h1>This is an about page</h1>
<canvas
id="myCanvas"
ref="canvasElement"
width="255"
height="255"
style="border: 1px solid grey; background-color: bisque"
></canvas>
<button @click="sendMessage()">send</button>
<button @click="ws.sendMessage({ action: 'subscribe' }), render()">subscribe</button>
</div> -->
<n-grid :cols="2">
<n-grid-item>
<canvas
id="myCanvas"
ref="canvasElement"
width="255"
height="255"
style="border: 1px solid grey; background-color: bisque"
></canvas>
</n-grid-item>
<n-grid-item>
<button @click="ws.sendMessage({ action: 'subscribe' }), render()">subscribe</button>
<n-button>naive-ui</n-button>
<n-grid :cols="6">
<n-grid-item> </n-grid-item>
</n-grid>
</n-grid-item>
</n-grid>
</template>
<script lang="ts">
import { useNotification } from '@kyvg/vue3-notification'
import { ref, type Ref } from 'vue'
const { notify } = useNotification()
// const canvasElement: Ref<HTMLCanvasElement | undefined> = ref()
// const context: Ref<CanvasRenderingContext2D | undefined> = ref()
import { NButton, NGrid, NGridItem } from 'naive-ui'
import { storeToRefs } from 'pinia'
import { defineComponent } from 'vue'
import { useControlStore } from '../stores/controlStore'
const controlStore = useControlStore()
// const { posts, loading, error } = storeToRefs(useControlStore())
export default defineComponent({
components: {
NButton,
NGrid,
NGridItem
},
setup(): {
canvasElement: Ref<HTMLCanvasElement | undefined>
context: Ref<CanvasRenderingContext2D | undefined>
} {
const canvasElement = ref()
const context = ref()
// ...
console.log('canvasElement', canvasElement, canvasElement.value?.getContext('2d'))
return {
canvasElement,
context,
...storeToRefs(useControlStore())
}
},
mounted() {
console.log('mounted', this)
this.context = this.canvasElement?.getContext('2d') || undefined
console.log('this.context', this.context)
this.render()
},
data() {
return {
ws: this.$ws
}
},
methods: {
// toggleWs() {
// this.$ws.connected ? this.$ws.connect() : this.$ws.disconnect()
// console.log(this)
// }
render() {
console.log('context', this.context)
if (!this.context) {
return
}
// this.context.fillText('jelledev.com', 50, 50)
this.context.beginPath()
// Define a start point
this.context.moveTo(128, 0)
// Define an end point
this.context.lineTo(128, 255)
// Define a start point
this.context.moveTo(0, 128)
// Define an end point
this.context.lineTo(255, 128)
this.context.stroke()
}
}
})
</script>
<style>
/* @media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
} */
</style>

12
maddius/maddius_matrix_control/components/esp_server/esp_vue/tsconfig.app.json

@ -0,0 +1,12 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

11
maddius/maddius_matrix_control/components/esp_server/esp_vue/tsconfig.json

@ -0,0 +1,11 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}

16
maddius/maddius_matrix_control/components/esp_server/esp_vue/tsconfig.node.json

@ -0,0 +1,16 @@
{
"extends": "@tsconfig/node18/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*"
],
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

24
maddius/maddius_matrix_control/components/esp_server/esp_vue/vite.config.ts

@ -0,0 +1,24 @@
import { fileURLToPath, URL } from 'node:url'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import { defineConfig } from 'vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
rollupOptions: {
output: {
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`
}
}
}
})

229
maddius/maddius_matrix_control/components/esp_server/keep_alive.c

@ -0,0 +1,229 @@
/* Keep Alive engine for wss server example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_log.h>
#include <esp_system.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "keep_alive.h"
#include "esp_timer.h"
typedef enum {
NO_CLIENT = 0,
CLIENT_FD_ADD,
CLIENT_FD_REMOVE,
CLIENT_UPDATE,
CLIENT_ACTIVE,
STOP_TASK,
} client_fd_action_type_t;
typedef struct {
client_fd_action_type_t type;
int fd;
uint64_t last_seen;
} client_fd_action_t;
typedef struct wss_keep_alive_storage {
size_t max_clients;
wss_check_client_alive_cb_t check_client_alive_cb;
wss_check_client_alive_cb_t client_not_alive_cb;
size_t keep_alive_period_ms;
size_t not_alive_after_ms;
void * user_ctx;
QueueHandle_t q;
client_fd_action_t clients[];
} wss_keep_alive_storage_t;
typedef struct wss_keep_alive_storage* wss_keep_alive_t;
static const char *TAG = "wss_keep_alive";
static uint64_t _tick_get_ms(void)
{
return esp_timer_get_time()/1000;
}
// Goes over active clients to find out how long we could sleep before checking who's alive
static uint64_t get_max_delay(wss_keep_alive_t h)
{
int64_t check_after_ms = 30000; // max delay, no need to check anyone
for (int i=0; i<h->max_clients; ++i) {
if (h->clients[i].type == CLIENT_ACTIVE) {
uint64_t check_this_client_at = h->clients[i].last_seen + h->keep_alive_period_ms;
if (check_this_client_at < check_after_ms + _tick_get_ms()) {
check_after_ms = check_this_client_at - _tick_get_ms();
if (check_after_ms < 0) {
check_after_ms = 1000; // min delay, some client(s) not responding already
}
}
}
}
return check_after_ms;
}
static bool update_client(wss_keep_alive_t h, int sockfd, uint64_t timestamp)
{
for (int i=0; i<h->max_clients; ++i) {
if (h->clients[i].type == CLIENT_ACTIVE && h->clients[i].fd == sockfd) {
h->clients[i].last_seen = timestamp;
return true;
}
}
return false;
}
static bool remove_client(wss_keep_alive_t h, int sockfd)
{
for (int i=0; i<h->max_clients; ++i) {
if (h->clients[i].type == CLIENT_ACTIVE && h->clients[i].fd == sockfd) {
h->clients[i].type = NO_CLIENT;
h->clients[i].fd = -1;
return true;
}
}
return false;
}
static bool add_new_client(wss_keep_alive_t h,int sockfd)
{
for (int i=0; i<h->max_clients; ++i) {
if (h->clients[i].type == NO_CLIENT) {
h->clients[i].type = CLIENT_ACTIVE;
h->clients[i].fd = sockfd;
h->clients[i].last_seen = _tick_get_ms();
return true; // success
}
}
return false;
}
static void keep_alive_task(void* arg)
{
wss_keep_alive_storage_t *keep_alive_storage = arg;
bool run_task = true;
client_fd_action_t client_action;
while (run_task) {
if (xQueueReceive(keep_alive_storage->q, (void *) &client_action,
get_max_delay(keep_alive_storage) / portTICK_PERIOD_MS) == pdTRUE) {
switch (client_action.type) {
case CLIENT_FD_ADD:
if (!add_new_client(keep_alive_storage, client_action.fd)) {
ESP_LOGE(TAG, "Cannot add new client");
}
break;
case CLIENT_FD_REMOVE:
if (!remove_client(keep_alive_storage, client_action.fd)) {
ESP_LOGE(TAG, "Cannot remove client fd:%d", client_action.fd);
}
break;
case CLIENT_UPDATE:
if (!update_client(keep_alive_storage, client_action.fd, client_action.last_seen)) {
ESP_LOGE(TAG, "Cannot find client fd:%d", client_action.fd);
}
break;
case STOP_TASK:
run_task = false;
break;
default:
ESP_LOGE(TAG, "Unexpected client action");
break;
}
} else {
// timeout: check if PING message needed
for (int i=0; i<keep_alive_storage->max_clients; ++i) {
if (keep_alive_storage->clients[i].type == CLIENT_ACTIVE) {
if (keep_alive_storage->clients[i].last_seen + keep_alive_storage->keep_alive_period_ms <= _tick_get_ms()) {
ESP_LOGD(TAG, "Haven't seen the client (fd=%d) for a while", keep_alive_storage->clients[i].fd);
if (keep_alive_storage->clients[i].last_seen + keep_alive_storage->not_alive_after_ms <= _tick_get_ms()) {
ESP_LOGE(TAG, "Client (fd=%d) not alive!", keep_alive_storage->clients[i].fd);
keep_alive_storage->client_not_alive_cb(keep_alive_storage, keep_alive_storage->clients[i].fd);
} else {
keep_alive_storage->check_client_alive_cb(keep_alive_storage, keep_alive_storage->clients[i].fd);
}
}
}
}
}
}
vQueueDelete(keep_alive_storage->q);
free(keep_alive_storage);
vTaskDelete(NULL);
}
wss_keep_alive_t wss_keep_alive_start(wss_keep_alive_config_t *config)
{
size_t queue_size = config->max_clients/2;
size_t client_list_size = config->max_clients + queue_size;
wss_keep_alive_t keep_alive_storage = calloc(1,
sizeof(wss_keep_alive_storage_t) + client_list_size* sizeof(client_fd_action_t));
if (keep_alive_storage == NULL) {
return false;
}
keep_alive_storage->check_client_alive_cb = config->check_client_alive_cb;
keep_alive_storage->client_not_alive_cb = config->client_not_alive_cb;
keep_alive_storage->max_clients = config->max_clients;
keep_alive_storage->not_alive_after_ms = config->not_alive_after_ms;
keep_alive_storage->keep_alive_period_ms = config->keep_alive_period_ms;
keep_alive_storage->user_ctx = config->user_ctx;
keep_alive_storage->q = xQueueCreate(queue_size, sizeof(client_fd_action_t));
if (xTaskCreate(keep_alive_task, "keep_alive_task", config->task_stack_size,
keep_alive_storage, config->task_prio, NULL) != pdTRUE) {
wss_keep_alive_stop(keep_alive_storage);
return false;
}
return keep_alive_storage;
}
void wss_keep_alive_stop(wss_keep_alive_t h)
{
client_fd_action_t stop = { .type = STOP_TASK };
xQueueSendToBack(h->q, &stop, 0);
// internal structs will be de-allocated in the task
}
esp_err_t wss_keep_alive_add_client(wss_keep_alive_t h, int fd)
{
client_fd_action_t client_fd_action = { .fd = fd, .type = CLIENT_FD_ADD};
if (xQueueSendToBack(h->q, &client_fd_action, 0) == pdTRUE) {
return ESP_OK;
}
return ESP_FAIL;
}
esp_err_t wss_keep_alive_remove_client(wss_keep_alive_t h, int fd)
{
client_fd_action_t client_fd_action = { .fd = fd, .type = CLIENT_FD_REMOVE};
if (xQueueSendToBack(h->q, &client_fd_action, 0) == pdTRUE) {
return ESP_OK;
}
return ESP_FAIL;
}
esp_err_t wss_keep_alive_client_is_active(wss_keep_alive_t h, int fd)
{
client_fd_action_t client_fd_action = { .fd = fd, .type = CLIENT_UPDATE,
.last_seen = _tick_get_ms()};
if (xQueueSendToBack(h->q, &client_fd_action, 0) == pdTRUE) {
return ESP_OK;
}
return ESP_FAIL;
}
void wss_keep_alive_set_user_ctx(wss_keep_alive_t h, void *ctx)
{
h->user_ctx = ctx;
}
void* wss_keep_alive_get_user_ctx(wss_keep_alive_t h)
{
return h->user_ctx;
}

106
maddius/maddius_matrix_control/components/esp_server/keep_alive.h

@ -0,0 +1,106 @@
/* Keep Alive engine for wss server example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#pragma once
#define KEEP_ALIVE_CONFIG_DEFAULT() \
{ \
.max_clients = 10, \
.task_stack_size = 2048, \
.task_prio = tskIDLE_PRIORITY + 1, \
.keep_alive_period_ms = 5000, \
.not_alive_after_ms = 10000, \
}
#ifdef __cplusplus
extern "C"
{
#endif
struct wss_keep_alive_storage;
typedef struct wss_keep_alive_storage *wss_keep_alive_t;
typedef bool (*wss_check_client_alive_cb_t)(wss_keep_alive_t h, int fd);
typedef bool (*wss_client_not_alive_cb_t)(wss_keep_alive_t h, int fd);
/**
* @brief Confiuration struct
*/
typedef struct
{
size_t max_clients; /*!< max number of clients */
size_t task_stack_size; /*!< stack size of the created task */
size_t task_prio; /*!< priority of the created task */
size_t keep_alive_period_ms; /*!< check every client after this time */
size_t not_alive_after_ms; /*!< consider client not alive after this time */
wss_check_client_alive_cb_t check_client_alive_cb; /*!< callback function to check if client is alive */
wss_client_not_alive_cb_t client_not_alive_cb; /*!< callback function to notify that the client is not alive */
void *user_ctx; /*!< user context available in the keep-alive handle */
} wss_keep_alive_config_t;
/**
* @brief Adds a new client to internal set of clients to keep an eye on
*
* @param h keep-alive handle
* @param fd socket file descriptor for this client
* @return ESP_OK on success
*/
esp_err_t wss_keep_alive_add_client(wss_keep_alive_t h, int fd);
/**
* @brief Removes this client from the set
*
* @param h keep-alive handle
* @param fd socket file descriptor for this client
* @return ESP_OK on success
*/
esp_err_t wss_keep_alive_remove_client(wss_keep_alive_t h, int fd);
/**
* @brief Notify that this client is alive
*
* @param h keep-alive handle
* @param fd socket file descriptor for this client
* @return ESP_OK on success
*/
esp_err_t wss_keep_alive_client_is_active(wss_keep_alive_t h, int fd);
/**
* @brief Starts keep-alive engine
*
* @param config keep-alive configuration
* @return keep alive handle
*/
wss_keep_alive_t wss_keep_alive_start(wss_keep_alive_config_t *config);
/**
* @brief Stops keep-alive engine
*
* @param h keep-alive handle
*/
void wss_keep_alive_stop(wss_keep_alive_t h);
/**
* @brief Sets user defined context
*
* @param h keep-alive handle
* @param ctx user context
*/
void wss_keep_alive_set_user_ctx(wss_keep_alive_t h, void *ctx);
/**
* @brief Gets user defined context
*
* @param h keep-alive handle
* @return ctx user context
*/
void *wss_keep_alive_get_user_ctx(wss_keep_alive_t h);
#ifdef __cplusplus
}
#endif

194
maddius/maddius_matrix_control/components/esp_server/udp_server.c

@ -0,0 +1,194 @@
/* BSD Socket API Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#define PORT CONFIG_EXAMPLE_PORT
static const char *TAG = "udp_server";
void udp_server_task(void *pvParameters)
{
char rx_buffer[128];
char addr_str[128];
int addr_family = (int)pvParameters;
int ip_protocol = 0;
struct sockaddr_in6 dest_addr;
while (1)
{
if (addr_family == AF_INET)
{
struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr_ip4->sin_family = AF_INET;
dest_addr_ip4->sin_port = htons(PORT);
ip_protocol = IPPROTO_IP;
}
else if (addr_family == AF_INET6)
{
bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un));
dest_addr.sin6_family = AF_INET6;
dest_addr.sin6_port = htons(PORT);
ip_protocol = IPPROTO_IPV6;
}
int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
if (sock < 0)
{
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket created");
#if defined(CONFIG_LWIP_NETBUF_RECVINFO) && !defined(CONFIG_EXAMPLE_IPV6)
int enable = 1;
lwip_setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));
#endif
#if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6)
if (addr_family == AF_INET6)
{
// Note that by default IPV6 binds to both protocols, it is must be disabled
// if both protocols used at the same time (used in CI)
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
}
#endif
// Set timeout
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err < 0)
{
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
}
ESP_LOGI(TAG, "Socket bound, port %d", PORT);
struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
socklen_t socklen = sizeof(source_addr);
#if defined(CONFIG_LWIP_NETBUF_RECVINFO) && !defined(CONFIG_EXAMPLE_IPV6)
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsgtmp;
u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
iov.iov_base = rx_buffer;
iov.iov_len = sizeof(rx_buffer);
msg.msg_control = cmsg_buf;
msg.msg_controllen = sizeof(cmsg_buf);
msg.msg_flags = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_name = (struct sockaddr *)&source_addr;
msg.msg_namelen = socklen;
#endif
while (1)
{
ESP_LOGI(TAG, "Waiting for data");
#if defined(CONFIG_LWIP_NETBUF_RECVINFO) && !defined(CONFIG_EXAMPLE_IPV6)
int len = recvmsg(sock, &msg, 0);
#else
int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen);
#endif
// Error occurred during receiving
if (len < 0)
{
ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);
break;
}
// Data received
else
{
// Get the sender's ip address as string
if (source_addr.ss_family == PF_INET)
{
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
#if defined(CONFIG_LWIP_NETBUF_RECVINFO) && !defined(CONFIG_EXAMPLE_IPV6)
for (cmsgtmp = CMSG_FIRSTHDR(&msg); cmsgtmp != NULL; cmsgtmp = CMSG_NXTHDR(&msg, cmsgtmp))
{
if (cmsgtmp->cmsg_level == IPPROTO_IP && cmsgtmp->cmsg_type == IP_PKTINFO)
{
struct in_pktinfo *pktinfo;
pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgtmp);
ESP_LOGI(TAG, "dest ip: %s", inet_ntoa(pktinfo->ipi_addr));
}
}
#endif
}
else if (source_addr.ss_family == PF_INET6)
{
inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
}
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string...
ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
ESP_LOGI(TAG, "%s", rx_buffer);
int err = sendto(sock, rx_buffer, len, 0, (struct sockaddr *)&source_addr, sizeof(source_addr));
if (err < 0)
{
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
break;
}
}
}
// dont restart
// if (sock != -1)
// {
// ESP_LOGE(TAG, "Shutting down socket and restarting...");
// shutdown(sock, 0);
// close(sock);
// }
}
vTaskDelete(NULL);
}
// void app_main(void)
// {
// ESP_ERROR_CHECK(nvs_flash_init());
// ESP_ERROR_CHECK(esp_netif_init());
// ESP_ERROR_CHECK(esp_event_loop_create_default());
// /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
// * Read "Establishing Wi-Fi or Ethernet Connection" section in
// * examples/protocols/README.md for more information about this function.
// */
// ESP_ERROR_CHECK(example_connect());
// #ifdef CONFIG_EXAMPLE_IPV4
// xTaskCreate(udp_server_task, "udp_server", 4096, (void*)AF_INET, 5, NULL);
// #endif
// #ifdef CONFIG_EXAMPLE_IPV6
// xTaskCreate(udp_server_task, "udp_server", 4096, (void*)AF_INET6, 5, NULL);
// #endif
// }

11
maddius/maddius_matrix_control/components/esp_server/udp_server.h

@ -0,0 +1,11 @@
#ifdef __cplusplus
extern "C"
{
#endif
void udp_server_task(void *pvParameters);
#ifdef __cplusplus
}
#endif

157
maddius/maddius_matrix_control/components/esp_server/websocket_client.c

@ -0,0 +1,157 @@
/* ESP HTTP Client Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "protocol_examples_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "esp_websocket_client.h"
#include "esp_event.h"
#include "websocket_client.h"
#define NO_DATA_TIMEOUT_SEC 10
static const char *TAG = "WEBSOCKET";
static TimerHandle_t shutdown_signal_timer;
static SemaphoreHandle_t shutdown_sema;
static void shutdown_signaler(TimerHandle_t xTimer)
{
ESP_LOGI(TAG, "No data received for %d seconds, signaling shutdown", NO_DATA_TIMEOUT_SEC);
xSemaphoreGive(shutdown_sema);
}
#if CONFIG_WEBSOCKET_URI_FROM_STDIN
static void get_string(char *line, size_t size)
{
int count = 0;
while (count < size)
{
int c = fgetc(stdin);
if (c == '\n')
{
line[count] = '\0';
break;
}
else if (c > 0 && c < 127)
{
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
#endif /* CONFIG_WEBSOCKET_URI_FROM_STDIN */
static void websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
switch (event_id)
{
case WEBSOCKET_EVENT_CONNECTED:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
break;
case WEBSOCKET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DISCONNECTED");
break;
case WEBSOCKET_EVENT_DATA:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DATA");
ESP_LOGI(TAG, "Received opcode=%d", data->op_code);
ESP_LOGW(TAG, "Received=%.*s", data->data_len, (char *)data->data_ptr);
ESP_LOGW(TAG, "Total payload length=%d, data_len=%d, current payload offset=%d\r\n", data->payload_len, data->data_len, data->payload_offset);
xTimerReset(shutdown_signal_timer, portMAX_DELAY);
break;
case WEBSOCKET_EVENT_ERROR:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_ERROR");
break;
}
}
// TODO write task
void websocket_client_start(void)
{
esp_websocket_client_config_t websocket_cfg = {};
shutdown_signal_timer = xTimerCreate("Websocket shutdown timer", NO_DATA_TIMEOUT_SEC * 1000 / portTICK_PERIOD_MS,
pdFALSE, NULL, shutdown_signaler);
shutdown_sema = xSemaphoreCreateBinary();
#if CONFIG_WEBSOCKET_URI_FROM_STDIN
char line[128];
ESP_LOGI(TAG, "Please enter uri of websocket endpoint");
get_string(line, sizeof(line));
websocket_cfg.uri = line;
ESP_LOGI(TAG, "Endpoint uri: %s\n", line);
#else
websocket_cfg.uri = CONFIG_WEBSOCKET_URI;
#endif /* CONFIG_WEBSOCKET_URI_FROM_STDIN */
ESP_LOGI(TAG, "Connecting to %s...", websocket_cfg.uri);
esp_websocket_client_handle_t client = esp_websocket_client_init(&websocket_cfg);
esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, websocket_event_handler, (void *)client);
esp_websocket_client_start(client);
xTimerStart(shutdown_signal_timer, portMAX_DELAY);
char data[32];
int i = 0;
while (i < 10)
{
if (esp_websocket_client_is_connected(client))
{
int len = sprintf(data, "hello %04d", i++);
ESP_LOGI(TAG, "Sending %s", data);
esp_websocket_client_send_text(client, data, len, portMAX_DELAY);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
xSemaphoreTake(shutdown_sema, portMAX_DELAY);
esp_websocket_client_stop(client);
ESP_LOGI(TAG, "Websocket Stopped");
esp_websocket_client_destroy(client);
}
// void app_main(void)
// {
// ESP_LOGI(TAG, "[APP] Startup..");
// ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
// ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
// esp_log_level_set("*", ESP_LOG_INFO);
// esp_log_level_set("WEBSOCKET_CLIENT", ESP_LOG_DEBUG);
// esp_log_level_set("TRANS_TCP", ESP_LOG_DEBUG);
// ESP_ERROR_CHECK(nvs_flash_init());
// ESP_ERROR_CHECK(esp_netif_init());
// ESP_ERROR_CHECK(esp_event_loop_create_default());
// /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
// * Read "Establishing Wi-Fi or Ethernet Connection" section in
// * examples/protocols/README.md for more information about this function.
// */
// ESP_ERROR_CHECK(example_connect());
// websocket_app_start();
// }

11
maddius/maddius_matrix_control/components/esp_server/websocket_client.h

@ -0,0 +1,11 @@
#ifdef __cplusplus
extern "C"
{
#endif
void websocket_client_start(void);
#ifdef __cplusplus
}
#endif

1
maddius/maddius_matrix_control/components/espressif__arduino-esp32/.component_hash

@ -0,0 +1 @@
e946617ee6bec30ef0cff505bc537e658a80d7b9222c060e225bf748f2029442

271
maddius/maddius_matrix_control/components/espressif__arduino-esp32/CMakeLists.txt

@ -0,0 +1,271 @@
# Check ESP-IDF version and error out if it is not in the supported range.
#
# Note for arduino-esp32 developers: to bypass the version check locally,
# set ARDUINO_SKIP_IDF_VERSION_CHECK environment variable to 1. For example:
# export ARDUINO_SKIP_IDF_VERSION_CHECK=1
# idf.py build
set(min_supported_idf_version "5.1.0")
set(max_supported_idf_version "5.1.99")
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}")
if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}")
if (idf_version VERSION_LESS min_supported_idf_version)
message(FATAL_ERROR "Arduino-esp32 can be used with ESP-IDF versions "
"between ${min_supported_idf_version} and ${max_supported_idf_version}, "
"but an older version is detected: ${idf_version}.")
endif()
if (idf_version VERSION_GREATER max_supported_idf_version)
message(FATAL_ERROR "Arduino-esp32 can be used with ESP-IDF versions "
"between ${min_supported_idf_version} and ${max_supported_idf_version}, "
"but a newer version is detected: ${idf_version}.")
endif()
endif()
set(CORE_SRCS
cores/esp32/base64.cpp
cores/esp32/cbuf.cpp
cores/esp32/chip-debug-report.cpp
cores/esp32/esp32-hal-adc.c
cores/esp32/esp32-hal-bt.c
cores/esp32/esp32-hal-cpu.c
cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.c
cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-i2c-slave.c
cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c
cores/esp32/esp32-hal-misc.c
cores/esp32/esp32-hal-periman.c
cores/esp32/esp32-hal-psram.c
cores/esp32/esp32-hal-rgb-led.c
cores/esp32/esp32-hal-sigmadelta.c
cores/esp32/esp32-hal-spi.c
cores/esp32/esp32-hal-time.c
cores/esp32/esp32-hal-timer.c
cores/esp32/esp32-hal-tinyusb.c
cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-uart.c
cores/esp32/esp32-hal-rmt.c
cores/esp32/Esp.cpp
cores/esp32/FunctionalInterrupt.cpp
cores/esp32/HardwareSerial.cpp
cores/esp32/IPAddress.cpp
cores/esp32/IPv6Address.cpp
cores/esp32/libb64/cdecode.c
cores/esp32/libb64/cencode.c
cores/esp32/main.cpp
cores/esp32/MD5Builder.cpp
cores/esp32/Print.cpp
cores/esp32/stdlib_noniso.c
cores/esp32/Stream.cpp
cores/esp32/StreamString.cpp
cores/esp32/Tone.cpp
cores/esp32/HWCDC.cpp
cores/esp32/USB.cpp
cores/esp32/USBCDC.cpp
cores/esp32/USBMSC.cpp
cores/esp32/FirmwareMSC.cpp
cores/esp32/firmware_msc_fat.c
cores/esp32/wiring_pulse.c
cores/esp32/wiring_shift.c
cores/esp32/WMath.cpp
cores/esp32/WString.cpp
)
set(LIBRARY_SRCS
libraries/ArduinoOTA/src/ArduinoOTA.cpp
libraries/AsyncUDP/src/AsyncUDP.cpp
libraries/BluetoothSerial/src/BluetoothSerial.cpp
libraries/BluetoothSerial/src/BTAddress.cpp
libraries/BluetoothSerial/src/BTAdvertisedDeviceSet.cpp
libraries/BluetoothSerial/src/BTScanResultsSet.cpp
libraries/DNSServer/src/DNSServer.cpp
libraries/EEPROM/src/EEPROM.cpp
libraries/ESPmDNS/src/ESPmDNS.cpp
libraries/Ethernet/src/ETH.cpp
libraries/FFat/src/FFat.cpp
libraries/FS/src/FS.cpp
libraries/FS/src/vfs_api.cpp
libraries/HTTPClient/src/HTTPClient.cpp
libraries/HTTPUpdate/src/HTTPUpdate.cpp
libraries/LittleFS/src/LittleFS.cpp
libraries/Insights/src/Insights.cpp
libraries/I2S/src/I2S.cpp
libraries/NetBIOS/src/NetBIOS.cpp
libraries/Preferences/src/Preferences.cpp
libraries/RainMaker/src/RMaker.cpp
libraries/RainMaker/src/RMakerNode.cpp
libraries/RainMaker/src/RMakerParam.cpp
libraries/RainMaker/src/RMakerDevice.cpp
libraries/RainMaker/src/RMakerType.cpp
libraries/RainMaker/src/RMakerQR.cpp
libraries/RainMaker/src/RMakerUtils.cpp
libraries/RainMaker/src/AppInsights.cpp
libraries/SD_MMC/src/SD_MMC.cpp
libraries/SD/src/SD.cpp
libraries/SD/src/sd_diskio.cpp
libraries/SD/src/sd_diskio_crc.c
libraries/SimpleBLE/src/SimpleBLE.cpp
libraries/SPIFFS/src/SPIFFS.cpp
libraries/SPI/src/SPI.cpp
libraries/Ticker/src/Ticker.cpp
libraries/Update/src/Updater.cpp
libraries/Update/src/HttpsOTAUpdate.cpp
libraries/USB/src/USBHID.cpp
libraries/USB/src/USBHIDMouse.cpp
libraries/USB/src/USBHIDKeyboard.cpp
libraries/USB/src/USBHIDGamepad.cpp
libraries/USB/src/USBHIDConsumerControl.cpp
libraries/USB/src/USBHIDSystemControl.cpp
libraries/USB/src/USBHIDVendor.cpp
libraries/USB/src/USBVendor.cpp
libraries/WebServer/src/WebServer.cpp
libraries/WebServer/src/Parsing.cpp
libraries/WebServer/src/detail/mimetable.cpp
libraries/WiFiClientSecure/src/ssl_client.cpp
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp
libraries/WiFi/src/WiFiAP.cpp
libraries/WiFi/src/WiFiClient.cpp
libraries/WiFi/src/WiFi.cpp
libraries/WiFi/src/WiFiGeneric.cpp
libraries/WiFi/src/WiFiMulti.cpp
libraries/WiFi/src/WiFiScan.cpp
libraries/WiFi/src/WiFiServer.cpp
libraries/WiFi/src/WiFiSTA.cpp
libraries/WiFi/src/WiFiUdp.cpp
libraries/WiFiProv/src/WiFiProv.cpp
libraries/Wire/src/Wire.cpp
)
set(BLE_SRCS
libraries/BLE/src/BLE2902.cpp
libraries/BLE/src/BLE2904.cpp
libraries/BLE/src/BLEAddress.cpp
libraries/BLE/src/BLEAdvertisedDevice.cpp
libraries/BLE/src/BLEAdvertising.cpp
libraries/BLE/src/BLEBeacon.cpp
libraries/BLE/src/BLECharacteristic.cpp
libraries/BLE/src/BLECharacteristicMap.cpp
libraries/BLE/src/BLEClient.cpp
libraries/BLE/src/BLEDescriptor.cpp
libraries/BLE/src/BLEDescriptorMap.cpp
libraries/BLE/src/BLEDevice.cpp
libraries/BLE/src/BLEEddystoneTLM.cpp
libraries/BLE/src/BLEEddystoneURL.cpp
libraries/BLE/src/BLEExceptions.cpp
libraries/BLE/src/BLEHIDDevice.cpp
libraries/BLE/src/BLERemoteCharacteristic.cpp
libraries/BLE/src/BLERemoteDescriptor.cpp
libraries/BLE/src/BLERemoteService.cpp
libraries/BLE/src/BLEScan.cpp
libraries/BLE/src/BLESecurity.cpp
libraries/BLE/src/BLEServer.cpp
libraries/BLE/src/BLEService.cpp
libraries/BLE/src/BLEServiceMap.cpp
libraries/BLE/src/BLEUtils.cpp
libraries/BLE/src/BLEUUID.cpp
libraries/BLE/src/BLEValue.cpp
libraries/BLE/src/FreeRTOS.cpp
libraries/BLE/src/GeneralUtils.cpp
)
set(includedirs
variants/${CONFIG_ARDUINO_VARIANT}/
cores/esp32/
libraries/ArduinoOTA/src
libraries/AsyncUDP/src
libraries/BLE/src
libraries/BluetoothSerial/src
libraries/DNSServer/src
libraries/EEPROM/src
libraries/ESP32/src
libraries/ESPmDNS/src
libraries/Ethernet/src
libraries/FFat/src
libraries/FS/src
libraries/HTTPClient/src
libraries/HTTPUpdate/src
libraries/LittleFS/src
libraries/Insights/src
libraries/I2S/src
libraries/NetBIOS/src
libraries/Preferences/src
libraries/RainMaker/src
libraries/SD_MMC/src
libraries/SD/src
libraries/SimpleBLE/src
libraries/SPIFFS/src
libraries/SPI/src
libraries/Ticker/src
libraries/Update/src
libraries/USB/src
libraries/WebServer/src
libraries/WiFiClientSecure/src
libraries/WiFi/src
libraries/WiFiProv/src
libraries/Wire/src
)
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
set(priv_includes cores/esp32/libb64)
set(requires spi_flash mbedtls wifi_provisioning wpa_supplicant esp_adc esp_eth http_parser)
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid)
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
if(NOT CONFIG_FREERTOS_HZ EQUAL 1000 AND NOT "$ENV{ARDUINO_SKIP_TICK_CHECK}")
# See delay() in cores/esp32/esp32-hal-misc.c.
message(FATAL_ERROR "esp32-arduino requires CONFIG_FREERTOS_HZ=1000 "
"(currently ${CONFIG_FREERTOS_HZ})")
endif()
string(TOUPPER ${CONFIG_ARDUINO_VARIANT} idf_target_caps)
string(REPLACE "-" "_" idf_target_for_macro "${idf_target_caps}")
target_compile_options(${COMPONENT_TARGET} PUBLIC
-DARDUINO=10812
-DARDUINO_${idf_target_for_macro}_DEV
-DARDUINO_ARCH_ESP32
-DARDUINO_BOARD="${idf_target_caps}_DEV"
-DARDUINO_VARIANT="${CONFIG_ARDUINO_VARIANT}"
-DESP32)
if(CONFIG_AUTOSTART_ARDUINO)
# in autostart mode, arduino-esp32 contains app_main() function and needs to
# reference setup() and loop() in the main component. If we add main
# component to priv_requires then we create a large circular dependency
# (arduino-esp32 -> main -> arduino-esp32) and can get linker errors, so
# instead we add setup() and loop() to the undefined symbols list so the
# linker will always include them.
#
# (As they are C++ symbol, we need to add the C++ mangled names.)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u _Z5setupv -u _Z4loopv")
endif()
# This function adds a dependency on the given component if the component is included into the build.
function(maybe_add_component component_name)
idf_build_get_property(components BUILD_COMPONENTS)
if (${component_name} IN_LIST components)
idf_component_get_property(lib_name ${component_name} COMPONENT_LIB)
target_link_libraries(${COMPONENT_LIB} PUBLIC ${lib_name})
endif()
endfunction()
maybe_add_component(esp-dsp)
if(CONFIG_ESP_INSIGHTS_ENABLED)
maybe_add_component(esp_insights)
endif()
if(CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK)
maybe_add_component(esp_rainmaker)
maybe_add_component(qrcode)
endif()
if(IDF_TARGET MATCHES "esp32s2|esp32s3" AND CONFIG_TINYUSB_ENABLED)
maybe_add_component(arduino_tinyusb)
endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_ArduinoOTA)
maybe_add_component(esp_https_ota)
endif()
if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_LITTLEFS)
maybe_add_component(esp_littlefs)
endif()

412
maddius/maddius_matrix_control/components/espressif__arduino-esp32/Kconfig.projbuild

@ -0,0 +1,412 @@
menu "Arduino Configuration"
config ARDUINO_VARIANT
string "Arduino target variant (board)"
default IDF_TARGET
help
The name of a target variant (e.g., a specific board) in the variants/
folder, e.g. "heltec_wifi_lora_32_V2". The name is case sensitive.
Specifying a variant name different from the target enables additional
customization, for example the definition of GPIO pins.
config ENABLE_ARDUINO_DEPENDS
bool
select LWIP_SO_RCVBUF
select ETHERNET
select WIFI_ENABLED
select ESP32_PHY_CALIBRATION_AND_DATA_STORAGE if IDF_TARGET_ESP32
select MEMMAP_SMP
default "y"
config AUTOSTART_ARDUINO
bool "Autostart Arduino setup and loop on boot"
default "n"
help
Enabling this option will implement app_main and start Arduino.
All you need to implement in your main.cpp is setup() and loop()
and include Arduino.h
If disabled, you can call initArduino() to run any preparations
required by the framework
choice ARDUINO_RUNNING_CORE
bool "Core on which Arduino's setup() and loop() are running"
default ARDUINO_RUN_CORE0 if FREERTOS_UNICORE
default ARDUINO_RUN_CORE1 if !FREERTOS_UNICORE
help
Select on which core Arduino's setup() and loop() functions run
config ARDUINO_RUN_CORE0
bool "CORE 0"
config ARDUINO_RUN_CORE1
bool "CORE 1"
depends on !FREERTOS_UNICORE
config ARDUINO_RUN_NO_AFFINITY
bool "BOTH"
depends on !FREERTOS_UNICORE
endchoice
config ARDUINO_RUNNING_CORE
int
default 0 if ARDUINO_RUN_CORE0
default 1 if ARDUINO_RUN_CORE1
default -1 if ARDUINO_RUN_NO_AFFINITY
config ARDUINO_LOOP_STACK_SIZE
int "Loop thread stack size"
default 8192
help
Amount of stack available for the Arduino task.
choice ARDUINO_EVENT_RUNNING_CORE
bool "Core on which Arduino's event handler is running"
default ARDUINO_EVENT_RUN_CORE0 if FREERTOS_UNICORE
default ARDUINO_EVENT_RUN_CORE1 if !FREERTOS_UNICORE
help
Select on which core Arduino's WiFi.onEvent() run
config ARDUINO_EVENT_RUN_CORE0
bool "CORE 0"
config ARDUINO_EVENT_RUN_CORE1
bool "CORE 1"
depends on !FREERTOS_UNICORE
config ARDUINO_EVENT_RUN_NO_AFFINITY
bool "BOTH"
depends on !FREERTOS_UNICORE
endchoice
config ARDUINO_EVENT_RUNNING_CORE
int
default 0 if ARDUINO_EVENT_RUN_CORE0
default 1 if ARDUINO_EVENT_RUN_CORE1
default -1 if ARDUINO_EVENT_RUN_NO_AFFINITY
choice ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
bool "Core on which Arduino's Serial Event task is running"
default ARDUINO_SERIAL_EVENT_RUN_CORE0 if FREERTOS_UNICORE
default ARDUINO_SERIAL_EVENT_RUN_NO_AFFINITY if !FREERTOS_UNICORE
help
Select on which core Arduino's Serial Event task run
config ARDUINO_SERIAL_EVENT_RUN_CORE0
bool "CORE 0"
config ARDUINO_SERIAL_EVENT_RUN_CORE1
bool "CORE 1"
depends on !FREERTOS_UNICORE
config ARDUINO_SERIAL_EVENT_RUN_NO_AFFINITY
bool "BOTH"
depends on !FREERTOS_UNICORE
endchoice
config ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
int
default 0 if ARDUINO_SERIAL_EVENT_RUN_CORE0
default 1 if ARDUINO_SERIAL_EVENT_RUN_CORE1
default -1 if ARDUINO_SERIAL_EVENT_RUN_NO_AFFINITY
config ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
int "Serial Event task stack size"
default 2048
help
Amount of stack available for the Serial Event task.
config ARDUINO_SERIAL_EVENT_TASK_PRIORITY
int "Priority of the Serial Event task"
default 24
help
Select at what priority you want the Serial Event task to run.
choice ARDUINO_UDP_RUNNING_CORE
bool "Core on which Arduino's UDP is running"
default ARDUINO_UDP_RUN_CORE0
help
Select on which core Arduino's UDP run
config ARDUINO_UDP_RUN_CORE0
bool "CORE 0"
config ARDUINO_UDP_RUN_CORE1
bool "CORE 1"
depends on !FREERTOS_UNICORE
config ARDUINO_UDP_RUN_NO_AFFINITY
bool "BOTH"
depends on !FREERTOS_UNICORE
endchoice
config ARDUINO_UDP_RUNNING_CORE
int
default 0 if ARDUINO_UDP_RUN_CORE0
default 1 if ARDUINO_UDP_RUN_CORE1
default -1 if ARDUINO_UDP_RUN_NO_AFFINITY
config ARDUINO_UDP_TASK_PRIORITY
int "Priority of the UDP task"
default 3
help
Select at what priority you want the UDP task to run.
config ARDUINO_ISR_IRAM
bool "Run interrupts in IRAM"
default "n"
help
Enabling this option will Attach all interrupts with the IRAm flag.
It will also make some HAL function, like, digitalRead/Write and more
be loaded into IRAM for access inside ISRs.
Beware that this is a very dangerous setting. Enable it only if you
are fully aware of the consequences.
config DISABLE_HAL_LOCKS
bool "Disable mutex locks for HAL"
default "n"
help
Enabling this option will run all hardware abstraction without locks.
While communication with external hardware will be faster, you need to
make sure that there is no option to use the same bus from another thread
or interrupt at the same time. Option is best used with Arduino enabled
and code implemented only in setup/loop and Arduino callbacks
menu "Debug Log Configuration"
choice ARDUHAL_LOG_DEFAULT_LEVEL
bool "Default log level"
default ARDUHAL_LOG_DEFAULT_LEVEL_ERROR
help
Specify how much output to see in logs by default.
config ARDUHAL_LOG_DEFAULT_LEVEL_NONE
bool "No output"
config ARDUHAL_LOG_DEFAULT_LEVEL_ERROR
bool "Error"
config ARDUHAL_LOG_DEFAULT_LEVEL_WARN
bool "Warning"
config ARDUHAL_LOG_DEFAULT_LEVEL_INFO
bool "Info"
config ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG
bool "Debug"
config ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE
bool "Verbose"
endchoice
config ARDUHAL_LOG_DEFAULT_LEVEL
int
default 0 if ARDUHAL_LOG_DEFAULT_LEVEL_NONE
default 1 if ARDUHAL_LOG_DEFAULT_LEVEL_ERROR
default 2 if ARDUHAL_LOG_DEFAULT_LEVEL_WARN
default 3 if ARDUHAL_LOG_DEFAULT_LEVEL_INFO
default 4 if ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG
default 5 if ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE
config ARDUHAL_LOG_COLORS
bool "Use ANSI terminal colors in log output"
default "n"
help
Enable ANSI terminal color codes in bootloader output.
In order to view these, your terminal program must support ANSI color codes.
config ARDUHAL_ESP_LOG
bool "Forward ESP_LOGx to Arduino log output"
default "n"
help
This option will redefine the ESP_LOGx macros to Arduino's log_x macros.
To enable for your application, add the follwing after your includes:
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif
endmenu
choice ARDUHAL_PARTITION_SCHEME
bool "Used partition scheme"
default ARDUHAL_PARTITION_SCHEME_DEFAULT
help
Specify which partition scheme to be used.
config ARDUHAL_PARTITION_SCHEME_DEFAULT
bool "Default"
config ARDUHAL_PARTITION_SCHEME_MINIMAL
bool "Minimal (for 2MB FLASH)"
config ARDUHAL_PARTITION_SCHEME_NO_OTA
bool "No OTA (for large apps)"
config ARDUHAL_PARTITION_SCHEME_HUGE_APP
bool "Huge App (for very large apps)"
config ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS
bool "Minimal SPIFFS (for large apps with OTA)"
endchoice
config ARDUHAL_PARTITION_SCHEME
string
default "default" if ARDUHAL_PARTITION_SCHEME_DEFAULT
default "minimal" if ARDUHAL_PARTITION_SCHEME_MINIMAL
default "no_ota" if ARDUHAL_PARTITION_SCHEME_NO_OTA
default "huge_app" if ARDUHAL_PARTITION_SCHEME_HUGE_APP
default "min_spiffs" if ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS
config AUTOCONNECT_WIFI
bool "Autoconnect WiFi on boot"
default "n"
depends on AUTOSTART_ARDUINO
select ARDUINO_SELECTIVE_WiFi
help
If enabled, WiFi will connect to the last used SSID (if station was enabled),
else connection will be started only after calling WiFi.begin(ssid, password)
config ARDUINO_SELECTIVE_COMPILATION
bool "Include only specific Arduino libraries"
default n
config ARDUINO_SELECTIVE_ArduinoOTA
bool "Enable ArduinoOTA"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
select ARDUINO_SELECTIVE_ESPmDNS
default y
config ARDUINO_SELECTIVE_AsyncUDP
bool "Enable AsyncUDP"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_AzureIoT
bool "Enable AzureIoT"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_HTTPClient
default y
config ARDUINO_SELECTIVE_BLE
bool "Enable BLE"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_BluetoothSerial
bool "Enable BluetoothSerial"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_DNSServer
bool "Enable DNSServer"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_EEPROM
bool "Enable EEPROM"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_ESP32
bool "Enable ESP32"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_ESPmDNS
bool "Enable ESPmDNS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_FFat
bool "Enable FFat"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_FS
bool "Enable FS"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_HTTPClient
bool "Enable HTTPClient"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
select ARDUINO_SELECTIVE_WiFiClientSecure
default y
config ARDUINO_SELECTIVE_LITTLEFS
bool "Enable LITTLEFS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_NetBIOS
bool "Enable NetBIOS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_Preferences
bool "Enable Preferences"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_SD
bool "Enable SD"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_SD_MMC
bool "Enable SD_MMC"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_SimpleBLE
bool "Enable SimpleBLE"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_SPI
bool "Enable SPI"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_SPIFFS
bool "Enable SPIFFS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_Ticker
bool "Enable Ticker"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_Update
bool "Enable Update"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_WebServer
bool "Enable WebServer"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
select ARDUINO_SELECTIVE_FS
config ARDUINO_SELECTIVE_WiFi
bool "Enable WiFi"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_WiFiClientSecure
bool "Enable WiFiClientSecure"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_WiFiProv
bool "Enable WiFiProv"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_Wire
bool "Enable Wire"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
endmenu

239
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Arduino.h

@ -0,0 +1,239 @@
/*
Arduino.h - Main include file for the Arduino SDK
Copyright (c) 2005-2013 Arduino Team. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Arduino_h
#define Arduino_h
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "esp_arduino_version.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp32-hal.h"
#include "esp8266-compat.h"
#include "soc/gpio_reg.h"
#include "stdlib_noniso.h"
#include "binary.h"
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define EULER 2.718281828459045235360287471352
#define SERIAL 0x0
#define DISPLAY 0x1
#define LSBFIRST 0
#define MSBFIRST 1
//Interrupt Modes
#define RISING 0x01
#define FALLING 0x02
#define CHANGE 0x03
#define ONLOW 0x04
#define ONHIGH 0x05
#define ONLOW_WE 0x0C
#define ONHIGH_WE 0x0D
#define DEFAULT 1
#define EXTERNAL 0
#ifndef __STRINGIFY
#define __STRINGIFY(a) #a
#endif
// can't define max() / min() because of conflicts with C++
#define _min(a,b) ((a)<(b)?(a):(b))
#define _max(a,b) ((a)>(b)?(a):(b))
#define _abs(x) ((x)>0?(x):-(x)) // abs() comes from STL
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define _round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) // round() comes from STL
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
// ESP32xx runs FreeRTOS... disabling interrupts can lead to issues, such as Watchdog Timeout
#define sei() portENABLE_INTERRUPTS()
#define cli() portDISABLE_INTERRUPTS()
#define interrupts() sei()
#define noInterrupts() cli()
#define clockCyclesPerMicrosecond() ( (long int)getCpuFrequencyMhz() )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
// avr-libc defines _NOP() since 1.6.2
#ifndef _NOP
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
#endif
#define bit(b) (1UL << (b))
#define _BV(b) (1UL << (b))
#define digitalPinToTimer(pin) (0)
#define analogInPinToBit(P) (P)
#if SOC_GPIO_PIN_COUNT <= 32
#define digitalPinToPort(pin) (0)
#define digitalPinToBitMask(pin) (1UL << (pin))
#define portOutputRegister(port) ((volatile uint32_t*)GPIO_OUT_REG)
#define portInputRegister(port) ((volatile uint32_t*)GPIO_IN_REG)
#define portModeRegister(port) ((volatile uint32_t*)GPIO_ENABLE_REG)
#elif SOC_GPIO_PIN_COUNT <= 64
#define digitalPinToPort(pin) (((pin)>31)?1:0)
#define digitalPinToBitMask(pin) (1UL << (((pin)>31)?((pin)-32):(pin)))
#define portOutputRegister(port) ((volatile uint32_t*)((port)?GPIO_OUT1_REG:GPIO_OUT_REG))
#define portInputRegister(port) ((volatile uint32_t*)((port)?GPIO_IN1_REG:GPIO_IN_REG))
#define portModeRegister(port) ((volatile uint32_t*)((port)?GPIO_ENABLE1_REG:GPIO_ENABLE_REG))
#else
#error SOC_GPIO_PIN_COUNT > 64 not implemented
#endif
#define NOT_A_PIN -1
#define NOT_A_PORT -1
#define NOT_AN_INTERRUPT -1
#define NOT_ON_TIMER 0
// some defines generic for all SoC moved from variants/board_name/pins_arduino.h
#define NUM_DIGITAL_PINS SOC_GPIO_PIN_COUNT // All GPIOs
#if SOC_ADC_PERIPH_NUM == 1
#define NUM_ANALOG_INPUTS (SOC_ADC_CHANNEL_NUM(0)) // Depends on the SoC (ESP32C6, ESP32H2, ESP32C2, ESP32P4)
#elif SOC_ADC_PERIPH_NUM == 2
#define NUM_ANALOG_INPUTS (SOC_ADC_CHANNEL_NUM(0)+SOC_ADC_CHANNEL_NUM(1)) // Depends on the SoC (ESP32, ESP32S2, ESP32S3, ESP32C3)
#endif
#define EXTERNAL_NUM_INTERRUPTS NUM_DIGITAL_PINS // All GPIOs
#define analogInputToDigitalPin(p) (((p)<NUM_ANALOG_INPUTS)?(analogChannelToDigitalPin(p)):-1)
#define digitalPinToInterrupt(p) (((p)<NUM_DIGITAL_PINS)?(p):NOT_AN_INTERRUPT)
#define digitalPinHasPWM(p) ((p)<NUM_DIGITAL_PINS)
typedef bool boolean;
typedef uint8_t byte;
typedef unsigned int word;
#ifdef __cplusplus
void setup(void);
void loop(void);
// The default is using Real Hardware random number generator
// But when randomSeed() is called, it turns to Psedo random
// generator, exactly as done in Arduino mainstream
long random(long);
long random(long, long);
// Calling randomSeed() will make random()
// using pseudo random like in Arduino
void randomSeed(unsigned long);
// Allow the Application to decide if the random generator
// will use Real Hardware random generation (true - default)
// or Pseudo random generation (false) as in Arduino MainStream
void useRealRandomGenerator(bool useRandomHW);
#endif
long map(long, long, long, long, long);
#ifdef __cplusplus
extern "C" {
#endif
void init(void);
void initVariant(void);
void initArduino(void);
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout);
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
#ifdef __cplusplus
}
#include <algorithm>
#include <cmath>
#include "WCharacter.h"
#include "WString.h"
#include "Stream.h"
#include "Printable.h"
#include "Print.h"
#include "IPAddress.h"
#include "Client.h"
#include "Server.h"
#include "Udp.h"
#include "HardwareSerial.h"
#include "Esp.h"
// Use float-compatible stl abs() and round(), we don't use Arduino macros to avoid issues with the C++ libraries
using std::abs;
using std::isinf;
using std::isnan;
using std::max;
using std::min;
using std::round;
uint16_t makeWord(uint16_t w);
uint16_t makeWord(uint8_t h, uint8_t l);
#define word(...) makeWord(__VA_ARGS__)
size_t getArduinoLoopTaskStackSize(void);
#define SET_LOOP_TASK_STACK_SIZE(sz) size_t getArduinoLoopTaskStackSize() { return sz;}
bool shouldPrintChipDebugReport(void);
#define ENABLE_CHIP_DEBUG_REPORT bool shouldPrintChipDebugReport(void){return true;}
// allows user to bypass esp_spiram_test()
bool esp_psram_extram_test(void);
#define BYPASS_SPIRAM_TEST(bypass) bool testSPIRAM(void) { if (bypass) return true; else return esp_psram_extram_test(); }
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
extern "C" bool getLocalTime(struct tm * info, uint32_t ms = 5000);
extern "C" void configTime(long gmtOffset_sec, int daylightOffset_sec,
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
extern "C" void configTzTime(const char* tz,
const char* server1, const char* server2 = nullptr, const char* server3 = nullptr);
void setToneChannel(uint8_t channel = 0);
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
void noTone(uint8_t _pin);
#endif /* __cplusplus */
#include "pins_arduino.h"
#endif /* _ESP32_CORE_ARDUINO_H_ */

48
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Client.h

@ -0,0 +1,48 @@
/*
Client.h - Base class that provides Client
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef client_h
#define client_h
#include "Print.h"
#include "Stream.h"
#include "IPAddress.h"
class Client: public Stream
{
public:
virtual int connect(IPAddress ip, uint16_t port) =0;
virtual int connect(const char *host, uint16_t port) =0;
virtual size_t write(uint8_t) =0;
virtual size_t write(const uint8_t *buf, size_t size) =0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
protected:
uint8_t* rawIPAddress(IPAddress& addr)
{
return addr.raw_address();
}
};
#endif

471
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Esp.cpp

@ -0,0 +1,471 @@
/*
Esp.cpp - ESP31B-specific APIs
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Arduino.h"
#include "Esp.h"
#include "esp_sleep.h"
#include "spi_flash_mmap.h"
#include <memory>
#include <soc/soc.h>
#include <esp_partition.h>
extern "C" {
#include "esp_ota_ops.h"
#include "esp_image_format.h"
}
#include <MD5Builder.h>
#include "soc/spi_reg.h"
#include "esp_system.h"
#include "esp_chip_info.h"
#include "esp_mac.h"
#include "esp_flash.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/spi_flash.h"
#include "soc/efuse_reg.h"
#define ESP_FLASH_IMAGE_BASE 0x1000 // Flash offset containing flash size and spi mode
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/spi_flash.h"
#include "soc/efuse_reg.h"
#define ESP_FLASH_IMAGE_BASE 0x1000
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/spi_flash.h"
#include "soc/efuse_reg.h"
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32s3 is located at 0x0000
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/spi_flash.h"
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c3 is located at 0x0000
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/spi_flash.h"
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32c6 is located at 0x0000
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/spi_flash.h"
#define ESP_FLASH_IMAGE_BASE 0x0000 // Esp32h2 is located at 0x0000
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/spi_flash.h"
#define ESP_FLASH_IMAGE_BASE 0x1000
#endif
// REG_SPI_BASE is not defined for S3/C3 ??
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
#ifndef REG_SPI_BASE
#define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 )))
#endif // REG_SPI_BASE
#endif // TARGET
/**
* User-defined Literals
* usage:
*
* uint32_t = test = 10_MHz; // --> 10000000
*/
unsigned long long operator"" _kHz(unsigned long long x)
{
return x * 1000;
}
unsigned long long operator"" _MHz(unsigned long long x)
{
return x * 1000 * 1000;
}
unsigned long long operator"" _GHz(unsigned long long x)
{
return x * 1000 * 1000 * 1000;
}
unsigned long long operator"" _kBit(unsigned long long x)
{
return x * 1024;
}
unsigned long long operator"" _MBit(unsigned long long x)
{
return x * 1024 * 1024;
}
unsigned long long operator"" _GBit(unsigned long long x)
{
return x * 1024 * 1024 * 1024;
}
unsigned long long operator"" _kB(unsigned long long x)
{
return x * 1024;
}
unsigned long long operator"" _MB(unsigned long long x)
{
return x * 1024 * 1024;
}
unsigned long long operator"" _GB(unsigned long long x)
{
return x * 1024 * 1024 * 1024;
}
EspClass ESP;
void EspClass::deepSleep(uint32_t time_us)
{
esp_deep_sleep(time_us);
}
void EspClass::restart(void)
{
esp_restart();
}
uint32_t EspClass::getHeapSize(void)
{
return heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
}
uint32_t EspClass::getFreeHeap(void)
{
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
}
uint32_t EspClass::getMinFreeHeap(void)
{
return heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
}
uint32_t EspClass::getMaxAllocHeap(void)
{
return heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
}
uint32_t EspClass::getPsramSize(void)
{
if(psramFound()){
return heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
}
return 0;
}
uint32_t EspClass::getFreePsram(void)
{
if(psramFound()){
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
}
return 0;
}
uint32_t EspClass::getMinFreePsram(void)
{
if(psramFound()){
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
}
return 0;
}
uint32_t EspClass::getMaxAllocPsram(void)
{
if(psramFound()){
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
}
return 0;
}
static uint32_t sketchSize(sketchSize_t response) {
esp_image_metadata_t data;
const esp_partition_t *running = esp_ota_get_running_partition();
if (!running) return 0;
const esp_partition_pos_t running_pos = {
.offset = running->address,
.size = running->size,
};
data.start_addr = running_pos.offset;
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
if (response) {
return running_pos.size - data.image_len;
} else {
return data.image_len;
}
}
uint32_t EspClass::getSketchSize () {
return sketchSize(SKETCH_SIZE_TOTAL);
}
String EspClass::getSketchMD5()
{
static String result;
if (result.length()) {
return result;
}
uint32_t lengthLeft = getSketchSize();
const esp_partition_t *running = esp_ota_get_running_partition();
if (!running) {
log_e("Partition could not be found");
return String();
}
const size_t bufSize = SPI_FLASH_SEC_SIZE;
std::unique_ptr<uint8_t[]> buf(new uint8_t[bufSize]);
uint32_t offset = 0;
if(!buf.get()) {
log_e("Not enough memory to allocate buffer");
return String();
}
MD5Builder md5;
md5.begin();
while( lengthLeft > 0) {
size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
if (!ESP.flashRead(running->address + offset, reinterpret_cast<uint32_t*>(buf.get()), (readBytes + 3) & ~3)) {
log_e("Could not read buffer from flash");
return String();
}
md5.add(buf.get(), readBytes);
lengthLeft -= readBytes;
offset += readBytes;
}
md5.calculate();
result = md5.toString();
return result;
}
uint32_t EspClass::getFreeSketchSpace () {
const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
if(!_partition){
return 0;
}
return _partition->size;
}
uint16_t EspClass::getChipRevision(void)
{
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
return chip_info.revision;
}
const char * EspClass::getChipModel(void)
{
#if CONFIG_IDF_TARGET_ESP32
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_PACKAGE);
uint32_t pkg_ver = chip_ver & 0x7;
switch (pkg_ver) {
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6 :
if (getChipRevision() == 3)
return "ESP32-D0WDQ6-V3";
else
return "ESP32-D0WDQ6";
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5 :
if (getChipRevision() == 3)
return "ESP32-D0WD-V3";
else
return "ESP32-D0WD";
case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 :
return "ESP32-D2WD";
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 :
return "ESP32-PICO-D2";
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 :
return "ESP32-PICO-D4";
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302 :
return "ESP32-PICO-V3-02";
case EFUSE_RD_CHIP_VER_PKG_ESP32D0WDR2V3 :
return "ESP32-D0WDR2-V3";
default:
return "Unknown";
}
#elif CONFIG_IDF_TARGET_ESP32S2
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
switch (pkg_ver) {
case 0:
return "ESP32-S2";
case 1:
return "ESP32-S2FH16";
case 2:
return "ESP32-S2FH32";
default:
return "ESP32-S2 (Unknown)";
}
#else
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
switch(chip_info.model){
case CHIP_ESP32S3: return "ESP32-S3";
case CHIP_ESP32C3: return "ESP32-C3";
case CHIP_ESP32C2: return "ESP32-C2";
case CHIP_ESP32C6: return "ESP32-C6";
case CHIP_ESP32H2: return "ESP32-H2";
default: return "UNKNOWN";
}
#endif
}
uint8_t EspClass::getChipCores(void)
{
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
return chip_info.cores;
}
const char * EspClass::getSdkVersion(void)
{
return esp_get_idf_version();
}
const char * EspClass::getCoreVersion(void)
{
return ESP_ARDUINO_VERSION_STR;
}
uint32_t ESP_getFlashChipId(void)
{
uint32_t id = g_rom_flashchip.device_id;
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
return id;
}
uint32_t EspClass::getFlashChipSize(void)
{
uint32_t id = (ESP_getFlashChipId() >> 16) & 0xFF;
return 2 << (id - 1);
}
uint32_t EspClass::getFlashChipSpeed(void)
{
esp_image_header_t fhdr;
if(esp_flash_read(esp_flash_default_chip, (void*)&fhdr, ESP_FLASH_IMAGE_BASE, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) {
return 0;
}
return magicFlashChipSpeed(fhdr.spi_speed);
}
FlashMode_t EspClass::getFlashChipMode(void)
{
#if CONFIG_IDF_TARGET_ESP32S2
uint32_t spi_ctrl = REG_READ(PERIPHS_SPI_FLASH_CTRL);
#else
#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C6
uint32_t spi_ctrl = REG_READ(DR_REG_SPI0_BASE + 0x8);
#else
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
#endif
#endif
/* Not all of the following constants are already defined in older versions of spi_reg.h, so do it manually for now*/
if (spi_ctrl & BIT(24)) { //SPI_FREAD_QIO
return (FM_QIO);
} else if (spi_ctrl & BIT(20)) { //SPI_FREAD_QUAD
return (FM_QOUT);
} else if (spi_ctrl & BIT(23)) { //SPI_FREAD_DIO
return (FM_DIO);
} else if (spi_ctrl & BIT(14)) { // SPI_FREAD_DUAL
return (FM_DOUT);
} else if (spi_ctrl & BIT(13)) { //SPI_FASTRD_MODE
return (FM_FAST_READ);
} else {
return (FM_SLOW_READ);
}
return (FM_DOUT);
}
uint32_t EspClass::magicFlashChipSize(uint8_t byte)
{
switch(byte & 0x0F) {
case 0x0: // 8 MBit (1MB)
return (1_MB);
case 0x1: // 16 MBit (2MB)
return (2_MB);
case 0x2: // 32 MBit (4MB)
return (4_MB);
case 0x3: // 64 MBit (8MB)
return (8_MB);
case 0x4: // 128 MBit (16MB)
return (16_MB);
default: // fail?
return 0;
}
}
uint32_t EspClass::magicFlashChipSpeed(uint8_t byte)
{
switch(byte & 0x0F) {
case 0x0: // 40 MHz
return (40_MHz);
case 0x1: // 26 MHz
return (26_MHz);
case 0x2: // 20 MHz
return (20_MHz);
case 0xf: // 80 MHz
return (80_MHz);
default: // fail?
return 0;
}
}
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
{
FlashMode_t mode = (FlashMode_t) byte;
if(mode > FM_SLOW_READ) {
mode = FM_UNKNOWN;
}
return mode;
}
bool EspClass::flashEraseSector(uint32_t sector)
{
return esp_flash_erase_region(esp_flash_default_chip, sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE) == ESP_OK;
}
// Warning: These functions do not work with encrypted flash
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size)
{
return esp_flash_write(esp_flash_default_chip, (const void*) data, offset, size) == ESP_OK;
}
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
{
return esp_flash_read(esp_flash_default_chip, (void*) data, offset, size) == ESP_OK;
}
bool EspClass::partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size)
{
return esp_partition_erase_range(partition, offset, size) == ESP_OK;
}
bool EspClass::partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
{
return esp_partition_write(partition, offset, data, size) == ESP_OK;
}
bool EspClass::partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size)
{
return esp_partition_read(partition, offset, data, size) == ESP_OK;
}
uint64_t EspClass::getEfuseMac(void)
{
uint64_t _chipmacid = 0LL;
esp_efuse_mac_get_default((uint8_t*) (&_chipmacid));
return _chipmacid;
}

122
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/Esp.h

@ -0,0 +1,122 @@
/*
Esp.h - ESP31B-specific APIs
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ESP_H
#define ESP_H
#include <Arduino.h>
#include <esp_partition.h>
#include <hal/cpu_hal.h>
#include "esp_cpu.h"
/**
* AVR macros for WDT managment
*/
typedef enum {
WDTO_0MS = 0, //!< WDTO_0MS
WDTO_15MS = 15, //!< WDTO_15MS
WDTO_30MS = 30, //!< WDTO_30MS
WDTO_60MS = 60, //!< WDTO_60MS
WDTO_120MS = 120, //!< WDTO_120MS
WDTO_250MS = 250, //!< WDTO_250MS
WDTO_500MS = 500, //!< WDTO_500MS
WDTO_1S = 1000,//!< WDTO_1S
WDTO_2S = 2000,//!< WDTO_2S
WDTO_4S = 4000,//!< WDTO_4S
WDTO_8S = 8000 //!< WDTO_8S
} WDTO_t;
typedef enum {
FM_QIO = 0x00,
FM_QOUT = 0x01,
FM_DIO = 0x02,
FM_DOUT = 0x03,
FM_FAST_READ = 0x04,
FM_SLOW_READ = 0x05,
FM_UNKNOWN = 0xff
} FlashMode_t;
typedef enum {
SKETCH_SIZE_TOTAL = 0,
SKETCH_SIZE_FREE = 1
} sketchSize_t;
class EspClass
{
public:
EspClass() {}
~EspClass() {}
void restart();
//Internal RAM
uint32_t getHeapSize(); //total heap size
uint32_t getFreeHeap(); //available heap
uint32_t getMinFreeHeap(); //lowest level of free heap since boot
uint32_t getMaxAllocHeap(); //largest block of heap that can be allocated at once
//SPI RAM
uint32_t getPsramSize();
uint32_t getFreePsram();
uint32_t getMinFreePsram();
uint32_t getMaxAllocPsram();
uint16_t getChipRevision();
const char * getChipModel();
uint8_t getChipCores();
uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
inline uint32_t getCycleCount() __attribute__((always_inline));
const char * getSdkVersion(); //version of ESP-IDF
const char * getCoreVersion();//version of this core
void deepSleep(uint32_t time_us);
uint32_t getFlashChipSize();
uint32_t getFlashChipSpeed();
FlashMode_t getFlashChipMode();
uint32_t magicFlashChipSize(uint8_t byte);
uint32_t magicFlashChipSpeed(uint8_t byte);
FlashMode_t magicFlashChipMode(uint8_t byte);
uint32_t getSketchSize();
String getSketchMD5();
uint32_t getFreeSketchSpace();
bool flashEraseSector(uint32_t sector);
bool flashWrite(uint32_t offset, uint32_t *data, size_t size);
bool flashRead(uint32_t offset, uint32_t *data, size_t size);
bool partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size);
bool partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
bool partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size);
uint64_t getEfuseMac();
};
uint32_t ARDUINO_ISR_ATTR EspClass::getCycleCount()
{
return (uint32_t)esp_cpu_get_cycle_count();
}
extern EspClass ESP;
#endif //ESP_H

426
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FirmwareMSC.cpp

@ -0,0 +1,426 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "FirmwareMSC.h"
#if CONFIG_TINYUSB_MSC_ENABLED
#include <cstring>
#include "esp_partition.h"
#include "esp_ota_ops.h"
#include "esp_image_format.h"
#include "esp32-hal.h"
#include "pins_arduino.h"
#include "firmware_msc_fat.h"
#include "spi_flash_mmap.h"
#ifndef USB_FW_MSC_VENDOR_ID
#define USB_FW_MSC_VENDOR_ID "ESP32" //max 8 chars
#endif
#ifndef USB_FW_MSC_PRODUCT_ID
#define USB_FW_MSC_PRODUCT_ID "Firmware MSC"//max 16 chars
#endif
#ifndef USB_FW_MSC_PRODUCT_REVISION
#define USB_FW_MSC_PRODUCT_REVISION "1.0" //max 4 chars
#endif
#ifndef USB_FW_MSC_VOLUME_NAME
#define USB_FW_MSC_VOLUME_NAME "ESP32-FWMSC" //max 11 chars
#endif
#ifndef USB_FW_MSC_SERIAL_NUMBER
#define USB_FW_MSC_SERIAL_NUMBER 0x00000000
#endif
ESP_EVENT_DEFINE_BASE(ARDUINO_FIRMWARE_MSC_EVENTS);
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
//General Variables
static uint8_t * msc_ram_disk = NULL;
static fat_boot_sector_t * msc_boot = NULL;
static uint8_t * msc_table = NULL;
static uint16_t msc_table_sectors = 0;
static uint16_t msc_total_sectors = 0;
static bool mcs_is_fat16 = false;
//Firmware Read
static const esp_partition_t* msc_run_partition = NULL;
static uint16_t fw_start_sector = 0;
static uint16_t fw_end_sector = 0;
static size_t fw_size = 0;
static fat_dir_entry_t * fw_entry = NULL;
//Firmware Write
typedef enum {
MSC_UPDATE_IDLE,
MSC_UPDATE_STARTING,
MSC_UPDATE_RUNNING,
MSC_UPDATE_END
} msc_update_state_t;
static const esp_partition_t* msc_ota_partition = NULL;
static msc_update_state_t msc_update_state = MSC_UPDATE_IDLE;
static uint16_t msc_update_start_sector = 0;
static uint32_t msc_update_bytes_written = 0;
static fat_dir_entry_t * msc_update_entry = NULL;
static uint32_t get_firmware_size(const esp_partition_t* partition){
esp_image_metadata_t data;
const esp_partition_pos_t running_pos = {
.offset = partition->address,
.size = partition->size,
};
data.start_addr = running_pos.offset;
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
return data.image_len;
}
//Get number of sectors required based on the size of the firmware and OTA partition
static size_t msc_update_get_required_disk_sectors(){
size_t data_sectors = 16;
size_t total_sectors = 0;
msc_run_partition = esp_ota_get_running_partition();
msc_ota_partition = esp_ota_get_next_update_partition(NULL);
if(msc_run_partition){
fw_size = get_firmware_size(msc_run_partition);
data_sectors += FAT_SIZE_TO_SECTORS(fw_size);
log_d("APP size: %u (%u sectors)", fw_size, FAT_SIZE_TO_SECTORS(fw_size));
} else {
log_w("APP partition not found. Reading disabled");
}
if(msc_ota_partition){
data_sectors += FAT_SIZE_TO_SECTORS(msc_ota_partition->size);
log_d("OTA size: %u (%u sectors)", msc_ota_partition->size, FAT_SIZE_TO_SECTORS(msc_ota_partition->size));
} else {
log_w("OTA partition not found. Writing disabled");
}
msc_table_sectors = fat_sectors_per_alloc_table(data_sectors, false);
total_sectors = data_sectors + msc_table_sectors + 2;
if(total_sectors > 0xFF4){
log_d("USING FAT16");
mcs_is_fat16 = true;
total_sectors -= msc_table_sectors;
msc_table_sectors = fat_sectors_per_alloc_table(data_sectors, true);
total_sectors += msc_table_sectors;
} else {
log_d("USING FAT12");
mcs_is_fat16 = false;
}
log_d("FAT sector size: %u", DISK_SECTOR_SIZE);
log_d("FAT data sectors: %u", data_sectors);
log_d("FAT table sectors: %u", msc_table_sectors);
log_d("FAT total sectors: %u (%uKB)", total_sectors, (total_sectors * DISK_SECTOR_SIZE) / 1024);
return total_sectors;
}
//setup the ramdisk and add the firmware download file
static bool msc_update_setup_disk(const char * volume_label, uint32_t serial_number){
msc_total_sectors = msc_update_get_required_disk_sectors();
uint8_t ram_sectors = msc_table_sectors + 2;
msc_ram_disk = (uint8_t*)calloc(ram_sectors, DISK_SECTOR_SIZE);
if(!msc_ram_disk){
log_e("Failed to allocate RAM Disk: %u bytes", ram_sectors * DISK_SECTOR_SIZE);
return false;
}
fw_start_sector = ram_sectors;
fw_end_sector = fw_start_sector;
msc_boot = fat_add_boot_sector(msc_ram_disk, msc_total_sectors, msc_table_sectors, fat_file_system_type(mcs_is_fat16), volume_label, serial_number);
msc_table = fat_add_table(msc_ram_disk, msc_boot, mcs_is_fat16);
//fat_dir_entry_t * label = fat_add_label(msc_ram_disk, volume_label);
if(msc_run_partition){
fw_entry = fat_add_root_file(msc_ram_disk, 0, "FIRMWARE", "BIN", fw_size, 2, mcs_is_fat16);
fw_end_sector = FAT_SIZE_TO_SECTORS(fw_size) + fw_start_sector;
}
return true;
}
static void msc_update_delete_disk(){
fw_entry = NULL;
fw_size = 0;
fw_end_sector = 0;
fw_start_sector = 0;
msc_table = NULL;
msc_boot = NULL;
msc_table_sectors = 0;
msc_total_sectors = 0;
msc_run_partition = NULL;
msc_ota_partition = NULL;
msc_update_state = MSC_UPDATE_IDLE;
msc_update_start_sector = 0;
msc_update_bytes_written = 0;
msc_update_entry = NULL;
free(msc_ram_disk);
msc_ram_disk = NULL;
}
//filter out entries to only include BINs in the root folder
static fat_dir_entry_t * msc_update_get_root_bin_entry(uint8_t index){
fat_dir_entry_t * entry = (fat_dir_entry_t *)(msc_ram_disk + ((msc_boot->sectors_per_alloc_table+1) * DISK_SECTOR_SIZE) + (index * sizeof(fat_dir_entry_t)));
fat_lfn_entry_t * lfn = (fat_lfn_entry_t*)entry;
//empty entry
if(entry->file_magic == 0){
return NULL;
}
//long file name
if(lfn->attr == 0x0F && lfn->type == 0x00 && lfn->first_cluster == 0x0000){
return NULL;
}
//only files marked as archives
if(entry->file_attr != FAT_FILE_ATTR_ARCHIVE){
return NULL;
}
//deleted
if(entry->file_magic == 0xE5 || entry->file_magic == 0x05){
return NULL;
}
//not bins
if(memcmp("BIN", entry->file_extension, 3)){
return NULL;
}
return entry;
}
//get an empty bin (the host will add an entry for file about to be written with size of zero)
static fat_dir_entry_t * msc_update_find_new_bin(){
for(uint8_t i=16; i;){
i--;
fat_dir_entry_t * entry = msc_update_get_root_bin_entry(i);
if(entry && entry->file_size == 0){
return entry;
}
}
return NULL;
}
//get a bin starting from particular sector
static fat_dir_entry_t * msc_update_find_bin(uint16_t sector){
for(uint8_t i=16; i; ){
i--;
fat_dir_entry_t * entry = msc_update_get_root_bin_entry(i);
if(entry && entry->data_start_sector == (sector - msc_boot->sectors_per_alloc_table)){
return entry;
}
}
return NULL;
}
//write the new data and erase the flash blocks when necessary
static esp_err_t msc_update_write(const esp_partition_t *partition, uint32_t offset, void *data, size_t size){
esp_err_t err = ESP_OK;
if((offset & (SPI_FLASH_SEC_SIZE-1)) == 0){
err = esp_partition_erase_range(partition, offset, SPI_FLASH_SEC_SIZE);
log_v("ERASE[0x%08X]: %s", offset, (err != ESP_OK)?"FAIL":"OK");
if(err != ESP_OK){
return err;
}
}
return esp_partition_write(partition, offset, data, size);
}
//called when error was encountered while updating
static void msc_update_error(){
log_e("UPDATE_ERROR: %u", msc_update_bytes_written);
arduino_firmware_msc_event_data_t p;
p.error.size = msc_update_bytes_written;
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_ERROR_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
msc_update_state = MSC_UPDATE_IDLE;
msc_update_entry = NULL;
msc_update_bytes_written = 0;
msc_update_start_sector = 0;
}
//called when all firmware bytes have been received
static void msc_update_end(){
log_d("UPDATE_END: %u", msc_update_entry->file_size);
msc_update_state = MSC_UPDATE_END;
size_t ota_size = get_firmware_size(msc_ota_partition);
if(ota_size != msc_update_entry->file_size){
log_e("OTA SIZE MISMATCH %u != %u", ota_size, msc_update_entry->file_size);
msc_update_error();
return;
}
if(!ota_size || esp_ota_set_boot_partition(msc_ota_partition) != ESP_OK){
log_e("ENABLING OTA PARTITION FAILED");
msc_update_error();
return;
}
arduino_firmware_msc_event_data_t p;
p.end.size = msc_update_entry->file_size;
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_END_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
}
static int32_t msc_write(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
if(lba < fw_start_sector){
//write to sectors that are in RAM
memcpy(msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, buffer, bufsize);
if(msc_ota_partition && lba == (fw_start_sector - 1)){
//monitor the root folder table
if(msc_update_state <= MSC_UPDATE_RUNNING){
fat_dir_entry_t * update_entry = msc_update_find_new_bin();
if(update_entry) {
if(msc_update_entry) {
log_v("REPLACING ENTRY");
} else {
log_v("ASSIGNING ENTRY");
}
if(msc_update_state <= MSC_UPDATE_STARTING){
msc_update_state = MSC_UPDATE_STARTING;
msc_update_bytes_written = 0;
msc_update_start_sector = 0;
}
msc_update_entry = update_entry;
} else if(msc_update_state == MSC_UPDATE_RUNNING){
if(!msc_update_entry && msc_update_start_sector){
msc_update_entry = msc_update_find_bin(msc_update_start_sector);
}
if(msc_update_entry && msc_update_bytes_written >= msc_update_entry->file_size){
msc_update_end();
}
}
}
}
} else if(msc_ota_partition && lba >= msc_update_start_sector){
//handle writes to the region where the new firmware will be uploaded
arduino_firmware_msc_event_data_t p;
if(msc_update_state <= MSC_UPDATE_STARTING && buffer[0] == 0xE9){
msc_update_state = MSC_UPDATE_RUNNING;
msc_update_start_sector = lba;
msc_update_bytes_written = 0;
log_d("UPDATE_START: %u (0x%02X)", lba, lba - msc_boot->sectors_per_alloc_table);
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_START_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
if(msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK){
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
p.write.size = bufsize;
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_WRITE_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
} else {
msc_update_error();
return 0;
}
} else if(msc_update_state == MSC_UPDATE_RUNNING){
if(msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written < msc_update_entry->file_size && (msc_update_bytes_written + bufsize) >= msc_update_entry->file_size){
bufsize = msc_update_entry->file_size - msc_update_bytes_written;
}
if(msc_update_write(msc_ota_partition, ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) == ESP_OK){
log_v("UPDATE_WRITE: %u %u", ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset, bufsize);
msc_update_bytes_written = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset + bufsize;
p.write.offset = ((lba - msc_update_start_sector) * DISK_SECTOR_SIZE) + offset;
p.write.size = bufsize;
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_WRITE_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
if(msc_update_entry && msc_update_entry->file_size && msc_update_bytes_written >= msc_update_entry->file_size){
msc_update_end();
}
} else {
msc_update_error();
return 0;
}
}
}
return bufsize;
}
static int32_t msc_read(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){
//log_d("lba: %u, offset: %u, bufsize: %u", lba, offset, bufsize);
if(lba < fw_start_sector){
memcpy(buffer, msc_ram_disk + (lba * DISK_SECTOR_SIZE) + offset, bufsize);
} else if(msc_run_partition && lba < fw_end_sector){
//read the currently running firmware
if(esp_partition_read(msc_run_partition, ((lba - fw_start_sector) * DISK_SECTOR_SIZE) + offset, buffer, bufsize) != ESP_OK){
return 0;
}
} else {
memset(buffer, 0, bufsize);
}
return bufsize;
}
static bool msc_start_stop(uint8_t power_condition, bool start, bool load_eject){
//log_d("power: %u, start: %u, eject: %u", power_condition, start, load_eject);
arduino_firmware_msc_event_data_t p;
p.power.power_condition = power_condition;
p.power.start = start;
p.power.load_eject = load_eject;
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_POWER_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
return true;
}
static volatile TaskHandle_t msc_task_handle = NULL;
static void msc_task(void *pvParameters){
for (;;) {
if(msc_update_state == MSC_UPDATE_END){
delay(100);
esp_restart();
}
delay(100);
}
msc_task_handle = NULL;
vTaskDelete(NULL);
}
FirmwareMSC::FirmwareMSC():msc(){}
FirmwareMSC::~FirmwareMSC(){
end();
}
bool FirmwareMSC::begin(){
if(msc_ram_disk){
return true;
}
if(!msc_update_setup_disk(USB_FW_MSC_VOLUME_NAME, USB_FW_MSC_SERIAL_NUMBER)){
return false;
}
if(!msc_task_handle){
xTaskCreateUniversal(msc_task, "msc_disk", 1024, NULL, 2, (TaskHandle_t*)&msc_task_handle, 0);
if(!msc_task_handle){
msc_update_delete_disk();
return false;
}
}
msc.vendorID(USB_FW_MSC_VENDOR_ID);
msc.productID(USB_FW_MSC_PRODUCT_ID);
msc.productRevision(USB_FW_MSC_PRODUCT_REVISION);
msc.onStartStop(msc_start_stop);
msc.onRead(msc_read);
msc.onWrite(msc_write);
msc.mediaPresent(true);
msc.begin(msc_boot->fat12_sector_num, DISK_SECTOR_SIZE);
return true;
}
void FirmwareMSC::end(){
msc.end();
if(msc_task_handle){
vTaskDelete(msc_task_handle);
msc_task_handle = NULL;
}
msc_update_delete_disk();
}
void FirmwareMSC::onEvent(esp_event_handler_t callback){
onEvent(ARDUINO_FIRMWARE_MSC_ANY_EVENT, callback);
}
void FirmwareMSC::onEvent(arduino_firmware_msc_event_t event, esp_event_handler_t callback){
arduino_usb_event_handler_register_with(ARDUINO_FIRMWARE_MSC_EVENTS, event, callback, this);
}
#if ARDUINO_USB_MSC_ON_BOOT
FirmwareMSC MSC_Update;
#endif
#endif /* CONFIG_USB_MSC_ENABLED */

70
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FirmwareMSC.h

@ -0,0 +1,70 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdbool.h>
#include "USBMSC.h"
#if CONFIG_TINYUSB_MSC_ENABLED
#include "esp_event.h"
ESP_EVENT_DECLARE_BASE(ARDUINO_FIRMWARE_MSC_EVENTS);
typedef enum {
ARDUINO_FIRMWARE_MSC_ANY_EVENT = ESP_EVENT_ANY_ID,
ARDUINO_FIRMWARE_MSC_START_EVENT = 0,
ARDUINO_FIRMWARE_MSC_WRITE_EVENT,
ARDUINO_FIRMWARE_MSC_END_EVENT,
ARDUINO_FIRMWARE_MSC_ERROR_EVENT,
ARDUINO_FIRMWARE_MSC_POWER_EVENT,
ARDUINO_FIRMWARE_MSC_MAX_EVENT,
} arduino_firmware_msc_event_t;
typedef union {
struct {
size_t offset;
size_t size;
} write;
struct {
uint8_t power_condition;
bool start;
bool load_eject;
} power;
struct {
size_t size;
} end;
struct {
size_t size;
} error;
} arduino_firmware_msc_event_data_t;
class FirmwareMSC {
private:
USBMSC msc;
public:
FirmwareMSC();
~FirmwareMSC();
bool begin();
void end();
void onEvent(esp_event_handler_t callback);
void onEvent(arduino_firmware_msc_event_t event, esp_event_handler_t callback);
};
#if ARDUINO_USB_MSC_ON_BOOT
extern FirmwareMSC MSC_Update;
#endif
#endif /* CONFIG_TINYUSB_MSC_ENABLED */

44
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FunctionalInterrupt.cpp

@ -0,0 +1,44 @@
/*
* FunctionalInterrupt.cpp
*
* Created on: 8 jul. 2018
* Author: Herman
*/
#include "FunctionalInterrupt.h"
#include "Arduino.h"
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrArg)(void*);
extern "C"
{
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional);
}
void ARDUINO_ISR_ATTR interruptFunctional(void* arg)
{
InterruptArgStructure* localArg = (InterruptArgStructure*)arg;
if (localArg->interruptFunction)
{
localArg->interruptFunction();
}
}
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
{
// use the local interrupt routine which takes the ArgStructure as argument
__attachInterruptFunctionalArg (pin, (voidFuncPtrArg)interruptFunctional, new InterruptArgStructure{intRoutine}, mode, true);
}
extern "C"
{
void cleanupFunctional(void* arg)
{
delete (InterruptArgStructure*)arg;
}
}

21
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/FunctionalInterrupt.h

@ -0,0 +1,21 @@
/*
* FunctionalInterrupt.h
*
* Created on: 8 jul. 2018
* Author: Herman
*/
#ifndef CORE_CORE_FUNCTIONALINTERRUPT_H_
#define CORE_CORE_FUNCTIONALINTERRUPT_H_
#include <functional>
#include <stdint.h>
struct InterruptArgStructure {
std::function<void(void)> interruptFunction;
};
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
#endif /* CORE_CORE_FUNCTIONALINTERRUPT_H_ */

447
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HWCDC.cpp

@ -0,0 +1,447 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "USB.h"
#if SOC_USB_SERIAL_JTAG_SUPPORTED
#include "esp32-hal.h"
#include "esp32-hal-periman.h"
#include "HWCDC.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/ringbuf.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#include "soc/io_mux_reg.h"
#pragma GCC diagnostic ignored "-Wvolatile"
#include "hal/usb_serial_jtag_ll.h"
#pragma GCC diagnostic warning "-Wvolatile"
#include "rom/ets_sys.h"
ESP_EVENT_DEFINE_BASE(ARDUINO_HW_CDC_EVENTS);
static RingbufHandle_t tx_ring_buf = NULL;
static QueueHandle_t rx_queue = NULL;
static uint8_t rx_data_buf[64] = {0};
static intr_handle_t intr_handle = NULL;
static volatile bool initial_empty = false;
static SemaphoreHandle_t tx_lock = NULL;
// workaround for when USB CDC is not connected
static uint32_t tx_timeout_ms = 0;
static bool tx_timeout_change_request = false;
static esp_event_loop_handle_t arduino_hw_cdc_event_loop_handle = NULL;
static esp_err_t arduino_hw_cdc_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, BaseType_t *task_unblocked){
if(arduino_hw_cdc_event_loop_handle == NULL){
return ESP_FAIL;
}
return esp_event_isr_post_to(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_data, event_data_size, task_unblocked);
}
static esp_err_t arduino_hw_cdc_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg){
if (!arduino_hw_cdc_event_loop_handle) {
esp_event_loop_args_t event_task_args = {
.queue_size = 5,
.task_name = "arduino_hw_cdc_events",
.task_priority = 5,
.task_stack_size = 2048,
.task_core_id = tskNO_AFFINITY
};
if (esp_event_loop_create(&event_task_args, &arduino_hw_cdc_event_loop_handle) != ESP_OK) {
log_e("esp_event_loop_create failed");
}
}
if(arduino_hw_cdc_event_loop_handle == NULL){
return ESP_FAIL;
}
return esp_event_handler_register_with(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
}
static void hw_cdc_isr_handler(void *arg) {
portBASE_TYPE xTaskWoken = 0;
uint32_t usbjtag_intr_status = 0;
arduino_hw_cdc_event_data_t event = {0};
usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
// Interrupt tells us the host picked up the data we sent.
if (usb_serial_jtag_ll_txfifo_writable() == 1) {
// We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
if(!initial_empty){
initial_empty = true;
// First time USB is plugged and the application has not explicitly set TX Timeout, set it to default 100ms.
// Otherwise, USB is still unplugged and the timeout will be kept as Zero in order to avoid any delay in the
// application whenever it uses write() and the TX Queue gets full.
if (!tx_timeout_change_request) {
tx_timeout_ms = 100;
}
//send event?
//ets_printf("CONNECTED\n");
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_CONNECTED_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
}
size_t queued_size;
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR(tx_ring_buf, &queued_size, 64);
// If the hardware fifo is avaliable, write in it. Otherwise, do nothing.
if (queued_buff != NULL) { //Although tx_queued_bytes may be larger than 0. We may have interrupt before xRingbufferSend() was called.
//Copy the queued buffer into the TX FIFO
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
usb_serial_jtag_ll_write_txfifo(queued_buff, queued_size);
usb_serial_jtag_ll_txfifo_flush();
vRingbufferReturnItemFromISR(tx_ring_buf, queued_buff, &xTaskWoken);
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
//send event?
//ets_printf("TX:%u\n", queued_size);
event.tx.len = queued_size;
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_TX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
}
} else {
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
}
}
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT) {
// read rx buffer(max length is 64), and send avaliable data to ringbuffer.
// Ensure the rx buffer size is larger than RX_MAX_SIZE.
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo(rx_data_buf, 64);
uint32_t i=0;
for(i=0; i<rx_fifo_len; i++){
if(rx_queue == NULL || !xQueueSendFromISR(rx_queue, rx_data_buf+i, &xTaskWoken)){
break;
}
}
//send event?
//ets_printf("RX:%u/%u\n", i, rx_fifo_len);
event.rx.len = i;
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_RX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
}
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET) {
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_BUS_RESET);
initial_empty = false;
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
//ets_printf("BUS_RESET\n");
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_BUS_RESET_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
}
if (xTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
if(xPortInIsrContext()){
xRingbufferSendFromISR(tx_ring_buf, (void*) (&c), 1, NULL);
} else {
xRingbufferSend(tx_ring_buf, (void*) (&c), 1, tx_timeout_ms / portTICK_PERIOD_MS);
}
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
}
HWCDC::HWCDC() {
}
HWCDC::~HWCDC(){
end();
}
HWCDC::operator bool() const
{
return initial_empty;
}
void HWCDC::onEvent(esp_event_handler_t callback){
onEvent(ARDUINO_HW_CDC_ANY_EVENT, callback);
}
void HWCDC::onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback){
arduino_hw_cdc_event_handler_register_with(ARDUINO_HW_CDC_EVENTS, event, callback, this);
}
bool HWCDC::deinit(void * busptr)
{
// avoid any recursion issue with Peripheral Manager perimanSetPinBus() call
static bool running = false;
if (running) return true;
running = true;
// Setting USB D+ D- pins
bool retCode = true;
retCode &= perimanSetPinBus(USB_DM_GPIO_NUM, ESP32_BUS_TYPE_INIT, NULL);
retCode &= perimanSetPinBus(USB_DP_GPIO_NUM, ESP32_BUS_TYPE_INIT, NULL);
if (retCode) {
// Force the host to re-enumerate (BUS_RESET)
pinMode(USB_DM_GPIO_NUM, OUTPUT_OPEN_DRAIN);
pinMode(USB_DP_GPIO_NUM, OUTPUT_OPEN_DRAIN);
digitalWrite(USB_DM_GPIO_NUM, LOW);
digitalWrite(USB_DP_GPIO_NUM, LOW);
}
// release the flag
running = false;
return retCode;
}
void HWCDC::begin(unsigned long baud)
{
if(tx_lock == NULL) {
tx_lock = xSemaphoreCreateMutex();
}
//RX Buffer default has 256 bytes if not preset
if(rx_queue == NULL) {
if (!setRxBufferSize(256)) {
log_e("HW CDC RX Buffer error");
}
}
//TX Buffer default has 256 bytes if not preset
if (tx_ring_buf == NULL) {
if (!setTxBufferSize(256)) {
log_e("HW CDC TX Buffer error");
}
}
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET);
if(!intr_handle && esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0, hw_cdc_isr_handler, NULL, &intr_handle) != ESP_OK){
isr_log_e("HW USB CDC failed to init interrupts");
end();
return;
}
if (perimanSetBusDeinit(ESP32_BUS_TYPE_USB, HWCDC::deinit)) {
// Setting USB D+ D- pins
perimanSetPinBus(USB_DM_GPIO_NUM, ESP32_BUS_TYPE_USB, (void *) this);
perimanSetPinBus(USB_DP_GPIO_NUM, ESP32_BUS_TYPE_USB, (void *) this);
} else {
log_e("Serial JTAG Pins can't be set into Peripheral Manager.");
}
usb_serial_jtag_ll_txfifo_flush();
}
void HWCDC::end()
{
//Disable tx/rx interrupt.
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
esp_intr_free(intr_handle);
intr_handle = NULL;
if(tx_lock != NULL) {
vSemaphoreDelete(tx_lock);
tx_lock = NULL;
}
setRxBufferSize(0);
setTxBufferSize(0);
if (arduino_hw_cdc_event_loop_handle) {
esp_event_loop_delete(arduino_hw_cdc_event_loop_handle);
arduino_hw_cdc_event_loop_handle = NULL;
}
HWCDC::deinit(this);
}
void HWCDC::setTxTimeoutMs(uint32_t timeout){
tx_timeout_ms = timeout;
// it registers that the user has explicitly requested to use a value as TX timeout
// used for the workaround with unplugged USB and TX Queue Full that causes a delay on every write()
tx_timeout_change_request = true;
}
/*
* WRITING
*/
size_t HWCDC::setTxBufferSize(size_t tx_queue_len){
if(tx_ring_buf){
vRingbufferDelete(tx_ring_buf);
tx_ring_buf = NULL;
}
if(!tx_queue_len){
return 0;
}
tx_ring_buf = xRingbufferCreate(tx_queue_len, RINGBUF_TYPE_BYTEBUF);
if(!tx_ring_buf){
return 0;
}
return tx_queue_len;
}
int HWCDC::availableForWrite(void)
{
if(tx_ring_buf == NULL || tx_lock == NULL){
return 0;
}
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
return 0;
}
size_t a = xRingbufferGetCurFreeSize(tx_ring_buf);
xSemaphoreGive(tx_lock);
return a;
}
size_t HWCDC::write(const uint8_t *buffer, size_t size)
{
if(buffer == NULL || size == 0 || tx_ring_buf == NULL || tx_lock == NULL){
return 0;
}
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
return 0;
}
size_t max_size = xRingbufferGetMaxItemSize(tx_ring_buf);
size_t space = xRingbufferGetCurFreeSize(tx_ring_buf);
size_t to_send = size, so_far = 0;
if(space > size){
space = size;
}
// Non-Blocking method, Sending data to ringbuffer, and handle the data in ISR.
if(xRingbufferSend(tx_ring_buf, (void*) (buffer), space, 0) != pdTRUE){
size = 0;
} else {
to_send -= space;
so_far += space;
// Now trigger the ISR to read data from the ring buffer.
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
while(to_send){
if(max_size > to_send){
max_size = to_send;
}
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
if(xRingbufferSend(tx_ring_buf, (void*) (buffer+so_far), max_size, tx_timeout_ms / portTICK_PERIOD_MS) != pdTRUE){
size = so_far;
break;
}
so_far += max_size;
to_send -= max_size;
// Now trigger the ISR to read data from the ring buffer.
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
}
}
xSemaphoreGive(tx_lock);
return size;
}
size_t HWCDC::write(uint8_t c)
{
return write(&c, 1);
}
void HWCDC::flush(void)
{
if(tx_ring_buf == NULL || tx_lock == NULL){
return;
}
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
return;
}
UBaseType_t uxItemsWaiting = 0;
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
if(uxItemsWaiting){
// Now trigger the ISR to read data from the ring buffer.
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
}
while(uxItemsWaiting){
delay(5);
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
}
xSemaphoreGive(tx_lock);
}
/*
* READING
*/
size_t HWCDC::setRxBufferSize(size_t rx_queue_len){
if(rx_queue){
vQueueDelete(rx_queue);
rx_queue = NULL;
}
if(!rx_queue_len){
return 0;
}
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
if(!rx_queue){
return 0;
}
return rx_queue_len;
}
int HWCDC::available(void)
{
if(rx_queue == NULL){
return -1;
}
return uxQueueMessagesWaiting(rx_queue);
}
int HWCDC::peek(void)
{
if(rx_queue == NULL){
return -1;
}
uint8_t c;
if(xQueuePeek(rx_queue, &c, 0)) {
return c;
}
return -1;
}
int HWCDC::read(void)
{
if(rx_queue == NULL){
return -1;
}
uint8_t c = 0;
if(xQueueReceive(rx_queue, &c, 0)) {
return c;
}
return -1;
}
size_t HWCDC::read(uint8_t *buffer, size_t size)
{
if(rx_queue == NULL){
return -1;
}
uint8_t c = 0;
size_t count = 0;
while(count < size && xQueueReceive(rx_queue, &c, 0)){
buffer[count++] = c;
}
return count;
}
/*
* DEBUG
*/
void HWCDC::setDebugOutput(bool en)
{
if(en) {
uartSetDebug(NULL);
ets_install_putc1((void (*)(char)) &cdc0_write_char);
} else {
ets_install_putc1(NULL);
}
}
#if ARDUINO_USB_MODE
#if ARDUINO_USB_CDC_ON_BOOT//Serial used for USB CDC
HWCDC Serial;
#else
HWCDC USBSerial;
#endif
#endif
#endif /* SOC_USB_SERIAL_JTAG_SUPPORTED */

114
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HWCDC.h

@ -0,0 +1,114 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#if SOC_USB_SERIAL_JTAG_SUPPORTED
#include <inttypes.h>
#include "esp_event.h"
#include "Stream.h"
ESP_EVENT_DECLARE_BASE(ARDUINO_HW_CDC_EVENTS);
typedef enum {
ARDUINO_HW_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
ARDUINO_HW_CDC_CONNECTED_EVENT = 0,
ARDUINO_HW_CDC_BUS_RESET_EVENT,
ARDUINO_HW_CDC_RX_EVENT,
ARDUINO_HW_CDC_TX_EVENT,
ARDUINO_HW_CDC_MAX_EVENT,
} arduino_hw_cdc_event_t;
typedef union {
struct {
size_t len;
} rx;
struct {
size_t len;
} tx;
} arduino_hw_cdc_event_data_t;
class HWCDC: public Stream
{
private:
static bool deinit(void * busptr);
public:
HWCDC();
~HWCDC();
void onEvent(esp_event_handler_t callback);
void onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback);
size_t setRxBufferSize(size_t);
size_t setTxBufferSize(size_t);
void setTxTimeoutMs(uint32_t timeout);
void begin(unsigned long baud=0);
void end();
int available(void);
int availableForWrite(void);
int peek(void);
int read(void);
size_t read(uint8_t *buffer, size_t size);
size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);
void flush(void);
inline size_t read(char * buffer, size_t size)
{
return read((uint8_t*) buffer, size);
}
inline size_t write(const char * buffer, size_t size)
{
return write((uint8_t*) buffer, size);
}
inline size_t write(const char * s)
{
return write((uint8_t*) s, strlen(s));
}
inline size_t write(unsigned long n)
{
return write((uint8_t) n);
}
inline size_t write(long n)
{
return write((uint8_t) n);
}
inline size_t write(unsigned int n)
{
return write((uint8_t) n);
}
inline size_t write(int n)
{
return write((uint8_t) n);
}
operator bool() const;
void setDebugOutput(bool);
uint32_t baudRate(){return 115200;}
};
#if ARDUINO_USB_MODE
#if ARDUINO_USB_CDC_ON_BOOT//Serial used for USB CDC
extern HWCDC Serial;
#else
extern HWCDC USBSerial;
#endif
#endif
#endif /* CONFIG_IDF_TARGET_ESP32C3 */

627
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HardwareSerial.cpp

@ -0,0 +1,627 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <ctime>
#include "pins_arduino.h"
#include "HardwareSerial.h"
#include "soc/soc_caps.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
#endif
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES-1)
#endif
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
#endif
#ifndef SOC_RX0
#if CONFIG_IDF_TARGET_ESP32
#define SOC_RX0 3
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define SOC_RX0 44
#elif CONFIG_IDF_TARGET_ESP32C3
#define SOC_RX0 20
#elif CONFIG_IDF_TARGET_ESP32C6
#define SOC_RX0 17
#elif CONFIG_IDF_TARGET_ESP32H2
#define SOC_RX0 23
#endif
#endif
#ifndef SOC_TX0
#if CONFIG_IDF_TARGET_ESP32
#define SOC_TX0 1
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define SOC_TX0 43
#elif CONFIG_IDF_TARGET_ESP32C3
#define SOC_TX0 21
#elif CONFIG_IDF_TARGET_ESP32C6
#define SOC_TX0 16
#elif CONFIG_IDF_TARGET_ESP32H2
#define SOC_TX0 24
#endif
#endif
void serialEvent(void) __attribute__((weak));
void serialEvent(void) {}
#if SOC_UART_NUM > 1
#ifndef RX1
#if CONFIG_IDF_TARGET_ESP32
#define RX1 9
#elif CONFIG_IDF_TARGET_ESP32S2
#define RX1 18
#elif CONFIG_IDF_TARGET_ESP32C3
#define RX1 18
#elif CONFIG_IDF_TARGET_ESP32S3
#define RX1 15
#elif CONFIG_IDF_TARGET_ESP32C6
#define RX1 4
#elif CONFIG_IDF_TARGET_ESP32H2
#define RX1 0
#endif
#endif
#ifndef TX1
#if CONFIG_IDF_TARGET_ESP32
#define TX1 10
#elif CONFIG_IDF_TARGET_ESP32S2
#define TX1 17
#elif CONFIG_IDF_TARGET_ESP32C3
#define TX1 19
#elif CONFIG_IDF_TARGET_ESP32S3
#define TX1 16
#elif CONFIG_IDF_TARGET_ESP32C6
#define TX1 5
#elif CONFIG_IDF_TARGET_ESP32H2
#define TX1 1
#endif
#endif
void serialEvent1(void) __attribute__((weak));
void serialEvent1(void) {}
#endif /* SOC_UART_NUM > 1 */
#if SOC_UART_NUM > 2
#ifndef RX2
#if CONFIG_IDF_TARGET_ESP32
#define RX2 16
#elif CONFIG_IDF_TARGET_ESP32S3
#define RX2 19
#endif
#endif
#ifndef TX2
#if CONFIG_IDF_TARGET_ESP32
#define TX2 17
#elif CONFIG_IDF_TARGET_ESP32S3
#define TX2 20
#endif
#endif
void serialEvent2(void) __attribute__((weak));
void serialEvent2(void) {}
#endif /* SOC_UART_NUM > 2 */
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
HardwareSerial Serial0(0);
#else
HardwareSerial Serial(0);
#endif
#if SOC_UART_NUM > 1
HardwareSerial Serial1(1);
#endif
#if SOC_UART_NUM > 2
HardwareSerial Serial2(2);
#endif
void serialEventRun(void)
{
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
if(Serial0.available()) serialEvent();
#else
if(Serial.available()) serialEvent();
#endif
#if SOC_UART_NUM > 1
if(Serial1.available()) serialEvent1();
#endif
#if SOC_UART_NUM > 2
if(Serial2.available()) serialEvent2();
#endif
}
#endif
#if !CONFIG_DISABLE_HAL_LOCKS
#define HSERIAL_MUTEX_LOCK() do {} while (xSemaphoreTake(_lock, portMAX_DELAY) != pdPASS)
#define HSERIAL_MUTEX_UNLOCK() xSemaphoreGive(_lock)
#else
#define HSERIAL_MUTEX_LOCK()
#define HSERIAL_MUTEX_UNLOCK()
#endif
HardwareSerial::HardwareSerial(uint8_t uart_nr) :
_uart_nr(uart_nr),
_uart(NULL),
_rxBufferSize(256),
_txBufferSize(0),
_onReceiveCB(NULL),
_onReceiveErrorCB(NULL),
_onReceiveTimeout(false),
_rxTimeout(2),
_rxFIFOFull(0),
_eventTask(NULL)
#if !CONFIG_DISABLE_HAL_LOCKS
,_lock(NULL)
#endif
{
#if !CONFIG_DISABLE_HAL_LOCKS
if(_lock == NULL){
_lock = xSemaphoreCreateMutex();
if(_lock == NULL){
log_e("xSemaphoreCreateMutex failed");
return;
}
}
#endif
// sets UART0 (default console) RX/TX pins as already configured in boot
if (uart_nr == 0) {
setPins(SOC_RX0, SOC_TX0);
}
// set deinit function in the Peripheral Manager
uart_init_PeriMan();
}
HardwareSerial::~HardwareSerial()
{
end();
#if !CONFIG_DISABLE_HAL_LOCKS
if(_lock != NULL){
vSemaphoreDelete(_lock);
}
#endif
}
void HardwareSerial::_createEventTask(void *args)
{
// Creating UART event Task
xTaskCreateUniversal(_uartEventTask, "uart_event_task", ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE, this, ARDUINO_SERIAL_EVENT_TASK_PRIORITY, &_eventTask, ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE);
if (_eventTask == NULL) {
log_e(" -- UART%d Event Task not Created!", _uart_nr);
}
}
void HardwareSerial::_destroyEventTask(void)
{
if (_eventTask != NULL) {
vTaskDelete(_eventTask);
_eventTask = NULL;
}
}
void HardwareSerial::onReceiveError(OnReceiveErrorCb function)
{
HSERIAL_MUTEX_LOCK();
// function may be NULL to cancel onReceive() from its respective task
_onReceiveErrorCB = function;
// this can be called after Serial.begin(), therefore it shall create the event task
if (function != NULL && _uart != NULL && _eventTask == NULL) {
_createEventTask(this);
}
HSERIAL_MUTEX_UNLOCK();
}
void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout)
{
HSERIAL_MUTEX_LOCK();
// function may be NULL to cancel onReceive() from its respective task
_onReceiveCB = function;
// setting the callback to NULL will just disable it
if (_onReceiveCB != NULL) {
// When Rx timeout is Zero (disabled), there is only one possible option that is callback when FIFO reaches 120 bytes
_onReceiveTimeout = _rxTimeout > 0 ? onlyOnTimeout : false;
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
if (_onReceiveTimeout) {
uartSetRxFIFOFull(_uart, 120);
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
}
// this method can be called after Serial.begin(), therefore it shall create the event task
if (_uart != NULL && _eventTask == NULL) {
_createEventTask(this); // Create event task
}
}
HSERIAL_MUTEX_UNLOCK();
}
// This function allow the user to define how many bytes will trigger an Interrupt that will copy RX FIFO to the internal RX Ringbuffer
// ISR will also move data from FIFO to RX Ringbuffer after a RX Timeout defined in HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
// A low value of FIFO Full bytes will consume more CPU time within the ISR
// A high value of FIFO Full bytes will make the application wait longer to have byte available for the Stkech in a streaming scenario
// Both RX FIFO Full and RX Timeout may affect when onReceive() will be called
bool HardwareSerial::setRxFIFOFull(uint8_t fifoBytes)
{
HSERIAL_MUTEX_LOCK();
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
if (_onReceiveCB != NULL && _onReceiveTimeout) {
fifoBytes = 120;
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
}
bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
if (fifoBytes > 0 && fifoBytes < SOC_UART_FIFO_LEN - 1) _rxFIFOFull = fifoBytes;
HSERIAL_MUTEX_UNLOCK();
return retCode;
}
// timout is calculates in time to receive UART symbols at the UART baudrate.
// the estimation is about 11 bits per symbol (SERIAL_8N1)
bool HardwareSerial::setRxTimeout(uint8_t symbols_timeout)
{
HSERIAL_MUTEX_LOCK();
// Zero disables timeout, thus, onReceive callback will only be called when RX FIFO reaches 120 bytes
// Any non-zero value will activate onReceive callback based on UART baudrate with about 11 bits per symbol
_rxTimeout = symbols_timeout;
if (!symbols_timeout) _onReceiveTimeout = false; // only when RX timeout is disabled, we also must disable this flag
bool retCode = uartSetRxTimeout(_uart, _rxTimeout); // Set new timeout
HSERIAL_MUTEX_UNLOCK();
return retCode;
}
void HardwareSerial::eventQueueReset()
{
QueueHandle_t uartEventQueue = NULL;
if (_uart == NULL) {
return;
}
uartGetEventQueue(_uart, &uartEventQueue);
if (uartEventQueue != NULL) {
xQueueReset(uartEventQueue);
}
}
void HardwareSerial::_uartEventTask(void *args)
{
HardwareSerial *uart = (HardwareSerial *)args;
uart_event_t event;
QueueHandle_t uartEventQueue = NULL;
uartGetEventQueue(uart->_uart, &uartEventQueue);
if (uartEventQueue != NULL) {
for(;;) {
//Waiting for UART event.
if(xQueueReceive(uartEventQueue, (void * )&event, (TickType_t)portMAX_DELAY)) {
hardwareSerial_error_t currentErr = UART_NO_ERROR;
switch(event.type) {
case UART_DATA:
if(uart->_onReceiveCB && uart->available() > 0 &&
((uart->_onReceiveTimeout && event.timeout_flag) || !uart->_onReceiveTimeout) )
uart->_onReceiveCB();
break;
case UART_FIFO_OVF:
log_w("UART%d FIFO Overflow. Consider adding Hardware Flow Control to your Application.", uart->_uart_nr);
currentErr = UART_FIFO_OVF_ERROR;
break;
case UART_BUFFER_FULL:
log_w("UART%d Buffer Full. Consider increasing your buffer size of your Application.", uart->_uart_nr);
currentErr = UART_BUFFER_FULL_ERROR;
break;
case UART_BREAK:
log_w("UART%d RX break.", uart->_uart_nr);
currentErr = UART_BREAK_ERROR;
break;
case UART_PARITY_ERR:
log_w("UART%d parity error.", uart->_uart_nr);
currentErr = UART_PARITY_ERROR;
break;
case UART_FRAME_ERR:
log_w("UART%d frame error.", uart->_uart_nr);
currentErr = UART_FRAME_ERROR;
break;
default:
log_w("UART%d unknown event type %d.", uart->_uart_nr, event.type);
break;
}
if (currentErr != UART_NO_ERROR) {
if(uart->_onReceiveErrorCB) uart->_onReceiveErrorCB(currentErr);
}
}
}
}
vTaskDelete(NULL);
}
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd)
{
if(_uart_nr >= SOC_UART_NUM) {
log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_NUM - 1);
return;
}
#if !CONFIG_DISABLE_HAL_LOCKS
if(_lock == NULL){
log_e("MUTEX Lock failed. Can't begin.");
return;
}
#endif
HSERIAL_MUTEX_LOCK();
// First Time or after end() --> set default Pins
if (!uartIsDriverInstalled(_uart)) {
// get previously used RX/TX pins, if any.
int8_t _rxPin = uart_get_RxPin(_uart_nr);
int8_t _txPin = uart_get_TxPin(_uart_nr);
switch (_uart_nr) {
case UART_NUM_0:
if (rxPin < 0 && txPin < 0) {
// do not change RX0/TX0 if it has already been set before
rxPin = _rxPin < 0 ? SOC_RX0 : _rxPin;
txPin = _txPin < 0 ? SOC_TX0 : _txPin;
}
break;
#if SOC_UART_NUM > 1 // may save some flash bytes...
case UART_NUM_1:
if (rxPin < 0 && txPin < 0) {
// do not change RX1/TX1 if it has already been set before
rxPin = _rxPin < 0 ? RX1 : _rxPin;
txPin = _txPin < 0 ? TX1 : _txPin;
}
break;
#endif
#if SOC_UART_NUM > 2 // may save some flash bytes...
case UART_NUM_2:
if (rxPin < 0 && txPin < 0) {
// do not change RX2/TX2 if it has already been set before
rxPin = _rxPin < 0 ? RX2 : _rxPin;
txPin = _txPin < 0 ? TX2 : _txPin;
}
break;
#endif
}
}
if(_uart) {
// in this case it is a begin() over a previous begin() - maybe to change baud rate
// thus do not disable debug output
end(false);
}
// IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified.
// it will detach previous UART attached pins
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, _rxBufferSize, _txBufferSize, invert, rxfifo_full_thrhd);
if (!baud) {
// using baud rate as zero, forces it to try to detect the current baud rate in place
uartStartDetectBaudrate(_uart);
time_t startMillis = millis();
unsigned long detectedBaudRate = 0;
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
yield();
}
end(false);
if(detectedBaudRate) {
delay(100); // Give some time...
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, _rxBufferSize, _txBufferSize, invert, rxfifo_full_thrhd);
} else {
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
_uart = NULL;
}
}
// create a task to deal with Serial Events when, for example, calling begin() twice to change the baudrate,
// or when setting the callback before calling begin()
if (_uart != NULL && (_onReceiveCB != NULL || _onReceiveErrorCB != NULL) && _eventTask == NULL) {
_createEventTask(this);
}
// Set UART RX timeout
uartSetRxTimeout(_uart, _rxTimeout);
// Set UART FIFO Full depending on the baud rate.
// Lower baud rates will force to emulate byte-by-byte reading
// Higher baud rates will keep IDF default of 120 bytes for FIFO FULL Interrupt
// It can also be changed by the application at any time
if (!_rxFIFOFull) { // it has not being changed before calling begin()
// set a default FIFO Full value for the IDF driver
uint8_t fifoFull = 1;
if (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout)) {
fifoFull = 120;
}
uartSetRxFIFOFull(_uart, fifoFull);
_rxFIFOFull = fifoFull;
}
HSERIAL_MUTEX_UNLOCK();
}
void HardwareSerial::updateBaudRate(unsigned long baud)
{
uartSetBaudRate(_uart, baud);
}
void HardwareSerial::end(bool fullyTerminate)
{
// default Serial.end() will completely disable HardwareSerial,
// including any tasks or debug message channel (log_x()) - but not for IDF log messages!
if(fullyTerminate) {
_onReceiveCB = NULL;
_onReceiveErrorCB = NULL;
if (uartGetDebug() == _uart_nr) {
uartSetDebug(0);
}
_rxFIFOFull = 0;
uartEnd(_uart_nr); // fully detach all pins and delete the UART driver
} else {
// do not invalidate callbacks, detach pins, invalidate DBG output
uart_driver_delete(_uart_nr);
}
uartEnd(_uart_nr);
_uart = 0;
_destroyEventTask();
}
void HardwareSerial::setDebugOutput(bool en)
{
if(_uart == 0) {
return;
}
if(en) {
uartSetDebug(_uart);
} else {
if(uartGetDebug() == _uart_nr) {
uartSetDebug(NULL);
}
}
}
int HardwareSerial::available(void)
{
return uartAvailable(_uart);
}
int HardwareSerial::availableForWrite(void)
{
return uartAvailableForWrite(_uart);
}
int HardwareSerial::peek(void)
{
if (available()) {
return uartPeek(_uart);
}
return -1;
}
int HardwareSerial::read(void)
{
uint8_t c = 0;
if (uartReadBytes(_uart, &c, 1, 0) == 1) {
return c;
} else {
return -1;
}
}
// read characters into buffer
// terminates if size characters have been read, or no further are pending
// returns the number of characters placed in the buffer
// the buffer is NOT null terminated.
size_t HardwareSerial::read(uint8_t *buffer, size_t size)
{
return uartReadBytes(_uart, buffer, size, 0);
}
// Overrides Stream::readBytes() to be faster using IDF
size_t HardwareSerial::readBytes(uint8_t *buffer, size_t length)
{
return uartReadBytes(_uart, buffer, length, (uint32_t)getTimeout());
}
void HardwareSerial::flush(void)
{
uartFlush(_uart);
}
void HardwareSerial::flush(bool txOnly)
{
uartFlushTxOnly(_uart, txOnly);
}
size_t HardwareSerial::write(uint8_t c)
{
uartWrite(_uart, c);
return 1;
}
size_t HardwareSerial::write(const uint8_t *buffer, size_t size)
{
uartWriteBuf(_uart, buffer, size);
return size;
}
uint32_t HardwareSerial::baudRate()
{
return uartGetBaudRate(_uart);
}
HardwareSerial::operator bool() const
{
return uartIsDriverInstalled(_uart);
}
void HardwareSerial::setRxInvert(bool invert)
{
uartSetRxInvert(_uart, invert);
}
// negative Pin value will keep it unmodified
// can be called after or before begin()
bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
{
// uartSetPins() checks if pins are valid and, if necessary, detaches the previous ones
return uartSetPins(_uart_nr, rxPin, txPin, ctsPin, rtsPin);
}
// Enables or disables Hardware Flow Control using RTS and/or CTS pins
// must use setAllPins() in order to set RTS/CTS pins
// SerialHwFlowCtrl = UART_HW_FLOWCTRL_DISABLE, UART_HW_FLOWCTRL_RTS,
// UART_HW_FLOWCTRL_CTS, UART_HW_FLOWCTRL_CTS_RTS
bool HardwareSerial::setHwFlowCtrlMode(SerialHwFlowCtrl mode, uint8_t threshold)
{
return uartSetHwFlowCtrlMode(_uart, mode, threshold);
}
// Sets the uart mode in the esp32 uart for use with RS485 modes
// HwFlowCtrl must be disabled and RTS pin set
// SerialMode = UART_MODE_UART, UART_MODE_RS485_HALF_DUPLEX, UART_MODE_IRDA,
// or testing mode: UART_MODE_RS485_COLLISION_DETECT, UART_MODE_RS485_APP_CTRL
bool HardwareSerial::setMode(SerialMode mode)
{
return uartSetMode(_uart, mode);
}
size_t HardwareSerial::setRxBufferSize(size_t new_size) {
if (_uart) {
log_e("RX Buffer can't be resized when Serial is already running.\n");
return 0;
}
if (new_size <= SOC_UART_FIFO_LEN) {
log_e("RX Buffer must be higher than %d.\n", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128
return 0;
}
_rxBufferSize = new_size;
return _rxBufferSize;
}
size_t HardwareSerial::setTxBufferSize(size_t new_size) {
if (_uart) {
log_e("TX Buffer can't be resized when Serial is already running.\n");
return 0;
}
if (new_size <= SOC_UART_FIFO_LEN) {
log_e("TX Buffer must be higher than %d.\n", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128
return 0;
}
_txBufferSize = new_size;
return _txBufferSize;
}

260
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/HardwareSerial.h

@ -0,0 +1,260 @@
/*
HardwareSerial.h - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support)
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266)
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266)
Modified 13 October 2018 by Jeroen Döll (add baudrate detection)
Baudrate detection example usage (detection on Serial1):
void setup() {
Serial.begin(115200);
delay(100);
Serial.println();
Serial1.begin(0, SERIAL_8N1, -1, -1, true, 11000UL); // Passing 0 for baudrate to detect it, the last parameter is a timeout in ms
unsigned long detectedBaudRate = Serial1.baudRate();
if(detectedBaudRate) {
Serial.printf("Detected baudrate is %lu\n", detectedBaudRate);
} else {
Serial.println("No baudrate detected, Serial1 will not work!");
}
}
Pay attention: the baudrate returned by baudRate() may be rounded, eg 115200 returns 115201
*/
#ifndef HardwareSerial_h
#define HardwareSerial_h
#include <inttypes.h>
#include <functional>
#include "Stream.h"
#include "esp32-hal.h"
#include "soc/soc_caps.h"
#include "HWCDC.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
enum SerialConfig {
SERIAL_5N1 = 0x8000010,
SERIAL_6N1 = 0x8000014,
SERIAL_7N1 = 0x8000018,
SERIAL_8N1 = 0x800001c,
SERIAL_5N2 = 0x8000030,
SERIAL_6N2 = 0x8000034,
SERIAL_7N2 = 0x8000038,
SERIAL_8N2 = 0x800003c,
SERIAL_5E1 = 0x8000012,
SERIAL_6E1 = 0x8000016,
SERIAL_7E1 = 0x800001a,
SERIAL_8E1 = 0x800001e,
SERIAL_5E2 = 0x8000032,
SERIAL_6E2 = 0x8000036,
SERIAL_7E2 = 0x800003a,
SERIAL_8E2 = 0x800003e,
SERIAL_5O1 = 0x8000013,
SERIAL_6O1 = 0x8000017,
SERIAL_7O1 = 0x800001b,
SERIAL_8O1 = 0x800001f,
SERIAL_5O2 = 0x8000033,
SERIAL_6O2 = 0x8000037,
SERIAL_7O2 = 0x800003b,
SERIAL_8O2 = 0x800003f
};
typedef uart_mode_t SerialMode;
typedef uart_hw_flowcontrol_t SerialHwFlowCtrl;
typedef enum {
UART_NO_ERROR,
UART_BREAK_ERROR,
UART_BUFFER_FULL_ERROR,
UART_FIFO_OVF_ERROR,
UART_FRAME_ERROR,
UART_PARITY_ERROR
} hardwareSerial_error_t;
typedef std::function<void(void)> OnReceiveCb;
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
class HardwareSerial: public Stream
{
public:
HardwareSerial(uint8_t uart_nr);
~HardwareSerial();
// setRxTimeout sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc)
// param symbols_timeout defines a timeout threshold in uart symbol periods. Setting 0 symbol timeout disables the callback call by timeout.
// Maximum timeout setting is calculacted automatically by IDF. If set above the maximum, it is ignored and an error is printed on Serial0 (check console).
// Examples: Maximum for 11 bits symbol is 92 (SERIAL_8N2, SERIAL_8E1, SERIAL_8O1, etc), Maximum for 10 bits symbol is 101 (SERIAL_8N1).
// For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
bool setRxTimeout(uint8_t symbols_timeout);
// setRxFIFOFull(uint8_t fifoBytes) will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
// This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data, Serial internal
// RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
// This parameter can be set to 1 in order to receive byte by byte, but it will also consume more CPU time as the ISR will be activates often.
bool setRxFIFOFull(uint8_t fifoBytes);
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
// UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
// UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbos by default in IDF)
// onlyOnTimeout parameter will define how onReceive will behave:
// Default: true -- The callback will only be called when RX Timeout happens.
// Whole stream of bytes will be ready for being read on the callback function at once.
// This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received in the streaming
// false -- The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
// The stream of incommig bytes will be "split" into blocks of 120 bytes on each callback.
// This option avoid any sort of Rx Overflow, but leaves the UART packet reassembling work to the Application.
void onReceive(OnReceiveCb function, bool onlyOnTimeout = false);
// onReceive will be called on error events (see hardwareSerial_error_t)
void onReceiveError(OnReceiveErrorCb function);
// eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe usefull in some use cases
void eventQueueReset();
// When pins are changed, it will detach the previous ones
// if pin is negative, it won't be set/changed and will be kept as is
// timeout_ms is used in baudrate detection (ESP32, ESP32S2 only)
// invert will invert RX/TX polarity
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112);
void end(bool fullyTerminate = true);
void updateBaudRate(unsigned long baud);
int available(void);
int availableForWrite(void);
int peek(void);
int read(void);
size_t read(uint8_t *buffer, size_t size);
inline size_t read(char * buffer, size_t size)
{
return read((uint8_t*) buffer, size);
}
// Overrides Stream::readBytes() to be faster using IDF
size_t readBytes(uint8_t *buffer, size_t length);
size_t readBytes(char *buffer, size_t length)
{
return readBytes((uint8_t *) buffer, length);
}
void flush(void);
void flush( bool txOnly);
size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);
inline size_t write(const char * buffer, size_t size)
{
return write((uint8_t*) buffer, size);
}
inline size_t write(const char * s)
{
return write((uint8_t*) s, strlen(s));
}
inline size_t write(unsigned long n)
{
return write((uint8_t) n);
}
inline size_t write(long n)
{
return write((uint8_t) n);
}
inline size_t write(unsigned int n)
{
return write((uint8_t) n);
}
inline size_t write(int n)
{
return write((uint8_t) n);
}
uint32_t baudRate();
operator bool() const;
void setDebugOutput(bool);
void setRxInvert(bool);
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
// setPins() can be called after or before begin()
// When pins are changed, it will detach the previous ones
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
bool setHwFlowCtrlMode(SerialHwFlowCtrl mode = UART_HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
// Used to set RS485 modes such as UART_MODE_RS485_HALF_DUPLEX for Auto RTS function on ESP32
// UART_MODE_UART = 0x00 mode: regular UART mode
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
bool setMode(SerialMode mode);
size_t setRxBufferSize(size_t new_size);
size_t setTxBufferSize(size_t new_size);
protected:
uint8_t _uart_nr;
uart_t* _uart;
size_t _rxBufferSize;
size_t _txBufferSize;
OnReceiveCb _onReceiveCB;
OnReceiveErrorCb _onReceiveErrorCB;
// _onReceive and _rxTimeout have be consistent when timeout is disabled
bool _onReceiveTimeout;
uint8_t _rxTimeout, _rxFIFOFull;
TaskHandle_t _eventTask;
#if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t _lock;
#endif
void _createEventTask(void *args);
void _destroyEventTask(void);
static void _uartEventTask(void *args);
};
extern void serialEventRun(void) __attribute__((weak));
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
#ifndef ARDUINO_USB_CDC_ON_BOOT
#define ARDUINO_USB_CDC_ON_BOOT 0
#endif
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
#if !ARDUINO_USB_MODE
#include "USB.h"
#include "USBCDC.h"
#endif
extern HardwareSerial Serial0;
#else
extern HardwareSerial Serial;
#endif
#if SOC_UART_NUM > 1
extern HardwareSerial Serial1;
#endif
#if SOC_UART_NUM > 2
extern HardwareSerial Serial2;
#endif
#endif
#endif // HardwareSerial_h

125
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/IPAddress.cpp

@ -0,0 +1,125 @@
/*
IPAddress.cpp - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <IPAddress.h>
#include <Print.h>
IPAddress::IPAddress()
{
_address.dword = 0;
}
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
{
_address.bytes[0] = first_octet;
_address.bytes[1] = second_octet;
_address.bytes[2] = third_octet;
_address.bytes[3] = fourth_octet;
}
IPAddress::IPAddress(uint32_t address)
{
_address.dword = address;
}
IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
}
IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this;
}
IPAddress& IPAddress::operator=(uint32_t address)
{
_address.dword = address;
return *this;
}
bool IPAddress::operator==(const uint8_t* addr) const
{
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
}
size_t IPAddress::printTo(Print& p) const
{
size_t n = 0;
for(int i = 0; i < 3; i++) {
n += p.print(_address.bytes[i], DEC);
n += p.print('.');
}
n += p.print(_address.bytes[3], DEC);
return n;
}
String IPAddress::toString() const
{
char szRet[16];
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]);
return String(szRet);
}
bool IPAddress::fromString(const char *address)
{
// TODO: add support for "a", "a.b", "a.b.c" formats
uint16_t acc = 0; // Accumulator
uint8_t dots = 0;
while (*address)
{
char c = *address++;
if (c >= '0' && c <= '9')
{
acc = acc * 10 + (c - '0');
if (acc > 255) {
// Value out of [0..255] range
return false;
}
}
else if (c == '.')
{
if (dots == 3) {
// Too much dots (there must be 3 dots)
return false;
}
_address.bytes[dots++] = acc;
acc = 0;
}
else
{
// Invalid char
return false;
}
}
if (dots != 3) {
// Too few dots (there must be 3 dots)
return false;
}
_address.bytes[3] = acc;
return true;
}
// declared one time - as external in IPAddress.h
IPAddress INADDR_NONE(0, 0, 0, 0);

96
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/IPAddress.h

@ -0,0 +1,96 @@
/*
IPAddress.h - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef IPAddress_h
#define IPAddress_h
#include <stdint.h>
#include <WString.h>
#include <Printable.h>
// A class to make it easier to handle and pass around IP addresses
class IPAddress: public Printable
{
private:
union {
uint8_t bytes[4]; // IPv4 address
uint32_t dword;
} _address;
// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address()
{
return _address.bytes;
}
public:
// Constructors
IPAddress();
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
IPAddress(uint32_t address);
IPAddress(const uint8_t *address);
virtual ~IPAddress() {}
bool fromString(const char *address);
bool fromString(const String &address) { return fromString(address.c_str()); }
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t() const
{
return _address.dword;
}
bool operator==(const IPAddress& addr) const
{
return _address.dword == addr._address.dword;
}
bool operator==(const uint8_t* addr) const;
// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const
{
return _address.bytes[index];
}
uint8_t& operator[](int index)
{
return _address.bytes[index];
}
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address);
IPAddress& operator=(uint32_t address);
virtual size_t printTo(Print& p) const;
String toString() const;
friend class EthernetClass;
friend class UDP;
friend class Client;
friend class Server;
friend class DhcpClass;
friend class DNSClient;
};
// changed to extern because const declaration creates copies in BSS of INADDR_NONE for each CPP unit that includes it
extern IPAddress INADDR_NONE;
#endif

90
maddius/maddius_matrix_control/components/espressif__arduino-esp32/cores/esp32/IPv6Address.cpp

@ -0,0 +1,90 @@
/*
IPv6Address.cpp - Base class that provides IPv6Address
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <IPv6Address.h>
#include <Print.h>
IPv6Address::IPv6Address()
{
memset(_address.bytes, 0, sizeof(_address.bytes));
}
IPv6Address::IPv6Address(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
}
IPv6Address::IPv6Address(const uint32_t *address)
{
memcpy(_address.bytes, (const uint8_t *)address, sizeof(_address.bytes));
}
IPv6Address& IPv6Address::operator=(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this;
}
bool IPv6Address::operator==(const uint8_t* addr) const
{
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
}
size_t IPv6Address::printTo(Print& p) const
{
size_t n = 0;
for(int i = 0; i < 16; i+=2) {
if(i){
n += p.print(':');
}
n += p.printf("%02x", _address.bytes[i]);
n += p.printf("%02x", _address.bytes[i+1]);
}
return n;
}
String IPv6Address::toString() const
{
char szRet[40];
sprintf(szRet,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
_address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3],
_address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7],
_address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11],
_address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]);
return String(szRet);
}
bool IPv6Address::fromString(const char *address)
{
//format 0011:2233:4455:6677:8899:aabb:ccdd:eeff
if(strlen(address) != 39){
return false;
}
char * pos = (char *)address;
size_t i = 0;
for(i = 0; i < 16; i+=2) {
if(!sscanf(pos, "%2hhx", &_address.bytes[i]) || !sscanf(pos+2, "%2hhx", &_address.bytes[i+1])){
return false;
}
pos += 5;
}
return true;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save