/* * This program source code file is part of SystemK, a library in the KTag project. * * 🛡️ 🃞 * * Copyright © 2016-2025 Joseph P. Kearney and the KTag developers. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * There should be a copy of the GNU Affero General Public License in the LICENSE * file in the root of this repository. If not, see . */ /** \file * \brief This file defines the interface to the NeoPixels used by the KTag system (SystemK). * */ #ifndef NEOPIXELS_H #define NEOPIXELS_H #include #ifdef ESP_PLATFORM #include "sdkconfig.h" #endif // ESP_PLATFORM #ifdef PSOC_PLATFORM #include "CONFIG.h" #endif // PSOC_PLATFORM #include "Gamma.h" #include "Sine.h" #include "Animation.h" #if (CONFIG_KTAG_N_NEOPIXEL_CHANNELS == 1) typedef enum { // The Lil' Bruv and the Little Boy BLuE only have one NeoPixel channel. NEOPIXEL_CHANNEL_BARREL = 0, NEOPIXEL_CHANNEL_RECEIVER = 0, NEOPIXEL_CHANNEL_DISPLAY = 0, NEOPIXEL_CHANNEL_EFFECTS = 0, NEOPIXEL_CHANNEL_ALL = 100, NEOPIXEL_CHANNEL_NONE = 200 } NeoPixelsChannel_T; #elif (CONFIG_KTAG_N_NEOPIXEL_CHANNELS == 4) typedef enum { // The 2020TPC and the 32ESPecial have four NeoPixel channels. NEOPIXEL_CHANNEL_BARREL = 0, NEOPIXEL_CHANNEL_RECEIVER = 1, NEOPIXEL_CHANNEL_DISPLAY = 2, NEOPIXEL_CHANNEL_EFFECTS = 3, NEOPIXEL_CHANNEL_ALL = 100, NEOPIXEL_CHANNEL_NONE = 200 } NeoPixelsChannel_T; #else #error "Unsupported number of NeoPixel channels defined. Supported configurations are 1 and 4." #endif #include "NeoPixel_HW_Interface.h" #include "Animations/All_Off.h" #include "Animations/All_On.h" #include "Animations/BLE_Nearby.h" #include "Animations/BLE_RSSI.h" #include "Animations/Countdown.h" #include "Animations/Flamethrower.h" #include "Animations/Flashlight.h" #include "Animations/Health_Report.h" #include "Animations/Idle_Animation.h" #include "Animations/Menu_Animation.h" #include "Animations/Shot_Fired.h" #include "Animations/Tag_Received.h" #include "Animations/Tagged_Out.h" #include "Animations/Team_Colors.h" #include "Animations/Test_Pattern.h" extern QueueHandle_t xQueueNeoPixels; extern TaskHandle_t NeoPixels_Task_Handle; extern SemaphoreHandle_t NeoPixels_Semaphore; #if (CONFIG_KTAG_N_NEOPIXEL_CHANNELS == 1) #include "Single_Channel_Helpers.h" #elif (CONFIG_KTAG_N_NEOPIXEL_CHANNELS == 4) #include "Four_Channel_Helpers.h" #else #error "Unsupported number of NeoPixel channels defined. Supported configurations are 1 and 4." #endif typedef enum { COLOR_ORDER_RGB = 0, COLOR_ORDER_RBG = 1, COLOR_ORDER_GRB = 2, COLOR_ORDER_GBR = 3, COLOR_ORDER_BRG = 4, COLOR_ORDER_BGR = 5 } ColorOrder_T; typedef enum { DISPLAY_STYLE_DEFAULT = 0, DISPLAY_STYLE_SOLID = 1, DISPLAY_STYLE_ALTERNATE = 2, DISPLAY_STYLE_BLINK = 3, DISPLAY_STYLE_HEARTBEAT = 4, //----------------------------------------------- FIRST_DISPLAY_STYLE = DISPLAY_STYLE_DEFAULT, LAST_DISPLAY_STYLE = DISPLAY_STYLE_HEARTBEAT } DisplayStyle_T; typedef enum { NEOPIXELS_ALL_OFF, NEOPIXELS_ALL_ON, NEOPIXELS_TEST_PATTERN, NEOPIXELS_PLAY_SHOT_FIRED, NEOPIXELS_FLASHLIGHT_ON, NEOPIXELS_FLAMETHROWER, NEOPIXELS_TAG_RECEIVED, NEOPIXELS_TAGGED_OUT, NEOPIXELS_MENU, NEOPIXELS_HEALTH_REPORT, NEOPIXELS_BLE_RSSI, NEOPIXELS_IDLE, NEOPIXELS_COUNTDOWN, //! For #NEOPIXELS_TEAM_COLORS, #NeoPixelsAction_T::Data is a #DisplayStyle_T. NEOPIXELS_TEAM_COLORS, //! For #NEOPIXELS_TEAM_COLORS, #NeoPixelsAction_T::Data is a #BLENearby_T. NEOPIXELS_BLE_NEARBY } NeoPixelsActionID_T; typedef enum { NEOPIXELS_FOREGROUND, NEOPIXELS_BACKGROUND, } NeoPixelsProminence_T; typedef struct { NeoPixelsActionID_T ID; NeoPixelsProminence_T Prominence; void * Data; } NeoPixelsAction_T; typedef struct { color_t color; DisplayStyle_T style; } All_On_Data_T; void NeoPixels_Task(void * pvParameters); static inline __attribute__((always_inline)) void NeoPixels_Set_Color(NeoPixelsChannel_T channel, uint8_t position, color_t color) { HW_NeoPixels_Set_RGB(channel, position, Gamma8[Red(color)], Gamma8[Green(color)], Gamma8[Blue(color)]); } static inline void NeoPixel_Set_Range(NeoPixelsChannel_T channel, uint8_t start, uint8_t end, uint8_t red, uint8_t green ,uint8_t blue) { for (uint_fast8_t position = start; position <= end; position++) { HW_NeoPixels_Set_RGB(channel, position, red, green, blue); } } static inline __attribute__((always_inline)) void NeoPixels_Set_Color_Range(NeoPixelsChannel_T channel, uint8_t start, uint8_t end, color_t color) { NeoPixel_Set_Range(channel, start, end, Gamma8[Red(color)], Gamma8[Green(color)], Gamma8[Blue(color)]); } static inline __attribute__((always_inline)) void NeoPixels_Set_Color_Range_On_All_Channels(uint8_t start, uint8_t end, color_t color) { #if (CONFIG_KTAG_N_NEOPIXEL_CHANNELS > 1) NeoPixel_Set_Range(NEOPIXEL_CHANNEL_BARREL, start, end, Gamma8[Red(color)], Gamma8[Green(color)], Gamma8[Blue(color)]); NeoPixel_Set_Range(NEOPIXEL_CHANNEL_RECEIVER, start, end, Gamma8[Red(color)], Gamma8[Green(color)], Gamma8[Blue(color)]); NeoPixel_Set_Range(NEOPIXEL_CHANNEL_DISPLAY, start, end, Gamma8[Red(color)], Gamma8[Green(color)], Gamma8[Blue(color)]); NeoPixel_Set_Range(NEOPIXEL_CHANNEL_EFFECTS, start, end, Gamma8[Red(color)], Gamma8[Green(color)], Gamma8[Blue(color)]); #else // (CONFIG_KTAG_N_NEOPIXEL_CHANNELS > 1) NeoPixel_Set_Range(NEOPIXEL_CHANNEL_BARREL, start, end, Gamma8[Red(color)], Gamma8[Green(color)], Gamma8[Blue(color)]); #endif // (CONFIG_KTAG_N_NEOPIXEL_CHANNELS > 1) } static inline __attribute__((always_inline)) DisplayStyle_T NeoPixels_ToDisplayStyle(void * value) { DisplayStyle_T result = FIRST_DISPLAY_STYLE; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wtype-limits" if (((DisplayStyle_T)value >= FIRST_DISPLAY_STYLE) && ((DisplayStyle_T)value <= LAST_DISPLAY_STYLE)) { result = (DisplayStyle_T)value; } #pragma GCC diagnostic pop return result; } #endif // NEOPIXELS_H