diff options
Diffstat (limited to 'quantum')
| -rw-r--r-- | quantum/quantum.c | 256 | ||||
| -rw-r--r-- | quantum/quantum.h | 4 |
2 files changed, 217 insertions, 43 deletions
diff --git a/quantum/quantum.c b/quantum/quantum.c index 9aa498dad..0fb798a74 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c | |||
| @@ -1138,30 +1138,38 @@ void matrix_scan_quantum() { | |||
| 1138 | 1138 | ||
| 1139 | matrix_scan_kb(); | 1139 | matrix_scan_kb(); |
| 1140 | } | 1140 | } |
| 1141 | #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) | 1141 | #if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS)) |
| 1142 | 1142 | ||
| 1143 | static const uint8_t backlight_pin = BACKLIGHT_PIN; | 1143 | // The logic is a bit complex, we support 3 setups: |
| 1144 | // 1. hardware PWM when backlight is wired to a PWM pin | ||
| 1145 | // depending on this pin, we use a different output compare unit | ||
| 1146 | // 2. software PWM with hardware timers, but the used timer depends | ||
| 1147 | // on the audio setup (audio wins other backlight) | ||
| 1148 | // 3. full software PWM | ||
| 1144 | 1149 | ||
| 1145 | // depending on the pin, we use a different output compare unit | ||
| 1146 | #if BACKLIGHT_PIN == B7 | 1150 | #if BACKLIGHT_PIN == B7 |
| 1151 | # define HARDWARE_PWM | ||
| 1147 | # define TCCRxA TCCR1A | 1152 | # define TCCRxA TCCR1A |
| 1148 | # define TCCRxB TCCR1B | 1153 | # define TCCRxB TCCR1B |
| 1149 | # define COMxx1 COM1C1 | 1154 | # define COMxx1 COM1C1 |
| 1150 | # define OCRxx OCR1C | 1155 | # define OCRxx OCR1C |
| 1151 | # define ICRx ICR1 | 1156 | # define ICRx ICR1 |
| 1152 | #elif BACKLIGHT_PIN == B6 | 1157 | #elif BACKLIGHT_PIN == B6 |
| 1158 | # define HARDWARE_PWM | ||
| 1153 | # define TCCRxA TCCR1A | 1159 | # define TCCRxA TCCR1A |
| 1154 | # define TCCRxB TCCR1B | 1160 | # define TCCRxB TCCR1B |
| 1155 | # define COMxx1 COM1B1 | 1161 | # define COMxx1 COM1B1 |
| 1156 | # define OCRxx OCR1B | 1162 | # define OCRxx OCR1B |
| 1157 | # define ICRx ICR1 | 1163 | # define ICRx ICR1 |
| 1158 | #elif BACKLIGHT_PIN == B5 | 1164 | #elif BACKLIGHT_PIN == B5 |
| 1165 | # define HARDWARE_PWM | ||
| 1159 | # define TCCRxA TCCR1A | 1166 | # define TCCRxA TCCR1A |
| 1160 | # define TCCRxB TCCR1B | 1167 | # define TCCRxB TCCR1B |
| 1161 | # define COMxx1 COM1A1 | 1168 | # define COMxx1 COM1A1 |
| 1162 | # define OCRxx OCR1A | 1169 | # define OCRxx OCR1A |
| 1163 | # define ICRx ICR1 | 1170 | # define ICRx ICR1 |
| 1164 | #elif BACKLIGHT_PIN == C6 | 1171 | #elif BACKLIGHT_PIN == C6 |
| 1172 | # define HARDWARE_PWM | ||
| 1165 | # define TCCRxA TCCR3A | 1173 | # define TCCRxA TCCR3A |
| 1166 | # define TCCRxB TCCR3B | 1174 | # define TCCRxB TCCR3B |
| 1167 | # define COMxx1 COM1A1 | 1175 | # define COMxx1 COM1A1 |
| @@ -1175,28 +1183,115 @@ static const uint8_t backlight_pin = BACKLIGHT_PIN; | |||
| 1175 | # define ICRx ICR1 | 1183 | # define ICRx ICR1 |
| 1176 | # define TIMSK1 TIMSK | 1184 | # define TIMSK1 TIMSK |
| 1177 | #else | 1185 | #else |
| 1178 | # define NO_HARDWARE_PWM | 1186 | # if !defined(BACKLIGHT_CUSTOM_DRIVER) |
| 1187 | # if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO) | ||
| 1188 | // timer 1 is not used by audio , backlight can use it | ||
| 1189 | #pragma message "Using hardware timer 1 with software PWM" | ||
| 1190 | # define HARDWARE_PWM | ||
| 1191 | # define BACKLIGHT_PWM_TIMER | ||
| 1192 | # define TCCRxA TCCR1A | ||
| 1193 | # define TCCRxB TCCR1B | ||
| 1194 | # define OCRxx OCR1A | ||
| 1195 | # define OCRxAH OCR1AH | ||
| 1196 | # define OCRxAL OCR1AL | ||
| 1197 | # define TIMERx_COMPA_vect TIMER1_COMPA_vect | ||
| 1198 | # define TIMERx_OVF_vect TIMER1_OVF_vect | ||
| 1199 | # define OCIExA OCIE1A | ||
| 1200 | # define TOIEx TOIE1 | ||
| 1201 | # define ICRx ICR1 | ||
| 1202 | # ifndef TIMSK | ||
| 1203 | # define TIMSK TIMSK1 | ||
| 1204 | # endif | ||
| 1205 | # elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO) | ||
| 1206 | #pragma message "Using hardware timer 3 with software PWM" | ||
| 1207 | // timer 3 is not used by audio, backlight can use it | ||
| 1208 | # define HARDWARE_PWM | ||
| 1209 | # define BACKLIGHT_PWM_TIMER | ||
| 1210 | # define TCCRxA TCCR3A | ||
| 1211 | # define TCCRxB TCCR3B | ||
| 1212 | # define OCRxx OCR3A | ||
| 1213 | # define OCRxAH OCR3AH | ||
| 1214 | # define OCRxAL OCR3AL | ||
| 1215 | # define TIMERx_COMPA_vect TIMER3_COMPA_vect | ||
| 1216 | # define TIMERx_OVF_vect TIMER3_OVF_vect | ||
| 1217 | # define OCIExA OCIE3A | ||
| 1218 | # define TOIEx TOIE3 | ||
| 1219 | # define ICRx ICR1 | ||
| 1220 | # ifndef TIMSK | ||
| 1221 | # define TIMSK TIMSK3 | ||
| 1222 | # endif | ||
| 1223 | # else | ||
| 1224 | #pragma message "Audio in use - using pure software PWM" | ||
| 1225 | #define NO_HARDWARE_PWM | ||
| 1226 | # endif | ||
| 1227 | # else | ||
| 1228 | #pragma message "Custom driver defined - using pure software PWM" | ||
| 1229 | #define NO_HARDWARE_PWM | ||
| 1230 | # endif | ||
| 1179 | #endif | 1231 | #endif |
| 1180 | 1232 | ||
| 1181 | #ifndef BACKLIGHT_ON_STATE | 1233 | #ifndef BACKLIGHT_ON_STATE |
| 1182 | #define BACKLIGHT_ON_STATE 0 | 1234 | #define BACKLIGHT_ON_STATE 0 |
| 1183 | #endif | 1235 | #endif |
| 1184 | 1236 | ||
| 1185 | #ifdef NO_HARDWARE_PWM // pwm through software | 1237 | void backlight_on(uint8_t backlight_pin) { |
| 1238 | #if BACKLIGHT_ON_STATE == 0 | ||
| 1239 | writePinLow(backlight_pin); | ||
| 1240 | #else | ||
| 1241 | writePinHigh(backlight_pin); | ||
| 1242 | #endif | ||
| 1243 | } | ||
| 1186 | 1244 | ||
| 1187 | __attribute__ ((weak)) | 1245 | void backlight_off(uint8_t backlight_pin) { |
| 1246 | #if BACKLIGHT_ON_STATE == 0 | ||
| 1247 | writePinHigh(backlight_pin); | ||
| 1248 | #else | ||
| 1249 | writePinLow(backlight_pin); | ||
| 1250 | #endif | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | |||
| 1254 | #if defined(NO_HARDWARE_PWM) || defined(BACKLIGHT_PWM_TIMER) // pwm through software | ||
| 1255 | |||
| 1256 | // we support multiple backlight pins | ||
| 1257 | #ifndef BACKLIGHT_LED_COUNT | ||
| 1258 | #define BACKLIGHT_LED_COUNT 1 | ||
| 1259 | #endif | ||
| 1260 | |||
| 1261 | #if BACKLIGHT_LED_COUNT == 1 | ||
| 1262 | #define BACKLIGHT_PIN_INIT { BACKLIGHT_PIN } | ||
| 1263 | #else | ||
| 1264 | #define BACKLIGHT_PIN_INIT BACKLIGHT_PINS | ||
| 1265 | #endif | ||
| 1266 | |||
| 1267 | #define FOR_EACH_LED(x) \ | ||
| 1268 | for (uint8_t i = 0; i < BACKLIGHT_LED_COUNT; i++) \ | ||
| 1269 | { \ | ||
| 1270 | uint8_t backlight_pin = backlight_pins[i]; \ | ||
| 1271 | { \ | ||
| 1272 | x \ | ||
| 1273 | } \ | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | static const uint8_t backlight_pins[BACKLIGHT_LED_COUNT] = BACKLIGHT_PIN_INIT; | ||
| 1277 | |||
| 1278 | #else // full hardware PWM | ||
| 1279 | |||
| 1280 | // we support only one backlight pin | ||
| 1281 | static const uint8_t backlight_pin = BACKLIGHT_PIN; | ||
| 1282 | #define FOR_EACH_LED(x) x | ||
| 1283 | |||
| 1284 | #endif | ||
| 1285 | |||
| 1286 | #ifdef NO_HARDWARE_PWM | ||
| 1287 | __attribute__((weak)) | ||
| 1188 | void backlight_init_ports(void) | 1288 | void backlight_init_ports(void) |
| 1189 | { | 1289 | { |
| 1190 | // Setup backlight pin as output and output to on state. | 1290 | // Setup backlight pin as output and output to on state. |
| 1191 | // DDRx |= n | 1291 | FOR_EACH_LED( |
| 1192 | _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); | 1292 | setPinOutput(backlight_pin); |
| 1193 | #if BACKLIGHT_ON_STATE == 0 | 1293 | backlight_on(backlight_pin); |
| 1194 | // PORTx &= ~n | 1294 | ) |
| 1195 | _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | ||
| 1196 | #else | ||
| 1197 | // PORTx |= n | ||
| 1198 | _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); | ||
| 1199 | #endif | ||
| 1200 | } | 1295 | } |
| 1201 | 1296 | ||
| 1202 | __attribute__ ((weak)) | 1297 | __attribute__ ((weak)) |
| @@ -1207,21 +1302,14 @@ uint8_t backlight_tick = 0; | |||
| 1207 | #ifndef BACKLIGHT_CUSTOM_DRIVER | 1302 | #ifndef BACKLIGHT_CUSTOM_DRIVER |
| 1208 | void backlight_task(void) { | 1303 | void backlight_task(void) { |
| 1209 | if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) { | 1304 | if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) { |
| 1210 | #if BACKLIGHT_ON_STATE == 0 | 1305 | FOR_EACH_LED( |
| 1211 | // PORTx &= ~n | 1306 | backlight_on(backlight_pin); |
| 1212 | _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | 1307 | ) |
| 1213 | #else | 1308 | } |
| 1214 | // PORTx |= n | 1309 | else { |
| 1215 | _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); | 1310 | FOR_EACH_LED( |
| 1216 | #endif | 1311 | backlight_off(backlight_pin); |
| 1217 | } else { | 1312 | ) |
| 1218 | #if BACKLIGHT_ON_STATE == 0 | ||
| 1219 | // PORTx |= n | ||
| 1220 | _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); | ||
| 1221 | #else | ||
| 1222 | // PORTx &= ~n | ||
| 1223 | _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | ||
| 1224 | #endif | ||
| 1225 | } | 1313 | } |
| 1226 | backlight_tick = (backlight_tick + 1) % 16; | 1314 | backlight_tick = (backlight_tick + 1) % 16; |
| 1227 | } | 1315 | } |
| @@ -1233,7 +1321,52 @@ void backlight_task(void) { | |||
| 1233 | #endif | 1321 | #endif |
| 1234 | #endif | 1322 | #endif |
| 1235 | 1323 | ||
| 1236 | #else // pwm through timer | 1324 | #else // hardware pwm through timer |
| 1325 | |||
| 1326 | #ifdef BACKLIGHT_PWM_TIMER | ||
| 1327 | |||
| 1328 | // The idea of software PWM assisted by hardware timers is the following | ||
| 1329 | // we use the hardware timer in fast PWM mode like for hardware PWM, but | ||
| 1330 | // instead of letting the Output Match Comparator control the led pin | ||
| 1331 | // (which is not possible since the backlight is not wired to PWM pins on the | ||
| 1332 | // CPU), we do the LED on/off by oursleves. | ||
| 1333 | // The timer is setup to count up to 0xFFFF, and we set the Output Compare | ||
| 1334 | // register to the current 16bits backlight level (after CIE correction). | ||
| 1335 | // This means the CPU will trigger a compare match interrupt when the counter | ||
| 1336 | // reaches the backlight level, where we turn off the LEDs, | ||
| 1337 | // but also an overflow interrupt when the counter rolls back to 0, | ||
| 1338 | // in which we're going to turn on the LEDs. | ||
| 1339 | // The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz. | ||
| 1340 | |||
| 1341 | // Triggered when the counter reaches the OCRx value | ||
| 1342 | ISR(TIMERx_COMPA_vect) { | ||
| 1343 | FOR_EACH_LED( | ||
| 1344 | backlight_off(backlight_pin); | ||
| 1345 | ) | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | // Triggered when the counter reaches the TOP value | ||
| 1349 | // this one triggers at F_CPU/65536 =~ 244 Hz | ||
| 1350 | ISR(TIMERx_OVF_vect) { | ||
| 1351 | #ifdef BACKLIGHT_BREATHING | ||
| 1352 | breathing_task(); | ||
| 1353 | #endif | ||
| 1354 | // for very small values of OCRxx (or backlight level) | ||
| 1355 | // we can't guarantee this whole code won't execute | ||
| 1356 | // at the same time as the compare match interrupt | ||
| 1357 | // which means that we might turn on the leds while | ||
| 1358 | // trying to turn them off, leading to flickering | ||
| 1359 | // artifacts (especially while breathing, because breathing_task | ||
| 1360 | // takes many computation cycles). | ||
| 1361 | // so better not turn them on while the counter TOP is very low. | ||
| 1362 | if (OCRxx > 256) { | ||
| 1363 | FOR_EACH_LED( | ||
| 1364 | backlight_on(backlight_pin); | ||
| 1365 | ) | ||
| 1366 | } | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | #endif | ||
| 1237 | 1370 | ||
| 1238 | #define TIMER_TOP 0xFFFFU | 1371 | #define TIMER_TOP 0xFFFFU |
| 1239 | 1372 | ||
| @@ -1265,11 +1398,28 @@ void backlight_set(uint8_t level) { | |||
| 1265 | level = BACKLIGHT_LEVELS; | 1398 | level = BACKLIGHT_LEVELS; |
| 1266 | 1399 | ||
| 1267 | if (level == 0) { | 1400 | if (level == 0) { |
| 1401 | #ifdef BACKLIGHT_PWM_TIMER | ||
| 1402 | if (OCRxx) { | ||
| 1403 | TIMSK &= ~(_BV(OCIExA)); | ||
| 1404 | TIMSK &= ~(_BV(TOIEx)); | ||
| 1405 | FOR_EACH_LED( | ||
| 1406 | backlight_off(backlight_pin); | ||
| 1407 | ) | ||
| 1408 | } | ||
| 1409 | #else | ||
| 1268 | // Turn off PWM control on backlight pin | 1410 | // Turn off PWM control on backlight pin |
| 1269 | TCCRxA &= ~(_BV(COMxx1)); | 1411 | TCCRxA &= ~(_BV(COMxx1)); |
| 1412 | #endif | ||
| 1270 | } else { | 1413 | } else { |
| 1414 | #ifdef BACKLIGHT_PWM_TIMER | ||
| 1415 | if (!OCRxx) { | ||
| 1416 | TIMSK |= _BV(OCIExA); | ||
| 1417 | TIMSK |= _BV(TOIEx); | ||
| 1418 | } | ||
| 1419 | #else | ||
| 1271 | // Turn on PWM control of backlight pin | 1420 | // Turn on PWM control of backlight pin |
| 1272 | TCCRxA |= _BV(COMxx1); | 1421 | TCCRxA |= _BV(COMxx1); |
| 1422 | #endif | ||
| 1273 | } | 1423 | } |
| 1274 | // Set the brightness | 1424 | // Set the brightness |
| 1275 | set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS)); | 1425 | set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS)); |
| @@ -1289,12 +1439,25 @@ static uint8_t breathing_period = BREATHING_PERIOD; | |||
| 1289 | static uint8_t breathing_halt = BREATHING_NO_HALT; | 1439 | static uint8_t breathing_halt = BREATHING_NO_HALT; |
| 1290 | static uint16_t breathing_counter = 0; | 1440 | static uint16_t breathing_counter = 0; |
| 1291 | 1441 | ||
| 1442 | #ifdef BACKLIGHT_PWM_TIMER | ||
| 1443 | static bool breathing = false; | ||
| 1444 | |||
| 1445 | bool is_breathing(void) { | ||
| 1446 | return breathing; | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | #define breathing_interrupt_enable() do { breathing = true; } while (0) | ||
| 1450 | #define breathing_interrupt_disable() do { breathing = false; } while (0) | ||
| 1451 | #else | ||
| 1452 | |||
| 1292 | bool is_breathing(void) { | 1453 | bool is_breathing(void) { |
| 1293 | return !!(TIMSK1 & _BV(TOIE1)); | 1454 | return !!(TIMSK1 & _BV(TOIE1)); |
| 1294 | } | 1455 | } |
| 1295 | 1456 | ||
| 1296 | #define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0) | 1457 | #define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0) |
| 1297 | #define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0) | 1458 | #define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0) |
| 1459 | #endif | ||
| 1460 | |||
| 1298 | #define breathing_min() do {breathing_counter = 0;} while (0) | 1461 | #define breathing_min() do {breathing_counter = 0;} while (0) |
| 1299 | #define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0) | 1462 | #define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0) |
| 1300 | 1463 | ||
| @@ -1368,10 +1531,14 @@ static inline uint16_t scale_backlight(uint16_t v) { | |||
| 1368 | return v / BACKLIGHT_LEVELS * get_backlight_level(); | 1531 | return v / BACKLIGHT_LEVELS * get_backlight_level(); |
| 1369 | } | 1532 | } |
| 1370 | 1533 | ||
| 1534 | #ifdef BACKLIGHT_PWM_TIMER | ||
| 1535 | void breathing_task(void) | ||
| 1536 | #else | ||
| 1371 | /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run | 1537 | /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run |
| 1372 | * about 244 times per second. | 1538 | * about 244 times per second. |
| 1373 | */ | 1539 | */ |
| 1374 | ISR(TIMER1_OVF_vect) | 1540 | ISR(TIMER1_OVF_vect) |
| 1541 | #endif | ||
| 1375 | { | 1542 | { |
| 1376 | uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS; | 1543 | uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS; |
| 1377 | // resetting after one period to prevent ugly reset at overflow. | 1544 | // resetting after one period to prevent ugly reset at overflow. |
| @@ -1393,19 +1560,21 @@ __attribute__ ((weak)) | |||
| 1393 | void backlight_init_ports(void) | 1560 | void backlight_init_ports(void) |
| 1394 | { | 1561 | { |
| 1395 | // Setup backlight pin as output and output to on state. | 1562 | // Setup backlight pin as output and output to on state. |
| 1396 | // DDRx |= n | 1563 | FOR_EACH_LED( |
| 1397 | _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); | 1564 | setPinOutput(backlight_pin); |
| 1398 | #if BACKLIGHT_ON_STATE == 0 | 1565 | backlight_on(backlight_pin); |
| 1399 | // PORTx &= ~n | 1566 | ) |
| 1400 | _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | 1567 | |
| 1401 | #else | ||
| 1402 | // PORTx |= n | ||
| 1403 | _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); | ||
| 1404 | #endif | ||
| 1405 | // I could write a wall of text here to explain... but TL;DW | 1568 | // I could write a wall of text here to explain... but TL;DW |
| 1406 | // Go read the ATmega32u4 datasheet. | 1569 | // Go read the ATmega32u4 datasheet. |
| 1407 | // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on | 1570 | // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on |
| 1408 | 1571 | ||
| 1572 | #ifdef BACKLIGHT_PWM_TIMER | ||
| 1573 | // TimerX setup, Fast PWM mode count to TOP set in ICRx | ||
| 1574 | TCCRxA = _BV(WGM11); // = 0b00000010; | ||
| 1575 | // clock select clk/1 | ||
| 1576 | TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; | ||
| 1577 | #else // hardware PWM | ||
| 1409 | // Pin PB7 = OCR1C (Timer 1, Channel C) | 1578 | // Pin PB7 = OCR1C (Timer 1, Channel C) |
| 1410 | // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0 | 1579 | // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0 |
| 1411 | // (i.e. start high, go low when counter matches.) | 1580 | // (i.e. start high, go low when counter matches.) |
| @@ -1417,8 +1586,9 @@ void backlight_init_ports(void) | |||
| 1417 | "In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]." | 1586 | "In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]." |
| 1418 | "In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)." | 1587 | "In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)." |
| 1419 | */ | 1588 | */ |
| 1420 | TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010; | 1589 | TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010; |
| 1421 | TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; | 1590 | TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; |
| 1591 | #endif | ||
| 1422 | // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0. | 1592 | // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0. |
| 1423 | ICRx = TIMER_TOP; | 1593 | ICRx = TIMER_TOP; |
| 1424 | 1594 | ||
| @@ -1428,9 +1598,9 @@ void backlight_init_ports(void) | |||
| 1428 | #endif | 1598 | #endif |
| 1429 | } | 1599 | } |
| 1430 | 1600 | ||
| 1431 | #endif // NO_HARDWARE_PWM | 1601 | #endif // hardware backlight |
| 1432 | 1602 | ||
| 1433 | #else // backlight | 1603 | #else // no backlight |
| 1434 | 1604 | ||
| 1435 | __attribute__ ((weak)) | 1605 | __attribute__ ((weak)) |
| 1436 | void backlight_init_ports(void) {} | 1606 | void backlight_init_ports(void) {} |
diff --git a/quantum/quantum.h b/quantum/quantum.h index 987516ded..17cb90274 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h | |||
| @@ -260,8 +260,12 @@ void tap_code16(uint16_t code); | |||
| 260 | #ifdef BACKLIGHT_ENABLE | 260 | #ifdef BACKLIGHT_ENABLE |
| 261 | void backlight_init_ports(void); | 261 | void backlight_init_ports(void); |
| 262 | void backlight_task(void); | 262 | void backlight_task(void); |
| 263 | void backlight_task_internal(void); | ||
| 264 | void backlight_on(uint8_t backlight_pin); | ||
| 265 | void backlight_off(uint8_t backlight_pin); | ||
| 263 | 266 | ||
| 264 | #ifdef BACKLIGHT_BREATHING | 267 | #ifdef BACKLIGHT_BREATHING |
| 268 | void breathing_task(void); | ||
| 265 | void breathing_enable(void); | 269 | void breathing_enable(void); |
| 266 | void breathing_pulse(void); | 270 | void breathing_pulse(void); |
| 267 | void breathing_disable(void); | 271 | void breathing_disable(void); |
