aboutsummaryrefslogtreecommitdiff
path: root/fsm/ramping.h
diff options
context:
space:
mode:
Diffstat (limited to 'fsm/ramping.h')
-rw-r--r--fsm/ramping.h167
1 files changed, 167 insertions, 0 deletions
diff --git a/fsm/ramping.h b/fsm/ramping.h
new file mode 100644
index 0000000..c4b7d48
--- /dev/null
+++ b/fsm/ramping.h
@@ -0,0 +1,167 @@
+// fsm-ramping.h: Ramping functions for SpaghettiMonster.
+// Copyright (C) 2017-2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#ifdef USE_RAMPING
+
+// actual_level: last ramp level set by set_level()
+uint8_t actual_level = 0;
+// the level used before actual
+uint8_t prev_level = 0;
+
+void set_level(uint8_t level);
+//void set_level_smooth(uint8_t level);
+void set_level_zero(); // implement this in a hwdef
+
+#ifdef USE_SET_LEVEL_GRADUALLY
+// adjust brightness very smoothly
+uint8_t gradual_target;
+inline void set_level_gradually(uint8_t lvl);
+void gradual_tick();
+
+// reduce repetition with macros
+#define GRADUAL_TICK_SETUP() \
+ PWM_DATATYPE target;
+
+// tick to a specific value
+#define GRADUAL_ADJUST_SIMPLE(TARGET,PWM) \
+ if (PWM < TARGET) PWM ++; \
+ else if (PWM > TARGET) PWM --;
+
+// tick to a specific value, except when immediate 0 to 255 is needed
+#define GRADUAL_ADJUST_STACKED(TARGET,PWM,TOP) \
+ if ( ((PWM == 0) && (TARGET == TOP)) \
+ || ((PWM == TOP) && (TARGET == 0))) \
+ PWM = TARGET; \
+ else GRADUAL_ADJUST_SIMPLE(TARGET,PWM)
+
+// tick the top layer of the stack
+#define GRADUAL_ADJUST_1CH(TABLE,PWM) \
+ target = PWM_GET(TABLE, gt); \
+ if (PWM < target) PWM ++; \
+ else if (PWM > target) PWM --;
+
+// tick a base level of the stack
+// (with support for special DD FET behavior
+// like "low=0, high=255" --> "low=255, high=254")
+#define GRADUAL_ADJUST(TABLE,PWM,TOP) \
+ target = PWM_GET(TABLE, gt); \
+ if ((gt < actual_level) \
+ && (PWM == 0) \
+ && (target == TOP)) PWM = TOP; \
+ else \
+ if (PWM < target) PWM ++; \
+ else if (PWM > target) PWM --;
+
+#endif // ifdef USE_SET_LEVEL_GRADUALLY
+
+// auto-detect the data type for PWM tables
+// FIXME: PWM bits and data type should be per PWM table
+// FIXME: this whole thing is a mess and should be removed
+#ifndef PWM1_BITS
+ #define PWM1_BITS 8
+ #define PWM1_TOP 255
+ #define STACKED_PWM_TOP 255
+#endif
+#if PWM_BITS <= 8
+ #define STACKED_PWM_DATATYPE uint8_t
+ #define PWM_DATATYPE uint8_t
+ #define PWM_DATATYPE2 uint16_t
+ #ifndef PWM_TOP
+ #define PWM_TOP 255
+ #endif
+ #define STACKED_PWM_TOP 255
+ #ifndef PWM_GET
+ #define PWM_GET(x,y) pgm_read_byte(x+y)
+ #endif
+#else
+ #define STACKED_PWM_DATATYPE uint16_t
+ #define PWM_DATATYPE uint16_t
+ #ifndef PWM_DATATYPE2
+ #define PWM_DATATYPE2 uint32_t
+ #endif
+ #ifndef PWM_TOP
+ #define PWM_TOP 1023 // 10 bits by default
+ #endif
+ #ifndef STACKED_PWM_TOP
+ #define STACKED_PWM_TOP 1023
+ #endif
+ // pointer plus 2*y bytes
+ //#define PWM_GET(x,y) pgm_read_word(x+(2*y))
+ // nope, the compiler was already doing the math correctly
+ #ifndef PWM_GET
+ #define PWM_GET(x,y) pgm_read_word(x+y)
+ #endif
+#endif
+#define PWM_GET8(x,y) pgm_read_byte(x+y)
+#define PWM_GET16(x,y) pgm_read_word(x+y)
+
+// use UI-defined ramp tables if they exist
+#ifdef PWM1_LEVELS
+PROGMEM const PWM1_DATATYPE pwm1_levels[] = { PWM1_LEVELS };
+#endif
+#ifdef PWM2_LEVELS
+PROGMEM const PWM2_DATATYPE pwm2_levels[] = { PWM2_LEVELS };
+#endif
+#ifdef PWM3_LEVELS
+PROGMEM const PWM3_DATATYPE pwm3_levels[] = { PWM3_LEVELS };
+#endif
+#ifdef PWM4_LEVELS
+PROGMEM const PWM4_DATATYPE pwm4_levels[] = { PWM4_LEVELS };
+#endif
+#ifdef PWM5_LEVELS
+PROGMEM const PWM5_DATATYPE pwm5_levels[] = { PWM5_LEVELS };
+#endif
+
+// convenience defs for 1 LED with stacked channels
+// FIXME: remove this, use pwm1/2/3 instead
+#ifdef LOW_PWM_LEVELS
+PROGMEM const PWM_DATATYPE low_pwm_levels[] = { LOW_PWM_LEVELS };
+#endif
+#ifdef MED_PWM_LEVELS
+PROGMEM const PWM_DATATYPE med_pwm_levels[] = { MED_PWM_LEVELS };
+#endif
+#ifdef HIGH_PWM_LEVELS
+PROGMEM const PWM_DATATYPE high_pwm_levels[] = { HIGH_PWM_LEVELS };
+#endif
+
+// 2 channel CCT blending ramp
+#ifdef BLEND_PWM_LEVELS
+// FIXME: remove this, use pwm1/2/3 instead
+PROGMEM const PWM_DATATYPE blend_pwm_levels[] = { BLEND_PWM_LEVELS };
+#endif
+
+
+// pulse frequency modulation, a.k.a. dynamic PWM
+// (different ceiling / frequency at each ramp level)
+// FIXME: dynamic PWM should be a per-channel option, not global
+#ifdef PWM_TOPS
+PROGMEM const PWM_DATATYPE pwm_tops[] = { PWM_TOPS };
+#endif
+
+// FIXME: jump start should be per channel / channel mode
+#ifdef USE_JUMP_START
+ #ifndef JUMP_START_TIME
+ #define JUMP_START_TIME 8 // in ms, should be 4, 8, or 12
+ #endif
+ #ifndef DEFAULT_JUMP_START_LEVEL
+ #define DEFAULT_JUMP_START_LEVEL 10
+ #endif
+ #ifdef USE_CFG
+ #define JUMP_START_LEVEL cfg.jump_start_level
+ #else
+ #define JUMP_START_LEVEL jump_start_level
+ uint8_t jump_start_level = DEFAULT_JUMP_START_LEVEL;
+ #endif
+#endif
+
+// RAMP_SIZE / MAX_LVL
+// cfg-*.h should define RAMP_SIZE
+//#define RAMP_SIZE (sizeof(stacked_pwm1_levels)/sizeof(STACKED_PWM_DATATYPE))
+#define MAX_LEVEL RAMP_SIZE
+
+
+#endif // ifdef USE_RAMPING
+