├── .gitignore ├── README.md ├── examples ├── adjustable-baud.js ├── adjustable-port.js ├── analogled.js ├── basic.js ├── button.js ├── combination.js ├── ir.js ├── led.js ├── piezo.js ├── ping.js ├── pir.js ├── rc.js ├── sensor-throttled.js ├── sensor.js └── servo.js ├── index.js ├── lib ├── board.js ├── button.js ├── ir.js ├── lcd.js ├── led.js ├── piezo.js ├── ping.js ├── pir.js ├── rc.js ├── sensor.js └── servo.js ├── package.json └── src ├── du.ino ├── duino └── duino.ino └── libs ├── IRremote ├── IRremote.cpp ├── IRremote.h ├── IRremoteInt.h ├── LICENSE.txt ├── examples │ ├── IRrecord │ │ └── IRrecord.ino │ ├── IRrecvDemo │ │ └── IRrecvDemo.ino │ ├── IRrecvDump │ │ └── IRrecvDump.ino │ ├── IRrelay │ │ └── IRrelay.ino │ ├── IRsendDemo │ │ └── IRsendDemo.ino │ ├── IRtest │ │ └── IRtest.ino │ ├── IRtest2 │ │ └── IRtest2.ino │ └── JVCPanasonicSendDemo │ │ └── JVCPanasonicSendDemo.ino ├── keywords.txt └── readme └── RCSwitch ├── RCSwitch.cpp └── RCSwitch.h /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # duino 2 | 3 | A framework for working with Arduinos in node.js 4 | 5 | ![arduino](http://i.imgur.com/eFq84.jpg) 6 | 7 | # install 8 | 9 | npm install duino 10 | 11 | # usage 12 | 13 | ````javascript 14 | var arduino = require('duino'), 15 | board = new arduino.Board(); 16 | 17 | var led = new arduino.Led({ 18 | board: board, 19 | pin: 13 20 | }); 21 | 22 | led.blink(); 23 | ```` 24 | 25 | # what ಠ_ಠ 26 | 27 | The way this works is simple (in theory, not in practice). The Arduino listens for low-level signals over a serial port, while we abstract all of the logic on the Node side. 28 | 29 | 1. Plug in your Arduino 30 | 2. Upload the C code at `./src/du.ino` to it 31 | 3. Write a simple **duino** script 32 | 4. ????? 33 | 5. Profit! 34 | 35 | # libraries 36 | 37 | ##board 38 | 39 | ````javascript 40 | var board = new arduino.Board({ 41 | device: "ACM" 42 | }); 43 | ```` 44 | The board library will attempt to autodiscover the Arduino. 45 | The `device` option can be used to set a regex filter that will help the library when scanning for matching devices. 46 | **Note**: the value of this parameter will be used as argument of the grep command 47 | 48 | If this parameter is not provided the board library will attempt to autodiscover the Arduino by quering every device containing 'usb' in its name. 49 | 50 | ````javascript 51 | var board = new arduino.Board({ 52 | debug: true 53 | }); 54 | ```` 55 | 56 | Debug mode is off by default. Turning it on will enable verbose logging in your terminal, and tell the Arduino board to echo everthing back to you. You will get something like this: 57 | 58 | ![debug](http://i.imgur.com/gBYZA.png) 59 | 60 | The **board** object is an EventEmitter. You can listen for the following events: 61 | 62 | * `data` messages from the serial port, delimited by newlines 63 | * `connected` when the serial port has connected 64 | * `ready` when all internal post-connection logic has finished and the board is ready to use 65 | 66 | ````javascript 67 | board.on('ready', function(){ 68 | // do stuff 69 | }); 70 | 71 | board.on('data', function(m){ 72 | console.log(m); 73 | } 74 | ```` 75 | 76 | ###board.serial 77 | 78 | Low-level access to the serial connection to the board 79 | 80 | ###board.write(msg) 81 | 82 | Write a message to the board, wrapped in predefined delimiters (! and .) 83 | 84 | ###board.pinMode(pin, mode) 85 | 86 | Set the mode for a pin. `mode` is either `'in'` or `'out'` 87 | 88 | ###board.digitalWrite(pin, val) 89 | 90 | Write one of the following to a pin: 91 | 92 | ####board.HIGH and board.LOW 93 | 94 | Constants for use in low-level digital writes 95 | 96 | ###board.analogWrite(pin,val) 97 | 98 | Write a value between 0-255 to a pin 99 | 100 | ##led 101 | 102 | ````javascript 103 | var led = new arduino.Led({ 104 | board: board, 105 | pin: 13 106 | }); 107 | ```` 108 | 109 | Pin will default to 13. 110 | 111 | ###led.on() 112 | 113 | Turn the LED on 114 | 115 | ###led.off() 116 | 117 | Turn the LED off 118 | 119 | ###led.blink(interval) 120 | 121 | Blink the LED at `interval` ms. Defaults to 1000 122 | 123 | ###led.fade(interval) 124 | 125 | Fade the to full brightness then back to minimal brightness in `interval` ms. Defaults to 2000 126 | 127 | ###led.bright 128 | 129 | Current brightness of the LED 130 | 131 | ##lcd 132 | 133 | This is a port of the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal) into JavaScript. Note that communicating with the LCD requires use of the synchronous `board.delay()` busy loop which will block other node.js events from being processed for several milliseconds at a time. (This could be converted to pause a board-level buffered message queue instead.) 134 | 135 | ````javascript 136 | var lcd = new d.LCD({ 137 | board: board, 138 | pins: {rs:12, rw:11, e:10, data:[5, 4, 3, 2]} 139 | }); 140 | lcd.begin(16, 2); 141 | lcd.print("Hello Internet."); 142 | ```` 143 | 144 | In `options`, the "pins" field can either be an array matching a call to any of the [LiquidCrystal constructors](http://arduino.cc/en/Reference/LiquidCrystalConstructor) or an object with "rs", "rw" (optional), "e" and a 4- or 8-long array of "data" pins. Pins will default to `[12, 11, 5, 4, 3, 2]` if not provided. 145 | 146 | ###lcd.begin(), lcd.clear(), lcd.home(), lcd.setCursor(), lcd.scrollDisplayLeft(), lcd.scrollDisplayRight() 147 | 148 | These should behave the same as their counterparts in the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal). 149 | 150 | ###lcd.display(on), lcd.cursor(on), lcd.blink(on), lcd.autoscroll(on) 151 | 152 | These are similar to the methods in the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal), however they can take an optional boolean parameter. If true or not provided, the setting is enabled. If false, the setting is disabled. For compatibility `.noDisplay()`, `.noCursor()`, `.noBlink()` and `.noAutoscroll()` methods are provided as well. 153 | 154 | ###lcd.write(val), lcd.print(val) 155 | 156 | These take a buffer, string or integer and send it to the display. The `.write` and `print` methods are equivalent, aliases to the same function. 157 | 158 | ###lcd.createChar(location, charmap) 159 | 160 | Configures a custom character for code `location` (numbers 0–7). `charmap` can be a 40-byte buffer as in [the C++ method](http://arduino.cc/en/Reference/LiquidCrystalCreateChar), or an array of 5-bit binary strings, or a 40-character string with pixels denoted by any non-space (`' '`) character. These bits determine the 5x8 pixel pattern of the custom character. 161 | 162 | ````javascript 163 | var square = new Buffer("1f1f1f1f1f1f1f1f", 'hex'); 164 | 165 | var smiley = [ 166 | '00000', 167 | '10001', 168 | '00000', 169 | '00000', 170 | '10001', 171 | '01110', 172 | '00000' 173 | ]; 174 | 175 | var random = 176 | ". .." + 177 | " . . " + 178 | ". . ." + 179 | " . . " + 180 | " .. " + 181 | ". . " + 182 | " . ." + 183 | ".. .." ; 184 | 185 | lcd.createChar(0, square); 186 | lcd.createChar(1, smiley); 187 | lcd.createChar(2, random); 188 | lcd.setCursor(5,2); 189 | lcd.print(new Buffer("\0\1\2\1\0")); // NOTE: when `.print`ing a string, 'ascii' turns \0 into a space 190 | ```` 191 | 192 | ##piezo 193 | 194 | ````javascript 195 | var led = new arduino.Piezo({ 196 | board: board, 197 | pin: 13 198 | }); 199 | ```` 200 | Pin will default to 13. 201 | 202 | ###piezo.note(note, duration) 203 | 204 | Play a pre-calculated note for a given duration (in milliseconds). 205 | 206 | `note` must be a string, one of `d`, `e`, `f`, `g`, `a`, `b`, or `c` (must be lowercase) 207 | 208 | ###piezo.tone(tone, duration) 209 | 210 | Write a square wave to the piezo element. 211 | 212 | `tone` and `duration` must be integers. See code comments for math on `tone` generation. 213 | 214 | ##button 215 | 216 | ````javascript 217 | var button = new arduino.Button({ 218 | board: board, 219 | pin: 13 220 | }); 221 | ```` 222 | Pin will default to 13. 223 | 224 | Buttons are simply EventEmitters. They will emit the events `up` and `down`. You may also access their `down` property. 225 | 226 | ````javascript 227 | button.on('down', function(){ 228 | // delete the database! 229 | console.log('BOOM'); 230 | }); 231 | 232 | setInterval(function(){ 233 | console.log(button.down); 234 | }, 1000); 235 | ```` 236 | 237 | ##ping 238 | 239 | See: 240 | 241 | ````javascript 242 | var range = new arduino.Ping({ 243 | board: board 244 | }); 245 | 246 | range.on('read', function () { 247 | console.log("Distance to target (cm)", range.centimeters); 248 | }); 249 | ```` 250 | 251 | ##servo 252 | 253 | ````javascript 254 | var servo = new arduino.Servo({ 255 | board: board 256 | }); 257 | 258 | servo.write(0); 259 | servo.write(180); 260 | ```` 261 | Pin will default to 9. (Arduino PWM default) 262 | 263 | ###servo.sweep() 264 | 265 | Increment position from 0 to 180. 266 | 267 | ###servo.write(pos) 268 | 269 | Instruct the servo to immediately go to a position from 0 to 180. 270 | 271 | ##motor 272 | 273 | ##potentiometer 274 | 275 | # protocol 276 | 277 | Each message sent to the Arduino board by the **board** class has 8 bytes. 278 | 279 | A full message looks like this: 280 | 281 | !0113001. 282 | 283 | `!` Start 284 | `01` Command (digitalWrite) 285 | `13` Pin number 286 | `001` Value (high) 287 | `.` Stop 288 | 289 | I was drunk. It works. 290 | 291 | ##command 292 | 293 | What is implemented right now: 294 | 295 | * `00` pinMode 296 | * `01` digitalWrite 297 | * `02` digitalRead 298 | * `03` analogWrite 299 | * `04` analogRead 300 | * `97` ping 301 | * `98` servo 302 | * `99` debug 303 | 304 | ##pin 305 | 306 | Pins can be sent as an integer or a string(`1`, `2`, `"3"`, `"A0"`) 307 | 308 | ##value 309 | 310 | * `board.LOW`(`0`) 311 | * `board.HIGH`(`255`) 312 | * integer/string from `0`-`255` for PWM pins 313 | 314 | # license 315 | 316 | (The MIT License) 317 | 318 | Copyright (c) 2011 Cam Pedersen 319 | 320 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 321 | 322 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 323 | 324 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 325 | 326 | -------------------------------------------------------------------------------- /examples/adjustable-baud.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'); 2 | 3 | var board = new arduino.Board({ 4 | debug: true, 5 | baudrate: 9600 6 | }).setup(); 7 | 8 | var led = new arduino.Led({ 9 | board: board, 10 | pin: 9 11 | }); 12 | 13 | board.on('ready', function(){ 14 | led.blink(); 15 | }); 16 | -------------------------------------------------------------------------------- /examples/adjustable-port.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'); 2 | 3 | var board = new arduino.Board({ 4 | debug: true, 5 | device: "ACM" 6 | }).setup(); 7 | 8 | var led = new arduino.Led({ 9 | board: board, 10 | pin: "13" 11 | }); 12 | 13 | board.on('ready', function(){ 14 | led.blink(); 15 | }); 16 | -------------------------------------------------------------------------------- /examples/analogled.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'); 2 | 3 | var board = new arduino.Board({ 4 | debug: true 5 | }).setup(); 6 | 7 | var aled = new arduino.Led({ 8 | board: board, 9 | pin: 9 10 | }); 11 | 12 | board.on('ready', function(){ 13 | aled.fade(); 14 | }); 15 | -------------------------------------------------------------------------------- /examples/basic.js: -------------------------------------------------------------------------------- 1 | 2 | var arduino = require('../'); 3 | 4 | var board = new arduino.Board().setup(); 5 | 6 | board.on('connected', function(){ 7 | board.write('HELLO WORLD'); 8 | }); 9 | 10 | board.on('message', function(data) { 11 | console.log(data); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/button.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'); 2 | 3 | var board = new arduino.Board().setup(); 4 | 5 | var button = new arduino.Button({ 6 | board: board, 7 | pin: 2 8 | }); 9 | 10 | button.on('down', function(){ 11 | console.log('DOWN'); 12 | }); 13 | 14 | button.on('up', function(){ 15 | console.log('UP'); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/combination.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'); 2 | 3 | var board = new arduino.Board().setup(); 4 | 5 | var button = new arduino.Button({ 6 | board: board, 7 | pin: 2 8 | }); 9 | 10 | var led = new arduino.Led({ 11 | board: board, 12 | pin: 13 13 | }); 14 | 15 | button.on('down', function(){ 16 | led.on(); 17 | }); 18 | 19 | button.on('up', function(){ 20 | led.off(); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/ir.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../') 2 | var arduino = require('../') 3 | board, ir; 4 | 5 | var board = new arduino.Board({ 6 | debug: true 7 | }).setup(); 8 | 9 | var ir = new arduino.IR({ 10 | board: board 11 | }); 12 | 13 | board.on('ready', function(){ 14 | setTimeout(function() { 15 | //ir.send(3, "20DF10EF", 48); 16 | ir.send(7, "802080A0", "C2CA"); 17 | }, 1000); 18 | }); 19 | -------------------------------------------------------------------------------- /examples/led.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'); 2 | 3 | var board = new arduino.Board({ 4 | debug: true 5 | }).setup(); 6 | 7 | var led = new arduino.Led({ 8 | board: board, 9 | pin: "13" 10 | }); 11 | 12 | board.on('ready', function(){ 13 | led.blink(); 14 | }); 15 | -------------------------------------------------------------------------------- /examples/piezo.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'); 2 | 3 | var board = new arduino.Board({ 4 | debug: true 5 | }).setup(); 6 | 7 | var piezo = new arduino.Piezo({ 8 | board: board 9 | }); 10 | 11 | board.on('ready', function(){ 12 | piezo.note('a', 1000); 13 | 14 | setTimeout(function(){ 15 | piezo.note('b', 1100); 16 | }, 1000); 17 | }); 18 | 19 | 20 | // Resources 21 | // http://arduino.cc/en/Tutorial/Tone4 22 | -------------------------------------------------------------------------------- /examples/ping.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'), 2 | board, ping; 3 | 4 | board = new arduino.Board({ 5 | debug: false 6 | }).setup(); 7 | 8 | ping = new arduino.Ping({ 9 | board: board, 10 | pin: 7 11 | }); 12 | 13 | // 'read' events fire approx ~50ms 14 | ping.on('read', function(err) { 15 | 16 | // Current sensor data stored in properties 17 | // of this Ping instance: 18 | // 19 | // this.microseconds - time lapse from fire to read 20 | // this.inches - calculated distance to object in inches 21 | // this.centimeters - calculated distance to object in centimeters 22 | 23 | console.log('Object is ~' + Math.round(this.inches) + ' inches from sensor'); 24 | 25 | }); 26 | 27 | // To test, use the following: 28 | // http://arduino.cc/en/uploads/Tutorial/ping_bb.png 29 | // 30 | // More information: 31 | // http://arduino.cc/en/Tutorial/Ping 32 | -------------------------------------------------------------------------------- /examples/pir.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'), 2 | board, pir; 3 | 4 | board = new arduino.Board({ 5 | debug: false 6 | }).setup(); 7 | 8 | pir = new arduino.PIR({ 9 | board: board, 10 | pin: 7 11 | }); 12 | 13 | // 'calibrated' event fired when PIR sensor is 14 | // ready to detect movement/motion in observable range 15 | // 16 | // All events receive error and date arguments 17 | pir.on('calibrated', function(err, date) { 18 | 19 | console.log('calibrated'); 20 | 21 | // Current sensor data stored in properties 22 | // of this PIR instance: 23 | // 24 | // this.state - current state of motion 25 | // 0 No motion currently detected 26 | // 1 Motion currently detected 27 | 28 | // 'motionstart' event fired when motion occurs 29 | // within the observable range of the PIR sensor 30 | this.on('motionstart', function(err, date) { 31 | 32 | console.log('motionstart', this.state); 33 | console.log( date ); 34 | 35 | }); 36 | 37 | // 'motionend' event fired when motion has ceased 38 | // within the observable range of the PIR sensor 39 | this.on('motionend', function(err, date) { 40 | 41 | console.log('motionend', this.state); 42 | 43 | }); 44 | }); 45 | 46 | 47 | // To test, use the following: 48 | // http://www.ladyada.net/images/sensors/pirardbb.gif 49 | // http://bildr.org/blog/wp-content/uploads/2011/06/PIR-Arduino_hookup.png 50 | // 51 | // More information: 52 | // http://www.ladyada.net/learn/sensors/pir.html 53 | -------------------------------------------------------------------------------- /examples/rc.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../') 2 | board, rc; 3 | 4 | var board = new arduino.Board({ 5 | debug: true 6 | }).setup(); 7 | 8 | var rc = new arduino.RC({ 9 | board: board, 10 | pin: "10" 11 | }); 12 | 13 | board.on('ready', function(){ 14 | setTimeout(function() { 15 | // alternative: rc.decimal("123456") 16 | rc.triState("0FFF0FFFFF0F"); 17 | }, 1000); 18 | setTimeout(function() { 19 | rc.triState("0FFF0FFFFF00"); 20 | }, 2000); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/sensor-throttled.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'), 2 | board, sensor, piezo; 3 | 4 | board = new arduino.Board({ 5 | debug: false 6 | }).setup(); 7 | 8 | sensor = new arduino.Sensor({ 9 | board: board, 10 | pin: 'A0', 11 | throttle: 100 12 | }); 13 | 14 | piezo = new arduino.Piezo({ 15 | board: board, 16 | pin: 11 17 | }); 18 | 19 | sensor.on('read', function(err, value) { 20 | value = +value; 21 | 22 | // |value| is the raw sensor output 23 | console.log( value ); 24 | 25 | if ( value > 0 ) { 26 | piezo.note('b', 100); 27 | } 28 | }); 29 | 30 | // Tested with: 31 | // SoftPot 32 | // http://www.spectrasymbol.com/how-it-works-softpot 33 | // http://www.sparkfun.com/datasheets/Sensors/Flex/SoftPot-Datasheet.pdf 34 | // 35 | // sensor 36 | // http://www.ladyada.net/learn/sensors/cds.html 37 | -------------------------------------------------------------------------------- /examples/sensor.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'), 2 | board, sensor; 3 | 4 | board = new arduino.Board({ 5 | debug: true 6 | }).setup(); 7 | 8 | sensor = new arduino.Sensor({ 9 | board: board, 10 | pin: 'A0' 11 | }); 12 | 13 | sensor.on('read', function(err, value) { 14 | value = +value; 15 | // |value| is the raw sensor output 16 | console.log( value ); 17 | }); 18 | 19 | // Tested with: 20 | // SoftPot 21 | // http://www.spectrasymbol.com/how-it-works-softpot 22 | // http://www.sparkfun.com/datasheets/Sensors/Flex/SoftPot-Datasheet.pdf 23 | // 24 | // sensor 25 | // http://www.ladyada.net/learn/sensors/cds.html 26 | -------------------------------------------------------------------------------- /examples/servo.js: -------------------------------------------------------------------------------- 1 | var arduino = require('../'), 2 | board, led, servo; 3 | 4 | // Construct instances 5 | board = new arduino.Board({ 6 | debug: true 7 | }).setup(); 8 | 9 | led = new arduino.Led({ 10 | board: board, 11 | pin: 13 12 | }); 13 | 14 | servo = new arduino.Servo({ 15 | board: board, 16 | pin: 9 17 | }); 18 | 19 | // Once servo is attached: 20 | // - "read" 21 | // - log position 22 | // - "aftersweep" 23 | // - blink the led 24 | // - read the position 25 | // - detach the servo 26 | // - "detached" 27 | // - log detach message 28 | // 29 | // - execute full sweep 30 | 31 | servo.on('attached', function(err) { 32 | console.log('attached'); 33 | 34 | this.on('read', function(err, pos) { 35 | console.log(pos); 36 | }); 37 | 38 | this.on('detached', function(err) { 39 | console.log('detached'); 40 | }); 41 | 42 | this.on('aftersweep', function(err) { 43 | led.blink(); 44 | 45 | this.read(); 46 | this.detach(); 47 | }); 48 | 49 | this.sweep(); 50 | }); 51 | 52 | // To test, use the following: 53 | // http://arduino.cc/en/uploads/Tutorial/sweep_BB.png 54 | // 55 | // More information: 56 | // http://www.ladyada.net/learn/sensors/pir.html 57 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | Board: require('./lib/board'), 4 | Led: require('./lib/led'), 5 | Piezo: require('./lib/piezo'), 6 | Button: require('./lib/button'), 7 | Servo: require('./lib/servo'), 8 | Sensor: require('./lib/sensor'), 9 | Ping: require('./lib/ping'), 10 | PIR: require('./lib/pir'), 11 | LCD: require('./lib/lcd'), 12 | RC: require('./lib/rc'), 13 | IR: require('./lib/ir') 14 | }; 15 | -------------------------------------------------------------------------------- /lib/board.js: -------------------------------------------------------------------------------- 1 | var events = require('events'), 2 | child = require('child_process'), 3 | util = require('util'), 4 | chalk = require('chalk'), 5 | serial = require('serialport'); 6 | 7 | /* 8 | * The main Arduino constructor 9 | * 10 | * [NEW] Does *not* open a serial connection. Add a `setup()` call to do so. 11 | * 12 | * This allows the user to add a listener for error events that occur 13 | * during the serial connection attempts. 14 | */ 15 | var Board = function (options) { 16 | this.log('info', 'initializing'); 17 | this.debug = options && options.debug || false; 18 | this.devregex = options && options.devregex || 'usb|ttyACM*|ttyS0'; 19 | this.baudrate = options && options.baudrate || 115200; 20 | this.writeBuffer = []; 21 | } 22 | 23 | /* 24 | * EventEmitter, I choose you! 25 | */ 26 | util.inherits(Board, events.EventEmitter); 27 | 28 | /* 29 | * Establish the serial connection 30 | * 31 | * Tries to open a serial connection with `connectSerial()`. 32 | * If successful, the connection is initialized ("clearing bytes", debug mode). 33 | * If unsuccessful, error event is emitted; if no listeners: error is thrown. 34 | */ 35 | Board.prototype.setup = function() { 36 | var self = this; 37 | this.connectSerial(function(found) { 38 | if (found) { 39 | self.serial = found; 40 | self.emit('connected'); 41 | 42 | self.log('info', 'binding serial events'); 43 | self.serial.on('data', function(data){ 44 | self.log('receive', chalk.red(data.toString())); 45 | self.emit('data', data); 46 | }); 47 | 48 | setTimeout(function(){ 49 | self.log('info', 'board ready'); 50 | self.sendClearingBytes(); 51 | 52 | if (self.debug) { 53 | self.log('info', 'sending debug mode toggle on to board'); 54 | self.write('99' + self.normalizePin(0) + self.normalizeVal(1)); 55 | process.on('SIGINT', function(){ 56 | self.log('info', 'sending debug mode toggle off to board'); 57 | self.write('99' + self.normalizePin(0) + self.normalizeVal(0)); 58 | delete self.serial; 59 | setTimeout(function(){ 60 | process.exit(); 61 | }, 100); 62 | }); 63 | } 64 | 65 | if (self.writeBuffer.length > 0) { 66 | self.processWriteBuffer(); 67 | } 68 | 69 | self.emit('ready'); 70 | }, 500); 71 | } else { 72 | msg = "Could not establish Serial connection to Arduino."; 73 | if (self.listeners('error').length > 0) { 74 | self.emit('error', msg); 75 | } else { 76 | throw new Error(msg); 77 | } 78 | } 79 | }); 80 | return this; 81 | } 82 | 83 | /* 84 | * (Tries to) Open serial connection with Arduino (formerly named `detect()`) 85 | * 86 | * Loops through devices matching `devregex` and naively tries to open a serial 87 | * connection with each until one succeeds. 88 | * This should really message the device and wait for a correct response to 89 | * ensure that we're actually connected to an Arduino running `duino`. FIXME 90 | * 91 | * Returns false if no serial connection could be established. 92 | */ 93 | Board.prototype.connectSerial = function (callback) { 94 | this.log('info', 'attempting to find Arduino board'); 95 | var self = this; 96 | child.exec('ls /dev | grep -E "'+ self.devregex +'"', function(err, stdout, stderr){ 97 | 98 | function skipUnwanted(e) { 99 | return (e !== '') && (e.slice(0, 2) !== 'cu'); 100 | } 101 | 102 | var devices = stdout.slice(0, -1).split('\n').filter(skipUnwanted), 103 | device, 104 | candidate; 105 | 106 | // loop over list of possible Arduinos 107 | // do not stop (even/especially on error, that's the point!) until 108 | // - we run out of options, or 109 | // - a serial connection is established 110 | var success = devices.some(function(device) { 111 | try { 112 | self.log('debug', 'attempting to open serial conn.: ' + device); 113 | candidate = new serial.SerialPort('/dev/' + device, { 114 | baudrate: self.baudrate, 115 | parser: serial.parsers.readline('\n') 116 | }); 117 | 118 | // connection succeeded, though we don't test whether it's an Arduino 119 | self.log('info', 'found board at /dev/' + device); 120 | return true; 121 | 122 | } catch (e) { 123 | // ignore error and cont. 124 | self.log('warning', 'error while establishing serial connection with' 125 | + '/dev/' + device + '; trying next'); 126 | return false; 127 | } 128 | }); 129 | 130 | if (success) { 131 | callback(candidate); 132 | } else { 133 | callback(false); 134 | } 135 | }); 136 | } 137 | 138 | /* 139 | * The board will eat the first 4 bytes of the session 140 | * So we give it crap to eat 141 | */ 142 | Board.prototype.sendClearingBytes = function () { 143 | this.serial.write('00000000'); 144 | } 145 | 146 | /* 147 | * Process the writeBuffer (messages attempted before serial was ready) 148 | */ 149 | Board.prototype.processWriteBuffer = function () { 150 | this.log('info', 'processing buffered messages'); 151 | while (this.writeBuffer.length > 0) { 152 | this.log('info', 'writing buffered message'); 153 | this.write(this.writeBuffer.shift()); 154 | } 155 | } 156 | 157 | /* 158 | * Low-level serial write 159 | */ 160 | Board.prototype.write = function (m) { 161 | if (this.serial) { 162 | this.log('write', m); 163 | this.serial.write('!' + m + '.'); 164 | } else { 165 | this.log('info', 'serial not ready, buffering message: ' + chalk.red(m)); 166 | this.writeBuffer.push(m); 167 | } 168 | } 169 | 170 | // Add a 0 to the front of a single-digit pin number 171 | Board.prototype.normalizePin = function (pin) { 172 | return this.lpad( 2, '0', pin ); 173 | } 174 | 175 | // Left-pad values with 0s so it has three digits. 176 | Board.prototype.normalizeVal = function(val) { 177 | return this.lpad( 3, '0', val ); 178 | } 179 | 180 | // Left-pad `str` with `chr` and return the last `len` digits 181 | Board.prototype.lpad = function(len, chr, str) { 182 | return (Array(len + 1).join(chr || ' ') + str).substr(-len); 183 | }; 184 | 185 | /* 186 | * Define constants 187 | */ 188 | Board.prototype.HIGH = '255'; 189 | Board.prototype.LOW = '000'; 190 | 191 | /* 192 | * Set a pin's mode 193 | * val == out = 001 194 | * val == in = 000 195 | */ 196 | Board.prototype.pinMode = function (pin, val) { 197 | pin = this.normalizePin(pin); 198 | this.log('info', 'set pin ' + pin + ' mode to ' + val); 199 | val = ( 200 | val == 'out' ? 201 | this.normalizeVal(1) : 202 | this.normalizeVal(0) 203 | ); 204 | this.write('00' + pin + val); 205 | } 206 | 207 | /* 208 | * Tell the board to write to a digital pin 209 | */ 210 | Board.prototype.digitalWrite = function (pin, val) { 211 | pin = this.normalizePin(pin); 212 | val = this.normalizeVal(val); 213 | this.log('info', 'digitalWrite to pin ' + pin + ': ' + chalk.green(val)); 214 | this.write('01' + pin + val); 215 | } 216 | 217 | /* 218 | * Tell the board to extract data from a pin 219 | */ 220 | Board.prototype.digitalRead = function (pin) { 221 | pin = this.normalizePin(pin); 222 | this.log('info', 'digitalRead from pin ' + pin); 223 | this.write('02' + pin + this.normalizeVal(0)); 224 | } 225 | 226 | Board.prototype.analogWrite = function (pin, val) { 227 | pin = this.normalizePin(pin); 228 | val = this.normalizeVal(val); 229 | this.log('info', 'analogWrite to pin ' + pin + ': ' + chalk.green(val)); 230 | this.write('03' + pin + val); 231 | } 232 | Board.prototype.analogRead = function (pin) { 233 | pin = this.normalizePin(pin); 234 | this.log('info', 'analogRead from pin ' + pin); 235 | this.write('04' + pin + this.normalizeVal(0)); 236 | } 237 | 238 | /* 239 | * Utility function to pause for a given time 240 | */ 241 | Board.prototype.delay = function (ms) { 242 | ms += Date.now(); 243 | while (Date.now() < ms) { } 244 | } 245 | 246 | /* 247 | * Logger utility function 248 | */ 249 | Board.prototype.log = function (/*level, message*/) { 250 | var args = [].slice.call(arguments); 251 | if (this.debug) { 252 | console.log(chalk.gray(Date.now()) + chalk.blue(' duino ') + chalk.magenta(args.shift()) + ' ' + args.join(', ')); 253 | } 254 | } 255 | 256 | module.exports = Board; 257 | -------------------------------------------------------------------------------- /lib/button.js: -------------------------------------------------------------------------------- 1 | var events = require('events'), 2 | util = require('util'); 3 | 4 | /* 5 | * Main Button constructor 6 | * Process options 7 | * Tell the board to set it up 8 | */ 9 | var Button = function (options) { 10 | if (!options || !options.board) throw new Error('Must supply required options to Button'); 11 | this.board = options.board; 12 | this.pin = options.pin || 13; 13 | this.down = false; 14 | this.board.pinMode(this.pin, 'in'); 15 | var self = this; 16 | setInterval(function () { 17 | self.board.digitalRead(self.pin); 18 | }, 50); 19 | this.board.on('data', function (m) { 20 | m = m.slice(0, -1).split('::'); 21 | 22 | var err = null; 23 | 24 | if (m.length > 1 && m[0] == self.pin) { 25 | // 0 is up 26 | // 1 is down 27 | if (m[1] == 0 && self.down) { 28 | self.down = false; 29 | self.emit('up', err); 30 | } 31 | if (m[1] == 1 && !self.down) { 32 | self.down = true; 33 | self.emit('down', err); 34 | } 35 | } 36 | }); 37 | } 38 | 39 | /* 40 | * EventEmitter, I choose you! 41 | */ 42 | util.inherits(Button, events.EventEmitter); 43 | 44 | module.exports = Button; 45 | -------------------------------------------------------------------------------- /lib/ir.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Main IR constructor 3 | * Process options 4 | * Tell the board to set it up 5 | */ 6 | var IR = function (options) { 7 | if (!options || !options.board) throw new Error('Must supply required options to IR'); 8 | this.board = options.board; 9 | } 10 | 11 | /* 12 | * Send IR code 13 | * types: 14 | * 1 RC5 15 | * 2 RC6 16 | * 3 NEC 17 | * 4 Sony 18 | * 5 DISH 19 | * 6 Sharp 20 | * 7 Panasonic 21 | * 8 JVC 22 | */ 23 | IR.prototype.send = function (type, val, len) { 24 | len = len + ''; 25 | for (var i = len.length; i < 4; i++) { 26 | len = '0' + len; 27 | }; 28 | var msg = '9500' + type + val + len; 29 | this.board.write(msg); 30 | } 31 | 32 | module.exports = IR; 33 | -------------------------------------------------------------------------------- /lib/lcd.js: -------------------------------------------------------------------------------- 1 | // port of LiquidCrystal.cpp by natevw 2 | 3 | 4 | // commands 5 | LCD_CLEARDISPLAY = 0x01; 6 | LCD_RETURNHOME = 0x02; 7 | LCD_ENTRYMODESET = 0x04; 8 | LCD_DISPLAYCONTROL = 0x08; 9 | LCD_CURSORSHIFT = 0x10; 10 | LCD_FUNCTIONSET = 0x20; 11 | LCD_SETCGRAMADDR = 0x40; 12 | LCD_SETDDRAMADDR = 0x80; 13 | 14 | // flags for display entry mode 15 | LCD_ENTRYRIGHT = 0x00; 16 | LCD_ENTRYLEFT = 0x02; 17 | LCD_ENTRYSHIFTINCREMENT = 0x01; 18 | LCD_ENTRYSHIFTDECREMENT = 0x00; 19 | 20 | // flags for display on/off control 21 | LCD_DISPLAYON = 0x04; 22 | LCD_DISPLAYOFF = 0x00; 23 | LCD_CURSORON = 0x02; 24 | LCD_CURSOROFF = 0x00; 25 | LCD_BLINKON = 0x01; 26 | LCD_BLINKOFF = 0x00; 27 | 28 | // flags for display/cursor shift 29 | LCD_DISPLAYMOVE = 0x08; 30 | LCD_CURSORMOVE = 0x00; 31 | LCD_MOVERIGHT = 0x04; 32 | LCD_MOVELEFT = 0x00; 33 | 34 | // flags for function set 35 | LCD_8BITMODE = 0x10; 36 | LCD_4BITMODE = 0x00; 37 | LCD_2LINE = 0x08; 38 | LCD_1LINE = 0x00; 39 | LCD_5x10DOTS = 0x04; 40 | LCD_5x8DOTS = 0x00; 41 | 42 | 43 | 44 | var LCD = function (options) { 45 | if (!options || !options.board) throw new Error('Must supply required options'); 46 | this.board = options.board; 47 | 48 | var pins = options.pins || [12, 11, 5, 4, 3, 2]; 49 | if (!Array.isArray(pins)) 50 | this.pins = pins; 51 | else if (pins.length % 2) 52 | this.pins = {rs:pins[0], rw:pins[1], e:pins[2], data:pins.slice(3)}; 53 | else 54 | this.pins = {rs:pins[0], e:pins[1], data:pins.slice(2)}; 55 | if (!('rw' in this.pins)) this.pins.rw = 255; 56 | 57 | this.board.pinMode(this.pins.rs, 'out'); 58 | if (this.pins.rw !== 255) { 59 | this.board.pinMode(this.pins.rw, 'out'); 60 | } 61 | this.board.pinMode(this.pins.e, 'out'); 62 | 63 | this.begin(16, 1); 64 | } 65 | 66 | LCD.prototype.begin = function (cols, lines, dotsize) { 67 | this._numlines = lines; 68 | 69 | var displayfunction = 0; 70 | displayfunction |= (lines > 1) ? LCD_2LINE : LCD_1LINE; 71 | displayfunction |= (dotsize && lines === 1) ? LCD_5x10DOTS : LCD_5x8DOTS; 72 | 73 | this._delayMicroseconds(50000); 74 | this.board.digitalWrite(this.pins.rs, this.board.LOW); 75 | this.board.digitalWrite(this.pins.e, this.board.LOW); 76 | if (this.pins.rw !== 255) 77 | this.board.digitalWrite(this.pins.rw, this.board.LOW); 78 | 79 | // put the LCD into 4 bit or 8 bit mode 80 | if (this.pins.data.length === 4) { 81 | displayfunction |= LCD_4BITMODE; 82 | this._writeNbits(4, 0x03); 83 | this._delayMicroseconds(4500); 84 | this._writeNbits(4, 0x03); 85 | this._delayMicroseconds(4500); 86 | this._writeNbits(4, 0x03); 87 | this._delayMicroseconds(150); 88 | this._writeNbits(4, 0x02); 89 | } else { 90 | displayfunction |= LCD_8BITMODE; 91 | this.command(LCD_FUNCTIONSET | displayfunction); 92 | this._delayMicroseconds(4500); 93 | this.command(LCD_FUNCTIONSET | displayfunction); 94 | this._delayMicroseconds(150); 95 | this.command(LCD_FUNCTIONSET | displayfunction); 96 | } 97 | 98 | this.command(LCD_FUNCTIONSET | displayfunction); 99 | 100 | this._displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 101 | this.display(); 102 | 103 | this.clear(); 104 | 105 | this._displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 106 | this.leftToRight(); 107 | } 108 | 109 | LCD.prototype.clear = function () { 110 | this.command(LCD_CLEARDISPLAY); 111 | this._delayMicroseconds(2000); // this command takes a long time! 112 | } 113 | 114 | LCD.prototype.home = function () { 115 | this.command(LCD_RETURNHOME); 116 | this._delayMicroseconds(2000); 117 | } 118 | 119 | LCD.prototype.setCursor = function (col, row) { 120 | if (row >= this._numlines) { 121 | row = this._numlines - 1; 122 | } 123 | 124 | var row_offsets = [0x00, 0x40, 0x14, 0x54]; 125 | this.command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 126 | } 127 | 128 | LCD.prototype.display = function (on) { 129 | on = (arguments.length) ? on : true; 130 | if (on) this._displaycontrol |= LCD_DISPLAYON 131 | else this._displaycontrol &= ~LCD_DISPLAYON; 132 | this.command(LCD_DISPLAYCONTROL | this._displaycontrol); 133 | } 134 | 135 | LCD.prototype.noDisplay = function () { this.display(false); } 136 | 137 | LCD.prototype.cursor = function (on) { 138 | on = (arguments.length) ? on : true; 139 | if (on) this._displaycontrol |= LCD_CURSORON 140 | else this._displaycontrol &= ~LCD_CURSORON; 141 | this.command(LCD_DISPLAYCONTROL | this._displaycontrol); 142 | } 143 | 144 | LCD.prototype.noCursor = function () { this.cursor(false); } 145 | 146 | LCD.prototype.blink = function (on) { 147 | on = (arguments.length) ? on : true; 148 | if (on) this._displaycontrol |= LCD_BLINKON 149 | else this._displaycontrol &= ~LCD_BLINKON; 150 | this.command(LCD_DISPLAYCONTROL | this._displaycontrol); 151 | } 152 | 153 | LCD.prototype.noBlink = function () { this.blink(false); } 154 | 155 | LCD.prototype.scrollDisplayLeft = function () { 156 | this.command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 157 | } 158 | 159 | LCD.prototype.scrollDisplayRight = function () { 160 | this.command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 161 | } 162 | 163 | 164 | LCD.prototype.leftToRight = function () { 165 | this._displaymode |= LCD_ENTRYLEFT; 166 | this.command(LCD_ENTRYMODESET | this._displaymode); 167 | } 168 | 169 | LCD.prototype.rightToLeft = function () { 170 | this._displaymode &= ~LCD_ENTRYLEFT; 171 | this.command(LCD_ENTRYMODESET | this._displaymode); 172 | } 173 | 174 | LCD.prototype.autoscroll = function (on) { 175 | on = (arguments.length) ? on : true; 176 | if (on) this._displaymode |= LCD_ENTRYSHIFTINCREMENT 177 | else this._displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 178 | this.command(LCD_ENTRYMODESET | this._displaymode); 179 | } 180 | 181 | LCD.prototype.noAutoscroll = function () { this.autoscroll(false); } 182 | 183 | LCD.prototype.createChar = function (location, charmap) { 184 | location &= 0x7; 185 | this.command(LCD_SETCGRAMADDR | (location << 3)); 186 | 187 | var buffer = new Buffer(8); 188 | if (Array.isArray(charmap)) for (var i = 0; i < 8; i++) { 189 | buffer[i] = parseInt(charmap[i], 2); 190 | } else if (typeof charmap === 'string') for (var i = 0; i < 8; i++) { 191 | var byte = 0; 192 | if (charmap[5*i + 0] !== ' ') byte |= 0x10; 193 | if (charmap[5*i + 1] !== ' ') byte |= 0x08; 194 | if (charmap[5*i + 2] !== ' ') byte |= 0x04; 195 | if (charmap[5*i + 3] !== ' ') byte |= 0x02; 196 | if (charmap[5*i + 4] !== ' ') byte |= 0x01; 197 | buffer[i] = byte; 198 | } else buffer = charmap; 199 | this.write(buffer); 200 | } 201 | 202 | LCD.prototype.write = LCD.prototype.print = function (str) { 203 | // TODO: map misc Unicode chars to typical LCD extended charset? 204 | var bytes = (typeof str === 'string') ? new Buffer(str, 'ascii') : 205 | (typeof str === 'object') ? str : new Buffer([str]); 206 | for (var i = 0, len = bytes.length; i < len; i++) 207 | this.send(bytes[i], this.board.HIGH); 208 | } 209 | 210 | 211 | /* 212 | * mid/low level stuff 213 | */ 214 | 215 | LCD.prototype.command = function (value) { 216 | this.send(value, this.board.LOW); 217 | } 218 | 219 | LCD.prototype.send = function (value, mode) { 220 | this.board.digitalWrite(this.pins.rs, mode); 221 | if (this.pins.rw !== 255) { 222 | this.board.digitalWrite(this.pins.rw, this.board.LOW); 223 | } 224 | if (this.pins.data.length === 8) { 225 | this._writeNbits(8, value); 226 | } else { 227 | this._writeNbits(4, value >> 4); 228 | this._writeNbits(4, value & 0xF); 229 | } 230 | } 231 | 232 | LCD.prototype._writeNbits = function (n, value) { 233 | for (var i = 0; i < n; i++) { 234 | this.board.pinMode(this.pins.data[i], 'out'); 235 | var bit = (value >> i) & 0x01; 236 | this.board.digitalWrite(this.pins.data[i], (bit) ? this.board.HIGH : this.board.LOW); 237 | } 238 | this._pulseEnable(); 239 | } 240 | 241 | LCD.prototype._pulseEnable = function () { 242 | this.board.digitalWrite(this.pins.e, this.board.LOW); 243 | this._delayMicroseconds(1); 244 | this.board.digitalWrite(this.pins.e, this.board.HIGH); 245 | this._delayMicroseconds(1); // enable pulse must be >450ns 246 | this.board.digitalWrite(this.pins.e, this.board.LOW); 247 | this._delayMicroseconds(100); // commands need > 37us to settle 248 | } 249 | 250 | LCD.prototype._delayMicroseconds = function (us) { 251 | this.board.delay(us/1000); 252 | } 253 | 254 | module.exports = LCD; -------------------------------------------------------------------------------- /lib/led.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Main LED constructor 4 | * Process options 5 | * Tell the board to set it up 6 | */ 7 | var Led = function (options) { 8 | if (!options || !options.board) throw new Error('Must supply required options to LED'); 9 | this.board = options.board; 10 | this.pin = options.pin || 13; 11 | this.bright = 0; 12 | this.board.pinMode(this.pin, 'out'); 13 | this.direction = -1; 14 | } 15 | 16 | /* 17 | * Turn the LED on 18 | */ 19 | Led.prototype.on = function () { 20 | this.board.digitalWrite(this.pin, this.board.HIGH); 21 | this.bright = 255; 22 | } 23 | 24 | /* 25 | * Turn the LED off 26 | */ 27 | Led.prototype.off = function () { 28 | this.board.digitalWrite(this.pin, this.board.LOW); 29 | this.bright = 0; 30 | } 31 | 32 | Led.prototype.brightLevel = function(val) { 33 | this.board.analogWrite(this.pin, this.bright = val); 34 | } 35 | 36 | Led.prototype.fade = function(interval) { 37 | to = (interval||5000)/(255*2); 38 | var self = this; 39 | setInterval(function() { 40 | if(!self.board.serial) return; //Interval too fast for debug messages on ^c 41 | if(self.bright==0) direction = 1; 42 | if(self.bright==255) direction = -1; 43 | self.brightLevel(self.bright+direction); 44 | },to); 45 | } 46 | 47 | 48 | /* 49 | * Start a bariable blinking pattern 50 | */ 51 | Led.prototype.blink = function (interval) { 52 | interval = interval || 1000; 53 | var self = this; 54 | setInterval(function(){ 55 | if (self.bright) { 56 | self.off() 57 | } else { 58 | self.on(); 59 | } 60 | }, interval); 61 | } 62 | 63 | module.exports = Led; 64 | -------------------------------------------------------------------------------- /lib/piezo.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Main Pieze constructor 4 | * Process options 5 | * Tell the board to set pin mode 6 | */ 7 | var Piezo = function (options) { 8 | if (!options || !options.board) throw new Error('Must supply required options to Piezo'); 9 | this.board = options.board; 10 | this.pin = options.pin || 13; 11 | this.bright = false; 12 | this.board.pinMode(this.pin, 'out'); 13 | } 14 | 15 | /* 16 | * Send a square wave to the speaker for a given duration 17 | */ 18 | Piezo.prototype.tone = function (tone, duration) { 19 | this.board.log('info', 'starting tone ' + tone.toString().green + ' for ' + duration.toString().green + ' milliseconds'); 20 | 21 | var self = this, 22 | tone = Math.floor(tone / 1000); // timeHigh is in microseconds and our delay() function is in milliseconds 23 | i = 0; 24 | 25 | setInterval(function(){ 26 | if (self.bright) { 27 | self.board.digitalWrite(self.pin, self.board.LOW); 28 | self.bright = false; 29 | } else { 30 | self.board.digitalWrite(self.pin, self.board.HIGH); 31 | self.bright = true; 32 | } 33 | 34 | if (i++ >= duration) { 35 | self.board.log('info', 'tone end'); 36 | clearInterval(this); 37 | } 38 | }, tone); 39 | 40 | } 41 | 42 | /* 43 | * Play a tone for a given duration to create a note 44 | * 45 | * timeHigh = period / 2 = 1 / (2 * toneFrequency) 46 | * 47 | * note frequency period timeHigh 48 | * c 261hz 3830 1915 49 | * d 294hz 3400 1700 50 | * e 329hz 3038 1519 51 | * f 349hz 2854 1432 52 | * g 392hz 2550 1275 53 | * a 440hz 2272 1136 54 | * b 493hz 2028 1014 55 | * c 523hz 1912 956 56 | */ 57 | Piezo.prototype.note = function (note, duration) { 58 | this.board.log('info', 'playing note ' + note.green + ' for ' + duration.toString().green + ' milliseconds'); 59 | var notes = { 60 | 'c': 1915, 61 | 'd': 1700, 62 | 'e': 1519, 63 | 'f': 1432, 64 | 'g': 1275, 65 | 'a': 1136, 66 | 'b': 1014, 67 | 'c': 956 68 | }; 69 | this.tone(notes[note], duration); 70 | } 71 | 72 | module.exports = Piezo; 73 | -------------------------------------------------------------------------------- /lib/ping.js: -------------------------------------------------------------------------------- 1 | var events = require('events'), 2 | util = require('util'); 3 | 4 | /* 5 | * Main Ping constructor 6 | * Process options 7 | * Tell the board to set it up 8 | */ 9 | var Ping = function (options) { 10 | if (!options || !options.board) throw new Error('Must supply required options to Ping'); 11 | this.board = options.board; 12 | this.pin = this.board.normalizePin(options.pin || 9); 13 | 14 | // Data response is in microseconds 15 | this.microseconds = 0; 16 | this.inches = 0; 17 | this.centimeters = 0; 18 | 19 | var types = { 20 | read: true 21 | }; 22 | 23 | // Loop and trigger fire-read sequences 24 | setInterval(function () { 25 | this.fire(); 26 | }.bind(this), 50); 27 | 28 | this.board.on('data', function (message) { 29 | var m = message.slice(0, -1).split('::'), 30 | err = null, 31 | pin, type, data; 32 | 33 | if (!m.length) { 34 | return; 35 | } 36 | 37 | pin = m[0]; 38 | type = m[1]; 39 | data = m.length === 3 ? m[2] : null; 40 | 41 | if (pin === this.pin && types[type]) { 42 | // See: http://arduino.cc/en/Tutorial/Ping 43 | // According to Parallax's datasheet for the PING))), there are 44 | // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per 45 | // second). This gives the distance travelled by the ping, outbound 46 | // and return, so we divide by 2 to get the distance of the obstacle. 47 | // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf 48 | this.inches = data / 74 / 2; 49 | // The speed of sound is 340 m/s or 29 microseconds per centimeter. 50 | // The ping travels out and back, so to find the distance of the 51 | // object we take half of the distance travelled. 52 | this.centimeters = data / 29 / 2; 53 | 54 | this.emit(type, err, data); 55 | } 56 | }.bind(this)); 57 | }; 58 | 59 | util.inherits(Ping, events.EventEmitter); 60 | 61 | Ping.prototype.command = function () { 62 | var msg = '97' + this.pin + ([].slice.call(arguments).join('')); 63 | 64 | this.board.write(msg); 65 | }; 66 | 67 | Ping.prototype.fire = function () { 68 | this.command('01'); 69 | }; 70 | 71 | module.exports = Ping; 72 | -------------------------------------------------------------------------------- /lib/pir.js: -------------------------------------------------------------------------------- 1 | var events = require('events'), 2 | util = require('util'); 3 | 4 | /* 5 | * Main PIR constructor 6 | * Process options 7 | * Tell the board to set it up 8 | */ 9 | var PIR = function (options) { 10 | if (!options || !options.board) { 11 | throw new Error('Must supply required options to PIR'); 12 | } 13 | this.board = options.board; 14 | this.pin = this.board.normalizePin(options.pin || 9); 15 | this.state = null; 16 | this.calibrated = false; 17 | 18 | setInterval(function () { 19 | this.board.digitalRead(this.pin); 20 | }.bind(this), 50); 21 | 22 | this.board.on('data', function (message) { 23 | var m = message.slice(0, -1).split('::'), 24 | timestamp = new Date(), 25 | err = null, 26 | pin, data; 27 | 28 | if (!m.length) { 29 | return; 30 | } 31 | 32 | pin = m[0]; 33 | data = m[1]; 34 | 35 | if (pin === this.pin) { 36 | 37 | // If this is not a calibration event 38 | if (this.state != null && this.state != +data) { 39 | 40 | // Update current state of PIR instance 41 | this.state = +data; 42 | 43 | // 'motionstart' event fired when motion occurs 44 | // within the observable range of the PIR sensor 45 | if (data === '01') { 46 | this.emit('motionstart', err, timestamp); 47 | } 48 | 49 | // 'motionend' event fired when motion has ceased 50 | // within the observable range of the PIR sensor 51 | if (data === '00') { 52 | this.emit('motionend', err, timestamp); 53 | } 54 | } 55 | 56 | // 'calibrated' event fired when PIR sensor is 57 | // ready to detect movement/motion in observable range 58 | if (!this.calibrated) { 59 | this.calibrated = true; 60 | this.state = +data; 61 | this.emit('calibrated', err, timestamp); 62 | } 63 | } 64 | }.bind(this)); 65 | }; 66 | 67 | util.inherits(PIR, events.EventEmitter); 68 | 69 | module.exports = PIR; 70 | -------------------------------------------------------------------------------- /lib/rc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Main RC constructor 3 | * Process options 4 | * Tell the board to set it up 5 | */ 6 | var RC = function (options) { 7 | if (!options || !options.board) throw new Error('Must supply required options to LED'); 8 | this.board = options.board; 9 | this.pin = this.board.normalizePin(options.pin || 10); 10 | } 11 | 12 | /* 13 | * Send triState code 14 | */ 15 | RC.prototype.triState = function (val) { 16 | var msg = '96' + this.pin + val; 17 | this.board.write(msg); 18 | } 19 | 20 | /* 21 | * Send decimal code 22 | * val must be 12 chars or less 23 | */ 24 | RC.prototype.decimal = function (val) { 25 | // at most twelve, null-term if shorter 26 | var terminatedval = (val + '\0').slice(0,12) 27 | var msg = '94' + this.pin + terminatedval; 28 | this.board.write(msg); 29 | } 30 | 31 | module.exports = RC; 32 | -------------------------------------------------------------------------------- /lib/sensor.js: -------------------------------------------------------------------------------- 1 | var events = require('events'), 2 | util = require('util'); 3 | 4 | /* 5 | * Main Sensor constructor 6 | * Process options 7 | * Tell the board to set it up 8 | */ 9 | var Sensor = function (options) { 10 | if (!options || !options.board) throw new Error('Must supply required options to Sensor'); 11 | this.board = options.board; 12 | this.pin = options.pin || 'A0'; 13 | this.board.pinMode(this.pin, 'in'); 14 | 15 | // Poll for sensor readings 16 | setInterval(function () { 17 | this.board.analogRead(this.pin); 18 | }.bind(this), options.throttle || 50); 19 | 20 | // When data is received, parse inbound message 21 | // match pin to instance pin value 22 | this.board.on('data', function (message) { 23 | var m = message.slice(0, -1).split('::'), 24 | err = null, 25 | pin, data; 26 | 27 | if (!m.length) { 28 | return; 29 | } 30 | 31 | pin = m[0] 32 | data = m.length === 2 ? m[1] : null; 33 | 34 | if (pin === this.pin) { 35 | this.emit('read', err, data); 36 | } 37 | }.bind(this)); 38 | }; 39 | 40 | /* 41 | * EventEmitter, I choose you! 42 | */ 43 | util.inherits(Sensor, events.EventEmitter); 44 | 45 | module.exports = Sensor; 46 | -------------------------------------------------------------------------------- /lib/servo.js: -------------------------------------------------------------------------------- 1 | var events = require('events'), 2 | util = require('util'); 3 | 4 | /* 5 | * Main Servo constructor 6 | * Process options 7 | * Tell the board to set it up 8 | */ 9 | var Servo = function (options) { 10 | if (!options || !options.board) throw new Error('Must supply required options to Servo'); 11 | this.board = options.board; 12 | this.pin = this.board.normalizePin(options.pin || 9); 13 | 14 | var types = { 15 | attached: true, 16 | detached: true, 17 | read: true, 18 | moved: true 19 | }; 20 | 21 | this.board.on('ready', function () { 22 | console.log('board ready, attaching servo', this); 23 | this.attach(); 24 | }.bind(this)); 25 | 26 | this.board.on('data', function (message) { 27 | var m = message.slice(0, -1).split('::'), 28 | err = null, 29 | pin, type, data; 30 | 31 | if (!m.length) { 32 | return; 33 | } 34 | 35 | pin = m[0] 36 | type = m[1]; 37 | data = m.length === 3 ? m[2] : null; 38 | 39 | if (pin === this.pin && types[type]) { 40 | this.emit(type, err, data); 41 | } 42 | }.bind(this)); 43 | }; 44 | 45 | util.inherits(Servo, events.EventEmitter); 46 | 47 | Servo.prototype.command = function () { 48 | var msg = '98' + this.pin + ([].slice.call(arguments).join('')); 49 | 50 | // this.board.log( 'info', 'command', msg ); 51 | this.board.write(msg); 52 | }; 53 | 54 | Servo.prototype.detach = function () { 55 | this.command('00'); 56 | }; 57 | 58 | Servo.prototype.attach = function () { 59 | this.command('01'); 60 | }; 61 | 62 | Servo.prototype.write = function (pos) { 63 | pos = this.board.lpad(3, '0', pos); 64 | this.board.log('info', 'moving to: ' + pos); 65 | this.command('02' + pos); 66 | }; 67 | 68 | Servo.prototype.read = function () { 69 | this.command('03'); 70 | }; 71 | 72 | // Servo.prototype.writeMilliseconds = function () {}; 73 | // Servo.prototype.attached = function (callback) { 74 | // this.callbacks.attached.push(callback); 75 | // }; 76 | 77 | Servo.prototype.sweep = function (options) { 78 | // Ensure no missing options object 79 | options = options || {}; 80 | 81 | var timeout = { 82 | inner: null, 83 | outer: null 84 | }, 85 | moves = 0, 86 | // sweep settings 87 | lapse = options.lapse || 2000, 88 | to = options.to || 180, 89 | from = options.from || 1, 90 | // sweep handlers 91 | doSweep = function doSweep(pos) { 92 | // this.board.log('info', 'current position: ', pos); 93 | var moveTo, 94 | posint = +pos; 95 | 96 | // this.board.log('info', 'current pos int: ', posint); 97 | 98 | if (posint === 93) { 99 | moveTo = 1; 100 | } else { 101 | 102 | // this.board.log('info', 'posint not 93.....'); 103 | 104 | if (posint < to) { 105 | moveTo = to; 106 | } else if (posint == to) { 107 | moveTo = 90; 108 | } else { 109 | moveTo = from; 110 | } 111 | } 112 | 113 | this.write(moveTo); 114 | 115 | moves++; 116 | }; 117 | 118 | this.on('read', doSweep); 119 | 120 | // Initialize sweep; wait for for stack unwind. 121 | timeout.outer = setTimeout(function loop() { 122 | // Read the current position, will trigger 123 | // 'read' event with position data; 124 | if (moves < 2) { 125 | this.read(); 126 | 127 | timeout.inner = setTimeout(loop.bind(this), lapse); 128 | } else { 129 | // this.board.log('info', 'info', 'clearing'); 130 | 131 | clearTimeout(timeout.inner); 132 | clearTimeout(timeout.outer); 133 | 134 | loop = null; 135 | 136 | this.removeListener('read', doSweep); 137 | this.emit.call(this, 'aftersweep'); 138 | } 139 | }.bind(this), 0); 140 | }; 141 | 142 | module.exports = Servo; 143 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Cam Pedersen", 4 | "email": "diffference@gmail.com", 5 | "url": "http://campedersen.com/" 6 | }, 7 | "contributors": [ 8 | { "name": "Rick Waldron", "email": "waldron.rick@gmail.com" }, 9 | { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" }, 10 | { "name": "Seiya Konno", "email": "nulltask@gmail.com" }, 11 | { "name": "Nathan Vander Wilt", "email": "nate@calftrail.com" }, 12 | { "name": "Adam Brault (&yet)", "email": "contact@andyet.com" }, 13 | { "name": "Emanuele Tessore", "email": "setola@gmail.com" }, 14 | { "name": "Willi Thiel", "email": "ni-c@ni-c.de" }, 15 | { "name": "Tom Janson", "email": "priv.tom.janson+duino@gmail.com" } 16 | ], 17 | "name": "duino", 18 | "description": "Arduino framework for mad scientists", 19 | "version": "0.1.0", 20 | "keywords": [ 21 | "arduino", 22 | "serial", 23 | "framework" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/ecto/duino.git" 28 | }, 29 | "main": "index.js", 30 | "engines": { 31 | "node": "*" 32 | }, 33 | "dependencies": { 34 | "serialport": "*", 35 | "chalk": "*" 36 | }, 37 | "devDependencies": {} 38 | } 39 | -------------------------------------------------------------------------------- /src/du.ino: -------------------------------------------------------------------------------- 1 | duino/duino.ino -------------------------------------------------------------------------------- /src/duino/duino.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool debug = false; 6 | 7 | int index = 0; 8 | 9 | char messageBuffer[24]; 10 | char cmd[3]; 11 | char pin[3]; 12 | char val[13]; 13 | char aux[4]; 14 | char type[2]; 15 | char addr[5]; 16 | 17 | Servo servo; 18 | 19 | IRsend irsend; 20 | 21 | void setup() { 22 | Serial.begin(115200); 23 | } 24 | 25 | void loop() { 26 | while(Serial.available() > 0) { 27 | char x = Serial.read(); 28 | if (x == '!') index = 0; // start 29 | else if (x == '.') process(); // end 30 | else messageBuffer[index++] = x; 31 | } 32 | } 33 | 34 | /* 35 | * Deal with a full message and determine function to call 36 | */ 37 | void process() { 38 | index = 0; 39 | 40 | strncpy(cmd, messageBuffer, 2); 41 | cmd[2] = '\0'; 42 | strncpy(pin, messageBuffer + 2, 2); 43 | pin[2] = '\0'; 44 | 45 | if (debug) { 46 | Serial.println(messageBuffer); 47 | } 48 | int cmdid = atoi(cmd); 49 | 50 | if (cmdid == 95) { 51 | strncpy(type, messageBuffer + 4, 1); 52 | type[1] = '\0'; 53 | strncpy(val, messageBuffer + 5, 9); 54 | val[8] = '\0'; 55 | strncpy(addr, messageBuffer + 14, 4); 56 | addr[4] = '\0'; 57 | } else if (cmdid == 96 || cmdid == 94) { 58 | strncpy(val, messageBuffer + 4, 12); 59 | val[12] = '\0'; 60 | } else if (cmdid > 96) { 61 | strncpy(val, messageBuffer + 4, 2); 62 | val[2] = '\0'; 63 | strncpy(aux, messageBuffer + 6, 3); 64 | aux[3] = '\0'; 65 | } else { 66 | strncpy(val, messageBuffer + 4, 3); 67 | val[3] = '\0'; 68 | strncpy(aux, messageBuffer + 7, 3); 69 | aux[3] = '\0'; 70 | } 71 | 72 | // Serial.println(cmd); 73 | // Serial.println(pin); 74 | // Serial.println(val); 75 | // Serial.println(aux); 76 | 77 | switch(cmdid) { 78 | case 0: sm(pin,val); break; 79 | case 1: dw(pin,val); break; 80 | case 2: dr(pin,val); break; 81 | case 3: aw(pin,val); break; 82 | case 4: ar(pin,val); break; 83 | case 94: handleRCDecimal(pin, val); break; 84 | case 95: handleIRsend(type, val, addr); break; 85 | case 96: handleRCTriState(pin, val); break; 86 | case 97: handlePing(pin,val,aux); break; 87 | case 98: handleServo(pin,val,aux); break; 88 | case 99: toggleDebug(val); break; 89 | default: break; 90 | } 91 | } 92 | 93 | /* 94 | * Toggle debug mode 95 | */ 96 | void toggleDebug(char *val) { 97 | if (atoi(val) == 0) { 98 | debug = false; 99 | Serial.println("goodbye"); 100 | } else { 101 | debug = true; 102 | Serial.println("hello"); 103 | } 104 | } 105 | 106 | /* 107 | * Set pin mode 108 | */ 109 | void sm(char *pin, char *val) { 110 | if (debug) Serial.println("sm"); 111 | int p = getPin(pin); 112 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 113 | if (atoi(val) == 0) { 114 | pinMode(p, OUTPUT); 115 | } else { 116 | pinMode(p, INPUT); 117 | } 118 | } 119 | 120 | /* 121 | * Digital write 122 | */ 123 | void dw(char *pin, char *val) { 124 | if (debug) Serial.println("dw"); 125 | int p = getPin(pin); 126 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 127 | pinMode(p, OUTPUT); 128 | if (atoi(val) == 0) { 129 | digitalWrite(p, LOW); 130 | } else { 131 | digitalWrite(p, HIGH); 132 | } 133 | } 134 | 135 | /* 136 | * Digital read 137 | */ 138 | void dr(char *pin, char *val) { 139 | if (debug) Serial.println("dr"); 140 | int p = getPin(pin); 141 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 142 | pinMode(p, INPUT); 143 | int oraw = digitalRead(p); 144 | char m[7]; 145 | sprintf(m, "%02d::%02d", p,oraw); 146 | Serial.println(m); 147 | } 148 | 149 | /* 150 | * Analog read 151 | */ 152 | void ar(char *pin, char *val) { 153 | if(debug) Serial.println("ar"); 154 | int p = getPin(pin); 155 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 156 | pinMode(p, INPUT); // don't want to sw 157 | int rval = analogRead(p); 158 | char m[8]; 159 | sprintf(m, "%s::%03d", pin, rval); 160 | Serial.println(m); 161 | } 162 | 163 | void aw(char *pin, char *val) { 164 | if(debug) Serial.println("aw"); 165 | int p = getPin(pin); 166 | pinMode(p, OUTPUT); 167 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 168 | analogWrite(p,atoi(val)); 169 | } 170 | 171 | int getPin(char *pin) { //Converts to A0-A5, and returns -1 on error 172 | int ret = -1; 173 | if(pin[0] == 'A' || pin[0] == 'a') { 174 | switch(pin[1]) { 175 | case '0': ret = A0; break; 176 | case '1': ret = A1; break; 177 | case '2': ret = A2; break; 178 | case '3': ret = A3; break; 179 | case '4': ret = A4; break; 180 | case '5': ret = A5; break; 181 | default: break; 182 | } 183 | } else { 184 | ret = atoi(pin); 185 | if(ret == 0 && (pin[0] != '0' || pin[1] != '0')) { 186 | ret = -1; 187 | } 188 | } 189 | return ret; 190 | } 191 | 192 | /* 193 | * Handle Ping commands 194 | * fire, read 195 | */ 196 | void handlePing(char *pin, char *val, char *aux) { 197 | if (debug) Serial.println("ss"); 198 | int p = getPin(pin); 199 | 200 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 201 | Serial.println("got signal"); 202 | 203 | // 01(1) Fire and Read 204 | if (atoi(val) == 1) { 205 | char m[16]; 206 | 207 | pinMode(p, OUTPUT); 208 | digitalWrite(p, LOW); 209 | delayMicroseconds(2); 210 | digitalWrite(p, HIGH); 211 | delayMicroseconds(5); 212 | digitalWrite(p, LOW); 213 | 214 | Serial.println("ping fired"); 215 | 216 | pinMode(p, INPUT); 217 | sprintf(m, "%s::read::%08d", pin, pulseIn(p, HIGH)); 218 | Serial.println(m); 219 | 220 | delay(50); 221 | } 222 | } 223 | 224 | /* 225 | * Handle Servo commands 226 | * attach, detach, write, read, writeMicroseconds, attached 227 | */ 228 | void handleServo(char *pin, char *val, char *aux) { 229 | if (debug) Serial.println("ss"); 230 | int p = getPin(pin); 231 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 232 | Serial.println("signal: servo"); 233 | 234 | // 00(0) Detach 235 | if (atoi(val) == 0) { 236 | servo.detach(); 237 | char m[12]; 238 | sprintf(m, "%s::detached", pin); 239 | Serial.println(m); 240 | 241 | // 01(1) Attach 242 | } else if (atoi(val) == 1) { 243 | // servo.attach(p, 750, 2250); 244 | servo.attach(p); 245 | char m[12]; 246 | sprintf(m, "%s::attached", pin); 247 | Serial.println(m); 248 | 249 | // 02(2) Write 250 | } else if (atoi(val) == 2) { 251 | Serial.println("writing to servo"); 252 | Serial.println(atoi(aux)); 253 | // Write to servo 254 | servo.write(atoi(aux)); 255 | delay(15); 256 | 257 | // 03(3) Read 258 | } else if (atoi(val) == 3) { 259 | Serial.println("reading servo"); 260 | int sval = servo.read(); 261 | char m[13]; 262 | sprintf(m, "%s::read::%03d", pin, sval); 263 | Serial.println(m); 264 | } 265 | } 266 | 267 | /* 268 | * Handle RC commands 269 | * handleRCTriState("10", "0FFF0FFFFF0F") 270 | */ 271 | void handleRCTriState(char *pin, char *val) { 272 | int p = getPin(pin); 273 | if(p == -1) { if(debug) Serial.println("badpin"); return; } 274 | if (debug) Serial.println("RC"); 275 | RCSwitch rc = RCSwitch(); 276 | rc.enableTransmit(p); 277 | rc.sendTriState(val); 278 | } 279 | 280 | /* 281 | * Handle RC commands via decimal code 282 | * For those sockets that don't use tri-state. 283 | * handleRCDecimal("10", "5522351") 284 | */ 285 | void handleRCDecimal(char *pin, char *val) { 286 | int p = getPin(pin); 287 | if (p == -1) { if (debug) Serial.println("badpin"); return; } 288 | if (debug) Serial.println("RCdec" + atol(val)); 289 | RCSwitch rc = RCSwitch(); 290 | rc.enableTransmit(p); 291 | rc.send(atol(val), 24); 292 | } 293 | 294 | /* 295 | * Handle IR commands 296 | */ 297 | void handleIRsend(char *type, char *val, char *addr) { 298 | if (debug) Serial.println("IR"); 299 | switch (atoi(type)) { 300 | case 1: 301 | irsend.sendRC5(strtol(val, (char **)0, 16), atoi(addr)); 302 | break; 303 | case 2: 304 | irsend.sendRC6(strtol(val, (char **)0, 16), atoi(addr)); 305 | break; 306 | case 3: 307 | irsend.sendNEC(strtol(val, (char **)0, 16), atoi(addr)); 308 | break; 309 | case 4: 310 | irsend.sendSony(strtol(val, (char **)0, 16), atoi(addr)); 311 | break; 312 | case 5: 313 | irsend.sendDISH(strtol(val, (char **)0, 16), atoi(addr)); 314 | break; 315 | case 6: 316 | irsend.sendSharp(strtol(val, (char **)0, 16), atoi(addr)); 317 | break; 318 | case 7: 319 | irsend.sendPanasonic(strtol(addr, (char **)0, 16), strtol(val, (char **)0, 16)); 320 | break; 321 | case 8: 322 | irsend.sendJVC(atoi(val), atoi(addr), 1); 323 | break; 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /src/libs/IRremote/IRremote.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote 3 | * Version 0.11 August, 2009 4 | * Copyright 2009 Ken Shirriff 5 | * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 6 | * 7 | * Modified by Paul Stoffregen to support other boards and timers 8 | * Modified by Mitra Ardron 9 | * Added Sanyo and Mitsubishi controllers 10 | * Modified Sony to spot the repeat codes that some Sony's send 11 | * 12 | * Interrupt code based on NECIRrcv by Joe Knapp 13 | * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 14 | * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 15 | * 16 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 17 | */ 18 | 19 | #include "IRremote.h" 20 | #include "IRremoteInt.h" 21 | 22 | // Provides ISR 23 | #include 24 | 25 | volatile irparams_t irparams; 26 | 27 | // These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging. 28 | // To use them, set DEBUG in IRremoteInt.h 29 | // Normally macros are used for efficiency 30 | #ifdef DEBUG 31 | int MATCH(int measured, int desired) { 32 | Serial.print("Testing: "); 33 | Serial.print(TICKS_LOW(desired), DEC); 34 | Serial.print(" <= "); 35 | Serial.print(measured, DEC); 36 | Serial.print(" <= "); 37 | Serial.println(TICKS_HIGH(desired), DEC); 38 | return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired); 39 | } 40 | 41 | int MATCH_MARK(int measured_ticks, int desired_us) { 42 | Serial.print("Testing mark "); 43 | Serial.print(measured_ticks * USECPERTICK, DEC); 44 | Serial.print(" vs "); 45 | Serial.print(desired_us, DEC); 46 | Serial.print(": "); 47 | Serial.print(TICKS_LOW(desired_us + MARK_EXCESS), DEC); 48 | Serial.print(" <= "); 49 | Serial.print(measured_ticks, DEC); 50 | Serial.print(" <= "); 51 | Serial.println(TICKS_HIGH(desired_us + MARK_EXCESS), DEC); 52 | return measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS); 53 | } 54 | 55 | int MATCH_SPACE(int measured_ticks, int desired_us) { 56 | Serial.print("Testing space "); 57 | Serial.print(measured_ticks * USECPERTICK, DEC); 58 | Serial.print(" vs "); 59 | Serial.print(desired_us, DEC); 60 | Serial.print(": "); 61 | Serial.print(TICKS_LOW(desired_us - MARK_EXCESS), DEC); 62 | Serial.print(" <= "); 63 | Serial.print(measured_ticks, DEC); 64 | Serial.print(" <= "); 65 | Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC); 66 | return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS); 67 | } 68 | #endif 69 | 70 | void IRsend::sendNEC(unsigned long data, int nbits) 71 | { 72 | enableIROut(38); 73 | mark(NEC_HDR_MARK); 74 | space(NEC_HDR_SPACE); 75 | for (int i = 0; i < nbits; i++) { 76 | if (data & TOPBIT) { 77 | mark(NEC_BIT_MARK); 78 | space(NEC_ONE_SPACE); 79 | } 80 | else { 81 | mark(NEC_BIT_MARK); 82 | space(NEC_ZERO_SPACE); 83 | } 84 | data <<= 1; 85 | } 86 | mark(NEC_BIT_MARK); 87 | space(0); 88 | } 89 | 90 | void IRsend::sendSony(unsigned long data, int nbits) { 91 | enableIROut(40); 92 | mark(SONY_HDR_MARK); 93 | space(SONY_HDR_SPACE); 94 | data = data << (32 - nbits); 95 | for (int i = 0; i < nbits; i++) { 96 | if (data & TOPBIT) { 97 | mark(SONY_ONE_MARK); 98 | space(SONY_HDR_SPACE); 99 | } 100 | else { 101 | mark(SONY_ZERO_MARK); 102 | space(SONY_HDR_SPACE); 103 | } 104 | data <<= 1; 105 | } 106 | } 107 | 108 | void IRsend::sendRaw(unsigned int buf[], int len, int hz) 109 | { 110 | enableIROut(hz); 111 | for (int i = 0; i < len; i++) { 112 | if (i & 1) { 113 | space(buf[i]); 114 | } 115 | else { 116 | mark(buf[i]); 117 | } 118 | } 119 | space(0); // Just to be sure 120 | } 121 | 122 | // Note: first bit must be a one (start bit) 123 | void IRsend::sendRC5(unsigned long data, int nbits) 124 | { 125 | enableIROut(36); 126 | data = data << (32 - nbits); 127 | mark(RC5_T1); // First start bit 128 | space(RC5_T1); // Second start bit 129 | mark(RC5_T1); // Second start bit 130 | for (int i = 0; i < nbits; i++) { 131 | if (data & TOPBIT) { 132 | space(RC5_T1); // 1 is space, then mark 133 | mark(RC5_T1); 134 | } 135 | else { 136 | mark(RC5_T1); 137 | space(RC5_T1); 138 | } 139 | data <<= 1; 140 | } 141 | space(0); // Turn off at end 142 | } 143 | 144 | // Caller needs to take care of flipping the toggle bit 145 | void IRsend::sendRC6(unsigned long data, int nbits) 146 | { 147 | enableIROut(36); 148 | data = data << (32 - nbits); 149 | mark(RC6_HDR_MARK); 150 | space(RC6_HDR_SPACE); 151 | mark(RC6_T1); // start bit 152 | space(RC6_T1); 153 | int t; 154 | for (int i = 0; i < nbits; i++) { 155 | if (i == 3) { 156 | // double-wide trailer bit 157 | t = 2 * RC6_T1; 158 | } 159 | else { 160 | t = RC6_T1; 161 | } 162 | if (data & TOPBIT) { 163 | mark(t); 164 | space(t); 165 | } 166 | else { 167 | space(t); 168 | mark(t); 169 | } 170 | 171 | data <<= 1; 172 | } 173 | space(0); // Turn off at end 174 | } 175 | void IRsend::sendPanasonic(unsigned int address, unsigned long data) { 176 | enableIROut(35); 177 | mark(PANASONIC_HDR_MARK); 178 | space(PANASONIC_HDR_SPACE); 179 | 180 | for(int i=0;i<16;i++) 181 | { 182 | mark(PANASONIC_BIT_MARK); 183 | if (address & 0x8000) { 184 | space(PANASONIC_ONE_SPACE); 185 | } else { 186 | space(PANASONIC_ZERO_SPACE); 187 | } 188 | address <<= 1; 189 | } 190 | for (int i=0; i < 32; i++) { 191 | mark(PANASONIC_BIT_MARK); 192 | if (data & TOPBIT) { 193 | space(PANASONIC_ONE_SPACE); 194 | } else { 195 | space(PANASONIC_ZERO_SPACE); 196 | } 197 | data <<= 1; 198 | } 199 | mark(PANASONIC_BIT_MARK); 200 | space(0); 201 | } 202 | void IRsend::sendJVC(unsigned long data, int nbits, int repeat) 203 | { 204 | enableIROut(38); 205 | data = data << (32 - nbits); 206 | if (!repeat){ 207 | mark(JVC_HDR_MARK); 208 | space(JVC_HDR_SPACE); 209 | } 210 | for (int i = 0; i < nbits; i++) { 211 | if (data & TOPBIT) { 212 | mark(JVC_BIT_MARK); 213 | space(JVC_ONE_SPACE); 214 | } 215 | else { 216 | mark(JVC_BIT_MARK); 217 | space(JVC_ZERO_SPACE); 218 | } 219 | data <<= 1; 220 | } 221 | mark(JVC_BIT_MARK); 222 | space(0); 223 | } 224 | void IRsend::mark(int time) { 225 | // Sends an IR mark for the specified number of microseconds. 226 | // The mark output is modulated at the PWM frequency. 227 | TIMER_ENABLE_PWM; // Enable pin 3 PWM output 228 | if (time > 0) delayMicroseconds(time); 229 | } 230 | 231 | /* Leave pin off for time (given in microseconds) */ 232 | void IRsend::space(int time) { 233 | // Sends an IR space for the specified number of microseconds. 234 | // A space is no output, so the PWM output is disabled. 235 | TIMER_DISABLE_PWM; // Disable pin 3 PWM output 236 | if (time > 0) delayMicroseconds(time); 237 | } 238 | 239 | void IRsend::enableIROut(int khz) { 240 | // Enables IR output. The khz value controls the modulation frequency in kilohertz. 241 | // The IR output will be on pin 3 (OC2B). 242 | // This routine is designed for 36-40KHz; if you use it for other values, it's up to you 243 | // to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.) 244 | // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B 245 | // controlling the duty cycle. 246 | // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A) 247 | // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin. 248 | // A few hours staring at the ATmega documentation and this will all make sense. 249 | // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details. 250 | 251 | 252 | // Disable the Timer2 Interrupt (which is used for receiving IR) 253 | TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt 254 | 255 | pinMode(TIMER_PWM_PIN, OUTPUT); 256 | digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low 257 | 258 | // COM2A = 00: disconnect OC2A 259 | // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted 260 | // WGM2 = 101: phase-correct PWM with OCRA as top 261 | // CS2 = 000: no prescaling 262 | // The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A. 263 | TIMER_CONFIG_KHZ(khz); 264 | } 265 | 266 | IRrecv::IRrecv(int recvpin) 267 | { 268 | irparams.recvpin = recvpin; 269 | irparams.blinkflag = 0; 270 | } 271 | 272 | // initialization 273 | void IRrecv::enableIRIn() { 274 | cli(); 275 | // setup pulse clock timer interrupt 276 | //Prescale /8 (16M/8 = 0.5 microseconds per tick) 277 | // Therefore, the timer interval can range from 0.5 to 128 microseconds 278 | // depending on the reset value (255 to 0) 279 | TIMER_CONFIG_NORMAL(); 280 | 281 | //Timer2 Overflow Interrupt Enable 282 | TIMER_ENABLE_INTR; 283 | 284 | TIMER_RESET; 285 | 286 | sei(); // enable interrupts 287 | 288 | // initialize state machine variables 289 | irparams.rcvstate = STATE_IDLE; 290 | irparams.rawlen = 0; 291 | 292 | // set pin modes 293 | pinMode(irparams.recvpin, INPUT); 294 | } 295 | 296 | // enable/disable blinking of pin 13 on IR processing 297 | void IRrecv::blink13(int blinkflag) 298 | { 299 | irparams.blinkflag = blinkflag; 300 | if (blinkflag) 301 | pinMode(BLINKLED, OUTPUT); 302 | } 303 | 304 | // TIMER2 interrupt code to collect raw data. 305 | // Widths of alternating SPACE, MARK are recorded in rawbuf. 306 | // Recorded in ticks of 50 microseconds. 307 | // rawlen counts the number of entries recorded so far. 308 | // First entry is the SPACE between transmissions. 309 | // As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues. 310 | // As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts 311 | ISR(TIMER_INTR_NAME) 312 | { 313 | TIMER_RESET; 314 | 315 | uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin); 316 | 317 | irparams.timer++; // One more 50us tick 318 | if (irparams.rawlen >= RAWBUF) { 319 | // Buffer overflow 320 | irparams.rcvstate = STATE_STOP; 321 | } 322 | switch(irparams.rcvstate) { 323 | case STATE_IDLE: // In the middle of a gap 324 | if (irdata == MARK) { 325 | if (irparams.timer < GAP_TICKS) { 326 | // Not big enough to be a gap. 327 | irparams.timer = 0; 328 | } 329 | else { 330 | // gap just ended, record duration and start recording transmission 331 | irparams.rawlen = 0; 332 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 333 | irparams.timer = 0; 334 | irparams.rcvstate = STATE_MARK; 335 | } 336 | } 337 | break; 338 | case STATE_MARK: // timing MARK 339 | if (irdata == SPACE) { // MARK ended, record time 340 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 341 | irparams.timer = 0; 342 | irparams.rcvstate = STATE_SPACE; 343 | } 344 | break; 345 | case STATE_SPACE: // timing SPACE 346 | if (irdata == MARK) { // SPACE just ended, record it 347 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 348 | irparams.timer = 0; 349 | irparams.rcvstate = STATE_MARK; 350 | } 351 | else { // SPACE 352 | if (irparams.timer > GAP_TICKS) { 353 | // big SPACE, indicates gap between codes 354 | // Mark current code as ready for processing 355 | // Switch to STOP 356 | // Don't reset timer; keep counting space width 357 | irparams.rcvstate = STATE_STOP; 358 | } 359 | } 360 | break; 361 | case STATE_STOP: // waiting, measuring gap 362 | if (irdata == MARK) { // reset gap timer 363 | irparams.timer = 0; 364 | } 365 | break; 366 | } 367 | 368 | if (irparams.blinkflag) { 369 | if (irdata == MARK) { 370 | BLINKLED_ON(); // turn pin 13 LED on 371 | } 372 | else { 373 | BLINKLED_OFF(); // turn pin 13 LED off 374 | } 375 | } 376 | } 377 | 378 | void IRrecv::resume() { 379 | irparams.rcvstate = STATE_IDLE; 380 | irparams.rawlen = 0; 381 | } 382 | 383 | 384 | 385 | // Decodes the received IR message 386 | // Returns 0 if no data ready, 1 if data ready. 387 | // Results of decoding are stored in results 388 | int IRrecv::decode(decode_results *results) { 389 | results->rawbuf = irparams.rawbuf; 390 | results->rawlen = irparams.rawlen; 391 | if (irparams.rcvstate != STATE_STOP) { 392 | return ERR; 393 | } 394 | #ifdef DEBUG 395 | Serial.println("Attempting NEC decode"); 396 | #endif 397 | if (decodeNEC(results)) { 398 | return DECODED; 399 | } 400 | #ifdef DEBUG 401 | Serial.println("Attempting Sony decode"); 402 | #endif 403 | if (decodeSony(results)) { 404 | return DECODED; 405 | } 406 | #ifdef DEBUG 407 | Serial.println("Attempting Sanyo decode"); 408 | #endif 409 | if (decodeSanyo(results)) { 410 | return DECODED; 411 | } 412 | #ifdef DEBUG 413 | Serial.println("Attempting Mitsubishi decode"); 414 | #endif 415 | if (decodeMitsubishi(results)) { 416 | return DECODED; 417 | } 418 | #ifdef DEBUG 419 | Serial.println("Attempting RC5 decode"); 420 | #endif 421 | if (decodeRC5(results)) { 422 | return DECODED; 423 | } 424 | #ifdef DEBUG 425 | Serial.println("Attempting RC6 decode"); 426 | #endif 427 | if (decodeRC6(results)) { 428 | return DECODED; 429 | } 430 | #ifdef DEBUG 431 | Serial.println("Attempting Panasonic decode"); 432 | #endif 433 | if (decodePanasonic(results)) { 434 | return DECODED; 435 | } 436 | #ifdef DEBUG 437 | Serial.println("Attempting JVC decode"); 438 | #endif 439 | if (decodeJVC(results)) { 440 | return DECODED; 441 | } 442 | // decodeHash returns a hash on any input. 443 | // Thus, it needs to be last in the list. 444 | // If you add any decodes, add them before this. 445 | if (decodeHash(results)) { 446 | return DECODED; 447 | } 448 | // Throw away and start over 449 | resume(); 450 | return ERR; 451 | } 452 | 453 | // NECs have a repeat only 4 items long 454 | long IRrecv::decodeNEC(decode_results *results) { 455 | long data = 0; 456 | int offset = 1; // Skip first space 457 | // Initial mark 458 | if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) { 459 | return ERR; 460 | } 461 | offset++; 462 | // Check for repeat 463 | if (irparams.rawlen == 4 && 464 | MATCH_SPACE(results->rawbuf[offset], NEC_RPT_SPACE) && 465 | MATCH_MARK(results->rawbuf[offset+1], NEC_BIT_MARK)) { 466 | results->bits = 0; 467 | results->value = REPEAT; 468 | results->decode_type = NEC; 469 | return DECODED; 470 | } 471 | if (irparams.rawlen < 2 * NEC_BITS + 4) { 472 | return ERR; 473 | } 474 | // Initial space 475 | if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) { 476 | return ERR; 477 | } 478 | offset++; 479 | for (int i = 0; i < NEC_BITS; i++) { 480 | if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) { 481 | return ERR; 482 | } 483 | offset++; 484 | if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE)) { 485 | data = (data << 1) | 1; 486 | } 487 | else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) { 488 | data <<= 1; 489 | } 490 | else { 491 | return ERR; 492 | } 493 | offset++; 494 | } 495 | // Success 496 | results->bits = NEC_BITS; 497 | results->value = data; 498 | results->decode_type = NEC; 499 | return DECODED; 500 | } 501 | 502 | long IRrecv::decodeSony(decode_results *results) { 503 | long data = 0; 504 | if (irparams.rawlen < 2 * SONY_BITS + 2) { 505 | return ERR; 506 | } 507 | int offset = 0; // Dont skip first space, check its size 508 | 509 | // Some Sony's deliver repeats fast after first 510 | // unfortunately can't spot difference from of repeat from two fast clicks 511 | if (results->rawbuf[offset] < SONY_DOUBLE_SPACE_USECS) { 512 | // Serial.print("IR Gap found: "); 513 | results->bits = 0; 514 | results->value = REPEAT; 515 | results->decode_type = SANYO; 516 | return DECODED; 517 | } 518 | offset++; 519 | 520 | // Initial mark 521 | if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) { 522 | return ERR; 523 | } 524 | offset++; 525 | 526 | while (offset + 1 < irparams.rawlen) { 527 | if (!MATCH_SPACE(results->rawbuf[offset], SONY_HDR_SPACE)) { 528 | break; 529 | } 530 | offset++; 531 | if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) { 532 | data = (data << 1) | 1; 533 | } 534 | else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) { 535 | data <<= 1; 536 | } 537 | else { 538 | return ERR; 539 | } 540 | offset++; 541 | } 542 | 543 | // Success 544 | results->bits = (offset - 1) / 2; 545 | if (results->bits < 12) { 546 | results->bits = 0; 547 | return ERR; 548 | } 549 | results->value = data; 550 | results->decode_type = SONY; 551 | return DECODED; 552 | } 553 | 554 | // I think this is a Sanyo decoder - serial = SA 8650B 555 | // Looks like Sony except for timings, 48 chars of data and time/space different 556 | long IRrecv::decodeSanyo(decode_results *results) { 557 | long data = 0; 558 | if (irparams.rawlen < 2 * SANYO_BITS + 2) { 559 | return ERR; 560 | } 561 | int offset = 0; // Skip first space 562 | // Initial space 563 | /* Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay 564 | Serial.print("IR Gap: "); 565 | Serial.println( results->rawbuf[offset]); 566 | Serial.println( "test against:"); 567 | Serial.println(results->rawbuf[offset]); 568 | */ 569 | if (results->rawbuf[offset] < SANYO_DOUBLE_SPACE_USECS) { 570 | // Serial.print("IR Gap found: "); 571 | results->bits = 0; 572 | results->value = REPEAT; 573 | results->decode_type = SANYO; 574 | return DECODED; 575 | } 576 | offset++; 577 | 578 | // Initial mark 579 | if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) { 580 | return ERR; 581 | } 582 | offset++; 583 | 584 | // Skip Second Mark 585 | if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) { 586 | return ERR; 587 | } 588 | offset++; 589 | 590 | while (offset + 1 < irparams.rawlen) { 591 | if (!MATCH_SPACE(results->rawbuf[offset], SANYO_HDR_SPACE)) { 592 | break; 593 | } 594 | offset++; 595 | if (MATCH_MARK(results->rawbuf[offset], SANYO_ONE_MARK)) { 596 | data = (data << 1) | 1; 597 | } 598 | else if (MATCH_MARK(results->rawbuf[offset], SANYO_ZERO_MARK)) { 599 | data <<= 1; 600 | } 601 | else { 602 | return ERR; 603 | } 604 | offset++; 605 | } 606 | 607 | // Success 608 | results->bits = (offset - 1) / 2; 609 | if (results->bits < 12) { 610 | results->bits = 0; 611 | return ERR; 612 | } 613 | results->value = data; 614 | results->decode_type = SANYO; 615 | return DECODED; 616 | } 617 | 618 | // Looks like Sony except for timings, 48 chars of data and time/space different 619 | long IRrecv::decodeMitsubishi(decode_results *results) { 620 | // Serial.print("?!? decoding Mitsubishi:");Serial.print(irparams.rawlen); Serial.print(" want "); Serial.println( 2 * MITSUBISHI_BITS + 2); 621 | long data = 0; 622 | if (irparams.rawlen < 2 * MITSUBISHI_BITS + 2) { 623 | return ERR; 624 | } 625 | int offset = 0; // Skip first space 626 | // Initial space 627 | /* Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay 628 | Serial.print("IR Gap: "); 629 | Serial.println( results->rawbuf[offset]); 630 | Serial.println( "test against:"); 631 | Serial.println(results->rawbuf[offset]); 632 | */ 633 | /* Not seeing double keys from Mitsubishi 634 | if (results->rawbuf[offset] < MITSUBISHI_DOUBLE_SPACE_USECS) { 635 | // Serial.print("IR Gap found: "); 636 | results->bits = 0; 637 | results->value = REPEAT; 638 | results->decode_type = MITSUBISHI; 639 | return DECODED; 640 | } 641 | */ 642 | offset++; 643 | 644 | // Typical 645 | // 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7 646 | 647 | // Initial Space 648 | if (!MATCH_MARK(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) { 649 | return ERR; 650 | } 651 | offset++; 652 | while (offset + 1 < irparams.rawlen) { 653 | if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ONE_MARK)) { 654 | data = (data << 1) | 1; 655 | } 656 | else if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ZERO_MARK)) { 657 | data <<= 1; 658 | } 659 | else { 660 | // Serial.println("A"); Serial.println(offset); Serial.println(results->rawbuf[offset]); 661 | return ERR; 662 | } 663 | offset++; 664 | if (!MATCH_SPACE(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) { 665 | // Serial.println("B"); Serial.println(offset); Serial.println(results->rawbuf[offset]); 666 | break; 667 | } 668 | offset++; 669 | } 670 | 671 | // Success 672 | results->bits = (offset - 1) / 2; 673 | if (results->bits < MITSUBISHI_BITS) { 674 | results->bits = 0; 675 | return ERR; 676 | } 677 | results->value = data; 678 | results->decode_type = MITSUBISHI; 679 | return DECODED; 680 | } 681 | 682 | 683 | // Gets one undecoded level at a time from the raw buffer. 684 | // The RC5/6 decoding is easier if the data is broken into time intervals. 685 | // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, 686 | // successive calls to getRClevel will return MARK, MARK, SPACE. 687 | // offset and used are updated to keep track of the current position. 688 | // t1 is the time interval for a single bit in microseconds. 689 | // Returns -1 for error (measured time interval is not a multiple of t1). 690 | int IRrecv::getRClevel(decode_results *results, int *offset, int *used, int t1) { 691 | if (*offset >= results->rawlen) { 692 | // After end of recorded buffer, assume SPACE. 693 | return SPACE; 694 | } 695 | int width = results->rawbuf[*offset]; 696 | int val = ((*offset) % 2) ? MARK : SPACE; 697 | int correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS; 698 | 699 | int avail; 700 | if (MATCH(width, t1 + correction)) { 701 | avail = 1; 702 | } 703 | else if (MATCH(width, 2*t1 + correction)) { 704 | avail = 2; 705 | } 706 | else if (MATCH(width, 3*t1 + correction)) { 707 | avail = 3; 708 | } 709 | else { 710 | return -1; 711 | } 712 | 713 | (*used)++; 714 | if (*used >= avail) { 715 | *used = 0; 716 | (*offset)++; 717 | } 718 | #ifdef DEBUG 719 | if (val == MARK) { 720 | Serial.println("MARK"); 721 | } 722 | else { 723 | Serial.println("SPACE"); 724 | } 725 | #endif 726 | return val; 727 | } 728 | 729 | long IRrecv::decodeRC5(decode_results *results) { 730 | if (irparams.rawlen < MIN_RC5_SAMPLES + 2) { 731 | return ERR; 732 | } 733 | int offset = 1; // Skip gap space 734 | long data = 0; 735 | int used = 0; 736 | // Get start bits 737 | if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR; 738 | if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return ERR; 739 | if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR; 740 | int nbits; 741 | for (nbits = 0; offset < irparams.rawlen; nbits++) { 742 | int levelA = getRClevel(results, &offset, &used, RC5_T1); 743 | int levelB = getRClevel(results, &offset, &used, RC5_T1); 744 | if (levelA == SPACE && levelB == MARK) { 745 | // 1 bit 746 | data = (data << 1) | 1; 747 | } 748 | else if (levelA == MARK && levelB == SPACE) { 749 | // zero bit 750 | data <<= 1; 751 | } 752 | else { 753 | return ERR; 754 | } 755 | } 756 | 757 | // Success 758 | results->bits = nbits; 759 | results->value = data; 760 | results->decode_type = RC5; 761 | return DECODED; 762 | } 763 | 764 | long IRrecv::decodeRC6(decode_results *results) { 765 | if (results->rawlen < MIN_RC6_SAMPLES) { 766 | return ERR; 767 | } 768 | int offset = 1; // Skip first space 769 | // Initial mark 770 | if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) { 771 | return ERR; 772 | } 773 | offset++; 774 | if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) { 775 | return ERR; 776 | } 777 | offset++; 778 | long data = 0; 779 | int used = 0; 780 | // Get start bit (1) 781 | if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return ERR; 782 | if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return ERR; 783 | int nbits; 784 | for (nbits = 0; offset < results->rawlen; nbits++) { 785 | int levelA, levelB; // Next two levels 786 | levelA = getRClevel(results, &offset, &used, RC6_T1); 787 | if (nbits == 3) { 788 | // T bit is double wide; make sure second half matches 789 | if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return ERR; 790 | } 791 | levelB = getRClevel(results, &offset, &used, RC6_T1); 792 | if (nbits == 3) { 793 | // T bit is double wide; make sure second half matches 794 | if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return ERR; 795 | } 796 | if (levelA == MARK && levelB == SPACE) { // reversed compared to RC5 797 | // 1 bit 798 | data = (data << 1) | 1; 799 | } 800 | else if (levelA == SPACE && levelB == MARK) { 801 | // zero bit 802 | data <<= 1; 803 | } 804 | else { 805 | return ERR; // Error 806 | } 807 | } 808 | // Success 809 | results->bits = nbits; 810 | results->value = data; 811 | results->decode_type = RC6; 812 | return DECODED; 813 | } 814 | long IRrecv::decodePanasonic(decode_results *results) { 815 | unsigned long long data = 0; 816 | int offset = 1; 817 | 818 | if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_MARK)) { 819 | return ERR; 820 | } 821 | offset++; 822 | if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_SPACE)) { 823 | return ERR; 824 | } 825 | offset++; 826 | 827 | // decode address 828 | for (int i = 0; i < PANASONIC_BITS; i++) { 829 | if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_BIT_MARK)) { 830 | return ERR; 831 | } 832 | if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ONE_SPACE)) { 833 | data = (data << 1) | 1; 834 | } else if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ZERO_SPACE)) { 835 | data <<= 1; 836 | } else { 837 | return ERR; 838 | } 839 | offset++; 840 | } 841 | results->value = (unsigned long)data; 842 | results->panasonicAddress = (unsigned int)(data >> 32); 843 | results->decode_type = PANASONIC; 844 | results->bits = PANASONIC_BITS; 845 | return DECODED; 846 | } 847 | long IRrecv::decodeJVC(decode_results *results) { 848 | long data = 0; 849 | int offset = 1; // Skip first space 850 | // Check for repeat 851 | if (irparams.rawlen - 1 == 33 && 852 | MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK) && 853 | MATCH_MARK(results->rawbuf[irparams.rawlen-1], JVC_BIT_MARK)) { 854 | results->bits = 0; 855 | results->value = REPEAT; 856 | results->decode_type = JVC; 857 | return DECODED; 858 | } 859 | // Initial mark 860 | if (!MATCH_MARK(results->rawbuf[offset], JVC_HDR_MARK)) { 861 | return ERR; 862 | } 863 | offset++; 864 | if (irparams.rawlen < 2 * JVC_BITS + 1 ) { 865 | return ERR; 866 | } 867 | // Initial space 868 | if (!MATCH_SPACE(results->rawbuf[offset], JVC_HDR_SPACE)) { 869 | return ERR; 870 | } 871 | offset++; 872 | for (int i = 0; i < JVC_BITS; i++) { 873 | if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)) { 874 | return ERR; 875 | } 876 | offset++; 877 | if (MATCH_SPACE(results->rawbuf[offset], JVC_ONE_SPACE)) { 878 | data = (data << 1) | 1; 879 | } 880 | else if (MATCH_SPACE(results->rawbuf[offset], JVC_ZERO_SPACE)) { 881 | data <<= 1; 882 | } 883 | else { 884 | return ERR; 885 | } 886 | offset++; 887 | } 888 | //Stop bit 889 | if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)){ 890 | return ERR; 891 | } 892 | // Success 893 | results->bits = JVC_BITS; 894 | results->value = data; 895 | results->decode_type = JVC; 896 | return DECODED; 897 | } 898 | 899 | /* ----------------------------------------------------------------------- 900 | * hashdecode - decode an arbitrary IR code. 901 | * Instead of decoding using a standard encoding scheme 902 | * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value. 903 | * 904 | * The algorithm: look at the sequence of MARK signals, and see if each one 905 | * is shorter (0), the same length (1), or longer (2) than the previous. 906 | * Do the same with the SPACE signals. Hszh the resulting sequence of 0's, 907 | * 1's, and 2's to a 32-bit value. This will give a unique value for each 908 | * different code (probably), for most code systems. 909 | * 910 | * http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html 911 | */ 912 | 913 | // Compare two tick values, returning 0 if newval is shorter, 914 | // 1 if newval is equal, and 2 if newval is longer 915 | // Use a tolerance of 20% 916 | int IRrecv::compare(unsigned int oldval, unsigned int newval) { 917 | if (newval < oldval * .8) { 918 | return 0; 919 | } 920 | else if (oldval < newval * .8) { 921 | return 2; 922 | } 923 | else { 924 | return 1; 925 | } 926 | } 927 | 928 | // Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param 929 | #define FNV_PRIME_32 16777619 930 | #define FNV_BASIS_32 2166136261 931 | 932 | /* Converts the raw code values into a 32-bit hash code. 933 | * Hopefully this code is unique for each button. 934 | * This isn't a "real" decoding, just an arbitrary value. 935 | */ 936 | long IRrecv::decodeHash(decode_results *results) { 937 | // Require at least 6 samples to prevent triggering on noise 938 | if (results->rawlen < 6) { 939 | return ERR; 940 | } 941 | long hash = FNV_BASIS_32; 942 | for (int i = 1; i+2 < results->rawlen; i++) { 943 | int value = compare(results->rawbuf[i], results->rawbuf[i+2]); 944 | // Add value into the hash 945 | hash = (hash * FNV_PRIME_32) ^ value; 946 | } 947 | results->value = hash; 948 | results->bits = 32; 949 | results->decode_type = UNKNOWN; 950 | return DECODED; 951 | } 952 | 953 | /* Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand ) 954 | 955 | The Dish send function needs to be repeated 4 times, and the Sharp function 956 | has the necessary repeat built in because of the need to invert the signal. 957 | 958 | Sharp protocol documentation: 959 | http://www.sbprojects.com/knowledge/ir/sharp.htm 960 | 961 | Here are the LIRC files that I found that seem to match the remote codes 962 | from the oscilloscope: 963 | 964 | Sharp LCD TV: 965 | http://lirc.sourceforge.net/remotes/sharp/GA538WJSA 966 | 967 | DISH NETWORK (echostar 301): 968 | http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx 969 | 970 | For the DISH codes, only send the last for characters of the hex. 971 | i.e. use 0x1C10 instead of 0x0000000000001C10 which is listed in the 972 | linked LIRC file. 973 | */ 974 | 975 | void IRsend::sendSharp(unsigned long data, int nbits) { 976 | unsigned long invertdata = data ^ SHARP_TOGGLE_MASK; 977 | enableIROut(38); 978 | for (int i = 0; i < nbits; i++) { 979 | if (data & 0x4000) { 980 | mark(SHARP_BIT_MARK); 981 | space(SHARP_ONE_SPACE); 982 | } 983 | else { 984 | mark(SHARP_BIT_MARK); 985 | space(SHARP_ZERO_SPACE); 986 | } 987 | data <<= 1; 988 | } 989 | 990 | mark(SHARP_BIT_MARK); 991 | space(SHARP_ZERO_SPACE); 992 | delay(46); 993 | for (int i = 0; i < nbits; i++) { 994 | if (invertdata & 0x4000) { 995 | mark(SHARP_BIT_MARK); 996 | space(SHARP_ONE_SPACE); 997 | } 998 | else { 999 | mark(SHARP_BIT_MARK); 1000 | space(SHARP_ZERO_SPACE); 1001 | } 1002 | invertdata <<= 1; 1003 | } 1004 | mark(SHARP_BIT_MARK); 1005 | space(SHARP_ZERO_SPACE); 1006 | delay(46); 1007 | } 1008 | 1009 | void IRsend::sendDISH(unsigned long data, int nbits) 1010 | { 1011 | enableIROut(56); 1012 | mark(DISH_HDR_MARK); 1013 | space(DISH_HDR_SPACE); 1014 | for (int i = 0; i < nbits; i++) { 1015 | if (data & DISH_TOP_BIT) { 1016 | mark(DISH_BIT_MARK); 1017 | space(DISH_ONE_SPACE); 1018 | } 1019 | else { 1020 | mark(DISH_BIT_MARK); 1021 | space(DISH_ZERO_SPACE); 1022 | } 1023 | data <<= 1; 1024 | } 1025 | } 1026 | -------------------------------------------------------------------------------- /src/libs/IRremote/IRremote.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote 3 | * Version 0.1 July, 2009 4 | * Copyright 2009 Ken Shirriff 5 | * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com 6 | * Edited by Mitra to add new controller SANYO 7 | * 8 | * Interrupt code based on NECIRrcv by Joe Knapp 9 | * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 10 | * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 11 | * 12 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 13 | */ 14 | 15 | #ifndef IRremote_h 16 | #define IRremote_h 17 | 18 | // The following are compile-time library options. 19 | // If you change them, recompile the library. 20 | // If DEBUG is defined, a lot of debugging output will be printed during decoding. 21 | // TEST must be defined for the IRtest unittests to work. It will make some 22 | // methods virtual, which will be slightly slower, which is why it is optional. 23 | // #define DEBUG 24 | // #define TEST 25 | 26 | // Results returned from the decoder 27 | class decode_results { 28 | public: 29 | int decode_type; // NEC, SONY, RC5, UNKNOWN 30 | unsigned int panasonicAddress; // This is only used for decoding Panasonic data 31 | unsigned long value; // Decoded value 32 | int bits; // Number of bits in decoded value 33 | volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks 34 | int rawlen; // Number of records in rawbuf. 35 | }; 36 | 37 | // Values for decode_type 38 | #define NEC 1 39 | #define SONY 2 40 | #define RC5 3 41 | #define RC6 4 42 | #define DISH 5 43 | #define SHARP 6 44 | #define PANASONIC 7 45 | #define JVC 8 46 | #define SANYO 9 47 | #define MITSUBISHI 10 48 | #define UNKNOWN -1 49 | 50 | // Decoded value for NEC when a repeat code is received 51 | #define REPEAT 0xffffffff 52 | 53 | // main class for receiving IR 54 | class IRrecv 55 | { 56 | public: 57 | IRrecv(int recvpin); 58 | void blink13(int blinkflag); 59 | int decode(decode_results *results); 60 | void enableIRIn(); 61 | void resume(); 62 | private: 63 | // These are called by decode 64 | int getRClevel(decode_results *results, int *offset, int *used, int t1); 65 | long decodeNEC(decode_results *results); 66 | long decodeSony(decode_results *results); 67 | long decodeSanyo(decode_results *results); 68 | long decodeMitsubishi(decode_results *results); 69 | long decodeRC5(decode_results *results); 70 | long decodeRC6(decode_results *results); 71 | long decodePanasonic(decode_results *results); 72 | long decodeJVC(decode_results *results); 73 | long decodeHash(decode_results *results); 74 | int compare(unsigned int oldval, unsigned int newval); 75 | 76 | } 77 | ; 78 | 79 | // Only used for testing; can remove virtual for shorter code 80 | #ifdef TEST 81 | #define VIRTUAL virtual 82 | #else 83 | #define VIRTUAL 84 | #endif 85 | 86 | class IRsend 87 | { 88 | public: 89 | IRsend() {} 90 | void sendNEC(unsigned long data, int nbits); 91 | void sendSony(unsigned long data, int nbits); 92 | // Neither Sanyo nor Mitsubishi send is implemented yet 93 | // void sendSanyo(unsigned long data, int nbits); 94 | // void sendMitsubishi(unsigned long data, int nbits); 95 | void sendRaw(unsigned int buf[], int len, int hz); 96 | void sendRC5(unsigned long data, int nbits); 97 | void sendRC6(unsigned long data, int nbits); 98 | void sendDISH(unsigned long data, int nbits); 99 | void sendSharp(unsigned long data, int nbits); 100 | void sendPanasonic(unsigned int address, unsigned long data); 101 | void sendJVC(unsigned long data, int nbits, int repeat); // *Note instead of sending the REPEAT constant if you want the JVC repeat signal sent, send the original code value and change the repeat argument from 0 to 1. JVC protocol repeats by skipping the header NOT by sending a separate code value like NEC does. 102 | // private: 103 | void enableIROut(int khz); 104 | VIRTUAL void mark(int usec); 105 | VIRTUAL void space(int usec); 106 | } 107 | ; 108 | 109 | // Some useful constants 110 | 111 | #define USECPERTICK 50 // microseconds per clock interrupt tick 112 | #define RAWBUF 100 // Length of raw duration buffer 113 | 114 | // Marks tend to be 100us too long, and spaces 100us too short 115 | // when received due to sensor lag. 116 | #define MARK_EXCESS 100 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /src/libs/IRremote/IRremoteInt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote 3 | * Version 0.1 July, 2009 4 | * Copyright 2009 Ken Shirriff 5 | * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 6 | * 7 | * Modified by Paul Stoffregen to support other boards and timers 8 | * 9 | * Interrupt code based on NECIRrcv by Joe Knapp 10 | * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 11 | * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 12 | * 13 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 14 | */ 15 | 16 | #ifndef IRremoteint_h 17 | #define IRremoteint_h 18 | 19 | #if defined(ARDUINO) && ARDUINO >= 100 20 | #include 21 | #else 22 | #include 23 | #endif 24 | 25 | // define which timer to use 26 | // 27 | // Uncomment the timer you wish to use on your board. If you 28 | // are using another library which uses timer2, you have options 29 | // to switch IRremote to use a different timer. 30 | 31 | // Arduino Mega 32 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 33 | //#define IR_USE_TIMER1 // tx = pin 11 34 | #define IR_USE_TIMER2 // tx = pin 9 35 | //#define IR_USE_TIMER3 // tx = pin 5 36 | //#define IR_USE_TIMER4 // tx = pin 6 37 | //#define IR_USE_TIMER5 // tx = pin 46 38 | 39 | // Teensy 1.0 40 | #elif defined(__AVR_AT90USB162__) 41 | #define IR_USE_TIMER1 // tx = pin 17 42 | 43 | // Teensy 2.0 44 | #elif defined(__AVR_ATmega32U4__) 45 | //#define IR_USE_TIMER1 // tx = pin 14 46 | //#define IR_USE_TIMER3 // tx = pin 9 47 | #define IR_USE_TIMER4_HS // tx = pin 10 48 | 49 | // Teensy 3.0 50 | #elif defined(__MK20DX128__) 51 | #define IR_USE_TIMER_CMT // tx = pin 5 52 | 53 | // Teensy++ 1.0 & 2.0 54 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 55 | //#define IR_USE_TIMER1 // tx = pin 25 56 | #define IR_USE_TIMER2 // tx = pin 1 57 | //#define IR_USE_TIMER3 // tx = pin 16 58 | 59 | // Sanguino 60 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 61 | //#define IR_USE_TIMER1 // tx = pin 13 62 | #define IR_USE_TIMER2 // tx = pin 14 63 | 64 | // Atmega8 65 | #elif defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__) 66 | #define IR_USE_TIMER1 // tx = pin 9 67 | 68 | // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc 69 | #else 70 | //#define IR_USE_TIMER1 // tx = pin 9 71 | #define IR_USE_TIMER2 // tx = pin 3 72 | #endif 73 | 74 | 75 | 76 | #ifdef F_CPU 77 | #define SYSCLOCK F_CPU // main Arduino clock 78 | #else 79 | #define SYSCLOCK 16000000 // main Arduino clock 80 | #endif 81 | 82 | #define ERR 0 83 | #define DECODED 1 84 | 85 | 86 | // defines for setting and clearing register bits 87 | #ifndef cbi 88 | #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 89 | #endif 90 | #ifndef sbi 91 | #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 92 | #endif 93 | 94 | // Pulse parms are *50-100 for the Mark and *50+100 for the space 95 | // First MARK is the one after the long gap 96 | // pulse parameters in usec 97 | #define NEC_HDR_MARK 9000 98 | #define NEC_HDR_SPACE 4500 99 | #define NEC_BIT_MARK 560 100 | #define NEC_ONE_SPACE 1600 101 | #define NEC_ZERO_SPACE 560 102 | #define NEC_RPT_SPACE 2250 103 | 104 | #define SONY_HDR_MARK 2400 105 | #define SONY_HDR_SPACE 600 106 | #define SONY_ONE_MARK 1200 107 | #define SONY_ZERO_MARK 600 108 | #define SONY_RPT_LENGTH 45000 109 | #define SONY_DOUBLE_SPACE_USECS 500 // usually ssee 713 - not using ticks as get number wrapround 110 | 111 | // SA 8650B 112 | #define SANYO_HDR_MARK 3500 // seen range 3500 113 | #define SANYO_HDR_SPACE 950 // seen 950 114 | #define SANYO_ONE_MARK 2400 // seen 2400 115 | #define SANYO_ZERO_MARK 700 // seen 700 116 | #define SANYO_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround 117 | #define SANYO_RPT_LENGTH 45000 118 | 119 | // Mitsubishi RM 75501 120 | // 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7 121 | 122 | // #define MITSUBISHI_HDR_MARK 250 // seen range 3500 123 | #define MITSUBISHI_HDR_SPACE 350 // 7*50+100 124 | #define MITSUBISHI_ONE_MARK 1950 // 41*50-100 125 | #define MITSUBISHI_ZERO_MARK 750 // 17*50-100 126 | // #define MITSUBISHI_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround 127 | // #define MITSUBISHI_RPT_LENGTH 45000 128 | 129 | 130 | #define RC5_T1 889 131 | #define RC5_RPT_LENGTH 46000 132 | 133 | #define RC6_HDR_MARK 2666 134 | #define RC6_HDR_SPACE 889 135 | #define RC6_T1 444 136 | #define RC6_RPT_LENGTH 46000 137 | 138 | #define SHARP_BIT_MARK 245 139 | #define SHARP_ONE_SPACE 1805 140 | #define SHARP_ZERO_SPACE 795 141 | #define SHARP_GAP 600000 142 | #define SHARP_TOGGLE_MASK 0x3FF 143 | #define SHARP_RPT_SPACE 3000 144 | 145 | #define DISH_HDR_MARK 400 146 | #define DISH_HDR_SPACE 6100 147 | #define DISH_BIT_MARK 400 148 | #define DISH_ONE_SPACE 1700 149 | #define DISH_ZERO_SPACE 2800 150 | #define DISH_RPT_SPACE 6200 151 | #define DISH_TOP_BIT 0x8000 152 | 153 | #define PANASONIC_HDR_MARK 3502 154 | #define PANASONIC_HDR_SPACE 1750 155 | #define PANASONIC_BIT_MARK 502 156 | #define PANASONIC_ONE_SPACE 1244 157 | #define PANASONIC_ZERO_SPACE 400 158 | 159 | #define JVC_HDR_MARK 8000 160 | #define JVC_HDR_SPACE 4000 161 | #define JVC_BIT_MARK 600 162 | #define JVC_ONE_SPACE 1600 163 | #define JVC_ZERO_SPACE 550 164 | #define JVC_RPT_LENGTH 60000 165 | 166 | #define SHARP_BITS 15 167 | #define DISH_BITS 16 168 | 169 | #define TOLERANCE 25 // percent tolerance in measurements 170 | #define LTOL (1.0 - TOLERANCE/100.) 171 | #define UTOL (1.0 + TOLERANCE/100.) 172 | 173 | #define _GAP 5000 // Minimum map between transmissions 174 | #define GAP_TICKS (_GAP/USECPERTICK) 175 | 176 | #define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK)) 177 | #define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1)) 178 | 179 | #ifndef DEBUG 180 | int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);} 181 | int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));} 182 | int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));} 183 | // Debugging versions are in IRremote.cpp 184 | #endif 185 | 186 | // receiver states 187 | #define STATE_IDLE 2 188 | #define STATE_MARK 3 189 | #define STATE_SPACE 4 190 | #define STATE_STOP 5 191 | 192 | // information for the interrupt handler 193 | typedef struct { 194 | uint8_t recvpin; // pin for IR data from detector 195 | uint8_t rcvstate; // state machine 196 | uint8_t blinkflag; // TRUE to enable blinking of pin 13 on IR processing 197 | unsigned int timer; // state timer, counts 50uS ticks. 198 | unsigned int rawbuf[RAWBUF]; // raw data 199 | uint8_t rawlen; // counter of entries in rawbuf 200 | } 201 | irparams_t; 202 | 203 | // Defined in IRremote.cpp 204 | extern volatile irparams_t irparams; 205 | 206 | // IR detector output is active low 207 | #define MARK 0 208 | #define SPACE 1 209 | 210 | #define TOPBIT 0x80000000 211 | 212 | #define NEC_BITS 32 213 | #define SONY_BITS 12 214 | #define SANYO_BITS 12 215 | #define MITSUBISHI_BITS 16 216 | #define MIN_RC5_SAMPLES 11 217 | #define MIN_RC6_SAMPLES 1 218 | #define PANASONIC_BITS 48 219 | #define JVC_BITS 16 220 | 221 | 222 | 223 | 224 | // defines for timer2 (8 bits) 225 | #if defined(IR_USE_TIMER2) 226 | #define TIMER_RESET 227 | #define TIMER_ENABLE_PWM (TCCR2A |= _BV(COM2B1)) 228 | #define TIMER_DISABLE_PWM (TCCR2A &= ~(_BV(COM2B1))) 229 | #define TIMER_ENABLE_INTR (TIMSK2 = _BV(OCIE2A)) 230 | #define TIMER_DISABLE_INTR (TIMSK2 = 0) 231 | #define TIMER_INTR_NAME TIMER2_COMPA_vect 232 | #define TIMER_CONFIG_KHZ(val) ({ \ 233 | const uint8_t pwmval = SYSCLOCK / 2000 / (val); \ 234 | TCCR2A = _BV(WGM20); \ 235 | TCCR2B = _BV(WGM22) | _BV(CS20); \ 236 | OCR2A = pwmval; \ 237 | OCR2B = pwmval / 3; \ 238 | }) 239 | #define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000) 240 | #if (TIMER_COUNT_TOP < 256) 241 | #define TIMER_CONFIG_NORMAL() ({ \ 242 | TCCR2A = _BV(WGM21); \ 243 | TCCR2B = _BV(CS20); \ 244 | OCR2A = TIMER_COUNT_TOP; \ 245 | TCNT2 = 0; \ 246 | }) 247 | #else 248 | #define TIMER_CONFIG_NORMAL() ({ \ 249 | TCCR2A = _BV(WGM21); \ 250 | TCCR2B = _BV(CS21); \ 251 | OCR2A = TIMER_COUNT_TOP / 8; \ 252 | TCNT2 = 0; \ 253 | }) 254 | #endif 255 | #if defined(CORE_OC2B_PIN) 256 | #define TIMER_PWM_PIN CORE_OC2B_PIN /* Teensy */ 257 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 258 | #define TIMER_PWM_PIN 9 /* Arduino Mega */ 259 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 260 | #define TIMER_PWM_PIN 14 /* Sanguino */ 261 | #else 262 | #define TIMER_PWM_PIN 3 /* Arduino Duemilanove, Diecimila, LilyPad, etc */ 263 | #endif 264 | 265 | 266 | // defines for timer1 (16 bits) 267 | #elif defined(IR_USE_TIMER1) 268 | #define TIMER_RESET 269 | #define TIMER_ENABLE_PWM (TCCR1A |= _BV(COM1A1)) 270 | #define TIMER_DISABLE_PWM (TCCR1A &= ~(_BV(COM1A1))) 271 | #if defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__) 272 | #define TIMER_ENABLE_INTR (TIMSK = _BV(OCIE1A)) 273 | #define TIMER_DISABLE_INTR (TIMSK = 0) 274 | #else 275 | #define TIMER_ENABLE_INTR (TIMSK1 = _BV(OCIE1A)) 276 | #define TIMER_DISABLE_INTR (TIMSK1 = 0) 277 | #endif 278 | #define TIMER_INTR_NAME TIMER1_COMPA_vect 279 | #define TIMER_CONFIG_KHZ(val) ({ \ 280 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 281 | TCCR1A = _BV(WGM11); \ 282 | TCCR1B = _BV(WGM13) | _BV(CS10); \ 283 | ICR1 = pwmval; \ 284 | OCR1A = pwmval / 3; \ 285 | }) 286 | #define TIMER_CONFIG_NORMAL() ({ \ 287 | TCCR1A = 0; \ 288 | TCCR1B = _BV(WGM12) | _BV(CS10); \ 289 | OCR1A = SYSCLOCK * USECPERTICK / 1000000; \ 290 | TCNT1 = 0; \ 291 | }) 292 | #if defined(CORE_OC1A_PIN) 293 | #define TIMER_PWM_PIN CORE_OC1A_PIN /* Teensy */ 294 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 295 | #define TIMER_PWM_PIN 11 /* Arduino Mega */ 296 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 297 | #define TIMER_PWM_PIN 13 /* Sanguino */ 298 | #else 299 | #define TIMER_PWM_PIN 9 /* Arduino Duemilanove, Diecimila, LilyPad, etc */ 300 | #endif 301 | 302 | 303 | // defines for timer3 (16 bits) 304 | #elif defined(IR_USE_TIMER3) 305 | #define TIMER_RESET 306 | #define TIMER_ENABLE_PWM (TCCR3A |= _BV(COM3A1)) 307 | #define TIMER_DISABLE_PWM (TCCR3A &= ~(_BV(COM3A1))) 308 | #define TIMER_ENABLE_INTR (TIMSK3 = _BV(OCIE3A)) 309 | #define TIMER_DISABLE_INTR (TIMSK3 = 0) 310 | #define TIMER_INTR_NAME TIMER3_COMPA_vect 311 | #define TIMER_CONFIG_KHZ(val) ({ \ 312 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 313 | TCCR3A = _BV(WGM31); \ 314 | TCCR3B = _BV(WGM33) | _BV(CS30); \ 315 | ICR3 = pwmval; \ 316 | OCR3A = pwmval / 3; \ 317 | }) 318 | #define TIMER_CONFIG_NORMAL() ({ \ 319 | TCCR3A = 0; \ 320 | TCCR3B = _BV(WGM32) | _BV(CS30); \ 321 | OCR3A = SYSCLOCK * USECPERTICK / 1000000; \ 322 | TCNT3 = 0; \ 323 | }) 324 | #if defined(CORE_OC3A_PIN) 325 | #define TIMER_PWM_PIN CORE_OC3A_PIN /* Teensy */ 326 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 327 | #define TIMER_PWM_PIN 5 /* Arduino Mega */ 328 | #else 329 | #error "Please add OC3A pin number here\n" 330 | #endif 331 | 332 | 333 | // defines for timer4 (10 bits, high speed option) 334 | #elif defined(IR_USE_TIMER4_HS) 335 | #define TIMER_RESET 336 | #define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1)) 337 | #define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1))) 338 | #define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4)) 339 | #define TIMER_DISABLE_INTR (TIMSK4 = 0) 340 | #define TIMER_INTR_NAME TIMER4_OVF_vect 341 | #define TIMER_CONFIG_KHZ(val) ({ \ 342 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 343 | TCCR4A = (1<> 8; \ 349 | OCR4C = pwmval; \ 350 | TC4H = (pwmval / 3) >> 8; \ 351 | OCR4A = (pwmval / 3) & 255; \ 352 | }) 353 | #define TIMER_CONFIG_NORMAL() ({ \ 354 | TCCR4A = 0; \ 355 | TCCR4B = _BV(CS40); \ 356 | TCCR4C = 0; \ 357 | TCCR4D = 0; \ 358 | TCCR4E = 0; \ 359 | TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \ 360 | OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \ 361 | TC4H = 0; \ 362 | TCNT4 = 0; \ 363 | }) 364 | #if defined(CORE_OC4A_PIN) 365 | #define TIMER_PWM_PIN CORE_OC4A_PIN /* Teensy */ 366 | #elif defined(__AVR_ATmega32U4__) 367 | #define TIMER_PWM_PIN 13 /* Leonardo */ 368 | #else 369 | #error "Please add OC4A pin number here\n" 370 | #endif 371 | 372 | 373 | // defines for timer4 (16 bits) 374 | #elif defined(IR_USE_TIMER4) 375 | #define TIMER_RESET 376 | #define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1)) 377 | #define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1))) 378 | #define TIMER_ENABLE_INTR (TIMSK4 = _BV(OCIE4A)) 379 | #define TIMER_DISABLE_INTR (TIMSK4 = 0) 380 | #define TIMER_INTR_NAME TIMER4_COMPA_vect 381 | #define TIMER_CONFIG_KHZ(val) ({ \ 382 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 383 | TCCR4A = _BV(WGM41); \ 384 | TCCR4B = _BV(WGM43) | _BV(CS40); \ 385 | ICR4 = pwmval; \ 386 | OCR4A = pwmval / 3; \ 387 | }) 388 | #define TIMER_CONFIG_NORMAL() ({ \ 389 | TCCR4A = 0; \ 390 | TCCR4B = _BV(WGM42) | _BV(CS40); \ 391 | OCR4A = SYSCLOCK * USECPERTICK / 1000000; \ 392 | TCNT4 = 0; \ 393 | }) 394 | #if defined(CORE_OC4A_PIN) 395 | #define TIMER_PWM_PIN CORE_OC4A_PIN 396 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 397 | #define TIMER_PWM_PIN 6 /* Arduino Mega */ 398 | #else 399 | #error "Please add OC4A pin number here\n" 400 | #endif 401 | 402 | 403 | // defines for timer5 (16 bits) 404 | #elif defined(IR_USE_TIMER5) 405 | #define TIMER_RESET 406 | #define TIMER_ENABLE_PWM (TCCR5A |= _BV(COM5A1)) 407 | #define TIMER_DISABLE_PWM (TCCR5A &= ~(_BV(COM5A1))) 408 | #define TIMER_ENABLE_INTR (TIMSK5 = _BV(OCIE5A)) 409 | #define TIMER_DISABLE_INTR (TIMSK5 = 0) 410 | #define TIMER_INTR_NAME TIMER5_COMPA_vect 411 | #define TIMER_CONFIG_KHZ(val) ({ \ 412 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 413 | TCCR5A = _BV(WGM51); \ 414 | TCCR5B = _BV(WGM53) | _BV(CS50); \ 415 | ICR5 = pwmval; \ 416 | OCR5A = pwmval / 3; \ 417 | }) 418 | #define TIMER_CONFIG_NORMAL() ({ \ 419 | TCCR5A = 0; \ 420 | TCCR5B = _BV(WGM52) | _BV(CS50); \ 421 | OCR5A = SYSCLOCK * USECPERTICK / 1000000; \ 422 | TCNT5 = 0; \ 423 | }) 424 | #if defined(CORE_OC5A_PIN) 425 | #define TIMER_PWM_PIN CORE_OC5A_PIN 426 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 427 | #define TIMER_PWM_PIN 46 /* Arduino Mega */ 428 | #else 429 | #error "Please add OC5A pin number here\n" 430 | #endif 431 | 432 | 433 | // defines for special carrier modulator timer 434 | #elif defined(IR_USE_TIMER_CMT) 435 | #define TIMER_RESET ({ \ 436 | uint8_t tmp = CMT_MSC; \ 437 | CMT_CMD2 = 30; \ 438 | }) 439 | #define TIMER_ENABLE_PWM CORE_PIN5_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_DSE|PORT_PCR_SRE 440 | #define TIMER_DISABLE_PWM CORE_PIN5_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_DSE|PORT_PCR_SRE 441 | #define TIMER_ENABLE_INTR NVIC_ENABLE_IRQ(IRQ_CMT) 442 | #define TIMER_DISABLE_INTR NVIC_DISABLE_IRQ(IRQ_CMT) 443 | #define TIMER_INTR_NAME cmt_isr 444 | #ifdef ISR 445 | #undef ISR 446 | #endif 447 | #define ISR(f) void f(void) 448 | #if F_BUS == 48000000 449 | #define CMT_PPS_VAL 5 450 | #else 451 | #define CMT_PPS_VAL 2 452 | #endif 453 | #define TIMER_CONFIG_KHZ(val) ({ \ 454 | SIM_SCGC4 |= SIM_SCGC4_CMT; \ 455 | SIM_SOPT2 |= SIM_SOPT2_PTD7PAD; \ 456 | CMT_PPS = CMT_PPS_VAL; \ 457 | CMT_CGH1 = 2667 / val; \ 458 | CMT_CGL1 = 5333 / val; \ 459 | CMT_CMD1 = 0; \ 460 | CMT_CMD2 = 30; \ 461 | CMT_CMD3 = 0; \ 462 | CMT_CMD4 = 0; \ 463 | CMT_OC = 0x60; \ 464 | CMT_MSC = 0x01; \ 465 | }) 466 | #define TIMER_CONFIG_NORMAL() ({ \ 467 | SIM_SCGC4 |= SIM_SCGC4_CMT; \ 468 | CMT_PPS = CMT_PPS_VAL; \ 469 | CMT_CGH1 = 1; \ 470 | CMT_CGL1 = 1; \ 471 | CMT_CMD1 = 0; \ 472 | CMT_CMD2 = 30; \ 473 | CMT_CMD3 = 0; \ 474 | CMT_CMD4 = 19; \ 475 | CMT_OC = 0; \ 476 | CMT_MSC = 0x03; \ 477 | }) 478 | #define TIMER_PWM_PIN 5 479 | 480 | 481 | #else // unknown timer 482 | #error "Internal code configuration error, no known IR_USE_TIMER# defined\n" 483 | #endif 484 | 485 | 486 | // defines for blinking the LED 487 | #if defined(CORE_LED0_PIN) 488 | #define BLINKLED CORE_LED0_PIN 489 | #define BLINKLED_ON() (digitalWrite(CORE_LED0_PIN, HIGH)) 490 | #define BLINKLED_OFF() (digitalWrite(CORE_LED0_PIN, LOW)) 491 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 492 | #define BLINKLED 13 493 | #define BLINKLED_ON() (PORTB |= B10000000) 494 | #define BLINKLED_OFF() (PORTB &= B01111111) 495 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 496 | #define BLINKLED 0 497 | #define BLINKLED_ON() (PORTD |= B00000001) 498 | #define BLINKLED_OFF() (PORTD &= B11111110) 499 | #else 500 | #define BLINKLED 13 501 | #define BLINKLED_ON() (PORTB |= B00100000) 502 | #define BLINKLED_OFF() (PORTB &= B11011111) 503 | #endif 504 | 505 | #endif 506 | -------------------------------------------------------------------------------- /src/libs/IRremote/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | GNU LESSER GENERAL PUBLIC LICENSE 3 | Version 2.1, February 1999 4 | 5 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 6 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | [This is the first released version of the Lesser GPL. It also counts 11 | as the successor of the GNU Library Public License, version 2, hence 12 | the version number 2.1.] 13 | 14 | Preamble 15 | 16 | The licenses for most software are designed to take away your 17 | freedom to share and change it. By contrast, the GNU General Public 18 | Licenses are intended to guarantee your freedom to share and change 19 | free software--to make sure the software is free for all its users. 20 | 21 | This license, the Lesser General Public License, applies to some 22 | specially designated software packages--typically libraries--of the 23 | Free Software Foundation and other authors who decide to use it. You 24 | can use it too, but we suggest you first think carefully about whether 25 | this license or the ordinary General Public License is the better 26 | strategy to use in any particular case, based on the explanations below. 27 | 28 | When we speak of free software, we are referring to freedom of use, 29 | not price. Our General Public Licenses are designed to make sure that 30 | you have the freedom to distribute copies of free software (and charge 31 | for this service if you wish); that you receive source code or can get 32 | it if you want it; that you can change the software and use pieces of 33 | it in new free programs; and that you are informed that you can do 34 | these things. 35 | 36 | To protect your rights, we need to make restrictions that forbid 37 | distributors to deny you these rights or to ask you to surrender these 38 | rights. These restrictions translate to certain responsibilities for 39 | you if you distribute copies of the library or if you modify it. 40 | 41 | For example, if you distribute copies of the library, whether gratis 42 | or for a fee, you must give the recipients all the rights that we gave 43 | you. You must make sure that they, too, receive or can get the source 44 | code. If you link other code with the library, you must provide 45 | complete object files to the recipients, so that they can relink them 46 | with the library after making changes to the library and recompiling 47 | it. And you must show them these terms so they know their rights. 48 | 49 | We protect your rights with a two-step method: (1) we copyright the 50 | library, and (2) we offer you this license, which gives you legal 51 | permission to copy, distribute and/or modify the library. 52 | 53 | To protect each distributor, we want to make it very clear that 54 | there is no warranty for the free library. Also, if the library is 55 | modified by someone else and passed on, the recipients should know 56 | that what they have is not the original version, so that the original 57 | author's reputation will not be affected by problems that might be 58 | introduced by others. 59 | 60 | Finally, software patents pose a constant threat to the existence of 61 | any free program. We wish to make sure that a company cannot 62 | effectively restrict the users of a free program by obtaining a 63 | restrictive license from a patent holder. Therefore, we insist that 64 | any patent license obtained for a version of the library must be 65 | consistent with the full freedom of use specified in this license. 66 | 67 | Most GNU software, including some libraries, is covered by the 68 | ordinary GNU General Public License. This license, the GNU Lesser 69 | General Public License, applies to certain designated libraries, and 70 | is quite different from the ordinary General Public License. We use 71 | this license for certain libraries in order to permit linking those 72 | libraries into non-free programs. 73 | 74 | When a program is linked with a library, whether statically or using 75 | a shared library, the combination of the two is legally speaking a 76 | combined work, a derivative of the original library. The ordinary 77 | General Public License therefore permits such linking only if the 78 | entire combination fits its criteria of freedom. The Lesser General 79 | Public License permits more lax criteria for linking other code with 80 | the library. 81 | 82 | We call this license the "Lesser" General Public License because it 83 | does Less to protect the user's freedom than the ordinary General 84 | Public License. It also provides other free software developers Less 85 | of an advantage over competing non-free programs. These disadvantages 86 | are the reason we use the ordinary General Public License for many 87 | libraries. However, the Lesser license provides advantages in certain 88 | special circumstances. 89 | 90 | For example, on rare occasions, there may be a special need to 91 | encourage the widest possible use of a certain library, so that it becomes 92 | a de-facto standard. To achieve this, non-free programs must be 93 | allowed to use the library. A more frequent case is that a free 94 | library does the same job as widely used non-free libraries. In this 95 | case, there is little to gain by limiting the free library to free 96 | software only, so we use the Lesser General Public License. 97 | 98 | In other cases, permission to use a particular library in non-free 99 | programs enables a greater number of people to use a large body of 100 | free software. For example, permission to use the GNU C Library in 101 | non-free programs enables many more people to use the whole GNU 102 | operating system, as well as its variant, the GNU/Linux operating 103 | system. 104 | 105 | Although the Lesser General Public License is Less protective of the 106 | users' freedom, it does ensure that the user of a program that is 107 | linked with the Library has the freedom and the wherewithal to run 108 | that program using a modified version of the Library. 109 | 110 | The precise terms and conditions for copying, distribution and 111 | modification follow. Pay close attention to the difference between a 112 | "work based on the library" and a "work that uses the library". The 113 | former contains code derived from the library, whereas the latter must 114 | be combined with the library in order to run. 115 | 116 | GNU LESSER GENERAL PUBLIC LICENSE 117 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 118 | 119 | 0. This License Agreement applies to any software library or other 120 | program which contains a notice placed by the copyright holder or 121 | other authorized party saying it may be distributed under the terms of 122 | this Lesser General Public License (also called "this License"). 123 | Each licensee is addressed as "you". 124 | 125 | A "library" means a collection of software functions and/or data 126 | prepared so as to be conveniently linked with application programs 127 | (which use some of those functions and data) to form executables. 128 | 129 | The "Library", below, refers to any such software library or work 130 | which has been distributed under these terms. A "work based on the 131 | Library" means either the Library or any derivative work under 132 | copyright law: that is to say, a work containing the Library or a 133 | portion of it, either verbatim or with modifications and/or translated 134 | straightforwardly into another language. (Hereinafter, translation is 135 | included without limitation in the term "modification".) 136 | 137 | "Source code" for a work means the preferred form of the work for 138 | making modifications to it. For a library, complete source code means 139 | all the source code for all modules it contains, plus any associated 140 | interface definition files, plus the scripts used to control compilation 141 | and installation of the library. 142 | 143 | Activities other than copying, distribution and modification are not 144 | covered by this License; they are outside its scope. The act of 145 | running a program using the Library is not restricted, and output from 146 | such a program is covered only if its contents constitute a work based 147 | on the Library (independent of the use of the Library in a tool for 148 | writing it). Whether that is true depends on what the Library does 149 | and what the program that uses the Library does. 150 | 151 | 1. You may copy and distribute verbatim copies of the Library's 152 | complete source code as you receive it, in any medium, provided that 153 | you conspicuously and appropriately publish on each copy an 154 | appropriate copyright notice and disclaimer of warranty; keep intact 155 | all the notices that refer to this License and to the absence of any 156 | warranty; and distribute a copy of this License along with the 157 | Library. 158 | 159 | You may charge a fee for the physical act of transferring a copy, 160 | and you may at your option offer warranty protection in exchange for a 161 | fee. 162 | 163 | 2. You may modify your copy or copies of the Library or any portion 164 | of it, thus forming a work based on the Library, and copy and 165 | distribute such modifications or work under the terms of Section 1 166 | above, provided that you also meet all of these conditions: 167 | 168 | a) The modified work must itself be a software library. 169 | 170 | b) You must cause the files modified to carry prominent notices 171 | stating that you changed the files and the date of any change. 172 | 173 | c) You must cause the whole of the work to be licensed at no 174 | charge to all third parties under the terms of this License. 175 | 176 | d) If a facility in the modified Library refers to a function or a 177 | table of data to be supplied by an application program that uses 178 | the facility, other than as an argument passed when the facility 179 | is invoked, then you must make a good faith effort to ensure that, 180 | in the event an application does not supply such function or 181 | table, the facility still operates, and performs whatever part of 182 | its purpose remains meaningful. 183 | 184 | (For example, a function in a library to compute square roots has 185 | a purpose that is entirely well-defined independent of the 186 | application. Therefore, Subsection 2d requires that any 187 | application-supplied function or table used by this function must 188 | be optional: if the application does not supply it, the square 189 | root function must still compute square roots.) 190 | 191 | These requirements apply to the modified work as a whole. If 192 | identifiable sections of that work are not derived from the Library, 193 | and can be reasonably considered independent and separate works in 194 | themselves, then this License, and its terms, do not apply to those 195 | sections when you distribute them as separate works. But when you 196 | distribute the same sections as part of a whole which is a work based 197 | on the Library, the distribution of the whole must be on the terms of 198 | this License, whose permissions for other licensees extend to the 199 | entire whole, and thus to each and every part regardless of who wrote 200 | it. 201 | 202 | Thus, it is not the intent of this section to claim rights or contest 203 | your rights to work written entirely by you; rather, the intent is to 204 | exercise the right to control the distribution of derivative or 205 | collective works based on the Library. 206 | 207 | In addition, mere aggregation of another work not based on the Library 208 | with the Library (or with a work based on the Library) on a volume of 209 | a storage or distribution medium does not bring the other work under 210 | the scope of this License. 211 | 212 | 3. You may opt to apply the terms of the ordinary GNU General Public 213 | License instead of this License to a given copy of the Library. To do 214 | this, you must alter all the notices that refer to this License, so 215 | that they refer to the ordinary GNU General Public License, version 2, 216 | instead of to this License. (If a newer version than version 2 of the 217 | ordinary GNU General Public License has appeared, then you can specify 218 | that version instead if you wish.) Do not make any other change in 219 | these notices. 220 | 221 | Once this change is made in a given copy, it is irreversible for 222 | that copy, so the ordinary GNU General Public License applies to all 223 | subsequent copies and derivative works made from that copy. 224 | 225 | This option is useful when you wish to copy part of the code of 226 | the Library into a program that is not a library. 227 | 228 | 4. You may copy and distribute the Library (or a portion or 229 | derivative of it, under Section 2) in object code or executable form 230 | under the terms of Sections 1 and 2 above provided that you accompany 231 | it with the complete corresponding machine-readable source code, which 232 | must be distributed under the terms of Sections 1 and 2 above on a 233 | medium customarily used for software interchange. 234 | 235 | If distribution of object code is made by offering access to copy 236 | from a designated place, then offering equivalent access to copy the 237 | source code from the same place satisfies the requirement to 238 | distribute the source code, even though third parties are not 239 | compelled to copy the source along with the object code. 240 | 241 | 5. A program that contains no derivative of any portion of the 242 | Library, but is designed to work with the Library by being compiled or 243 | linked with it, is called a "work that uses the Library". Such a 244 | work, in isolation, is not a derivative work of the Library, and 245 | therefore falls outside the scope of this License. 246 | 247 | However, linking a "work that uses the Library" with the Library 248 | creates an executable that is a derivative of the Library (because it 249 | contains portions of the Library), rather than a "work that uses the 250 | library". The executable is therefore covered by this License. 251 | Section 6 states terms for distribution of such executables. 252 | 253 | When a "work that uses the Library" uses material from a header file 254 | that is part of the Library, the object code for the work may be a 255 | derivative work of the Library even though the source code is not. 256 | Whether this is true is especially significant if the work can be 257 | linked without the Library, or if the work is itself a library. The 258 | threshold for this to be true is not precisely defined by law. 259 | 260 | If such an object file uses only numerical parameters, data 261 | structure layouts and accessors, and small macros and small inline 262 | functions (ten lines or less in length), then the use of the object 263 | file is unrestricted, regardless of whether it is legally a derivative 264 | work. (Executables containing this object code plus portions of the 265 | Library will still fall under Section 6.) 266 | 267 | Otherwise, if the work is a derivative of the Library, you may 268 | distribute the object code for the work under the terms of Section 6. 269 | Any executables containing that work also fall under Section 6, 270 | whether or not they are linked directly with the Library itself. 271 | 272 | 6. As an exception to the Sections above, you may also combine or 273 | link a "work that uses the Library" with the Library to produce a 274 | work containing portions of the Library, and distribute that work 275 | under terms of your choice, provided that the terms permit 276 | modification of the work for the customer's own use and reverse 277 | engineering for debugging such modifications. 278 | 279 | You must give prominent notice with each copy of the work that the 280 | Library is used in it and that the Library and its use are covered by 281 | this License. You must supply a copy of this License. If the work 282 | during execution displays copyright notices, you must include the 283 | copyright notice for the Library among them, as well as a reference 284 | directing the user to the copy of this License. Also, you must do one 285 | of these things: 286 | 287 | a) Accompany the work with the complete corresponding 288 | machine-readable source code for the Library including whatever 289 | changes were used in the work (which must be distributed under 290 | Sections 1 and 2 above); and, if the work is an executable linked 291 | with the Library, with the complete machine-readable "work that 292 | uses the Library", as object code and/or source code, so that the 293 | user can modify the Library and then relink to produce a modified 294 | executable containing the modified Library. (It is understood 295 | that the user who changes the contents of definitions files in the 296 | Library will not necessarily be able to recompile the application 297 | to use the modified definitions.) 298 | 299 | b) Use a suitable shared library mechanism for linking with the 300 | Library. A suitable mechanism is one that (1) uses at run time a 301 | copy of the library already present on the user's computer system, 302 | rather than copying library functions into the executable, and (2) 303 | will operate properly with a modified version of the library, if 304 | the user installs one, as long as the modified version is 305 | interface-compatible with the version that the work was made with. 306 | 307 | c) Accompany the work with a written offer, valid for at 308 | least three years, to give the same user the materials 309 | specified in Subsection 6a, above, for a charge no more 310 | than the cost of performing this distribution. 311 | 312 | d) If distribution of the work is made by offering access to copy 313 | from a designated place, offer equivalent access to copy the above 314 | specified materials from the same place. 315 | 316 | e) Verify that the user has already received a copy of these 317 | materials or that you have already sent this user a copy. 318 | 319 | For an executable, the required form of the "work that uses the 320 | Library" must include any data and utility programs needed for 321 | reproducing the executable from it. However, as a special exception, 322 | the materials to be distributed need not include anything that is 323 | normally distributed (in either source or binary form) with the major 324 | components (compiler, kernel, and so on) of the operating system on 325 | which the executable runs, unless that component itself accompanies 326 | the executable. 327 | 328 | It may happen that this requirement contradicts the license 329 | restrictions of other proprietary libraries that do not normally 330 | accompany the operating system. Such a contradiction means you cannot 331 | use both them and the Library together in an executable that you 332 | distribute. 333 | 334 | 7. You may place library facilities that are a work based on the 335 | Library side-by-side in a single library together with other library 336 | facilities not covered by this License, and distribute such a combined 337 | library, provided that the separate distribution of the work based on 338 | the Library and of the other library facilities is otherwise 339 | permitted, and provided that you do these two things: 340 | 341 | a) Accompany the combined library with a copy of the same work 342 | based on the Library, uncombined with any other library 343 | facilities. This must be distributed under the terms of the 344 | Sections above. 345 | 346 | b) Give prominent notice with the combined library of the fact 347 | that part of it is a work based on the Library, and explaining 348 | where to find the accompanying uncombined form of the same work. 349 | 350 | 8. You may not copy, modify, sublicense, link with, or distribute 351 | the Library except as expressly provided under this License. Any 352 | attempt otherwise to copy, modify, sublicense, link with, or 353 | distribute the Library is void, and will automatically terminate your 354 | rights under this License. However, parties who have received copies, 355 | or rights, from you under this License will not have their licenses 356 | terminated so long as such parties remain in full compliance. 357 | 358 | 9. You are not required to accept this License, since you have not 359 | signed it. However, nothing else grants you permission to modify or 360 | distribute the Library or its derivative works. These actions are 361 | prohibited by law if you do not accept this License. Therefore, by 362 | modifying or distributing the Library (or any work based on the 363 | Library), you indicate your acceptance of this License to do so, and 364 | all its terms and conditions for copying, distributing or modifying 365 | the Library or works based on it. 366 | 367 | 10. Each time you redistribute the Library (or any work based on the 368 | Library), the recipient automatically receives a license from the 369 | original licensor to copy, distribute, link with or modify the Library 370 | subject to these terms and conditions. You may not impose any further 371 | restrictions on the recipients' exercise of the rights granted herein. 372 | You are not responsible for enforcing compliance by third parties with 373 | this License. 374 | 375 | 11. If, as a consequence of a court judgment or allegation of patent 376 | infringement or for any other reason (not limited to patent issues), 377 | conditions are imposed on you (whether by court order, agreement or 378 | otherwise) that contradict the conditions of this License, they do not 379 | excuse you from the conditions of this License. If you cannot 380 | distribute so as to satisfy simultaneously your obligations under this 381 | License and any other pertinent obligations, then as a consequence you 382 | may not distribute the Library at all. For example, if a patent 383 | license would not permit royalty-free redistribution of the Library by 384 | all those who receive copies directly or indirectly through you, then 385 | the only way you could satisfy both it and this License would be to 386 | refrain entirely from distribution of the Library. 387 | 388 | If any portion of this section is held invalid or unenforceable under any 389 | particular circumstance, the balance of the section is intended to apply, 390 | and the section as a whole is intended to apply in other circumstances. 391 | 392 | It is not the purpose of this section to induce you to infringe any 393 | patents or other property right claims or to contest validity of any 394 | such claims; this section has the sole purpose of protecting the 395 | integrity of the free software distribution system which is 396 | implemented by public license practices. Many people have made 397 | generous contributions to the wide range of software distributed 398 | through that system in reliance on consistent application of that 399 | system; it is up to the author/donor to decide if he or she is willing 400 | to distribute software through any other system and a licensee cannot 401 | impose that choice. 402 | 403 | This section is intended to make thoroughly clear what is believed to 404 | be a consequence of the rest of this License. 405 | 406 | 12. If the distribution and/or use of the Library is restricted in 407 | certain countries either by patents or by copyrighted interfaces, the 408 | original copyright holder who places the Library under this License may add 409 | an explicit geographical distribution limitation excluding those countries, 410 | so that distribution is permitted only in or among countries not thus 411 | excluded. In such case, this License incorporates the limitation as if 412 | written in the body of this License. 413 | 414 | 13. The Free Software Foundation may publish revised and/or new 415 | versions of the Lesser General Public License from time to time. 416 | Such new versions will be similar in spirit to the present version, 417 | but may differ in detail to address new problems or concerns. 418 | 419 | Each version is given a distinguishing version number. If the Library 420 | specifies a version number of this License which applies to it and 421 | "any later version", you have the option of following the terms and 422 | conditions either of that version or of any later version published by 423 | the Free Software Foundation. If the Library does not specify a 424 | license version number, you may choose any version ever published by 425 | the Free Software Foundation. 426 | 427 | 14. If you wish to incorporate parts of the Library into other free 428 | programs whose distribution conditions are incompatible with these, 429 | write to the author to ask for permission. For software which is 430 | copyrighted by the Free Software Foundation, write to the Free 431 | Software Foundation; we sometimes make exceptions for this. Our 432 | decision will be guided by the two goals of preserving the free status 433 | of all derivatives of our free software and of promoting the sharing 434 | and reuse of software generally. 435 | 436 | NO WARRANTY 437 | 438 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 439 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 440 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 441 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 442 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 443 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 444 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 445 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 446 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 447 | 448 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 449 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 450 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 451 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 452 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 453 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 454 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 455 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 456 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 457 | DAMAGES. 458 | 459 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/IRrecord/IRrecord.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRrecord: record and play back IR signals as a minimal 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * An IR LED must be connected to the output PWM pin 3. 5 | * A button must be connected to the input BUTTON_PIN; this is the 6 | * send button. 7 | * A visible LED can be connected to STATUS_PIN to provide status. 8 | * 9 | * The logic is: 10 | * If the button is pressed, send the IR code. 11 | * If an IR code is received, record it. 12 | * 13 | * Version 0.11 September, 2009 14 | * Copyright 2009 Ken Shirriff 15 | * http://arcfn.com 16 | */ 17 | 18 | #include 19 | 20 | int RECV_PIN = 11; 21 | int BUTTON_PIN = 12; 22 | int STATUS_PIN = 13; 23 | 24 | IRrecv irrecv(RECV_PIN); 25 | IRsend irsend; 26 | 27 | decode_results results; 28 | 29 | void setup() 30 | { 31 | Serial.begin(9600); 32 | irrecv.enableIRIn(); // Start the receiver 33 | pinMode(BUTTON_PIN, INPUT); 34 | pinMode(STATUS_PIN, OUTPUT); 35 | } 36 | 37 | // Storage for the recorded code 38 | int codeType = -1; // The type of code 39 | unsigned long codeValue; // The code value if not raw 40 | unsigned int rawCodes[RAWBUF]; // The durations if raw 41 | int codeLen; // The length of the code 42 | int toggle = 0; // The RC5/6 toggle state 43 | 44 | // Stores the code for later playback 45 | // Most of this code is just logging 46 | void storeCode(decode_results *results) { 47 | codeType = results->decode_type; 48 | int count = results->rawlen; 49 | if (codeType == UNKNOWN) { 50 | Serial.println("Received unknown code, saving as raw"); 51 | codeLen = results->rawlen - 1; 52 | // To store raw codes: 53 | // Drop first value (gap) 54 | // Convert from ticks to microseconds 55 | // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion 56 | for (int i = 1; i <= codeLen; i++) { 57 | if (i % 2) { 58 | // Mark 59 | rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS; 60 | Serial.print(" m"); 61 | } 62 | else { 63 | // Space 64 | rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS; 65 | Serial.print(" s"); 66 | } 67 | Serial.print(rawCodes[i - 1], DEC); 68 | } 69 | Serial.println(""); 70 | } 71 | else { 72 | if (codeType == NEC) { 73 | Serial.print("Received NEC: "); 74 | if (results->value == REPEAT) { 75 | // Don't record a NEC repeat value as that's useless. 76 | Serial.println("repeat; ignoring."); 77 | return; 78 | } 79 | } 80 | else if (codeType == SONY) { 81 | Serial.print("Received SONY: "); 82 | } 83 | else if (codeType == RC5) { 84 | Serial.print("Received RC5: "); 85 | } 86 | else if (codeType == RC6) { 87 | Serial.print("Received RC6: "); 88 | } 89 | else { 90 | Serial.print("Unexpected codeType "); 91 | Serial.print(codeType, DEC); 92 | Serial.println(""); 93 | } 94 | Serial.println(results->value, HEX); 95 | codeValue = results->value; 96 | codeLen = results->bits; 97 | } 98 | } 99 | 100 | void sendCode(int repeat) { 101 | if (codeType == NEC) { 102 | if (repeat) { 103 | irsend.sendNEC(REPEAT, codeLen); 104 | Serial.println("Sent NEC repeat"); 105 | } 106 | else { 107 | irsend.sendNEC(codeValue, codeLen); 108 | Serial.print("Sent NEC "); 109 | Serial.println(codeValue, HEX); 110 | } 111 | } 112 | else if (codeType == SONY) { 113 | irsend.sendSony(codeValue, codeLen); 114 | Serial.print("Sent Sony "); 115 | Serial.println(codeValue, HEX); 116 | } 117 | else if (codeType == RC5 || codeType == RC6) { 118 | if (!repeat) { 119 | // Flip the toggle bit for a new button press 120 | toggle = 1 - toggle; 121 | } 122 | // Put the toggle bit into the code to send 123 | codeValue = codeValue & ~(1 << (codeLen - 1)); 124 | codeValue = codeValue | (toggle << (codeLen - 1)); 125 | if (codeType == RC5) { 126 | Serial.print("Sent RC5 "); 127 | Serial.println(codeValue, HEX); 128 | irsend.sendRC5(codeValue, codeLen); 129 | } 130 | else { 131 | irsend.sendRC6(codeValue, codeLen); 132 | Serial.print("Sent RC6 "); 133 | Serial.println(codeValue, HEX); 134 | } 135 | } 136 | else if (codeType == UNKNOWN /* i.e. raw */) { 137 | // Assume 38 KHz 138 | irsend.sendRaw(rawCodes, codeLen, 38); 139 | Serial.println("Sent raw"); 140 | } 141 | } 142 | 143 | int lastButtonState; 144 | 145 | void loop() { 146 | // If button pressed, send the code. 147 | int buttonState = digitalRead(BUTTON_PIN); 148 | if (lastButtonState == HIGH && buttonState == LOW) { 149 | Serial.println("Released"); 150 | irrecv.enableIRIn(); // Re-enable receiver 151 | } 152 | 153 | if (buttonState) { 154 | Serial.println("Pressed, sending"); 155 | digitalWrite(STATUS_PIN, HIGH); 156 | sendCode(lastButtonState == buttonState); 157 | digitalWrite(STATUS_PIN, LOW); 158 | delay(50); // Wait a bit between retransmissions 159 | } 160 | else if (irrecv.decode(&results)) { 161 | digitalWrite(STATUS_PIN, HIGH); 162 | storeCode(&results); 163 | irrecv.resume(); // resume receiver 164 | digitalWrite(STATUS_PIN, LOW); 165 | } 166 | lastButtonState = buttonState; 167 | } 168 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/IRrecvDemo/IRrecvDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | */ 8 | 9 | #include 10 | 11 | int RECV_PIN = 11; 12 | 13 | IRrecv irrecv(RECV_PIN); 14 | 15 | decode_results results; 16 | 17 | void setup() 18 | { 19 | Serial.begin(9600); 20 | irrecv.enableIRIn(); // Start the receiver 21 | } 22 | 23 | void loop() { 24 | if (irrecv.decode(&results)) { 25 | Serial.println(results.value, HEX); 26 | irrecv.resume(); // Receive the next value 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/IRrecvDump/IRrecvDump.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRrecvDump - dump details of IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 8 | */ 9 | 10 | #include 11 | 12 | int RECV_PIN = 11; 13 | 14 | IRrecv irrecv(RECV_PIN); 15 | 16 | decode_results results; 17 | 18 | void setup() 19 | { 20 | Serial.begin(9600); 21 | irrecv.enableIRIn(); // Start the receiver 22 | } 23 | 24 | // Dumps out the decode_results structure. 25 | // Call this after IRrecv::decode() 26 | // void * to work around compiler issue 27 | //void dump(void *v) { 28 | // decode_results *results = (decode_results *)v 29 | void dump(decode_results *results) { 30 | int count = results->rawlen; 31 | if (results->decode_type == UNKNOWN) { 32 | Serial.print("Unknown encoding: "); 33 | } 34 | else if (results->decode_type == NEC) { 35 | Serial.print("Decoded NEC: "); 36 | } 37 | else if (results->decode_type == SONY) { 38 | Serial.print("Decoded SONY: "); 39 | } 40 | else if (results->decode_type == RC5) { 41 | Serial.print("Decoded RC5: "); 42 | } 43 | else if (results->decode_type == RC6) { 44 | Serial.print("Decoded RC6: "); 45 | } 46 | else if (results->decode_type == PANASONIC) { 47 | Serial.print("Decoded PANASONIC - Address: "); 48 | Serial.print(results->panasonicAddress,HEX); 49 | Serial.print(" Value: "); 50 | } 51 | else if (results->decode_type == JVC) { 52 | Serial.print("Decoded JVC: "); 53 | } 54 | Serial.print(results->value, HEX); 55 | Serial.print(" ("); 56 | Serial.print(results->bits, DEC); 57 | Serial.println(" bits)"); 58 | Serial.print("Raw ("); 59 | Serial.print(count, DEC); 60 | Serial.print("): "); 61 | 62 | for (int i = 0; i < count; i++) { 63 | if ((i % 2) == 1) { 64 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 65 | } 66 | else { 67 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 68 | } 69 | Serial.print(" "); 70 | } 71 | Serial.println(""); 72 | } 73 | 74 | 75 | void loop() { 76 | if (irrecv.decode(&results)) { 77 | Serial.println(results.value, HEX); 78 | dump(&results); 79 | irrecv.resume(); // Receive the next value 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/IRrelay/IRrelay.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | */ 8 | 9 | #include 10 | 11 | int RECV_PIN = 11; 12 | int RELAY_PIN = 4; 13 | 14 | IRrecv irrecv(RECV_PIN); 15 | decode_results results; 16 | 17 | // Dumps out the decode_results structure. 18 | // Call this after IRrecv::decode() 19 | // void * to work around compiler issue 20 | //void dump(void *v) { 21 | // decode_results *results = (decode_results *)v 22 | void dump(decode_results *results) { 23 | int count = results->rawlen; 24 | if (results->decode_type == UNKNOWN) { 25 | Serial.println("Could not decode message"); 26 | } 27 | else { 28 | if (results->decode_type == NEC) { 29 | Serial.print("Decoded NEC: "); 30 | } 31 | else if (results->decode_type == SONY) { 32 | Serial.print("Decoded SONY: "); 33 | } 34 | else if (results->decode_type == RC5) { 35 | Serial.print("Decoded RC5: "); 36 | } 37 | else if (results->decode_type == RC6) { 38 | Serial.print("Decoded RC6: "); 39 | } 40 | Serial.print(results->value, HEX); 41 | Serial.print(" ("); 42 | Serial.print(results->bits, DEC); 43 | Serial.println(" bits)"); 44 | } 45 | Serial.print("Raw ("); 46 | Serial.print(count, DEC); 47 | Serial.print("): "); 48 | 49 | for (int i = 0; i < count; i++) { 50 | if ((i % 2) == 1) { 51 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 52 | } 53 | else { 54 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 55 | } 56 | Serial.print(" "); 57 | } 58 | Serial.println(""); 59 | } 60 | 61 | void setup() 62 | { 63 | pinMode(RELAY_PIN, OUTPUT); 64 | pinMode(13, OUTPUT); 65 | Serial.begin(9600); 66 | irrecv.enableIRIn(); // Start the receiver 67 | } 68 | 69 | int on = 0; 70 | unsigned long last = millis(); 71 | 72 | void loop() { 73 | if (irrecv.decode(&results)) { 74 | // If it's been at least 1/4 second since the last 75 | // IR received, toggle the relay 76 | if (millis() - last > 250) { 77 | on = !on; 78 | digitalWrite(RELAY_PIN, on ? HIGH : LOW); 79 | digitalWrite(13, on ? HIGH : LOW); 80 | dump(&results); 81 | } 82 | last = millis(); 83 | irrecv.resume(); // Receive the next value 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/IRsendDemo/IRsendDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend 3 | * An IR LED must be connected to Arduino PWM pin 3. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | */ 8 | 9 | #include 10 | 11 | IRsend irsend; 12 | 13 | void setup() 14 | { 15 | Serial.begin(9600); 16 | } 17 | 18 | void loop() { 19 | if (Serial.read() != -1) { 20 | for (int i = 0; i < 3; i++) { 21 | irsend.sendSony(0xa90, 12); // Sony TV power code 22 | delay(40); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/IRtest/IRtest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRtest unittest 3 | * Version 0.1 July, 2009 4 | * Copyright 2009 Ken Shirriff 5 | * http://arcfn.com 6 | * 7 | * Note: to run these tests, edit IRremote/IRremote.h to add "#define TEST" 8 | * You must then recompile the library by removing IRremote.o and restarting 9 | * the arduino IDE. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | // Dumps out the decode_results structure. 16 | // Call this after IRrecv::decode() 17 | // void * to work around compiler issue 18 | //void dump(void *v) { 19 | // decode_results *results = (decode_results *)v 20 | void dump(decode_results *results) { 21 | int count = results->rawlen; 22 | if (results->decode_type == UNKNOWN) { 23 | Serial.println("Could not decode message"); 24 | } 25 | else { 26 | if (results->decode_type == NEC) { 27 | Serial.print("Decoded NEC: "); 28 | } 29 | else if (results->decode_type == SONY) { 30 | Serial.print("Decoded SONY: "); 31 | } 32 | else if (results->decode_type == RC5) { 33 | Serial.print("Decoded RC5: "); 34 | } 35 | else if (results->decode_type == RC6) { 36 | Serial.print("Decoded RC6: "); 37 | } 38 | Serial.print(results->value, HEX); 39 | Serial.print(" ("); 40 | Serial.print(results->bits, DEC); 41 | Serial.println(" bits)"); 42 | } 43 | Serial.print("Raw ("); 44 | Serial.print(count, DEC); 45 | Serial.print("): "); 46 | 47 | for (int i = 0; i < count; i++) { 48 | if ((i % 2) == 1) { 49 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 50 | } 51 | else { 52 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 53 | } 54 | Serial.print(" "); 55 | } 56 | Serial.println(""); 57 | } 58 | 59 | IRrecv irrecv(0); 60 | decode_results results; 61 | 62 | class IRsendDummy : 63 | public IRsend 64 | { 65 | public: 66 | // For testing, just log the marks/spaces 67 | #define SENDLOG_LEN 128 68 | int sendlog[SENDLOG_LEN]; 69 | int sendlogcnt; 70 | IRsendDummy() : 71 | IRsend() { 72 | } 73 | void reset() { 74 | sendlogcnt = 0; 75 | } 76 | void mark(int time) { 77 | sendlog[sendlogcnt] = time; 78 | if (sendlogcnt < SENDLOG_LEN) sendlogcnt++; 79 | } 80 | void space(int time) { 81 | sendlog[sendlogcnt] = -time; 82 | if (sendlogcnt < SENDLOG_LEN) sendlogcnt++; 83 | } 84 | // Copies the dummy buf into the interrupt buf 85 | void useDummyBuf() { 86 | int last = SPACE; 87 | irparams.rcvstate = STATE_STOP; 88 | irparams.rawlen = 1; // Skip the gap 89 | for (int i = 0 ; i < sendlogcnt; i++) { 90 | if (sendlog[i] < 0) { 91 | if (last == MARK) { 92 | // New space 93 | irparams.rawbuf[irparams.rawlen++] = (-sendlog[i] - MARK_EXCESS) / USECPERTICK; 94 | last = SPACE; 95 | } 96 | else { 97 | // More space 98 | irparams.rawbuf[irparams.rawlen - 1] += -sendlog[i] / USECPERTICK; 99 | } 100 | } 101 | else if (sendlog[i] > 0) { 102 | if (last == SPACE) { 103 | // New mark 104 | irparams.rawbuf[irparams.rawlen++] = (sendlog[i] + MARK_EXCESS) / USECPERTICK; 105 | last = MARK; 106 | } 107 | else { 108 | // More mark 109 | irparams.rawbuf[irparams.rawlen - 1] += sendlog[i] / USECPERTICK; 110 | } 111 | } 112 | } 113 | if (irparams.rawlen % 2) { 114 | irparams.rawlen--; // Remove trailing space 115 | } 116 | } 117 | }; 118 | 119 | IRsendDummy irsenddummy; 120 | 121 | void verify(unsigned long val, int bits, int type) { 122 | irsenddummy.useDummyBuf(); 123 | irrecv.decode(&results); 124 | Serial.print("Testing "); 125 | Serial.print(val, HEX); 126 | if (results.value == val && results.bits == bits && results.decode_type == type) { 127 | Serial.println(": OK"); 128 | } 129 | else { 130 | Serial.println(": Error"); 131 | dump(&results); 132 | } 133 | } 134 | 135 | void testNEC(unsigned long val, int bits) { 136 | irsenddummy.reset(); 137 | irsenddummy.sendNEC(val, bits); 138 | verify(val, bits, NEC); 139 | } 140 | void testSony(unsigned long val, int bits) { 141 | irsenddummy.reset(); 142 | irsenddummy.sendSony(val, bits); 143 | verify(val, bits, SONY); 144 | } 145 | void testRC5(unsigned long val, int bits) { 146 | irsenddummy.reset(); 147 | irsenddummy.sendRC5(val, bits); 148 | verify(val, bits, RC5); 149 | } 150 | void testRC6(unsigned long val, int bits) { 151 | irsenddummy.reset(); 152 | irsenddummy.sendRC6(val, bits); 153 | verify(val, bits, RC6); 154 | } 155 | 156 | void test() { 157 | Serial.println("NEC tests"); 158 | testNEC(0x00000000, 32); 159 | testNEC(0xffffffff, 32); 160 | testNEC(0xaaaaaaaa, 32); 161 | testNEC(0x55555555, 32); 162 | testNEC(0x12345678, 32); 163 | Serial.println("Sony tests"); 164 | testSony(0xfff, 12); 165 | testSony(0x000, 12); 166 | testSony(0xaaa, 12); 167 | testSony(0x555, 12); 168 | testSony(0x123, 12); 169 | Serial.println("RC5 tests"); 170 | testRC5(0xfff, 12); 171 | testRC5(0x000, 12); 172 | testRC5(0xaaa, 12); 173 | testRC5(0x555, 12); 174 | testRC5(0x123, 12); 175 | Serial.println("RC6 tests"); 176 | testRC6(0xfffff, 20); 177 | testRC6(0x00000, 20); 178 | testRC6(0xaaaaa, 20); 179 | testRC6(0x55555, 20); 180 | testRC6(0x12345, 20); 181 | } 182 | 183 | void setup() 184 | { 185 | Serial.begin(9600); 186 | test(); 187 | } 188 | 189 | void loop() { 190 | } 191 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/IRtest2/IRtest2.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Test send/receive functions of IRremote, using a pair of Arduinos. 3 | * 4 | * Arduino #1 should have an IR LED connected to the send pin (3). 5 | * Arduino #2 should have an IR detector/demodulator connected to the 6 | * receive pin (11) and a visible LED connected to pin 3. 7 | * 8 | * The cycle: 9 | * Arduino #1 will wait 2 seconds, then run through the tests. 10 | * It repeats this forever. 11 | * Arduino #2 will wait for at least one second of no signal 12 | * (to synchronize with #1). It will then wait for the same test 13 | * signals. It will log all the status to the serial port. It will 14 | * also indicate status through the LED, which will flash each time a test 15 | * is completed. If there is an error, it will light up for 5 seconds. 16 | * 17 | * The test passes if the LED flashes 19 times, pauses, and then repeats. 18 | * The test fails if the LED lights for 5 seconds. 19 | * 20 | * The test software automatically decides which board is the sender and which is 21 | * the receiver by looking for an input on the send pin, which will indicate 22 | * the sender. You should hook the serial port to the receiver for debugging. 23 | * 24 | * Copyright 2010 Ken Shirriff 25 | * http://arcfn.com 26 | */ 27 | 28 | #include 29 | 30 | int RECV_PIN = 11; 31 | int LED_PIN = 3; 32 | 33 | IRrecv irrecv(RECV_PIN); 34 | IRsend irsend; 35 | 36 | decode_results results; 37 | 38 | #define RECEIVER 1 39 | #define SENDER 2 40 | #define ERROR 3 41 | 42 | int mode; 43 | 44 | void setup() 45 | { 46 | Serial.begin(9600); 47 | // Check RECV_PIN to decide if we're RECEIVER or SENDER 48 | if (digitalRead(RECV_PIN) == HIGH) { 49 | mode = RECEIVER; 50 | irrecv.enableIRIn(); 51 | pinMode(LED_PIN, OUTPUT); 52 | digitalWrite(LED_PIN, LOW); 53 | Serial.println("Receiver mode"); 54 | } 55 | else { 56 | mode = SENDER; 57 | Serial.println("Sender mode"); 58 | } 59 | } 60 | 61 | // Wait for the gap between tests, to synchronize with 62 | // the sender. 63 | // Specifically, wait for a signal followed by a gap of at last gap ms. 64 | void waitForGap(int gap) { 65 | Serial.println("Waiting for gap"); 66 | while (1) { 67 | while (digitalRead(RECV_PIN) == LOW) { 68 | } 69 | unsigned long time = millis(); 70 | while (digitalRead(RECV_PIN) == HIGH) { 71 | if (millis() - time > gap) { 72 | return; 73 | } 74 | } 75 | } 76 | } 77 | 78 | // Dumps out the decode_results structure. 79 | // Call this after IRrecv::decode() 80 | void dump(decode_results *results) { 81 | int count = results->rawlen; 82 | if (results->decode_type == UNKNOWN) { 83 | Serial.println("Could not decode message"); 84 | } 85 | else { 86 | if (results->decode_type == NEC) { 87 | Serial.print("Decoded NEC: "); 88 | } 89 | else if (results->decode_type == SONY) { 90 | Serial.print("Decoded SONY: "); 91 | } 92 | else if (results->decode_type == RC5) { 93 | Serial.print("Decoded RC5: "); 94 | } 95 | else if (results->decode_type == RC6) { 96 | Serial.print("Decoded RC6: "); 97 | } 98 | Serial.print(results->value, HEX); 99 | Serial.print(" ("); 100 | Serial.print(results->bits, DEC); 101 | Serial.println(" bits)"); 102 | } 103 | Serial.print("Raw ("); 104 | Serial.print(count, DEC); 105 | Serial.print("): "); 106 | 107 | for (int i = 0; i < count; i++) { 108 | if ((i % 2) == 1) { 109 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 110 | } 111 | else { 112 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 113 | } 114 | Serial.print(" "); 115 | } 116 | Serial.println(""); 117 | } 118 | 119 | 120 | // Test send or receive. 121 | // If mode is SENDER, send a code of the specified type, value, and bits 122 | // If mode is RECEIVER, receive a code and verify that it is of the 123 | // specified type, value, and bits. For success, the LED is flashed; 124 | // for failure, the mode is set to ERROR. 125 | // The motivation behind this method is that the sender and the receiver 126 | // can do the same test calls, and the mode variable indicates whether 127 | // to send or receive. 128 | void test(char *label, int type, unsigned long value, int bits) { 129 | if (mode == SENDER) { 130 | Serial.println(label); 131 | if (type == NEC) { 132 | irsend.sendNEC(value, bits); 133 | } 134 | else if (type == SONY) { 135 | irsend.sendSony(value, bits); 136 | } 137 | else if (type == RC5) { 138 | irsend.sendRC5(value, bits); 139 | } 140 | else if (type == RC6) { 141 | irsend.sendRC6(value, bits); 142 | } 143 | else { 144 | Serial.print(label); 145 | Serial.println("Bad type!"); 146 | } 147 | delay(200); 148 | } 149 | else if (mode == RECEIVER) { 150 | irrecv.resume(); // Receive the next value 151 | unsigned long max_time = millis() + 30000; 152 | Serial.print(label); 153 | 154 | // Wait for decode or timeout 155 | while (!irrecv.decode(&results)) { 156 | if (millis() > max_time) { 157 | Serial.println("Timeout receiving data"); 158 | mode = ERROR; 159 | return; 160 | } 161 | } 162 | if (type == results.decode_type && value == results.value && bits == results.bits) { 163 | Serial.println (": OK"); 164 | digitalWrite(LED_PIN, HIGH); 165 | delay(20); 166 | digitalWrite(LED_PIN, LOW); 167 | } 168 | else { 169 | Serial.println(": BAD"); 170 | dump(&results); 171 | mode = ERROR; 172 | } 173 | } 174 | } 175 | 176 | // Test raw send or receive. This is similar to the test method, 177 | // except it send/receives raw data. 178 | void testRaw(char *label, unsigned int *rawbuf, int rawlen) { 179 | if (mode == SENDER) { 180 | Serial.println(label); 181 | irsend.sendRaw(rawbuf, rawlen, 38 /* kHz */); 182 | delay(200); 183 | } 184 | else if (mode == RECEIVER ) { 185 | irrecv.resume(); // Receive the next value 186 | unsigned long max_time = millis() + 30000; 187 | Serial.print(label); 188 | 189 | // Wait for decode or timeout 190 | while (!irrecv.decode(&results)) { 191 | if (millis() > max_time) { 192 | Serial.println("Timeout receiving data"); 193 | mode = ERROR; 194 | return; 195 | } 196 | } 197 | 198 | // Received length has extra first element for gap 199 | if (rawlen != results.rawlen - 1) { 200 | Serial.print("Bad raw length "); 201 | Serial.println(results.rawlen, DEC); 202 | mode = ERROR; 203 | return; 204 | } 205 | for (int i = 0; i < rawlen; i++) { 206 | long got = results.rawbuf[i+1] * USECPERTICK; 207 | // Adjust for extra duration of marks 208 | if (i % 2 == 0) { 209 | got -= MARK_EXCESS; 210 | } 211 | else { 212 | got += MARK_EXCESS; 213 | } 214 | // See if close enough, within 25% 215 | if (rawbuf[i] * 1.25 < got || got * 1.25 < rawbuf[i]) { 216 | Serial.println(": BAD"); 217 | dump(&results); 218 | mode = ERROR; 219 | return; 220 | } 221 | 222 | } 223 | Serial.println (": OK"); 224 | digitalWrite(LED_PIN, HIGH); 225 | delay(20); 226 | digitalWrite(LED_PIN, LOW); 227 | } 228 | } 229 | 230 | // This is the raw data corresponding to NEC 0x12345678 231 | unsigned int sendbuf[] = { /* NEC format */ 232 | 9000, 4500, 233 | 560, 560, 560, 560, 560, 560, 560, 1690, /* 1 */ 234 | 560, 560, 560, 560, 560, 1690, 560, 560, /* 2 */ 235 | 560, 560, 560, 560, 560, 1690, 560, 1690, /* 3 */ 236 | 560, 560, 560, 1690, 560, 560, 560, 560, /* 4 */ 237 | 560, 560, 560, 1690, 560, 560, 560, 1690, /* 5 */ 238 | 560, 560, 560, 1690, 560, 1690, 560, 560, /* 6 */ 239 | 560, 560, 560, 1690, 560, 1690, 560, 1690, /* 7 */ 240 | 560, 1690, 560, 560, 560, 560, 560, 560, /* 8 */ 241 | 560}; 242 | 243 | void loop() { 244 | if (mode == SENDER) { 245 | delay(2000); // Delay for more than gap to give receiver a better chance to sync. 246 | } 247 | else if (mode == RECEIVER) { 248 | waitForGap(1000); 249 | } 250 | else if (mode == ERROR) { 251 | // Light up for 5 seconds for error 252 | digitalWrite(LED_PIN, HIGH); 253 | delay(5000); 254 | digitalWrite(LED_PIN, LOW); 255 | mode = RECEIVER; // Try again 256 | return; 257 | } 258 | 259 | // The test suite. 260 | test("SONY1", SONY, 0x123, 12); 261 | test("SONY2", SONY, 0x000, 12); 262 | test("SONY3", SONY, 0xfff, 12); 263 | test("SONY4", SONY, 0x12345, 20); 264 | test("SONY5", SONY, 0x00000, 20); 265 | test("SONY6", SONY, 0xfffff, 20); 266 | test("NEC1", NEC, 0x12345678, 32); 267 | test("NEC2", NEC, 0x00000000, 32); 268 | test("NEC3", NEC, 0xffffffff, 32); 269 | test("NEC4", NEC, REPEAT, 32); 270 | test("RC51", RC5, 0x12345678, 32); 271 | test("RC52", RC5, 0x0, 32); 272 | test("RC53", RC5, 0xffffffff, 32); 273 | test("RC61", RC6, 0x12345678, 32); 274 | test("RC62", RC6, 0x0, 32); 275 | test("RC63", RC6, 0xffffffff, 32); 276 | 277 | // Tests of raw sending and receiving. 278 | // First test sending raw and receiving raw. 279 | // Then test sending raw and receiving decoded NEC 280 | // Then test sending NEC and receiving raw 281 | testRaw("RAW1", sendbuf, 67); 282 | if (mode == SENDER) { 283 | testRaw("RAW2", sendbuf, 67); 284 | test("RAW3", NEC, 0x12345678, 32); 285 | } 286 | else { 287 | test("RAW2", NEC, 0x12345678, 32); 288 | testRaw("RAW3", sendbuf, 67); 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /src/libs/IRremote/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend 3 | * An IR LED must be connected to Arduino PWM pin 3. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 8 | */ 9 | #include 10 | 11 | #define PanasonicAddress 0x4004 // Panasonic address (Pre data) 12 | #define PanasonicPower 0x100BCBD // Panasonic Power button 13 | 14 | #define JVCPower 0xC5E8 15 | 16 | IRsend irsend; 17 | 18 | void setup() 19 | { 20 | } 21 | 22 | void loop() { 23 | irsend.sendPanasonic(PanasonicAddress,PanasonicPower); // This should turn your TV on and off 24 | 25 | irsend.sendJVC(JVCPower, 16,0); // hex value, 16 bits, no repeat 26 | delayMicroseconds(50); // see http://www.sbprojects.com/knowledge/ir/jvc.php for information 27 | irsend.sendJVC(JVCPower, 16,1); // hex value, 16 bits, repeat 28 | delayMicroseconds(50); 29 | } 30 | -------------------------------------------------------------------------------- /src/libs/IRremote/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For IRremote 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | decode_results KEYWORD1 10 | IRrecv KEYWORD1 11 | IRsend KEYWORD1 12 | 13 | ####################################### 14 | # Methods and Functions (KEYWORD2) 15 | ####################################### 16 | 17 | blink13 KEYWORD2 18 | decode KEYWORD2 19 | enableIRIn KEYWORD2 20 | resume KEYWORD2 21 | enableIROut KEYWORD2 22 | sendNEC KEYWORD2 23 | sendSony KEYWORD2 24 | sendSanyo KEYWORD2 25 | sendMitsubishi KEYWORD2 26 | sendRaw KEYWORD2 27 | sendRC5 KEYWORD2 28 | sendRC6 KEYWORD2 29 | sendDISH KEYWORD2 30 | sendSharp KEYWORD2 31 | sendPanasonic KEYWORD2 32 | sendJVC KEYWORD2 33 | 34 | # 35 | ####################################### 36 | # Constants (LITERAL1) 37 | ####################################### 38 | 39 | NEC LITERAL1 40 | SONY LITERAL1 41 | SANYO LITERAL1 42 | MITSUBISHI LITERAL1 43 | RC5 LITERAL1 44 | RC6 LITERAL1 45 | DISH LITERAL1 46 | SHARP LITERAL1 47 | PANASONIC LITERAL1 48 | JVC LITERAL1 49 | UNKNOWN LITERAL1 50 | REPEAT LITERAL1 -------------------------------------------------------------------------------- /src/libs/IRremote/readme: -------------------------------------------------------------------------------- 1 | This is the IRremote library for the Arduino. 2 | 3 | To download from github (http://github.com/shirriff/Arduino-IRremote), click on the "Downloads" link in the upper right, click "Download as zip", and get a zip file. Unzip it and rename the directory shirriff-Arduino-IRremote-nnn to IRremote 4 | 5 | To install, move the downloaded IRremote directory to: 6 | arduino-1.x/libraries/IRremote 7 | where arduino-1.x is your Arduino installation directory 8 | 9 | After installation you should have files such as: 10 | arduino-1.x/libraries/IRremote/IRremote.cpp 11 | 12 | For details on the library see the Wiki on github or the blog post http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 13 | 14 | Copyright 2009-2012 Ken Shirriff 15 | -------------------------------------------------------------------------------- /src/libs/RCSwitch/RCSwitch.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ni-c/duino/a92968a36bf0eab64a6b426dfa674eb1a31b9880/src/libs/RCSwitch/RCSwitch.cpp -------------------------------------------------------------------------------- /src/libs/RCSwitch/RCSwitch.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ni-c/duino/a92968a36bf0eab64a6b426dfa674eb1a31b9880/src/libs/RCSwitch/RCSwitch.h --------------------------------------------------------------------------------