aboutsummaryrefslogtreecommitdiff
path: root/fsm/ramping.h
blob: c4b7d487ba3b9776ed090ec4af645b4cdcedfec7 (plain)
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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