├── LICENSE ├── README.md ├── documentation ├── TinyRemoteXL_current.png ├── TinyRemoteXL_pic1.jpg ├── TinyRemoteXL_pic2.jpg └── TinyRemoteXL_wiring.png ├── hardware ├── TinyRemoteXL_BOM.tsv ├── TinyRemoteXL_gerber.zip └── TinyRemoteXL_schematic.pdf └── software ├── TinyRemoteXL.ino ├── makefile └── tinyremotexl.hex /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. 2 | To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send 3 | a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TinyRemoteXL - 12-Button IR Remote Control based on ATtiny13A 2 | TinyRemoteXL is a 12-button IR remote control based on an ATtiny13A powered by a CR2032 or LIR2032 coin cell battery. 3 | 4 | - Design Files (EasyEDA): https://easyeda.com/wagiminator/attiny13-tinyremoteir-xl 5 | 6 | ![pic1.jpg](https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/main/documentation/TinyRemoteXL_pic1.jpg) 7 | ![pic2.jpg](https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/main/documentation/TinyRemoteXL_pic2.jpg) 8 | 9 | # Hardware 10 | The basic hardware is similar to the 5-button [TinyRemote](https://github.com/wagiminator/ATtiny13-TinyRemote). The main difference is that the ATtiny13 has to query 12 buttons here. There are various options for using a larger number of buttons with just a few pins. However, most of them do not meet the following conditions: 11 | 12 | - there are only four pins available for twelve buttons, 13 | - a keystroke must trigger an asynchronous interrupt to wake the ATtiny from deep sleep mode, 14 | - the circuit must not consume any electricity as long as no button is pressed. 15 | 16 | A combination of voltage dividers and a couple of diodes does the trick: 17 | 18 | ![wiring.png](https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/main/documentation/TinyRemoteXL_wiring.png) 19 | 20 | If, for example, button 4 is pressed, pin PB0 is pulled to ground via the corresponding diode and a pin change interrupt is triggered, which wakes up the ATtiny. The diodes prevent the 4k7 resistors of the voltage divider from shorting out. The voltage that can be measured at PB2 via the ADC results from the supply voltage divided by the 10k resistor on the upper side and two 4k7 resistors (= 9k4) on the lower side. This value depends on the key pressed. 21 | 22 | # Software 23 | ## IR Protocol Implementation 24 | The implementation for the NEC, SAMSUNG, SONY and RC-5 protocol is taken from [TinyRemote](https://github.com/wagiminator/ATtiny13-TinyRemote). Refer to this project for a complete explanation. 25 | 26 | ## Setting the IR Codes 27 | Before compiling you have to define the IR commands for each button. Different protocols and device addresses can be used. Several codes can also be assigned to a single key, separated by semicolons. 28 | 29 | ```c 30 | #define KEY1 NEC_sendCode(0x04,0x08) // LG TV Power: addr 0x04, cmd 0x08 31 | #define KEY2 RC5_sendCode(0x00,0x0B) // Philips TV Power: addr 0x00, cmd 0x0B 32 | #define KEY3 SON_sendCode(0x01,0x15,12) // Sony TV Power: addr 0x01, cmd 0x15, 12-bit version 33 | #define KEY4 SAM_sendCode(0x07,0x02) // Samsung TV Power: addr: 07, cmd: 02 34 | #define KEY5 NEC_sendCode(0xAB04,0x08);SON_sendCode(0xE401,0x15,20) 35 | [...] 36 | ``` 37 | 38 | ## Button Detection 39 | If a key has been pressed, a pin change interrupt is triggered and the ATtiny is brought out of sleep mode. The pressed key is then identified via the voltage divider between the individual keys using the ADC of the ATtiny. 40 | 41 | ```c 42 | // Pin assignments 43 | #define BINT1_PIN PB0 // interrupt pin for buttons 1..6 44 | #define BINT2_PIN PB3 // interrupt pin for buttons 7..12 45 | #define BADC1_AP 1 // ADC port for buttons 1..6 46 | #define BADC2_AP 2 // ADC port for buttons 7..12 47 | 48 | // Button ADC thresholds 49 | const uint8_t THRESHOLDS[] PROGMEM = {217, 173, 158, 136, 103, 41, 0}; 50 | 51 | // ADC read button row and return button number 52 | uint8_t readButtonRow(uint8_t port) { 53 | PRR = 0; // power on ADC 54 | ADMUX = (1< Board -> MicroCore** and select **ATtiny13**. 132 | - Go to **Tools** and choose the following board options: 133 | - **Clock:** 1.2 MHz internal osc. 134 | - **BOD:** BOD disabled 135 | - **Timing:** Micros disabled 136 | - Connect your programmer to your PC and to the ATtiny. 137 | - Go to **Tools -> Programmer** and select your ISP programmer (e.g. [USBasp](https://aliexpress.com/wholesale?SearchText=usbasp)). 138 | - Go to **Tools -> Burn Bootloader** to burn the fuses. 139 | - Open the TinyRemoteXL sketch and click **Upload**. 140 | 141 | ### If using the precompiled hex-file 142 | - Make sure you have installed [avrdude](https://learn.adafruit.com/usbtinyisp/avrdude). 143 | - Connect your programmer to your PC and to the ATtiny. 144 | - Open a terminal. 145 | - Navigate to the folder with the hex-file. 146 | - Execute the following command (if necessary replace "usbasp" with the programmer you use): 147 | ``` 148 | avrdude -c usbasp -p t13 -U lfuse:w:0x2a:m -U hfuse:w:0xff:m -U flash:w:tinyremotexl.hex 149 | ``` 150 | 151 | ### If using the makefile (Linux/Mac) 152 | - Make sure you have installed [avr-gcc toolchain and avrdude](http://maxembedded.com/2015/06/setting-up-avr-gcc-toolchain-on-linux-and-mac-os-x/). 153 | - Connect your programmer to your PC and to the ATtiny. 154 | - Open a terminal. 155 | - Navigate to the folder with the makefile and sketch. 156 | - Run `PROGRMR=usbasp make install` to compile, burn the fuses and upload the firmware (change PROGRMR accordingly). 157 | 158 | # References, Links and Notes 159 | 1. [TinyRemote](https://github.com/wagiminator/ATtiny13-TinyRemote) 160 | 2. [TinyRemote RF](https://github.com/wagiminator/ATtiny13-TinyRemoteRF) 161 | 3. [IR remote control explanations by San Bergmans](https://www.sbprojects.net/knowledge/ir/index.php) 162 | 4. [IR remote control by Christoph Niessen (german)](http://chris.cnie.de/avr/tcm231421.html) 163 | 5. [IR remote control detective by David Johnson-Davies](http://www.technoblogy.com/show?24A9) 164 | 6. [Infrared communication concepts (altium.com)](https://techdocs.altium.com/display/FPGA/Infrared+Communication+Concepts) 165 | 7. [NEC decoder based on ATtiny13A](https://github.com/wagiminator/ATtiny13-TinyDecoder) 166 | 8. [OSC Calibrator](https://github.com/wagiminator/ATtiny84-TinyCalibrator) 167 | 9. [ATtiny13A datasheet](http://ww1.microchip.com/downloads/en/DeviceDoc/doc8126.pdf) 168 | 169 | # License 170 | ![license.png](https://i.creativecommons.org/l/by-sa/3.0/88x31.png) 171 | 172 | This work is licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License. 173 | (http://creativecommons.org/licenses/by-sa/3.0/) 174 | -------------------------------------------------------------------------------- /documentation/TinyRemoteXL_current.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/2f2b75bb2fb1de5cc67e1a943933c5a036ffe88a/documentation/TinyRemoteXL_current.png -------------------------------------------------------------------------------- /documentation/TinyRemoteXL_pic1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/2f2b75bb2fb1de5cc67e1a943933c5a036ffe88a/documentation/TinyRemoteXL_pic1.jpg -------------------------------------------------------------------------------- /documentation/TinyRemoteXL_pic2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/2f2b75bb2fb1de5cc67e1a943933c5a036ffe88a/documentation/TinyRemoteXL_pic2.jpg -------------------------------------------------------------------------------- /documentation/TinyRemoteXL_wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/2f2b75bb2fb1de5cc67e1a943933c5a036ffe88a/documentation/TinyRemoteXL_wiring.png -------------------------------------------------------------------------------- /hardware/TinyRemoteXL_BOM.tsv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/2f2b75bb2fb1de5cc67e1a943933c5a036ffe88a/hardware/TinyRemoteXL_BOM.tsv -------------------------------------------------------------------------------- /hardware/TinyRemoteXL_gerber.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/2f2b75bb2fb1de5cc67e1a943933c5a036ffe88a/hardware/TinyRemoteXL_gerber.zip -------------------------------------------------------------------------------- /hardware/TinyRemoteXL_schematic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteXL/2f2b75bb2fb1de5cc67e1a943933c5a036ffe88a/hardware/TinyRemoteXL_schematic.pdf -------------------------------------------------------------------------------- /software/TinyRemoteXL.ino: -------------------------------------------------------------------------------- 1 | // =================================================================================== 2 | // Project: TinyRemoteXL - IR Remote Control based on ATtiny13A 3 | // Version: v1.0 4 | // Year: 2021 5 | // Author: Stefan Wagner 6 | // Github: https://github.com/wagiminator 7 | // EasyEDA: https://easyeda.com/wagiminator 8 | // License: http://creativecommons.org/licenses/by-sa/3.0/ 9 | // =================================================================================== 10 | // 11 | // Description: 12 | // ------------ 13 | // IR remote control using an ATtiny 13A. Timer0 generates a carrier 14 | // frequency with a duty cycle of 25% on the output pin to the 15 | // IR LED. The signal is modulated by toggling the pin to input/output. 16 | // 17 | // The code utilizes the sleep mode power down function. The device will 18 | // work several months on a CR2032 battery. 19 | // 20 | // Wiring: 21 | // ------- 22 | // +-\/-+ 23 | // --- RST ADC0 PB5 1|° |8 Vcc 24 | // BINT2 ------- ADC3 PB3 2| |7 PB2 ADC1 -------- BADC1 25 | // BADC2 ------- ADC2 PB4 3| |6 PB1 AIN1 OC0B --- IR LED 26 | // GND 4| |5 PB0 AIN0 OC0A --- BINT1 27 | // +----+ 28 | // 29 | // Compilation Settings: 30 | // --------------------- 31 | // Controller: ATtiny13A 32 | // Core: MicroCore (https://github.com/MCUdude/MicroCore) 33 | // Clockspeed: 1.2 MHz internal 34 | // BOD: BOD disabled 35 | // Timing: Micros disabled 36 | // 37 | // Leave the rest on default settings. Don't forget to "Burn bootloader"! 38 | // No Arduino core functions or libraries are used. Use the makefile if 39 | // you want to compile without Arduino IDE. 40 | // 41 | // Note: The internal oscillator may need to be calibrated for the device 42 | // to function properly. 43 | // 44 | // Fuse settings: -U lfuse:w:0x2a:m -U hfuse:w:0xff:m 45 | 46 | 47 | // =================================================================================== 48 | // Libraries and Definitions 49 | // =================================================================================== 50 | 51 | // Oscillator calibration value (uncomment and set if necessary) 52 | //#define OSCCAL_VAL 0x48 53 | 54 | // Libraries 55 | #include // for GPIO 56 | #include // for sleep mode 57 | #include // to store data in programm memory 58 | #include // for interrupts 59 | #include // for delays 60 | 61 | // Pin assignments 62 | #define IR_PIN PB1 // IR LED pin 63 | #define BINT1_PIN PB0 // interrupt pin for buttons 1..6 64 | #define BINT2_PIN PB3 // interrupt pin for buttons 7..12 65 | #define BADC1_AP 1 // ADC port for buttons 1..6 66 | #define BADC2_AP 2 // ADC port for buttons 7..12 67 | 68 | // Assign IR commands to the keys. Different protocols and device addresses 69 | // can be used. Several codes can also be assigned to a single key, separated 70 | // by semicolons. 71 | #define KEY1 NEC_sendCode(0x04,0x08) // LG TV Power: addr 0x04, cmd 0x08 72 | #define KEY2 RC5_sendCode(0x00,0x0B) // Philips TV Power: addr 0x00, cmd 0x0B 73 | #define KEY3 SON_sendCode(0x01,0x15,12) // Sony TV Power: addr 0x01, cmd 0x15, 12-bit version 74 | #define KEY4 SAM_sendCode(0x07,0x02) // Samsung TV Power: addr: 07, cmd: 02 75 | #define KEY5 NEC_sendCode(0xAB04,0x08);SON_sendCode(0xE401,0x15,20) 76 | #define KEY6 NEC_sendCode(0x04,0x01) 77 | #define KEY7 NEC_sendCode(0x04,0x02) 78 | #define KEY8 NEC_sendCode(0x04,0x03) 79 | #define KEY9 NEC_sendCode(0x04,0x04) 80 | #define KEY10 NEC_sendCode(0x04,0x05) 81 | #define KEY11 NEC_sendCode(0x04,0x06) 82 | #define KEY12 NEC_sendCode(0x04,0x07) 83 | 84 | // Macros to switch on/off IR LED 85 | #define IR_on() DDRB |= (1<|<--- Bit=0 --->|<----- Bit=1 ---->| 104 | // 105 | // IR telegram starts with a 9ms leading burst followed by a 4.5ms pause. 106 | // Afterwards 4 data bytes are transmitted, least significant bit first. 107 | // A "0" bit is a 562.5us burst followed by a 562.5us pause, a "1" bit is 108 | // a 562.5us burst followed by a 1687.5us pause. A final 562.5us burst 109 | // signifies the end of the transmission. The four data bytes are in order: 110 | // - the 8-bit address for the receiving device, 111 | // - the 8-bit logical inverse of the address, 112 | // - the 8-bit command and 113 | // - the 8-bit logical inverse of the command. 114 | // The Extended NEC protocol uses 16-bit addresses. Instead of sending an 115 | // 8-bit address and its logically inverse, first the low byte and then the 116 | // high byte of the address is transmitted. 117 | // 118 | // If the key on the remote controller is kept depressed, a repeat code 119 | // will be issued consisting of a 9ms leading burst, a 2.25ms pause and 120 | // a 562.5us burst to mark the end. The repeat code will continue to be 121 | // sent out at 108ms intervals, until the key is finally released. 122 | 123 | // Define values for 38kHz PWM frequency and 25% duty cycle 124 | #define NEC_TOP 31 // 1200kHz / 38kHz - 1 = 31 125 | #define NEC_DUTY 7 // 1200kHz / 38kHz / 4 - 1 = 7 126 | 127 | // Macros to modulate the signals according to NEC protocol with compensated timings 128 | #define NEC_startPulse() {IR_on(); _delay_us(9000); IR_off(); _delay_us(4500);} 129 | #define NEC_repeatPulse() {IR_on(); _delay_us(9000); IR_off(); _delay_us(2250);} 130 | #define NEC_normalPulse() {IR_on(); _delay_us( 562); IR_off(); _delay_us( 557);} 131 | #define NEC_bit1Pause() _delay_us(1120) // 1687.5us - 562.5us = 1125us 132 | #define NEC_repeatCode() {_delay_ms(40); NEC_repeatPulse(); NEC_normalPulse(); _delay_ms(56);} 133 | 134 | // Send a single byte via IR 135 | void NEC_sendByte(uint8_t value) { 136 | for(uint8_t i=8; i; i--, value>>=1) { // send 8 bits, LSB first 137 | NEC_normalPulse(); // 562us burst, 562us pause 138 | if(value & 1) NEC_bit1Pause(); // extend pause if bit is 1 139 | } 140 | } 141 | 142 | // Send complete telegram (start frame + address + command) via IR 143 | void NEC_sendCode(uint16_t addr, uint8_t cmd) { 144 | // Prepare carrier wave 145 | OCR0A = NEC_TOP; // set PWM frequency 146 | OCR0B = NEC_DUTY; // set duty cycle 147 | 148 | // Send telegram 149 | NEC_startPulse(); // 9ms burst + 4.5ms pause to signify start of transmission 150 | if(addr > 0xFF) { // if extended NEC protocol (16-bit address): 151 | NEC_sendByte(addr); // send address low byte 152 | NEC_sendByte(addr >> 8); // send address high byte 153 | } else { // if standard NEC protocol (8-bit address): 154 | NEC_sendByte(addr); // send address byte 155 | NEC_sendByte(~addr); // send inverse of address byte 156 | } 157 | NEC_sendByte(cmd); // send command byte 158 | NEC_sendByte(~cmd); // send inverse of command byte 159 | NEC_normalPulse(); // 562us burst to signify end of transmission 160 | while(~PINB & BT_MASK) NEC_repeatCode(); // send repeat command until button is released 161 | } 162 | 163 | // =================================================================================== 164 | // SAMSUNG Protocol Implementation 165 | // =================================================================================== 166 | // 167 | // The SAMSUNG protocol corresponds to the NEC protocol, except that the start pulse is 168 | // 4.5ms long and the address byte is sent twice. The telegram is repeated every 108ms 169 | // as long as the button is pressed. 170 | 171 | #define SAM_startPulse() {IR_on(); _delay_us(4500); IR_off(); _delay_us(4500);} 172 | #define SAM_repeatPause() _delay_ms(44) 173 | 174 | // Send complete telegram (start frame + address + command) via IR 175 | void SAM_sendCode(uint8_t addr, uint8_t cmd) { 176 | // Prepare carrier wave 177 | OCR0A = NEC_TOP; // set PWM frequency 178 | OCR0B = NEC_DUTY; // set duty cycle 179 | 180 | // Send telegram 181 | do { 182 | SAM_startPulse(); // 9ms burst + 4.5ms pause to signify start of transmission 183 | NEC_sendByte(addr); // send address byte 184 | NEC_sendByte(addr); // send address byte again 185 | NEC_sendByte(cmd); // send command byte 186 | NEC_sendByte(~cmd); // send inverse of command byte 187 | NEC_normalPulse(); // 562us burst to signify end of transmission 188 | SAM_repeatPause(); // wait for next repeat 189 | } while(~PINB & BT_MASK); // repeat sending until button is released 190 | } 191 | 192 | // =================================================================================== 193 | // RC-5 Protocol Implementation 194 | // =================================================================================== 195 | // 196 | // The RC-5 protocol uses bi-phase modulation (Manchester coding). 197 | // 198 | // +-------+ +-------+ ON 199 | // | | 200 | // 889us | 889us 889us | 889us 201 | // | | 202 | // +-------+ +-------+ OFF 203 | // 204 | // |<-- Bit "0" -->| |<-- Bit "1" -->| 205 | // 206 | // IR telegram starts with two start bits. The first bit is always "1", 207 | // the second bit is "1" in the original protocol and inverted 7th bit 208 | // of the command in the extended RC-5 protocol. The third bit toggles 209 | // after each button release. The next five bits represent the device 210 | // address, MSB first and the last six bits represent the command, MSB 211 | // first. 212 | // 213 | // As long as a key remains down the telegram will be repeated every 214 | // 114ms without changing the toggle bit. 215 | 216 | // Define values for 36kHz PWM frequency and 25% duty cycle 217 | #define RC5_TOP 32 // 1200kHz / 36kHz - 1 = 32 218 | #define RC5_DUTY 7 // 1200kHz / 36kHz / 4 - 1 = 7 219 | 220 | // Macros to modulate the signals according to RC-5 protocol with compensated timings 221 | #define RC5_bit0Pulse() {IR_on(); _delay_us(889); IR_off(); _delay_us(884);} 222 | #define RC5_bit1Pulse() {IR_off(); _delay_us(889); IR_on(); _delay_us(884);} 223 | #define RC5_repeatPause() _delay_ms(89) // 114ms - 14 * 2 * 889us 224 | 225 | // Bitmasks 226 | #define RC5_startBit 0b0010000000000000 227 | #define RC5_cmdBit7 0b0001000000000000 228 | #define RC5_toggleBit 0b0000100000000000 229 | 230 | // Toggle variable 231 | uint8_t RC5_toggle = 0; 232 | 233 | // Send complete telegram (startbits + togglebit + address + command) via IR 234 | void RC5_sendCode(uint8_t addr, uint8_t cmd) { 235 | // Prepare carrier wave 236 | OCR0A = RC5_TOP; // set PWM frequency 237 | OCR0B = RC5_DUTY; // set duty cycle 238 | 239 | // Prepare the message 240 | uint16_t message = addr << 6; // shift address to the right position 241 | message |= (cmd & 0x3f); // add the low 6 bits of the command 242 | if(~cmd & 0x40) message |= RC5_cmdBit7; // add inverse of 7th command bit 243 | message |= RC5_startBit; // add start bit 244 | if(RC5_toggle) message |= RC5_toggleBit; // add toggle bit 245 | 246 | // Send the message 247 | do { 248 | uint16_t bitmask = RC5_startBit; // set the bitmask to first bit to send 249 | for(uint8_t i=14; i; i--, bitmask>>=1) { // 14 bits, MSB first 250 | (message & bitmask) ? (RC5_bit1Pulse()) : (RC5_bit0Pulse()); // send the bit 251 | } 252 | IR_off(); // switch off IR LED 253 | RC5_repeatPause(); // wait for next repeat 254 | } while(~PINB & BT_MASK); // repeat sending until button is released 255 | RC5_toggle ^= 1; // toggle the toggle bit 256 | } 257 | 258 | // =================================================================================== 259 | // SONY SIRC Protocol Implementation 260 | // =================================================================================== 261 | // 262 | // The SONY SIRC protocol uses pulse length modulation. 263 | // 264 | // +--------------------+ +-----+ +----------+ +-- ON 265 | // | | | | | | | 266 | // | 2400us |600us|600us|600us| 1200us |600us| ... 267 | // | | | | | | | 268 | // ------+ +-----+ +-----+ +-----+ OFF 269 | // 270 | // |<------ Start Frame ----->|<- Bit=0 ->|<--- Bit=1 ---->| 271 | // 272 | // A "0" bit is a 600us burst followed by a 600us space, a "1" bit is a 273 | // 1200us burst followed by a 600us space. An IR telegram starts with a 274 | // 2400us leading burst followed by a 600us space. The command and 275 | // address bits are then transmitted, LSB first. Depending on the 276 | // protocol version, these are in detail: 277 | // - 12-bit version: 7 command bits, 5 address bits 278 | // - 15-bit version: 7 command bits, 8 address bits 279 | // - 20-bit version: 7 command bits, 5 address bits, 8 extended bits 280 | // 281 | // As long as a key remains down the message will be repeated every 45ms. 282 | 283 | // Define values for 40kHz PWM frequency and 25% duty cycle 284 | #define SON_TOP 29 // 1200kHz / 40kHz - 1 = 29 285 | #define SON_DUTY 7 // 1200kHz / 40kHz / 4 - 1 = 7 286 | 287 | // Macros to modulate the signals according to SONY protocol with compensated timings 288 | #define SON_startPulse() {IR_on(); _delay_us(2400); IR_off(); _delay_us( 595);} 289 | #define SON_bit0Pulse() {IR_on(); _delay_us( 600); IR_off(); _delay_us( 595);} 290 | #define SON_bit1Pulse() {IR_on(); _delay_us(1200); IR_off(); _delay_us( 595);} 291 | #define SON_repeatPause() _delay_ms(27) 292 | 293 | // Send "number" of bits of "value" via IR 294 | void SON_sendByte(uint8_t value, uint8_t number) { 295 | do { // send number of bits, LSB first 296 | (value & 1) ? (SON_bit1Pulse()) : (SON_bit0Pulse()); // send bit 297 | value>>=1; // next bit 298 | } while(--number); 299 | } 300 | 301 | // Send complete telegram (start frame + command + address) via IR 302 | void SON_sendCode(uint16_t addr, uint8_t cmd, uint8_t bits) { 303 | // Prepare carrier wave 304 | OCR0A = SON_TOP; // set PWM frequency 305 | OCR0B = SON_DUTY; // set duty cycle 306 | 307 | // Send telegram 308 | do { 309 | SON_startPulse(); // signify start of transmission 310 | SON_sendByte(cmd, 7); // send 7 command bits 311 | switch (bits) { 312 | case 12: SON_sendByte(addr, 5); break; // 12-bit version: send 5 address bits 313 | case 15: SON_sendByte(addr, 8); break; // 15-bit version: send 8 address bits 314 | case 20: SON_sendByte(addr, 8); SON_sendByte(addr>>8, 5); break; // 20-bit: 13 bits 315 | default: break; 316 | } 317 | SON_repeatPause(); // wait until next repeat 318 | } while(~PINB & BT_MASK); // repeat sending until button is released 319 | } 320 | 321 | // =================================================================================== 322 | // ADC Implementation for Buttons 323 | // =================================================================================== 324 | 325 | // Button ADC thresholds 326 | const uint8_t THRESHOLDS[] PROGMEM = {217, 173, 158, 136, 103, 41, 0}; 327 | 328 | // ADC read button row and return button number 329 | uint8_t readButtonRow(uint8_t port) { 330 | PRR = 0; // power on ADC 331 | ADMUX = (1< $(TARGET).asm 89 | 90 | size: 91 | @echo "------------------" 92 | @echo "FLASH: $(shell $(AVRSIZE) -d $(TARGET).elf | awk '/[0-9]/ {print $$1 + $$2}') bytes" 93 | @echo "SRAM: $(shell $(AVRSIZE) -d $(TARGET).elf | awk '/[0-9]/ {print $$2 + $$3}') bytes" 94 | @echo "------------------" 95 | 96 | removetemp: 97 | @echo "Removing temporary files ..." 98 | @$(CLEAN) 99 | 100 | removeelf: 101 | @echo "Removing $(TARGET).elf ..." 102 | @rm -f $(TARGET).elf 103 | -------------------------------------------------------------------------------- /software/tinyremotexl.hex: -------------------------------------------------------------------------------- 1 | :1000000019C026C0CAC024C023C022C021C020C03D 2 | :100010001FC01EC0FDC0FEC03EC160C18FC1B8C1BF 3 | :10002000B9C1BAC1BBC1BCC1BDC1C1C1D9AD9E8836 4 | :100030006729000011241FBECFE9CDBF20E0A0E654 5 | :10004000B0E001C01D92A136B207E1F7A7D0B1C15F 6 | :10005000D7CF15BC806287B986B1806C86B93699D6 7 | :10006000FECF95B1379881E085BD80E0E82FF0E0C4 8 | :10007000E45DFF4FE4919E1710F48F5FF7CF089572 9 | :10008000B99A80FF0BC0E7E6F1E03197F1F700C0C5 10 | :100090000000B998FEEEFA95F1F707C090EF9A9537 11 | :1000A000F1F7B998EEEEEA95F1F78695615041F7D0 12 | :1000B000089598E0B99A21EE2A95F1F7B998EFEDF5 13 | :1000C000EA95F1F780FF06C0EFE4F1E03197F1F730 14 | :1000D00000C000008695915069F708951F93CF9353 15 | :1000E000DF93EC01162F8FE186BF87E089BDB99AB7 16 | :1000F0008BE89AE00197F1F700C00000B99885E419 17 | :1001000095E00197F1F700C000008C2FCF3FD1059B 18 | :1001100021F018F0CEDF8D2F03C0CBDF8C2F809520 19 | :10012000C8DF812FC6DF812F8095C3DFB99A91EE9A 20 | :100130009A95F1F7B9988FED8A95F1F786B390E02B 21 | :100140008095909589709927892B19F18FED9EE202 22 | :100150000197F1F700C00000B99A8BE89AE0019787 23 | :10016000F1F700C00000B99882EA92E00197F1F738 24 | :1001700000C00000B99A91EE9A95F1F7B9988FED09 25 | :100180008A95F1F78FE991E40197F1F700C000003B 26 | :10019000D5CFDF91CF911F910895189589E088BB45 27 | :1001A00093E29FBD83BF93E096B990E898B996E13A 28 | :1001B00094BB91E095BD90E29BBF85BB789485B7D9 29 | :1001C000877E806185BFCDE1DFE110E285B7806287 30 | :1001D00085BF889585B78F7D85BF8BE291E00197BC 31 | :1001E000F1F700C00000B09903C081E032DF07C022 32 | :1001F000B399ECCF82E02DDF882341F38A5F90E052 33 | :10020000FC013197EC30F10508F7E65FFF4F0994E8 34 | :1002100068E0C9C016BF87E089BD8091600088236F 35 | :1002200019F04BE058E302C04BE050E38EE020E0D1 36 | :1002300030E2B90164237523672B41F0B998EAE0F5 37 | :10024000F1E03197F1F700C0B99A07C0B99AEAE036 38 | :10025000F1E03197F1F700C0B998E9E0F1E03197AA 39 | :10026000F1F736952795815021F7B9988BE498E6F8 40 | :100270000197F1F700C0000086B390E0809590955B 41 | :1002800089709927892B91F69091600081E08927E8 42 | :10029000809360009BCFC6BF87E089BDB99AEFEC21 43 | :1002A000F2E03197F1F700C00000B998FEEEFA9540 44 | :1002B000F1F767E085E1E4DE65E081E0E1DE83EA15 45 | :1002C0009FE10197F1F700C0000086B390E08095B0 46 | :1002D000909589709927892B09F778CFD6BF87E049 47 | :1002E00089BDB99AE5E4F5E03197F1F700C0000067 48 | :1002F000B99885E495E00197F1F700C0000087E028 49 | :10030000D8DE87E0D6DE82E0D4DE8DEFD2DEB99A89 50 | :1003100091EE9A95F1F7B998EFEDEA95F1F78FE83C 51 | :1003200093E30197F1F700C0000086B390E0809559 52 | :10033000909589709927892BA1F648CF68E084E0D1 53 | :100340009BEACCDEC6BF87E089BDB99AEFECF2E04C 54 | :100350003197F1F700C00000B998FEEEFA95F1F779 55 | :1003600067E085E18DDE68E081E08ADE65E084EEAD 56 | :1003700087DE83EA9FE10197F1F700C0000086B3B2 57 | :1003800090E08095909589709927892BF1F61ECF82 58 | :1003900061E009C062E007C063E005C064E003C03B 59 | :1003A00065E001C066E084E090E098DE0FCF67E092 60 | :0603B000FACFF894FFCF24 61 | :00000001FF 62 | --------------------------------------------------------------------------------