mirror of
https://github.com/Ralim/IronOS.git
synced 2025-07-23 12:23:06 +02:00
Adding Pinecilv2 ws2812b mod option (#2099)
* support for WS2812B mod on Pinecil v2 * document support for WS2812B mod on Pinecil v2 * update IronOS-mkdocs.yml * Protect WS2812B_Pin with define WS2812B_ENABLE
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
- [Known Hardware Issues](../Documentation/HardwareIssues.md)
|
||||
- [Power sources](../Documentation/PowerSources.md)
|
||||
- [New Hardware Requirements](../Documentation/PortingToNewDevice.md)
|
||||
- [WS2812B RGB Modding (Pinecil V2)](../Documentation/WS2812BModding.md)
|
||||
- [Translations](../Documentation/Translation.md)
|
||||
- [Development](../Documentation/Development.md)
|
||||
- [Changelog](../Documentation/History.md)
|
||||
|
33
Documentation/WS2812BModding.md
Normal file
33
Documentation/WS2812BModding.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# WS2812B RGB Modding (Pinecil V2)
|
||||
|
||||
## What is it?
|
||||
|
||||
The idea of this mod is to bring the RGB feature of the MHP30 to the Pinecil V2.
|
||||
Use a transparent shell for a better effect.
|
||||
|
||||
Pinecil V2 has a free GPIO_12 accessible through TP10, which is along the screen, cf [Pinecil PCB placement v2.0](https://files.pine64.org/doc/Pinecil/Pinecil_PCB_placement_v2.0_20220608.pdf) page 3. (TP9 (GPIO_14) is also available but hidden below the screen. If you want to use it, change `WS2812B_Pin` in `source/Core/BSP/Pinecilv2/Pins.h`.)
|
||||
|
||||
We'll using it to drive a WS2812B and let the color logic already present for the MHP30 do its magic:
|
||||
|
||||
- green when temperature is safe (< 55°C)
|
||||
- pulsing red when heating
|
||||
- solid red when desired temperature is reached
|
||||
- orange when cooling down
|
||||
|
||||
## Electrical considerations
|
||||
|
||||
WS2812B requires a Vdd between 3.5 and 5.3V and Vih (high level of input signal) must be at least 0.7*Vdd.
|
||||
Pinecil V2 GPIO levels are 3.3V and the 5V rail is actually max 4.6V.
|
||||
So we can directly power the WS2812B on the 5V rail and command it with the GPIO without need for a level shifter, or for a Zener diode to clamp Vdd.
|
||||
|
||||
## How to wire it?
|
||||
|
||||
- WS2812B pin 1 (Vdd) is connected to the "5V" rail, e.g. on the C8 capacitor as illustrated [here](https://github.com/Ralim/IronOS/issues/1410#issuecomment-1296064392).
|
||||
- WS2812B pin 3 (Vss) is connected to the Pinecil GND, e.g. on the U10 pad at the back of the PCB, below R35, as illustrated [here](https://github.com/Ralim/IronOS/issues/1410#issuecomment-1296064392).
|
||||
- WS2812B pin 4 (Din) is connected to TP10.
|
||||
|
||||
You can use e.g. 0.1-mm enameled wire and isolate connections with UV glue to avoid any shortcut.
|
||||
|
||||
## How to enable it in the code?
|
||||
|
||||
`make firmware-EN model=Pinecilv2 ws2812b_enable=1`
|
@@ -42,6 +42,7 @@ nav:
|
||||
- Known Hardware Issues: HardwareIssues.md
|
||||
- Power sources: PowerSources.md
|
||||
- New Hardware Requirements: PortingToNewDevice.md
|
||||
- WS2812B RGB Modding (Pinecil V2): WS2812BModding.md
|
||||
- Translations: Translation.md
|
||||
- Development: Development.md
|
||||
- Changelog: History.md
|
||||
|
@@ -7,6 +7,9 @@
|
||||
#include "Pins.h"
|
||||
#include "Settings.h"
|
||||
#include "Setup.h"
|
||||
#if defined(WS2812B_ENABLE)
|
||||
#include "WS2812B.h"
|
||||
#endif
|
||||
#include "TipThermoModel.h"
|
||||
#include "USBPD.h"
|
||||
#include "Utils.hpp"
|
||||
@@ -27,6 +30,10 @@ uint8_t tempMeasureTicks = 25;
|
||||
|
||||
uint16_t totalPWM = 255; // Total length of the cycle's ticks
|
||||
|
||||
#if defined(WS2812B_ENABLE)
|
||||
WS2812B<WS2812B_Pin, 1> ws2812b;
|
||||
#endif
|
||||
|
||||
void resetWatchdog() {
|
||||
// #TODO
|
||||
}
|
||||
@@ -124,6 +131,12 @@ uint8_t getButtonB() {
|
||||
return val;
|
||||
}
|
||||
|
||||
void BSPInit(void) {
|
||||
#if defined(WS2812B_ENABLE)
|
||||
ws2812b.init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void reboot() { hal_system_reset(); }
|
||||
|
||||
void delay_ms(uint16_t count) {
|
||||
@@ -143,7 +156,33 @@ bool isTipDisconnected() {
|
||||
}
|
||||
|
||||
void setStatusLED(const enum StatusLED state) {
|
||||
// Dont have one
|
||||
#if defined(WS2812B_ENABLE)
|
||||
static enum StatusLED lastState = LED_UNKNOWN;
|
||||
|
||||
if (lastState != state || state == LED_HEATING) {
|
||||
switch (state) {
|
||||
default:
|
||||
case LED_UNKNOWN:
|
||||
case LED_OFF:
|
||||
ws2812b.led_set_color(0, 0, 0, 0);
|
||||
break;
|
||||
case LED_STANDBY:
|
||||
ws2812b.led_set_color(0, 0, 0xFF, 0); // green
|
||||
break;
|
||||
case LED_HEATING: {
|
||||
ws2812b.led_set_color(0, ((xTaskGetTickCount() / 4) % 192) + 64, 0, 0); // Red fade
|
||||
} break;
|
||||
case LED_HOT:
|
||||
ws2812b.led_set_color(0, 0xFF, 0, 0); // red
|
||||
break;
|
||||
case LED_COOLING_STILL_HOT:
|
||||
ws2812b.led_set_color(0, 0xFF, 0x20, 0x00); // Orange
|
||||
break;
|
||||
}
|
||||
ws2812b.led_update();
|
||||
lastState = state;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void setBuzzer(bool on) {}
|
||||
|
||||
|
@@ -41,4 +41,11 @@
|
||||
#define UART_TX_Pin GPIO_PIN_22
|
||||
#define UART_RX_Pin GPIO_PIN_23
|
||||
|
||||
#if defined(WS2812B_ENABLE)
|
||||
// WS2812B mod using TP10
|
||||
#define WS2812B_Pin GPIO_PIN_12
|
||||
// WS2812B mod using TP9 is doable too, but harder to reach. Thanks @t3chguy
|
||||
//#define WS2812B_Pin GPIO_PIN_14
|
||||
#endif
|
||||
|
||||
#endif /* BSP_PINE64_PINS_H_ */
|
||||
|
@@ -20,5 +20,6 @@ void preRToSInit() {
|
||||
gpio_write(OLED_RESET_Pin, 0);
|
||||
delay_ms(10);
|
||||
gpio_write(OLED_RESET_Pin, 1);
|
||||
BSPInit();
|
||||
FRToSI2C::FRToSInit();
|
||||
}
|
||||
|
81
source/Core/Drivers/WS2812B.h
Normal file
81
source/Core/Drivers/WS2812B.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* WS2812B.h
|
||||
*
|
||||
* Created on: 9 July 2023
|
||||
* Author: Doegox
|
||||
* Currently for RISC-V architecture only
|
||||
* Based on WS2812.h by Ralim for STM32
|
||||
*/
|
||||
#include "Pins.h"
|
||||
#include "Setup.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef CORE_DRIVERS_WS2812B_H_
|
||||
#define CORE_DRIVERS_WS2812B_H_
|
||||
|
||||
#ifndef WS2812B_LED_CHANNEL_COUNT
|
||||
#define WS2812B_LED_CHANNEL_COUNT 3
|
||||
#endif
|
||||
|
||||
#define WS2812B_RAW_BYTES_PER_LED (WS2812B_LED_CHANNEL_COUNT * 8)
|
||||
|
||||
template <uint16_t LED_PIN, int LED_COUNT> class WS2812B {
|
||||
private:
|
||||
uint8_t leds_colors[WS2812B_LED_CHANNEL_COUNT * LED_COUNT];
|
||||
|
||||
public:
|
||||
void led_update() {
|
||||
__disable_irq();
|
||||
// Bitbang it out as our cpu irq latency is too high
|
||||
for (unsigned int i = 0; i < sizeof(leds_colors); i++) {
|
||||
// Shove out MSB first
|
||||
for (int x = 0; x < 8; x++) {
|
||||
if ((leds_colors[i] & (1 << (7 - x))) == (1 << (7 - x))) {
|
||||
gpio_write(LED_PIN, 1);
|
||||
for (int k = 0; k < 27; k++) {
|
||||
__ASM volatile("nop");
|
||||
}
|
||||
gpio_write(LED_PIN, 0);
|
||||
for (int k = 0; k < 10; k++) {
|
||||
__ASM volatile("nop");
|
||||
}
|
||||
} else {
|
||||
gpio_write(LED_PIN, 1);
|
||||
for (int k = 0; k < 10; k++) {
|
||||
__ASM volatile("nop");
|
||||
}
|
||||
gpio_write(LED_PIN, 0);
|
||||
for (int k = 0; k < 27; k++) {
|
||||
__ASM volatile("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void init(void) { memset(leds_colors, 0, sizeof(leds_colors));
|
||||
gpio_set_mode(LED_PIN, GPIO_OUTPUT_MODE);
|
||||
gpio_write(LED_PIN, 1);
|
||||
led_set_color(0, 0, 0xFF, 0); // green
|
||||
led_update();
|
||||
}
|
||||
|
||||
void led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b) {
|
||||
leds_colors[index * WS2812B_LED_CHANNEL_COUNT + 0] = g;
|
||||
leds_colors[index * WS2812B_LED_CHANNEL_COUNT + 1] = r;
|
||||
leds_colors[index * WS2812B_LED_CHANNEL_COUNT + 2] = b;
|
||||
}
|
||||
|
||||
void led_set_color_all(uint8_t r, uint8_t g, uint8_t b) {
|
||||
for (int index = 0; index < LED_COUNT; index++) {
|
||||
leds_colors[index * WS2812B_LED_CHANNEL_COUNT + 0] = g;
|
||||
leds_colors[index * WS2812B_LED_CHANNEL_COUNT + 1] = r;
|
||||
leds_colors[index * WS2812B_LED_CHANNEL_COUNT + 2] = b;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* CORE_DRIVERS_WS2812B_H_ */
|
@@ -361,6 +361,12 @@ ifdef swd_enable
|
||||
GLOBAL_DEFINES+=-DSWD_ENABLE
|
||||
endif
|
||||
|
||||
ifeq ($(model),$(filter $(model),$(ALL_PINECIL_V2_MODELS)))
|
||||
ifdef ws2812b_enable
|
||||
GLOBAL_DEFINES += -DWS2812B_ENABLE
|
||||
endif
|
||||
endif
|
||||
|
||||
# Libs -------------------------------------------------------------------------
|
||||
LIBS=
|
||||
|
||||
|
@@ -8,6 +8,7 @@ AVAILABLE_LANGUAGES=()
|
||||
BUILD_LANGUAGES=()
|
||||
AVAILABLE_MODELS=("TS100" "TS80" "TS80P" "Pinecil" "MHP30" "Pinecilv2" "S60" "S60P" "T55" "TS101")
|
||||
BUILD_MODELS=()
|
||||
OPTIONS=()
|
||||
|
||||
builder_info() {
|
||||
echo -e "
|
||||
@@ -28,17 +29,19 @@ usage() {
|
||||
builder_info
|
||||
echo -e "
|
||||
Usage :
|
||||
$(basename "$0") [-l <LANG_CODES>] [-m <MODELS>] [-h]
|
||||
$(basename "$0") [-l <LANG_CODES>] [-m <MODELS>] [-o <OPTIONS>] [-h]
|
||||
|
||||
Parameters :
|
||||
-l LANG_CODE : Force a specific language (${AVAILABLE_LANGUAGES[*]})
|
||||
-m MODEL : Force a specific model (${AVAILABLE_MODELS[*]})
|
||||
-o key=val : Pass options to make
|
||||
-h : Show this help message
|
||||
|
||||
Example :
|
||||
$(basename "$0") -l EN -m TS100 (Build one language and model)
|
||||
$(basename "$0") -l EN -m \"TS100 MHP30\" (Build one language and multi models)
|
||||
$(basename "$0") -l \"DE EN\" -m \"TS100 MHP30\" (Build multi languages and models)
|
||||
$(basename "$0") -l EN -m Pinecilv2 -o ws2812b_enable=1
|
||||
|
||||
INFO :
|
||||
By default, without parameters, the build is for all platforms and all languages
|
||||
@@ -84,8 +87,9 @@ isInArray() {
|
||||
|
||||
declare -a margs=()
|
||||
declare -a largs=()
|
||||
declare -a oargs=()
|
||||
|
||||
while getopts "h:l:m:" option; do
|
||||
while getopts "h:l:m:o:" option; do
|
||||
case "${option}" in
|
||||
h)
|
||||
usage
|
||||
@@ -96,6 +100,9 @@ while getopts "h:l:m:" option; do
|
||||
m)
|
||||
IFS=' ' read -r -a margs <<<"${OPTARG}"
|
||||
;;
|
||||
o)
|
||||
IFS=' ' read -r -a oargs <<< "${OPTARG}"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
@@ -156,6 +163,16 @@ fi
|
||||
|
||||
echo "********************************************"
|
||||
|
||||
echo -n "Requested options : "
|
||||
if ((${#oargs[@]})); then
|
||||
for i in "${oargs[@]}"; do
|
||||
echo -n "$i "
|
||||
OPTIONS+=("$i")
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "********************************************"
|
||||
##
|
||||
#StartBuild
|
||||
|
||||
@@ -168,7 +185,7 @@ if [ ${#BUILD_LANGUAGES[@]} -gt 0 ] && [ ${#BUILD_MODELS[@]} -gt 0 ]; then
|
||||
|
||||
for model in "${BUILD_MODELS[@]}"; do
|
||||
echo "Building firmware for $model in ${BUILD_LANGUAGES[*]}"
|
||||
make -j"$(nproc)" model="$model" "${BUILD_LANGUAGES[@]/#/firmware-}" >/dev/null
|
||||
make -j"$(nproc)" model="$model" "${BUILD_LANGUAGES[@]/#/firmware-}" "${OPTIONS[@]}" >/dev/null
|
||||
checkLastCommand
|
||||
done
|
||||
else
|
||||
|
Reference in New Issue
Block a user