indicator_leds.c (3483B)
1 /* 2 Copyright 2019 MechMerlin <mechmerlin@gmail.com> 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 #include <avr/interrupt.h> 18 #include <avr/io.h> 19 #include <stdbool.h> 20 #include <util/delay.h> 21 #include "indicator_leds.h" 22 23 #define LED_T1H 900 24 #define LED_T1L 600 25 #define LED_T0H 400 26 #define LED_T0L 900 27 28 void send_bit_d4(bool bitVal) { 29 if(bitVal) { 30 asm volatile ( 31 "sbi %[port], %[bit] \n\t" 32 ".rept %[onCycles] \n\t" 33 "nop \n\t" 34 ".endr \n\t" 35 "cbi %[port], %[bit] \n\t" 36 ".rept %[offCycles] \n\t" 37 "nop \n\t" 38 ".endr \n\t" 39 :: 40 [port] "I" (_SFR_IO_ADDR(PORTD)), 41 [bit] "I" (4), 42 [onCycles] "I" (NS_TO_CYCLES(LED_T1H) - 2), 43 [offCycles] "I" (NS_TO_CYCLES(LED_T1L) - 2)); 44 } else { 45 asm volatile ( 46 "sbi %[port], %[bit] \n\t" 47 ".rept %[onCycles] \n\t" 48 "nop \n\t" 49 ".endr \n\t" 50 "cbi %[port], %[bit] \n\t" 51 ".rept %[offCycles] \n\t" 52 "nop \n\t" 53 ".endr \n\t" 54 :: 55 [port] "I" (_SFR_IO_ADDR(PORTD)), 56 [bit] "I" (4), 57 [onCycles] "I" (NS_TO_CYCLES(LED_T0H) - 2), 58 [offCycles] "I" (NS_TO_CYCLES(LED_T0L) - 2)); 59 } 60 } 61 62 void send_bit_d6(bool bitVal) 63 { 64 if(bitVal) { 65 asm volatile ( 66 "sbi %[port], %[bit] \n\t" 67 ".rept %[onCycles] \n\t" 68 "nop \n\t" 69 ".endr \n\t" 70 "cbi %[port], %[bit] \n\t" 71 ".rept %[offCycles] \n\t" 72 "nop \n\t" 73 ".endr \n\t" 74 :: 75 [port] "I" (_SFR_IO_ADDR(PORTD)), 76 [bit] "I" (6), 77 [onCycles] "I" (NS_TO_CYCLES(LED_T1H) - 2), 78 [offCycles] "I" (NS_TO_CYCLES(LED_T1L) - 2)); 79 } else { 80 asm volatile ( 81 "sbi %[port], %[bit] \n\t" 82 ".rept %[onCycles] \n\t" 83 "nop \n\t" 84 ".endr \n\t" 85 "cbi %[port], %[bit] \n\t" 86 ".rept %[offCycles] \n\t" 87 "nop \n\t" 88 ".endr \n\t" 89 :: 90 [port] "I" (_SFR_IO_ADDR(PORTD)), 91 [bit] "I" (6), 92 [onCycles] "I" (NS_TO_CYCLES(LED_T0H) - 2), 93 [offCycles] "I" (NS_TO_CYCLES(LED_T0L) - 2)); 94 } 95 } 96 97 void send_value(uint8_t byte, enum Device device) { 98 for(uint8_t b = 0; b < 8; b++) { 99 if(device == Device_STATUSLED) { 100 send_bit_d4(byte & 0b10000000); 101 } 102 if(device == Device_PCBRGB) { 103 send_bit_d6(byte & 0b10000000); 104 } 105 byte <<= 1; 106 } 107 } 108 109 void send_color(uint8_t r, uint8_t g, uint8_t b, enum Device device) { 110 send_value(r, device); 111 send_value(g, device); 112 send_value(b, device); 113 } 114 115 // Port from backlight_set_state 116 void indicator_leds_set(bool leds[8]) { 117 cli(); 118 send_color(leds[1] ? 255 : 0, leds[2] ? 255 : 0, leds[0] ? 255 : 0, Device_STATUSLED); 119 send_color(leds[4] ? 255 : 0, leds[3] ? 255 : 0, leds[5] ? 255 : 0, Device_STATUSLED); 120 leds[6] ? (PORTD &= ~0b10000000) : (PORTD |= 0b10000000); 121 sei(); 122 show(); 123 }