|
24 | 24 | #include "eagle_soc.h"
|
25 | 25 | #include "ets_sys.h"
|
26 | 26 |
|
| 27 | +#ifndef F_CPU |
| 28 | +#define F_CPU 800000000L |
| 29 | +#endif |
| 30 | + |
| 31 | +struct pwm_isr_table { |
| 32 | + uint8_t len; |
| 33 | + uint16_t steps[17]; |
| 34 | + uint32_t masks[17]; |
| 35 | +}; |
| 36 | + |
| 37 | +struct pwm_isr_data { |
| 38 | + struct pwm_isr_table tables[2]; |
| 39 | + uint8_t active;//0 or 1, which table is active in ISR |
| 40 | +}; |
| 41 | + |
| 42 | +static struct pwm_isr_data _pwm_isr_data; |
| 43 | + |
27 | 44 | uint32_t pwm_mask = 0;
|
28 | 45 | uint16_t pwm_values[17] = {0,};
|
29 | 46 | uint32_t pwm_freq = 1000;
|
30 | 47 | uint32_t pwm_range = PWMRANGE;
|
31 | 48 |
|
| 49 | +uint8_t pwm_steps_changed = 0; |
32 | 50 | uint32_t pwm_multiplier = 0;
|
33 |
| -uint16_t pwm_steps[17]; |
34 |
| -uint8_t pwm_steps_len = 0; |
35 |
| -uint32_t pwm_steps_mask[17]; |
36 |
| - |
37 |
| -int pwm_sort_array(uint16_t a[], uint16_t al){ |
38 |
| - uint16_t i, j; |
39 |
| - for (i = 1; i < al; i++) { |
40 |
| - uint16_t tmp = a[i]; |
41 |
| - for (j = i; j >= 1 && tmp < a[j-1]; j--) |
42 |
| - a[j] = a[j-1]; |
43 |
| - a[j] = tmp; |
44 |
| - } |
45 |
| - int bl = 1; |
46 |
| - for(i = 1; i < al; i++){ |
47 |
| - if(a[i] != a[i-1]) a[bl++] = a[i]; |
48 |
| - } |
49 |
| - return bl; |
| 51 | + |
| 52 | +int pwm_sort_array(uint16_t a[], uint16_t al) |
| 53 | +{ |
| 54 | + uint16_t i, j; |
| 55 | + for (i = 1; i < al; i++) { |
| 56 | + uint16_t tmp = a[i]; |
| 57 | + for (j = i; j >= 1 && tmp < a[j-1]; j--) { |
| 58 | + a[j] = a[j-1]; |
| 59 | + } |
| 60 | + a[j] = tmp; |
| 61 | + } |
| 62 | + int bl = 1; |
| 63 | + for(i = 1; i < al; i++) { |
| 64 | + if(a[i] != a[i-1]) { |
| 65 | + a[bl++] = a[i]; |
| 66 | + } |
| 67 | + } |
| 68 | + return bl; |
50 | 69 | }
|
51 | 70 |
|
52 |
| -uint32_t pwm_get_mask(uint16_t value){ |
53 |
| - uint32_t mask = 0; |
54 |
| - int i; |
55 |
| - for(i=0; i<17; i++){ |
56 |
| - if((pwm_mask & (1 << i)) != 0 && pwm_values[i] == value) mask |= (1 << i); |
57 |
| - } |
58 |
| - return mask; |
| 71 | +uint32_t pwm_get_mask(uint16_t value) |
| 72 | +{ |
| 73 | + uint32_t mask = 0; |
| 74 | + int i; |
| 75 | + for(i=0; i<17; i++) { |
| 76 | + if((pwm_mask & (1 << i)) != 0 && pwm_values[i] == value) { |
| 77 | + mask |= (1 << i); |
| 78 | + } |
| 79 | + } |
| 80 | + return mask; |
59 | 81 | }
|
60 | 82 |
|
61 |
| -void prep_pwm_steps(){ |
62 |
| - if(pwm_mask == 0){ |
63 |
| - pwm_steps_len = 0; |
64 |
| - return; |
65 |
| - } |
66 |
| - |
67 |
| - int pwm_temp_steps_len = 0; |
68 |
| - uint16_t pwm_temp_steps[17]; |
69 |
| - uint32_t pwm_temp_masks[17]; |
70 |
| - |
71 |
| - int i; |
72 |
| - for(i=0; i<17; i++){ |
73 |
| - if((pwm_mask & (1 << i)) != 0 && pwm_values[i] != 0) pwm_temp_steps[pwm_temp_steps_len++] = pwm_values[i]; |
74 |
| - } |
75 |
| - pwm_temp_steps[pwm_temp_steps_len++] = pwm_range; |
76 |
| - pwm_temp_steps_len = pwm_sort_array(pwm_temp_steps, pwm_temp_steps_len) - 1; |
77 |
| - for(i=0; i<pwm_temp_steps_len; i++){ |
78 |
| - pwm_temp_masks[i] = pwm_get_mask(pwm_temp_steps[i]); |
79 |
| - } |
80 |
| - for(i=pwm_temp_steps_len; i>0; i--){ |
81 |
| - pwm_temp_steps[i] = pwm_temp_steps[i] - pwm_temp_steps[i-1]; |
82 |
| - } |
83 |
| - ETS_FRC1_INTR_DISABLE(); |
84 |
| - pwm_steps_len = pwm_temp_steps_len; |
85 |
| - ets_memcpy(pwm_steps, pwm_temp_steps, (pwm_temp_steps_len + 1) * 2); |
86 |
| - ets_memcpy(pwm_steps_mask, pwm_temp_masks, pwm_temp_steps_len * 4); |
87 |
| - pwm_multiplier = ESP8266_CLOCK/(pwm_range * pwm_freq); |
88 |
| - ETS_FRC1_INTR_ENABLE(); |
| 83 | +void prep_pwm_steps() |
| 84 | +{ |
| 85 | + if(pwm_mask == 0) { |
| 86 | + return; |
| 87 | + } |
| 88 | + |
| 89 | + int pwm_temp_steps_len = 0; |
| 90 | + uint16_t pwm_temp_steps[17]; |
| 91 | + uint32_t pwm_temp_masks[17]; |
| 92 | + uint32_t range = pwm_range; |
| 93 | + |
| 94 | + if((F_CPU / ESP8266_CLOCK) == 1) { |
| 95 | + range /= 2; |
| 96 | + } |
| 97 | + |
| 98 | + int i; |
| 99 | + for(i=0; i<17; i++) { |
| 100 | + if((pwm_mask & (1 << i)) != 0 && pwm_values[i] != 0) { |
| 101 | + pwm_temp_steps[pwm_temp_steps_len++] = pwm_values[i]; |
| 102 | + } |
| 103 | + } |
| 104 | + pwm_temp_steps[pwm_temp_steps_len++] = range; |
| 105 | + pwm_temp_steps_len = pwm_sort_array(pwm_temp_steps, pwm_temp_steps_len) - 1; |
| 106 | + for(i=0; i<pwm_temp_steps_len; i++) { |
| 107 | + pwm_temp_masks[i] = pwm_get_mask(pwm_temp_steps[i]); |
| 108 | + } |
| 109 | + for(i=pwm_temp_steps_len; i>0; i--) { |
| 110 | + pwm_temp_steps[i] = pwm_temp_steps[i] - pwm_temp_steps[i-1]; |
| 111 | + } |
| 112 | + |
| 113 | + pwm_steps_changed = 0; |
| 114 | + struct pwm_isr_table *table = &(_pwm_isr_data.tables[!_pwm_isr_data.active]); |
| 115 | + table->len = pwm_temp_steps_len; |
| 116 | + ets_memcpy(table->steps, pwm_temp_steps, (pwm_temp_steps_len + 1) * 2); |
| 117 | + ets_memcpy(table->masks, pwm_temp_masks, pwm_temp_steps_len * 4); |
| 118 | + pwm_multiplier = ESP8266_CLOCK/(range * pwm_freq); |
| 119 | + pwm_steps_changed = 1; |
89 | 120 | }
|
90 | 121 |
|
91 |
| -void ICACHE_RAM_ATTR pwm_timer_isr(){ |
92 |
| - static uint8_t current_step = 0; |
93 |
| - static uint8_t stepcount = 0; |
94 |
| - static uint16_t steps[17]; |
95 |
| - static uint32_t masks[17]; |
96 |
| - if(current_step < stepcount){ |
97 |
| - T1L = (pwm_steps[current_step+1] * pwm_multiplier); |
98 |
| - TEIE |= TEIE1; |
99 |
| - if(masks[current_step] & 0xFFFF) GPOC = masks[current_step] & 0xFFFF; |
100 |
| - if(masks[current_step] & 0x10000) GP16O = 0; |
101 |
| - current_step++; |
102 |
| - } else { |
103 |
| - current_step = 0; |
104 |
| - stepcount = 0; |
105 |
| - if(pwm_mask == 0) return; |
106 |
| - T1L = (pwm_steps[current_step] * pwm_multiplier); |
107 |
| - TEIE |= TEIE1; |
108 |
| - if(pwm_mask & 0xFFFF) GPOS = pwm_mask & 0xFFFF; |
109 |
| - if(pwm_mask & 0x10000) GP16O = 1; |
110 |
| - stepcount = pwm_steps_len; |
111 |
| - memcpy(steps, pwm_steps, (stepcount + 1) * 2); |
112 |
| - memcpy(masks, pwm_steps_mask, stepcount * 4); |
113 |
| - } |
| 122 | +void ICACHE_RAM_ATTR pwm_timer_isr() //103-138 |
| 123 | +{ |
| 124 | + struct pwm_isr_table *table = &(_pwm_isr_data.tables[_pwm_isr_data.active]); |
| 125 | + static uint8_t current_step = 0; |
| 126 | + TEIE &= ~TEIE1;//14 |
| 127 | + T1I = 0;//9 |
| 128 | + if(current_step < table->len) { //20/21 |
| 129 | + if(table->masks[current_step] & 0xFFFF) { |
| 130 | + GPOC = table->masks[current_step] & 0xFFFF; //15/21 |
| 131 | + } |
| 132 | + if(table->masks[current_step] & 0x10000) { |
| 133 | + GP16O = 0; //6/13 |
| 134 | + } |
| 135 | + current_step++;//1 |
| 136 | + } else { |
| 137 | + current_step = 0;//1 |
| 138 | + if(pwm_mask == 0) { //12 |
| 139 | + table->len = 0; |
| 140 | + return; |
| 141 | + } |
| 142 | + if(pwm_mask & 0xFFFF) { |
| 143 | + GPOS = pwm_mask & 0xFFFF; //11 |
| 144 | + } |
| 145 | + if(pwm_mask & 0x10000) { |
| 146 | + GP16O = 1; //5/13 |
| 147 | + } |
| 148 | + if(pwm_steps_changed) { //12/21 |
| 149 | + _pwm_isr_data.active = !_pwm_isr_data.active; |
| 150 | + table = &(_pwm_isr_data.tables[_pwm_isr_data.active]); |
| 151 | + pwm_steps_changed = 0; |
| 152 | + } |
| 153 | + } |
| 154 | + T1L = (table->steps[current_step] * pwm_multiplier);//23 |
| 155 | + TEIE |= TEIE1;//13 |
114 | 156 | }
|
115 | 157 |
|
116 |
| -void pwm_start_timer(){ |
117 |
| - timer1_disable(); |
118 |
| - timer1_attachInterrupt(pwm_timer_isr); |
119 |
| - timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE); |
120 |
| - timer1_write(1); |
| 158 | +void pwm_start_timer() |
| 159 | +{ |
| 160 | + timer1_disable(); |
| 161 | + ETS_FRC_TIMER1_INTR_ATTACH(NULL, NULL); |
| 162 | + ETS_FRC_TIMER1_NMI_INTR_ATTACH(pwm_timer_isr); |
| 163 | + timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE); |
| 164 | + timer1_write(1); |
121 | 165 | }
|
122 | 166 |
|
123 |
| -extern void __analogWrite(uint8_t pin, int value) { |
124 |
| - bool start_timer = false; |
125 |
| - if(value == 0){ |
126 |
| - pwm_mask &= ~(1 << pin); |
127 |
| - prep_pwm_steps(); |
128 |
| - digitalWrite(pin, LOW); |
129 |
| - if(pwm_mask == 0) timer1_disable(); |
130 |
| - return; |
131 |
| - } |
132 |
| - if((pwm_mask & (1 << pin)) == 0){ |
133 |
| - if(pwm_mask == 0) start_timer = true; |
134 |
| - pwm_mask |= (1 << pin); |
135 |
| - pinMode(pin, OUTPUT); |
136 |
| - digitalWrite(pin, LOW); |
137 |
| - } |
138 |
| - pwm_values[pin] = value % (pwm_range + 1); |
139 |
| - prep_pwm_steps(); |
140 |
| - if(start_timer){ |
141 |
| - pwm_start_timer(); |
142 |
| - } |
| 167 | +extern void __analogWrite(uint8_t pin, int value) |
| 168 | +{ |
| 169 | + bool start_timer = false; |
| 170 | + if(value == 0) { |
| 171 | + pwm_mask &= ~(1 << pin); |
| 172 | + prep_pwm_steps(); |
| 173 | + digitalWrite(pin, LOW); |
| 174 | + if(pwm_mask == 0) { |
| 175 | + ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL); |
| 176 | + timer1_disable(); |
| 177 | + timer1_isr_init(); |
| 178 | + } |
| 179 | + return; |
| 180 | + } |
| 181 | + if((pwm_mask & (1 << pin)) == 0) { |
| 182 | + if(pwm_mask == 0) { |
| 183 | + memset(&_pwm_isr_data, 0, sizeof(struct pwm_isr_data*)); |
| 184 | + start_timer = true; |
| 185 | + } |
| 186 | + pwm_mask |= (1 << pin); |
| 187 | + pinMode(pin, OUTPUT); |
| 188 | + digitalWrite(pin, LOW); |
| 189 | + } |
| 190 | + if((F_CPU / ESP8266_CLOCK) == 1) { |
| 191 | + value = (value+1) / 2; |
| 192 | + } |
| 193 | + pwm_values[pin] = value % (pwm_range + 1); |
| 194 | + prep_pwm_steps(); |
| 195 | + if(start_timer) { |
| 196 | + pwm_start_timer(); |
| 197 | + } |
143 | 198 | }
|
144 | 199 |
|
145 |
| -extern void __analogWriteFreq(uint32_t freq){ |
146 |
| - pwm_freq = freq; |
147 |
| - prep_pwm_steps(); |
| 200 | +extern void __analogWriteFreq(uint32_t freq) |
| 201 | +{ |
| 202 | + pwm_freq = freq; |
| 203 | + prep_pwm_steps(); |
148 | 204 | }
|
149 | 205 |
|
150 |
| -extern void __analogWriteRange(uint32_t range){ |
151 |
| - pwm_range = range; |
152 |
| - prep_pwm_steps(); |
| 206 | +extern void __analogWriteRange(uint32_t range) |
| 207 | +{ |
| 208 | + pwm_range = range; |
| 209 | + prep_pwm_steps(); |
153 | 210 | }
|
154 | 211 |
|
155 | 212 | extern void analogWrite(uint8_t pin, int val) __attribute__ ((weak, alias("__analogWrite")));
|
|
0 commit comments