Skip to content

Commit

Permalink
Sync PR with dev branch
Browse files Browse the repository at this point in the history
  • Loading branch information
ia committed Mar 6, 2025
2 parents f564fa1 + 83aa1b6 commit b8d6c88
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 4 deletions.
1 change: 1 addition & 0 deletions Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 33 additions & 0 deletions Documentation/WS2812BModding.md
Original file line number Diff line number Diff line change
@@ -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`
1 change: 1 addition & 0 deletions scripts/IronOS-mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 40 additions & 1 deletion source/Core/BSP/Pinecilv2/BSP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {}

Expand Down
7 changes: 7 additions & 0 deletions source/Core/BSP/Pinecilv2/Pins.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
1 change: 1 addition & 0 deletions source/Core/BSP/Pinecilv2/preRTOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 81 additions & 0 deletions source/Core/Drivers/WS2812B.h
Original file line number Diff line number Diff line change
@@ -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_ */
6 changes: 6 additions & 0 deletions source/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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=

Expand Down
23 changes: 20 additions & 3 deletions source/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
;;
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down

0 comments on commit b8d6c88

Please sign in to comment.