From 649c54661425004a434c942a50f8167f57e6d88b Mon Sep 17 00:00:00 2001 From: Andrew Lorimer Date: Thu, 19 May 2016 16:28:33 +1000 Subject: [PATCH] Added final version of code --- .../Adafruit_BMP085_U.cpp | 481 +++++ .../Adafruit_BMP085_U.h | 122 ++ .../Adafruit_BMP085_Unified-master/README.md | 27 + .../examples/sensorapi/sensorapi.pde | 132 ++ .../library.properties | 9 + libraries/Adafruit_DHTxx/DHT.cpp | 259 +++ libraries/Adafruit_DHTxx/DHT.h | 75 + libraries/Adafruit_DHTxx/README.md | 5 + .../examples/DHTtester/DHTtester.ino | 69 + libraries/Adafruit_DHTxx/keywords.txt | 22 + libraries/Adafruit_DHTxx/library.properties | 9 + .../Adafruit_Sensor-master/Adafruit_Sensor.h | 154 ++ libraries/Adafruit_Sensor-master/README.md | 221 +++ .../Adafruit_Sensor-master/library.properties | 9 + .../.gitattributes | 22 + .../.gitignore | 192 ++ .../LICENSE.md | 9 + .../README.md | 49 + .../BMP180_altitude_example.ino | 169 ++ .../examples/README.md | 5 + .../SFE_BMP180_example/SFE_BMP180_example.ino | 201 +++ .../keywords.txt | 27 + .../library.properties | 9 + .../src/README.md | 5 + .../src/SFE_BMP180.cpp | 388 ++++ .../src/SFE_BMP180.h | 122 ++ libraries/Bridge/README.adoc | 24 + libraries/Bridge/examples/Bridge/Bridge.ino | 185 ++ .../ConsoleAsciiTable/ConsoleAsciiTable.ino | 95 + .../examples/ConsolePixel/ConsolePixel.ino | 64 + .../examples/ConsoleRead/ConsoleRead.ino | 60 + .../Bridge/examples/Datalogger/Datalogger.ino | 102 ++ .../FileWriteScript/FileWriteScript.ino | 84 + .../Bridge/examples/HttpClient/HttpClient.ino | 53 + .../HttpClientConsole/HttpClientConsole.ino | 55 + .../MailboxReadMessage/MailboxReadMessage.ino | 58 + libraries/Bridge/examples/Process/Process.ino | 72 + .../RemoteDueBlink/RemoteDueBlink.ino | 33 + .../examples/ShellCommands/ShellCommands.ino | 55 + .../SpacebrewYun/inputOutput/inputOutput.ino | 134 ++ .../spacebrewBoolean/spacebrewBoolean.ino | 94 + .../spacebrewRange/spacebrewRange.ino | 88 + .../spacebrewString/spacebrewString.ino | 86 + .../TemperatureWebPanel.ino | 125 ++ .../TemperatureWebPanel/www/index.html | 16 + .../TemperatureWebPanel/www/zepto.min.js | 2 + .../Bridge/examples/TimeCheck/TimeCheck.ino | 88 + .../Bridge/examples/WiFiStatus/WiFiStatus.ino | 52 + .../YunFirstConfig/YunFirstConfig.ino | 327 ++++ .../YunSerialTerminal/YunSerialTerminal.ino | 82 + libraries/Bridge/keywords.txt | 92 + libraries/Bridge/library.properties | 10 + libraries/Bridge/src/Bridge.cpp | 281 +++ libraries/Bridge/src/Bridge.h | 125 ++ libraries/Bridge/src/BridgeClient.cpp | 207 +++ libraries/Bridge/src/BridgeClient.h | 71 + libraries/Bridge/src/BridgeSSLClient.cpp | 36 + libraries/Bridge/src/BridgeSSLClient.h | 36 + libraries/Bridge/src/BridgeServer.cpp | 54 + libraries/Bridge/src/BridgeServer.h | 51 + libraries/Bridge/src/BridgeUdp.cpp | 198 +++ libraries/Bridge/src/BridgeUdp.h | 65 + libraries/Bridge/src/Console.cpp | 150 ++ libraries/Bridge/src/Console.h | 71 + libraries/Bridge/src/FileIO.cpp | 283 +++ libraries/Bridge/src/FileIO.h | 120 ++ libraries/Bridge/src/HttpClient.cpp | 204 +++ libraries/Bridge/src/HttpClient.h | 59 + libraries/Bridge/src/Mailbox.cpp | 56 + libraries/Bridge/src/Mailbox.h | 53 + libraries/Bridge/src/Process.cpp | 142 ++ libraries/Bridge/src/Process.h | 71 + libraries/Bridge/src/YunClient.h | 27 + libraries/Bridge/src/YunServer.h | 27 + libraries/DHT-sensor-library-master/DHT.cpp | 259 +++ libraries/DHT-sensor-library-master/DHT.h | 75 + libraries/DHT-sensor-library-master/README.md | 5 + .../examples/DHTtester/DHTtester.ino | 69 + .../DHT-sensor-library-master/keywords.txt | 22 + .../library.properties | 9 + libraries/Mitov/Mitov.h | 1572 +++++++++++++++++ .../MitovEmbedded_Adafruit_NeoPixel/COPYING | 794 +++++++++ .../MitovEmbedded_Adafruit_NeoPixel.h | 1092 ++++++++++++ .../MitovEmbedded_Adafruit_NeoPixel/README.md | 12 + .../keywords.txt | 29 + .../library.properties | 9 + libraries/Mitov/Mitov_7Segment.h | 367 ++++ libraries/Mitov/Mitov_Accelerometer.h | 94 + libraries/Mitov/Mitov_AmplitudeMeter.h | 93 + libraries/Mitov/Mitov_Arduino_SPI.h | 57 + libraries/Mitov/Mitov_BMP180_Pressure.h | 369 ++++ libraries/Mitov/Mitov_BasicDisplay.h | 68 + libraries/Mitov/Mitov_BasicEthernet.h | 655 +++++++ libraries/Mitov/Mitov_BasicGenerator.h | 132 ++ libraries/Mitov/Mitov_Basic_GPIO.h | 165 ++ libraries/Mitov/Mitov_Basic_I2C.h | 159 ++ libraries/Mitov/Mitov_Basic_RTC.h | 75 + libraries/Mitov/Mitov_Basic_SPI.h | 139 ++ libraries/Mitov/Mitov_BinaryDecoder.h | 59 + libraries/Mitov/Mitov_BinaryGenerators.h | 48 + libraries/Mitov/Mitov_Button.h | 54 + libraries/Mitov/Mitov_Color.h | 150 ++ libraries/Mitov/Mitov_CommonMux.h | 123 ++ libraries/Mitov/Mitov_CompassHeading.h | 96 + libraries/Mitov/Mitov_Compass_AK8963.h | 192 ++ libraries/Mitov/Mitov_Controllino_RS485.h | 98 + libraries/Mitov/Mitov_Controllino_RTC.h | 121 ++ libraries/Mitov/Mitov_Converters.h | 465 +++++ libraries/Mitov/Mitov_Counter.h | 173 ++ libraries/Mitov/Mitov_DHT_Sensor.h | 286 +++ libraries/Mitov/Mitov_DateTime.h | 59 + libraries/Mitov/Mitov_DigitalsToUnsigned.h | 36 + libraries/Mitov/Mitov_Display4DSystems.h | 625 +++++++ libraries/Mitov/Mitov_ESP8266.h | 662 +++++++ libraries/Mitov/Mitov_ESP8266_WiFi.h | 540 ++++++ libraries/Mitov/Mitov_EthernetShield.h | 148 ++ libraries/Mitov/Mitov_FormattedSerial.h | 152 ++ libraries/Mitov/Mitov_FrequencyMeter.h | 52 + libraries/Mitov/Mitov_GPRS.h | 187 ++ libraries/Mitov/Mitov_GSMShield.h | 113 ++ libraries/Mitov/Mitov_GaussGenerator.h | 99 ++ libraries/Mitov/Mitov_Goldilocks_DAC.h | 58 + libraries/Mitov/Mitov_HMC5883_Compass.h | 219 +++ libraries/Mitov/Mitov_HX711_Weight.h | 241 +++ libraries/Mitov/Mitov_HeatIndex.h | 104 ++ .../Mitov/Mitov_InfraredAvoidanceSensor.h | 94 + libraries/Mitov/Mitov_Keypad.h | 285 +++ libraries/Mitov/Mitov_L298NDualMotorDriver.h | 86 + libraries/Mitov/Mitov_L9110SDualMotorDriver.h | 84 + libraries/Mitov/Mitov_LEDBarDisplay.h | 98 + libraries/Mitov/Mitov_LEGO_RCX_LightSensor.h | 93 + libraries/Mitov/Mitov_LinkIt_GPRS.h | 108 ++ libraries/Mitov/Mitov_LinkIt_WiFi.h | 286 +++ libraries/Mitov/Mitov_LiquidCrystalDisplay.h | 674 +++++++ libraries/Mitov/Mitov_LogicFlipFlops.h | 214 +++ libraries/Mitov/Mitov_LogicGates.h | 77 + libraries/Mitov/Mitov_MPU9250.h | 466 +++++ libraries/Mitov/Mitov_Math.h | 533 ++++++ libraries/Mitov/Mitov_MaximLedControl.h | 1208 +++++++++++++ .../Mitov_MaximLedControl_7SegmentText.h | 171 ++ libraries/Mitov/Mitov_Maxim_MAX521X.h | 125 ++ libraries/Mitov/Mitov_Maxim_MAX7300.h | 290 +++ .../Mitov/Mitov_Maxim_MotorDriverShield.h | 400 +++++ .../Mitov/Mitov_Maxim_OneWire_Thermometer.h | 234 +++ .../Mitov/Mitov_Maxim_Potentiometer_I2C.h | 124 ++ libraries/Mitov/Mitov_MicroSDCard.h | 695 ++++++++ libraries/Mitov/Mitov_Microchip_DAC_SPI.h | 134 ++ libraries/Mitov/Mitov_Microchip_MCP23017.h | 233 +++ libraries/Mitov/Mitov_MultiMerger.h | 43 + libraries/Mitov/Mitov_NeoPixel.h | 509 ++++++ libraries/Mitov/Mitov_PIDController.h | 129 ++ libraries/Mitov/Mitov_PS2_Controller.h | 99 ++ libraries/Mitov/Mitov_PS2_Controller_Basic.h | 157 ++ libraries/Mitov/Mitov_PS2_Controller_Serial.h | 145 ++ libraries/Mitov/Mitov_Packet.h | 999 +++++++++++ libraries/Mitov/Mitov_Potentiometer_SPI.h | 215 +++ libraries/Mitov/Mitov_PriorityEncoder.h | 35 + libraries/Mitov/Mitov_PulseMeter.h | 51 + libraries/Mitov/Mitov_PulseWideModulation.h | 49 + libraries/Mitov/Mitov_RCServoMeter.h | 52 + libraries/Mitov/Mitov_RTC_DS1302.h | 240 +++ libraries/Mitov/Mitov_RTC_DS1307.h | 184 ++ libraries/Mitov/Mitov_RTC_DS3231.h | 177 ++ libraries/Mitov/Mitov_RampToValue.h | 100 ++ libraries/Mitov/Mitov_RandomGenerator.h | 184 ++ libraries/Mitov/Mitov_Remember.h | 61 + libraries/Mitov/Mitov_RotaryEncoderSensor.h | 151 ++ libraries/Mitov/Mitov_Sabertooth_DualMotor.h | 367 ++++ libraries/Mitov/Mitov_SchmittTrigger.h | 118 ++ libraries/Mitov/Mitov_Servo.h | 42 + libraries/Mitov/Mitov_SimpleList.h | 264 +++ libraries/Mitov/Mitov_SineGenerator.h | 70 + libraries/Mitov/Mitov_Snapshot.h | 57 + libraries/Mitov/Mitov_SoftwareSPI.h | 65 + libraries/Mitov/Mitov_SoftwareSerial.h | 99 ++ libraries/Mitov/Mitov_SpeedToClock.h | 88 + .../Mitov/Mitov_SpeedToSpeedAndDirection.h | 120 ++ libraries/Mitov/Mitov_SquareGenerator.h | 40 + libraries/Mitov/Mitov_Steering_Differential.h | 97 + libraries/Mitov/Mitov_Stepper.h | 154 ++ libraries/Mitov/Mitov_StringPrint.h | 48 + libraries/Mitov/Mitov_Structure.h | 321 ++++ libraries/Mitov/Mitov_TVOut_RCA.h | 638 +++++++ libraries/Mitov/Mitov_TeensySerial.h | 161 ++ .../Mitov_TexasInstruments_Thermometer.h | 39 + libraries/Mitov/Mitov_Text.h | 513 ++++++ libraries/Mitov/Mitov_Timing.h | 226 +++ libraries/Mitov/Mitov_TriangleGenerator.h | 93 + libraries/Mitov/Mitov_UARTSerial.h | 55 + libraries/Mitov/Mitov_USARTSerial.h | 126 ++ libraries/Mitov/Mitov_UltrasonicRanger.h | 176 ++ libraries/Mitov/Mitov_WiFiShield.h | 267 +++ libraries/Mitov/Mitov_Wii_Controller.h | 139 ++ libraries/Mitov/OpenWire.h | 362 ++++ libraries/Mitov/README.md | 21 + libraries/Mitov/avr/ServoTimers.h | 59 + libraries/Mitov/sam/ServoTimers.h | 88 + libraries/OneWire/OneWire.cpp | 577 ++++++ libraries/OneWire/OneWire.h | 371 ++++ .../DS18x20_Temperature.pde | 112 ++ .../examples/DS2408_Switch/DS2408_Switch.pde | 77 + .../examples/DS250x_PROM/DS250x_PROM.pde | 90 + libraries/OneWire/keywords.txt | 38 + libraries/OneWire/library.json | 58 + libraries/OneWire/library.properties | 10 + libraries/VirtualWire/CHANGES | 16 + libraries/VirtualWire/LICENSE | 17 + libraries/VirtualWire/MANIFEST | 12 + libraries/VirtualWire/Makefile | 26 + libraries/VirtualWire/README | 8 + libraries/VirtualWire/VWutil/crc16.h | 103 ++ libraries/VirtualWire/VirtualWire.cpp | 478 +++++ libraries/VirtualWire/VirtualWire.h | 107 ++ libraries/VirtualWire/VirtualWire.o | Bin 0 -> 24448 bytes libraries/VirtualWire/VirtualWire_Config.h | 152 ++ .../VirtualWire/examples/client/client.pde | 63 + .../receiver/applet/HardwareSerial.cpp.o | Bin 0 -> 14308 bytes .../examples/receiver/applet/Print.cpp.o | Bin 0 -> 22848 bytes .../examples/receiver/applet/WInterrupts.c.o | Bin 0 -> 5572 bytes .../examples/receiver/applet/WMath.cpp.o | Bin 0 -> 6980 bytes .../examples/receiver/applet/core.a | Bin 0 -> 96278 bytes .../examples/receiver/applet/pins_arduino.c.o | Bin 0 -> 3012 bytes .../examples/receiver/applet/receiver.cpp | 68 + .../examples/receiver/applet/receiver.cpp.o | Bin 0 -> 5040 bytes .../examples/receiver/applet/receiver.eep | 1 + .../examples/receiver/applet/receiver.elf | Bin 0 -> 35970 bytes .../examples/receiver/applet/receiver.hex | 187 ++ .../examples/receiver/applet/receiver.pde | 50 + .../examples/receiver/applet/wiring.c.o | Bin 0 -> 8800 bytes .../receiver/applet/wiring_analog.c.o | Bin 0 -> 6512 bytes .../receiver/applet/wiring_digital.c.o | Bin 0 -> 8220 bytes .../examples/receiver/applet/wiring_pulse.c.o | Bin 0 -> 6400 bytes .../receiver/applet/wiring_serial.c.o | Bin 0 -> 7048 bytes .../examples/receiver/applet/wiring_shift.c.o | Bin 0 -> 4032 bytes .../examples/receiver/receiver.pde | 50 + .../server/applet/HardwareSerial.cpp.o | Bin 0 -> 14308 bytes .../examples/server/applet/Print.cpp.o | Bin 0 -> 22848 bytes .../examples/server/applet/WInterrupts.c.o | Bin 0 -> 5572 bytes .../examples/server/applet/WMath.cpp.o | Bin 0 -> 6980 bytes .../VirtualWire/examples/server/applet/core.a | Bin 0 -> 96278 bytes .../examples/server/applet/pins_arduino.c.o | Bin 0 -> 3012 bytes .../examples/server/applet/server.cpp | 75 + .../examples/server/applet/server.cpp.o | Bin 0 -> 5968 bytes .../examples/server/applet/server.eep | 1 + .../examples/server/applet/server.elf | Bin 0 -> 37298 bytes .../examples/server/applet/server.hex | 244 +++ .../examples/server/applet/server.pde | 59 + .../examples/server/applet/wiring.c.o | Bin 0 -> 8800 bytes .../examples/server/applet/wiring_analog.c.o | Bin 0 -> 6512 bytes .../examples/server/applet/wiring_digital.c.o | Bin 0 -> 8220 bytes .../examples/server/applet/wiring_pulse.c.o | Bin 0 -> 6400 bytes .../examples/server/applet/wiring_serial.c.o | Bin 0 -> 7048 bytes .../examples/server/applet/wiring_shift.c.o | Bin 0 -> 4032 bytes .../VirtualWire/examples/server/server.pde | 59 + .../transmitter/applet/HardwareSerial.cpp.o | Bin 0 -> 14308 bytes .../examples/transmitter/applet/Print.cpp.o | Bin 0 -> 22848 bytes .../transmitter/applet/WInterrupts.c.o | Bin 0 -> 5572 bytes .../examples/transmitter/applet/WMath.cpp.o | Bin 0 -> 6980 bytes .../examples/transmitter/applet/core.a | Bin 0 -> 96278 bytes .../transmitter/applet/pins_arduino.c.o | Bin 0 -> 3012 bytes .../transmitter/applet/transmitter.cpp | 52 + .../transmitter/applet/transmitter.cpp.o | Bin 0 -> 4524 bytes .../transmitter/applet/transmitter.eep | 1 + .../transmitter/applet/transmitter.elf | Bin 0 -> 36028 bytes .../transmitter/applet/transmitter.hex | 202 +++ .../transmitter/applet/transmitter.pde | 36 + .../examples/transmitter/applet/wiring.c.o | Bin 0 -> 8800 bytes .../transmitter/applet/wiring_analog.c.o | Bin 0 -> 6512 bytes .../transmitter/applet/wiring_digital.c.o | Bin 0 -> 8220 bytes .../transmitter/applet/wiring_pulse.c.o | Bin 0 -> 6400 bytes .../transmitter/applet/wiring_serial.c.o | Bin 0 -> 7048 bytes .../transmitter/applet/wiring_shift.c.o | Bin 0 -> 4032 bytes .../examples/transmitter/transmitter.pde | 36 + libraries/VirtualWire/keywords.txt | 20 + libraries/VirtualWire/util/crc16.h | 103 ++ .../Visuino_LiquidCrystal/Visuino_FastIO.cpp | 267 +++ .../Visuino_LiquidCrystal/Visuino_FastIO.h | 219 +++ .../Visuino_LiquidCrystal/Visuino_I2CIO.cpp | 198 +++ .../Visuino_LiquidCrystal/Visuino_I2CIO.h | 148 ++ .../Visuino_LiquidCrystal/Visuino_LCD.cpp | 347 ++++ libraries/Visuino_LiquidCrystal/Visuino_LCD.h | 536 ++++++ .../Visuino_LiquidCrystal.cpp | 299 ++++ .../Visuino_LiquidCrystal.h | 161 ++ .../Visuino_LiquidCrystal_I2C.cpp | 291 +++ .../Visuino_LiquidCrystal_I2C.h | 204 +++ .../Visuino_LiquidCrystal_SR.cpp | 209 +++ .../Visuino_LiquidCrystal_SR.h | 176 ++ .../Visuino_LiquidCrystal_SR2W.cpp | 135 ++ .../Visuino_LiquidCrystal_SR2W.h | 202 +++ .../Visuino_LiquidCrystal_SR3W.cpp | 283 +++ .../Visuino_LiquidCrystal_SR3W.h | 202 +++ libraries/Visuino_LiquidCrystal/keywords.txt | 52 + libraries/bmp180/bmp180.cpp | 153 ++ libraries/bmp180/bmp180.h | 36 + libraries/rc-switch-2.52/RCSwitch.cpp | 823 +++++++++ libraries/rc-switch-2.52/RCSwitch.h | 144 ++ libraries/rc-switch-2.52/README.md | 15 + .../ReceiveDemo_Advanced.pde | 24 + .../ReceiveDemo_Advanced/helperfunctions.ino | 20 + .../examples/ReceiveDemo_Advanced/output.ino | 52 + .../ReceiveDemo_Simple/ReceiveDemo_Simple.pde | 35 + .../examples/SendDemo/SendDemo.pde | 57 + .../TypeA_WithDIPSwitches.pde | 40 + .../TypeA_WithDIPSwitches_Lightweight.ino | 43 + .../TypeB_WithRotaryOrSlidingSwitches.pde | 40 + .../TypeC_Intertechno/TypeC_Intertechno.pde | 40 + .../examples/TypeD_REV/TypeD_REV.ino | 41 + .../examples/Webserver/Webserver.pde | 154 ++ libraries/rc-switch-2.52/keywords.txt | 57 + libraries/readme.txt | 1 + .../modified_Examples/receiver/receiver.ino | 53 + .../transmitter/transmitter.ino | 35 + test_Code/pinState/pinState.ino | 7 + test_Code/receive-test/receive-test.ino | 25 + test_Code/receive/receive.ino | 28 + test_Code/transmit-test/transmit-test.ino | 18 + test_Code/transmit/transmit.ino | 241 +++ test_Code/weather_Reciver/weather_Reciver.ino | 174 ++ .../weather_Transmitter.ino | 135 ++ weather_Receiver/weather_Receiver.ino | 215 +++ weather_Transmitter/weather_Transmitter.ino | 229 +++ 321 files changed, 44423 insertions(+) create mode 100644 libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.cpp create mode 100644 libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.h create mode 100644 libraries/Adafruit_BMP085_Unified-master/README.md create mode 100644 libraries/Adafruit_BMP085_Unified-master/examples/sensorapi/sensorapi.pde create mode 100644 libraries/Adafruit_BMP085_Unified-master/library.properties create mode 100644 libraries/Adafruit_DHTxx/DHT.cpp create mode 100644 libraries/Adafruit_DHTxx/DHT.h create mode 100644 libraries/Adafruit_DHTxx/README.md create mode 100644 libraries/Adafruit_DHTxx/examples/DHTtester/DHTtester.ino create mode 100644 libraries/Adafruit_DHTxx/keywords.txt create mode 100644 libraries/Adafruit_DHTxx/library.properties create mode 100644 libraries/Adafruit_Sensor-master/Adafruit_Sensor.h create mode 100644 libraries/Adafruit_Sensor-master/README.md create mode 100644 libraries/Adafruit_Sensor-master/library.properties create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/.gitattributes create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/.gitignore create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/LICENSE.md create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/README.md create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/examples/BMP180_altitude_example/BMP180_altitude_example.ino create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/examples/README.md create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/examples/SFE_BMP180_example/SFE_BMP180_example.ino create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/keywords.txt create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/library.properties create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/src/README.md create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/src/SFE_BMP180.cpp create mode 100644 libraries/BMP180_Breakout_Arduino_Library-master/src/SFE_BMP180.h create mode 100644 libraries/Bridge/README.adoc create mode 100644 libraries/Bridge/examples/Bridge/Bridge.ino create mode 100644 libraries/Bridge/examples/ConsoleAsciiTable/ConsoleAsciiTable.ino create mode 100644 libraries/Bridge/examples/ConsolePixel/ConsolePixel.ino create mode 100644 libraries/Bridge/examples/ConsoleRead/ConsoleRead.ino create mode 100644 libraries/Bridge/examples/Datalogger/Datalogger.ino create mode 100644 libraries/Bridge/examples/FileWriteScript/FileWriteScript.ino create mode 100644 libraries/Bridge/examples/HttpClient/HttpClient.ino create mode 100644 libraries/Bridge/examples/HttpClientConsole/HttpClientConsole.ino create mode 100644 libraries/Bridge/examples/MailboxReadMessage/MailboxReadMessage.ino create mode 100644 libraries/Bridge/examples/Process/Process.ino create mode 100644 libraries/Bridge/examples/RemoteDueBlink/RemoteDueBlink.ino create mode 100644 libraries/Bridge/examples/ShellCommands/ShellCommands.ino create mode 100644 libraries/Bridge/examples/SpacebrewYun/inputOutput/inputOutput.ino create mode 100644 libraries/Bridge/examples/SpacebrewYun/spacebrewBoolean/spacebrewBoolean.ino create mode 100644 libraries/Bridge/examples/SpacebrewYun/spacebrewRange/spacebrewRange.ino create mode 100644 libraries/Bridge/examples/SpacebrewYun/spacebrewString/spacebrewString.ino create mode 100644 libraries/Bridge/examples/TemperatureWebPanel/TemperatureWebPanel.ino create mode 100644 libraries/Bridge/examples/TemperatureWebPanel/www/index.html create mode 100644 libraries/Bridge/examples/TemperatureWebPanel/www/zepto.min.js create mode 100644 libraries/Bridge/examples/TimeCheck/TimeCheck.ino create mode 100644 libraries/Bridge/examples/WiFiStatus/WiFiStatus.ino create mode 100644 libraries/Bridge/examples/YunFirstConfig/YunFirstConfig.ino create mode 100644 libraries/Bridge/examples/YunSerialTerminal/YunSerialTerminal.ino create mode 100644 libraries/Bridge/keywords.txt create mode 100644 libraries/Bridge/library.properties create mode 100644 libraries/Bridge/src/Bridge.cpp create mode 100644 libraries/Bridge/src/Bridge.h create mode 100644 libraries/Bridge/src/BridgeClient.cpp create mode 100644 libraries/Bridge/src/BridgeClient.h create mode 100644 libraries/Bridge/src/BridgeSSLClient.cpp create mode 100644 libraries/Bridge/src/BridgeSSLClient.h create mode 100644 libraries/Bridge/src/BridgeServer.cpp create mode 100644 libraries/Bridge/src/BridgeServer.h create mode 100644 libraries/Bridge/src/BridgeUdp.cpp create mode 100644 libraries/Bridge/src/BridgeUdp.h create mode 100644 libraries/Bridge/src/Console.cpp create mode 100644 libraries/Bridge/src/Console.h create mode 100644 libraries/Bridge/src/FileIO.cpp create mode 100644 libraries/Bridge/src/FileIO.h create mode 100644 libraries/Bridge/src/HttpClient.cpp create mode 100644 libraries/Bridge/src/HttpClient.h create mode 100644 libraries/Bridge/src/Mailbox.cpp create mode 100644 libraries/Bridge/src/Mailbox.h create mode 100644 libraries/Bridge/src/Process.cpp create mode 100644 libraries/Bridge/src/Process.h create mode 100644 libraries/Bridge/src/YunClient.h create mode 100644 libraries/Bridge/src/YunServer.h create mode 100644 libraries/DHT-sensor-library-master/DHT.cpp create mode 100644 libraries/DHT-sensor-library-master/DHT.h create mode 100644 libraries/DHT-sensor-library-master/README.md create mode 100644 libraries/DHT-sensor-library-master/examples/DHTtester/DHTtester.ino create mode 100644 libraries/DHT-sensor-library-master/keywords.txt create mode 100644 libraries/DHT-sensor-library-master/library.properties create mode 100644 libraries/Mitov/Mitov.h create mode 100644 libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/COPYING create mode 100644 libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/MitovEmbedded_Adafruit_NeoPixel.h create mode 100644 libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/README.md create mode 100644 libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/keywords.txt create mode 100644 libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/library.properties create mode 100644 libraries/Mitov/Mitov_7Segment.h create mode 100644 libraries/Mitov/Mitov_Accelerometer.h create mode 100644 libraries/Mitov/Mitov_AmplitudeMeter.h create mode 100644 libraries/Mitov/Mitov_Arduino_SPI.h create mode 100644 libraries/Mitov/Mitov_BMP180_Pressure.h create mode 100644 libraries/Mitov/Mitov_BasicDisplay.h create mode 100644 libraries/Mitov/Mitov_BasicEthernet.h create mode 100644 libraries/Mitov/Mitov_BasicGenerator.h create mode 100644 libraries/Mitov/Mitov_Basic_GPIO.h create mode 100644 libraries/Mitov/Mitov_Basic_I2C.h create mode 100644 libraries/Mitov/Mitov_Basic_RTC.h create mode 100644 libraries/Mitov/Mitov_Basic_SPI.h create mode 100644 libraries/Mitov/Mitov_BinaryDecoder.h create mode 100644 libraries/Mitov/Mitov_BinaryGenerators.h create mode 100644 libraries/Mitov/Mitov_Button.h create mode 100644 libraries/Mitov/Mitov_Color.h create mode 100644 libraries/Mitov/Mitov_CommonMux.h create mode 100644 libraries/Mitov/Mitov_CompassHeading.h create mode 100644 libraries/Mitov/Mitov_Compass_AK8963.h create mode 100644 libraries/Mitov/Mitov_Controllino_RS485.h create mode 100644 libraries/Mitov/Mitov_Controllino_RTC.h create mode 100644 libraries/Mitov/Mitov_Converters.h create mode 100644 libraries/Mitov/Mitov_Counter.h create mode 100644 libraries/Mitov/Mitov_DHT_Sensor.h create mode 100644 libraries/Mitov/Mitov_DateTime.h create mode 100644 libraries/Mitov/Mitov_DigitalsToUnsigned.h create mode 100644 libraries/Mitov/Mitov_Display4DSystems.h create mode 100644 libraries/Mitov/Mitov_ESP8266.h create mode 100644 libraries/Mitov/Mitov_ESP8266_WiFi.h create mode 100644 libraries/Mitov/Mitov_EthernetShield.h create mode 100644 libraries/Mitov/Mitov_FormattedSerial.h create mode 100644 libraries/Mitov/Mitov_FrequencyMeter.h create mode 100644 libraries/Mitov/Mitov_GPRS.h create mode 100644 libraries/Mitov/Mitov_GSMShield.h create mode 100644 libraries/Mitov/Mitov_GaussGenerator.h create mode 100644 libraries/Mitov/Mitov_Goldilocks_DAC.h create mode 100644 libraries/Mitov/Mitov_HMC5883_Compass.h create mode 100644 libraries/Mitov/Mitov_HX711_Weight.h create mode 100644 libraries/Mitov/Mitov_HeatIndex.h create mode 100644 libraries/Mitov/Mitov_InfraredAvoidanceSensor.h create mode 100644 libraries/Mitov/Mitov_Keypad.h create mode 100644 libraries/Mitov/Mitov_L298NDualMotorDriver.h create mode 100644 libraries/Mitov/Mitov_L9110SDualMotorDriver.h create mode 100644 libraries/Mitov/Mitov_LEDBarDisplay.h create mode 100644 libraries/Mitov/Mitov_LEGO_RCX_LightSensor.h create mode 100644 libraries/Mitov/Mitov_LinkIt_GPRS.h create mode 100644 libraries/Mitov/Mitov_LinkIt_WiFi.h create mode 100644 libraries/Mitov/Mitov_LiquidCrystalDisplay.h create mode 100644 libraries/Mitov/Mitov_LogicFlipFlops.h create mode 100644 libraries/Mitov/Mitov_LogicGates.h create mode 100644 libraries/Mitov/Mitov_MPU9250.h create mode 100644 libraries/Mitov/Mitov_Math.h create mode 100644 libraries/Mitov/Mitov_MaximLedControl.h create mode 100644 libraries/Mitov/Mitov_MaximLedControl_7SegmentText.h create mode 100644 libraries/Mitov/Mitov_Maxim_MAX521X.h create mode 100644 libraries/Mitov/Mitov_Maxim_MAX7300.h create mode 100644 libraries/Mitov/Mitov_Maxim_MotorDriverShield.h create mode 100644 libraries/Mitov/Mitov_Maxim_OneWire_Thermometer.h create mode 100644 libraries/Mitov/Mitov_Maxim_Potentiometer_I2C.h create mode 100644 libraries/Mitov/Mitov_MicroSDCard.h create mode 100644 libraries/Mitov/Mitov_Microchip_DAC_SPI.h create mode 100644 libraries/Mitov/Mitov_Microchip_MCP23017.h create mode 100644 libraries/Mitov/Mitov_MultiMerger.h create mode 100644 libraries/Mitov/Mitov_NeoPixel.h create mode 100644 libraries/Mitov/Mitov_PIDController.h create mode 100644 libraries/Mitov/Mitov_PS2_Controller.h create mode 100644 libraries/Mitov/Mitov_PS2_Controller_Basic.h create mode 100644 libraries/Mitov/Mitov_PS2_Controller_Serial.h create mode 100644 libraries/Mitov/Mitov_Packet.h create mode 100644 libraries/Mitov/Mitov_Potentiometer_SPI.h create mode 100644 libraries/Mitov/Mitov_PriorityEncoder.h create mode 100644 libraries/Mitov/Mitov_PulseMeter.h create mode 100644 libraries/Mitov/Mitov_PulseWideModulation.h create mode 100644 libraries/Mitov/Mitov_RCServoMeter.h create mode 100644 libraries/Mitov/Mitov_RTC_DS1302.h create mode 100644 libraries/Mitov/Mitov_RTC_DS1307.h create mode 100644 libraries/Mitov/Mitov_RTC_DS3231.h create mode 100644 libraries/Mitov/Mitov_RampToValue.h create mode 100644 libraries/Mitov/Mitov_RandomGenerator.h create mode 100644 libraries/Mitov/Mitov_Remember.h create mode 100644 libraries/Mitov/Mitov_RotaryEncoderSensor.h create mode 100644 libraries/Mitov/Mitov_Sabertooth_DualMotor.h create mode 100644 libraries/Mitov/Mitov_SchmittTrigger.h create mode 100644 libraries/Mitov/Mitov_Servo.h create mode 100644 libraries/Mitov/Mitov_SimpleList.h create mode 100644 libraries/Mitov/Mitov_SineGenerator.h create mode 100644 libraries/Mitov/Mitov_Snapshot.h create mode 100644 libraries/Mitov/Mitov_SoftwareSPI.h create mode 100644 libraries/Mitov/Mitov_SoftwareSerial.h create mode 100644 libraries/Mitov/Mitov_SpeedToClock.h create mode 100644 libraries/Mitov/Mitov_SpeedToSpeedAndDirection.h create mode 100644 libraries/Mitov/Mitov_SquareGenerator.h create mode 100644 libraries/Mitov/Mitov_Steering_Differential.h create mode 100644 libraries/Mitov/Mitov_Stepper.h create mode 100644 libraries/Mitov/Mitov_StringPrint.h create mode 100644 libraries/Mitov/Mitov_Structure.h create mode 100644 libraries/Mitov/Mitov_TVOut_RCA.h create mode 100644 libraries/Mitov/Mitov_TeensySerial.h create mode 100644 libraries/Mitov/Mitov_TexasInstruments_Thermometer.h create mode 100644 libraries/Mitov/Mitov_Text.h create mode 100644 libraries/Mitov/Mitov_Timing.h create mode 100644 libraries/Mitov/Mitov_TriangleGenerator.h create mode 100644 libraries/Mitov/Mitov_UARTSerial.h create mode 100644 libraries/Mitov/Mitov_USARTSerial.h create mode 100644 libraries/Mitov/Mitov_UltrasonicRanger.h create mode 100644 libraries/Mitov/Mitov_WiFiShield.h create mode 100644 libraries/Mitov/Mitov_Wii_Controller.h create mode 100644 libraries/Mitov/OpenWire.h create mode 100644 libraries/Mitov/README.md create mode 100644 libraries/Mitov/avr/ServoTimers.h create mode 100644 libraries/Mitov/sam/ServoTimers.h create mode 100644 libraries/OneWire/OneWire.cpp create mode 100644 libraries/OneWire/OneWire.h create mode 100644 libraries/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde create mode 100644 libraries/OneWire/examples/DS2408_Switch/DS2408_Switch.pde create mode 100644 libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde create mode 100644 libraries/OneWire/keywords.txt create mode 100644 libraries/OneWire/library.json create mode 100644 libraries/OneWire/library.properties create mode 100644 libraries/VirtualWire/CHANGES create mode 100644 libraries/VirtualWire/LICENSE create mode 100644 libraries/VirtualWire/MANIFEST create mode 100644 libraries/VirtualWire/Makefile create mode 100644 libraries/VirtualWire/README create mode 100644 libraries/VirtualWire/VWutil/crc16.h create mode 100644 libraries/VirtualWire/VirtualWire.cpp create mode 100644 libraries/VirtualWire/VirtualWire.h create mode 100644 libraries/VirtualWire/VirtualWire.o create mode 100644 libraries/VirtualWire/VirtualWire_Config.h create mode 100644 libraries/VirtualWire/examples/client/client.pde create mode 100644 libraries/VirtualWire/examples/receiver/applet/HardwareSerial.cpp.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/Print.cpp.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/WInterrupts.c.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/WMath.cpp.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/core.a create mode 100644 libraries/VirtualWire/examples/receiver/applet/pins_arduino.c.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/receiver.cpp create mode 100644 libraries/VirtualWire/examples/receiver/applet/receiver.cpp.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/receiver.eep create mode 100644 libraries/VirtualWire/examples/receiver/applet/receiver.elf create mode 100644 libraries/VirtualWire/examples/receiver/applet/receiver.hex create mode 100644 libraries/VirtualWire/examples/receiver/applet/receiver.pde create mode 100644 libraries/VirtualWire/examples/receiver/applet/wiring.c.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/wiring_analog.c.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/wiring_digital.c.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/wiring_pulse.c.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/wiring_serial.c.o create mode 100644 libraries/VirtualWire/examples/receiver/applet/wiring_shift.c.o create mode 100644 libraries/VirtualWire/examples/receiver/receiver.pde create mode 100644 libraries/VirtualWire/examples/server/applet/HardwareSerial.cpp.o create mode 100644 libraries/VirtualWire/examples/server/applet/Print.cpp.o create mode 100644 libraries/VirtualWire/examples/server/applet/WInterrupts.c.o create mode 100644 libraries/VirtualWire/examples/server/applet/WMath.cpp.o create mode 100644 libraries/VirtualWire/examples/server/applet/core.a create mode 100644 libraries/VirtualWire/examples/server/applet/pins_arduino.c.o create mode 100644 libraries/VirtualWire/examples/server/applet/server.cpp create mode 100644 libraries/VirtualWire/examples/server/applet/server.cpp.o create mode 100644 libraries/VirtualWire/examples/server/applet/server.eep create mode 100644 libraries/VirtualWire/examples/server/applet/server.elf create mode 100644 libraries/VirtualWire/examples/server/applet/server.hex create mode 100644 libraries/VirtualWire/examples/server/applet/server.pde create mode 100644 libraries/VirtualWire/examples/server/applet/wiring.c.o create mode 100644 libraries/VirtualWire/examples/server/applet/wiring_analog.c.o create mode 100644 libraries/VirtualWire/examples/server/applet/wiring_digital.c.o create mode 100644 libraries/VirtualWire/examples/server/applet/wiring_pulse.c.o create mode 100644 libraries/VirtualWire/examples/server/applet/wiring_serial.c.o create mode 100644 libraries/VirtualWire/examples/server/applet/wiring_shift.c.o create mode 100644 libraries/VirtualWire/examples/server/server.pde create mode 100644 libraries/VirtualWire/examples/transmitter/applet/HardwareSerial.cpp.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/Print.cpp.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/WInterrupts.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/WMath.cpp.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/core.a create mode 100644 libraries/VirtualWire/examples/transmitter/applet/pins_arduino.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/transmitter.cpp create mode 100644 libraries/VirtualWire/examples/transmitter/applet/transmitter.cpp.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/transmitter.eep create mode 100644 libraries/VirtualWire/examples/transmitter/applet/transmitter.elf create mode 100644 libraries/VirtualWire/examples/transmitter/applet/transmitter.hex create mode 100644 libraries/VirtualWire/examples/transmitter/applet/transmitter.pde create mode 100644 libraries/VirtualWire/examples/transmitter/applet/wiring.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/wiring_analog.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/wiring_digital.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/wiring_pulse.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/wiring_serial.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/applet/wiring_shift.c.o create mode 100644 libraries/VirtualWire/examples/transmitter/transmitter.pde create mode 100644 libraries/VirtualWire/keywords.txt create mode 100644 libraries/VirtualWire/util/crc16.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_FastIO.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_FastIO.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_I2CIO.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_I2CIO.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LCD.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LCD.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.h create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.cpp create mode 100644 libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.h create mode 100644 libraries/Visuino_LiquidCrystal/keywords.txt create mode 100644 libraries/bmp180/bmp180.cpp create mode 100644 libraries/bmp180/bmp180.h create mode 100644 libraries/rc-switch-2.52/RCSwitch.cpp create mode 100644 libraries/rc-switch-2.52/RCSwitch.h create mode 100644 libraries/rc-switch-2.52/README.md create mode 100644 libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde create mode 100644 libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/helperfunctions.ino create mode 100644 libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/output.ino create mode 100644 libraries/rc-switch-2.52/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde create mode 100644 libraries/rc-switch-2.52/examples/SendDemo/SendDemo.pde create mode 100644 libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde create mode 100644 libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino create mode 100644 libraries/rc-switch-2.52/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde create mode 100644 libraries/rc-switch-2.52/examples/TypeC_Intertechno/TypeC_Intertechno.pde create mode 100644 libraries/rc-switch-2.52/examples/TypeD_REV/TypeD_REV.ino create mode 100644 libraries/rc-switch-2.52/examples/Webserver/Webserver.pde create mode 100644 libraries/rc-switch-2.52/keywords.txt create mode 100644 libraries/readme.txt create mode 100644 test_Code/modified_Examples/receiver/receiver.ino create mode 100644 test_Code/modified_Examples/transmitter/transmitter.ino create mode 100644 test_Code/pinState/pinState.ino create mode 100644 test_Code/receive-test/receive-test.ino create mode 100644 test_Code/receive/receive.ino create mode 100644 test_Code/transmit-test/transmit-test.ino create mode 100644 test_Code/transmit/transmit.ino create mode 100644 test_Code/weather_Reciver/weather_Reciver.ino create mode 100644 test_Code/weather_Transmitter/weather_Transmitter.ino create mode 100644 weather_Receiver/weather_Receiver.ino create mode 100644 weather_Transmitter/weather_Transmitter.ino diff --git a/libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.cpp b/libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.cpp new file mode 100644 index 0000000..0c077c4 --- /dev/null +++ b/libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.cpp @@ -0,0 +1,481 @@ +/*************************************************************************** + This is a library for the BMP085 pressure sensor + + Designed specifically to work with the Adafruit BMP085 or BMP180 Breakout + ----> http://www.adafruit.com/products/391 + ----> http://www.adafruit.com/products/1603 + + These displays use I2C to communicate, 2 pins are required to interface. + + Adafruit invests time and resources providing this open source code, + please support Adafruit andopen-source hardware by purchasing products + from Adafruit! + + Written by Kevin Townsend for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ***************************************************************************/ +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#ifdef __AVR_ATtiny85__ + #include "TinyWireM.h" + #define Wire TinyWireM +#else + #include +#endif + +#include +#include + +#include "Adafruit_BMP085_U.h" + +static bmp085_calib_data _bmp085_coeffs; // Last read accelerometer data will be available here +static uint8_t _bmp085Mode; + +#define BMP085_USE_DATASHEET_VALS (0) /* Set to 1 for sanity check */ + +/*************************************************************************** + PRIVATE FUNCTIONS + ***************************************************************************/ + +/**************************************************************************/ +/*! + @brief Writes an 8 bit value over I2C +*/ +/**************************************************************************/ +static void writeCommand(byte reg, byte value) +{ + Wire.beginTransmission((uint8_t)BMP085_ADDRESS); + #if ARDUINO >= 100 + Wire.write((uint8_t)reg); + Wire.write((uint8_t)value); + #else + Wire.send(reg); + Wire.send(value); + #endif + Wire.endTransmission(); +} + +/**************************************************************************/ +/*! + @brief Reads an 8 bit value over I2C +*/ +/**************************************************************************/ +static void read8(byte reg, uint8_t *value) +{ + Wire.beginTransmission((uint8_t)BMP085_ADDRESS); + #if ARDUINO >= 100 + Wire.write((uint8_t)reg); + #else + Wire.send(reg); + #endif + Wire.endTransmission(); + Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)1); + #if ARDUINO >= 100 + *value = Wire.read(); + #else + *value = Wire.receive(); + #endif + Wire.endTransmission(); +} + +/**************************************************************************/ +/*! + @brief Reads a 16 bit value over I2C +*/ +/**************************************************************************/ +static void read16(byte reg, uint16_t *value) +{ + Wire.beginTransmission((uint8_t)BMP085_ADDRESS); + #if ARDUINO >= 100 + Wire.write((uint8_t)reg); + #else + Wire.send(reg); + #endif + Wire.endTransmission(); + Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)2); + #if ARDUINO >= 100 + *value = (Wire.read() << 8) | Wire.read(); + #else + *value = (Wire.receive() << 8) | Wire.receive(); + #endif + Wire.endTransmission(); +} + +/**************************************************************************/ +/*! + @brief Reads a signed 16 bit value over I2C +*/ +/**************************************************************************/ +static void readS16(byte reg, int16_t *value) +{ + uint16_t i; + read16(reg, &i); + *value = (int16_t)i; +} + +/**************************************************************************/ +/*! + @brief Reads the factory-set coefficients +*/ +/**************************************************************************/ +static void readCoefficients(void) +{ + #if BMP085_USE_DATASHEET_VALS + _bmp085_coeffs.ac1 = 408; + _bmp085_coeffs.ac2 = -72; + _bmp085_coeffs.ac3 = -14383; + _bmp085_coeffs.ac4 = 32741; + _bmp085_coeffs.ac5 = 32757; + _bmp085_coeffs.ac6 = 23153; + _bmp085_coeffs.b1 = 6190; + _bmp085_coeffs.b2 = 4; + _bmp085_coeffs.mb = -32768; + _bmp085_coeffs.mc = -8711; + _bmp085_coeffs.md = 2868; + _bmp085Mode = 0; + #else + readS16(BMP085_REGISTER_CAL_AC1, &_bmp085_coeffs.ac1); + readS16(BMP085_REGISTER_CAL_AC2, &_bmp085_coeffs.ac2); + readS16(BMP085_REGISTER_CAL_AC3, &_bmp085_coeffs.ac3); + read16(BMP085_REGISTER_CAL_AC4, &_bmp085_coeffs.ac4); + read16(BMP085_REGISTER_CAL_AC5, &_bmp085_coeffs.ac5); + read16(BMP085_REGISTER_CAL_AC6, &_bmp085_coeffs.ac6); + readS16(BMP085_REGISTER_CAL_B1, &_bmp085_coeffs.b1); + readS16(BMP085_REGISTER_CAL_B2, &_bmp085_coeffs.b2); + readS16(BMP085_REGISTER_CAL_MB, &_bmp085_coeffs.mb); + readS16(BMP085_REGISTER_CAL_MC, &_bmp085_coeffs.mc); + readS16(BMP085_REGISTER_CAL_MD, &_bmp085_coeffs.md); + #endif +} + +/**************************************************************************/ +/*! + +*/ +/**************************************************************************/ +static void readRawTemperature(int32_t *temperature) +{ + #if BMP085_USE_DATASHEET_VALS + *temperature = 27898; + #else + uint16_t t; + writeCommand(BMP085_REGISTER_CONTROL, BMP085_REGISTER_READTEMPCMD); + delay(5); + read16(BMP085_REGISTER_TEMPDATA, &t); + *temperature = t; + #endif +} + +/**************************************************************************/ +/*! + +*/ +/**************************************************************************/ +static void readRawPressure(int32_t *pressure) +{ + #if BMP085_USE_DATASHEET_VALS + *pressure = 23843; + #else + uint8_t p8; + uint16_t p16; + int32_t p32; + + writeCommand(BMP085_REGISTER_CONTROL, BMP085_REGISTER_READPRESSURECMD + (_bmp085Mode << 6)); + switch(_bmp085Mode) + { + case BMP085_MODE_ULTRALOWPOWER: + delay(5); + break; + case BMP085_MODE_STANDARD: + delay(8); + break; + case BMP085_MODE_HIGHRES: + delay(14); + break; + case BMP085_MODE_ULTRAHIGHRES: + default: + delay(26); + break; + } + + read16(BMP085_REGISTER_PRESSUREDATA, &p16); + p32 = (uint32_t)p16 << 8; + read8(BMP085_REGISTER_PRESSUREDATA+2, &p8); + p32 += p8; + p32 >>= (8 - _bmp085Mode); + + *pressure = p32; + #endif +} + +/**************************************************************************/ +/*! + @brief Compute B5 coefficient used in temperature & pressure calcs. +*/ +/**************************************************************************/ +int32_t Adafruit_BMP085_Unified::computeB5(int32_t ut) { + int32_t X1 = (ut - (int32_t)_bmp085_coeffs.ac6) * ((int32_t)_bmp085_coeffs.ac5) >> 15; + int32_t X2 = ((int32_t)_bmp085_coeffs.mc << 11) / (X1+(int32_t)_bmp085_coeffs.md); + return X1 + X2; +} + + +/*************************************************************************** + CONSTRUCTOR + ***************************************************************************/ + +/**************************************************************************/ +/*! + @brief Instantiates a new Adafruit_BMP085_Unified class +*/ +/**************************************************************************/ +Adafruit_BMP085_Unified::Adafruit_BMP085_Unified(int32_t sensorID) { + _sensorID = sensorID; +} + +/*************************************************************************** + PUBLIC FUNCTIONS + ***************************************************************************/ + +/**************************************************************************/ +/*! + @brief Setups the HW +*/ +/**************************************************************************/ +bool Adafruit_BMP085_Unified::begin(bmp085_mode_t mode) +{ + // Enable I2C + Wire.begin(); + + /* Mode boundary check */ + if ((mode > BMP085_MODE_ULTRAHIGHRES) || (mode < 0)) + { + mode = BMP085_MODE_ULTRAHIGHRES; + } + + /* Make sure we have the right device */ + uint8_t id; + read8(BMP085_REGISTER_CHIPID, &id); + if(id != 0x55) + { + return false; + } + + /* Set the mode indicator */ + _bmp085Mode = mode; + + /* Coefficients need to be read once */ + readCoefficients(); + + return true; +} + +/**************************************************************************/ +/*! + @brief Gets the compensated pressure level in kPa +*/ +/**************************************************************************/ +void Adafruit_BMP085_Unified::getPressure(float *pressure) +{ + int32_t ut = 0, up = 0, compp = 0; + int32_t x1, x2, b5, b6, x3, b3, p; + uint32_t b4, b7; + + /* Get the raw pressure and temperature values */ + readRawTemperature(&ut); + readRawPressure(&up); + + /* Temperature compensation */ + b5 = computeB5(ut); + + /* Pressure compensation */ + b6 = b5 - 4000; + x1 = (_bmp085_coeffs.b2 * ((b6 * b6) >> 12)) >> 11; + x2 = (_bmp085_coeffs.ac2 * b6) >> 11; + x3 = x1 + x2; + b3 = (((((int32_t) _bmp085_coeffs.ac1) * 4 + x3) << _bmp085Mode) + 2) >> 2; + x1 = (_bmp085_coeffs.ac3 * b6) >> 13; + x2 = (_bmp085_coeffs.b1 * ((b6 * b6) >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + b4 = (_bmp085_coeffs.ac4 * (uint32_t) (x3 + 32768)) >> 15; + b7 = ((uint32_t) (up - b3) * (50000 >> _bmp085Mode)); + + if (b7 < 0x80000000) + { + p = (b7 << 1) / b4; + } + else + { + p = (b7 / b4) << 1; + } + + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + compp = p + ((x1 + x2 + 3791) >> 4); + + /* Assign compensated pressure value */ + *pressure = compp; +} + +/**************************************************************************/ +/*! + @brief Reads the temperatures in degrees Celsius +*/ +/**************************************************************************/ +void Adafruit_BMP085_Unified::getTemperature(float *temp) +{ + int32_t UT, X1, X2, B5; // following ds convention + float t; + + readRawTemperature(&UT); + + #if BMP085_USE_DATASHEET_VALS + // use datasheet numbers! + UT = 27898; + _bmp085_coeffs.ac6 = 23153; + _bmp085_coeffs.ac5 = 32757; + _bmp085_coeffs.mc = -8711; + _bmp085_coeffs.md = 2868; + #endif + + B5 = computeB5(UT); + t = (B5+8) >> 4; + t /= 10; + + *temp = t; +} + +/**************************************************************************/ +/*! + Calculates the altitude (in meters) from the specified atmospheric + pressure (in hPa), and sea-level pressure (in hPa). + + @param seaLevel Sea-level pressure in hPa + @param atmospheric Atmospheric pressure in hPa +*/ +/**************************************************************************/ +float Adafruit_BMP085_Unified::pressureToAltitude(float seaLevel, float atmospheric) +{ + // Equation taken from BMP180 datasheet (page 16): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + + return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); +} + +/**************************************************************************/ +/*! + Calculates the altitude (in meters) from the specified atmospheric + pressure (in hPa), and sea-level pressure (in hPa). Note that this + function just calls the overload of pressureToAltitude which takes + seaLevel and atmospheric pressure--temperature is ignored. The original + implementation of this function was based on calculations from Wikipedia + which are not accurate at higher altitudes. To keep compatibility with + old code this function remains with the same interface, but it calls the + more accurate calculation. + + @param seaLevel Sea-level pressure in hPa + @param atmospheric Atmospheric pressure in hPa + @param temp Temperature in degrees Celsius +*/ +/**************************************************************************/ +float Adafruit_BMP085_Unified::pressureToAltitude(float seaLevel, float atmospheric, float temp) +{ + return pressureToAltitude(seaLevel, atmospheric); +} + +/**************************************************************************/ +/*! + Calculates the pressure at sea level (in hPa) from the specified altitude + (in meters), and atmospheric pressure (in hPa). + + @param altitude Altitude in meters + @param atmospheric Atmospheric pressure in hPa +*/ +/**************************************************************************/ +float Adafruit_BMP085_Unified::seaLevelForAltitude(float altitude, float atmospheric) +{ + // Equation taken from BMP180 datasheet (page 17): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + + return atmospheric / pow(1.0 - (altitude/44330.0), 5.255); +} + +/**************************************************************************/ +/*! + Calculates the pressure at sea level (in hPa) from the specified altitude + (in meters), and atmospheric pressure (in hPa). Note that this + function just calls the overload of seaLevelForAltitude which takes + altitude and atmospheric pressure--temperature is ignored. The original + implementation of this function was based on calculations from Wikipedia + which are not accurate at higher altitudes. To keep compatibility with + old code this function remains with the same interface, but it calls the + more accurate calculation. + + @param altitude Altitude in meters + @param atmospheric Atmospheric pressure in hPa + @param temp Temperature in degrees Celsius +*/ +/**************************************************************************/ +float Adafruit_BMP085_Unified::seaLevelForAltitude(float altitude, float atmospheric, float temp) +{ + return seaLevelForAltitude(altitude, atmospheric); +} + + + +/**************************************************************************/ +/*! + @brief Provides the sensor_t data for this sensor +*/ +/**************************************************************************/ +void Adafruit_BMP085_Unified::getSensor(sensor_t *sensor) +{ + /* Clear the sensor_t object */ + memset(sensor, 0, sizeof(sensor_t)); + + /* Insert the sensor name in the fixed length char array */ + strncpy (sensor->name, "BMP085", sizeof(sensor->name) - 1); + sensor->name[sizeof(sensor->name)- 1] = 0; + sensor->version = 1; + sensor->sensor_id = _sensorID; + sensor->type = SENSOR_TYPE_PRESSURE; + sensor->min_delay = 0; + sensor->max_value = 1100.0F; // 300..1100 hPa + sensor->min_value = 300.0F; + sensor->resolution = 0.01F; // Datasheet states 0.01 hPa resolution +} + +/**************************************************************************/ +/*! + @brief Reads the sensor and returns the data as a sensors_event_t +*/ +/**************************************************************************/ +bool Adafruit_BMP085_Unified::getEvent(sensors_event_t *event) +{ + float pressure_kPa; + + /* Clear the event */ + memset(event, 0, sizeof(sensors_event_t)); + + event->version = sizeof(sensors_event_t); + event->sensor_id = _sensorID; + event->type = SENSOR_TYPE_PRESSURE; + event->timestamp = 0; + getPressure(&pressure_kPa); + event->pressure = pressure_kPa / 100.0F; + + return true; +} diff --git a/libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.h b/libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.h new file mode 100644 index 0000000..d26979d --- /dev/null +++ b/libraries/Adafruit_BMP085_Unified-master/Adafruit_BMP085_U.h @@ -0,0 +1,122 @@ +/*************************************************************************** + This is a library for the BMP085 pressure sensor + + Designed specifically to work with the Adafruit BMP085 or BMP180 Breakout + ----> http://www.adafruit.com/products/391 + ----> http://www.adafruit.com/products/1603 + + These displays use I2C to communicate, 2 pins are required to interface. + + Adafruit invests time and resources providing this open source code, + please support Adafruit andopen-source hardware by purchasing products + from Adafruit! + + Written by Kevin Townsend for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ***************************************************************************/ +#ifndef __BMP085_H__ +#define __BMP085_H__ + +#if (ARDUINO >= 100) + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +#ifdef __AVR_ATtiny85__ + #include "TinyWireM.h" + #define Wire TinyWireM +#else + #include +#endif + +/*========================================================================= + I2C ADDRESS/BITS + -----------------------------------------------------------------------*/ + #define BMP085_ADDRESS (0x77) +/*=========================================================================*/ + +/*========================================================================= + REGISTERS + -----------------------------------------------------------------------*/ + enum + { + BMP085_REGISTER_CAL_AC1 = 0xAA, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_AC2 = 0xAC, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_AC3 = 0xAE, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_AC4 = 0xB0, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_AC5 = 0xB2, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_AC6 = 0xB4, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_B1 = 0xB6, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_B2 = 0xB8, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_MB = 0xBA, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_MC = 0xBC, // R Calibration data (16 bits) + BMP085_REGISTER_CAL_MD = 0xBE, // R Calibration data (16 bits) + BMP085_REGISTER_CHIPID = 0xD0, + BMP085_REGISTER_VERSION = 0xD1, + BMP085_REGISTER_SOFTRESET = 0xE0, + BMP085_REGISTER_CONTROL = 0xF4, + BMP085_REGISTER_TEMPDATA = 0xF6, + BMP085_REGISTER_PRESSUREDATA = 0xF6, + BMP085_REGISTER_READTEMPCMD = 0x2E, + BMP085_REGISTER_READPRESSURECMD = 0x34 + }; +/*=========================================================================*/ + +/*========================================================================= + MODE SETTINGS + -----------------------------------------------------------------------*/ + typedef enum + { + BMP085_MODE_ULTRALOWPOWER = 0, + BMP085_MODE_STANDARD = 1, + BMP085_MODE_HIGHRES = 2, + BMP085_MODE_ULTRAHIGHRES = 3 + } bmp085_mode_t; +/*=========================================================================*/ + +/*========================================================================= + CALIBRATION DATA + -----------------------------------------------------------------------*/ + typedef struct + { + int16_t ac1; + int16_t ac2; + int16_t ac3; + uint16_t ac4; + uint16_t ac5; + uint16_t ac6; + int16_t b1; + int16_t b2; + int16_t mb; + int16_t mc; + int16_t md; + } bmp085_calib_data; +/*=========================================================================*/ + +class Adafruit_BMP085_Unified : public Adafruit_Sensor +{ + public: + Adafruit_BMP085_Unified(int32_t sensorID = -1); + + bool begin(bmp085_mode_t mode = BMP085_MODE_ULTRAHIGHRES); + void getTemperature(float *temp); + void getPressure(float *pressure); + float pressureToAltitude(float seaLvel, float atmospheric); + float seaLevelForAltitude(float altitude, float atmospheric); + // Note that the next two functions are just for compatibility with old + // code that passed the temperature as a third parameter. A newer + // calculation is used which does not need temperature. + float pressureToAltitude(float seaLevel, float atmospheric, float temp); + float seaLevelForAltitude(float altitude, float atmospheric, float temp); + bool getEvent(sensors_event_t*); + void getSensor(sensor_t*); + + private: + int32_t computeB5(int32_t ut); + int32_t _sensorID; +}; + +#endif diff --git a/libraries/Adafruit_BMP085_Unified-master/README.md b/libraries/Adafruit_BMP085_Unified-master/README.md new file mode 100644 index 0000000..cc2e35b --- /dev/null +++ b/libraries/Adafruit_BMP085_Unified-master/README.md @@ -0,0 +1,27 @@ +#Adafruit Unified BMP085/BMP180 Driver (Barometric Pressure Sensor) # + +This driver is for the Adafruit BMP085 Breakout (http://www.adafruit.com/products/391) or BMP180 breakout (http://www.adafruit.com/products/1603), and is based on Adafruit's Unified Sensor Library (Adafruit_Sensor). + +## About the BMP085 / BMP180 ## + +This precision sensor from Bosch is the best low-cost sensing solution for measuring barometric pressure and temperature. Because pressure changes with altitude you can also use it as an altimeter! + +## What is the Adafruit Unified Sensor Library? ## + +The Adafruit Unified Sensor Library ([Adafruit_Sensor](https://github.com/adafruit/Adafruit_Sensor)) provides a common interface and data type for any supported sensor. It defines some basic information about the sensor (sensor limits, etc.), and returns standard SI units of a specific type and scale for each supported sensor type. + +It provides a simple abstraction layer between your application and the actual sensor HW, allowing you to drop in any comparable sensor with only one or two lines of code to change in your project (essentially the constructor since the functions to read sensor data and get information about the sensor are defined in the base Adafruit_Sensor class). + +This is imporant useful for two reasons: + +1.) You can use the data right away because it's already converted to SI units that you understand and can compare, rather than meaningless values like 0..1023. + +2.) Because SI units are standardised in the sensor library, you can also do quick sanity checks when working with new sensors, or drop in any comparable sensor if you need better sensitivity or if a lower cost unit becomes available, etc. + +Light sensors will always report units in lux, gyroscopes will always report units in rad/s, etc. ... freeing you up to focus on the data, rather than digging through the datasheet to understand what the sensor's raw numbers really mean. + +## About this Driver ## + +Adafruit invests time and resources providing this open source code. Please support Adafruit and open-source hardware by purchasing products from Adafruit! + +Written by Kevin (KTOWN) Townsend for Adafruit Industries. diff --git a/libraries/Adafruit_BMP085_Unified-master/examples/sensorapi/sensorapi.pde b/libraries/Adafruit_BMP085_Unified-master/examples/sensorapi/sensorapi.pde new file mode 100644 index 0000000..46b7b51 --- /dev/null +++ b/libraries/Adafruit_BMP085_Unified-master/examples/sensorapi/sensorapi.pde @@ -0,0 +1,132 @@ +#include +#include +#include + +/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor), + which provides a common 'type' for sensor data and some helper functions. + + To use this driver you will also need to download the Adafruit_Sensor + library and include it in your libraries folder. + + You should also assign a unique ID to this sensor for use with + the Adafruit Sensor API so that you can identify this particular + sensor in any data logs, etc. To assign a unique ID, simply + provide an appropriate value in the constructor below (12345 + is used by default in this example). + + Connections + =========== + Connect SCL to analog 5 + Connect SDA to analog 4 + Connect VDD to 3.3V DC + Connect GROUND to common ground + + History + ======= + 2013/JUN/17 - Updated altitude calculations (KTOWN) + 2013/FEB/13 - First version (KTOWN) +*/ + +Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085); + +/**************************************************************************/ +/* + Displays some basic information on this sensor from the unified + sensor API sensor_t type (see Adafruit_Sensor for more information) +*/ +/**************************************************************************/ +void displaySensorDetails(void) +{ + sensor_t sensor; + bmp.getSensor(&sensor); + Serial.println("------------------------------------"); + Serial.print ("Sensor: "); Serial.println(sensor.name); + Serial.print ("Driver Ver: "); Serial.println(sensor.version); + Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); + Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" hPa"); + Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" hPa"); + Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" hPa"); + Serial.println("------------------------------------"); + Serial.println(""); + delay(500); +} + +/**************************************************************************/ +/* + Arduino setup function (automatically called at startup) +*/ +/**************************************************************************/ +void setup(void) +{ + Serial.begin(9600); + Serial.println("Pressure Sensor Test"); Serial.println(""); + + /* Initialise the sensor */ + if(!bmp.begin()) + { + /* There was a problem detecting the BMP085 ... check your connections */ + Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!"); + while(1); + } + + /* Display some basic information on this sensor */ + displaySensorDetails(); +} + +/**************************************************************************/ +/* + Arduino loop function, called once 'setup' is complete (your own code + should go here) +*/ +/**************************************************************************/ +void loop(void) +{ + /* Get a new sensor event */ + sensors_event_t event; + bmp.getEvent(&event); + + /* Display the results (barometric pressure is measure in hPa) */ + if (event.pressure) + { + /* Display atmospheric pressue in hPa */ + Serial.print("Pressure: "); + Serial.print(event.pressure); + Serial.println(" hPa"); + + /* Calculating altitude with reasonable accuracy requires pressure * + * sea level pressure for your position at the moment the data is * + * converted, as well as the ambient temperature in degress * + * celcius. If you don't have these values, a 'generic' value of * + * 1013.25 hPa can be used (defined as SENSORS_PRESSURE_SEALEVELHPA * + * in sensors.h), but this isn't ideal and will give variable * + * results from one day to the next. * + * * + * You can usually find the current SLP value by looking at weather * + * websites or from environmental information centers near any major * + * airport. * + * * + * For example, for Paris, France you can check the current mean * + * pressure and sea level at: http://bit.ly/16Au8ol */ + + /* First we get the current temperature from the BMP085 */ + float temperature; + bmp.getTemperature(&temperature); + Serial.print("Temperature: "); + Serial.print(temperature); + Serial.println(" C"); + + /* Then convert the atmospheric pressure, and SLP to altitude */ + /* Update this next line with the current SLP for better results */ + float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA; + Serial.print("Altitude: "); + Serial.print(bmp.pressureToAltitude(seaLevelPressure, + event.pressure)); + Serial.println(" m"); + Serial.println(""); + } + else + { + Serial.println("Sensor error"); + } + delay(1000); +} diff --git a/libraries/Adafruit_BMP085_Unified-master/library.properties b/libraries/Adafruit_BMP085_Unified-master/library.properties new file mode 100644 index 0000000..392b259 --- /dev/null +++ b/libraries/Adafruit_BMP085_Unified-master/library.properties @@ -0,0 +1,9 @@ +name=Adafruit BMP085 Unified +version=1.0.0 +author=Adafruit +maintainer=Adafruit +sentence=Unified sensor driver for Adafruit's BMP085 & BMP180 breakouts +paragraph=Unified sensor driver for Adafruit's BMP085 & BMP180 breakouts +category=Sensors +url=https://github.com/adafruit/Adafruit_BMP085_Unified +architectures=* diff --git a/libraries/Adafruit_DHTxx/DHT.cpp b/libraries/Adafruit_DHTxx/DHT.cpp new file mode 100644 index 0000000..86ad91c --- /dev/null +++ b/libraries/Adafruit_DHTxx/DHT.cpp @@ -0,0 +1,259 @@ +/* DHT library + +MIT license +written by Adafruit Industries +*/ + +#include "DHT.h" + +#define MIN_INTERVAL 2000 + +DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) { + _pin = pin; + _type = type; + #ifdef __AVR + _bit = digitalPinToBitMask(pin); + _port = digitalPinToPort(pin); + #endif + _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for + // reading pulses from DHT sensor. + // Note that count is now ignored as the DHT reading algorithm adjusts itself + // basd on the speed of the processor. +} + +void DHT::begin(void) { + // set up the pins! + pinMode(_pin, INPUT_PULLUP); + // Using this value makes sure that millis() - lastreadtime will be + // >= MIN_INTERVAL right away. Note that this assignment wraps around, + // but so will the subtraction. + _lastreadtime = -MIN_INTERVAL; + DEBUG_PRINT("Max clock cycles: "); DEBUG_PRINTLN(_maxcycles, DEC); +} + +//boolean S == Scale. True == Fahrenheit; False == Celcius +float DHT::readTemperature(bool S, bool force) { + float f = NAN; + + if (read(force)) { + switch (_type) { + case DHT11: + f = data[2]; + if(S) { + f = convertCtoF(f); + } + break; + case DHT22: + case DHT21: + f = data[2] & 0x7F; + f *= 256; + f += data[3]; + f *= 0.1; + if (data[2] & 0x80) { + f *= -1; + } + if(S) { + f = convertCtoF(f); + } + break; + } + } + return f; +} + +float DHT::convertCtoF(float c) { + return c * 1.8 + 32; +} + +float DHT::convertFtoC(float f) { + return (f - 32) * 0.55555; +} + +float DHT::readHumidity(bool force) { + float f = NAN; + if (read()) { + switch (_type) { + case DHT11: + f = data[0]; + break; + case DHT22: + case DHT21: + f = data[0]; + f *= 256; + f += data[1]; + f *= 0.1; + break; + } + } + return f; +} + +//boolean isFahrenheit: True == Fahrenheit; False == Celcius +float DHT::computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit) { + // Using both Rothfusz and Steadman's equations + // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml + float hi; + + if (!isFahrenheit) + temperature = convertCtoF(temperature); + + hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (percentHumidity * 0.094)); + + if (hi > 79) { + hi = -42.379 + + 2.04901523 * temperature + + 10.14333127 * percentHumidity + + -0.22475541 * temperature*percentHumidity + + -0.00683783 * pow(temperature, 2) + + -0.05481717 * pow(percentHumidity, 2) + + 0.00122874 * pow(temperature, 2) * percentHumidity + + 0.00085282 * temperature*pow(percentHumidity, 2) + + -0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2); + + if((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0)) + hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882); + + else if((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0)) + hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2); + } + + return isFahrenheit ? hi : convertFtoC(hi); +} + +boolean DHT::read(bool force) { + // Check if sensor was read less than two seconds ago and return early + // to use last reading. + uint32_t currenttime = millis(); + if (!force && ((currenttime - _lastreadtime) < 2000)) { + return _lastresult; // return last correct measurement + } + _lastreadtime = currenttime; + + // Reset 40 bits of received data to zero. + data[0] = data[1] = data[2] = data[3] = data[4] = 0; + + // Send start signal. See DHT datasheet for full signal diagram: + // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf + + // Go into high impedence state to let pull-up raise data line level and + // start the reading process. + digitalWrite(_pin, HIGH); + delay(250); + + // First set data line low for 20 milliseconds. + pinMode(_pin, OUTPUT); + digitalWrite(_pin, LOW); + delay(20); + + uint32_t cycles[80]; + { + // Turn off interrupts temporarily because the next sections are timing critical + // and we don't want any interruptions. + InterruptLock lock; + + // End the start signal by setting data line high for 40 microseconds. + digitalWrite(_pin, HIGH); + delayMicroseconds(40); + + // Now start reading the data line to get the value from the DHT sensor. + pinMode(_pin, INPUT_PULLUP); + delayMicroseconds(10); // Delay a bit to let sensor pull data line low. + + // First expect a low signal for ~80 microseconds followed by a high signal + // for ~80 microseconds again. + if (expectPulse(LOW) == 0) { + DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse.")); + _lastresult = false; + return _lastresult; + } + if (expectPulse(HIGH) == 0) { + DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse.")); + _lastresult = false; + return _lastresult; + } + + // Now read the 40 bits sent by the sensor. Each bit is sent as a 50 + // microsecond low pulse followed by a variable length high pulse. If the + // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds + // then it's a 1. We measure the cycle count of the initial 50us low pulse + // and use that to compare to the cycle count of the high pulse to determine + // if the bit is a 0 (high state cycle count < low state cycle count), or a + // 1 (high state cycle count > low state cycle count). Note that for speed all + // the pulses are read into a array and then examined in a later step. + for (int i=0; i<80; i+=2) { + cycles[i] = expectPulse(LOW); + cycles[i+1] = expectPulse(HIGH); + } + } // Timing critical code is now complete. + + // Inspect pulses and determine which ones are 0 (high state cycle count < low + // state cycle count), or 1 (high state cycle count > low state cycle count). + for (int i=0; i<40; ++i) { + uint32_t lowCycles = cycles[2*i]; + uint32_t highCycles = cycles[2*i+1]; + if ((lowCycles == 0) || (highCycles == 0)) { + DEBUG_PRINTLN(F("Timeout waiting for pulse.")); + _lastresult = false; + return _lastresult; + } + data[i/8] <<= 1; + // Now compare the low and high cycle times to see if the bit is a 0 or 1. + if (highCycles > lowCycles) { + // High cycles are greater than 50us low cycle count, must be a 1. + data[i/8] |= 1; + } + // Else high cycles are less than (or equal to, a weird case) the 50us low + // cycle count so this must be a zero. Nothing needs to be changed in the + // stored data. + } + + DEBUG_PRINTLN(F("Received:")); + DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? ")); + DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX); + + // Check we read 40 bits and that the checksum matches. + if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { + _lastresult = true; + return _lastresult; + } + else { + DEBUG_PRINTLN(F("Checksum failure!")); + _lastresult = false; + return _lastresult; + } +} + +// Expect the signal line to be at the specified level for a period of time and +// return a count of loop cycles spent at that level (this cycle count can be +// used to compare the relative time of two pulses). If more than a millisecond +// ellapses without the level changing then the call fails with a 0 response. +// This is adapted from Arduino's pulseInLong function (which is only available +// in the very latest IDE versions): +// https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c +uint32_t DHT::expectPulse(bool level) { + uint32_t count = 0; + // On AVR platforms use direct GPIO port access as it's much faster and better + // for catching pulses that are 10's of microseconds in length: + #ifdef __AVR + uint8_t portState = level ? _bit : 0; + while ((*portInputRegister(_port) & _bit) == portState) { + if (count++ >= _maxcycles) { + return 0; // Exceeded timeout, fail. + } + } + // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266 + // right now, perhaps bugs in direct port access functions?). + #else + while (digitalRead(_pin) == level) { + if (count++ >= _maxcycles) { + return 0; // Exceeded timeout, fail. + } + } + #endif + + return count; +} diff --git a/libraries/Adafruit_DHTxx/DHT.h b/libraries/Adafruit_DHTxx/DHT.h new file mode 100644 index 0000000..d81f6db --- /dev/null +++ b/libraries/Adafruit_DHTxx/DHT.h @@ -0,0 +1,75 @@ +/* DHT library + +MIT license +written by Adafruit Industries +*/ +#ifndef DHT_H +#define DHT_H + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + + +// Uncomment to enable printing out nice debug messages. +//#define DHT_DEBUG + +// Define where debug output will be printed. +#define DEBUG_PRINTER Serial + +// Setup debug printing macros. +#ifdef DHT_DEBUG + #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); } + #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); } +#else + #define DEBUG_PRINT(...) {} + #define DEBUG_PRINTLN(...) {} +#endif + +// Define types of sensors. +#define DHT11 11 +#define DHT22 22 +#define DHT21 21 +#define AM2301 21 + + +class DHT { + public: + DHT(uint8_t pin, uint8_t type, uint8_t count=6); + void begin(void); + float readTemperature(bool S=false, bool force=false); + float convertCtoF(float); + float convertFtoC(float); + float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=true); + float readHumidity(bool force=false); + boolean read(bool force=false); + + private: + uint8_t data[5]; + uint8_t _pin, _type; + #ifdef __AVR + // Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask + // for the digital pin connected to the DHT. Other platforms will use digitalRead. + uint8_t _bit, _port; + #endif + uint32_t _lastreadtime, _maxcycles; + bool _lastresult; + + uint32_t expectPulse(bool level); + +}; + +class InterruptLock { + public: + InterruptLock() { + noInterrupts(); + } + ~InterruptLock() { + interrupts(); + } + +}; + +#endif diff --git a/libraries/Adafruit_DHTxx/README.md b/libraries/Adafruit_DHTxx/README.md new file mode 100644 index 0000000..8bd49ff --- /dev/null +++ b/libraries/Adafruit_DHTxx/README.md @@ -0,0 +1,5 @@ +This is an Arduino library for the DHT series of low cost temperature/humidity sensors. + +Tutorial: https://learn.adafruit.com/dht + +To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder DHT. Check that the DHT folder contains DHT.cpp and DHT.h. Place the DHT library folder your /libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE. diff --git a/libraries/Adafruit_DHTxx/examples/DHTtester/DHTtester.ino b/libraries/Adafruit_DHTxx/examples/DHTtester/DHTtester.ino new file mode 100644 index 0000000..ae6c41a --- /dev/null +++ b/libraries/Adafruit_DHTxx/examples/DHTtester/DHTtester.ino @@ -0,0 +1,69 @@ +// Example testing sketch for various DHT humidity/temperature sensors +// Written by ladyada, public domain + +#include "DHT.h" + +#define DHTPIN 2 // what digital pin we're connected to + +// Uncomment whatever type you're using! +//#define DHTTYPE DHT11 // DHT 11 +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 +//#define DHTTYPE DHT21 // DHT 21 (AM2301) + +// Connect pin 1 (on the left) of the sensor to +5V +// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 +// to 3.3V instead of 5V! +// Connect pin 2 of the sensor to whatever your DHTPIN is +// Connect pin 4 (on the right) of the sensor to GROUND +// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor + +// Initialize DHT sensor. +// Note that older versions of this library took an optional third parameter to +// tweak the timings for faster processors. This parameter is no longer needed +// as the current DHT reading algorithm adjusts itself to work on faster procs. +DHT dht(DHTPIN, DHTTYPE); + +void setup() { + Serial.begin(9600); + Serial.println("DHTxx test!"); + + dht.begin(); +} + +void loop() { + // Wait a few seconds between measurements. + delay(2000); + + // Reading temperature or humidity takes about 250 milliseconds! + // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) + float h = dht.readHumidity(); + // Read temperature as Celsius (the default) + float t = dht.readTemperature(); + // Read temperature as Fahrenheit (isFahrenheit = true) + float f = dht.readTemperature(true); + + // Check if any reads failed and exit early (to try again). + if (isnan(h) || isnan(t) || isnan(f)) { + Serial.println("Failed to read from DHT sensor!"); + return; + } + + // Compute heat index in Fahrenheit (the default) + float hif = dht.computeHeatIndex(f, h); + // Compute heat index in Celsius (isFahreheit = false) + float hic = dht.computeHeatIndex(t, h, false); + + Serial.print("Humidity: "); + Serial.print(h); + Serial.print(" %\t"); + Serial.print("Temperature: "); + Serial.print(t); + Serial.print(" *C "); + Serial.print(f); + Serial.print(" *F\t"); + Serial.print("Heat index: "); + Serial.print(hic); + Serial.print(" *C "); + Serial.print(hif); + Serial.println(" *F"); +} diff --git a/libraries/Adafruit_DHTxx/keywords.txt b/libraries/Adafruit_DHTxx/keywords.txt new file mode 100644 index 0000000..146d4fa --- /dev/null +++ b/libraries/Adafruit_DHTxx/keywords.txt @@ -0,0 +1,22 @@ +########################################### +# Syntax Coloring Map For DHT-sensor-library +########################################### + +########################################### +# Datatypes (KEYWORD1) +########################################### + +DHT KEYWORD1 + +########################################### +# Methods and Functions (KEYWORD2) +########################################### + +begin KEYWORD2 +readTemperature KEYWORD2 +convertCtoF KEYWORD2 +convertFtoC KEYWORD2 +computeHeatIndex KEYWORD2 +readHumidity KEYWORD2 +read KEYWORD2 + diff --git a/libraries/Adafruit_DHTxx/library.properties b/libraries/Adafruit_DHTxx/library.properties new file mode 100644 index 0000000..c85a332 --- /dev/null +++ b/libraries/Adafruit_DHTxx/library.properties @@ -0,0 +1,9 @@ +name=DHT sensor library +version=1.2.3 +author=Adafruit +maintainer=Adafruit +sentence=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors +paragraph=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors +category=Sensors +url=https://github.com/adafruit/DHT-sensor-library +architectures=* diff --git a/libraries/Adafruit_Sensor-master/Adafruit_Sensor.h b/libraries/Adafruit_Sensor-master/Adafruit_Sensor.h new file mode 100644 index 0000000..7742afc --- /dev/null +++ b/libraries/Adafruit_Sensor-master/Adafruit_Sensor.h @@ -0,0 +1,154 @@ +/* +* Copyright (C) 2008 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software< /span> +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and + * extended sensor support to include color, voltage and current */ + +#ifndef _ADAFRUIT_SENSOR_H +#define _ADAFRUIT_SENSOR_H + +#if ARDUINO >= 100 + #include "Arduino.h" + #include "Print.h" +#else + #include "WProgram.h" +#endif + +/* Intentionally modeled after sensors.h in the Android API: + * https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */ + +/* Constants */ +#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */ +#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */ +#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */ +#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH) +#define SENSORS_MAGFIELD_EARTH_MAX (60.0F) /**< Maximum magnetic field on Earth's surface */ +#define SENSORS_MAGFIELD_EARTH_MIN (30.0F) /**< Minimum magnetic field on Earth's surface */ +#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) /**< Average sea level pressure is 1013.25 hPa */ +#define SENSORS_DPS_TO_RADS (0.017453293F) /**< Degrees/s to rad/s multiplier */ +#define SENSORS_GAUSS_TO_MICROTESLA (100) /**< Gauss to micro-Tesla multiplier */ + +/** Sensor types */ +typedef enum +{ + SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */ + SENSOR_TYPE_MAGNETIC_FIELD = (2), + SENSOR_TYPE_ORIENTATION = (3), + SENSOR_TYPE_GYROSCOPE = (4), + SENSOR_TYPE_LIGHT = (5), + SENSOR_TYPE_PRESSURE = (6), + SENSOR_TYPE_PROXIMITY = (8), + SENSOR_TYPE_GRAVITY = (9), + SENSOR_TYPE_LINEAR_ACCELERATION = (10), /**< Acceleration not including gravity */ + SENSOR_TYPE_ROTATION_VECTOR = (11), + SENSOR_TYPE_RELATIVE_HUMIDITY = (12), + SENSOR_TYPE_AMBIENT_TEMPERATURE = (13), + SENSOR_TYPE_VOLTAGE = (15), + SENSOR_TYPE_CURRENT = (16), + SENSOR_TYPE_COLOR = (17) +} sensors_type_t; + +/** struct sensors_vec_s is used to return a vector in a common format. */ +typedef struct { + union { + float v[3]; + struct { + float x; + float y; + float z; + }; + /* Orientation sensors */ + struct { + float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */ + float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */ + float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */ + }; + }; + int8_t status; + uint8_t reserved[3]; +} sensors_vec_t; + +/** struct sensors_color_s is used to return color data in a common format. */ +typedef struct { + union { + float c[3]; + /* RGB color space */ + struct { + float r; /**< Red component */ + float g; /**< Green component */ + float b; /**< Blue component */ + }; + }; + uint32_t rgba; /**< 24-bit RGBA value */ +} sensors_color_t; + +/* Sensor event (36 bytes) */ +/** struct sensor_event_s is used to provide a single sensor event in a common format. */ +typedef struct +{ + int32_t version; /**< must be sizeof(struct sensors_event_t) */ + int32_t sensor_id; /**< unique sensor identifier */ + int32_t type; /**< sensor type */ + int32_t reserved0; /**< reserved */ + int32_t timestamp; /**< time is in milliseconds */ + union + { + float data[4]; + sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */ + sensors_vec_t magnetic; /**< magnetic vector values are in micro-Tesla (uT) */ + sensors_vec_t orientation; /**< orientation values are in degrees */ + sensors_vec_t gyro; /**< gyroscope values are in rad/s */ + float temperature; /**< temperature is in degrees centigrade (Celsius) */ + float distance; /**< distance in centimeters */ + float light; /**< light in SI lux units */ + float pressure; /**< pressure in hectopascal (hPa) */ + float relative_humidity; /**< relative humidity in percent */ + float current; /**< current in milliamps (mA) */ + float voltage; /**< voltage in volts (V) */ + sensors_color_t color; /**< color in RGB component values */ + }; +} sensors_event_t; + +/* Sensor details (40 bytes) */ +/** struct sensor_s is used to describe basic information about a specific sensor. */ +typedef struct +{ + char name[12]; /**< sensor name */ + int32_t version; /**< version of the hardware + driver */ + int32_t sensor_id; /**< unique sensor identifier */ + int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */ + float max_value; /**< maximum value of this sensor's value in SI units */ + float min_value; /**< minimum value of this sensor's value in SI units */ + float resolution; /**< smallest difference between two values reported by this sensor */ + int32_t min_delay; /**< min delay in microseconds between events. zero = not a constant rate */ +} sensor_t; + +class Adafruit_Sensor { + public: + // Constructor(s) + Adafruit_Sensor() {} + virtual ~Adafruit_Sensor() {} + + // These must be defined by the subclass + virtual void enableAutoRange(bool enabled) {}; + virtual bool getEvent(sensors_event_t*) = 0; + virtual void getSensor(sensor_t*) = 0; + + private: + bool _autoRange; +}; + +#endif diff --git a/libraries/Adafruit_Sensor-master/README.md b/libraries/Adafruit_Sensor-master/README.md new file mode 100644 index 0000000..7e56bf9 --- /dev/null +++ b/libraries/Adafruit_Sensor-master/README.md @@ -0,0 +1,221 @@ +# Adafruit Unified Sensor Driver # + +Many small embedded systems exist to collect data from sensors, analyse the data, and either take an appropriate action or send that sensor data to another system for processing. + +One of the many challenges of embedded systems design is the fact that parts you used today may be out of production tomorrow, or system requirements may change and you may need to choose a different sensor down the road. + +Creating new drivers is a relatively easy task, but integrating them into existing systems is both error prone and time consuming since sensors rarely use the exact same units of measurement. + +By reducing all data to a single **sensors\_event\_t** 'type' and settling on specific, **standardised SI units** for each sensor family the same sensor types return values that are comparable with any other similar sensor. This enables you to switch sensor models with very little impact on the rest of the system, which can help mitigate some of the risks and problems of sensor availability and code reuse. + +The unified sensor abstraction layer is also useful for data-logging and data-transmission since you only have one well-known type to log or transmit over the air or wire. + +## Unified Sensor Drivers ## + +The following drivers are based on the Adafruit Unified Sensor Driver: + +**Accelerometers** + - [Adafruit\_ADXL345](https://github.com/adafruit/Adafruit_ADXL345) + - [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC) + - [Adafruit\_MMA8451\_Library](https://github.com/adafruit/Adafruit_MMA8451_Library) + +**Gyroscope** + - [Adafruit\_L3GD20\_U](https://github.com/adafruit/Adafruit_L3GD20_U) + +**Light** + - [Adafruit\_TSL2561](https://github.com/adafruit/Adafruit_TSL2561) + - [Adafruit\_TSL2591\_Library](https://github.com/adafruit/Adafruit_TSL2591_Library) + +**Magnetometers** + - [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC) + - [Adafruit\_HMC5883\_Unified](https://github.com/adafruit/Adafruit_HMC5883_Unified) + +**Barometric Pressure** + - [Adafruit\_BMP085\_Unified](https://github.com/adafruit/Adafruit_BMP085_Unified) + - [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library) + +**Humidity & Temperature** + - [Adafruit\_DHT\_Unified](https://github.com/adafruit/Adafruit_DHT_Unified) + +**Orientation** + - [Adafruit_BNO055](https://github.com/adafruit/Adafruit_BNO055) + +## How Does it Work? ## + +Any driver that supports the Adafruit unified sensor abstraction layer will implement the Adafruit\_Sensor base class. There are two main typedefs and one enum defined in Adafruit_Sensor.h that are used to 'abstract' away the sensor details and values: + +**Sensor Types (sensors\_type\_t)** + +These pre-defined sensor types are used to properly handle the two related typedefs below, and allows us determine what types of units the sensor uses, etc. + +``` +/** Sensor types */ +typedef enum +{ + SENSOR_TYPE_ACCELEROMETER = (1), + SENSOR_TYPE_MAGNETIC_FIELD = (2), + SENSOR_TYPE_ORIENTATION = (3), + SENSOR_TYPE_GYROSCOPE = (4), + SENSOR_TYPE_LIGHT = (5), + SENSOR_TYPE_PRESSURE = (6), + SENSOR_TYPE_PROXIMITY = (8), + SENSOR_TYPE_GRAVITY = (9), + SENSOR_TYPE_LINEAR_ACCELERATION = (10), + SENSOR_TYPE_ROTATION_VECTOR = (11), + SENSOR_TYPE_RELATIVE_HUMIDITY = (12), + SENSOR_TYPE_AMBIENT_TEMPERATURE = (13), + SENSOR_TYPE_VOLTAGE = (15), + SENSOR_TYPE_CURRENT = (16), + SENSOR_TYPE_COLOR = (17) +} sensors_type_t; +``` + +**Sensor Details (sensor\_t)** + +This typedef describes the specific capabilities of this sensor, and allows us to know what sensor we are using beneath the abstraction layer. + +``` +/* Sensor details (40 bytes) */ +/** struct sensor_s is used to describe basic information about a specific sensor. */ +typedef struct +{ + char name[12]; + int32_t version; + int32_t sensor_id; + int32_t type; + float max_value; + float min_value; + float resolution; + int32_t min_delay; +} sensor_t; +``` + +The individual fields are intended to be used as follows: + +- **name**: The sensor name or ID, up to a maximum of twelve characters (ex. "MPL115A2") +- **version**: The version of the sensor HW and the driver to allow us to differentiate versions of the board or driver +- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network +- **type**: The sensor type, based on **sensors\_type\_t** in sensors.h +- **max\_value**: The maximum value that this sensor can return (in the appropriate SI unit) +- **min\_value**: The minimum value that this sensor can return (in the appropriate SI unit) +- **resolution**: The smallest difference between two values that this sensor can report (in the appropriate SI unit) +- **min\_delay**: The minimum delay in microseconds between two sensor events, or '0' if there is no constant sensor rate + +**Sensor Data/Events (sensors\_event\_t)** + +This typedef is used to return sensor data from any sensor supported by the abstraction layer, using standard SI units and scales. + +``` +/* Sensor event (36 bytes) */ +/** struct sensor_event_s is used to provide a single sensor event in a common format. */ +typedef struct +{ + int32_t version; + int32_t sensor_id; + int32_t type; + int32_t reserved0; + int32_t timestamp; + union + { + float data[4]; + sensors_vec_t acceleration; + sensors_vec_t magnetic; + sensors_vec_t orientation; + sensors_vec_t gyro; + float temperature; + float distance; + float light; + float pressure; + float relative_humidity; + float current; + float voltage; + sensors_color_t color; + }; +} sensors_event_t; +``` +It includes the following fields: + +- **version**: Contain 'sizeof(sensors\_event\_t)' to identify which version of the API we're using in case this changes in the future +- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network (must match the sensor\_id value in the corresponding sensor\_t enum above!) +- **type**: the sensor type, based on **sensors\_type\_t** in sensors.h +- **timestamp**: time in milliseconds when the sensor value was read +- **data[4]**: An array of four 32-bit values that allows us to encapsulate any type of sensor data via a simple union (further described below) + +**Required Functions** + +In addition to the two standard types and the sensor type enum, all drivers based on Adafruit_Sensor must also implement the following two functions: + +``` +bool getEvent(sensors_event_t*); +``` +Calling this function will populate the supplied sensors\_event\_t reference with the latest available sensor data. You should call this function as often as you want to update your data. + +``` +void getSensor(sensor_t*); +``` +Calling this function will provide some basic information about the sensor (the sensor name, driver version, min and max values, etc. + +**Standardised SI values for sensors\_event\_t** + +A key part of the abstraction layer is the standardisation of values on SI units of a particular scale, which is accomplished via the data[4] union in sensors\_event\_t above. This 16 byte union includes fields for each main sensor type, and uses the following SI units and scales: + +- **acceleration**: values are in **meter per second per second** (m/s^2) +- **magnetic**: values are in **micro-Tesla** (uT) +- **orientation**: values are in **degrees** +- **gyro**: values are in **rad/s** +- **temperature**: values in **degrees centigrade** (Celsius) +- **distance**: values are in **centimeters** +- **light**: values are in **SI lux** units +- **pressure**: values are in **hectopascal** (hPa) +- **relative\_humidity**: values are in **percent** +- **current**: values are in **milliamps** (mA) +- **voltage**: values are in **volts** (V) +- **color**: values are in 0..1.0 RGB channel luminosity and 32-bit RGBA format + +## The Unified Driver Abstraction Layer in Practice ## + +Using the unified sensor abstraction layer is relatively easy once a compliant driver has been created. + +Every compliant sensor can now be read using a single, well-known 'type' (sensors\_event\_t), and there is a standardised way of interrogating a sensor about its specific capabilities (via sensor\_t). + +An example of reading the [TSL2561](https://github.com/adafruit/Adafruit_TSL2561) light sensor can be seen below: + +``` + Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345); + ... + /* Get a new sensor event */ + sensors_event_t event; + tsl.getEvent(&event); + + /* Display the results (light is measured in lux) */ + if (event.light) + { + Serial.print(event.light); Serial.println(" lux"); + } + else + { + /* If event.light = 0 lux the sensor is probably saturated + and no reliable data could be generated! */ + Serial.println("Sensor overload"); + } +``` + +Similarly, we can get the basic technical capabilities of this sensor with the following code: + +``` + sensor_t sensor; + + sensor_t sensor; + tsl.getSensor(&sensor); + + /* Display the sensor details */ + Serial.println("------------------------------------"); + Serial.print ("Sensor: "); Serial.println(sensor.name); + Serial.print ("Driver Ver: "); Serial.println(sensor.version); + Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); + Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux"); + Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux"); + Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux"); + Serial.println("------------------------------------"); + Serial.println(""); +``` diff --git a/libraries/Adafruit_Sensor-master/library.properties b/libraries/Adafruit_Sensor-master/library.properties new file mode 100644 index 0000000..fa7eefa --- /dev/null +++ b/libraries/Adafruit_Sensor-master/library.properties @@ -0,0 +1,9 @@ +name=Adafruit Unified Sensor +version=1.0.2 +author=Adafruit +maintainer=Adafruit +sentence=Required for all Adafruit Unified Sensor based libraries. +paragraph=A unified sensor abstraction layer used by many Adafruit sensor libraries. +category=Sensors +url=https://github.com/adafruit/Adafruit_Sensor +architectures=* diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/.gitattributes b/libraries/BMP180_Breakout_Arduino_Library-master/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/.gitignore b/libraries/BMP180_Breakout_Arduino_Library-master/.gitignore new file mode 100644 index 0000000..2778edb --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/.gitignore @@ -0,0 +1,192 @@ +################# +## SparkFun Useful stuff +################# + +## AVR Development +*.eep +*.elf +*.lst +*.lss +*.sym +*.d +*.o +*.srec +*.map + +## Notepad++ backup files +*.bak + +## BOM files +*bom* + +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +############# +## Eagle +############# + +# Ignore the board and schematic backup files +*.b#? +*.s#? + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +.builds +*.dotCover + +## TODO: If you have NuGet Package Restore enabled, uncomment this +#packages/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# ReSharper is a .NET coding add-in +_ReSharper* + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Others +[Bb]in +[Oo]bj +sql +TestResults +*.Cache +ClientBin +stylecop.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + + +############ +## Windows +############ + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +# Mac crap +.DS_Store diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/LICENSE.md b/libraries/BMP180_Breakout_Arduino_Library-master/LICENSE.md new file mode 100644 index 0000000..f8dc62d --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/LICENSE.md @@ -0,0 +1,9 @@ + +License Information +------------------- + +The hardware is released under [Creative Commons Share-alike 3.0](http://creativecommons.org/licenses/by-sa/3.0/). + +All other code is open source so please feel free to do anything you want with it; you buy me a beer if you use this and we meet someday ([Beerware license](http://en.wikipedia.org/wiki/Beerware)). + + diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/README.md b/libraries/BMP180_Breakout_Arduino_Library-master/README.md new file mode 100644 index 0000000..74b0b51 --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/README.md @@ -0,0 +1,49 @@ +SparkFun BMP180_Breakout Arduino Library +======================================== + +![BMP180 Breakout](https://dlnmh9ip6v2uc.cloudfront.net/images/products/1/1/8/2/4/11824-01.jpg) + +[*SEN-11824*](https://www.sparkfun.com/products/11824) + +This archive contains an Arduino library and example sketch showing how to use this sensor. The library must be installed onto your computer in order for the example code to work correctly. + +Repository Contents +------------------- + +* **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. +* **/src** - Source files for the library (.cpp, .h). +* **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. +* **library.properties** - General library properties for the Arduino package manager. + +Documentation +-------------- + +* **[*Installing an Arduino Library* Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. +* **[Product Repository](https://github.com/sparkfun/BMP180_Breakout)** - Main repository (including hardware files) for the BMP180 Breakout. +* **[Hookup Guide](https://learn.sparkfun.com/tutorials/bmp180-barometric-pressure-sensor-hookup)** - Basic hookup guide for the BMP180 Breakout. + +Products that use this Library +--------------------------------- + +* [SEN-11824](https://www.sparkfun.com/products/11824) - BMP180 Barometric Pressure Sensor Breakout + + +Version History +--------------- +* [V_1.1.2](https://github.com/sparkfun/BMP180_Breakout_Arduino_Library/tree/V_1.1.2) - Small patch on integers, cleaning up library files. +* [V_1.1.1](https://github.com/sparkfun/BMP180_Breakout_Arduino_Library/tree/V_1.1.1) - Updated library.properties file +* [V_1.1.0](https://github.com/sparkfun/BMP180_Breakout_Arduino_Library/tree/V_1.1.0) - Updated to new library structure +* V_1.0.0 - Untracked version + +License Information +------------------- + +This product is _**open source**_! + +The **code** is beerware; if you see me (or any other SparkFun employee) at the local, and you've found our code helpful, please buy us a round! + +Please use, reuse, and modify these files as you see fit. Please maintain attribution to SparkFun Electronics and release anything derivative under the same license. + +Distributed as-is; no warranty is given. + +\- Your friends at SparkFun. diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/examples/BMP180_altitude_example/BMP180_altitude_example.ino b/libraries/BMP180_Breakout_Arduino_Library-master/examples/BMP180_altitude_example/BMP180_altitude_example.ino new file mode 100644 index 0000000..046d36f --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/examples/BMP180_altitude_example/BMP180_altitude_example.ino @@ -0,0 +1,169 @@ +/* SFE_BMP180 altitude example sketch + +This sketch shows how to use the Bosch BMP180 pressure sensor +as an altimiter. +https://www.sparkfun.com/products/11824 + +Like most pressure sensors, the BMP180 measures absolute pressure. +Since absolute pressure varies with altitude, you can use the pressure +to determine your altitude. + +Because pressure also varies with weather, you must first take a pressure +reading at a known baseline altitude. Then you can measure variations +from that pressure + +Hardware connections: + +- (GND) to GND ++ (VDD) to 3.3V + +(WARNING: do not connect + to 5V or the sensor will be damaged!) + +You will also need to connect the I2C pins (SCL and SDA) to your +Arduino. The pins are different on different Arduinos: + +Any Arduino pins labeled: SDA SCL +Uno, Redboard, Pro: A4 A5 +Mega2560, Due: 20 21 +Leonardo: 2 3 + +Leave the IO (VDDIO) pin unconnected. This pin is for connecting +the BMP180 to systems with lower logic levels such as 1.8V + +Have fun! -Your friends at SparkFun. + +The SFE_BMP180 library uses floating-point equations developed by the +Weather Station Data Logger project: http://wmrx00.sourceforge.net/ + +Our example code uses the "beerware" license. You can do anything +you like with this code. No really, anything. If you find it useful, +buy me a beer someday. + +V10 Mike Grusin, SparkFun Electronics 10/24/2013 +V1.1.2 Updates for Arduino 1.6.4 5/2015 +*/ + +// Your sketch must #include this library, and the Wire library. +// (Wire is a standard library included with Arduino.): + +#include +#include + +// You will need to create an SFE_BMP180 object, here called "pressure": + +SFE_BMP180 pressure; + +double baseline; // baseline pressure + +void setup() +{ + Serial.begin(9600); + Serial.println("REBOOT"); + + // Initialize the sensor (it is important to get calibration values stored on the device). + + if (pressure.begin()) + Serial.println("BMP180 init success"); + else + { + // Oops, something went wrong, this is usually a connection problem, + // see the comments at the top of this sketch for the proper connections. + + Serial.println("BMP180 init fail (disconnected?)\n\n"); + while(1); // Pause forever. + } + + // Get the baseline pressure: + + baseline = getPressure(); + + Serial.print("baseline pressure: "); + Serial.print(baseline); + Serial.println(" mb"); +} + +void loop() +{ + double a,P; + + // Get a new pressure reading: + + P = getPressure(); + + // Show the relative altitude difference between + // the new reading and the baseline reading: + + a = pressure.altitude(P,baseline); + + Serial.print("relative altitude: "); + if (a >= 0.0) Serial.print(" "); // add a space for positive numbers + Serial.print(a,1); + Serial.print(" meters, "); + if (a >= 0.0) Serial.print(" "); // add a space for positive numbers + Serial.print(a*3.28084,0); + Serial.println(" feet"); + + delay(500); +} + + +double getPressure() +{ + char status; + double T,P,p0,a; + + // You must first get a temperature measurement to perform a pressure reading. + + // Start a temperature measurement: + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + + status = pressure.startTemperature(); + if (status != 0) + { + // Wait for the measurement to complete: + + delay(status); + + // Retrieve the completed temperature measurement: + // Note that the measurement is stored in the variable T. + // Use '&T' to provide the address of T to the function. + // Function returns 1 if successful, 0 if failure. + + status = pressure.getTemperature(T); + if (status != 0) + { + // Start a pressure measurement: + // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait). + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + + status = pressure.startPressure(3); + if (status != 0) + { + // Wait for the measurement to complete: + delay(status); + + // Retrieve the completed pressure measurement: + // Note that the measurement is stored in the variable P. + // Use '&P' to provide the address of P. + // Note also that the function requires the previous temperature measurement (T). + // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.) + // Function returns 1 if successful, 0 if failure. + + status = pressure.getPressure(P,T); + if (status != 0) + { + return(P); + } + else Serial.println("error retrieving pressure measurement\n"); + } + else Serial.println("error starting pressure measurement\n"); + } + else Serial.println("error retrieving temperature measurement\n"); + } + else Serial.println("error starting temperature measurement\n"); +} + + + diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/examples/README.md b/libraries/BMP180_Breakout_Arduino_Library-master/examples/README.md new file mode 100644 index 0000000..8bd943d --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/examples/README.md @@ -0,0 +1,5 @@ +SparkFun Example Sketches +--------------------------- + + +Basic Arduino Example Sketches that work with the SparkFun BMP180 Library. diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/examples/SFE_BMP180_example/SFE_BMP180_example.ino b/libraries/BMP180_Breakout_Arduino_Library-master/examples/SFE_BMP180_example/SFE_BMP180_example.ino new file mode 100644 index 0000000..37ed6dc --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/examples/SFE_BMP180_example/SFE_BMP180_example.ino @@ -0,0 +1,201 @@ +/* SFE_BMP180 library example sketch + +This sketch shows how to use the SFE_BMP180 library to read the +Bosch BMP180 barometric pressure sensor. +https://www.sparkfun.com/products/11824 + +Like most pressure sensors, the BMP180 measures absolute pressure. +This is the actual ambient pressure seen by the device, which will +vary with both altitude and weather. + +Before taking a pressure reading you must take a temparture reading. +This is done with startTemperature() and getTemperature(). +The result is in degrees C. + +Once you have a temperature reading, you can take a pressure reading. +This is done with startPressure() and getPressure(). +The result is in millibar (mb) aka hectopascals (hPa). + +If you'll be monitoring weather patterns, you will probably want to +remove the effects of altitude. This will produce readings that can +be compared to the published pressure readings from other locations. +To do this, use the sealevel() function. You will need to provide +the known altitude at which the pressure was measured. + +If you want to measure altitude, you will need to know the pressure +at a baseline altitude. This can be average sealevel pressure, or +a previous pressure reading at your altitude, in which case +subsequent altitude readings will be + or - the initial baseline. +This is done with the altitude() function. + +Hardware connections: + +- (GND) to GND ++ (VDD) to 3.3V + +(WARNING: do not connect + to 5V or the sensor will be damaged!) + +You will also need to connect the I2C pins (SCL and SDA) to your +Arduino. The pins are different on different Arduinos: + +Any Arduino pins labeled: SDA SCL +Uno, Redboard, Pro: A4 A5 +Mega2560, Due: 20 21 +Leonardo: 2 3 + +Leave the IO (VDDIO) pin unconnected. This pin is for connecting +the BMP180 to systems with lower logic levels such as 1.8V + +Have fun! -Your friends at SparkFun. + +The SFE_BMP180 library uses floating-point equations developed by the +Weather Station Data Logger project: http://wmrx00.sourceforge.net/ + +Our example code uses the "beerware" license. You can do anything +you like with this code. No really, anything. If you find it useful, +buy me a beer someday. + +V10 Mike Grusin, SparkFun Electronics 10/24/2013 +V1.1.2 Updates for Arduino 1.6.4 5/2015 +*/ + +// Your sketch must #include this library, and the Wire library. +// (Wire is a standard library included with Arduino.): + +#include +#include + +// You will need to create an SFE_BMP180 object, here called "pressure": + +SFE_BMP180 pressure; + +#define ALTITUDE 1655.0 // Altitude of SparkFun's HQ in Boulder, CO. in meters + +void setup() +{ + Serial.begin(9600); + Serial.println("REBOOT"); + + // Initialize the sensor (it is important to get calibration values stored on the device). + + if (pressure.begin()) + Serial.println("BMP180 init success"); + else + { + // Oops, something went wrong, this is usually a connection problem, + // see the comments at the top of this sketch for the proper connections. + + Serial.println("BMP180 init fail\n\n"); + while(1); // Pause forever. + } +} + +void loop() +{ + char status; + double T,P,p0,a; + + // Loop here getting pressure readings every 10 seconds. + + // If you want sea-level-compensated pressure, as used in weather reports, + // you will need to know the altitude at which your measurements are taken. + // We're using a constant called ALTITUDE in this sketch: + + Serial.println(); + Serial.print("provided altitude: "); + Serial.print(ALTITUDE,0); + Serial.print(" meters, "); + Serial.print(ALTITUDE*3.28084,0); + Serial.println(" feet"); + + // If you want to measure altitude, and not pressure, you will instead need + // to provide a known baseline pressure. This is shown at the end of the sketch. + + // You must first get a temperature measurement to perform a pressure reading. + + // Start a temperature measurement: + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + + status = pressure.startTemperature(); + if (status != 0) + { + // Wait for the measurement to complete: + delay(status); + + // Retrieve the completed temperature measurement: + // Note that the measurement is stored in the variable T. + // Function returns 1 if successful, 0 if failure. + + status = pressure.getTemperature(T); + if (status != 0) + { + // Print out the measurement: + Serial.print("temperature: "); + Serial.print(T,2); + Serial.print(" deg C, "); + Serial.print((9.0/5.0)*T+32.0,2); + Serial.println(" deg F"); + + // Start a pressure measurement: + // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait). + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + + status = pressure.startPressure(3); + if (status != 0) + { + // Wait for the measurement to complete: + delay(status); + + // Retrieve the completed pressure measurement: + // Note that the measurement is stored in the variable P. + // Note also that the function requires the previous temperature measurement (T). + // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.) + // Function returns 1 if successful, 0 if failure. + + status = pressure.getPressure(P,T); + if (status != 0) + { + // Print out the measurement: + Serial.print("absolute pressure: "); + Serial.print(P,2); + Serial.print(" mb, "); + Serial.print(P*0.0295333727,2); + Serial.println(" inHg"); + + // The pressure sensor returns abolute pressure, which varies with altitude. + // To remove the effects of altitude, use the sealevel function and your current altitude. + // This number is commonly used in weather reports. + // Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m. + // Result: p0 = sea-level compensated pressure in mb + + p0 = pressure.sealevel(P,ALTITUDE); // we're at 1655 meters (Boulder, CO) + Serial.print("relative (sea-level) pressure: "); + Serial.print(p0,2); + Serial.print(" mb, "); + Serial.print(p0*0.0295333727,2); + Serial.println(" inHg"); + + // On the other hand, if you want to determine your altitude from the pressure reading, + // use the altitude function along with a baseline pressure (sea-level or other). + // Parameters: P = absolute pressure in mb, p0 = baseline pressure in mb. + // Result: a = altitude in m. + + a = pressure.altitude(P,p0); + Serial.print("computed altitude: "); + Serial.print(a,0); + Serial.print(" meters, "); + Serial.print(a*3.28084,0); + Serial.println(" feet"); + } + else Serial.println("error retrieving pressure measurement\n"); + } + else Serial.println("error starting pressure measurement\n"); + } + else Serial.println("error retrieving temperature measurement\n"); + } + else Serial.println("error starting temperature measurement\n"); + + delay(5000); // Pause for 5 seconds. +} diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/keywords.txt b/libraries/BMP180_Breakout_Arduino_Library-master/keywords.txt new file mode 100644 index 0000000..664167d --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/keywords.txt @@ -0,0 +1,27 @@ +####################################### +# Syntax Coloring Map for SFE_BMP180 +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SFE_BMP180 KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +startTemperature KEYWORD2 +getTemperature KEYWORD2 +startPressure KEYWORD2 +getPressure KEYWORD2 +sealevel KEYWORD2 +altitude KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +BMP180_ADDR LITERAL1 \ No newline at end of file diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/library.properties b/libraries/BMP180_Breakout_Arduino_Library-master/library.properties new file mode 100644 index 0000000..535df8b --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/library.properties @@ -0,0 +1,9 @@ +name=Sparkfun BMP180 +version=1.1.2 +author=SparkFun Electronics +maintainer=SparkFun Electronics +sentence=Sparkfun examples for the Bosch BMP180 barometric pressure sensor +paragraph=Example code for the Sparkfun Bosch BMP180 barometric pressure sensor breakout board. +category=Signal Input/Output +url=https://github.com/sparkfun/BMP180_Breakout +architectures=* diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/src/README.md b/libraries/BMP180_Breakout_Arduino_Library-master/src/README.md new file mode 100644 index 0000000..60934ed --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/src/README.md @@ -0,0 +1,5 @@ +This folder should contain the .cpp and .h files for the library. + +If backward compatibility is needed, source code should be placed in the library root folder and in a "utilyt" folder. + +Check out the [library specification](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification) for more details. \ No newline at end of file diff --git a/libraries/BMP180_Breakout_Arduino_Library-master/src/SFE_BMP180.cpp b/libraries/BMP180_Breakout_Arduino_Library-master/src/SFE_BMP180.cpp new file mode 100644 index 0000000..8d9fb81 --- /dev/null +++ b/libraries/BMP180_Breakout_Arduino_Library-master/src/SFE_BMP180.cpp @@ -0,0 +1,388 @@ +/* + SFE_BMP180.cpp + Bosch BMP180 pressure sensor library for the Arduino microcontroller + Mike Grusin, SparkFun Electronics + + Uses floating-point equations from the Weather Station Data Logger project + http://wmrx00.sourceforge.net/ + http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf + + Forked from BMP085 library by M.Grusin + + version 1.0 2013/09/20 initial version + Verison 1.1.2 - Updated for Arduino 1.6.4 5/2015 + + Our example code uses the "beerware" license. You can do anything + you like with this code. No really, anything. If you find it useful, + buy me a (root) beer someday. +*/ + +#include +#include +#include +#include + + +SFE_BMP180::SFE_BMP180() +// Base library type +{ +} + + +char SFE_BMP180::begin() +// Initialize library for subsequent pressure measurements +{ + double c3,c4,b1; + + // Start up the Arduino's "wire" (I2C) library: + + Wire.begin(); + + // The BMP180 includes factory calibration data stored on the device. + // Each device has different numbers, these must be retrieved and + // used in the calculations when taking pressure measurements. + + // Retrieve calibration data from device: + + if (readInt(0xAA,AC1) && + readInt(0xAC,AC2) && + readInt(0xAE,AC3) && + readUInt(0xB0,AC4) && + readUInt(0xB2,AC5) && + readUInt(0xB4,AC6) && + readInt(0xB6,VB1) && + readInt(0xB8,VB2) && + readInt(0xBA,MB) && + readInt(0xBC,MC) && + readInt(0xBE,MD)) + { + + // All reads completed successfully! + + // If you need to check your math using known numbers, + // you can uncomment one of these examples. + // (The correct results are commented in the below functions.) + + // Example from Bosch datasheet + // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153; + // B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868; + + // Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf + // AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974; + // VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432; + + /* + Serial.print("AC1: "); Serial.println(AC1); + Serial.print("AC2: "); Serial.println(AC2); + Serial.print("AC3: "); Serial.println(AC3); + Serial.print("AC4: "); Serial.println(AC4); + Serial.print("AC5: "); Serial.println(AC5); + Serial.print("AC6: "); Serial.println(AC6); + Serial.print("VB1: "); Serial.println(VB1); + Serial.print("VB2: "); Serial.println(VB2); + Serial.print("MB: "); Serial.println(MB); + Serial.print("MC: "); Serial.println(MC); + Serial.print("MD: "); Serial.println(MD); + */ + + // Compute floating-point polynominals: + + c3 = 160.0 * pow(2,-15) * AC3; + c4 = pow(10,-3) * pow(2,-15) * AC4; + b1 = pow(160,2) * pow(2,-30) * VB1; + c5 = (pow(2,-15) / 160) * AC5; + c6 = AC6; + mc = (pow(2,11) / pow(160,2)) * MC; + md = MD / 160.0; + x0 = AC1; + x1 = 160.0 * pow(2,-13) * AC2; + x2 = pow(160,2) * pow(2,-25) * VB2; + y0 = c4 * pow(2,15); + y1 = c4 * c3; + y2 = c4 * b1; + p0 = (3791.0 - 8.0) / 1600.0; + p1 = 1.0 - 7357.0 * pow(2,-20); + p2 = 3038.0 * 100.0 * pow(2,-36); + + /* + Serial.println(); + Serial.print("c3: "); Serial.println(c3); + Serial.print("c4: "); Serial.println(c4); + Serial.print("c5: "); Serial.println(c5); + Serial.print("c6: "); Serial.println(c6); + Serial.print("b1: "); Serial.println(b1); + Serial.print("mc: "); Serial.println(mc); + Serial.print("md: "); Serial.println(md); + Serial.print("x0: "); Serial.println(x0); + Serial.print("x1: "); Serial.println(x1); + Serial.print("x2: "); Serial.println(x2); + Serial.print("y0: "); Serial.println(y0); + Serial.print("y1: "); Serial.println(y1); + Serial.print("y2: "); Serial.println(y2); + Serial.print("p0: "); Serial.println(p0); + Serial.print("p1: "); Serial.println(p1); + Serial.print("p2: "); Serial.println(p2); + */ + + // Success! + return(1); + } + else + { + // Error reading calibration data; bad component or connection? + return(1); + } +} + + +char SFE_BMP180::readInt(char address, int16_t &value) +// Read a signed integer (two bytes) from device +// address: register to start reading (plus subsequent register) +// value: external variable to store data (function modifies value) +{ + unsigned char data[2]; + + data[0] = address; + if (readBytes(data,2)) + { + value = (int16_t)((data[0]<<8)|data[1]); + //if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative + return(1); + } + value = 0; + return(0); +} + + +char SFE_BMP180::readUInt(char address, uint16_t &value) +// Read an unsigned integer (two bytes) from device +// address: register to start reading (plus subsequent register) +// value: external variable to store data (function modifies value) +{ + unsigned char data[2]; + + data[0] = address; + if (readBytes(data,2)) + { + value = (((uint16_t)data[0]<<8)|(uint16_t)data[1]); + return(1); + } + value = 0; + return(0); +} + + +char SFE_BMP180::readBytes(unsigned char *values, char length) +// Read an array of bytes from device +// values: external array to hold data. Put starting register in values[0]. +// length: number of bytes to read +{ + char x; + + Wire.beginTransmission(BMP180_ADDR); + Wire.write(values[0]); + _error = Wire.endTransmission(); + if (_error == 0) + { + Wire.requestFrom(BMP180_ADDR,length); + while(Wire.available() != length) ; // wait until bytes are ready + for(x=0;x= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +class SFE_BMP180 +{ + public: + SFE_BMP180(); // base type + + char begin(); + // call pressure.begin() to initialize BMP180 before use + // returns 1 if success, 0 if failure (bad component or I2C bus shorted?) + + char startTemperature(void); + // command BMP180 to start a temperature measurement + // returns (number of ms to wait) for success, 0 for fail + + char getTemperature(double &T); + // return temperature measurement from previous startTemperature command + // places returned value in T variable (deg C) + // returns 1 for success, 0 for fail + + char startPressure(char oversampling); + // command BMP180 to start a pressure measurement + // oversampling: 0 - 3 for oversampling value + // returns (number of ms to wait) for success, 0 for fail + + char getPressure(double &P, double &T); + // return absolute pressure measurement from previous startPressure command + // note: requires previous temperature measurement in variable T + // places returned value in P variable (mbar) + // returns 1 for success, 0 for fail + + double sealevel(double P, double A); + // convert absolute pressure to sea-level pressure (as used in weather data) + // P: absolute pressure (mbar) + // A: current altitude (meters) + // returns sealevel pressure in mbar + + double altitude(double P, double P0); + // convert absolute pressure to altitude (given baseline pressure; sea-level, runway, etc.) + // P: absolute pressure (mbar) + // P0: fixed baseline pressure (mbar) + // returns signed altitude in meters + + char getError(void); + // If any library command fails, you can retrieve an extended + // error code using this command. Errors are from the wire library: + // 0 = Success + // 1 = Data too long to fit in transmit buffer + // 2 = Received NACK on transmit of address + // 3 = Received NACK on transmit of data + // 4 = Other error + + private: + + char readInt(char address, int16_t &value); + // read an signed int (16 bits) from a BMP180 register + // address: BMP180 register address + // value: external signed int for returned value (16 bits) + // returns 1 for success, 0 for fail, with result in value + + char readUInt(char address, uint16_t &value); + // read an unsigned int (16 bits) from a BMP180 register + // address: BMP180 register address + // value: external unsigned int for returned value (16 bits) + // returns 1 for success, 0 for fail, with result in value + + char readBytes(unsigned char *values, char length); + // read a number of bytes from a BMP180 register + // values: array of char with register address in first location [0] + // length: number of bytes to read back + // returns 1 for success, 0 for fail, with read bytes in values[] array + + char writeBytes(unsigned char *values, char length); + // write a number of bytes to a BMP180 register (and consecutive subsequent registers) + // values: array of char with register address in first location [0] + // length: number of bytes to write + // returns 1 for success, 0 for fail + + int16_t AC1,AC2,AC3,VB1,VB2,MB,MC,MD; + uint16_t AC4,AC5,AC6; + double c5,c6,mc,md,x0,x1,x2,y0,y1,y2,p0,p1,p2; + char _error; +}; + +#define BMP180_ADDR 0x77 // 7-bit address + +#define BMP180_REG_CONTROL 0xF4 +#define BMP180_REG_RESULT 0xF6 + +#define BMP180_COMMAND_TEMPERATURE 0x2E +#define BMP180_COMMAND_PRESSURE0 0x34 +#define BMP180_COMMAND_PRESSURE1 0x74 +#define BMP180_COMMAND_PRESSURE2 0xB4 +#define BMP180_COMMAND_PRESSURE3 0xF4 + +#endif diff --git a/libraries/Bridge/README.adoc b/libraries/Bridge/README.adoc new file mode 100644 index 0000000..c660f86 --- /dev/null +++ b/libraries/Bridge/README.adoc @@ -0,0 +1,24 @@ += Bridge Library for Arduino = + +The Bridge library simplifies communication between the ATmega32U4 and the AR9331. + +For more information about this library please visit us at +http://www.arduino.cc/en/Reference/YunBridgeLibrary + +== License == + +Copyright (c) 2014 Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libraries/Bridge/examples/Bridge/Bridge.ino b/libraries/Bridge/examples/Bridge/Bridge.ino new file mode 100644 index 0000000..c6c7be3 --- /dev/null +++ b/libraries/Bridge/examples/Bridge/Bridge.ino @@ -0,0 +1,185 @@ +/* + Arduino Yún Bridge example + + This example for the Arduino Yún shows how to use the + Bridge library to access the digital and analog pins + on the board through REST calls. It demonstrates how + you can create your own API when using REST style + calls through the browser. + + Possible commands created in this shetch: + + "/arduino/digital/13" -> digitalRead(13) + "/arduino/digital/13/1" -> digitalWrite(13, HIGH) + "/arduino/analog/2/123" -> analogWrite(2, 123) + "/arduino/analog/2" -> analogRead(2) + "/arduino/mode/13/input" -> pinMode(13, INPUT) + "/arduino/mode/13/output" -> pinMode(13, OUTPUT) + + This example code is part of the public domain + + http://www.arduino.cc/en/Tutorial/Bridge + +*/ + +#include +#include +#include + +// Listen to the default port 5555, the Yún webserver +// will forward there all the HTTP requests you send +BridgeServer server; + +void setup() { + // Bridge startup + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); + digitalWrite(13, HIGH); + + // Listen for incoming connection only from localhost + // (no one from the external network could connect) + server.listenOnLocalhost(); + server.begin(); +} + +void loop() { + // Get clients coming from server + BridgeClient client = server.accept(); + + // There is a new client? + if (client) { + // Process request + process(client); + + // Close connection and free resources. + client.stop(); + } + + delay(50); // Poll every 50ms +} + +void process(BridgeClient client) { + // read the command + String command = client.readStringUntil('/'); + + // is "digital" command? + if (command == "digital") { + digitalCommand(client); + } + + // is "analog" command? + if (command == "analog") { + analogCommand(client); + } + + // is "mode" command? + if (command == "mode") { + modeCommand(client); + } +} + +void digitalCommand(BridgeClient client) { + int pin, value; + + // Read pin number + pin = client.parseInt(); + + // If the next character is a '/' it means we have an URL + // with a value like: "/digital/13/1" + if (client.read() == '/') { + value = client.parseInt(); + digitalWrite(pin, value); + } else { + value = digitalRead(pin); + } + + // Send feedback to client + client.print(F("Pin D")); + client.print(pin); + client.print(F(" set to ")); + client.println(value); + + // Update datastore key with the current pin value + String key = "D"; + key += pin; + Bridge.put(key, String(value)); +} + +void analogCommand(BridgeClient client) { + int pin, value; + + // Read pin number + pin = client.parseInt(); + + // If the next character is a '/' it means we have an URL + // with a value like: "/analog/5/120" + if (client.read() == '/') { + // Read value and execute command + value = client.parseInt(); + analogWrite(pin, value); + + // Send feedback to client + client.print(F("Pin D")); + client.print(pin); + client.print(F(" set to analog ")); + client.println(value); + + // Update datastore key with the current pin value + String key = "D"; + key += pin; + Bridge.put(key, String(value)); + } else { + // Read analog pin + value = analogRead(pin); + + // Send feedback to client + client.print(F("Pin A")); + client.print(pin); + client.print(F(" reads analog ")); + client.println(value); + + // Update datastore key with the current pin value + String key = "A"; + key += pin; + Bridge.put(key, String(value)); + } +} + +void modeCommand(BridgeClient client) { + int pin; + + // Read pin number + pin = client.parseInt(); + + // If the next character is not a '/' we have a malformed URL + if (client.read() != '/') { + client.println(F("error")); + return; + } + + String mode = client.readStringUntil('\r'); + + if (mode == "input") { + pinMode(pin, INPUT); + // Send feedback to client + client.print(F("Pin D")); + client.print(pin); + client.print(F(" configured as INPUT!")); + return; + } + + if (mode == "output") { + pinMode(pin, OUTPUT); + // Send feedback to client + client.print(F("Pin D")); + client.print(pin); + client.print(F(" configured as OUTPUT!")); + return; + } + + client.print(F("error: invalid mode ")); + client.print(mode); +} + + diff --git a/libraries/Bridge/examples/ConsoleAsciiTable/ConsoleAsciiTable.ino b/libraries/Bridge/examples/ConsoleAsciiTable/ConsoleAsciiTable.ino new file mode 100644 index 0000000..79d5aff --- /dev/null +++ b/libraries/Bridge/examples/ConsoleAsciiTable/ConsoleAsciiTable.ino @@ -0,0 +1,95 @@ +/* + ASCII table + + Prints out byte values in all possible formats: + * as raw binary values + * as ASCII-encoded decimal, hex, octal, and binary values + + For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII + + The circuit: No external hardware needed. + + created 2006 + by Nicholas Zambetti + http://www.zambetti.com + modified 9 Apr 2012 + by Tom Igoe + modified 22 May 2013 + by Cristian Maglie + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/ConsoleAsciiTable + + */ + +#include + +void setup() { + //Initialize Console and wait for port to open: + Bridge.begin(); + Console.begin(); + + // Uncomment the following line to enable buffering: + // - better transmission speed and efficiency + // - needs to call Console.flush() to ensure that all + // transmitted data is sent + + //Console.buffer(64); + + while (!Console) { + ; // wait for Console port to connect. + } + + // prints title with ending line break + Console.println("ASCII Table ~ Character Map"); +} + +// first visible ASCIIcharacter '!' is number 33: +int thisByte = 33; +// you can also write ASCII characters in single quotes. +// for example. '!' is the same as 33, so you could also use this: +//int thisByte = '!'; + +void loop() { + // prints value unaltered, i.e. the raw binary version of the + // byte. The Console monitor interprets all bytes as + // ASCII, so 33, the first number, will show up as '!' + Console.write(thisByte); + + Console.print(", dec: "); + // prints value as string as an ASCII-encoded decimal (base 10). + // Decimal is the default format for Console.print() and Console.println(), + // so no modifier is needed: + Console.print(thisByte); + // But you can declare the modifier for decimal if you want to. + //this also works if you uncomment it: + + // Console.print(thisByte, DEC); + + Console.print(", hex: "); + // prints value as string in hexadecimal (base 16): + Console.print(thisByte, HEX); + + Console.print(", oct: "); + // prints value as string in octal (base 8); + Console.print(thisByte, OCT); + + Console.print(", bin: "); + // prints value as string in binary (base 2) + // also prints ending line break: + Console.println(thisByte, BIN); + + // if printed last visible character '~' or 126, stop: + if (thisByte == 126) { // you could also use if (thisByte == '~') { + // ensure the latest bit of data is sent + Console.flush(); + + // This loop loops forever and does nothing + while (true) { + continue; + } + } + // go on to the next character + thisByte++; +} diff --git a/libraries/Bridge/examples/ConsolePixel/ConsolePixel.ino b/libraries/Bridge/examples/ConsolePixel/ConsolePixel.ino new file mode 100644 index 0000000..ee78f4c --- /dev/null +++ b/libraries/Bridge/examples/ConsolePixel/ConsolePixel.ino @@ -0,0 +1,64 @@ +/* + Console Pixel + + An example of using the Arduino board to receive data from the + Console on the Arduino Yún. In this case, the Arduino boards turns on an LED when + it receives the character 'H', and turns off the LED when it + receives the character 'L'. + + To see the Console, pick your Yún's name and IP address in the Port menu + then open the Port Monitor. You can also see it by opening a terminal window + and typing + ssh root@ yourYunsName.local 'telnet localhost 6571' + then pressing enter. When prompted for the password, enter it. + + + The circuit: + * LED connected from digital pin 13 to ground + + created 2006 + by David A. Mellis + modified 25 Jun 2013 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/ConsolePixel + + */ + +#include + +const int ledPin = 13; // the pin that the LED is attached to +char incomingByte; // a variable to read incoming Console data into + +void setup() { + Bridge.begin(); // Initialize Bridge + Console.begin(); // Initialize Console + + // Wait for the Console port to connect + while (!Console); + + Console.println("type H or L to turn pin 13 on or off"); + + // initialize the LED pin as an output: + pinMode(ledPin, OUTPUT); +} + +void loop() { + // see if there's incoming Console data: + if (Console.available() > 0) { + // read the oldest byte in the Console buffer: + incomingByte = Console.read(); + Console.println(incomingByte); + // if it's a capital H (ASCII 72), turn on the LED: + if (incomingByte == 'H') { + digitalWrite(ledPin, HIGH); + } + // if it's an L (ASCII 76) turn off the LED: + if (incomingByte == 'L') { + digitalWrite(ledPin, LOW); + } + } +} + diff --git a/libraries/Bridge/examples/ConsoleRead/ConsoleRead.ino b/libraries/Bridge/examples/ConsoleRead/ConsoleRead.ino new file mode 100644 index 0000000..8fc37fb --- /dev/null +++ b/libraries/Bridge/examples/ConsoleRead/ConsoleRead.ino @@ -0,0 +1,60 @@ +/* + Console Read example + + Read data coming from bridge using the Console.read() function + and store it in a string. + + To see the Console, pick your Yún's name and IP address in the Port menu + then open the Port Monitor. You can also see it by opening a terminal window + and typing: + ssh root@ yourYunsName.local 'telnet localhost 6571' + then pressing enter. When prompted for the password, enter it. + + created 13 Jun 2013 + by Angelo Scialabba + modified 16 June 2013 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/ConsoleRead + + */ + +#include + +String name; + +void setup() { + // Initialize Console and wait for port to open: + Bridge.begin(); + Console.begin(); + + // Wait for Console port to connect + while (!Console); + + Console.println("Hi, what's your name?"); +} + +void loop() { + if (Console.available() > 0) { + char c = Console.read(); // read the next char received + // look for the newline character, this is the last character in the string + if (c == '\n') { + //print text with the name received + Console.print("Hi "); + Console.print(name); + Console.println("! Nice to meet you!"); + Console.println(); + // Ask again for name and clear the old name + Console.println("Hi, what's your name?"); + name = ""; // clear the name string + } else { // if the buffer is empty Cosole.read() returns -1 + name += c; // append the read char from Console to the name string + } + } else { + delay(100); + } +} + + diff --git a/libraries/Bridge/examples/Datalogger/Datalogger.ino b/libraries/Bridge/examples/Datalogger/Datalogger.ino new file mode 100644 index 0000000..367cd72 --- /dev/null +++ b/libraries/Bridge/examples/Datalogger/Datalogger.ino @@ -0,0 +1,102 @@ +/* + SD card datalogger + + This example shows how to log data from three analog sensors + to an SD card mounted on the Arduino Yún using the Bridge library. + + The circuit: + * analog sensors on analog pins 0, 1 and 2 + * SD card attached to SD card slot of the Arduino Yún + + Prepare your SD card creating an empty folder in the SD root + named "arduino". This will ensure that the Yún will create a link + to the SD to the "/mnt/sd" path. + + You can remove the SD card while the Linux and the + sketch are running but be careful not to remove it while + the system is writing to it. + + created 24 Nov 2010 + modified 9 Apr 2012 + by Tom Igoe + adapted to the Yún Bridge library 20 Jun 2013 + by Federico Vanzati + modified 21 Jun 2013 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/YunDatalogger + + */ + +#include + +void setup() { + // Initialize the Bridge and the Serial + Bridge.begin(); + Serial.begin(9600); + FileSystem.begin(); + + while (!SerialUSB); // wait for Serial port to connect. + SerialUSB.println("Filesystem datalogger\n"); +} + + +void loop() { + // make a string that start with a timestamp for assembling the data to log: + String dataString; + dataString += getTimeStamp(); + dataString += " = "; + + // read three sensors and append to the string: + for (int analogPin = 0; analogPin < 3; analogPin++) { + int sensor = analogRead(analogPin); + dataString += String(sensor); + if (analogPin < 2) { + dataString += ","; // separate the values with a comma + } + } + + // open the file. note that only one file can be open at a time, + // so you have to close this one before opening another. + // The FileSystem card is mounted at the following "/mnt/FileSystema1" + File dataFile = FileSystem.open("/mnt/sd/datalog.txt", FILE_APPEND); + + // if the file is available, write to it: + if (dataFile) { + dataFile.println(dataString); + dataFile.close(); + // print to the serial port too: + SerialUSB.println(dataString); + } + // if the file isn't open, pop up an error: + else { + SerialUSB.println("error opening datalog.txt"); + } + + delay(15000); + +} + +// This function return a string with the time stamp +String getTimeStamp() { + String result; + Process time; + // date is a command line utility to get the date and the time + // in different formats depending on the additional parameter + time.begin("date"); + time.addParameter("+%D-%T"); // parameters: D for the complete date mm/dd/yy + // T for the time hh:mm:ss + time.run(); // run the command + + // read the output of the command + while (time.available() > 0) { + char c = time.read(); + if (c != '\n') { + result += c; + } + } + + return result; +} diff --git a/libraries/Bridge/examples/FileWriteScript/FileWriteScript.ino b/libraries/Bridge/examples/FileWriteScript/FileWriteScript.ino new file mode 100644 index 0000000..99899c0 --- /dev/null +++ b/libraries/Bridge/examples/FileWriteScript/FileWriteScript.ino @@ -0,0 +1,84 @@ +/* + Write to file using FileIO classes. + + This sketch demonstrate how to write file into the Yún filesystem. + A shell script file is created in /tmp, and it is executed afterwards. + + created 7 June 2010 + by Cristian Maglie + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/FileWriteScript + + */ + +#include + +void setup() { + // Setup Bridge (needed every time we communicate with the Arduino Yún) + Bridge.begin(); + // Initialize the Serial + SerialUSB.begin(9600); + + while (!SerialUSB); // wait for Serial port to connect. + SerialUSB.println("File Write Script example\n\n"); + + // Setup File IO + FileSystem.begin(); + + // Upload script used to gain network statistics + uploadScript(); +} + +void loop() { + // Run stats script every 5 secs. + runScript(); + delay(5000); +} + +// this function creates a file into the linux processor that contains a shell script +// to check the network traffic of the WiFi interface +void uploadScript() { + // Write our shell script in /tmp + // Using /tmp stores the script in RAM this way we can preserve + // the limited amount of FLASH erase/write cycles + File script = FileSystem.open("/tmp/wlan-stats.sh", FILE_WRITE); + // Shell script header + script.print("#!/bin/sh\n"); + // shell commands: + // ifconfig: is a command line utility for controlling the network interfaces. + // wlan0 is the interface we want to query + // grep: search inside the output of the ifconfig command the "RX bytes" keyword + // and extract the line that contains it + script.print("ifconfig wlan0 | grep 'RX bytes'\n"); + script.close(); // close the file + + // Make the script executable + Process chmod; + chmod.begin("chmod"); // chmod: change mode + chmod.addParameter("+x"); // x stays for executable + chmod.addParameter("/tmp/wlan-stats.sh"); // path to the file to make it executable + chmod.run(); +} + + +// this function run the script and read the output data +void runScript() { + // Run the script and show results on the Serial + Process myscript; + myscript.begin("/tmp/wlan-stats.sh"); + myscript.run(); + + String output = ""; + + // read the output of the script + while (myscript.available()) { + output += (char)myscript.read(); + } + // remove the blank spaces at the beginning and the ending of the string + output.trim(); + SerialUSB.println(output); + SerialUSB.flush(); +} + diff --git a/libraries/Bridge/examples/HttpClient/HttpClient.ino b/libraries/Bridge/examples/HttpClient/HttpClient.ino new file mode 100644 index 0000000..a3a5429 --- /dev/null +++ b/libraries/Bridge/examples/HttpClient/HttpClient.ino @@ -0,0 +1,53 @@ +/* + Yún HTTP Client + + This example for the Arduino Yún shows how create a basic + HTTP client that connects to the internet and downloads + content. In this case, you'll connect to the Arduino + website and download a version of the logo as ASCII text. + + created by Tom igoe + May 2013 + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/HttpClient + + */ + +#include +#include + +void setup() { + // Bridge takes about two seconds to start up + // it can be helpful to use the on-board LED + // as an indicator for when it has initialized + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); + digitalWrite(13, HIGH); + + SerialUSB.begin(9600); + + while (!SerialUSB); // wait for a serial connection +} + +void loop() { + // Initialize the client library + HttpClient client; + + // Make a HTTP request: + client.get("http://www.arduino.cc/asciilogo.txt"); + + // if there are incoming bytes available + // from the server, read them and print them: + while (client.available()) { + char c = client.read(); + SerialUSB.print(c); + } + SerialUSB.flush(); + + delay(5000); +} + + diff --git a/libraries/Bridge/examples/HttpClientConsole/HttpClientConsole.ino b/libraries/Bridge/examples/HttpClientConsole/HttpClientConsole.ino new file mode 100644 index 0000000..6d8c0ee --- /dev/null +++ b/libraries/Bridge/examples/HttpClientConsole/HttpClientConsole.ino @@ -0,0 +1,55 @@ +/* + Yún HTTP Client Console version for Arduino Uno and Mega using Yún Shield + + This example for the Arduino Yún shows how create a basic + HTTP client that connects to the internet and downloads + content. In this case, you'll connect to the Arduino + website and download a version of the logo as ASCII text. + + created by Tom igoe + May 2013 + modified by Marco Brianza to use Console + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/HttpClient + + */ + +#include +#include +#include + +void setup() { + // Bridge takes about two seconds to start up + // it can be helpful to use the on-board LED + // as an indicator for when it has initialized + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); + digitalWrite(13, HIGH); + + Console.begin(); + + while (!Console); // wait for a serial connection +} + +void loop() { + // Initialize the client library + HttpClient client; + + // Make a HTTP request: + client.get("http://www.arduino.cc/asciilogo.txt"); + + // if there are incoming bytes available + // from the server, read them and print them: + while (client.available()) { + char c = client.read(); + Console.print(c); + } + Console.flush(); + + delay(5000); +} + + diff --git a/libraries/Bridge/examples/MailboxReadMessage/MailboxReadMessage.ino b/libraries/Bridge/examples/MailboxReadMessage/MailboxReadMessage.ino new file mode 100644 index 0000000..b7cbe8a --- /dev/null +++ b/libraries/Bridge/examples/MailboxReadMessage/MailboxReadMessage.ino @@ -0,0 +1,58 @@ +/* + Read Messages from the Mailbox + + This example for the Arduino Yún shows how to + read the messages queue, called Mailbox, using the + Bridge library. + The messages can be sent to the queue through REST calls. + Appen the message in the URL after the keyword "/mailbox". + Example + + "/mailbox/hello" + + created 3 Feb 2014 + by Federico Vanzati & Federico Fissore + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/MailboxReadMessage + + */ + +#include + +void setup() { + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + // Initialize Bridge and Mailbox + Bridge.begin(); + Mailbox.begin(); + digitalWrite(13, HIGH); + + // Initialize Serial + SerialUSB.begin(9600); + + // Wait until a Serial Monitor is connected. + while (!SerialUSB); + + SerialUSB.println("Mailbox Read Message\n"); + SerialUSB.println("The Mailbox is checked every 10 seconds. The incoming messages will be shown below.\n"); +} + +void loop() { + String message; + + // if there is a message in the Mailbox + if (Mailbox.messageAvailable()) { + // read all the messages present in the queue + while (Mailbox.messageAvailable()) { + Mailbox.readMessage(message); + SerialUSB.println(message); + } + + SerialUSB.println("Waiting 10 seconds before checking the Mailbox again"); + } + + // wait 10 seconds + delay(10000); +} diff --git a/libraries/Bridge/examples/Process/Process.ino b/libraries/Bridge/examples/Process/Process.ino new file mode 100644 index 0000000..ad5b869 --- /dev/null +++ b/libraries/Bridge/examples/Process/Process.ino @@ -0,0 +1,72 @@ +/* + Running process using Process class. + + This sketch demonstrate how to run linux processes + using an Arduino Yún. + + created 5 Jun 2013 + by Cristian Maglie + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/Process + + */ + +#include + +void setup() { + // Initialize Bridge + Bridge.begin(); + + // Initialize Serial + SerialUSB.begin(9600); + + // Wait until a Serial Monitor is connected. + while (!SerialUSB); + + // run various example processes + runCurl(); + runCpuInfo(); +} + +void loop() { + // Do nothing here. +} + +void runCurl() { + // Launch "curl" command and get Arduino ascii art logo from the network + // curl is command line program for transferring data using different internet protocols + Process p; // Create a process and call it "p" + p.begin("curl"); // Process that launch the "curl" command + p.addParameter("http://www.arduino.cc/asciilogo.txt"); // Add the URL parameter to "curl" + p.run(); // Run the process and wait for its termination + + // Print arduino logo over the Serial + // A process output can be read with the stream methods + while (p.available() > 0) { + char c = p.read(); + SerialUSB.print(c); + } + // Ensure the last bit of data is sent. + SerialUSB.flush(); +} + +void runCpuInfo() { + // Launch "cat /proc/cpuinfo" command (shows info on Atheros CPU) + // cat is a command line utility that shows the content of a file + Process p; // Create a process and call it "p" + p.begin("cat"); // Process that launch the "cat" command + p.addParameter("/proc/cpuinfo"); // Add the cpuifo file path as parameter to cut + p.run(); // Run the process and wait for its termination + + // Print command output on the SerialUSB. + // A process output can be read with the stream methods + while (p.available() > 0) { + char c = p.read(); + SerialUSB.print(c); + } + // Ensure the last bit of data is sent. + SerialUSB.flush(); +} + diff --git a/libraries/Bridge/examples/RemoteDueBlink/RemoteDueBlink.ino b/libraries/Bridge/examples/RemoteDueBlink/RemoteDueBlink.ino new file mode 100644 index 0000000..4b5d271 --- /dev/null +++ b/libraries/Bridge/examples/RemoteDueBlink/RemoteDueBlink.ino @@ -0,0 +1,33 @@ +/* + Blink + Turns on an LED on for one second, then off for one second, repeatedly. + + Most Arduinos have an on-board LED you can control. On the Uno and + Leonardo, it is attached to digital pin 13. If you're unsure what + pin the on-board LED is connected to on your Arduino model, check + the documentation at http://www.arduino.cc + + This example code is in the public domain. + + modified 8 May 2014 + by Scott Fitzgerald + + modified by Marco Brianza to show the remote sketch update feature on Arduino Due using Yún Shield + */ + +#include + +// the setup function runs once when you press reset or power the board +void setup() { + checkForRemoteSketchUpdate(); + // initialize digital pin 13 as an output. + pinMode(13, OUTPUT); +} + +// the loop function runs over and over again forever +void loop() { + digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) + delay(100); // wait for a second + digitalWrite(13, LOW); // turn the LED off by making the voltage LOW + delay(100); // wait for a second +} diff --git a/libraries/Bridge/examples/ShellCommands/ShellCommands.ino b/libraries/Bridge/examples/ShellCommands/ShellCommands.ino new file mode 100644 index 0000000..a90c697 --- /dev/null +++ b/libraries/Bridge/examples/ShellCommands/ShellCommands.ino @@ -0,0 +1,55 @@ +/* + Running shell commands using Process class. + + This sketch demonstrate how to run linux shell commands + using an Arduino Yún. It runs the wifiCheck script on the Linux side + of the Yún, then uses grep to get just the signal strength line. + Then it uses parseInt() to read the wifi signal strength as an integer, + and finally uses that number to fade an LED using analogWrite(). + + The circuit: + * Arduino Yún with LED connected to pin 9 + + created 12 Jun 2013 + by Cristian Maglie + modified 25 June 2013 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/ShellCommands + + */ + +#include + +void setup() { + Bridge.begin(); // Initialize the Bridge + SerialUSB.begin(9600); // Initialize the Serial + + // Wait until a Serial Monitor is connected. + while (!SerialUSB); +} + +void loop() { + Process p; + // This command line runs the WifiStatus script, (/usr/bin/pretty-wifi-info.lua), then + // sends the result to the grep command to look for a line containing the word + // "Signal:" the result is passed to this sketch: + p.runShellCommand("/usr/bin/pretty-wifi-info.lua | grep Signal"); + + // do nothing until the process finishes, so you get the whole output: + while (p.running()); + + // Read command output. runShellCommand() should have passed "Signal: xx&": + while (p.available()) { + int result = p.parseInt(); // look for an integer + int signal = map(result, 0, 100, 0, 255); // map result from 0-100 range to 0-255 + analogWrite(9, signal); // set the brightness of LED on pin 9 + SerialUSB.println(result); // print the number as well + } + delay(5000); // wait 5 seconds before you do it again +} + + + diff --git a/libraries/Bridge/examples/SpacebrewYun/inputOutput/inputOutput.ino b/libraries/Bridge/examples/SpacebrewYun/inputOutput/inputOutput.ino new file mode 100644 index 0000000..0f259ed --- /dev/null +++ b/libraries/Bridge/examples/SpacebrewYun/inputOutput/inputOutput.ino @@ -0,0 +1,134 @@ +/* + Input Output + + Demonstrates how to create a sketch that sends and receives all standard + spacebrew data types, and a custom data type. Every time data is + received it is output to the Serial monitor. + + Make sure that your Yún is connected to the internet for this example + to function properly. + + The circuit: + - No circuit required + + created 2013 + by Julio Terra + + This example code is in the public domain. + + More information about Spacebrew is available at: + http://spacebrew.cc/ + + */ + +#include +#include + +// create a variable of type SpacebrewYun and initialize it with the constructor +SpacebrewYun sb = SpacebrewYun("aYun", "Arduino Yun spacebrew test"); + +// create variables to manage interval between each time we send a string +long last = 0; +int interval = 2000; + +int counter = 0; + +void setup() { + + // start the serial port + SerialUSB.begin(57600); + + // for debugging, wait until a serial console is connected + delay(4000); + while (!SerialUSB) { + ; + } + + // start-up the bridge + Bridge.begin(); + + // configure the spacebrew object to print status messages to serial + sb.verbose(true); + + // configure the spacebrew publisher and subscriber + sb.addPublish("string test", "string"); + sb.addPublish("range test", "range"); + sb.addPublish("boolean test", "boolean"); + sb.addPublish("custom test", "crazy"); + sb.addSubscribe("string test", "string"); + sb.addSubscribe("range test", "range"); + sb.addSubscribe("boolean test", "boolean"); + sb.addSubscribe("custom test", "crazy"); + + // register the string message handler method + sb.onRangeMessage(handleRange); + sb.onStringMessage(handleString); + sb.onBooleanMessage(handleBoolean); + sb.onCustomMessage(handleCustom); + + // connect to cloud spacebrew server at "sandbox.spacebrew.cc" + sb.connect("sandbox.spacebrew.cc"); + // we give some time to arduino to connect to sandbox, otherwise the first sb.monitor(); call will give an error + delay(1000); +} + + +void loop() { + // monitor spacebrew connection for new data + sb.monitor(); + + // connected to spacebrew then send a string every 2 seconds + if (sb.connected()) { + + // check if it is time to send a new message + if ((millis() - last) > interval) { + String test_str_msg = "testing, testing, "; + test_str_msg += counter; + counter ++; + + sb.send("string test", test_str_msg); + sb.send("range test", 500); + sb.send("boolean test", true); + sb.send("custom test", "youre loco"); + + last = millis(); + + } + } + delay(1000); +} + +// define handler methods, all standard data type handlers take two appropriate arguments + +void handleRange(String route, int value) { + SerialUSB.print("Range msg "); + SerialUSB.print(route); + SerialUSB.print(", value "); + SerialUSB.println(value); +} + +void handleString(String route, String value) { + SerialUSB.print("String msg "); + SerialUSB.print(route); + SerialUSB.print(", value "); + SerialUSB.println(value); +} + +void handleBoolean(String route, boolean value) { + SerialUSB.print("Boolen msg "); + SerialUSB.print(route); + SerialUSB.print(", value "); + SerialUSB.println(value ? "true" : "false"); +} + +// custom data type handlers takes three String arguments + +void handleCustom(String route, String value, String type) { + SerialUSB.print("Custom msg "); + SerialUSB.print(route); + SerialUSB.print(" of type "); + SerialUSB.print(type); + SerialUSB.print(", value "); + SerialUSB.println(value); +} + diff --git a/libraries/Bridge/examples/SpacebrewYun/spacebrewBoolean/spacebrewBoolean.ino b/libraries/Bridge/examples/SpacebrewYun/spacebrewBoolean/spacebrewBoolean.ino new file mode 100644 index 0000000..c63314d --- /dev/null +++ b/libraries/Bridge/examples/SpacebrewYun/spacebrewBoolean/spacebrewBoolean.ino @@ -0,0 +1,94 @@ +/* + Spacebrew Boolean + + Demonstrates how to create a sketch that sends and receives a + boolean value to and from Spacebrew. Every time the buttton is + pressed (or other digital input component) a spacebrew message + is sent. The sketch also accepts analog range messages from + other Spacebrew apps. + + Make sure that your Yún is connected to the internet for this example + to function properly. + + The circuit: + - Button connected to Yún, using the Arduino's internal pullup resistor. + + created 2013 + by Julio Terra + + This example code is in the public domain. + + More information about Spacebrew is available at: + http://spacebrew.cc/ + + */ + +#include +#include + +// create a variable of type SpacebrewYun and initialize it with the constructor +SpacebrewYun sb = SpacebrewYun("spacebrewYun Boolean", "Boolean sender and receiver"); + +// variable that holds the last potentiometer value +int last_value = 0; + +// create variables to manage interval between each time we send a string +void setup() { + + // start the serial port + SerialUSB.begin(57600); + + // for debugging, wait until a serial console is connected + delay(4000); + while (!SerialUSB) { + ; + } + + // start-up the bridge + Bridge.begin(); + + // configure the spacebrew object to print status messages to serial + sb.verbose(true); + + // configure the spacebrew publisher and subscriber + sb.addPublish("physical button", "boolean"); + sb.addSubscribe("virtual button", "boolean"); + + // register the string message handler method + sb.onBooleanMessage(handleBoolean); + + // connect to cloud spacebrew server at "sandbox.spacebrew.cc" + sb.connect("sandbox.spacebrew.cc"); + + pinMode(3, INPUT); + digitalWrite(3, HIGH); +} + + +void loop() { + // monitor spacebrew connection for new data + sb.monitor(); + + // connected to spacebrew then send a new value whenever the pot value changes + if (sb.connected()) { + int cur_value = digitalRead(3); + if (last_value != cur_value) { + if (cur_value == HIGH) { + sb.send("physical button", false); + } else { + sb.send("physical button", true); + } + last_value = cur_value; + } + } +} + +// handler method that is called whenever a new string message is received +void handleBoolean(String route, boolean value) { + // print the message that was received + SerialUSB.print("From "); + SerialUSB.print(route); + SerialUSB.print(", received msg: "); + SerialUSB.println(value ? "true" : "false"); +} + diff --git a/libraries/Bridge/examples/SpacebrewYun/spacebrewRange/spacebrewRange.ino b/libraries/Bridge/examples/SpacebrewYun/spacebrewRange/spacebrewRange.ino new file mode 100644 index 0000000..eda2d17 --- /dev/null +++ b/libraries/Bridge/examples/SpacebrewYun/spacebrewRange/spacebrewRange.ino @@ -0,0 +1,88 @@ +/* + Spacebrew Range + + Demonstrates how to create a sketch that sends and receives analog + range value to and from Spacebrew. Every time the state of the + potentiometer (or other analog input component) change a spacebrew + message is sent. The sketch also accepts analog range messages from + other Spacebrew apps. + + Make sure that your Yún is connected to the internet for this example + to function properly. + + The circuit: + - Potentiometer connected to Yún. Middle pin connected to analog pin A0, + other pins connected to 5v and GND pins. + + created 2013 + by Julio Terra + + This example code is in the public domain. + + More information about Spacebrew is available at: + http://spacebrew.cc/ + + */ + +#include +#include + +// create a variable of type SpacebrewYun and initialize it with the constructor +SpacebrewYun sb = SpacebrewYun("spacebrewYun Range", "Range sender and receiver"); + +// variable that holds the last potentiometer value +int last_value = 0; + +// create variables to manage interval between each time we send a string +void setup() { + + // start the serial port + SerialUSB.begin(57600); + + // for debugging, wait until a serial console is connected + delay(4000); + while (!SerialUSB) { + ; + } + + // start-up the bridge + Bridge.begin(); + + // configure the spacebrew object to print status messages to serial + sb.verbose(true); + + // configure the spacebrew publisher and subscriber + sb.addPublish("physical pot", "range"); + sb.addSubscribe("virtual pot", "range"); + + // register the string message handler method + sb.onRangeMessage(handleRange); + + // connect to cloud spacebrew server at "sandbox.spacebrew.cc" + sb.connect("sandbox.spacebrew.cc"); +} + + +void loop() { + // monitor spacebrew connection for new data + sb.monitor(); + + // connected to spacebrew then send a new value whenever the pot value changes + if (sb.connected()) { + int cur_value = analogRead(A0); + if (last_value != cur_value) { + sb.send("physical pot", cur_value); + last_value = cur_value; + } + } +} + +// handler method that is called whenever a new string message is received +void handleRange(String route, int value) { + // print the message that was received + SerialUSB.print("From "); + SerialUSB.print(route); + SerialUSB.print(", received msg: "); + SerialUSB.println(value); +} + diff --git a/libraries/Bridge/examples/SpacebrewYun/spacebrewString/spacebrewString.ino b/libraries/Bridge/examples/SpacebrewYun/spacebrewString/spacebrewString.ino new file mode 100644 index 0000000..189d311 --- /dev/null +++ b/libraries/Bridge/examples/SpacebrewYun/spacebrewString/spacebrewString.ino @@ -0,0 +1,86 @@ +/* + Spacebrew String + + Demonstrates how to create a sketch that sends and receives strings + to and from Spacebrew. Every time string data is received it + is output to the Serial monitor. + + Make sure that your Yún is connected to the internet for this example + to function properly. + + The circuit: + - No circuit required + + created 2013 + by Julio Terra + + This example code is in the public domain. + + More information about Spacebrew is available at: + http://spacebrew.cc/ + + */ + +#include +#include + +// create a variable of type SpacebrewYun and initialize it with the constructor +SpacebrewYun sb = SpacebrewYun("spacebrewYun Strings", "String sender and receiver"); + +// create variables to manage interval between each time we send a string +long last_time = 0; +int interval = 2000; + +void setup() { + + // start the serial port + SerialUSB.begin(57600); + + // for debugging, wait until a serial console is connected + delay(4000); + while (!SerialUSB) { + ; + } + + // start-up the bridge + Bridge.begin(); + + // configure the spacebrew object to print status messages to serial + sb.verbose(true); + + // configure the spacebrew publisher and subscriber + sb.addPublish("speak", "string"); + sb.addSubscribe("listen", "string"); + + // register the string message handler method + sb.onStringMessage(handleString); + + // connect to cloud spacebrew server at "sandbox.spacebrew.cc" + sb.connect("sandbox.spacebrew.cc"); +} + + +void loop() { + // monitor spacebrew connection for new data + sb.monitor(); + + // connected to spacebrew then send a string every 2 seconds + if (sb.connected()) { + + // check if it is time to send a new message + if ((millis() - last_time) > interval) { + sb.send("speak", "is anybody out there?"); + last_time = millis(); + } + } +} + +// handler method that is called whenever a new string message is received +void handleString(String route, String value) { + // print the message that was received + SerialUSB.print("From "); + SerialUSB.print(route); + SerialUSB.print(", received msg: "); + SerialUSB.println(value); +} + diff --git a/libraries/Bridge/examples/TemperatureWebPanel/TemperatureWebPanel.ino b/libraries/Bridge/examples/TemperatureWebPanel/TemperatureWebPanel.ino new file mode 100644 index 0000000..3a3ba67 --- /dev/null +++ b/libraries/Bridge/examples/TemperatureWebPanel/TemperatureWebPanel.ino @@ -0,0 +1,125 @@ +/* + Temperature web interface + + This example shows how to serve data from an analog input + via the Arduino Yún's built-in webserver using the Bridge library. + + The circuit: + * TMP36 temperature sensor on analog pin A1 + * SD card attached to SD card slot of the Arduino Yún + + This sketch must be uploaded via wifi. REST API must be set to "open". + + Prepare your SD card with an empty folder in the SD root + named "arduino" and a subfolder of that named "www". + This will ensure that the Yún will create a link + to the SD to the "/mnt/sd" path. + + In this sketch folder is a basic webpage and a copy of zepto.js, a + minimized version of jQuery. When you upload your sketch, these files + will be placed in the /arduino/www/TemperatureWebPanel folder on your SD card. + + You can then go to http://arduino.local/sd/TemperatureWebPanel + to see the output of this sketch. + + You can remove the SD card while the Linux and the + sketch are running but be careful not to remove it while + the system is writing to it. + + created 6 July 2013 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/TemperatureWebPanel + + */ + +#include +#include +#include + +// Listen on default port 5555, the webserver on the Yún +// will forward there all the HTTP requests for us. +BridgeServer server; +String startString; +long hits = 0; + +void setup() { + SerialUSB.begin(9600); + + // Bridge startup + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); + digitalWrite(13, HIGH); + + // using A0 and A2 as vcc and gnd for the TMP36 sensor: + pinMode(A0, OUTPUT); + pinMode(A2, OUTPUT); + digitalWrite(A0, HIGH); + digitalWrite(A2, LOW); + + // Listen for incoming connection only from localhost + // (no one from the external network could connect) + server.listenOnLocalhost(); + server.begin(); + + // get the time that this sketch started: + Process startTime; + startTime.runShellCommand("date"); + while (startTime.available()) { + char c = startTime.read(); + startString += c; + } +} + +void loop() { + // Get clients coming from server + BridgeClient client = server.accept(); + + // There is a new client? + if (client) { + // read the command + String command = client.readString(); + command.trim(); //kill whitespace + SerialUSB.println(command); + // is "temperature" command? + if (command == "temperature") { + + // get the time from the server: + Process time; + time.runShellCommand("date"); + String timeString = ""; + while (time.available()) { + char c = time.read(); + timeString += c; + } + SerialUSB.println(timeString); + int sensorValue = analogRead(A1); + // convert the reading to millivolts: + float voltage = sensorValue * (5000.0f / 1024.0f); + // convert the millivolts to temperature celsius: + float temperature = (voltage - 500.0f) / 10.0f; + // print the temperature: + client.print("Current time on the Yún: "); + client.println(timeString); + client.print("
Current temperature: "); + client.print(temperature); + client.print(" °C"); + client.print("
This sketch has been running since "); + client.print(startString); + client.print("
Hits so far: "); + client.print(hits); + } + + // Close connection and free resources. + client.stop(); + hits++; + } + + delay(50); // Poll every 50ms +} + + + diff --git a/libraries/Bridge/examples/TemperatureWebPanel/www/index.html b/libraries/Bridge/examples/TemperatureWebPanel/www/index.html new file mode 100644 index 0000000..c6b6747 --- /dev/null +++ b/libraries/Bridge/examples/TemperatureWebPanel/www/index.html @@ -0,0 +1,16 @@ + + + + + + + + + 0 + + + diff --git a/libraries/Bridge/examples/TemperatureWebPanel/www/zepto.min.js b/libraries/Bridge/examples/TemperatureWebPanel/www/zepto.min.js new file mode 100644 index 0000000..dbe4e3c --- /dev/null +++ b/libraries/Bridge/examples/TemperatureWebPanel/www/zepto.min.js @@ -0,0 +1,2 @@ +/* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */ +(function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?c.fn.concat.apply([],a):a}function O(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function P(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function Q(a,b){return typeof b=="number"&&!l[O(a)]?b+"px":b}function R(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=k(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function S(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function T(c,d,e){for(b in d)e&&(J(d[b])||K(d[b]))?(J(d[b])&&!J(c[b])&&(c[b]={}),K(d[b])&&!K(c[b])&&(c[b]=[]),T(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function U(b,d){return d===a?c(b):c(b).filter(d)}function V(a,b,c,d){return F(b)?b.call(a,c,d):b}function W(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function X(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function Y(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:isNaN(b=Number(a))?/^[\[\{]/.test(a)?c.parseJSON(a):a:b):a}catch(d){return a}}function Z(a,b){b(a);for(var c in a.childNodes)Z(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k=h.defaultView.getComputedStyle,l={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},m=/^\s*<(\w+|!)[^>]*>/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=["val","css","html","text","data","width","height","offset"],q=["after","prepend","before","append"],r=h.createElement("table"),s=h.createElement("tr"),t={tr:h.createElement("tbody"),tbody:r,thead:r,tfoot:r,td:s,th:s,"*":h.createElement("div")},u=/complete|loaded|interactive/,v=/^\.([\w-]+)$/,w=/^#([\w-]*)$/,x=/^[\w-]+$/,y={},z=y.toString,A={},B,C,D=h.createElement("div");return A.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=D).appendChild(a),d=~A.qsa(e,b).indexOf(a),f&&D.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},A.fragment=function(b,d,e){b.replace&&(b=b.replace(n,"<$1>")),d===a&&(d=m.test(b)&&RegExp.$1),d in t||(d="*");var g,h,i=t[d];return i.innerHTML=""+b,h=c.each(f.call(i.childNodes),function(){i.removeChild(this)}),J(e)&&(g=c(h),c.each(e,function(a,b){p.indexOf(a)>-1?g[a](b):g.attr(a,b)})),h},A.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},A.isZ=function(a){return a instanceof A.Z},A.init=function(b,d){if(!b)return A.Z();if(F(b))return c(h).ready(b);if(A.isZ(b))return b;var e;if(K(b))e=M(b);else if(I(b))e=[J(b)?c.extend({},b):b],b=null;else if(m.test(b))e=A.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=A.qsa(h,b)}return A.Z(e,b)},c=function(a,b){return A.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){T(a,c,b)}),a},A.qsa=function(a,b){var c;return H(a)&&w.test(b)?(c=a.getElementById(RegExp.$1))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(v.test(b)?a.getElementsByClassName(RegExp.$1):x.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=E,c.isFunction=F,c.isWindow=G,c.isArray=K,c.isPlainObject=J,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=B,c.trim=function(a){return a.trim()},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(L(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return F(a)?this.not(this.not(a)):c(g.call(this,function(b){return A.matches(b,a)}))},add:function(a,b){return c(C(this.concat(c(a,b))))},is:function(a){return this.length>0&&A.matches(this[0],a)},not:function(b){var d=[];if(F(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):L(b)&&F(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return I(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!I(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!I(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(A.qsa(this[0],a)):b=this.map(function(){return A.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:A.matches(d,a)))d=d!==b&&!H(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!H(a)&&b.indexOf(a)<0)return b.push(a),a});return U(b,a)},parent:function(a){return U(C(this.pluck("parentNode")),a)},children:function(a){return U(this.map(function(){return S(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return U(this.map(function(a,b){return g.call(S(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),k(this,"").getPropertyValue("display")=="none"&&(this.style.display=R(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=F(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=F(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(V(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(I(c))for(b in c)W(this,b,c[b]);else W(this,c,V(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&W(this,a)})},prop:function(b,c){return c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=V(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+O(b),c);return d!==null?Y(d):a},val:function(b){return b===a?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(a){return this.selected}).pluck("value"):this[0].value):this.each(function(a){this.value=V(this,b,a,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=V(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,c){if(arguments.length<2&&typeof a=="string")return this[0]&&(this[0].style[B(a)]||k(this[0],"").getPropertyValue(a));var d="";if(E(a)=="string")!c&&c!==0?this.each(function(){this.style.removeProperty(O(a))}):d=O(a)+":"+Q(a,c);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(O(b))}):d+=O(b)+":"+Q(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+d})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return e.some.call(this,function(a){return this.test(X(a))},P(a))},addClass:function(a){return this.each(function(b){d=[];var e=X(this),f=V(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&X(this,e+(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return X(this,"");d=X(this),V(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(P(a)," ")}),X(this,d.trim())})},toggleClass:function(b,d){return this.each(function(e){var f=c(this),g=V(this,b,e,X(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=this[0],g=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?G(f)?f["inner"+g]:H(f)?f.documentElement["offset"+g]:(e=this.offset())&&e[b]:this.each(function(a){f=c(this),f.css(b,V(this,d,a,f[b]()))})}}),q.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=E(b),a=="object"||a=="array"||b==null?b:A.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();Z(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),A.Z.prototype=c.fn,A.uniq=C,A.deserializeValue=Y,c.zepto=A,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/),m=a.match(/(BB10).*Version\/([\d.]+)/),n=a.match(/(RIM\sTablet\sOS)\s([\d.]+)/),o=a.match(/PlayBook/),p=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),q=a.match(/Firefox\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),m&&(b.bb10=!0,b.version=m[2]),n&&(b.rimtabletos=!0,b.version=n[2]),o&&(c.playbook=!0),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0),p&&(c.chrome=!0,c.version=p[1]),q&&(c.firefox=!0,c.version=q[1]),b.tablet=!!(f||o||e&&!a.match(/Mobile/)||q&&a.match(/Tablet/)),b.phone=!b.tablet&&!!(e||g||h||l||m||p&&a.match(/Android/)||p&&a.match(/CriOS\/([\d.]+)/)||q&&a.match(/Mobile/))}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a){function g(a){return a._zid||(a._zid=d++)}function h(a,b,d,e){b=i(b);if(b.ns)var f=j(b.ns);return(c[g(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||f.test(a.ns))&&(!d||g(a.fn)===g(d))&&(!e||a.sel==e)})}function i(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function j(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function k(b,c,d){a.type(b)!="string"?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function l(a,b){return a.del&&(a.e=="focus"||a.e=="blur")||!!b}function m(a){return f[a]||a}function n(b,d,e,h,j,n){var o=g(b),p=c[o]||(c[o]=[]);k(d,e,function(c,d){var e=i(c);e.fn=d,e.sel=h,e.e in f&&(d=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return e.fn.apply(this,arguments)}),e.del=j&&j(d,c);var g=e.del||d;e.proxy=function(a){var c=g.apply(b,[a].concat(a.data));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},e.i=p.length,p.push(e),b.addEventListener(m(e.e),e.proxy,l(e,n))})}function o(a,b,d,e,f){var i=g(a);k(b||"",d,function(b,d){h(a,b,d,e).forEach(function(b){delete c[i][b.i],a.removeEventListener(m(b.e),b.proxy,l(b,f))})})}function t(b){var c,d={originalEvent:b};for(c in b)!r.test(c)&&b[c]!==undefined&&(d[c]=b[c]);return a.each(s,function(a,c){d[a]=function(){return this[c]=p,b[a].apply(b,arguments)},d[c]=q}),d}function u(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={},f={mouseenter:"mouseover",mouseleave:"mouseout"};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:n,remove:o},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=g(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){n(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){o(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){n(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return o(d,b,a),c}})})};var p=function(){return!0},q=function(){return!1},r=/^([A-Z]|layer[XY]$)/,s={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){return this.each(function(e,f){n(f,c,d,b,function(c){return function(d){var e,g=a(d.target).closest(b,f).get(0);if(g)return e=a.extend(t(d),{currentTarget:g,liveFired:f}),c.apply(g,[e].concat([].slice.call(arguments,1)))}})})},a.fn.undelegate=function(a,b,c){return this.each(function(){o(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return!c||a.isFunction(c)?this.bind(b,c||d):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return!c||a.isFunction(c)?this.unbind(b,c||d):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){if(typeof b=="string"||a.isPlainObject(b))b=a.Event(b);return u(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,g){d=t(typeof b=="string"?a.Event(b):b),d.data=c,d.target=g,a.each(h(g,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){typeof a!="string"&&(b=a,a=b.type);var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c.isDefaultPrevented=function(){return this.defaultPrevented},c}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b);$.each(b,function(b,g){e=$.type(g),d&&(b=c?d:d+"["+(f?"":b)+"]"),!d&&f?a.add(g.name,g.value):e=="array"||!c&&e=="object"?serialize(a,g,c,b):a.add(b,g)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){if("type"in a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){clearTimeout(g),$(c).remove(),delete window[b]},e=function(c){d();if(!c||c=="timeout")window[b]=empty;ajaxError(null,c||"abort",f,a)},f={abort:e},g;return ajaxBeforeSend(f,a)===!1?(e("abort"),!1):(window[b]=function(b){d(),ajaxSuccess(b,f,a)},c.onerror=function(){e("error")},c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(g=setTimeout(function(){e("timeout")},a.timeout)),f)}return $.ajax(a)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host),settings.url||(settings.url=window.location.toString()),serializeData(settings),settings.cache===!1&&(settings.url=appendQuery(settings.url,"_="+Date.now()));var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,xhr.status?"error":"abort",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b,c,d){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(a,b,c,d){var e=parseArguments.apply(null,arguments);return e.type="POST",$.ajax(e)},$.getJSON=function(a,b,c){var d=parseArguments.apply(null,arguments);return d.dataType="json",$.ajax(d)},$.fn.load=function(a,b,c){if(!this.length)return this;var d=this,e=a.split(/\s/),f,g=parseArguments(a,b,c),h=g.success;return e.length>1&&(g.url=e[0],f=e[1]),g.success=function(a){d.html(f?$("
").html(a.replace(rscript,"")).find(f):a),h&&h.apply(d,arguments)},$.ajax(g),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace(/%20/g,"+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a,b){function s(a){return t(a.replace(/([a-z])([A-Z])/,"$1-$2"))}function t(a){return a.toLowerCase()}function u(a){return d?d+a:t(a)}var c="",d,e,f,g={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},h=window.document,i=h.createElement("div"),j=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,k,l,m,n,o,p,q,r={};a.each(g,function(a,e){if(i.style[a+"TransitionProperty"]!==b)return c="-"+t(a)+"-",d=e,!1}),k=c+"transform",r[l=c+"transition-property"]=r[m=c+"transition-duration"]=r[n=c+"transition-timing-function"]=r[o=c+"animation-name"]=r[p=c+"animation-duration"]=r[q=c+"animation-timing-function"]="",a.fx={off:d===b&&i.style.transitionProperty===b,speeds:{_default:400,fast:200,slow:600},cssPrefix:c,transitionEnd:u("TransitionEnd"),animationEnd:u("AnimationEnd")},a.fn.animate=function(b,c,d,e){return a.isPlainObject(c)&&(d=c.easing,e=c.complete,c=c.duration),c&&(c=(typeof c=="number"?c:a.fx.speeds[c]||a.fx.speeds._default)/1e3),this.anim(b,c,d,e)},a.fn.anim=function(c,d,e,f){var g,h={},i,t="",u=this,v,w=a.fx.transitionEnd;d===b&&(d=.4),a.fx.off&&(d=0);if(typeof c=="string")h[o]=c,h[p]=d+"s",h[q]=e||"linear",w=a.fx.animationEnd;else{i=[];for(g in c)j.test(g)?t+=g+"("+c[g]+") ":(h[g]=c[g],i.push(s(g)));t&&(h[k]=t,i.push(k)),d>0&&typeof c=="object"&&(h[l]=i.join(", "),h[m]=d+"s",h[n]=e||"linear")}return v=function(b){if(typeof b!="undefined"){if(b.target!==b.currentTarget)return;a(b.target).unbind(w,v)}a(this).css(r),f&&f.call(this)},d>0&&this.bind(w,v),this.size()&&this.get(0).clientLeft,this.css(h),d<=0&&setTimeout(function(){u.each(function(){v.call(this)})},0),this},i=null}(Zepto) diff --git a/libraries/Bridge/examples/TimeCheck/TimeCheck.ino b/libraries/Bridge/examples/TimeCheck/TimeCheck.ino new file mode 100644 index 0000000..af49b39 --- /dev/null +++ b/libraries/Bridge/examples/TimeCheck/TimeCheck.ino @@ -0,0 +1,88 @@ +/* + Time Check + + Gets the time from Linux via Bridge then parses out hours, + minutes and seconds for the Arduino using an Arduino Yún. + + created 27 May 2013 + modified 21 June 2013 + By Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/TimeCheck + + */ + + +#include + +Process date; // process used to get the date +int hours, minutes, seconds; // for the results +int lastSecond = -1; // need an impossible value for comparison + +void setup() { + Bridge.begin(); // initialize Bridge + SerialUSB.begin(9600); // initialize serial + + while (!Serial); // wait for Serial Monitor to open + SerialUSB.println("Time Check"); // Title of sketch + + // run an initial date process. Should return: + // hh:mm:ss : + if (!date.running()) { + date.begin("date"); + date.addParameter("+%T"); + date.run(); + } +} + +void loop() { + + if (lastSecond != seconds) { // if a second has passed + // print the time: + if (hours <= 9) { + SerialUSB.print("0"); // adjust for 0-9 + } + SerialUSB.print(hours); + SerialUSB.print(":"); + if (minutes <= 9) { + SerialUSB.print("0"); // adjust for 0-9 + } + SerialUSB.print(minutes); + SerialUSB.print(":"); + if (seconds <= 9) { + SerialUSB.print("0"); // adjust for 0-9 + } + SerialUSB.println(seconds); + + // restart the date process: + if (!date.running()) { + date.begin("date"); + date.addParameter("+%T"); + date.run(); + } + } + + //if there's a result from the date process, parse it: + while (date.available() > 0) { + // get the result of the date process (should be hh:mm:ss): + String timeString = date.readString(); + + // find the colons: + int firstColon = timeString.indexOf(":"); + int secondColon = timeString.lastIndexOf(":"); + + // get the substrings for hour, minute second: + String hourString = timeString.substring(0, firstColon); + String minString = timeString.substring(firstColon + 1, secondColon); + String secString = timeString.substring(secondColon + 1); + + // convert to ints,saving the previous second: + hours = hourString.toInt(); + minutes = minString.toInt(); + lastSecond = seconds; // save to do a time comparison + seconds = secString.toInt(); + } + +} diff --git a/libraries/Bridge/examples/WiFiStatus/WiFiStatus.ino b/libraries/Bridge/examples/WiFiStatus/WiFiStatus.ino new file mode 100644 index 0000000..556633e --- /dev/null +++ b/libraries/Bridge/examples/WiFiStatus/WiFiStatus.ino @@ -0,0 +1,52 @@ +/* + WiFi Status + + This sketch runs a script called "pretty-wifi-info.lua" + installed on your Yún in folder /usr/bin. + It prints information about the status of your wifi connection. + + It uses Serial to print, so you need to connect your Yún to your + computer using a USB cable and select the appropriate port from + the Port menu + + created 18 June 2013 + By Federico Fissore + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/YunWiFiStatus + + */ + +#include + +void setup() { + SerialUSB.begin(9600); // initialize serial communication + while (!SerialUSB); // do nothing until the serial monitor is opened + + SerialUSB.println("Starting bridge...\n"); + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); // make contact with the linux processor + digitalWrite(13, HIGH); // Led on pin 13 turns on when the bridge is ready + + delay(2000); // wait 2 seconds +} + +void loop() { + Process wifiCheck; // initialize a new process + + wifiCheck.runShellCommand("/usr/bin/pretty-wifi-info.lua"); // command you want to run + + // while there's any characters coming back from the + // process, print them to the serial monitor: + while (wifiCheck.available() > 0) { + char c = wifiCheck.read(); + SerialUSB.print(c); + } + + SerialUSB.println(); + + delay(5000); +} + diff --git a/libraries/Bridge/examples/YunFirstConfig/YunFirstConfig.ino b/libraries/Bridge/examples/YunFirstConfig/YunFirstConfig.ino new file mode 100644 index 0000000..cc91050 --- /dev/null +++ b/libraries/Bridge/examples/YunFirstConfig/YunFirstConfig.ino @@ -0,0 +1,327 @@ + +/* + Arduino Yún First configuration sketch + + Configures the Yun's wifi and infos via the Bridge + Works correctly if Line Ending is set as "NewLine" + If your board has two USB ports, use the Native one + + The circuit: + Arduino Yún/Yún101/YunShield with firmware > 1.6.1 + + created March 2016 + by Arduino LLC + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/YunFirstConfig +*/ + +#include + +#define MAX_WIFI_LIST 10 + +String networks[MAX_WIFI_LIST]; +String yunName; +String yunPassword; + +void setup() { + SERIAL_PORT_USBVIRTUAL.begin(9600); // initialize serial communication + while (!SERIAL_PORT_USBVIRTUAL); // do nothing until the serial monitor is opened + + SERIAL_PORT_USBVIRTUAL.println(F("Hi! Nice to see you!")); + SERIAL_PORT_USBVIRTUAL.println(F("I'm your Yun101 assistant sketch")); + SERIAL_PORT_USBVIRTUAL.println(F("I'll help you configuring your Yun in a matter of minutes")); + + SERIAL_PORT_USBVIRTUAL.println(F("Let's start by communicating with the Linux processor")); + SERIAL_PORT_USBVIRTUAL.println(F("When LED (L13) will light up we'll be ready to go!")); + SERIAL_PORT_USBVIRTUAL.println(F("Waiting...")); + SERIAL_PORT_USBVIRTUAL.println(F("(in the meanwhile, if you are using the IDE's serial monitor, make sure that it's configured to send a \"Newline\")\n")); + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); // make contact with the linux processor + digitalWrite(13, HIGH); // Led on pin 13 turns on when the bridge is ready + + // Recover if the board is in AP mode - unused + Process wifiList; + bool master = false; + wifiList.runShellCommand(F("iwinfo | grep \"Mode: Master\"")); + while (wifiList.available() > 0) { + wifiList.read(); + master = true; + } + + // Get the list of reachable networks + wifiList.runShellCommand(F("iwinfo wlan0 scan | grep ESSID | cut -d\"\\\"\" -f2")); + + uint8_t num_networks = 0; + uint8_t i = 0; + char c; + bool dropNet = false; + + networks[0].reserve(32); + + while (wifiList.available() > 0) { + c = wifiList.read(); + if (c != '\n') { + networks[i] += c; + } else { + // check if we already found networks[i] and eventually drop it + for (uint8_t s = 0; s < i; s++) { + if (networks[i].equals(networks[s])) { + dropNet = true; + } + } + if (i <= MAX_WIFI_LIST && dropNet == false) { + networks[i++].reserve(32); + } else { + dropNet = false; + networks[i]=""; + } + } + } + + num_networks = i; + + String encryption; + String password; + int chose = 0; + + // If networks number is 0, start manual configuration + if (num_networks == 0) { + SERIAL_PORT_USBVIRTUAL.println(F("Oops, it seems that you have no WiFi network available")); + SERIAL_PORT_USBVIRTUAL.println(F("Let's configure it manually")); + SERIAL_PORT_USBVIRTUAL.println(F("SSID of the network you want to connect to: ")); + networks[0] = getUserInput(networks[0], false); + SERIAL_PORT_USBVIRTUAL.println(F("Password for the network you want to connect to: ")); + password = getUserInput(password, true); + SERIAL_PORT_USBVIRTUAL.print(F("Encryption (eg WPA, WPA2, WEP): ")); + encryption = getUserInput(encryption, false); + } else { + // else print them prepending a number + SERIAL_PORT_USBVIRTUAL.print(F("It looks like you have ")); + SERIAL_PORT_USBVIRTUAL.print(num_networks); + SERIAL_PORT_USBVIRTUAL.println(F(" networks around you ")); + SERIAL_PORT_USBVIRTUAL.println(F("Which one do you want to connect to?\n")); + for (i = 0; i < num_networks && i < MAX_WIFI_LIST; i++) { + SERIAL_PORT_USBVIRTUAL.print(i); + SERIAL_PORT_USBVIRTUAL.println(") " + networks[i]); + } + String selection; + selection = getUserInput(selection, false); + chose = atoi(selection.c_str()); + } + + // Extract the selected network security + bool openNet = false; + wifiList.runShellCommand("iwinfo wlan0 scan | grep \"" + networks[chose] + "\" -A5 | grep Encryption | cut -f2 -d\":\""); + while (wifiList.available() > 0) { + c = wifiList.read(); + encryption += c; + } + + if (encryption.indexOf("none") >= 0) { + openNet = true; + encryption = "none"; + } + if (encryption.indexOf("WPA2") >= 0) { + encryption = "psk2"; + } + if (encryption.indexOf("WPA") >= 0) { + encryption = "psk"; + } + if (encryption.indexOf("WEP") >= 0) { + encryption = "wep"; + } + + if (openNet == false && password.length() == 0) { + SERIAL_PORT_USBVIRTUAL.print(F("It looks like you need a password to connect to ")); + SERIAL_PORT_USBVIRTUAL.println(networks[chose]); + SERIAL_PORT_USBVIRTUAL.print(F("Write it here: ")); + password = getUserInput(password, true); + } + + // Change hostname/root password + SERIAL_PORT_USBVIRTUAL.println(F("We are almost done! Give a name and a password to your Yun")); + SERIAL_PORT_USBVIRTUAL.print(F("Name: ")); + yunName = getUserInput(yunName, false); + SERIAL_PORT_USBVIRTUAL.print(F("Password: ")); + yunPassword = getUserInput(yunPassword, true); + + // Select a country code + String countryCode; + SERIAL_PORT_USBVIRTUAL.println(F("One last question: where do you live?")); + SERIAL_PORT_USBVIRTUAL.print(F("Insert a two letters county code (eg IT, US, DE): ")); + countryCode = getUserInput(countryCode, false); + + yunName.trim(); + yunPassword.trim(); + networks[chose].trim(); + password.trim(); + countryCode.trim(); + + // Configure the Yun with user provided strings + wifiConfig(yunName, yunPassword, networks[chose], password, "YUN" + yunName + "AP", countryCode, encryption); + + SERIAL_PORT_USBVIRTUAL.print(F("Waiting for the Yun to connect to the network")); +} + +bool Connected = false; +bool serialTerminalMode = false; +int runs = 0; + +void loop() { + if (!serialTerminalMode) { + String resultStr = ""; + + if (!Connected) { + SERIAL_PORT_USBVIRTUAL.print("."); + runs++; + } + + // If it takes more than 20 seconds to connect, stop trying + if (runs > 20) { + SERIAL_PORT_USBVIRTUAL.println(""); + SERIAL_PORT_USBVIRTUAL.println(F("We couldn't connect to the network.")); + SERIAL_PORT_USBVIRTUAL.println(F("Restart the board if you want to execute the wizard again")); + resultStr = getUserInput(resultStr, false); + } + + // Check if we have an IP address + Process wifiCheck; + wifiCheck.runShellCommand(F("/usr/bin/pretty-wifi-info.lua | grep \"IP address\" | cut -f2 -d\":\" | cut -f1 -d\"/\"" )); // command you want to run + while (wifiCheck.available() > 0) { + char c = wifiCheck.read(); + resultStr += c; + } + + delay(1000); + + if (resultStr != "") { + // We got an IP, freeze the loop, display the value and "spawn" a serial terminal + Connected = true; + resultStr.trim(); + SERIAL_PORT_USBVIRTUAL.println(""); + SERIAL_PORT_USBVIRTUAL.print(F("\nGreat! You can now reach your Yun from a browser typing http://")); + SERIAL_PORT_USBVIRTUAL.println(resultStr); + SERIAL_PORT_USBVIRTUAL.print(F("Press 'Enter' key twice to start a serial terminal")); + resultStr = getUserInput(resultStr, false); + serialTerminalMode = true; + //startSerialTerminal(); + SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command + delay(100); + SERIAL_PORT_HARDWARE.println("\nreset\n\n"); + SERIAL_PORT_HARDWARE.flush(); + SERIAL_PORT_HARDWARE.println("\nreset\n\n"); + SERIAL_PORT_HARDWARE.write((uint8_t *)"\n", 1); + } + + } else { + loopSerialTerminal(); + } +} + +String getUserInput(String out, bool obfuscated) { + /* + while (SerialUSB.available() <= 0) {} + while (SerialUSB.available() > 0) { + char c = SerialUSB.read(); + out += c; + } + return out; + */ + while (SERIAL_PORT_USBVIRTUAL.available() <= 0) {} + while (1) { + char c = SERIAL_PORT_USBVIRTUAL.read(); + if (c == '\n' || c == '\r') + break; + else { + if (c != -1) { + out += c; + if (obfuscated) + SERIAL_PORT_USBVIRTUAL.print("*"); + else + SERIAL_PORT_USBVIRTUAL.print(c); + } + } + } + SERIAL_PORT_USBVIRTUAL.println(""); + return out; +} + +void wifiConfig(String yunName, String yunPsw, String wifissid, String wifipsw, String wifiAPname, String countryCode, String encryption) { + Process p; + + p.runShellCommand("blink-start 100"); //start the blue blink + + p.runShellCommand("hostname " + yunName); //change the current hostname + p.runShellCommand("uci set system.@system[0].hostname='" + yunName + "'"); //change teh hostname in uci + + p.runShellCommand("uci set arduino.@arduino[0].access_point_wifi_name='" + wifiAPname + "'"); + + //this block resets the wifi psw + p.runShellCommand("uci set wireless.@wifi-iface[0].encryption='" + encryption + "'"); + p.runShellCommand("uci set wireless.@wifi-iface[0].mode='sta'\n"); + p.runShellCommand("uci set wireless.@wifi-iface[0].ssid='" + wifissid + "'"); + p.runShellCommand("uci set wireless.@wifi-iface[0].key='" + wifipsw + "'"); + p.runShellCommand("uci set wireless.radio0.channel='auto'"); + p.runShellCommand("uci set wireless.radio0.country='" + countryCode + "'"); + p.runShellCommand("uci delete network.lan.ipaddr"); + p.runShellCommand("uci delete network.lan.netmask"); + p.runShellCommand("uci set network.lan.proto='dhcp'"); + + p.runShellCommand("echo -e \"" + yunPsw + "\n" + yunPsw + "\" | passwd root"); //change the passwors + p.runShellCommand("uci commit"); //save the mods done via UCI + p.runShellCommand("blink-stop"); //start the blue blink + + p.runShellCommand("wifi "); +} + +long linuxBaud = 250000; + +void startSerialTerminal() { + SERIAL_PORT_USBVIRTUAL.begin(115200); // open serial connection via USB-Serial + SERIAL_PORT_HARDWARE.begin(linuxBaud); // open serial connection to Linux +} + +boolean commandMode = false; +void loopSerialTerminal() { + // copy from USB-CDC to UART + int c = SERIAL_PORT_USBVIRTUAL.read(); // read from USB-CDC + if (c != -1) { // got anything? + if (commandMode == false) { // if we aren't in command mode... + if (c == '~') { // Tilde '~' key pressed? + commandMode = true; // enter in command mode + } else { + SERIAL_PORT_HARDWARE.write(c); // otherwise write char to UART + } + } else { // if we are in command mode... + if (c == '0') { // '0' key pressed? + SERIAL_PORT_HARDWARE.begin(57600); // set speed to 57600 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 57600"); + } else if (c == '1') { // '1' key pressed? + SERIAL_PORT_HARDWARE.begin(115200); // set speed to 115200 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 115200"); + } else if (c == '2') { // '2' key pressed? + SERIAL_PORT_HARDWARE.begin(250000); // set speed to 250000 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 250000"); + } else if (c == '3') { // '3' key pressed? + SERIAL_PORT_HARDWARE.begin(500000); // set speed to 500000 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 500000"); + } else if (c == '~') { // '~` key pressed? + SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command + SERIAL_PORT_USBVIRTUAL.println("Sending bridge's shutdown command"); + } else { // any other key pressed? + SERIAL_PORT_HARDWARE.write('~'); // write '~' to UART + SERIAL_PORT_HARDWARE.write(c); // write char to UART + } + commandMode = false; // in all cases exit from command mode + } + } + + // copy from UART to USB-CDC + c = SERIAL_PORT_HARDWARE.read(); // read from UART + if (c != -1) { // got anything? + SERIAL_PORT_USBVIRTUAL.write(c); // write to USB-CDC + } +} diff --git a/libraries/Bridge/examples/YunSerialTerminal/YunSerialTerminal.ino b/libraries/Bridge/examples/YunSerialTerminal/YunSerialTerminal.ino new file mode 100644 index 0000000..98566d2 --- /dev/null +++ b/libraries/Bridge/examples/YunSerialTerminal/YunSerialTerminal.ino @@ -0,0 +1,82 @@ +/* + Arduino Yún USB-to-Serial + + Allows you to use the Yún's 32U4 processor as a + serial terminal for the Linux side on the Yún. + + Upload this to an Arduino Yún via serial (not WiFi) then open + the serial monitor at 115200 to see the boot process of Linux. + You can also use the serial monitor as a basic command line + interface for Linux using this sketch. + + From the serial monitor the following commands can be issued: + + '~' followed by '0' -> Set the UART speed to 57600 baud + '~' followed by '1' -> Set the UART speed to 115200 baud + '~' followed by '2' -> Set the UART speed to 250000 baud + '~' followed by '3' -> Set the UART speed to 500000 baud + '~' followed by '~' -> Sends the bridge's shutdown command to + obtain the console. + + The circuit: + Arduino Yún + + created March 2013 + by Massimo Banzi + modified by Cristian Maglie + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/YunSerialTerminal + +*/ + +long linuxBaud = 250000; + +void setup() { + SERIAL_PORT_USBVIRTUAL.begin(115200); // open serial connection via USB-Serial + SERIAL_PORT_HARDWARE.begin(linuxBaud); // open serial connection to Linux +} + +boolean commandMode = false; + +void loop() { + // copy from USB-CDC to UART + int c = SERIAL_PORT_USBVIRTUAL.read(); // read from USB-CDC + if (c != -1) { // got anything? + if (commandMode == false) { // if we aren't in command mode... + if (c == '~') { // Tilde '~' key pressed? + commandMode = true; // enter in command mode + } else { + SERIAL_PORT_HARDWARE.write(c); // otherwise write char to UART + } + } else { // if we are in command mode... + if (c == '0') { // '0' key pressed? + SERIAL_PORT_HARDWARE.begin(57600); // set speed to 57600 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 57600"); + } else if (c == '1') { // '1' key pressed? + SERIAL_PORT_HARDWARE.begin(115200); // set speed to 115200 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 115200"); + } else if (c == '2') { // '2' key pressed? + SERIAL_PORT_HARDWARE.begin(250000); // set speed to 250000 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 250000"); + } else if (c == '3') { // '3' key pressed? + SERIAL_PORT_HARDWARE.begin(500000); // set speed to 500000 + SERIAL_PORT_USBVIRTUAL.println("Speed set to 500000"); + } else if (c == '~') { // '~` key pressed? + SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command + SERIAL_PORT_USBVIRTUAL.println("Sending bridge's shutdown command"); + } else { // any other key pressed? + SERIAL_PORT_HARDWARE.write('~'); // write '~' to UART + SERIAL_PORT_HARDWARE.write(c); // write char to UART + } + commandMode = false; // in all cases exit from command mode + } + } + + // copy from UART to USB-CDC + c = SERIAL_PORT_HARDWARE.read(); // read from UART + if (c != -1) { // got anything? + SERIAL_PORT_USBVIRTUAL.write(c); // write to USB-CDC + } +} diff --git a/libraries/Bridge/keywords.txt b/libraries/Bridge/keywords.txt new file mode 100644 index 0000000..ef5d5eb --- /dev/null +++ b/libraries/Bridge/keywords.txt @@ -0,0 +1,92 @@ +####################################### +# Syntax Coloring Map For Bridge +####################################### + +####################################### +# Class (KEYWORD1) +####################################### + +Bridge KEYWORD1 YunBridgeLibrary +FileIO KEYWORD4 YunFileIOConstructor +FileSystem KEYWORD1 YunFileIOConstructor +Console KEYWORD1 YunConsoleConstructor +Process KEYWORD1 YunProcessConstructor +Mailbox KEYWORD1 YunMailboxConstructor +HttpClient KEYWORD1 YunHttpClientConstructor +YunServer KEYWORD1 YunServerConstructor +YunClient KEYWORD1 YunClientConstructor +BridgeServer KEYWORD1 YunServerConstructor +BridgeClient KEYWORD1 YunClientConstructor +BridgeSSLClient KEYWORD1 YunClientConstructor + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +# methods names in commond +begin KEYWORD2 +end KEYWORD2 +available KEYWORD2 +read KEYWORD2 +peek KEYWORD2 +write KEYWORD2 +flush KEYWORD2 +bool KEYWORD2 + +# Bridge Class +transfer KEYWORD2 +put KEYWORD2 +get KEYWORD2 + +# Console Class +buffer KEYWORD2 +noBuffer KEYWORD2 +connected KEYWORD2 + +# FileIO Class +File KEYWORD2 +BridgeFile KEYWORD2 +seek KEYWORD2 +position KEYWORD2 +size KEYWORD2 +close KEYWORD2 +name KEYWORD2 +isDirectory KEYWORD2 +openNextFile KEYWORD2 +rewindDirectory KEYWORD2 + +# Process Class +addParameter KEYWORD2 +runAsynchronously KEYWORD2 +run KEYWORD2 +running KEYWORD2 +exitValue KEYWORD2 +runShellCommand KEYWORD2 +runShellCommandAsynchronously KEYWORD2 + +# Mailbox Class +readMessage KEYWORD2 +writeMessage KEYWORD2 +writeJSON KEYWORD2 +message Available KEYWORD2 + +# HttpClient Class +getAsynchronously KEYWORD2 +ready KEYWORD2 +getResult KEYWORD2 + +# BridgeServer Class +accept KEYWORD2 +stop KEYWORD2 +connect KEYWORD2 +connectSSL KEYWORD2 +connected KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### + +FILE_READ LITERAL1 +FILE_WRITE LITERAL1 +FILE_APPEND LITERAL1 diff --git a/libraries/Bridge/library.properties b/libraries/Bridge/library.properties new file mode 100644 index 0000000..381f7ce --- /dev/null +++ b/libraries/Bridge/library.properties @@ -0,0 +1,10 @@ +name=Bridge +version=1.6.2 +author=Arduino +maintainer=Arduino +sentence=Enables the communication between the Linux processor and the microcontroller. For Arduino/Genuino Yún, Yún Shield and TRE only. +paragraph=The Bridge library feature: access to the shared storage, run and manage linux processes, open a remote console, access to the linux file system, including the SD card, enstablish http clients or servers. +category=Communication +url=http://www.arduino.cc/en/Reference/YunBridgeLibrary +architectures=* +dot_a_linkage=true diff --git a/libraries/Bridge/src/Bridge.cpp b/libraries/Bridge/src/Bridge.cpp new file mode 100644 index 0000000..02be380 --- /dev/null +++ b/libraries/Bridge/src/Bridge.cpp @@ -0,0 +1,281 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Bridge.h" + +BridgeClass::BridgeClass(Stream &_stream) : + index(0), stream(_stream), started(false), max_retries(0) { + // Empty +} + +void BridgeClass::begin() { + if (started) + return; + started = true; + + // Wait for U-boot to finish startup + do { + dropAll(); + delay(1000); + } while (stream.available() > 0); + + while (true) { + // Bridge interrupt: + // - Ask the bridge to close itself + uint8_t quit_cmd[] = {'X', 'X', 'X', 'X', 'X'}; + max_retries = 1; + transfer(quit_cmd, 5); + + // Bridge startup: + // - If the bridge is not running starts it safely + stream.print(CTRL_C); + delay(250); + stream.print(F("\n")); + delay(250); + stream.print(F("\n")); + delay(500); + // Wait for OpenWRT message + // "Press enter to activate console" + stream.print(F("run-bridge\n")); + delay(500); + dropAll(); + + // Reset the brigde to check if it is running + uint8_t cmd[] = {'X', 'X', '1', '0', '0'}; + uint8_t res[4]; + max_retries = 50; + uint16_t l = transfer(cmd, 5, res, 4); + if (l == TRANSFER_TIMEOUT) { + // Bridge didn't start... + // Maybe the board is starting-up? + + // Wait and retry + delay(1000); + continue; + } + if (res[0] != 0) + while (true); + + // Detect bridge version + if (l == 4) { + bridgeVersion = (res[1]-'0')*100 + (res[2]-'0')*10 + (res[3]-'0'); + } else { + // Bridge v1.0.0 didn't send any version info + bridgeVersion = 100; + } + + max_retries = 50; + return; + } +} + +void BridgeClass::put(const char *key, const char *value) { + // TODO: do it in a more efficient way + String cmd = "D"; + uint8_t res[1]; + cmd += key; + cmd += "\xFE"; + cmd += value; + transfer((uint8_t*)cmd.c_str(), cmd.length(), res, 1); +} + +unsigned int BridgeClass::get(const char *key, uint8_t *value, unsigned int maxlen) { + uint8_t cmd[] = {'d'}; + unsigned int l = transfer(cmd, 1, (uint8_t *)key, strlen(key), value, maxlen); + if (l < maxlen) + value[l] = 0; // Zero-terminate string + return l; +} + +#if defined(ARDUINO_ARCH_AVR) +// AVR use an optimized implementation of CRC +#include +#else +// Generic implementation for non-AVR architectures +uint16_t _crc_ccitt_update(uint16_t crc, uint8_t data) +{ + data ^= crc & 0xff; + data ^= data << 4; + return ((((uint16_t)data << 8) | ((crc >> 8) & 0xff)) ^ + (uint8_t)(data >> 4) ^ + ((uint16_t)data << 3)); +} +#endif + +void BridgeClass::crcUpdate(uint8_t c) { + CRC = _crc_ccitt_update(CRC, c); +} + +void BridgeClass::crcReset() { + CRC = 0xFFFF; +} + +void BridgeClass::crcWrite() { + stream.write((char)(CRC >> 8)); + stream.write((char)(CRC & 0xFF)); +} + +bool BridgeClass::crcCheck(uint16_t _CRC) { + return CRC == _CRC; +} + +uint16_t BridgeClass::transfer(const uint8_t *buff1, uint16_t len1, + const uint8_t *buff2, uint16_t len2, + const uint8_t *buff3, uint16_t len3, + uint8_t *rxbuff, uint16_t rxlen) +{ + uint16_t len = len1 + len2 + len3; + uint8_t retries = 0; + for ( ; retries < max_retries; retries++, delay(100), dropAll() /* Delay for retransmission */) { + // Send packet + crcReset(); + stream.write((char)0xFF); // Start of packet (0xFF) + crcUpdate(0xFF); + stream.write((char)index); // Message index + crcUpdate(index); + stream.write((char)((len >> 8) & 0xFF)); // Message length (hi) + crcUpdate((len >> 8) & 0xFF); + stream.write((char)(len & 0xFF)); // Message length (lo) + crcUpdate(len & 0xFF); + for (uint16_t i = 0; i < len1; i++) { // Payload + stream.write((char)buff1[i]); + crcUpdate(buff1[i]); + } + for (uint16_t i = 0; i < len2; i++) { // Payload + stream.write((char)buff2[i]); + crcUpdate(buff2[i]); + } + for (uint16_t i = 0; i < len3; i++) { // Payload + stream.write((char)buff3[i]); + crcUpdate(buff3[i]); + } + crcWrite(); // CRC + + // Wait for ACK in 100ms + if (timedRead(100) != 0xFF) + continue; + crcReset(); + crcUpdate(0xFF); + + // Check packet index + if (timedRead(5) != index) + continue; + crcUpdate(index); + + // Recv len + int lh = timedRead(10); + if (lh < 0) + continue; + crcUpdate(lh); + int ll = timedRead(10); + if (ll < 0) + continue; + crcUpdate(ll); + uint16_t l = lh; + l <<= 8; + l += ll; + + // Recv data + for (uint16_t i = 0; i < l; i++) { + // Cut received data if rxbuffer is too small + if (i >= rxlen) + break; + int c = timedRead(5); + if (c < 0) + continue; + rxbuff[i] = c; + crcUpdate(c); + } + + // Check CRC + int crc_hi = timedRead(5); + if (crc_hi < 0) + continue; + int crc_lo = timedRead(5); + if (crc_lo < 0) + continue; + if (!crcCheck((crc_hi << 8) + crc_lo)) + continue; + + // Increase index + index++; + + // Return bytes received + if (l > rxlen) + return rxlen; + return l; + } + + // Max retries exceeded + return TRANSFER_TIMEOUT; +} + +int BridgeClass::timedRead(unsigned int timeout) { + int c; + unsigned long _startMillis = millis(); + do { + c = stream.read(); + if (c >= 0) return c; + } while (millis() - _startMillis < timeout); + return -1; // -1 indicates timeout +} + +void BridgeClass::dropAll() { + while (stream.available() > 0) { + stream.read(); + } +} + +#if defined(ARDUINO_ARCH_SAM) +#include +#endif + +#if defined(ARDUINO_ARCH_SAM) +void checkForRemoteSketchUpdate(uint8_t pin) { + // The host force pin LOW to signal that a new sketch is coming + pinMode(pin, INPUT_PULLUP); + delay(50); + if (digitalRead(pin) == LOW) { + initiateReset(1); + while (true) + ; // Wait for reset to SAM-BA + } + + // Restore in standard state + pinMode(pin, INPUT); +} +#else +void checkForRemoteSketchUpdate(uint8_t /* pin */) { + // Empty, bootloader is enough. +} +#endif + +// Bridge instance +#if defined(SERIAL_PORT_LINUXBRIDGE) +SerialBridgeClass Bridge(SERIAL_PORT_LINUXBRIDGE); +#elif defined(SERIAL_PORT_HARDWARE) +SerialBridgeClass Bridge(SERIAL_PORT_HARDWARE); +#elif defined(SERIAL_PORT_HARDWARE_OPEN) +SerialBridgeClass Bridge(SERIAL_PORT_HARDWARE_OPEN); +#elif defined(__AVR_ATmega32U4__) // Legacy fallback +// Leonardo variants (where HardwareSerial is Serial1) +SerialBridgeClass Bridge(Serial1); +#else +SerialBridgeClass Bridge(Serial); +#endif + diff --git a/libraries/Bridge/src/Bridge.h b/libraries/Bridge/src/Bridge.h new file mode 100644 index 0000000..63361f1 --- /dev/null +++ b/libraries/Bridge/src/Bridge.h @@ -0,0 +1,125 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef BRIDGE_H_ +#define BRIDGE_H_ + +#ifndef BRIDGE_BAUDRATE +#define BRIDGE_BAUDRATE 250000 +#endif + +#include +#include + +class BridgeClass { + public: + BridgeClass(Stream &_stream); + void begin(); + + // Methods to handle key/value datastore + void put(const char *key, const char *value); + void put(const String &key, const String &value) + { + put(key.c_str(), value.c_str()); + } + unsigned int get(const char *key, uint8_t *buff, unsigned int size); + unsigned int get(const char *key, char *value, unsigned int maxlen) + { + return get(key, reinterpret_cast(value), maxlen); + } + + // Trasnfer a frame (with error correction and response) + uint16_t transfer(const uint8_t *buff1, uint16_t len1, + const uint8_t *buff2, uint16_t len2, + const uint8_t *buff3, uint16_t len3, + uint8_t *rxbuff, uint16_t rxlen); + // multiple inline versions of the same function to allow efficient frame concatenation + uint16_t transfer(const uint8_t *buff1, uint16_t len1) + { + return transfer(buff1, len1, NULL, 0); + } + uint16_t transfer(const uint8_t *buff1, uint16_t len1, + uint8_t *rxbuff, uint16_t rxlen) + { + return transfer(buff1, len1, NULL, 0, rxbuff, rxlen); + } + uint16_t transfer(const uint8_t *buff1, uint16_t len1, + const uint8_t *buff2, uint16_t len2, + uint8_t *rxbuff, uint16_t rxlen) + { + return transfer(buff1, len1, buff2, len2, NULL, 0, rxbuff, rxlen); + } + + uint16_t getBridgeVersion() + { + return bridgeVersion; + } + + static const uint16_t TRANSFER_TIMEOUT = 0xFFFF; + + private: + uint8_t index; + int timedRead(unsigned int timeout); + void dropAll(); + uint16_t bridgeVersion; + + private: + void crcUpdate(uint8_t c); + void crcReset(); + void crcWrite(); + bool crcCheck(uint16_t _CRC); + uint16_t CRC; + + private: + static const char CTRL_C = 3; + Stream &stream; + bool started; + uint8_t max_retries; +}; + +// This subclass uses a serial port Stream +class SerialBridgeClass : public BridgeClass { + public: + SerialBridgeClass(HardwareSerial &_serial) + : BridgeClass(_serial), serial(_serial) { + // Empty + } + + void begin(unsigned long baudrate = BRIDGE_BAUDRATE) { + serial.begin(baudrate); + BridgeClass::begin(); + } + + private: + HardwareSerial &serial; +}; + +extern SerialBridgeClass Bridge; + +// Some microcrontrollers don't start the bootloader after a reset. +// This function is intended to let the microcontroller erase its +// flash after checking a specific signal coming from the external +// device without the need to press the erase button on the board. +// The purpose is to enable a software update that does not require +// a manual interaction with the board. +extern void checkForRemoteSketchUpdate(uint8_t pin = 7); + +#endif /* BRIDGE_H_ */ + +#include +#include diff --git a/libraries/Bridge/src/BridgeClient.cpp b/libraries/Bridge/src/BridgeClient.cpp new file mode 100644 index 0000000..a342abc --- /dev/null +++ b/libraries/Bridge/src/BridgeClient.cpp @@ -0,0 +1,207 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +BridgeClient::BridgeClient(uint8_t _h, BridgeClass &_b) : + bridge(_b), handle(_h), opened(true), buffered(0) { +} + +BridgeClient::BridgeClient(BridgeClass &_b) : + bridge(_b), handle(0), opened(false), buffered(0) { +} + +BridgeClient::~BridgeClient() { +} + +BridgeClient& BridgeClient::operator=(const BridgeClient &_x) { + opened = _x.opened; + handle = _x.handle; + return *this; +} + +void BridgeClient::stop() { + if (opened) { + uint8_t cmd[] = {'j', handle}; + bridge.transfer(cmd, 2); + } + opened = false; + buffered = 0; + readPos = 0; +} + +void BridgeClient::doBuffer() { + // If there are already char in buffer exit + if (buffered > 0) + return; + + // Try to buffer up to 32 characters + readPos = 0; + uint8_t cmd[] = {'K', handle, sizeof(buffer)}; + buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer)); +} + +int BridgeClient::available() { + // Look if there is new data available + doBuffer(); + return buffered; +} + +int BridgeClient::read() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else { + buffered--; + return buffer[readPos++]; + } +} + +int BridgeClient::read(uint8_t *buff, size_t size) { + size_t readed = 0; + do { + if (buffered == 0) { + doBuffer(); + if (buffered == 0) + return readed; + } + buff[readed++] = buffer[readPos++]; + buffered--; + } while (readed < size); + return readed; +} + +int BridgeClient::peek() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else + return buffer[readPos]; +} + +size_t BridgeClient::write(uint8_t c) { + if (!opened) + return 0; + uint8_t cmd[] = {'l', handle, c}; + bridge.transfer(cmd, 3); + return 1; +} + +size_t BridgeClient::write(const uint8_t *buf, size_t size) { + if (!opened) + return 0; + uint8_t cmd[] = {'l', handle}; + bridge.transfer(cmd, 2, buf, size, NULL, 0); + return size; +} + +void BridgeClient::flush() { +} + +uint8_t BridgeClient::connected() { + if (!opened) + return false; + // Client is "connected" if it has unread bytes + if (available()) + return true; + + uint8_t cmd[] = {'L', handle}; + uint8_t res[1]; + bridge.transfer(cmd, 2, res, 1); + return (res[0] == 1); +} + +int BridgeClient::connect(IPAddress ip, uint16_t port) { + String address; + address.reserve(18); + address += ip[0]; + address += '.'; + address += ip[1]; + address += '.'; + address += ip[2]; + address += '.'; + address += ip[3]; + return connect(address.c_str(), port); +} + +int BridgeClient::connect(const char *host, uint16_t port) { + uint8_t tmp[] = { + 'C', + static_cast(port >> 8), + static_cast(port) + }; + uint8_t res[1]; + int l = bridge.transfer(tmp, 3, (const uint8_t *)host, strlen(host), res, 1); + if (l == 0) + return 0; + handle = res[0]; + + // wait for connection + uint8_t tmp2[] = { 'c', handle }; + uint8_t res2[1]; + while (true) { + bridge.transfer(tmp2, 2, res2, 1); + if (res2[0] == 0) + break; + delay(1); + } + opened = true; + + // check for successful connection + if (connected()) + return 1; + + stop(); + handle = 0; + return 0; +} + +int BridgeClient::connectSSL(const char *host, uint16_t port) { + if (bridge.getBridgeVersion() < 161) + return -1; + + uint8_t tmp[] = { + 'Z', + static_cast(port >> 8), + static_cast(port) + }; + uint8_t res[1]; + int l = bridge.transfer(tmp, 3, (const uint8_t *)host, strlen(host), res, 1); + if (l == 0) + return 0; + handle = res[0]; + + // wait for connection + uint8_t tmp2[] = { 'c', handle }; + uint8_t res2[1]; + while (true) { + bridge.transfer(tmp2, 2, res2, 1); + if (res2[0] == 0) + break; + delay(1); + } + opened = true; + + // check for successful connection + if (connected()) + return 1; + + stop(); + handle = 0; + return 0; +} \ No newline at end of file diff --git a/libraries/Bridge/src/BridgeClient.h b/libraries/Bridge/src/BridgeClient.h new file mode 100644 index 0000000..a55ebb7 --- /dev/null +++ b/libraries/Bridge/src/BridgeClient.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _BRIDGE_CLIENT_H_ +#define _BRIDGE_CLIENT_H_ + +#include +#include + +class BridgeClient : public Client { + public: + // Constructor with a user provided BridgeClass instance + BridgeClient(uint8_t _h, BridgeClass &_b = Bridge); + BridgeClient(BridgeClass &_b = Bridge); + ~BridgeClient(); + + // Stream methods + // (read message) + virtual int available(); + virtual int read(); + virtual int read(uint8_t *buf, size_t size); + virtual int peek(); + // (write response) + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual void flush(); + // TODO: add optimized function for block write + + virtual operator bool () { + return opened; + } + + virtual BridgeClient& operator=(const BridgeClient &_x); + + virtual void stop(); + virtual uint8_t connected(); + + virtual int connect(IPAddress ip, uint16_t port); + virtual int connect(const char *host, uint16_t port); + int connectSSL(const char* host, uint16_t port); + + private: + BridgeClass &bridge; + uint8_t handle; + boolean opened; + + private: + void doBuffer(); + uint8_t buffered; + uint8_t readPos; + static const int BUFFER_SIZE = 64; + uint8_t buffer[BUFFER_SIZE]; + +}; + +#endif // _BRIDGE_CLIENT_H_ diff --git a/libraries/Bridge/src/BridgeSSLClient.cpp b/libraries/Bridge/src/BridgeSSLClient.cpp new file mode 100644 index 0000000..dd8d34b --- /dev/null +++ b/libraries/Bridge/src/BridgeSSLClient.cpp @@ -0,0 +1,36 @@ +/* + Copyright (c) 2016 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +BridgeSSLClient::BridgeSSLClient(uint8_t _h, BridgeClass &_b) : + BridgeClient(_h, _b) +{ +} + +BridgeSSLClient::BridgeSSLClient(BridgeClass &_b): + BridgeClient(_b) +{ +} + +BridgeSSLClient::~BridgeSSLClient() { +} + +int BridgeSSLClient::connect(const char *host, uint16_t port) { + return BridgeClient::connectSSL(host, port); +} \ No newline at end of file diff --git a/libraries/Bridge/src/BridgeSSLClient.h b/libraries/Bridge/src/BridgeSSLClient.h new file mode 100644 index 0000000..2f09afb --- /dev/null +++ b/libraries/Bridge/src/BridgeSSLClient.h @@ -0,0 +1,36 @@ +/* + Copyright (c) 2016 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _BRIDGE_SSL_CLIENT_H_ +#define _BRIDGE_SSL_CLIENT_H_ + +#include +#include +#include + +class BridgeSSLClient : public BridgeClient { + public: + // Constructor with a user provided BridgeClass instance + BridgeSSLClient(uint8_t _h, BridgeClass &_b = Bridge); + BridgeSSLClient(BridgeClass &_b = Bridge); + ~BridgeSSLClient(); + + virtual int connect(const char* host, uint16_t port); +}; + +#endif // _BRIDGE_SSL_CLIENT_H_ diff --git a/libraries/Bridge/src/BridgeServer.cpp b/libraries/Bridge/src/BridgeServer.cpp new file mode 100644 index 0000000..a7aa9b0 --- /dev/null +++ b/libraries/Bridge/src/BridgeServer.cpp @@ -0,0 +1,54 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include + +BridgeServer::BridgeServer(uint16_t _p, BridgeClass &_b) : + bridge(_b), port(_p), listening(false), useLocalhost(false) { +} + +void BridgeServer::begin() { + uint8_t tmp[] = { + 'N', + static_cast(port >> 8), + static_cast(port) + }; + uint8_t res[1]; + String address = F("127.0.0.1"); + if (!useLocalhost) + address = F("0.0.0.0"); + bridge.transfer(tmp, 3, (const uint8_t *)address.c_str(), address.length(), res, 1); + listening = (res[0] == 1); +} + +BridgeClient BridgeServer::accept() { + uint8_t cmd[] = {'k'}; + uint8_t res[1]; + unsigned int l = bridge.transfer(cmd, 1, res, 1); + if (l == 0) + return BridgeClient(); + return BridgeClient(res[0]); +} + +size_t BridgeServer::write(uint8_t c) { + uint8_t cmd[] = { 'b', c }; + bridge.transfer(cmd, 2); + return 1; +} + diff --git a/libraries/Bridge/src/BridgeServer.h b/libraries/Bridge/src/BridgeServer.h new file mode 100644 index 0000000..676a972 --- /dev/null +++ b/libraries/Bridge/src/BridgeServer.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _BRIDGE_SERVER_H_ +#define _BRIDGE_SERVER_H_ + +#include +#include + +class BridgeClient; + +class BridgeServer : public Server { + public: + // Constructor with a user provided BridgeClass instance + BridgeServer(uint16_t port = 5555, BridgeClass &_b = Bridge); + + void begin(); + BridgeClient accept(); + + virtual size_t write(uint8_t c); + + void listenOnLocalhost() { + useLocalhost = true; + } + void noListenOnLocalhost() { + useLocalhost = false; + } + + private: + BridgeClass &bridge; + uint16_t port; + bool listening; + bool useLocalhost; +}; + +#endif // _BRIDGE_SERVER_H_ diff --git a/libraries/Bridge/src/BridgeUdp.cpp b/libraries/Bridge/src/BridgeUdp.cpp new file mode 100644 index 0000000..ae630e3 --- /dev/null +++ b/libraries/Bridge/src/BridgeUdp.cpp @@ -0,0 +1,198 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "BridgeUdp.h" + +BridgeUDP::BridgeUDP(BridgeClass &_b) : + bridge(_b), opened(false), avail(0), buffered(0), readPos(0) { +} + +/* Start BridgeUDP socket, listening at local port PORT */ +uint8_t BridgeUDP::begin(uint16_t port) { + if (opened) + return 0; + uint8_t cmd[] = {'e', (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)}; + uint8_t res[2]; + bridge.transfer(cmd, 3, res, 2); + if (res[1] == 1) // Error... + return 0; + handle = res[0]; + opened = true; + return 1; +} + +/* Release any resources being used by this BridgeUDP instance */ +void BridgeUDP::stop() +{ + if (!opened) + return; + uint8_t cmd[] = {'q', handle}; + bridge.transfer(cmd, 2); + opened = false; +} + +int BridgeUDP::beginPacket(const char *host, uint16_t port) +{ + if (!opened) + return 0; + uint8_t cmd[] = {'E', handle, (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)}; + uint8_t res[1]; + bridge.transfer(cmd, 4, (const uint8_t *)host, strlen(host), res, 1); + return res[0]; // 1=Success, 0=Error +} + +int BridgeUDP::beginBroadcastPacket(uint16_t port) +{ + if (!opened) + return 0; + uint8_t cmd[] = {'v', handle, (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)}; + uint8_t res[1]; + bridge.transfer(cmd, 4, res, 1); + return res[0]; // 1=Success, 0=Error +} + +int BridgeUDP::beginPacket(IPAddress ip, uint16_t port) +{ + if (!opened) + return 0; + String address; + address.reserve(18); + address += ip[0]; + address += '.'; + address += ip[1]; + address += '.'; + address += ip[2]; + address += '.'; + address += ip[3]; + return beginPacket(address.c_str(), port); +} + +int BridgeUDP::endPacket() +{ + if (!opened) + return 0; + uint8_t cmd[] = {'H', handle}; + uint8_t res[1]; + bridge.transfer(cmd, 2, res, 1); + return res[0]; // 1=Success, 0=Error +} + +size_t BridgeUDP::write(const uint8_t *buffer, size_t size) +{ + if (!opened) + return 0; + uint8_t cmd[] = {'h', handle}; + uint8_t res[1]; + bridge.transfer(cmd, 2, buffer, size, res, 1); + return res[0]; // 1=Success, 0=Error +} + +int BridgeUDP::parsePacket() +{ + if (!opened) + return 0; + buffered = 0; + readPos = 0; + uint8_t cmd[] = {'Q', handle}; + uint8_t res[3]; + bridge.transfer(cmd, 2, res, 3); + if (res[0] == 0) { + // There aren't any packets available + return 0; + } + avail = (res[1] << 8) + res[2]; + return 1; +} + +void BridgeUDP::doBuffer() { + // If there are already char in buffer exit + if (buffered > 0) + return; + if (avail == 0) + return; + + // Try to buffer up to 32 characters + readPos = 0; + uint8_t cmd[] = {'u', handle, sizeof(buffer)}; + buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer)); +} + +int BridgeUDP::read() +{ + if (!opened) + return -1; + doBuffer(); + if (buffered == 0) { + return -1; // no chars available + } + buffered--; + avail--; + return buffer[readPos++]; +} + +int BridgeUDP::read(unsigned char* buff, size_t size) +{ + if (!opened) + return -1; + size_t readed = 0; + do { + if (buffered == 0) { + doBuffer(); + if (buffered == 0) + return readed; + } + buff[readed++] = buffer[readPos++]; + buffered--; + avail--; + } while (readed < size); + return readed; +} + +int BridgeUDP::peek() +{ + if (!opened) + return -1; + doBuffer(); + if (buffered == 0) + return -1; // no chars available + return buffer[readPos]; +} + +IPAddress BridgeUDP::remoteIP() +{ + if (!opened) + return -1; + uint8_t cmd[] = {'T', handle}; + uint8_t res[7]; + bridge.transfer(cmd, 2, res, 7); + if (res[0] == 0) + return IPAddress(0,0,0,0); + return IPAddress(res[1], res[2], res[3], res[4]); +} + +uint16_t BridgeUDP::remotePort() +{ + if (!opened) + return -1; + uint8_t cmd[] = {'T', handle}; + uint8_t res[7]; + bridge.transfer(cmd, 2, res, 7); + if (res[0] == 0) + return 0; + return (res[5] << 8) + res[6]; +} diff --git a/libraries/Bridge/src/BridgeUdp.h b/libraries/Bridge/src/BridgeUdp.h new file mode 100644 index 0000000..73cec54 --- /dev/null +++ b/libraries/Bridge/src/BridgeUdp.h @@ -0,0 +1,65 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include +#include "Bridge.h" + +class BridgeUDP : public UDP { + + public: + BridgeUDP(BridgeClass &_b = Bridge); + virtual uint8_t begin(uint16_t); + virtual void stop(); + + virtual int beginPacket(IPAddress ip, uint16_t port); + virtual int beginPacket(const char *host, uint16_t port); + virtual int beginBroadcastPacket(uint16_t port); + virtual int endPacket(); + virtual size_t write(uint8_t d) { return write(&d, 1); } + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + virtual int parsePacket(); + /* return number of bytes available in the current packet, + will return zero if parsePacket hasn't been called yet */ + virtual int available() { return avail; } + virtual int read(); + virtual int read(unsigned char* buffer, size_t len); + virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; + virtual int peek(); + virtual void flush() { avail = 0; } + + virtual IPAddress remoteIP(); + virtual uint16_t remotePort(); + + private: + BridgeClass &bridge; + uint8_t handle; + boolean opened; + + private: + void doBuffer(); + uint16_t avail; + uint8_t buffered; + uint8_t readPos; + static const int BUFFER_SIZE = 64; + uint8_t buffer[BUFFER_SIZE]; +}; diff --git a/libraries/Bridge/src/Console.cpp b/libraries/Bridge/src/Console.cpp new file mode 100644 index 0000000..7e8323d --- /dev/null +++ b/libraries/Bridge/src/Console.cpp @@ -0,0 +1,150 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +// Default constructor uses global Bridge instance +ConsoleClass::ConsoleClass() : + bridge(Bridge), inBuffered(0), inReadPos(0), inBuffer(NULL), + autoFlush(true) +{ + // Empty +} + +// Constructor with a user provided BridgeClass instance +ConsoleClass::ConsoleClass(BridgeClass &_b) : + bridge(_b), inBuffered(0), inReadPos(0), inBuffer(NULL), + autoFlush(true) +{ + // Empty +} + +ConsoleClass::~ConsoleClass() { + end(); +} + +size_t ConsoleClass::write(uint8_t c) { + if (autoFlush) { + uint8_t tmp[] = { 'P', c }; + bridge.transfer(tmp, 2); + } else { + outBuffer[outBuffered++] = c; + if (outBuffered == outBufferSize) + flush(); + } + return 1; +} + +size_t ConsoleClass::write(const uint8_t *buff, size_t size) { + if (autoFlush) { + uint8_t tmp[] = { 'P' }; + bridge.transfer(tmp, 1, buff, size, NULL, 0); + } else { + size_t sent = size; + while (sent > 0) { + outBuffer[outBuffered++] = *buff++; + sent--; + if (outBuffered == outBufferSize) + flush(); + } + } + return size; +} + +void ConsoleClass::flush() { + if (autoFlush) + return; + + bridge.transfer(outBuffer, outBuffered); + outBuffered = 1; +} + +void ConsoleClass::noBuffer() { + if (autoFlush) + return; + delete[] outBuffer; + autoFlush = true; +} + +void ConsoleClass::buffer(uint8_t size) { + noBuffer(); + if (size == 0) + return; + outBuffer = new uint8_t[size + 1]; + outBuffer[0] = 'P'; // WRITE tag + outBufferSize = size + 1; + outBuffered = 1; + autoFlush = false; +} + +bool ConsoleClass::connected() { + uint8_t tmp = 'a'; + bridge.transfer(&tmp, 1, &tmp, 1); + return tmp == 1; +} + +int ConsoleClass::available() { + // Look if there is new data available + doBuffer(); + return inBuffered; +} + +int ConsoleClass::read() { + doBuffer(); + if (inBuffered == 0) + return -1; // no chars available + else { + inBuffered--; + return inBuffer[inReadPos++]; + } +} + +int ConsoleClass::peek() { + doBuffer(); + if (inBuffered == 0) + return -1; // no chars available + else + return inBuffer[inReadPos]; +} + +void ConsoleClass::doBuffer() { + // If there are already char in buffer exit + if (inBuffered > 0) + return; + + // Try to buffer up to 32 characters + inReadPos = 0; + uint8_t tmp[] = { 'p', BUFFER_SIZE }; + inBuffered = bridge.transfer(tmp, 2, inBuffer, BUFFER_SIZE); +} + +void ConsoleClass::begin() { + bridge.begin(); + end(); + inBuffer = new uint8_t[BUFFER_SIZE]; +} + +void ConsoleClass::end() { + noBuffer(); + if (inBuffer) { + delete[] inBuffer; + inBuffer = NULL; + } +} + +ConsoleClass Console; diff --git a/libraries/Bridge/src/Console.h b/libraries/Bridge/src/Console.h new file mode 100644 index 0000000..ca05b08 --- /dev/null +++ b/libraries/Bridge/src/Console.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef CONSOLE_H_ +#define CONSOLE_H_ + +#include + +class ConsoleClass : public Stream { + public: + // Default constructor uses global Bridge instance + ConsoleClass(); + // Constructor with a user provided BridgeClass instance + ConsoleClass(BridgeClass &_b); + ~ConsoleClass(); + + void begin(); + void end(); + + void buffer(uint8_t size); + void noBuffer(); + + bool connected(); + + // Stream methods + // (read from console socket) + int available(); + int read(); + int peek(); + // (write to console socket) + size_t write(uint8_t); + size_t write(const uint8_t *buffer, size_t size); + void flush(); + + operator bool () { + return connected(); + } + + private: + BridgeClass &bridge; + + void doBuffer(); + uint8_t inBuffered; + uint8_t inReadPos; + static const int BUFFER_SIZE = 32; + uint8_t *inBuffer; + + bool autoFlush; + uint8_t outBuffered; + uint8_t outBufferSize; + uint8_t *outBuffer; +}; + +extern ConsoleClass Console; + +#endif diff --git a/libraries/Bridge/src/FileIO.cpp b/libraries/Bridge/src/FileIO.cpp new file mode 100644 index 0000000..e24a567 --- /dev/null +++ b/libraries/Bridge/src/FileIO.cpp @@ -0,0 +1,283 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +namespace BridgeLib { + +File::File(BridgeClass &b) : bridge(b), mode(255) { + // Empty +} + +File::File(const char *_filename, uint8_t _mode, BridgeClass &b) : bridge(b), mode(_mode) { + filename = _filename; + uint8_t modes[] = {'r', 'w', 'a'}; + uint8_t cmd[] = {'F', modes[mode]}; + uint8_t res[2]; + dirPosition = 1; + bridge.transfer(cmd, 2, (uint8_t*)filename.c_str(), filename.length(), res, 2); + if (res[0] != 0) { // res[0] contains error code + mode = 255; // In case of error keep the file closed + return; + } + handle = res[1]; + buffered = 0; +} + +File::operator bool() { + return (mode != 255); +} + +File::~File() { + close(); +} + +size_t File::write(uint8_t c) { + return write(&c, 1); +} + +size_t File::write(const uint8_t *buf, size_t size) { + if (mode == 255) + return -1; + uint8_t cmd[] = {'g', handle}; + uint8_t res[1]; + bridge.transfer(cmd, 2, buf, size, res, 1); + if (res[0] != 0) // res[0] contains error code + return -res[0]; + return size; +} + +int File::read() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else { + buffered--; + return buffer[readPos++]; + } +} + +int File::peek() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else + return buffer[readPos]; +} + +boolean File::seek(uint32_t position) { + uint8_t cmd[] = { + 's', + handle, + static_cast(position >> 24), + static_cast(position >> 16), + static_cast(position >> 8), + static_cast(position) + }; + uint8_t res[1]; + bridge.transfer(cmd, 6, res, 1); + if (res[0] == 0) { + // If seek succeed then flush buffers + buffered = 0; + return true; + } + return false; +} + +uint32_t File::position() { + uint8_t cmd[] = {'S', handle}; + uint8_t res[5]; + bridge.transfer(cmd, 2, res, 5); + //err = res[0]; // res[0] contains error code + uint32_t pos; + pos = static_cast(res[1]) << 24; + pos += static_cast(res[2]) << 16; + pos += static_cast(res[3]) << 8; + pos += static_cast(res[4]); + return pos - buffered; +} + +void File::doBuffer() { + // If there are already char in buffer exit + if (buffered > 0) + return; + + // Try to buffer up to BUFFER_SIZE characters + readPos = 0; + uint8_t cmd[] = {'G', handle, BUFFER_SIZE - 1}; + uint16_t readed = bridge.transfer(cmd, 3, buffer, BUFFER_SIZE); + //err = buff[0]; // First byte is error code + if (readed == BridgeClass::TRANSFER_TIMEOUT || readed == 0) { + // transfer failed to retrieve any data + buffered = 0; + } else { + // transfer retrieved at least one byte of data so skip the error code character + readPos++; + buffered = readed - 1; + } +} + +int File::available() { + // Look if there is new data available + doBuffer(); + return buffered; +} + +void File::flush() { +} + +int File::read(void *buff, uint16_t nbyte) { + uint16_t n = 0; + uint8_t *p = reinterpret_cast(buff); + while (n < nbyte) { + if (buffered == 0) { + doBuffer(); + if (buffered == 0) + break; + } + *p++ = buffer[readPos++]; + buffered--; + n++; + } + return n; +} + +uint32_t File::size() { + if (bridge.getBridgeVersion() < 101) + return 0; + uint8_t cmd[] = {'t', handle}; + uint8_t buff[5]; + bridge.transfer(cmd, 2, buff, 5); + //err = res[0]; // First byte is error code + uint32_t res; + res = ((uint32_t)buff[1]) << 24; + res |= ((uint32_t)buff[2]) << 16; + res |= ((uint32_t)buff[3]) << 8; + res |= ((uint32_t)buff[4]); + return res; +} + +void File::close() { + if (mode == 255) + return; + uint8_t cmd[] = {'f', handle}; + uint8_t ret[1]; + bridge.transfer(cmd, 2, ret, 1); + mode = 255; +} + +const char *File::name() { + return filename.c_str(); +} + + +boolean File::isDirectory() { + uint8_t res[1]; + uint8_t cmd[] = {'i'}; + if (mode != 255) + return 0; + + bridge.transfer(cmd, 1, (uint8_t *)filename.c_str(), filename.length(), res, 1); + return res[0]; +} + + +File File::openNextFile(uint8_t mode) { + Process awk; + char tmp; + String command; + String filepath; + if (dirPosition == 0xFFFF) return File(); + + command = "ls "; + command += filename; + command += " | awk 'NR=="; + command += dirPosition; + command += "'"; + + awk.runShellCommand(command); + + while (awk.running()); + + command = ""; + + while (awk.available()) { + tmp = awk.read(); + if (tmp != '\n') command += tmp; + } + if (command.length() == 0) + return File(); + dirPosition++; + filepath = filename + "/" + command; + return File(filepath.c_str(), mode); + +} + +void File::rewindDirectory(void) { + dirPosition = 1; +} + + + + + + +boolean FileSystemClass::begin() { + return true; +} + +File FileSystemClass::open(const char *filename, uint8_t mode) { + return File(filename, mode); +} + +boolean FileSystemClass::exists(const char *filepath) { + Process ls; + ls.begin("ls"); + ls.addParameter(filepath); + int res = ls.run(); + return (res == 0); +} + +boolean FileSystemClass::mkdir(const char *filepath) { + Process mk; + mk.begin("mkdir"); + mk.addParameter("-p"); + mk.addParameter(filepath); + int res = mk.run(); + return (res == 0); +} + +boolean FileSystemClass::remove(const char *filepath) { + Process rm; + rm.begin("rm"); + rm.addParameter(filepath); + int res = rm.run(); + return (res == 0); +} + +boolean FileSystemClass::rmdir(const char *filepath) { + Process rm; + rm.begin("rmdir"); + rm.addParameter(filepath); + int res = rm.run(); + return (res == 0); +} + +FileSystemClass FileSystem; + +} diff --git a/libraries/Bridge/src/FileIO.h b/libraries/Bridge/src/FileIO.h new file mode 100644 index 0000000..c5a8e9e --- /dev/null +++ b/libraries/Bridge/src/FileIO.h @@ -0,0 +1,120 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __FILEIO_H__ +#define __FILEIO_H__ + +#include + +#define FILE_READ 0 +#define FILE_WRITE 1 +#define FILE_APPEND 2 + +namespace BridgeLib { + +class File : public Stream { + + public: + File(BridgeClass &b = Bridge); + File(const char *_filename, uint8_t _mode, BridgeClass &b = Bridge); + ~File(); + + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int read(); + virtual int peek(); + virtual int available(); + virtual void flush(); + int read(void *buf, uint16_t nbyte); + boolean seek(uint32_t pos); + uint32_t position(); + uint32_t size(); + void close(); + operator bool(); + const char * name(); + boolean isDirectory(); + File openNextFile(uint8_t mode = FILE_READ); + void rewindDirectory(void); + + //using Print::write; + + private: + void doBuffer(); + uint8_t buffered; + uint8_t readPos; + uint16_t dirPosition; + static const int BUFFER_SIZE = 64; + uint8_t buffer[BUFFER_SIZE]; + + + private: + BridgeClass &bridge; + String filename; + uint8_t mode; + uint8_t handle; + +}; + +class FileSystemClass { + public: + FileSystemClass() : bridge(Bridge) { } + FileSystemClass(BridgeClass &_b) : bridge(_b) { } + + boolean begin(); + + // Open the specified file/directory with the supplied mode (e.g. read or + // write, etc). Returns a File object for interacting with the file. + // Note that currently only one file can be open at a time. + File open(const char *filename, uint8_t mode = FILE_READ); + + // Methods to determine if the requested file path exists. + boolean exists(const char *filepath); + + // Create the requested directory hierarchy--if intermediate directories + // do not exist they will be created. + boolean mkdir(const char *filepath); + + // Delete the file. + boolean remove(const char *filepath); + + boolean rmdir(const char *filepath); + + private: + friend class File; + + BridgeClass &bridge; +}; + +extern FileSystemClass FileSystem; + +}; + +// We enclose File and FileSystem classes in namespace BridgeLib to avoid +// conflicts with legacy SD library. + +// This ensure compatibility with older sketches that uses only Bridge lib +// (the user can still use File instead of BridgeFile) +using namespace BridgeLib; + +// This allows sketches to use BridgeLib::File together with SD library +// (you must use BridgeFile instead of File when needed to disambiguate) +typedef BridgeLib::File BridgeFile; +typedef BridgeLib::FileSystemClass BridgeFileSystemClass; +#define BridgeFileSystem BridgeLib::FileSystem + +#endif diff --git a/libraries/Bridge/src/HttpClient.cpp b/libraries/Bridge/src/HttpClient.cpp new file mode 100644 index 0000000..ee1629c --- /dev/null +++ b/libraries/Bridge/src/HttpClient.cpp @@ -0,0 +1,204 @@ +/* + Copyright (c) 2013-2014 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "HttpClient.h" + +HttpClient::HttpClient() : + insecure(false) { + // Empty +} + +unsigned int HttpClient::get(String &url) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addHeader(); + addParameter(url); + return run(); +} + +unsigned int HttpClient::get(const char *url) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addHeader(); + addParameter(url); + return run(); +} + +void HttpClient::getAsynchronously(String &url) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addHeader(); + addParameter(url); + runAsynchronously(); +} + +void HttpClient::getAsynchronously(const char *url) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addHeader(); + addParameter(url); + runAsynchronously(); +} + +unsigned int HttpClient::post(String &url, String &data) { + return post(url.c_str(), data.c_str()); +} + +unsigned int HttpClient::post(const char *url, const char *data) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addParameter("--request"); + addParameter("POST"); + addParameter("--data"); + addParameter(data); + addHeader(); + addParameter(url); + return run(); +} + +void HttpClient::postAsynchronously(String &url, String &data) { + postAsynchronously(url.c_str(), data.c_str()); +} + +void HttpClient::postAsynchronously(const char *url, const char *data) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addParameter("--request"); + addParameter("POST"); + addParameter("--data"); + addParameter(data); + addHeader(); + addParameter(url); + runAsynchronously(); +} + +unsigned int HttpClient::patch(String &url, String &data) { + return patch(url.c_str(), data.c_str()); +} + +unsigned int HttpClient::patch(const char *url, const char *data) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addParameter("--request"); + addParameter("PATCH"); + addParameter("--data"); + addParameter(data); + addHeader(); + addParameter(url); + return run(); +} + +void HttpClient::patchAsynchronously(String &url, String &data) { + patchAsynchronously(url.c_str(), data.c_str()); +} + +void HttpClient::patchAsynchronously(const char *url, const char *data) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addParameter("--request"); + addParameter("PATCH"); + addParameter("--data"); + addParameter(data); + addHeader(); + addParameter(url); + runAsynchronously(); +} + +unsigned int HttpClient::put(String &url, String &data) { + return put(url.c_str(), data.c_str()); +} + +unsigned int HttpClient::put(const char *url, const char *data) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addParameter("--request"); + addParameter("PUT"); + addParameter("--data"); + addParameter(data); + addHeader(); + addParameter(url); + return run(); +} + +void HttpClient::putAsynchronously(String &url, String &data) { + putAsynchronously(url.c_str(), data.c_str()); +} + +void HttpClient::putAsynchronously(const char *url, const char *data) { + begin("curl"); + if (insecure) { + addParameter("-k"); + } + addParameter("--request"); + addParameter("PUT"); + addParameter("--data"); + addParameter(data); + addHeader(); + addParameter(url); + runAsynchronously(); +} + +boolean HttpClient::ready() { + return !running(); +} + +unsigned int HttpClient::getResult() { + return exitValue(); +} + +void HttpClient::noCheckSSL() { + insecure = true; +} + +void HttpClient::checkSSL() { + insecure = false; +} + +void HttpClient::setHeader(String &header) { + this->header = header; +} + +void HttpClient::setHeader(const char * header) { + this->header = String(header); +} + +void HttpClient::addHeader() { + if (header.length() > 0) { + addParameter("--header"); + addParameter(header); + } +} + diff --git a/libraries/Bridge/src/HttpClient.h b/libraries/Bridge/src/HttpClient.h new file mode 100644 index 0000000..a6e3c77 --- /dev/null +++ b/libraries/Bridge/src/HttpClient.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2013-2014 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef HTTPCLIENT_H_ +#define HTTPCLIENT_H_ + +#include + +class HttpClient : public Process { + public: + HttpClient(); + + unsigned int get(String &url); + unsigned int get(const char * url); + void getAsynchronously(String &url); + void getAsynchronously(const char * url); + unsigned int post(String &url, String &data); + unsigned int post(const char * url, const char * data); + void postAsynchronously(String &url, String &data); + void postAsynchronously(const char * url, const char * data); + unsigned int patch(String &url, String &data); + unsigned int patch(const char * url, const char * data); + void patchAsynchronously(String &url, String &data); + void patchAsynchronously(const char * url, const char * data); + unsigned int put(String &url, String &data); + unsigned int put(const char * url, const char * data); + void putAsynchronously(String &url, String &data); + void putAsynchronously(const char * url, const char * data); + void setHeader(String &header); + void setHeader(const char * header); + boolean ready(); + unsigned int getResult(); + void noCheckSSL(); + void checkSSL(); + + private: + boolean insecure; + + private: + void addHeader(); + String header; +}; + +#endif /* HTTPCLIENT_H_ */ diff --git a/libraries/Bridge/src/Mailbox.cpp b/libraries/Bridge/src/Mailbox.cpp new file mode 100644 index 0000000..0c571f7 --- /dev/null +++ b/libraries/Bridge/src/Mailbox.cpp @@ -0,0 +1,56 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +unsigned int MailboxClass::readMessage(uint8_t *buff, unsigned int size) { + uint8_t tmp[] = { 'm' }; + return bridge.transfer(tmp, 1, buff, size); +} + +void MailboxClass::readMessage(String &str, unsigned int maxLength) { + uint8_t tmp[] = { 'm' }; + // XXX: Is there a better way to create the string? + uint8_t buff[maxLength + 1]; + int l = bridge.transfer(tmp, 1, buff, maxLength); + buff[l] = 0; + str = (const char *)buff; +} + +void MailboxClass::writeMessage(const uint8_t *buff, unsigned int size) { + uint8_t cmd[] = {'M'}; + bridge.transfer(cmd, 1, buff, size, NULL, 0); +} + +void MailboxClass::writeMessage(const String& str) { + writeMessage((uint8_t*) str.c_str(), str.length()); +} + +void MailboxClass::writeJSON(const String& str) { + uint8_t cmd[] = {'J'}; + bridge.transfer(cmd, 1, (uint8_t*) str.c_str(), str.length(), NULL, 0); +} + +unsigned int MailboxClass::messageAvailable() { + uint8_t tmp[] = {'n'}; + uint8_t res[2]; + bridge.transfer(tmp, 1, res, 2); + return (res[0] << 8) + res[1]; +} + +MailboxClass Mailbox(Bridge); diff --git a/libraries/Bridge/src/Mailbox.h b/libraries/Bridge/src/Mailbox.h new file mode 100644 index 0000000..b2e3833 --- /dev/null +++ b/libraries/Bridge/src/Mailbox.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _MAILBOX_CLASS_H_INCLUDED_ +#define _MAILBOX_CLASS_H_INCLUDED_ + +#include + +class MailboxClass { + public: + MailboxClass(BridgeClass &b = Bridge) : bridge(b) { } + + void begin() { } + void end() { } + + // Receive a message and store it inside a buffer + unsigned int readMessage(uint8_t *buffer, unsigned int size); + // Receive a message and store it inside a String + void readMessage(String &str, unsigned int maxLength = 128); + + // Send a message + void writeMessage(const uint8_t *buffer, unsigned int size); + // Send a message + void writeMessage(const String& str); + // Send a JSON message + void writeJSON(const String& str); + + // Return the size of the next available message, 0 if there are + // no messages in queue. + unsigned int messageAvailable(); + + private: + BridgeClass &bridge; +}; + +extern MailboxClass Mailbox; + +#endif // _MAILBOX_CLASS_H_INCLUDED_ diff --git a/libraries/Bridge/src/Process.cpp b/libraries/Bridge/src/Process.cpp new file mode 100644 index 0000000..987f0b8 --- /dev/null +++ b/libraries/Bridge/src/Process.cpp @@ -0,0 +1,142 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +Process::~Process() { + close(); +} + +size_t Process::write(uint8_t c) { + uint8_t cmd[] = {'I', handle, c}; + bridge.transfer(cmd, 3); + return 1; +} + +void Process::flush() { +} + +int Process::available() { + // Look if there is new data available + doBuffer(); + return buffered; +} + +int Process::read() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else { + buffered--; + return buffer[readPos++]; + } +} + +int Process::peek() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else + return buffer[readPos]; +} + +void Process::doBuffer() { + // If there are already char in buffer exit + if (buffered > 0) + return; + + // Try to buffer up to 32 characters + readPos = 0; + uint8_t cmd[] = {'O', handle, sizeof(buffer)}; + buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer)); +} + +void Process::begin(const String &command) { + close(); + cmdline = new String(command); +} + +void Process::addParameter(const String ¶m) { + *cmdline += "\xFE"; + *cmdline += param; +} + +void Process::runAsynchronously() { + uint8_t cmd[] = {'R'}; + uint8_t res[2]; + bridge.transfer(cmd, 1, (uint8_t*)cmdline->c_str(), cmdline->length(), res, 2); + handle = res[1]; + + delete cmdline; + cmdline = NULL; + + if (res[0] == 0) // res[0] contains error code + started = true; +} + +boolean Process::running() { + uint8_t cmd[] = {'r', handle}; + uint8_t res[1]; + bridge.transfer(cmd, 2, res, 1); + return (res[0] == 1); +} + +unsigned int Process::exitValue() { + uint8_t cmd[] = {'W', handle}; + uint8_t res[2]; + bridge.transfer(cmd, 2, res, 2); + return (res[0] << 8) + res[1]; +} + +unsigned int Process::run() { + runAsynchronously(); + while (running()) + delay(100); + return exitValue(); +} + +void Process::close() { + if (started) { + uint8_t cmd[] = {'w', handle}; + bridge.transfer(cmd, 2); + } + started = false; +} + +unsigned int Process::runShellCommand(const String &command) { + runShellCommandAsynchronously(command); + while (running()) + delay(100); + return exitValue(); +} + +void Process::runShellCommandAsynchronously(const String &command) { + begin("/bin/ash"); + addParameter("-c"); + addParameter(command); + runAsynchronously(); +} + +// This method is currently unused +//static unsigned int __commandOutputAvailable(uint8_t handle) { +// uint8_t cmd[] = {'o', handle}; +// uint8_t res[1]; +// Bridge.transfer(cmd, 2, res, 1); +// return res[0]; +//} + diff --git a/libraries/Bridge/src/Process.h b/libraries/Bridge/src/Process.h new file mode 100644 index 0000000..7002764 --- /dev/null +++ b/libraries/Bridge/src/Process.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef PROCESS_H_ +#define PROCESS_H_ + +#include + +class Process : public Stream { + public: + // Constructor with a user provided BridgeClass instance + Process(BridgeClass &_b = Bridge) : + bridge(_b), started(false), buffered(0), readPos(0) { } + ~Process(); + + void begin(const String &command); + void addParameter(const String ¶m); + unsigned int run(); + void runAsynchronously(); + boolean running(); + unsigned int exitValue(); + void close(); + + unsigned int runShellCommand(const String &command); + void runShellCommandAsynchronously(const String &command); + + operator bool () { + return started; + } + + // Stream methods + // (read from process stdout) + int available(); + int read(); + int peek(); + // (write to process stdin) + size_t write(uint8_t); + void flush(); + // TODO: add optimized function for block write + + private: + BridgeClass &bridge; + uint8_t handle; + String *cmdline; + boolean started; + + private: + void doBuffer(); + uint8_t buffered; + uint8_t readPos; + static const int BUFFER_SIZE = 64; + uint8_t buffer[BUFFER_SIZE]; + +}; + +#endif diff --git a/libraries/Bridge/src/YunClient.h b/libraries/Bridge/src/YunClient.h new file mode 100644 index 0000000..faff247 --- /dev/null +++ b/libraries/Bridge/src/YunClient.h @@ -0,0 +1,27 @@ +/* + Copyright (c) 2014 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _YUN_CLIENT_H_ +#define _YUN_CLIENT_H_ + +#include + +#warning "The use of YunClient is deprecated. Use BridgeClient instead!" +typedef BridgeClient YunClient; + +#endif // _YUN_CLIENT_H_ diff --git a/libraries/Bridge/src/YunServer.h b/libraries/Bridge/src/YunServer.h new file mode 100644 index 0000000..95d05cd --- /dev/null +++ b/libraries/Bridge/src/YunServer.h @@ -0,0 +1,27 @@ +/* + Copyright (c) 2014 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _YUN_SERVER_H_ +#define _YUN_SERVER_H_ + +#include + +#warning "The use of YunServer is deprecated. Use BridgeServer instead!" +typedef BridgeServer YunServer; + +#endif // _YUN_SERVER_H_ diff --git a/libraries/DHT-sensor-library-master/DHT.cpp b/libraries/DHT-sensor-library-master/DHT.cpp new file mode 100644 index 0000000..86ad91c --- /dev/null +++ b/libraries/DHT-sensor-library-master/DHT.cpp @@ -0,0 +1,259 @@ +/* DHT library + +MIT license +written by Adafruit Industries +*/ + +#include "DHT.h" + +#define MIN_INTERVAL 2000 + +DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) { + _pin = pin; + _type = type; + #ifdef __AVR + _bit = digitalPinToBitMask(pin); + _port = digitalPinToPort(pin); + #endif + _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for + // reading pulses from DHT sensor. + // Note that count is now ignored as the DHT reading algorithm adjusts itself + // basd on the speed of the processor. +} + +void DHT::begin(void) { + // set up the pins! + pinMode(_pin, INPUT_PULLUP); + // Using this value makes sure that millis() - lastreadtime will be + // >= MIN_INTERVAL right away. Note that this assignment wraps around, + // but so will the subtraction. + _lastreadtime = -MIN_INTERVAL; + DEBUG_PRINT("Max clock cycles: "); DEBUG_PRINTLN(_maxcycles, DEC); +} + +//boolean S == Scale. True == Fahrenheit; False == Celcius +float DHT::readTemperature(bool S, bool force) { + float f = NAN; + + if (read(force)) { + switch (_type) { + case DHT11: + f = data[2]; + if(S) { + f = convertCtoF(f); + } + break; + case DHT22: + case DHT21: + f = data[2] & 0x7F; + f *= 256; + f += data[3]; + f *= 0.1; + if (data[2] & 0x80) { + f *= -1; + } + if(S) { + f = convertCtoF(f); + } + break; + } + } + return f; +} + +float DHT::convertCtoF(float c) { + return c * 1.8 + 32; +} + +float DHT::convertFtoC(float f) { + return (f - 32) * 0.55555; +} + +float DHT::readHumidity(bool force) { + float f = NAN; + if (read()) { + switch (_type) { + case DHT11: + f = data[0]; + break; + case DHT22: + case DHT21: + f = data[0]; + f *= 256; + f += data[1]; + f *= 0.1; + break; + } + } + return f; +} + +//boolean isFahrenheit: True == Fahrenheit; False == Celcius +float DHT::computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit) { + // Using both Rothfusz and Steadman's equations + // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml + float hi; + + if (!isFahrenheit) + temperature = convertCtoF(temperature); + + hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (percentHumidity * 0.094)); + + if (hi > 79) { + hi = -42.379 + + 2.04901523 * temperature + + 10.14333127 * percentHumidity + + -0.22475541 * temperature*percentHumidity + + -0.00683783 * pow(temperature, 2) + + -0.05481717 * pow(percentHumidity, 2) + + 0.00122874 * pow(temperature, 2) * percentHumidity + + 0.00085282 * temperature*pow(percentHumidity, 2) + + -0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2); + + if((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0)) + hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882); + + else if((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0)) + hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2); + } + + return isFahrenheit ? hi : convertFtoC(hi); +} + +boolean DHT::read(bool force) { + // Check if sensor was read less than two seconds ago and return early + // to use last reading. + uint32_t currenttime = millis(); + if (!force && ((currenttime - _lastreadtime) < 2000)) { + return _lastresult; // return last correct measurement + } + _lastreadtime = currenttime; + + // Reset 40 bits of received data to zero. + data[0] = data[1] = data[2] = data[3] = data[4] = 0; + + // Send start signal. See DHT datasheet for full signal diagram: + // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf + + // Go into high impedence state to let pull-up raise data line level and + // start the reading process. + digitalWrite(_pin, HIGH); + delay(250); + + // First set data line low for 20 milliseconds. + pinMode(_pin, OUTPUT); + digitalWrite(_pin, LOW); + delay(20); + + uint32_t cycles[80]; + { + // Turn off interrupts temporarily because the next sections are timing critical + // and we don't want any interruptions. + InterruptLock lock; + + // End the start signal by setting data line high for 40 microseconds. + digitalWrite(_pin, HIGH); + delayMicroseconds(40); + + // Now start reading the data line to get the value from the DHT sensor. + pinMode(_pin, INPUT_PULLUP); + delayMicroseconds(10); // Delay a bit to let sensor pull data line low. + + // First expect a low signal for ~80 microseconds followed by a high signal + // for ~80 microseconds again. + if (expectPulse(LOW) == 0) { + DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse.")); + _lastresult = false; + return _lastresult; + } + if (expectPulse(HIGH) == 0) { + DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse.")); + _lastresult = false; + return _lastresult; + } + + // Now read the 40 bits sent by the sensor. Each bit is sent as a 50 + // microsecond low pulse followed by a variable length high pulse. If the + // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds + // then it's a 1. We measure the cycle count of the initial 50us low pulse + // and use that to compare to the cycle count of the high pulse to determine + // if the bit is a 0 (high state cycle count < low state cycle count), or a + // 1 (high state cycle count > low state cycle count). Note that for speed all + // the pulses are read into a array and then examined in a later step. + for (int i=0; i<80; i+=2) { + cycles[i] = expectPulse(LOW); + cycles[i+1] = expectPulse(HIGH); + } + } // Timing critical code is now complete. + + // Inspect pulses and determine which ones are 0 (high state cycle count < low + // state cycle count), or 1 (high state cycle count > low state cycle count). + for (int i=0; i<40; ++i) { + uint32_t lowCycles = cycles[2*i]; + uint32_t highCycles = cycles[2*i+1]; + if ((lowCycles == 0) || (highCycles == 0)) { + DEBUG_PRINTLN(F("Timeout waiting for pulse.")); + _lastresult = false; + return _lastresult; + } + data[i/8] <<= 1; + // Now compare the low and high cycle times to see if the bit is a 0 or 1. + if (highCycles > lowCycles) { + // High cycles are greater than 50us low cycle count, must be a 1. + data[i/8] |= 1; + } + // Else high cycles are less than (or equal to, a weird case) the 50us low + // cycle count so this must be a zero. Nothing needs to be changed in the + // stored data. + } + + DEBUG_PRINTLN(F("Received:")); + DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? ")); + DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX); + + // Check we read 40 bits and that the checksum matches. + if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { + _lastresult = true; + return _lastresult; + } + else { + DEBUG_PRINTLN(F("Checksum failure!")); + _lastresult = false; + return _lastresult; + } +} + +// Expect the signal line to be at the specified level for a period of time and +// return a count of loop cycles spent at that level (this cycle count can be +// used to compare the relative time of two pulses). If more than a millisecond +// ellapses without the level changing then the call fails with a 0 response. +// This is adapted from Arduino's pulseInLong function (which is only available +// in the very latest IDE versions): +// https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c +uint32_t DHT::expectPulse(bool level) { + uint32_t count = 0; + // On AVR platforms use direct GPIO port access as it's much faster and better + // for catching pulses that are 10's of microseconds in length: + #ifdef __AVR + uint8_t portState = level ? _bit : 0; + while ((*portInputRegister(_port) & _bit) == portState) { + if (count++ >= _maxcycles) { + return 0; // Exceeded timeout, fail. + } + } + // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266 + // right now, perhaps bugs in direct port access functions?). + #else + while (digitalRead(_pin) == level) { + if (count++ >= _maxcycles) { + return 0; // Exceeded timeout, fail. + } + } + #endif + + return count; +} diff --git a/libraries/DHT-sensor-library-master/DHT.h b/libraries/DHT-sensor-library-master/DHT.h new file mode 100644 index 0000000..d81f6db --- /dev/null +++ b/libraries/DHT-sensor-library-master/DHT.h @@ -0,0 +1,75 @@ +/* DHT library + +MIT license +written by Adafruit Industries +*/ +#ifndef DHT_H +#define DHT_H + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + + +// Uncomment to enable printing out nice debug messages. +//#define DHT_DEBUG + +// Define where debug output will be printed. +#define DEBUG_PRINTER Serial + +// Setup debug printing macros. +#ifdef DHT_DEBUG + #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); } + #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); } +#else + #define DEBUG_PRINT(...) {} + #define DEBUG_PRINTLN(...) {} +#endif + +// Define types of sensors. +#define DHT11 11 +#define DHT22 22 +#define DHT21 21 +#define AM2301 21 + + +class DHT { + public: + DHT(uint8_t pin, uint8_t type, uint8_t count=6); + void begin(void); + float readTemperature(bool S=false, bool force=false); + float convertCtoF(float); + float convertFtoC(float); + float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=true); + float readHumidity(bool force=false); + boolean read(bool force=false); + + private: + uint8_t data[5]; + uint8_t _pin, _type; + #ifdef __AVR + // Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask + // for the digital pin connected to the DHT. Other platforms will use digitalRead. + uint8_t _bit, _port; + #endif + uint32_t _lastreadtime, _maxcycles; + bool _lastresult; + + uint32_t expectPulse(bool level); + +}; + +class InterruptLock { + public: + InterruptLock() { + noInterrupts(); + } + ~InterruptLock() { + interrupts(); + } + +}; + +#endif diff --git a/libraries/DHT-sensor-library-master/README.md b/libraries/DHT-sensor-library-master/README.md new file mode 100644 index 0000000..8bd49ff --- /dev/null +++ b/libraries/DHT-sensor-library-master/README.md @@ -0,0 +1,5 @@ +This is an Arduino library for the DHT series of low cost temperature/humidity sensors. + +Tutorial: https://learn.adafruit.com/dht + +To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder DHT. Check that the DHT folder contains DHT.cpp and DHT.h. Place the DHT library folder your /libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE. diff --git a/libraries/DHT-sensor-library-master/examples/DHTtester/DHTtester.ino b/libraries/DHT-sensor-library-master/examples/DHTtester/DHTtester.ino new file mode 100644 index 0000000..ae6c41a --- /dev/null +++ b/libraries/DHT-sensor-library-master/examples/DHTtester/DHTtester.ino @@ -0,0 +1,69 @@ +// Example testing sketch for various DHT humidity/temperature sensors +// Written by ladyada, public domain + +#include "DHT.h" + +#define DHTPIN 2 // what digital pin we're connected to + +// Uncomment whatever type you're using! +//#define DHTTYPE DHT11 // DHT 11 +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 +//#define DHTTYPE DHT21 // DHT 21 (AM2301) + +// Connect pin 1 (on the left) of the sensor to +5V +// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 +// to 3.3V instead of 5V! +// Connect pin 2 of the sensor to whatever your DHTPIN is +// Connect pin 4 (on the right) of the sensor to GROUND +// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor + +// Initialize DHT sensor. +// Note that older versions of this library took an optional third parameter to +// tweak the timings for faster processors. This parameter is no longer needed +// as the current DHT reading algorithm adjusts itself to work on faster procs. +DHT dht(DHTPIN, DHTTYPE); + +void setup() { + Serial.begin(9600); + Serial.println("DHTxx test!"); + + dht.begin(); +} + +void loop() { + // Wait a few seconds between measurements. + delay(2000); + + // Reading temperature or humidity takes about 250 milliseconds! + // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) + float h = dht.readHumidity(); + // Read temperature as Celsius (the default) + float t = dht.readTemperature(); + // Read temperature as Fahrenheit (isFahrenheit = true) + float f = dht.readTemperature(true); + + // Check if any reads failed and exit early (to try again). + if (isnan(h) || isnan(t) || isnan(f)) { + Serial.println("Failed to read from DHT sensor!"); + return; + } + + // Compute heat index in Fahrenheit (the default) + float hif = dht.computeHeatIndex(f, h); + // Compute heat index in Celsius (isFahreheit = false) + float hic = dht.computeHeatIndex(t, h, false); + + Serial.print("Humidity: "); + Serial.print(h); + Serial.print(" %\t"); + Serial.print("Temperature: "); + Serial.print(t); + Serial.print(" *C "); + Serial.print(f); + Serial.print(" *F\t"); + Serial.print("Heat index: "); + Serial.print(hic); + Serial.print(" *C "); + Serial.print(hif); + Serial.println(" *F"); +} diff --git a/libraries/DHT-sensor-library-master/keywords.txt b/libraries/DHT-sensor-library-master/keywords.txt new file mode 100644 index 0000000..146d4fa --- /dev/null +++ b/libraries/DHT-sensor-library-master/keywords.txt @@ -0,0 +1,22 @@ +########################################### +# Syntax Coloring Map For DHT-sensor-library +########################################### + +########################################### +# Datatypes (KEYWORD1) +########################################### + +DHT KEYWORD1 + +########################################### +# Methods and Functions (KEYWORD2) +########################################### + +begin KEYWORD2 +readTemperature KEYWORD2 +convertCtoF KEYWORD2 +convertFtoC KEYWORD2 +computeHeatIndex KEYWORD2 +readHumidity KEYWORD2 +read KEYWORD2 + diff --git a/libraries/DHT-sensor-library-master/library.properties b/libraries/DHT-sensor-library-master/library.properties new file mode 100644 index 0000000..c85a332 --- /dev/null +++ b/libraries/DHT-sensor-library-master/library.properties @@ -0,0 +1,9 @@ +name=DHT sensor library +version=1.2.3 +author=Adafruit +maintainer=Adafruit +sentence=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors +paragraph=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors +category=Sensors +url=https://github.com/adafruit/DHT-sensor-library +architectures=* diff --git a/libraries/Mitov/Mitov.h b/libraries/Mitov/Mitov.h new file mode 100644 index 0000000..a2df24f --- /dev/null +++ b/libraries/Mitov/Mitov.h @@ -0,0 +1,1572 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_h +#define _MITOV_h + +#include + +#if defined( VISUINO_TEENSY_3_0 ) || defined( VISUINO_TEENSY_3_1 ) || defined( VISUINO_TEENSY_LC ) + #define VISUINO_TEENSY +#endif + +#if defined( VISUINO_ARDUINO_DUE ) || defined( VISUINO_LINKIT_ONE ) || defined( VISUINO_TEENSY ) || defined( VISUINO_TEENSY_2_0 ) || defined( VISUINO_TEENSY_2_0_PP ) + #define NO_SERIAL_FORMAT +#endif + +#if defined( VISUINO_ESP8266 ) +#define V_FMOD(a,b) (a - b * floor(a / b)) +#else +#define V_FMOD(a,b) fmod(a,b) +#endif + +#ifndef PWMRANGE + #define PWMRANGE 255 +#endif + +#define MAKE_CALLBACK(A) (OpenWire::Component *)this, (OpenWire::TOnPinReceive)( void (OpenWire::Component::*) ( void *_Data ) )&A + +namespace Mitov +{ +//--------------------------------------------------------------------------- +#ifdef VISUINO_ESP8266 + +template const T& MitovMin(const T& a, const T& b) +{ + return (b < a) ? b : a; +} + +template const T& MitovMax(const T& a, const T& b) +{ + return (b > a) ? b : a; +} + +#else + #define MitovMin min + #define MitovMax max +#endif +//--------------------------------------------------------------------------- + struct TDataBlock + { + public: + uint32_t Size; + byte *Data; + + public: + TDataBlock( uint32_t ASize, void *AData ) : + Size( ASize), + Data( (byte *)AData ) + { + } + + }; +//--------------------------------------------------------------------------- + const bool GBooleanConst[] = { false, true }; +//--------------------------------------------------------------------------- + #pragma pack(push, 1) + struct TColor + { + public: + uint8_t Red; + uint8_t Green; + uint8_t Blue; + uint8_t Alpha = 0; + + public: + void SetValue( const long AValue ) + { + *((long *)this) = AValue & 0xFFFFFF; +// Blue = ( AValue >> 16 ) & 0xFF; +// Green = ( AValue >> 8 ) & 0xFF; +// Red = AValue & 0xFF; +// Alpha = 0; + } + + void operator =( const long AValue ) + { + SetValue( AValue ); + } + + bool operator ==( const TColor other ) + { + return *((long *)this) == *((long *)&other); + } + + operator long() + { + return *((long *)this); + } + + public: + String ToString() + { + return String( "(" ) + + String((int)Red ) + "," + + String((int)Green ) + "," + + String((int)Blue ) + ")"; + } + + public: + TColor( long AValue = 0 ) + { + SetValue( AValue ); + } + + TColor( unsigned char ARed, unsigned char AGreen, unsigned char ABlue ) : + Red( ARed ), + Green( AGreen ), + Blue( ABlue ) + { + } + + TColor( long AValue, bool ) // For Windows BGR support + { + Red = ( AValue >> 16 ) & 0xFF; + Green = ( AValue >> 8 ) & 0xFF; + Blue = AValue & 0xFF; + } + }; + #pragma pack(pop) +//--------------------------------------------------------------------------- + const double HoursPerDay = 24; + const double MinsPerHour = 60; + const double SecsPerMin = 60; + const double MSecsPerSec = 1000; + const double MinsPerDay = HoursPerDay * MinsPerHour; + const double SecsPerDay = MinsPerDay * SecsPerMin; + const double SecsPerHour = SecsPerMin * MinsPerHour; + const double MSecsPerDay = SecsPerDay * MSecsPerSec; + const int32_t IMSecsPerDay = MSecsPerDay; +// Days between 1/1/0001 and 12/31/1899 +// const double DateDelta = 693594; +//--------------------------------------------------------------------------- + const uint16_t MonthDays[2][12] = + { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} + }; +//--------------------------------------------------------------------------- + class TDateTime + { + public: + int32_t Time; // Number of milliseconds since midnight + int32_t Date; // One plus number of days since 1/1/0001 + + protected: + inline void DivMod( int32_t Dividend, uint16_t Divisor, uint16_t &Result, uint16_t &Remainder ) + { + Result = Dividend / Divisor; + Remainder = Dividend % Divisor; + } + + public: + void DecodeTime( uint16_t &Hour, uint16_t &Min, uint16_t &Sec, uint16_t &MSec ) + { + uint16_t MinCount, MSecCount; + + DivMod( Time, SecsPerMin * MSecsPerSec, MinCount, MSecCount ); + DivMod( MinCount, MinsPerHour, Hour, Min ); + DivMod( MSecCount, MSecsPerSec, Sec, MSec ); + } + + bool IsLeapYear( uint16_t Year ) + { + return (Year % 4 == 0) && ((Year % 100 != 0) || (Year % 400 == 0)); + } + + bool DecodeDateFully( uint16_t &Year, uint16_t &Month, uint16_t &Day, uint16_t &DOW ) + { + const uint32_t D1 = 365; + const uint32_t D4 = D1 * 4 + 1; + const uint32_t D100 = D4 * 25 - 1; + const uint32_t D400 = D100 * 4 + 1; + +/* + var + Y, M, D, I: Word; + T: Integer; + DayTable: PDayTable; + begin +*/ + int32_t T = Date; + if( T <= 0 ) + { + Year = 0; + Month = 0; + Day = 0; + DOW = 0; + return( false ); + } + + else + { + DOW = T % 7 + 1; + --T; + uint16_t Y = 1; + while( T >= D400 ) + { + T -= D400; + Y += 400; + } + + uint16_t D, I; + DivMod( T, D100, I, D ); + if( I == 4 ) + { + -- I; + D -= D100; + } + + Y += I * 100; + DivMod(D, D4, I, D); + + Y += I * 4; + DivMod(D, D1, I, D); + + if( I == 4 ) + { + --I; + D += D1; + } + + Y += I; + bool Result = IsLeapYear(Y); + + const uint16_t *DayTable = MonthDays[Result]; + uint16_t M = 0; // The C++ Day table is zero indexed! + for(;;) + { + I = DayTable[M]; + if( D < I ) + break; + + D -= I; + ++ M; + } + + Year = Y; + Month = M + 1; + Day = D + 1; + + return Result; + } + } + + bool TryEncodeDate( uint16_t Year, uint16_t Month, uint16_t Day ) + { + const uint16_t *DayTable = MonthDays[IsLeapYear(Year)]; + if( (Year >= 1) && (Year <= 9999) && (Month >= 1) && (Month <= 12) && + (Day >= 1) && (Day <= DayTable[Month])) + { + for( int i = 1; i < Month; i ++ ) + Day += DayTable[ i - 1 ]; + + int I = Year - 1; +// Serial.println( I ); +// Serial.println( Day ); + Date = ((uint32_t)I) * 365 + (int)( I / 4 ) - (int)( I / 100 ) + (int)( I / 400 ) + (uint32_t)Day; +// Serial.println( Date ); + return true; + } + + return false; + } + + bool TryEncodeTime( uint16_t Hour, uint16_t Min, uint16_t Sec, uint16_t MSec ) + { + if ((Hour < HoursPerDay) && (Min < MinsPerHour) && (Sec < SecsPerMin) && (MSec < MSecsPerSec)) + { + Time = (Hour * (MinsPerHour * SecsPerMin * MSecsPerSec)) + + (Min * SecsPerMin * MSecsPerSec) + + (Sec * MSecsPerSec) + + MSec; +// Date = DateDelta; // This is the "zero" day for a TTimeStamp, days between 1/1/0001 and 12/30/1899 including the latter date + Date = 0; // This is the "zero" day for a TTimeStamp, days between 1/1/0001 and 12/30/1899 including the latter date + return true; + } + + return false; + } + + bool TryEncodeDateTime( uint16_t AYear, uint16_t AMonth, uint16_t ADay, uint16_t AHour, uint16_t AMinute, uint16_t ASecond, uint16_t AMilliSecond ) + { + bool Result = TryEncodeDate( AYear, AMonth, ADay ); + if( Result ) + { + TDateTime LTime; + Result = LTime.TryEncodeTime( AHour, AMinute, ASecond, AMilliSecond ); + if( Result ) + Time = LTime.Time; + + } + + return Result; + } + + void DecodeDateTime( uint16_t &AYear, uint16_t &AMonth, uint16_t &ADay, uint16_t &AHour, uint16_t &AMinute, uint16_t &ASecond, uint16_t &AMilliSecond ) + { + uint16_t AWeekDay; + DecodeDateTime( AYear, AMonth, ADay, AWeekDay, AHour, AMinute, ASecond, AMilliSecond ); + } + + void DecodeDateTime( uint16_t &AYear, uint16_t &AMonth, uint16_t &ADay, uint16_t &AWeekDay, uint16_t &AHour, uint16_t &AMinute, uint16_t &ASecond, uint16_t &AMilliSecond ) + { + DecodeDateFully( AYear, AMonth, ADay, AWeekDay ); + DecodeTime( AHour, AMinute, ASecond, AMilliSecond ); + } + + String ToString() + { + uint16_t AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond; + DecodeDateTime( AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond ); + char ABuffer[ 6 + 4 + 5 * 2 + 3 + 2 + 1 ]; + sprintf( ABuffer, "(%04d.%02d.%02d %02d:%02d:%02d.%03d)", AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond ); + return ABuffer; + } + + public: + bool operator == ( TDateTime &AOther ) + { + if( Date != AOther.Date ) + return false; + + return ( Time == AOther.Time ); + } + + bool operator != ( TDateTime &AOther ) + { + if( Date != AOther.Date ) + return true; + + return ( Time != AOther.Time ); + } + + bool operator <= ( TDateTime &AOther ) + { + if( Date > AOther.Date ) + return false; + + if( Date < AOther.Date ) + return true; + + return ( Time <= AOther.Time ); + } + + bool operator >= ( TDateTime &AOther ) + { + if( Date > AOther.Date ) + return true; + + if( Date < AOther.Date ) + return false; + + return ( Time >= AOther.Time ); + } + + bool operator < ( TDateTime &AOther ) + { + if( Date > AOther.Date ) + return false; + + if( Date < AOther.Date ) + return true; + + return ( Time < AOther.Time ); + } + + bool operator > ( TDateTime &AOther ) + { + if( Date > AOther.Date ) + return true; + + if( Date < AOther.Date ) + return false; + + return ( Time > AOther.Time ); + } + + public: + TDateTime() : + Date( 693594 ), + Time( 0 ) + { + } + + TDateTime( int32_t ADate, int32_t ATime ) : + Date( ADate ), + Time( ATime ) + { + } + + TDateTime( uint32_t ADummy ) : + Date( 693594 ), + Time( 0 ) + { + } + + }; +//--------------------------------------------------------------------------- + template void swap ( T& a, T& b ) + { + T c(a); a=b; b=c; + } +//--------------------------------------------------------------------------- + class Bytes + { + public: + unsigned char *_Bytes; + unsigned int _BytesSize = 0; + + }; +//--------------------------------------------------------------------------- + class CommonSource : public OpenWire::Component + { + public: + OpenWire::SourcePin OutputPin; + + }; +//--------------------------------------------------------------------------- + class EnabledComponent : public OpenWire::Component + { + public: + bool Enabled = true; + + }; +//--------------------------------------------------------------------------- + class ClockingSupport : public OpenWire::Object + { + public: + OpenWire::ConnectSinkPin ClockInputPin; + + protected: + virtual void DoClockReceive( void *_Data ) = 0; + + public: + ClockingSupport() + { + ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ClockingSupport::DoClockReceive ); + } + + }; +//--------------------------------------------------------------------------- + class CommonEnableSource : public CommonSource + { + public: + bool Enabled = true; + + }; +//--------------------------------------------------------------------------- + class CommonSink : public OpenWire::Component + { + public: + OpenWire::SinkPin InputPin; + + protected: + virtual void DoReceive( void *_Data ) = 0; + + public: + CommonSink() + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&CommonSink::DoReceive ); + } + }; +//--------------------------------------------------------------------------- + class CommonFilter : public CommonSource + { + public: + OpenWire::SinkPin InputPin; + + protected: + virtual void DoReceive( void *_Data ) = 0; + + public: + CommonFilter() + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&CommonFilter::DoReceive ); + } + }; +//--------------------------------------------------------------------------- + class CommonEnableFilter : public CommonFilter + { + public: + bool Enabled = true; + + }; +//--------------------------------------------------------------------------- + class CommonImplementedEnableFilter : public CommonEnableFilter + { + protected: + virtual void ReceiveValue( void *_Data ) = 0; + + virtual void DoReceive( void *_Data ) override + { + if( ! Enabled ) + { + OutputPin.Notify( _Data ); + return; + } + + ReceiveValue( _Data ); + } + + }; +//--------------------------------------------------------------------------- + template class CommonTypedInOutFilter : public CommonImplementedEnableFilter + { + protected: + virtual T_OUT FilterValue( T_IN AValue ) = 0; + + protected: + virtual void ReceiveValue( void *_Data ) override + { + T_IN AInValue = *(T_IN*)_Data; + + T_OUT AOutValue = FilterValue( AInValue ); + + OutputPin.Notify( &AOutValue ); + } + + }; +//--------------------------------------------------------------------------- + template class CommonTypedFilter : public CommonTypedInOutFilter + { + }; +//--------------------------------------------------------------------------- + class CommonGenerator : public CommonSource + { + typedef Mitov::CommonSource inherited; + + protected: + unsigned long FLastTime = 0; + unsigned long FPeriod = 0; + + public: + bool Enabled = true; + float Frequency = 1.0; + + public: + void SetFrequency( float AValue ) + { + if( Frequency == AValue ) + return; + + Frequency = AValue; + CalculateFields(); + } + + protected: + virtual void Clock() = 0; + + protected: + virtual void CalculateFields() + { + FPeriod = ( (( 1 / Frequency ) * 1000000 ) + 0.5 ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + while( currentMicros - FLastTime >= FPeriod ) + { + if( Enabled ) + Clock(); + + FLastTime += FPeriod; + } + + inherited::SystemLoopBegin( currentMicros ); + } + + virtual void SystemStart() override + { + inherited::SystemStart(); + FLastTime = micros(); + } + + }; +//--------------------------------------------------------------------------- + template class ValueSource : public Mitov::CommonSource + { + typedef Mitov::CommonSource inherited; + + public: + OpenWire::SinkPin ClockInputPin; + + public: + T Value; + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + OutputPin.Notify( &Value ); + } + + void DoClockReceive( void *_Data ) + { + OutputPin.Notify( &Value ); + } + + public: + ValueSource( T AValue ) : + Value( AValue ) + { + ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ValueSource::DoClockReceive ); + } + + }; +//--------------------------------------------------------------------------- + template class BindableValueSource : public Mitov::ValueSource + { + typedef Mitov::ValueSource inherited; + + protected: + T OldValue; + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + OldValue = inherited::Value; + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( inherited::Value == OldValue ) + return; + + OldValue = inherited::Value; + inherited::OutputPin.Notify( &OldValue ); + } + + public: + BindableValueSource( T AValue ) : + inherited( AValue ), + OldValue( AValue ) + { + } + + }; +//--------------------------------------------------------------------------- + template class BasicMultiInput : public Mitov::CommonSource + { + typedef Mitov::CommonSource inherited; + + protected: + bool FModified = false; + T_OUT FLastOutput; + + protected: + void DoReceive( void *_Data ) + { + FModified = true; + } + + protected: + virtual T_OUT CalculateOutput() = 0; + + inline void CallCalculateSendOutput( bool AFromStart ) // Work around compiler bug + { + CalculateSendOutput( AFromStart ); + } + + virtual void CalculateSendOutput( bool AFromStart ) + { +// Serial.println( "CalculateSendOutput+++" ); + T_OUT AValue = CalculateOutput(); +// Serial.println( AValue ); + if( ! AFromStart ) + if( FLastOutput == AValue ) + return; + + OutputPin.SendValue( AValue ); // Use Send Value for String Compatibility! + FLastOutput = AValue; + + FModified = false; + } + + virtual void SystemStart() + { + CalculateSendOutput( true ); + } + + virtual void SystemLoopEnd() + { + if( FModified ) + CalculateSendOutput( false ); + + } + + }; +//--------------------------------------------------------------------------- + template class BasicCommonMultiInput : public Mitov::BasicMultiInput + { + typedef Mitov::BasicMultiInput inherited; + + public: + OpenWire::VlaueSinkPin InputPins[ C_NUM_INPUTS ]; + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + + for( int i = 0; i < C_NUM_INPUTS; ++i ) + InputPins[ i ].SetCallback( this, (OpenWire::TOnPinReceive)&BasicCommonMultiInput::DoReceive ); + + } + }; +//--------------------------------------------------------------------------- + template class CommonMultiInput : public Mitov::BasicCommonMultiInput + { + typedef Mitov::BasicCommonMultiInput inherited; + + }; +//--------------------------------------------------------------------------- + template class CommonClockedMultiInput : public Mitov::CommonMultiInput, public ClockingSupport + { + typedef Mitov::CommonMultiInput inherited; + + protected: + virtual void CalculateSendOutput( bool AFromStart ) + { + if( ClockInputPin.IsConnected() ) + return; + + inherited::CalculateSendOutput( AFromStart ); +/* + T_OUT AValue = CalculateOutput(); +// Serial.println( AValue ); + if( ! AFromStart ) + if( FLastOutput == AValue ) + return; + + OutputPin.SendValue( AValue ); // Use Send Value for String Compatibility! + FLastOutput = AValue; + + FModified = false; +*/ + } + + protected: + virtual T CalculateOutput() = 0; + + void DoClockReceive( void *_Data ) + { + T AValue = CalculateOutput(); +// if( FLastOutput == AValue ) +// return; + + inherited::OutputPin.SendValue( AValue ); // Use Send Value for String Compatibility! + inherited::FLastOutput = AValue; + + inherited::FModified = false; + } + + }; +//--------------------------------------------------------------------------- + class DigitalInput : public CommonSource + { + typedef Mitov::CommonSource inherited; + + public: + uint8_t PinNumber; + + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + pinMode(PinNumber, INPUT); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + bool AValue = digitalRead( PinNumber ); + OutputPin.Notify( &AValue ); + } + + public: + DigitalInput( int APinNumber ) : + PinNumber( APinNumber ) + { + } + }; +//--------------------------------------------------------------------------- + class DigitalOutput : public CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { +// Serial.println( "Test1" ); + if( *(bool*)_Data ) + digitalWrite( PinNumber, HIGH ); + + else + digitalWrite( PinNumber, LOW ); + + } + + public: + uint8_t PinNumber; + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + pinMode(PinNumber, OUTPUT); + } + + public: + DigitalOutput( int APinNumber ) : + PinNumber( APinNumber ) + { + } + }; +//--------------------------------------------------------------------------- + class ArduinoBasicAnalogInputChannel : public CommonSource + { + typedef Mitov::CommonSource inherited; + + protected: + uint8_t FPinNumber; + float FLastOutput; + + public: + ArduinoBasicAnalogInputChannel( int APinNumber ) : + FPinNumber( APinNumber ) + { + } + }; +//--------------------------------------------------------------------------- + class ArduinoAnalogInputChannel : public ArduinoBasicAnalogInputChannel + { + typedef Mitov::ArduinoBasicAnalogInputChannel inherited; + +#ifdef VISUINO_TEENSY + protected: + unsigned int FResolution = 0; + float FDivider = 1023.0; + + public: + void SetResolution( unsigned int AResolution ) + { + if( AResolution == FResolution ) + return; + + FResolution = AResolution; + analogReadRes( FResolution ); + CalculateMultiplier(); + } + + protected: + void CalculateMultiplier() + { + FDivider = pow( 2, FResolution ) - 1; + } + +#endif + protected: + virtual void SystemStart() + { +#ifdef VISUINO_TEENSY + analogReadRes( FResolution ); + FLastOutput = analogRead( FPinNumber ) / FDivider; +#else + FLastOutput = analogRead( FPinNumber ) / 1023.0; +#endif + OutputPin.Notify( &FLastOutput ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { +#ifdef VISUINO_TEENSY + float AValue = analogRead( FPinNumber ) / FDivider; +#else + float AValue = analogRead( FPinNumber ) / 1023.0; +#endif + if( AValue == FLastOutput ) + return; + + FLastOutput = AValue; + OutputPin.Notify( &AValue ); + } + + public: + ArduinoAnalogInputChannel( int APinNumber ) : + inherited( APinNumber ) + { + } + +#ifdef VISUINO_TEENSY + ArduinoAnalogInputChannel( int APinNumber, unsigned int AResolution ) : + inherited( APinNumber ), + FResolution( AResolution ) + { + CalculateMultiplier(); + } + +#endif + }; +//--------------------------------------------------------------------------- +#ifdef VISUINO_TEENSY +//--------------------------------------------------------------------------- + class ArduinoTouchAnalogInputChannel : public ArduinoBasicAnalogInputChannel + { + typedef Mitov::ArduinoBasicAnalogInputChannel inherited; + + protected: + virtual void SystemStart() + { + FLastOutput = touchRead( FPinNumber ); + OutputPin.Notify( &FLastOutput ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + float AValue = touchRead( FPinNumber ); + if( AValue == FLastOutput ) + return; + + FLastOutput = AValue; + OutputPin.Notify( &AValue ); + } + + public: + ArduinoTouchAnalogInputChannel( int APinNumber ) : + inherited( APinNumber ) + { + } + }; +//--------------------------------------------------------------------------- +/* + template void SetArduinoAnalogInputResolutionChannel( unsigned int AValue ) + { + analogReadRes( AValue ); + } +*/ +//--------------------------------------------------------------------------- +#endif // VISUINO_TEENSY +//--------------------------------------------------------------------------- + class AnalogOutput : public CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { + float AValue = *(float*)_Data; + analogWrite( PinNumber, ( AValue * PWMRANGE ) + 0.5 ); + } + + public: + uint8_t PinNumber; + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + + pinMode(PinNumber, OUTPUT); + } + + public: + AnalogOutput( int APinNumber ) : + PinNumber( APinNumber ) + { + } + }; +//--------------------------------------------------------------------------- + class ArduinoDigitalChannel : public CommonSource + { + typedef Mitov::CommonSource inherited; + + protected: + uint8_t FPinNumber; + bool FIsOutput : 1; + bool FIsPullUp : 1; + bool FIsAnalog : 1; + bool FCombinedInOut : 1; + bool FLastOutput : 1; + bool FRawInput : 1; + + public: + OpenWire::SinkPin DigitalInputPin; + OpenWire::SinkPin AnalogInputPin; + + protected: + void PinDirectionsInit() + { + if( FRawInput ) + return; + + if( FIsOutput ) + pinMode( FPinNumber, OUTPUT ); + + else + { + if( FIsPullUp ) + pinMode( FPinNumber, INPUT_PULLUP ); + + else + pinMode( FPinNumber, INPUT ); + } + } + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + + PinDirectionsInit(); + } + + virtual void SystemStart() + { + if( FRawInput ) + return; + + FLastOutput = ( digitalRead( FPinNumber ) == HIGH ); + OutputPin.SendValue( FLastOutput ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( !FIsOutput ) + { + bool AValue = ( digitalRead( FPinNumber ) == HIGH ); + if( AValue == FLastOutput ) + return; + + FLastOutput = AValue; +// Serial.println( AData.Value ); + OutputPin.Notify( &AValue ); + } + } + + protected: + void DoAnalogReceive( void *_Data ) + { + if( FIsOutput && FIsAnalog ) + { + float AValue = *(float*)_Data; + analogWrite( FPinNumber, ( AValue * PWMRANGE ) + 0.5 ); + } + } + +/* + void DoDigitalOutputReceive( void *_Data ) + { + *((int*)_Data) = FPinNumber; + } +*/ + void DoDigitalReceive( void *_Data ) + { + if( FRawInput ) + { + *((int*)_Data) = FPinNumber; + return; + } + + if( ( FCombinedInOut || FIsOutput ) && (! FIsAnalog )) + { + bool AValue = *(bool *)_Data; + + if( AValue ) + if( FCombinedInOut ) + pinMode( FPinNumber, OUTPUT ); + + if( AValue ) + digitalWrite( FPinNumber, HIGH ); + + else + digitalWrite( FPinNumber, LOW ); + + if( ! AValue ) + if( FCombinedInOut ) + if( FIsPullUp ) + pinMode( FPinNumber, INPUT_PULLUP ); + + else + pinMode( FPinNumber, INPUT ); + + } + } + + public: + void SetIsOutput( bool AValue ) + { + if( FIsOutput == AValue ) + return; + + FIsOutput = AValue; + PinDirectionsInit(); + } + + void SetIsPullUp( bool AValue ) + { + if( FIsPullUp == AValue ) + return; + + FIsPullUp = AValue; + PinDirectionsInit(); + } + + void SetIsAnalog( bool AValue ) + { + if( FIsAnalog == AValue ) + return; + + FIsAnalog = AValue; + PinDirectionsInit(); + } + + public: + ArduinoDigitalChannel( int APinNumber, bool AIsOutput, bool AIsPullUp, bool AIsAnalog, bool ACombinedInOut, bool ARawInput ) : + FPinNumber( APinNumber ), + FIsOutput( AIsOutput ), + FIsPullUp( AIsPullUp ), + FIsAnalog( AIsAnalog ), + FRawInput( ARawInput ), + FCombinedInOut( ACombinedInOut ) + + { + DigitalInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ArduinoDigitalChannel::DoDigitalReceive ); + AnalogInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ArduinoDigitalChannel::DoAnalogReceive ); + } + }; +//--------------------------------------------------------------------------- + class ArduinoAnalogOutputChannel : public CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + uint8_t FPinNumber; + + protected: + virtual void DoReceive( void *_Data ) + { + float AValue = *(float*)_Data; + analogWrite( FPinNumber, ( AValue * PWMRANGE ) + 0.5 ); + } + + public: + ArduinoAnalogOutputChannel( int APinNumber ) : + FPinNumber( APinNumber ) + { + } + + }; +//--------------------------------------------------------------------------- +#ifdef HAVE_CDCSERIAL + #define SERIAL_TYPE Serial_ +#else + #define SERIAL_TYPE HardwareSerial +#endif +//--------------------------------------------------------------------------- + enum TArduinoSerialParity { spNone, spEven, slOdd, slMark, slSpace }; +//--------------------------------------------------------------------------- + class BasicSerialPort : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SourcePin SendingOutputPin; + + public: + bool Enabled : 1; + + protected: + bool FSending : 1; + + public: + uint32_t AfterSendingDelay = 10000; + + public: + virtual Stream &GetStream() = 0; + + protected: + uint32_t FStartTime; + + public: + template void Print( T AValue ) + { + if( Enabled ) + { + FSending = true; + SendingOutputPin.SendValue( FSending ); + FStartTime = micros(); + GetStream().println( AValue ); + + } + } + + template void PrintChar( T AValue ) + { + if( Enabled ) + { + FSending = true; + SendingOutputPin.SendValue( FSending ); + FStartTime = micros(); + GetStream().print( AValue ); + } + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( FSending ) + { + if( currentMicros - FStartTime >= AfterSendingDelay ) + { + FSending = false; + SendingOutputPin.SendValue( FSending ); + } + } + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + BasicSerialPort() : + Enabled( true ), + FSending( false ) + { + } + }; +//--------------------------------------------------------------------------- + template class BasicTypedSerialPort : public Mitov::BasicSerialPort + { + typedef Mitov::BasicSerialPort inherited; + + public: + virtual Stream &GetStream() { return *T_SERIAL; } + + protected: + virtual void SystemInit() + { + if( Enabled ) + StartPort(); + + inherited::SystemInit(); + } + + protected: + virtual void StartPort() = 0; + + void RestartPort() + { + if( ! Enabled ) + return; + + T_SERIAL->end(); + StartPort(); + } + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartPort(); + + else + T_SERIAL->end(); + } + + }; +//--------------------------------------------------------------------------- + template class SpeedSerialPort : public Mitov::BasicTypedSerialPort + { + typedef Mitov::BasicTypedSerialPort inherited; + + public: + unsigned long Speed = 9600; + + public: + void SetSpeed( unsigned int AValue ) + { + if( Speed == AValue ) + return; + + Speed = AValue; + inherited::RestartPort(); + } + + protected: + virtual void StartPort() + { + T_SERIAL->begin( Speed ); + } + + }; +//--------------------------------------------------------------------------- + template class ArduinoSerialInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_SERIAL_INSTANCE->Print( *(T*)_Data ); + } + }; +//--------------------------------------------------------------------------- + template class ArduinoSerialInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_SERIAL_INSTANCE->Print( *(bool*)_Data ? "true" : "false" ); + } + }; +//--------------------------------------------------------------------------- + template class ArduinoSerialInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + if( *(char*)_Data == '\r' ) + T_SERIAL_INSTANCE->Print( "" ); + + else + T_SERIAL_INSTANCE->PrintChar( *(char*)_Data ); + } + }; +//--------------------------------------------------------------------------- + template class ArduinoSerialBinaryInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + if( T_SERIAL_INSTANCE->Enabled ) + { + Mitov::TDataBlock ADataBlock = *(Mitov::TDataBlock*)_Data; + T_SERIAL_INSTANCE->GetStream().write((uint8_t *) ADataBlock.Data, ADataBlock.Size ); +// T_SERIAL_INSTANCE->GetStream().write( *(unsigned char*)_Data ); + } + } + }; +//--------------------------------------------------------------------------- + template class ArduinoSerialStringInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_SERIAL_INSTANCE->Print( (char*)_Data ); + } + }; +//--------------------------------------------------------------------------- + template class ArduinoSerialObjectInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_SERIAL_INSTANCE->Print( ((T_OBJECT *)_Data)->ToString().c_str() ); + } + }; +//--------------------------------------------------------------------------- + template class ArduinoDirectSerialInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + virtual Stream &GetStream() + { + return T_SERIAL_INSTANCE->GetStream(); + } + + protected: + virtual void DoReceive( void *_Data ) override + { +// if( T_SERIAL_INSTANCE->Enabled ) +// T_SERIAL->write( *(unsigned char*)_Data ); + } + }; +//--------------------------------------------------------------------------- + template class ArduinoSerialOutput : public Mitov::CommonSource + { + typedef Mitov::CommonSource inherited; + +// protected: +// byte FData[ 2 ]; + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ! T_SERIAL_INSTANCE->Enabled ) + return; + +// if( Serial.available() ) + { + int AData = T_SERIAL_INSTANCE->GetStream().read(); + if( AData >= 0 ) + { +// FData[ 0 ] = AData; +// OutputPin.Notify( FData ); + + unsigned char AByte = AData; + OutputPin.SendValue( Mitov::TDataBlock( 1, &AByte )); + } + } + + inherited::SystemLoopBegin( currentMicros ); + } + +/* + public: + ArduinoSerialOutput() + { + FData[ 1 ] = 0; + } +*/ + }; +//--------------------------------------------------------------------------- + class ArduinoI2C_Command + { + public: + virtual void Execute() = 0; + + }; +//--------------------------------------------------------------------------- + class ArduinoI2CInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + ((ArduinoI2C_Command*)_Data )->Execute(); +// Wire.println( *(ArduinoI2C_Command*)_Data ); + } + }; +//--------------------------------------------------------------------------- + class GPRSAccessPoint + { + public: + bool Enabled = true; + + String AccessPoint; + String UserName; + String Password; + + int32_t NumberRetries = 5; + int32_t RetryInterval = 30000; + + public: + int32_t FRetryCount = 0; + unsigned long FLastTime = 0; + + public: + bool CanRetry( unsigned long currentMicros ) + { + if( FRetryCount > NumberRetries ) + return false; + + if(( currentMicros - FLastTime ) < RetryInterval ) + return false; + + return true; + } + + }; +//--------------------------------------------------------------------------- + class CommonConverter : public OpenWire::SinkPin + { + public: + OpenWire::SourcePin OutputPin; + + }; +//--------------------------------------------------------------------------- + class Convert_BinaryBlockToChar : public Mitov::CommonConverter + { + protected: + virtual void DoReceive( void *_Data ) + { + Mitov::TDataBlock ABlock = *(Mitov::TDataBlock *)_Data; + while( ABlock.Size-- ) + OutputPin.Notify( ABlock.Data++ ); + } + + }; +//--------------------------------------------------------------------------- + class Convert_BinaryToClock : public Mitov::CommonConverter + { + protected: + bool FLastValue = false; + + protected: + virtual void DoReceive( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( AValue == FLastValue ) + return; + + FLastValue = AValue; + if( AValue ) + OutputPin.Notify( NULL ); + + } + + }; +//--------------------------------------------------------------------------- + inline uint8_t FromBcdToDec(const uint8_t bcd) + { + return (10 * ((bcd & 0xF0) >> 4) + (bcd & 0x0F)); + } +//--------------------------------------------------------------------------- + inline uint8_t FromDecToBcd(const uint8_t dec) + { + const uint8_t tens = dec / 10; + const uint8_t ones = dec % 10; + return (tens << 4) | ones; + } +//--------------------------------------------------------------------------- + inline float ConvertCtoF(float c) + { + return c * 1.8 + 32; + } +//--------------------------------------------------------------------------- + inline float ConvertFtoC(float f) + { + return (f - 32) * 0.55555; + } +//--------------------------------------------------------------------------- + class InterruptLock + { + public: + InterruptLock() + { + noInterrupts(); + } + + ~InterruptLock() + { + interrupts(); + } + }; +//--------------------------------------------------------------------------- +} // Mitov + +#endif + diff --git a/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/COPYING b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/COPYING new file mode 100644 index 0000000..7dcf8e8 --- /dev/null +++ b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/COPYING @@ -0,0 +1,794 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + + +LGPL ADDENDUM: + + + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/MitovEmbedded_Adafruit_NeoPixel.h b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/MitovEmbedded_Adafruit_NeoPixel.h new file mode 100644 index 0000000..52b82c6 --- /dev/null +++ b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/MitovEmbedded_Adafruit_NeoPixel.h @@ -0,0 +1,1092 @@ +/*-------------------------------------------------------------------- + This file is part of the Adafruit NeoPixel library. + + NeoPixel is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + NeoPixel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with NeoPixel. If not, see + . + --------------------------------------------------------------------*/ + +#ifndef ADAFRUIT_NEOPIXEL_H +#define ADAFRUIT_NEOPIXEL_H + +#if (ARDUINO >= 100) + #include +#else + #include + #include +#endif + +// 'type' flags for LED pixels (third parameter to constructor): +#define NEO_RGB 0x00 // Wired for RGB data order +#define NEO_GRB 0x01 // Wired for GRB data order +#define NEO_BRG 0x04 + +#define NEO_COLMASK 0x01 +#define NEO_KHZ800 0x02 // 800 KHz datastream +#define NEO_SPDMASK 0x02 +// Trinket flash space is tight, v1 NeoPixels aren't handled by default. +// Remove the ifndef/endif to add support -- but code will be bigger. +// Conversely, can comment out the #defines to save space on other MCUs. +#ifndef __AVR_ATtiny85__ +#define NEO_KHZ400 0x00 // 400 KHz datastream +#endif + +class MitovEmbedded_Adafruit_NeoPixel { + + public: + + // Constructor: number of LEDs, pin number, LED type + MitovEmbedded_Adafruit_NeoPixel(uint16_t n, uint8_t p=6, uint8_t t=NEO_GRB + NEO_KHZ800); + ~MitovEmbedded_Adafruit_NeoPixel(); + + void + begin(void), + show(void), + setPin(uint8_t p), + setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b), + setPixelColor(uint16_t n, uint32_t c), + setBrightness(uint8_t), + clear(); + uint8_t + *getPixels(void) const, + getBrightness(void) const; + uint16_t + numPixels(void) const; + static uint32_t + Color(uint8_t r, uint8_t g, uint8_t b); + uint32_t + getPixelColor(uint16_t n) const; + inline bool + canShow(void) { return (micros() - endTime) >= 50L; } + + private: + + const uint16_t + numLEDs, // Number of RGB LEDs in strip + numBytes; // Size of 'pixels' buffer below + uint8_t + pin, // Output pin number + brightness, + *pixels, // Holds LED color values (3 bytes each) + rOffset, // Index of red byte within each 3-byte pixel + gOffset, // Index of green byte + bOffset; // Index of blue byte + const uint8_t + type; // Pixel flags (400 vs 800 KHz, RGB vs GRB color) + uint32_t + endTime; // Latch timing reference +#ifdef __AVR__ + const volatile uint8_t + *port; // Output PORT register + uint8_t + pinMask; // Output PORT bitmask +#endif + +}; + +MitovEmbedded_Adafruit_NeoPixel::MitovEmbedded_Adafruit_NeoPixel(uint16_t n, uint8_t p, uint8_t t) : + numLEDs(n), numBytes(n * 3), pin(p), brightness(0), + pixels(NULL), type(t), endTime(0) +#ifdef __AVR__ + ,port(portOutputRegister(digitalPinToPort(p))), + pinMask(digitalPinToBitMask(p)) +#endif +{ + if((pixels = (uint8_t *)malloc(numBytes))) { + memset(pixels, 0, numBytes); + } + if(t & NEO_GRB) { // GRB vs RGB; might add others if needed + rOffset = 1; + gOffset = 0; + bOffset = 2; + } else if (t & NEO_BRG) { + rOffset = 1; + gOffset = 2; + bOffset = 0; + } else { + rOffset = 0; + gOffset = 1; + bOffset = 2; + } + +} + +MitovEmbedded_Adafruit_NeoPixel::~MitovEmbedded_Adafruit_NeoPixel() { + if(pixels) free(pixels); + pinMode(pin, INPUT); +} + +void MitovEmbedded_Adafruit_NeoPixel::begin(void) { + pinMode(pin, OUTPUT); + digitalWrite(pin, LOW); +} + +void MitovEmbedded_Adafruit_NeoPixel::show(void) { + + if(!pixels) return; + + // Data latch = 50+ microsecond pause in the output stream. Rather than + // put a delay at the end of the function, the ending time is noted and + // the function will simply hold off (if needed) on issuing the + // subsequent round of data until the latch time has elapsed. This + // allows the mainline code to start generating the next frame of data + // rather than stalling for the latch. + while(!canShow()); + // endTime is a private member (rather than global var) so that mutliple + // instances on different pins can be quickly issued in succession (each + // instance doesn't delay the next). + + // In order to make this code runtime-configurable to work with any pin, + // SBI/CBI instructions are eschewed in favor of full PORT writes via the + // OUT or ST instructions. It relies on two facts: that peripheral + // functions (such as PWM) take precedence on output pins, so our PORT- + // wide writes won't interfere, and that interrupts are globally disabled + // while data is being issued to the LEDs, so no other code will be + // accessing the PORT. The code takes an initial 'snapshot' of the PORT + // state, computes 'pin high' and 'pin low' values, and writes these back + // to the PORT register as needed. + + noInterrupts(); // Need 100% focus on instruction timing + +#ifdef __AVR__ + + volatile uint16_t + i = numBytes; // Loop counter + volatile uint8_t + *ptr = pixels, // Pointer to next byte + b = *ptr++, // Current byte value + hi, // PORT w/output bit set high + lo; // PORT w/output bit set low + + // Hand-tuned assembly code issues data to the LED drivers at a specific + // rate. There's separate code for different CPU speeds (8, 12, 16 MHz) + // for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The + // datastream timing for the LED drivers allows a little wiggle room each + // way (listed in the datasheets), so the conditions for compiling each + // case are set up for a range of frequencies rather than just the exact + // 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on + // devices (e.g. 16.5 MHz DigiSpark). The ranges were arrived at based + // on the datasheet figures and have not been extensively tested outside + // the canonical 8/12/16 MHz speeds; there's no guarantee these will work + // close to the extremes (or possibly they could be pushed further). + // Keep in mind only one CPU speed case actually gets compiled; the + // resulting program isn't as massive as it might look from source here. + +// 8 MHz(ish) AVR --------------------------------------------------------- +#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) + +#ifdef NEO_KHZ400 + if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream +#endif + + volatile uint8_t n1, n2 = 0; // First, next bits out + + // Squeezing an 800 KHz stream out of an 8 MHz chip requires code + // specific to each PORT register. At present this is only written + // to work with pins on PORTD or PORTB, the most likely use case -- + // this covers all the pins on the Adafruit Flora and the bulk of + // digital pins on the Arduino Pro 8 MHz (keep in mind, this code + // doesn't even get compiled for 16 MHz boards like the Uno, Mega, + // Leonardo, etc., so don't bother extending this out of hand). + // Additional PORTs could be added if you really need them, just + // duplicate the else and loop and change the PORT. Each add'l + // PORT will require about 150(ish) bytes of program space. + + // 10 instruction clocks per bit: HHxxxxxLLL + // OUT instructions: ^ ^ ^ (T=0,2,7) + +#ifdef PORTD // PORTD isn't present on ATtiny85, etc. + + if(port == &PORTD) { + + hi = PORTD | pinMask; + lo = PORTD & ~pinMask; + n1 = lo; + if(b & 0x80) n1 = hi; + + // Dirty trick: RJMPs proceeding to the next instruction are used + // to delay two clock cycles in one instruction word (rather than + // using two NOPs). This was necessary in order to squeeze the + // loop down to exactly 64 words -- the maximum possible for a + // relative branch. + + asm volatile( + "headD:" "\n\t" // Clk Pseudocode + // Bit 7: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 6" "\n\t" // 1-2 if(b & 0x40) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 6: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 5" "\n\t" // 1-2 if(b & 0x20) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 5: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 4" "\n\t" // 1-2 if(b & 0x10) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 4: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 3" "\n\t" // 1-2 if(b & 0x08) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 3: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 2" "\n\t" // 1-2 if(b & 0x04) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 2: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 1" "\n\t" // 1-2 if(b & 0x02) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 1: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 0" "\n\t" // 1-2 if(b & 0x01) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet) + // Bit 0: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "brne headD" "\n" // 2 while(i) (Z flag set above) + : [byte] "+r" (b), + [n1] "+r" (n1), + [n2] "+r" (n2), + [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTD)), + [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo)); + + } else if(port == &PORTB) { + +#endif // PORTD + + // Same as above, just switched to PORTB and stripped of comments. + hi = PORTB | pinMask; + lo = PORTB & ~pinMask; + n1 = lo; + if(b & 0x80) n1 = hi; + + asm volatile( + "headB:" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 6" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 5" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 4" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 3" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 2" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 1" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 0" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "sbiw %[count], 1" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "ld %[byte] , %a[ptr]+" "\n\t" + "sbrc %[byte] , 7" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "brne headB" "\n" + : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi), + [lo] "r" (lo)); + +#ifdef PORTD + } // endif PORTB +#endif + +#ifdef NEO_KHZ400 + } else { // end 800 KHz, do 400 KHz + + // Timing is more relaxed; unrolling the inner loop for each bit is + // not necessary. Still using the peculiar RJMPs as 2X NOPs, not out + // of need but just to trim the code size down a little. + // This 400-KHz-datastream-on-8-MHz-CPU code is not quite identical + // to the 800-on-16 code later -- the hi/lo timing between WS2811 and + // WS2812 is not simply a 2:1 scale! + + // 20 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL + // ST instructions: ^ ^ ^ (T=0,4,10) + + volatile uint8_t next, bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head20:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 6) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7) + "dec %[bit]" "\n\t" // 1 bit-- (T = 8) + "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12) + "rjmp .+0" "\n\t" // 2 nop nop (T = 14) + "rjmp .+0" "\n\t" // 2 nop nop (T = 16) + "rjmp .+0" "\n\t" // 2 nop nop (T = 18) + "rjmp head20" "\n\t" // 2 -> head20 (next bit out) + "nextbyte20:" "\n\t" // (T = 10) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12) + "nop" "\n\t" // 1 nop (T = 13) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 14) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 16) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18) + "brne head20" "\n" // 2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [hi] "r" (hi), + [lo] "r" (lo), + [ptr] "e" (ptr)); + } +#endif + +// 12 MHz(ish) AVR -------------------------------------------------------- +#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) + +#ifdef NEO_KHZ400 + if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream +#endif + + // In the 12 MHz case, an optimized 800 KHz datastream (no dead time + // between bytes) requires a PORT-specific loop similar to the 8 MHz + // code (but a little more relaxed in this case). + + // 15 instruction clocks per bit: HHHHxxxxxxLLLLL + // OUT instructions: ^ ^ ^ (T=0,4,10) + + volatile uint8_t next; + +#ifdef PORTD + + if(port == &PORTD) { + + hi = PORTD | pinMask; + lo = PORTD & ~pinMask; + next = lo; + if(b & 0x80) next = hi; + + // Don't "optimize" the OUT calls into the bitTime subroutine; + // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs! + asm volatile( + "headD:" "\n\t" // (T = 0) + "out %[port], %[hi]" "\n\t" // (T = 1) + "rcall bitTimeD" "\n\t" // Bit 7 (T = 15) + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 6 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 5 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 4 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 3 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 2 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 1 + // Bit 0: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi (T = 1) + "rjmp .+0" "\n\t" // 2 nop nop (T = 3) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 5) + "out %[port] , %[next]" "\n\t" // 1 PORT = next (T = 6) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) (T = 8) + "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9) + "nop" "\n\t" // 1 (T = 10) + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo (T = 11) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 13) + "brne headD" "\n\t" // 2 if(i != 0) -> (next byte) + "rjmp doneD" "\n\t" + "bitTimeD:" "\n\t" // nop nop nop (T = 4) + "out %[port], %[next]" "\n\t" // 1 PORT = next (T = 5) + "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 7) + "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 0x80) (T = 8) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9) + "nop" "\n\t" // 1 (T = 10) + "out %[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11) + "ret" "\n\t" // 4 nop nop nop nop (T = 15) + "doneD:" "\n" + : [byte] "+r" (b), + [next] "+r" (next), + [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTD)), + [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo)); + + } else if(port == &PORTB) { + +#endif // PORTD + + hi = PORTB | pinMask; + lo = PORTB & ~pinMask; + next = lo; + if(b & 0x80) next = hi; + + // Same as above, just set for PORTB & stripped of comments + asm volatile( + "headB:" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port] , %[hi]" "\n\t" + "rjmp .+0" "\n\t" + "ld %[byte] , %a[ptr]+" "\n\t" + "out %[port] , %[next]" "\n\t" + "mov %[next] , %[lo]" "\n\t" + "sbrc %[byte] , 7" "\n\t" + "mov %[next] , %[hi]" "\n\t" + "nop" "\n\t" + "out %[port] , %[lo]" "\n\t" + "sbiw %[count], 1" "\n\t" + "brne headB" "\n\t" + "rjmp doneB" "\n\t" + "bitTimeB:" "\n\t" + "out %[port], %[next]" "\n\t" + "mov %[next], %[lo]" "\n\t" + "rol %[byte]" "\n\t" + "sbrc %[byte], 7" "\n\t" + "mov %[next], %[hi]" "\n\t" + "nop" "\n\t" + "out %[port], %[lo]" "\n\t" + "ret" "\n\t" + "doneB:" "\n" + : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi), + [lo] "r" (lo)); + +#ifdef PORTD + } +#endif + +#ifdef NEO_KHZ400 + } else { // 400 KHz + + // 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL + // ST instructions: ^ ^ ^ (T=0,6,15) + + volatile uint8_t next, bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head30:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "rjmp .+0" "\n\t" // 2 nop nop (T = 6) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 8) + "rjmp .+0" "\n\t" // 2 nop nop (T = 10) + "rjmp .+0" "\n\t" // 2 nop nop (T = 12) + "rjmp .+0" "\n\t" // 2 nop nop (T = 14) + "nop" "\n\t" // 1 nop (T = 15) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 17) + "rjmp .+0" "\n\t" // 2 nop nop (T = 19) + "dec %[bit]" "\n\t" // 1 bit-- (T = 20) + "breq nextbyte30" "\n\t" // 1-2 if(bit == 0) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22) + "rjmp .+0" "\n\t" // 2 nop nop (T = 24) + "rjmp .+0" "\n\t" // 2 nop nop (T = 26) + "rjmp .+0" "\n\t" // 2 nop nop (T = 28) + "rjmp head30" "\n\t" // 2 -> head30 (next bit out) + "nextbyte30:" "\n\t" // (T = 22) + "nop" "\n\t" // 1 nop (T = 23) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 24) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 26) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 28) + "brne head30" "\n" // 1-2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [hi] "r" (hi), + [lo] "r" (lo), + [ptr] "e" (ptr)); + } +#endif + +// 16 MHz(ish) AVR -------------------------------------------------------- +#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) + +#ifdef NEO_KHZ400 + if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream +#endif + + // WS2811 and WS2812 have different hi/lo duty cycles; this is + // similar but NOT an exact copy of the prior 400-on-8 code. + + // 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL + // ST instructions: ^ ^ ^ (T=0,5,13) + + volatile uint8_t next, bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head20:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 128) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "dec %[bit]" "\n\t" // 1 bit-- (T = 5) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 7) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8) + "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) (from dec above) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10) + "rjmp .+0" "\n\t" // 2 nop nop (T = 12) + "nop" "\n\t" // 1 nop (T = 13) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15) + "nop" "\n\t" // 1 nop (T = 16) + "rjmp .+0" "\n\t" // 2 nop nop (T = 18) + "rjmp head20" "\n\t" // 2 -> head20 (next bit out) + "nextbyte20:" "\n\t" // (T = 10) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15) + "nop" "\n\t" // 1 nop (T = 16) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18) + "brne head20" "\n" // 2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo)); + +#ifdef NEO_KHZ400 + } else { // 400 KHz + + // The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version. + + // 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL + // ST instructions: ^ ^ ^ (T=0,8,20) + + volatile uint8_t next, bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head40:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128) + "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "rjmp .+0" "\n\t" // 2 nop nop (T = 6) + "rjmp .+0" "\n\t" // 2 nop nop (T = 8) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 10) + "rjmp .+0" "\n\t" // 2 nop nop (T = 12) + "rjmp .+0" "\n\t" // 2 nop nop (T = 14) + "rjmp .+0" "\n\t" // 2 nop nop (T = 16) + "rjmp .+0" "\n\t" // 2 nop nop (T = 18) + "rjmp .+0" "\n\t" // 2 nop nop (T = 20) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 22) + "nop" "\n\t" // 1 nop (T = 23) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 24) + "dec %[bit]" "\n\t" // 1 bit-- (T = 25) + "breq nextbyte40" "\n\t" // 1-2 if(bit == 0) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27) + "nop" "\n\t" // 1 nop (T = 28) + "rjmp .+0" "\n\t" // 2 nop nop (T = 30) + "rjmp .+0" "\n\t" // 2 nop nop (T = 32) + "rjmp .+0" "\n\t" // 2 nop nop (T = 34) + "rjmp .+0" "\n\t" // 2 nop nop (T = 36) + "rjmp .+0" "\n\t" // 2 nop nop (T = 38) + "rjmp head40" "\n\t" // 2 -> head40 (next bit out) + "nextbyte40:" "\n\t" // (T = 27) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 28) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 30) + "rjmp .+0" "\n\t" // 2 nop nop (T = 32) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 34) + "rjmp .+0" "\n\t" // 2 nop nop (T = 36) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 38) + "brne head40" "\n" // 1-2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo)); + } +#endif + +#else + #error "CPU SPEED NOT SUPPORTED" +#endif + +#elif defined(__arm__) + +#if defined(__MK20DX128__) || defined(__MK20DX256__) // Teensy 3.0 & 3.1 +#define CYCLES_800_T0H (F_CPU / 4000000) +#define CYCLES_800_T1H (F_CPU / 1250000) +#define CYCLES_800 (F_CPU / 800000) +#define CYCLES_400_T0H (F_CPU / 2000000) +#define CYCLES_400_T1H (F_CPU / 833333) +#define CYCLES_400 (F_CPU / 400000) + + uint8_t *p = pixels, + *end = p + numBytes, pix, mask; + volatile uint8_t *set = portSetRegister(pin), + *clr = portClearRegister(pin); + uint32_t cyc; + + ARM_DEMCR |= ARM_DEMCR_TRCENA; + ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; + +#ifdef NEO_KHZ400 + if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream +#endif + cyc = ARM_DWT_CYCCNT + CYCLES_800; + while(p < end) { + pix = *p++; + for(mask = 0x80; mask; mask >>= 1) { + while(ARM_DWT_CYCCNT - cyc < CYCLES_800); + cyc = ARM_DWT_CYCCNT; + *set = 1; + if(pix & mask) { + while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H); + } else { + while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H); + } + *clr = 1; + } + } + while(ARM_DWT_CYCCNT - cyc < CYCLES_800); +#ifdef NEO_KHZ400 + } else { // 400 kHz bitstream + cyc = ARM_DWT_CYCCNT + CYCLES_400; + while(p < end) { + pix = *p++; + for(mask = 0x80; mask; mask >>= 1) { + while(ARM_DWT_CYCCNT - cyc < CYCLES_400); + cyc = ARM_DWT_CYCCNT; + *set = 1; + if(pix & mask) { + while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H); + } else { + while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H); + } + *clr = 1; + } + } + while(ARM_DWT_CYCCNT - cyc < CYCLES_400); + } +#endif + + + + + +#elif defined(__MKL26Z64__) // Teensy-LC + +#if F_CPU == 48000000 + uint8_t *p = pixels, + pix, count, dly, + bitmask = digitalPinToBitMask(pin); + volatile uint8_t *reg = portSetRegister(pin); + uint32_t num = numBytes; + asm volatile( + "L%=_begin:" "\n\t" + "ldrb %[pix], [%[p], #0]" "\n\t" + "lsl %[pix], #24" "\n\t" + "movs %[count], #7" "\n\t" + "L%=_loop:" "\n\t" + "lsl %[pix], #1" "\n\t" + "bcs L%=_loop_one" "\n\t" + "L%=_loop_zero:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #4" "\n\t" + "L%=_loop_delay_T0H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T0H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #13" "\n\t" + "L%=_loop_delay_T0L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T0L" "\n\t" + "b L%=_next" "\n\t" + "L%=_loop_one:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #13" "\n\t" + "L%=_loop_delay_T1H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T1H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #4" "\n\t" + "L%=_loop_delay_T1L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T1L" "\n\t" + "nop" "\n\t" + "L%=_next:" "\n\t" + "sub %[count], #1" "\n\t" + "bne L%=_loop" "\n\t" + "lsl %[pix], #1" "\n\t" + "bcs L%=_last_one" "\n\t" + "L%=_last_zero:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #4" "\n\t" + "L%=_last_delay_T0H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T0H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #10" "\n\t" + "L%=_last_delay_T0L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T0L" "\n\t" + "b L%=_repeat" "\n\t" + "L%=_last_one:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #13" "\n\t" + "L%=_last_delay_T1H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T1H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #1" "\n\t" + "L%=_last_delay_T1L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T1L" "\n\t" + "nop" "\n\t" + "L%=_repeat:" "\n\t" + "add %[p], #1" "\n\t" + "sub %[num], #1" "\n\t" + "bne L%=_begin" "\n\t" + "L%=_done:" "\n\t" + : [p] "+r" (p), + [pix] "=&r" (pix), + [count] "=&r" (count), + [dly] "=&r" (dly), + [num] "+r" (num) + : [bitmask] "r" (bitmask), + [reg] "r" (reg) + ); +#else +#error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz" +#endif + + +#else // Arduino Due + + #define SCALE VARIANT_MCK / 2UL / 1000000UL + #define INST (2UL * F_CPU / VARIANT_MCK) + #define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST)) + #define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST)) + #define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST)) + #define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST)) + #define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST)) + #define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST)) + + int pinMask, time0, time1, period, t; + Pio *port; + volatile WoReg *portSet, *portClear, *timeValue, *timeReset; + uint8_t *p, *end, pix, mask; + + pmc_set_writeprotect(false); + pmc_enable_periph_clk((uint32_t)TC3_IRQn); + TC_Configure(TC1, 0, + TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1); + TC_Start(TC1, 0); + + pinMask = g_APinDescription[pin].ulPin; // Don't 'optimize' these into + port = g_APinDescription[pin].pPort; // declarations above. Want to + portSet = &(port->PIO_SODR); // burn a few cycles after + portClear = &(port->PIO_CODR); // starting timer to minimize + timeValue = &(TC1->TC_CHANNEL[0].TC_CV); // the initial 'while'. + timeReset = &(TC1->TC_CHANNEL[0].TC_CCR); + p = pixels; + end = p + numBytes; + pix = *p++; + mask = 0x80; + +#ifdef NEO_KHZ400 + if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream +#endif + time0 = TIME_800_0; + time1 = TIME_800_1; + period = PERIOD_800; +#ifdef NEO_KHZ400 + } else { // 400 KHz bitstream + time0 = TIME_400_0; + time1 = TIME_400_1; + period = PERIOD_400; + } +#endif + + for(t = time0;; t = time0) { + if(pix & mask) t = time1; + while(*timeValue < period); + *portSet = pinMask; + *timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG; + while(*timeValue < t); + *portClear = pinMask; + if(!(mask >>= 1)) { // This 'inside-out' loop logic utilizes + if(p >= end) break; // idle time to minimize inter-byte delays. + pix = *p++; + mask = 0x80; + } + } + while(*timeValue < period); // Wait for last bit + TC_Stop(TC1, 0); + +#endif // end Arduino Due + +#endif // end Architecture select + + interrupts(); + endTime = micros(); // Save EOD time for latch on next call +} + +// Set the output pin number +void MitovEmbedded_Adafruit_NeoPixel::setPin(uint8_t p) { + pinMode(pin, INPUT); + pin = p; + pinMode(p, OUTPUT); + digitalWrite(p, LOW); +#ifdef __AVR__ + port = portOutputRegister(digitalPinToPort(p)); + pinMask = digitalPinToBitMask(p); +#endif +} + +// Set pixel color from separate R,G,B components: +void MitovEmbedded_Adafruit_NeoPixel::setPixelColor( + uint16_t n, uint8_t r, uint8_t g, uint8_t b) { + if(n < numLEDs) { + if(brightness) { // See notes in setBrightness() + r = (r * brightness) >> 8; + g = (g * brightness) >> 8; + b = (b * brightness) >> 8; + } + uint8_t *p = &pixels[n * 3]; + p[rOffset] = r; + p[gOffset] = g; + p[bOffset] = b; + } +} + +// Set pixel color from 'packed' 32-bit RGB color: +void MitovEmbedded_Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) { + if(n < numLEDs) { + uint8_t + r = (uint8_t)(c >> 16), + g = (uint8_t)(c >> 8), + b = (uint8_t)c; + if(brightness) { // See notes in setBrightness() + r = (r * brightness) >> 8; + g = (g * brightness) >> 8; + b = (b * brightness) >> 8; + } + uint8_t *p = &pixels[n * 3]; + p[rOffset] = r; + p[gOffset] = g; + p[bOffset] = b; + } +} + +// Convert separate R,G,B into packed 32-bit RGB color. +// Packed format is always RGB, regardless of LED strand color order. +uint32_t MitovEmbedded_Adafruit_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) { + return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; +} + +// Query color from previously-set pixel (returns packed 32-bit RGB value) +uint32_t MitovEmbedded_Adafruit_NeoPixel::getPixelColor(uint16_t n) const { + if(n >= numLEDs) { + // Out of bounds, return no color. + return 0; + } + uint8_t *p = &pixels[n * 3]; + uint32_t c = ((uint32_t)p[rOffset] << 16) | + ((uint32_t)p[gOffset] << 8) | + (uint32_t)p[bOffset]; + // Adjust this back up to the true color, as setting a pixel color will + // scale it back down again. + if(brightness) { // See notes in setBrightness() + //Cast the color to a byte array + uint8_t * c_ptr =reinterpret_cast(&c); + c_ptr[0] = (c_ptr[0] << 8)/brightness; + c_ptr[1] = (c_ptr[1] << 8)/brightness; + c_ptr[2] = (c_ptr[2] << 8)/brightness; + } + return c; // Pixel # is out of bounds +} + +// Returns pointer to pixels[] array. Pixel data is stored in device- +// native format and is not translated here. Application will need to be +// aware whether pixels are RGB vs. GRB and handle colors appropriately. +uint8_t *MitovEmbedded_Adafruit_NeoPixel::getPixels(void) const { + return pixels; +} + +uint16_t MitovEmbedded_Adafruit_NeoPixel::numPixels(void) const { + return numLEDs; +} + +// Adjust output brightness; 0=darkest (off), 255=brightest. This does +// NOT immediately affect what's currently displayed on the LEDs. The +// next call to show() will refresh the LEDs at this level. However, +// this process is potentially "lossy," especially when increasing +// brightness. The tight timing in the WS2811/WS2812 code means there +// aren't enough free cycles to perform this scaling on the fly as data +// is issued. So we make a pass through the existing color data in RAM +// and scale it (subsequent graphics commands also work at this +// brightness level). If there's a significant step up in brightness, +// the limited number of steps (quantization) in the old data will be +// quite visible in the re-scaled version. For a non-destructive +// change, you'll need to re-render the full strip data. C'est la vie. +void MitovEmbedded_Adafruit_NeoPixel::setBrightness(uint8_t b) { + // Stored brightness value is different than what's passed. + // This simplifies the actual scaling math later, allowing a fast + // 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t, + // adding 1 here may (intentionally) roll over...so 0 = max brightness + // (color values are interpreted literally; no scaling), 1 = min + // brightness (off), 255 = just below max brightness. + uint8_t newBrightness = b + 1; + if(newBrightness != brightness) { // Compare against prior value + // Brightness has changed -- re-scale existing data in RAM + uint8_t c, + *ptr = pixels, + oldBrightness = brightness - 1; // De-wrap old brightness value + uint16_t scale; + if(oldBrightness == 0) scale = 0; // Avoid /0 + else if(b == 255) scale = 65535 / oldBrightness; + else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; + for(uint16_t i=0; i> 8; + } + brightness = newBrightness; + } +} + +//Return the brightness value +uint8_t MitovEmbedded_Adafruit_NeoPixel::getBrightness(void) const { + return brightness - 1; +} + +void MitovEmbedded_Adafruit_NeoPixel::clear() { + memset(pixels, 0, numBytes); +} + +#endif // ADAFRUIT_NEOPIXEL_H diff --git a/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/README.md b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/README.md new file mode 100644 index 0000000..2eeda47 --- /dev/null +++ b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/README.md @@ -0,0 +1,12 @@ +Adafruit NeoPixel library +========================= + +Arduino library for controlling single-wire-based LED pixels and strip such as the [Adafruit 60 LED/meter Digital LED strip][strip], the [Adafruit FLORA RGB Smart Pixel][flora], the [Adafruit Breadboard-friendly RGB Smart Pixel][pixel], the [Adafruit NeoPixel Stick][stick], and the [Adafruit NeoPixel Shield][shield]. + +After downloading, rename folder to 'Adafruit_NeoPixel' and install in Arduino Libraries folder. Restart Arduino IDE, then open File->Sketchbook->Library->Adafruit_NeoPixel->strandtest sketch. + +[flora]: http://adafruit.com/products/1060 +[strip]: http://adafruit.com/products/1138 +[pixel]: http://adafruit.com/products/1312 +[stick]: http://adafruit.com/products/1426 +[shield]: http://adafruit.com/products/1430 diff --git a/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/keywords.txt b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/keywords.txt new file mode 100644 index 0000000..76f9446 --- /dev/null +++ b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/keywords.txt @@ -0,0 +1,29 @@ +####################################### +# Syntax Coloring Map For Adafruit_NeoPixel +####################################### +# Class +####################################### + +Adafruit_NeoPixel KEYWORD1 + +####################################### +# Methods and Functions +####################################### + +setPixelColor KEYWORD2 +setPin KEYWORD2 +setBrightness KEYWORD2 +numPixels KEYWORD2 +getPixelColor KEYWORD2 +Color KEYWORD2 + +####################################### +# Constants +####################################### + +NEO_GRB LITERAL1 +NEO_COLMASK LITERAL1 +NEO_KHZ800 LITERAL1 +NEO_SPDMASK LITERAL1 +NEO_RGB LITERAL1 +NEO_KHZ400 LITERAL1 diff --git a/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/library.properties b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/library.properties new file mode 100644 index 0000000..77a8832 --- /dev/null +++ b/libraries/Mitov/MitovEmbedded_Adafruit_NeoPixel/library.properties @@ -0,0 +1,9 @@ +name=Adafruit NeoPixel +version=1.0 +author=Adafruit +maintainer=Adafruit +sentence=Arduino library for controlling single-wire-based LED pixels and strip. +paragraph=Arduino library for controlling single-wire-based LED pixels and strip. +category=Display +url=https://github.com/adafruit/Adafruit_NeoPixel +architectures=* diff --git a/libraries/Mitov/Mitov_7Segment.h b/libraries/Mitov/Mitov_7Segment.h new file mode 100644 index 0000000..9229772 --- /dev/null +++ b/libraries/Mitov/Mitov_7Segment.h @@ -0,0 +1,367 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_7SEGMENT_h +#define _MITOV_7SEGMENT_h + +#include +#include + +namespace Mitov +{ + const byte C_Segments[16] = + { + 0b0111111, // = 0 + 0b0000110, // = 1 + 0b1011011, // = 2 + 0b1001111, // = 3 + 0b1100110, // = 4 + 0b1101101, // = 5 + 0b1111101, // = 6 + 0b0000111, // = 7 + 0b1111111, // = 8 + 0b1101111, // = 9 + 0b1110111, // = A + 0b1111100, // = B + 0b1011000, // = C + 0b1011110, // = D + 0b1111001, // = E + 0b1110001 // = F + }; +//--------------------------------------------------------------------------- + template class DisplayBasic7Segment : public Mitov::BasicDisplay + { + typedef Mitov::BasicDisplay inherited; + + public: + Mitov::SimpleList SegmentPins; + + public: + bool InvertedSegments; + + public: + DisplayBasic7Segment() : + InvertedSegments( false ) + { + SegmentPins.SetCount(16); + } + + }; +//--------------------------------------------------------------------------- + class Display7Segment : public Mitov::DisplayBasic7Segment + { + typedef Mitov::DisplayBasic7Segment inherited; + + protected: + virtual void DoReceive( void *_Data ) + { + inherited::DoReceive( _Data ); + UpdateDisplay(); + } + + virtual void UpdateDisplay() + { + int AValue = (Enabled) ? C_Segments[ FValue & 0xF ] : 0; + for( int i = 0; i < 16; ++i ) + { + bool ABitValue = AValue & 1; + ABitValue ^= InvertedSegments; + SegmentPins[ i ].Notify( &ABitValue ); + AValue >>= 1; + } + } + + }; +//--------------------------------------------------------------------------- + template class DisplayBasicDynamic7Segment : public Mitov::DisplayBasic7Segment + { + typedef Mitov::DisplayBasic7Segment inherited; + + public: + Mitov::SimpleList DigitPins; + + public: + unsigned long RefreshInterval = 1000; + bool InvertedDigits = false; + + protected: + unsigned long FLastTime = 0; + int FDigit = 0; + + protected: + virtual int GetSegmentsValue() = 0; + + virtual void UpdateDisplay() + { + int AValue; + if( inherited::Enabled ) + AValue = GetSegmentsValue(); + + else + AValue = 0; + + for( int i = 0; i < DigitPins.size(); ++i ) + { + bool ABitValue = false; + ABitValue ^= InvertedDigits; + DigitPins[ i ].Notify( &ABitValue ); + } + + for( int i = 0; i < 16; ++i ) + { + bool ABitValue = AValue & 1; + ABitValue ^= inherited::InvertedSegments; + inherited::SegmentPins[ i ].Notify( &ABitValue ); + AValue >>= 1; + } + + AValue = FDigit; + for( int i = 0; i < DigitPins.size(); ++i ) + { + bool ABitValue = ( AValue-- == 0 ); + ABitValue ^= InvertedDigits; + DigitPins[ i ].Notify( &ABitValue ); + } + } + + public: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ( currentMicros - FLastTime ) < RefreshInterval ) + return; + + ++FDigit; + + if( FDigit >= DigitPins.size() ) + FDigit = 0; + + FLastTime = currentMicros; + UpdateDisplay(); + } + + }; +//--------------------------------------------------------------------------- + class DisplayIntegerDynamic7Segment : public Mitov::DisplayBasicDynamic7Segment + { + typedef Mitov::DisplayBasicDynamic7Segment inherited; + + public: + bool LeadingZeroes = false; + + protected: + Mitov::SimpleList FPowers; + long FMaxValue; // The biggest possible to display value + long FMinValue; // The smallest possible to display value + + protected: + virtual int GetSegmentsValue() + { + int AValue; + if( FValue > FMaxValue ) + AValue = 0b0000001; + + else if( FValue < FMinValue ) + AValue = 0b0001000; + + else + { + AValue = ( (int)abs( FValue ) ) / FPowers[ FDigit ]; + if( ( FValue < 0 ) && ( FDigit > 0 )) + { + if( ( !LeadingZeroes ) && ( AValue == 0 ) ) + { + int APreviousValue = ( -FValue ) / FPowers[ FDigit - 1 ]; + if( APreviousValue > 0 ) + AValue = 0b1000000; + + else + AValue = 0; + + } + else + { + if( FDigit == DigitPins.size() - 1 ) + AValue = 0b1000000; + + else + { + int ADigitValue = AValue % 10; + AValue = C_Segments[ ADigitValue ]; + } + } + } + else + { + if( ( !LeadingZeroes ) && ( AValue == 0 ) ) + AValue = 0; + + else + { + int ADigitValue = AValue % 10; + AValue = C_Segments[ ADigitValue ]; + } + } + } + + return AValue; + } + + virtual void SystemInit() + { + FPowers.SetCount( DigitPins.size() ); + for( int i = 0; i < DigitPins.size(); ++i ) + FPowers[ i ] = pow( 10, i ) + 0.5; + + FMaxValue = pow( 10, DigitPins.size() ) + 0.5 - 1; + FMinValue = -( pow( 10, DigitPins.size() - 1 ) + 0.5 - 1 ); + + inherited::SystemInit(); + } + + }; +//--------------------------------------------------------------------------- + class DisplayAnalogDynamic7Segment : public Mitov::DisplayBasicDynamic7Segment + { + typedef Mitov::DisplayBasicDynamic7Segment inherited; + + public: + unsigned char Precision = 2; + + protected: + char *FBuffer; + char *FStartChar; + unsigned char FTextLength; + unsigned char FFirstPos; + + char FDecimalPointPos; + + protected: + virtual int GetSegmentsValue() + { + int AValue; + int ANumDigits = DigitPins.size(); + if( ! FStartChar ) + { + FStartChar = dtostrf( FValue, 1, Precision, FBuffer ); +// Serial.println( FStartChar ); + String AText( FStartChar ); + FTextLength = AText.length(); // strlen( FStartChar ); +// FTextLength = strlen( FStartChar ); +// Serial.println( FTextLength ); + FDecimalPointPos = AText.indexOf( '.' ); + if( Precision == 0 ) + { + if( FTextLength <= ANumDigits ) + FFirstPos = FTextLength - 1; + + else + FFirstPos = ANumDigits - 1; + + +// Serial.println( FStartChar ); +// Serial.println( FTextLength ); +// Serial.println( FFirstPos ); +// Serial.println( FDecimalPointPos ); + } + + else + { + if( FTextLength <= ANumDigits + 1 ) + FFirstPos = FTextLength - 1; + + else + FFirstPos = ANumDigits + 1 - 1; + } + +// Serial.println( FFirstPos ); + } + + int ACorrectedTextLength = FTextLength; + if( Precision > 0 ) + --ACorrectedTextLength; + + if( ( ACorrectedTextLength - Precision ) > ANumDigits ) + { + if( FValue > 0 ) + AValue = 0b0000001; // Overflow + + + else + AValue = 0b0001000; // Overflow - + } + + else + { + int ATextPos = FFirstPos - FDigit; + if( ATextPos < 0 ) + AValue = 0; + + else + { + if( ATextPos < 0 ) + return( 0 ); + + bool ADecimalPoint = ( FStartChar[ ATextPos ] == '.' ); + if( ATextPos <= FDecimalPointPos ) + --ATextPos; + +// if( ADecimalPoint ) +// --ATextPos; + + if( ATextPos < 0 ) + return( 0 ); + +/* + if( FDigit == 0 ) + { + Serial.println( FStartChar ); + Serial.println( ATextPos ); + } +*/ + if( FStartChar[ ATextPos ] == '-' ) + AValue = 0b1000000; + + else + { + AValue = FStartChar[ ATextPos ] - '0'; + AValue = C_Segments[ AValue ]; + } + + if( ADecimalPoint ) + AValue |= 0x80; + + } + } + + return AValue; + } + + virtual void DoReceive( void *_Data ) + { + FStartChar = NULL; + inherited::DoReceive( _Data ); + } + + public: + virtual void SystemInit() + { + FBuffer = new char[ 15 + Precision ]; + inherited::SystemInit(); + } + +/* + virtual ~DisplayAnalogDynamic7Segment() + { + delete [] FBuffer; + } +*/ + }; + +} + +#endif diff --git a/libraries/Mitov/Mitov_Accelerometer.h b/libraries/Mitov/Mitov_Accelerometer.h new file mode 100644 index 0000000..0aa15a9 --- /dev/null +++ b/libraries/Mitov/Mitov_Accelerometer.h @@ -0,0 +1,94 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_ACCELEROMETER_h +#define _MITOV_ACCELEROMETER_h + +#include + +namespace Mitov +{ + class Memsic2125Accelerometer : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SinkPin XInputPin; + OpenWire::SinkPin YInputPin; + + OpenWire::SourcePin XOutputPin; + OpenWire::SourcePin YOutputPin; + + public: + bool Enabled = true; + + protected: + class DataSet : public OpenWire::Object + { + protected: + OpenWire::SourcePin *FOutputPin; + + unsigned long FStartTime; + bool FOldValue; + const Memsic2125Accelerometer *FOwner; + + public: + virtual void DoReceive( void *_Data ) + { + if( ! FOwner->Enabled ) + return; + + bool AValue = *(bool *)_Data; + if( FOldValue == AValue ) + return; + + unsigned long ANow = micros(); + FOldValue = AValue; + if( AValue ) + { + FStartTime = ANow; + return; + } + + long APeriod = ANow - FStartTime; + + if( APeriod == 0 ) + APeriod = 1; + + float AAcceleration = (( APeriod / 10 ) - 500) * 8; + + FOutputPin->Notify( &AAcceleration ); + } + + public: + DataSet( const Memsic2125Accelerometer *AOwner, OpenWire::SinkPin *AInputPin, OpenWire::SourcePin *AOutputPin ) : + FOwner( AOwner ), + FOutputPin( AOutputPin ), + FOldValue( false ), + FStartTime( 0 ) + { + AInputPin->SetCallback( this, (OpenWire::TOnPinReceive)&DataSet::DoReceive ); + } + }; + + + protected: + DataSet FXDataSet; + DataSet FYDataSet; + + public: + Memsic2125Accelerometer() : + FXDataSet( this, &XInputPin, &XOutputPin ), + FYDataSet( this, &YInputPin, &YOutputPin ) + { + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_AmplitudeMeter.h b/libraries/Mitov/Mitov_AmplitudeMeter.h new file mode 100644 index 0000000..9db3aa9 --- /dev/null +++ b/libraries/Mitov/Mitov_AmplitudeMeter.h @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_AMPLITUDE_METER_h +#define _MITOV_AMPLITUDE_METER_h + +#include + +namespace Mitov +{ + const float FLT_MAX = 3.4028235E+38; + + class AmplitudeMeter : public Mitov::CommonEnableFilter + { + typedef Mitov::CommonEnableFilter inherited; + + public: + OpenWire::SourcePin MinOutputPin; + OpenWire::SourcePin MaxOutputPin; + + protected: + unsigned long FStartTime = 0; + double FAccumulator = 0.0f; + float FMin = 0; + float FMax = 0; + unsigned long FCount = 0; + + public: + long Period = 100; + + protected: + virtual void DoReceive( void *_Data ) + { + if( ! Enabled ) + return; + + float AValue = *(float *)_Data; + FAccumulator += AValue; + if( FCount == 0 ) + { + FMin = AValue; + FMax = AValue; + } + + else + { + if( AValue < FMin ) + FMin = AValue; + + if( AValue > FMax ) + FMax = AValue; + + } + + ++FCount; + + unsigned long ANow = micros(); + unsigned long APeriod = ANow - FStartTime; + + if( APeriod < ((unsigned long)Period) * 1000 ) + return; + + FStartTime = ANow; + if( FCount == 0 ) + --FCount; + + float AAverage = FAccumulator / FCount; + FAccumulator = 0; + FCount = 0; + + OutputPin.Notify( &AAverage ); + MinOutputPin.Notify( &FMin ); + MaxOutputPin.Notify( &FMax ); + } + + virtual void SystemInit() + { + FAccumulator = 0; + FCount = 0; + + inherited::SystemInit(); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Arduino_SPI.h b/libraries/Mitov/Mitov_Arduino_SPI.h new file mode 100644 index 0000000..ee62996 --- /dev/null +++ b/libraries/Mitov/Mitov_Arduino_SPI.h @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_ARDUINO_SPI_h +#define _MITOV_ARDUINO_SPI_h + +#include +#include + +namespace Mitov +{ + class ArduinoSPI : public Mitov::BasicSPI + { + typedef Mitov::BasicSPI inherited; + + public: + virtual uint16_t transfer16(uint16_t data) + { + return SPI.transfer16( data ); + } + + virtual uint8_t transfer(uint8_t data) + { + return SPI.transfer( data ); + } + + virtual void transfer(void *buf, size_t count) + { + SPI.transfer( buf, count ); + } + + virtual void beginTransaction(SPISettings settings) + { + SPI.beginTransaction( settings ); + } + + virtual void endTransaction() + { + SPI.endTransaction(); + } + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + SPI.begin(); + } + }; +//--------------------------------------------------------------------------- +} +#endif diff --git a/libraries/Mitov/Mitov_BMP180_Pressure.h b/libraries/Mitov/Mitov_BMP180_Pressure.h new file mode 100644 index 0000000..129229f --- /dev/null +++ b/libraries/Mitov/Mitov_BMP180_Pressure.h @@ -0,0 +1,369 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BMP180_h +#define _MITOV_BMP180_h + +#include +#include //I2C Arduino Library + +namespace Mitov +{ + + const byte BMP180_Address = 0x77; // 7-bit address + const byte BMP180_REG_CONTROL = 0xF4; + const byte BMP180_REG_RESULT = 0xF6; + + const byte BMP180_COMMAND_TEMPERATURE = 0x2E; + const byte BMP180_COMMAND_PRESSURE0 = 0x34; + const byte BMP180_COMMAND_PRESSURE1 = 0x74; + const byte BMP180_COMMAND_PRESSURE2 = 0xB4; + const byte BMP180_COMMAND_PRESSURE3 = 0xF4; +//--------------------------------------------------------------------------- + enum BMP180_PressureResolution { prLow, prStandard, prHigh, prHighest }; +//--------------------------------------------------------------------------- + class BMP180_Pressure : public EnabledComponent, public Mitov::ClockingSupport + { + typedef Mitov::EnabledComponent inherited; + + public: + OpenWire::SourcePin PressureOutputPin; + OpenWire::SourcePin TemperatureOutputPin; + OpenWire::TypedSourcePin ErrorOutputPin; + + protected: + enum TState { stCoeff, stIdle, stTemperature, stPressure }; + + public: + BMP180_PressureResolution Resolution : 2; + bool InFahrenheit : 1; + + protected: + bool FClocked : 1; + TState FState : 2; + + uint32_t FStartTime; + uint32_t FInterval; + + int16_t AC1,AC2,AC3,VB1,VB2,MB,MC,MD; + uint16_t AC4,AC5,AC6; + double c5,c6,mc,md,x0,x1,x2,y0,y1,y2,p0,p1,p2; + float T; + + protected: + bool WriteBytes( byte *values, char length ) + { + Wire.beginTransmission( BMP180_Address ); + Wire.write(values,length); + bool AError = ( Wire.endTransmission() != 0 ); + ErrorOutputPin.SetValue( AError, true ); + + return ( ! AError ); + } + + bool ReadBytes( byte *values, byte length ) + { + Wire.beginTransmission( BMP180_Address ); + Wire.write(values[0]); + bool AError = ( Wire.endTransmission() != 0 ); +// Serial.println( AError ); + ErrorOutputPin.SetValue( AError, true ); + if ( ! AError ) + { +// Serial.println( "READ" ); + Wire.requestFrom( BMP180_Address, length ); + while(Wire.available() != length) ; // wait until bytes are ready + + while( length-- ) + *values++ = Wire.read(); + +/* + values += length; + while( length-- ) + *--values = Wire.read(); +*/ + } + + return ( ! AError ); + } + + uint32_t ReadBytes( byte length ) + { +/* + union T24BitData + { + uint8_t Bytes[ 4 ]; + uint32_t Value; + }; + + T24BitData AData; + AData.Value = 0; + + ReadBytes( AData.Bytes + 3 - length, length ); + + return AData.Value; +*/ + uint8_t ABytes[ 4 ]; + ABytes[0] = BMP180_REG_RESULT; + + ReadBytes( ABytes, length ); + + uint32_t AValue = 0; + for( int i = 0; i < length; ++i ) + { + AValue <<= 8; + AValue |= ABytes[ i ]; + } + + return AValue; + } + + void StartReading( byte AType, TState AState, uint32_t AInterval ) + { + byte data[ 2 ] = + { + BMP180_REG_CONTROL + }; + + data[ 1 ] = AType; + +// Serial.println( "StartReading" ); + if( WriteBytes(data, 2)) + { +// Serial.println( "STATE" ); + + FState = AState; + FInterval = AInterval; + FStartTime = millis(); + } + } + + bool ReadUnsignedInt(char address, uint16_t &value) + { + unsigned char data[2]; + + data[0] = address; + if (ReadBytes(data,2)) + { + value = (((uint16_t)data[0]<<8)|(uint16_t)data[1]); + return( true ); + } + + value = 0; + return( false ); + } + + bool ReadInt(char address, int16_t &value) + { + return ReadUnsignedInt( address, *(uint16_t *)&value ); + } + + void StartReadingTemp() + { + if( FState == stCoeff ) + { +// Serial.println( "TEST0" ); + if( ! + ( + ReadInt(0xAA,AC1) && + ReadInt(0xAC,AC2) && + ReadInt(0xAE,AC3) && + ReadUnsignedInt(0xB0,AC4) && + ReadUnsignedInt(0xB2,AC5) && + ReadUnsignedInt(0xB4,AC6) && + ReadInt(0xB6,VB1) && + ReadInt(0xB8,VB2) && + ReadInt(0xBA,MB) && + ReadInt(0xBC,MC) && + ReadInt(0xBE,MD) + ) + ) + return; + + // All reads completed successfully! + + // If you need to check your math using known numbers, + // you can uncomment one of these examples. + // (The correct results are commented in the below functions.) + + // Example from Bosch datasheet + // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153; + // B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868; + + // Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf + // AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974; + // VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432; + + // Compute floating-point polynominals: + + double c3 = 160.0 * pow(2,-15) * AC3; + double c4 = pow(10,-3) * pow(2,-15) * AC4; + double b1 = pow(160,2) * pow(2,-30) * VB1; + c5 = (pow(2,-15) / 160) * AC5; + c6 = AC6; + mc = (pow(2,11) / pow(160,2)) * MC; + md = MD / 160.0; + x0 = AC1; + x1 = 160.0 * pow(2,-13) * AC2; + x2 = pow(160,2) * pow(2,-25) * VB2; + y0 = c4 * pow(2,15); + y1 = c4 * c3; + y2 = c4 * b1; + p0 = (3791.0 - 8.0) / 1600.0; + p1 = 1.0 - 7357.0 * pow(2,-20); + p2 = 3038.0 * 100.0 * pow(2,-36); + +// Serial.println( "TEST1" ); + FState = stIdle; + } + + StartReading( BMP180_COMMAND_TEMPERATURE, stTemperature, 5 ); + } + + void StartReadingPressure() + { + switch( Resolution ) + { + case prLow: StartReading( BMP180_COMMAND_PRESSURE0, stPressure, 5 ); break; + case prStandard: StartReading( BMP180_COMMAND_PRESSURE1, stPressure, 8 ); break; + case prHigh: StartReading( BMP180_COMMAND_PRESSURE2, stPressure, 14 ); break; + case prHighest: StartReading( BMP180_COMMAND_PRESSURE3, stPressure, 26 ); break; + } + } + + bool IsIdle() { return (( FState == stCoeff ) || ( FState == stIdle )); } + + protected: + virtual void DoClockReceive( void *_Data ) override + { + if( IsIdle() ) + StartReadingTemp(); + + else + FClocked = true; + } + + protected: + virtual void SystemStart() + { + if( Enabled ) + if( ! ClockInputPin.IsConnected() ) + StartReadingTemp(); + + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! Enabled ) + { + if( ! IsIdle() ) + if( FState == stTemperature ) + ReadBytes( 2 ); + + else + ReadBytes( 3 ); + + FState = stIdle; + } + + else + { + if( IsIdle() ) + { + if( FClocked || ( ! ClockInputPin.IsConnected() )) + StartReadingTemp(); + } + + else + { + unsigned long ACurrentMillis = millis(); +// Serial.println( "TEST2" ); + if( ACurrentMillis - FStartTime >= FInterval ) + if( FState == stTemperature ) + { + float tu = ReadBytes( 2 ); +// Serial.print( "T1: " ); Serial.println( tu ); + //example from Bosch datasheet + //tu = 27898; + + //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf + //tu = 0x69EC; + + float a = c5 * (tu - c6); + T = a + (mc / (a + md)); + + if( InFahrenheit ) + T = T * ( 9.0/5.0 ) + 32.0; + + TemperatureOutputPin.Notify( &T ); + StartReadingPressure(); + } + + else + { + float pu = ReadBytes( 3 ); +// Serial.print( "P1: " ); Serial.println( pu ); + pu /= 256.0; +// pu = (data[0] * 256.0) + data[1] + (data[2]/256.0); + + //example from Bosch datasheet + //pu = 23843; + + //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf, pu = 0x982FC0; + //pu = (0x98 * 256.0) + 0x2F + (0xC0/256.0); + + float s = T - 25.0; + float x = (x2 * pow(s,2)) + (x1 * s) + x0; + float y = (y2 * pow(s,2)) + (y1 * s) + y0; + float z = (pu - x) / y; + float P = (p2 * pow(z,2)) + (p1 * z) + p0; + + PressureOutputPin.Notify( &P ); + +// Serial.println( "VVVVVV" ); + if( ClockInputPin.IsConnected() ) + { +// Serial.println( "PPPPP" ); + FState = stIdle; + if( FClocked ) + { +// Serial.println( "TTTTTTT" ); + FClocked = false; + StartReadingTemp(); + } + } + + else + StartReadingTemp(); + } + + } + } + +/* + if( ! Enabled ) + if( FClocked || ( ! ClockInputPin.IsConnected() )) + ReadCompass(); +*/ + inherited::SystemLoopBegin( currentMicros ); + } + + public: + BMP180_Pressure() : + FClocked( false ), + Resolution( prStandard ), + FState( stCoeff ), + InFahrenheit( false ) + { + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_BasicDisplay.h b/libraries/Mitov/Mitov_BasicDisplay.h new file mode 100644 index 0000000..180c595 --- /dev/null +++ b/libraries/Mitov/Mitov_BasicDisplay.h @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BASIC_DISPLAY_h +#define _MITOV_BASIC_DISPLAY_h + +#include + +namespace Mitov +{ + template class BasicDisplay : public Mitov::CommonSink + { + typedef OpenWire::Component inherited; + + protected: + T FValue; + + public: + bool Enabled = true; + T InitialValue = 0; + + protected: + virtual void UpdateDisplay() = 0; + + protected: + virtual void DoReceive( void *_Data ) + { + FValue = *(T*)_Data; + } + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateDisplay(); + } + + void SetInitialValue( T AValue ) + { + if( InitialValue == AValue ) + return; + + InitialValue = AValue; + UpdateDisplay(); + } + + protected: + virtual void SystemInit() + { + FValue = InitialValue; + inherited::SystemInit(); + UpdateDisplay(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_BasicEthernet.h b/libraries/Mitov/Mitov_BasicEthernet.h new file mode 100644 index 0000000..5006c12 --- /dev/null +++ b/libraries/Mitov/Mitov_BasicEthernet.h @@ -0,0 +1,655 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BASIC_ETHERNET_h +#define _MITOV_BASIC_ETHERNET_h + +#include +//#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class TMACAddress + { + public: + byte FMacAddress[6]; + + public: + TMACAddress( + uint8_t mac_0, + uint8_t mac_1, + uint8_t mac_2, + uint8_t mac_3, + uint8_t mac_4, + uint8_t mac_5 ) + { + FMacAddress[ 0 ] = mac_0; + FMacAddress[ 1 ] = mac_1; + FMacAddress[ 2 ] = mac_2; + FMacAddress[ 3 ] = mac_3; + FMacAddress[ 4 ] = mac_4; + FMacAddress[ 5 ] = mac_5; + } + + TMACAddress() + { + memset( FMacAddress, 0, sizeof( FMacAddress ) ); + } + }; +//--------------------------------------------------------------------------- + inline String MACAdressToString( uint8_t *AMACAddress ) + { + char AMACString[ 6 * 3 + 1 ]; + sprintf( AMACString, "%02X-%02X-%02X-%02X-%02X-%02X", AMACString[ 0 ], AMACString[ 1 ], AMACString[ 2 ], AMACString[ 3 ], AMACString[ 4 ], AMACString[ 5 ] ); + return AMACString; +// MACOutputPin.Notify( AMACString ); + } +//--------------------------------------------------------------------------- + inline String IPAdressToString( ::IPAddress AIPAddress ) + { + char AIPString[ 4 * 4 + 1 ]; + sprintf( AIPString, "%u.%u.%u.%u", AIPAddress[ 0 ], AIPAddress[ 1 ], AIPAddress[ 2 ], AIPAddress[ 3 ] ); + return AIPString; + } +//--------------------------------------------------------------------------- + class BasicShieldIPAddress + { + public: + bool Enabled = false; + ::IPAddress IP; + + }; +//--------------------------------------------------------------------------- + class ShieldGatewayAddress : public BasicShieldIPAddress + { + public: + BasicShieldIPAddress Subnet; + }; +//--------------------------------------------------------------------------- + class ShieldDNSAddress : public BasicShieldIPAddress + { + public: + ShieldGatewayAddress Gateway; + }; +//--------------------------------------------------------------------------- + class ShieldIPAddress : public BasicShieldIPAddress + { + public: + ShieldDNSAddress DNS; + }; +//--------------------------------------------------------------------------- + class ShieldIPDNS2Address : public ShieldIPAddress + { + public: + BasicShieldIPAddress DNS2; + }; +//--------------------------------------------------------------------------- + class BasicSocket : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: +// OpenWire::SinkPin InputPin; + OpenWire::SourcePin OutputPin; + + public: + bool Enabled = true; + unsigned int Port = 80; + + protected: + virtual void StartSocket() = 0; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( IsEnabled() ) + StartSocket(); + + else + StopSocket(); + + } + + public: + virtual bool IsEnabled() + { + return Enabled; + } + + virtual bool CanSend() + { + return Enabled; + } + + virtual void BeginPacket() + { + } + + virtual void EndPacket() + { + } + + virtual void StopSocket() = 0; + + public: + virtual void SystemStart() + { +// Serial.println( Enabled ); + if( Enabled ) + StartSocket(); + + inherited::SystemStart(); + } + + }; +//--------------------------------------------------------------------------- + template class BasicEthernetSocket : public Mitov::BasicSocket + { + typedef Mitov::BasicSocket inherited; + + protected: + T_OWNER &FOwner; + + public: + virtual bool IsEnabled() + { + return Enabled && FOwner.Enabled; + } + + virtual bool CanSend() + { + return Enabled && FOwner.Enabled; + } + + virtual Print *GetPrint() = 0; + + public: + BasicEthernetSocket( T_OWNER &AOwner ) : + FOwner( AOwner ) + { + AOwner.Sockets.push_back( this ); + } + + }; +//--------------------------------------------------------------------------- + template class BasicEthernetConnectSocket : public Mitov::BasicEthernetSocket + { + typedef Mitov::BasicEthernetSocket inherited; + + public: + OpenWire::TypedSourcePin ConnectedOutputPin; + + OpenWire::SinkPin FlushInputPin; + OpenWire::SinkPin DisconnectInputPin; + + protected: + T_CLIENT FClient; + + protected: + void DoDisconnect( void *_Data ) + { + FClient.flush(); + FClient.stop(); + ConnectedOutputPin.SetValue( false, true ); +// Serial.println( "DoDisconnect" ); +// Serial.println( FClient.connected() ); + } + + void DoFlush( void *_Data ) + { + FClient.flush(); + } + + public: + virtual Print *GetPrint() + { + return &FClient; + } + + public: + virtual void SystemInit() + { + ConnectedOutputPin.SetValue( false, false ); + inherited::SystemInit(); + } + + public: + BasicEthernetConnectSocket( T_OWNER &AOwner ) : + inherited( AOwner ) + { + FlushInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicEthernetConnectSocket::DoFlush ); + + DisconnectInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicEthernetConnectSocket::DoDisconnect ); + } + + }; +//--------------------------------------------------------------------------- + template class TCPClientSocket : public BasicEthernetConnectSocket + { + typedef BasicEthernetConnectSocket inherited; + + public: + String URL; + ::IPAddress IPAddress; + + protected: + virtual void StartSocket() + { +// Serial.println( "StartSocket" ); + if( URL.length() ) + inherited::FClient.connect( URL.c_str(), inherited::Port ); + + else + { +// IPAddress.printTo( Serial ); + inherited::FClient.connect( IPAddress, inherited::Port ); + } + } + + virtual void StopSocket() + { + inherited::FClient.flush(); + inherited::FClient.stop(); + inherited::ConnectedOutputPin.SetValue( false, true ); + } + + public: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if ( inherited::FClient.available() ) + { + unsigned char AByte = inherited::FClient.read(); + inherited::OutputPin.SendValue( Mitov::TDataBlock( 1, &AByte )); +// inherited::OutputPin.Notify( &AByte ); + } + + inherited::ConnectedOutputPin.SetValue( inherited::FClient.connected(), true ); + + if (! inherited::FClient.connected()) + { + inherited::FClient.stop(); // Do we need this? + inherited::ConnectedOutputPin.SetValue( false, true ); + } + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + TCPClientSocket( T_OWNER &AOwner, ::IPAddress AIPAddress ) : + inherited( AOwner ), + IPAddress( AIPAddress ) + { + } + }; +//--------------------------------------------------------------------------- + template class TCPServerSocket : public BasicEthernetConnectSocket + { + typedef BasicEthernetConnectSocket inherited; + + protected: + T_SERVER *FServer; + + protected: + virtual void StartSocket() + { +// Serial.println( "StartSockect" ); + if( FServer ) + return; + +// Serial.println( Port ); + FServer = new T_SERVER( inherited::Port ); + FServer->begin(); +// Serial.println( "Start Server Sockect" ); +// Serial.println( inherited::Port ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( FServer ) + { + if( ! inherited::FClient ) + { +// Serial.println( inherited::Port ); +// Serial.println( "TRY CLIENT" ); + inherited::FClient = FServer->available(); + +// if( inherited::FClient ) +// Serial.println( "CLIENT" ); + +// Serial.println( "TRY CLIENT OUT" ); + } + +/* + if( inherited::FClient ) + if (! inherited::FClient.connected()) + { + Serial.println( "STOP" ); + inherited::FClient.stop(); // Do we need this? + } +*/ + if( inherited::FClient ) + { +// Serial.println( "CLIENT" ); + if( inherited::FClient.available() ) + { + unsigned char AByte = inherited::FClient.read(); +// Serial.println( "RECEIVED" ); + inherited::OutputPin.SendValue( Mitov::TDataBlock( 1, &AByte )); +// inherited::OutputPin.Notify( &AByte ); + } + + if( ! inherited::FClient.connected() ) + { +// Serial.println( "STOP" ); + inherited::FClient.stop(); // Do we need this? + inherited::ConnectedOutputPin.SetValue( false, true ); + } + } + } + +// Serial.println( inherited::FClient.connected() ); + + inherited::ConnectedOutputPin.SetValue( inherited::FClient.connected(), true ); +// Serial.println( "SYSTEM_LOOP" ); + inherited::SystemLoopBegin( currentMicros ); +// Serial.println( "SYSTEM_LOOP_OUT" ); + } + + public: + virtual bool CanSend() + { + return inherited::Enabled && inherited::FOwner.Enabled && inherited::FClient; + } + + virtual void StopSocket() + { + if( FServer ) + { + delete FServer; + FServer = NULL; + } + } + +/* + virtual void EndPacket() + { + Serial.println( "EndPacket" ); +// inherited::FClient.flush(); +// delay(1000); +// inherited::FClient.stop(); + } +*/ + public: + TCPServerSocket( T_OWNER &AOwner ) : + inherited( AOwner ), + FServer( NULL ) + { + } + +/* + virtual ~TCPServerSocket() + { + if( FServer ) + delete FServer; + } +*/ + }; +//--------------------------------------------------------------------------- + template class UDPSocket : public BasicEthernetSocket + { + typedef BasicEthernetSocket inherited; + + public: + OpenWire::SourcePin RemoteIPOutputPin; + OpenWire::SourcePin RemotePortOutputPin; + + public: + unsigned int RemotePort = 80; + ::IPAddress RemoteIPAddress; + + protected: + T_UDP FSocket; + String FHostName; + bool FResolved; + + public: + virtual bool CanSend() + { + return FResolved && inherited::CanSend(); + } + + protected: + virtual void StartSocket() + { + if( FHostName != "" ) + { +// Serial.println( "TEST1" ); + FResolved = inherited::FOwner.GetIPFromHostName( FHostName, RemoteIPAddress ); + } + +// Serial.print( "StartSocket: " ); +// Serial.println( inherited::Port ); + FSocket.begin( inherited::Port ); + } + + public: + virtual void BeginPacket() + { +// Serial.print( "BeginPacket: " ); +// Serial.print( RemoteIPAddress ); +// Serial.print( " " ); +// Serial.println( RemotePort ); + FSocket.beginPacket( RemoteIPAddress, RemotePort ); +//// FSocket.beginPacket( RemoteIPAddress, 8888 ); +// FSocket.println( "Hello1" ); +//// FSocket.endPacket(); + } + + virtual void EndPacket() + { +// Serial.println( "EndPacket" ); +// FSocket.println( "Hello" ); + FSocket.endPacket(); +// delay( 1000 ); + } + + virtual void StopSocket() + { +// Serial.println( "StopSocket" ); + FSocket.stop(); + } + + virtual Print *GetPrint() + { +// FSocket.println( "Hello2" ); +// return &Serial; +// Serial.println( "GetPrint" ); + return &FSocket; + } + + public: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + int APacketSize = FSocket.parsePacket(); + if( APacketSize ) + { +// Serial.println( APacketSize ); + byte *Adata = new byte[ APacketSize ]; + FSocket.read( Adata, APacketSize ); + + inherited::OutputPin.SendValue( Mitov::TDataBlock( APacketSize, Adata )); + RemoteIPOutputPin.SendValue( IPAdressToString( FSocket.remoteIP() )); + RemotePortOutputPin.SendValue( FSocket.remotePort() ); + + delete []Adata; + } +/* + if ( FSocket.available() ) + { + unsigned char AByte = FSocket.read(); + inherited::OutputPin.Notify( &AByte ); + } +*/ + inherited::SystemLoopBegin( currentMicros ); + } + + public: + UDPSocket( T_OWNER &AOwner, ::IPAddress ARemoteIPAddress ) : + inherited( AOwner ), + RemoteIPAddress( ARemoteIPAddress ), + FResolved( true ) + { + } + + UDPSocket( T_OWNER &AOwner, String AHostName ) : + inherited( AOwner ), + FHostName( AHostName ), + FResolved( false ) + { + } + }; +//--------------------------------------------------------------------------- + class BasicEthernetShield : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + Mitov::SimpleList*> Sockets; + + public: + bool Enabled = true; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartEthernet(); + + else + StopEthernet(); + + } + + public: + virtual bool GetIPFromHostName( String AHostName, ::IPAddress &AAdress ) = 0; + + protected: + virtual void SystemInit() + { + if( Enabled ) + StartEthernet(); + + inherited::SystemInit(); + } + + virtual void StopEthernet() + { + for( int i = 0; i < Sockets.size(); ++i ) + Sockets[ i ]->StopSocket(); + } + + void RestartEthernet() + { + if( ! Enabled ) + return; + +// T_SERIAL->end(); +// Ethernet.end(); + StartEthernet(); + } + + virtual void StartEthernet() = 0; + + }; +//--------------------------------------------------------------------------- + template class EthernetSocketInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { +// Serial.print( "DoReceive" ); + if( T_INSTANCE->CanSend() ) + { + T_INSTANCE->BeginPacket(); + +// Serial.print( "PRINT: " ); +// Serial.println( *(T*)_Data ); + + T_INSTANCE->GetPrint()->println( *(T*)_Data ); + T_INSTANCE->EndPacket(); + } + } + }; +//--------------------------------------------------------------------------- + template class EthernetSocketBinaryInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { + if( T_INSTANCE->CanSend() ) + { + T_INSTANCE->BeginPacket(); + Mitov::TDataBlock ADataBlock = *(Mitov::TDataBlock*)_Data; + +// Serial.println( ADataBlock.Size ); + T_INSTANCE->GetPrint()->write((uint8_t *) ADataBlock.Data, ADataBlock.Size ); +// T_INSTANCE->GetPrint()->write( *(unsigned char*)_Data ); + T_INSTANCE->EndPacket(); + } + } + }; +//--------------------------------------------------------------------------- + template class EthernetSocketStringInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { + if( T_INSTANCE->CanSend() ) + { + T_INSTANCE->BeginPacket(); + T_INSTANCE->GetPrint()->println( (char*)_Data ); + T_INSTANCE->EndPacket(); + } + } + }; +//--------------------------------------------------------------------------- + template class EthernetSocketObjectInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { + if( T_INSTANCE->CanSend() ) + { + T_INSTANCE->BeginPacket(); + Print *APrint = T_INSTANCE->GetPrint(); + APrint->println( ((T_OBJECT *)_Data)->ToString().c_str() ); + T_INSTANCE->EndPacket(); + } + } + }; +//--------------------------------------------------------------------------- +} +#endif diff --git a/libraries/Mitov/Mitov_BasicGenerator.h b/libraries/Mitov/Mitov_BasicGenerator.h new file mode 100644 index 0000000..8d7908c --- /dev/null +++ b/libraries/Mitov/Mitov_BasicGenerator.h @@ -0,0 +1,132 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BASIC_GENERATOR_h +#define _MITOV_BASIC_GENERATOR_h + +#include + +namespace Mitov +{ + template class BasicGenerator : public Mitov::CommonEnableSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: // Needs to be public due to compiler bug :-( + T FValue = T( 0 ); + + protected: + inline void SendOutput() // Needed to be due to compiler bug :-( + { + OutputPin.Notify( &FValue ); + } + + }; +//--------------------------------------------------------------------------- + template class BasicFrequencyGenerator : public Mitov::BasicGenerator + { + typedef Mitov::BasicGenerator inherited; + + public: + float Frequency = 1.0f; + T Amplitude; + T Offset; + + // 0 - 1 + float Phase = 0.0f; + + public: + void SetFrequency( float AValue ) + { + if( Frequency == AValue ) + return; + + Frequency = AValue; + inherited::CalculateFields(); + } + + void SetPhase( float AValue ) + { + if( Phase == AValue ) + return; + + Phase = AValue; + FPhase = Phase; + } + + protected: + float FPhase = 0.0f; + unsigned long FLastTime = 0; + + protected: + virtual void SystemStart() + { + FPhase = Phase; + + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! inherited::ClockInputPin.IsConnected() ) + Generate( currentMicros ); + + inherited::SystemLoopBegin( currentMicros ); + } + + void Generate( unsigned long currentMicros ) + { + if( inherited::Enabled ) + { + float APeriod = 1000000 / Frequency; + + float ATime = ( currentMicros - FLastTime ); + ATime /= APeriod; + FPhase += ATime; + FPhase = V_FMOD( FPhase, 1 ); + + CalculateValue(); + } + + FLastTime = currentMicros; + inherited::SendOutput(); + } + + protected: + virtual void CalculateValue() = 0; + + virtual void DoClockReceive( void *_Data ) + { + Generate( micros() ); + } + + public: + BasicFrequencyGenerator( T AAmplitude, T AOffset ) : + Amplitude( AAmplitude ), + Offset( AOffset ) + { + } + + }; +//--------------------------------------------------------------------------- + template class AsymmetricGenerator : public Mitov::BasicFrequencyGenerator + { + typedef Mitov::BasicFrequencyGenerator inherited; + + public: + // -1 - 1 + float Asymmetry = 0.0f; + + public: + using inherited::inherited; + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Basic_GPIO.h b/libraries/Mitov/Mitov_Basic_GPIO.h new file mode 100644 index 0000000..692be3e --- /dev/null +++ b/libraries/Mitov/Mitov_Basic_GPIO.h @@ -0,0 +1,165 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BASIC_GPIO_h +#define _MITOV_BASIC_GPIO_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class BasicGPIOChannel; +//--------------------------------------------------------------------------- + template class BasicGPIO : public T_BASECLASS + { + typedef T_BASECLASS inherited; + + public: + OpenWire::ConnectSinkPin ReadInputPin; + + public: + Mitov::SimpleList FChannels; + + protected: + virtual void PerformRead() = 0; + + void DoReadInputReceive( void * _Data ) + { + PerformRead(); + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! ReadInputPin.IsConnected() ) + PerformRead(); + } + + public: + BasicGPIO() + { + ReadInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicGPIO::DoReadInputReceive ); + } + + }; +//--------------------------------------------------------------------------- + template class EnableBasicGPIO : public BasicGPIO + { + typedef BasicGPIO inherited; + + public: + void SetEnabled( bool AValue ) + { + if( inherited::Enabled == AValue ) + return; + + inherited::Enabled = AValue; + UpdateEnable(); + } + + protected: + virtual void UpdateEnable() = 0; + + }; +//--------------------------------------------------------------------------- + class BasicGPIOChannel : public OpenWire::Object + { + public: + OpenWire::SourcePin OutputPin; + + protected: + bool FInValue = false; + + public: + void SendOutput() + { + OutputPin.Notify( &FInValue ); + } + + void UpdateOutput( bool AValue ) + { + if( FInValue == AValue ) + return; + + FInValue = AValue; + + OutputPin.Notify( &FInValue ); + } + + virtual void UpdateInput() = 0; + + }; +//--------------------------------------------------------------------------- + template class OwnedBasicGPIOChannel : public BasicGPIOChannel + { + public: + OpenWire::SinkPin InputPin; + + public: + void SetIsOutput( bool AValue ) + { + if( FIsOutput == AValue ) + return; + + FIsOutput = AValue; + PinDirectionsInit(); + } + + void SetIsPullUp( bool AValue ) + { + if( FIsPullUp == AValue ) + return; + + FIsPullUp = AValue; + PinDirectionsInit(); + } + + protected: + T_OWNER &FOwner; + bool FValue; + int FIndex; + bool FIsOutput; + bool FIsPullUp; + bool FCombinedInOut; + + protected: + virtual void PinDirectionsInit() = 0; + + protected: + void DoDataReceive( void * _Data ) + { + bool AValue = *(bool *)_Data; + if( FValue == AValue ) + return; + + FValue = AValue; + FOwner.SetChannelValue( FIndex, AValue ); + } + + public: + OwnedBasicGPIOChannel( T_OWNER &AOwner, int AIndex, bool AInitialValue, bool AIsOutput, bool AIsPullUp, bool AIsCombinedInOut ) : + FOwner( AOwner ), + FIndex( AIndex ), + FIsOutput( AIsOutput ), + FIsPullUp( AIsPullUp ), + FCombinedInOut( AIsCombinedInOut ), + FValue( AInitialValue ) + { + AOwner.FChannels.push_back( this ); + + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&OwnedBasicGPIOChannel::DoDataReceive ); +// PinDirectionsInit(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Basic_I2C.h b/libraries/Mitov/Mitov_Basic_I2C.h new file mode 100644 index 0000000..b7f8103 --- /dev/null +++ b/libraries/Mitov/Mitov_Basic_I2C.h @@ -0,0 +1,159 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BASIC_I2C_h +#define _MITOV_BASIC_I2C_h + +#include +#include + +namespace Mitov +{ +// class I2C : public OpenWire::Component + namespace I2C + { + const uint16_t I2C_DEFAULT_READ_TIMEOUT = 1000; +// public: + bool ReadBytes( uint8_t devAddr, uint8_t regAddr, uint8_t length, void *data, uint16_t timeout = I2C_DEFAULT_READ_TIMEOUT ) + { + int8_t count = 0; + uint32_t t1 = millis(); + + // Arduino v1.0.1+, Wire library + // Adds official support for repeated start condition, yay! + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) + { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) + ((uint8_t *)data )[count] = Wire.read(); + + Wire.endTransmission(); + } + + return ( count == length ); + } + + void WriteByte( uint8_t devAddr, uint8_t regAddr, uint8_t AValue ) + { +// Serial.print( "Address: " ); Serial.print( devAddr, HEX ); Serial.print( " Reg: " ); Serial.print( regAddr, HEX ); Serial.print( " = " ); Serial.println( AValue, BIN ); + Wire.beginTransmission( devAddr ); + Wire.write( regAddr ); + Wire.write( AValue ); + Wire.endTransmission(); + } + }; +//--------------------------------------------------------------------------- + class Basic_I2CChannel; +//--------------------------------------------------------------------------- + class Basic_MultiChannel_SourceI2C : public Mitov::EnabledComponent, public ClockingSupport + { + typedef Mitov::EnabledComponent inherited; + + public: + bool FModified = false; + + public: + Mitov::SimpleList FChannels; + +// protected: +// virtual void SystemInit(); + +// protected: +// virtual void DoClockReceive( void * ); + + }; +//--------------------------------------------------------------------------- + class Basic_I2CChannel : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + float FValue = 0.0f; + float FNewValue = 0.0f; + +// public: +// virtual void InitChannel() {} +// virtual void SendOutput() = 0; + + }; +//--------------------------------------------------------------------------- + template class Basic_Typed_I2CChannel : public Mitov::Basic_I2CChannel + { + typedef Mitov::Basic_I2CChannel inherited; + + public: + float InitialValue = 0.0f; + + protected: + int FIndex; + + protected: + T_OWNER &FOwner; + +/* + protected: + virtual void DoReceive( void *_Data ) + { + FNewValue = constrain( *((float *)_Data), 0, 1 ); + if( FNewValue == FValue ) + return; + + FOwner.FModified = true; + + if( FOwner.ClockInputPin.IsConnected() ) + FOwner.FModified = true; + + else + SendOutput(); + + } +*/ + + public: + Basic_Typed_I2CChannel( T_OWNER &AOwner, int AIndex ) : + FOwner( AOwner ), + FIndex( AIndex ) + { + AOwner.FChannels.push_back( this ); + } + + }; +//--------------------------------------------------------------------------- +/* + void Basic_MultiChannel_SourceI2C::DoClockReceive( void * ) + { + if( ! FModified ) + return; + + for( int i =0; i < FChannels.size(); ++i ) + FChannels[ i ]->SendOutput(); + } +*/ +//--------------------------------------------------------------------------- +/* + void Basic_MultiChannel_SourceI2C::SystemInit() + { + inherited::SystemInit(); + + for( int i =0; i < FChannels.size(); ++i ) + FChannels[ i ]->InitChannel(); + } +*/ +//--------------------------------------------------------------------------- +} +#endif diff --git a/libraries/Mitov/Mitov_Basic_RTC.h b/libraries/Mitov/Mitov_Basic_RTC.h new file mode 100644 index 0000000..8207f4e --- /dev/null +++ b/libraries/Mitov/Mitov_Basic_RTC.h @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BASIC_RTC_h +#define _MITOV_BASIC_RTC_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class BasicRTC : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: + OpenWire::SinkPin SetInputPin; + + protected: + virtual void DoSetReceive( void *_Data ) = 0; + virtual void ReadTime() = 0; + + virtual void DoClockReceive( void *_Data ) override + { + ReadTime(); + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ! ClockInputPin.IsConnected() ) + ReadTime(); + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + BasicRTC() + { + SetInputPin.SetCallback( MAKE_CALLBACK( BasicRTC::DoSetReceive )); + } + + }; +//--------------------------------------------------------------------------- + class BasicHaltRTC : public BasicRTC + { + typedef BasicRTC inherited; + + public: + bool Halt = false; + + public: + void SetHalt( bool AValue ) + { + if( Halt == AValue ) + return; + + Halt = AValue; + UpdateHalt(); + } + + protected: + virtual void UpdateHalt() = 0; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Basic_SPI.h b/libraries/Mitov/Mitov_Basic_SPI.h new file mode 100644 index 0000000..ec67e3a --- /dev/null +++ b/libraries/Mitov/Mitov_Basic_SPI.h @@ -0,0 +1,139 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BASIC_SPI_h +#define _MITOV_BASIC_SPI_h + +#include +#include + +namespace Mitov +{ + class BasicSPI : public OpenWire::Component + { + public: + virtual uint16_t transfer16(uint16_t data) = 0; + virtual uint8_t transfer(uint8_t data) = 0; + virtual void transfer(void *buf, size_t count) = 0; + virtual void beginTransaction(SPISettings settings) = 0; + virtual void endTransaction() = 0; + }; +//--------------------------------------------------------------------------- + class Basic_SPIChannel; +//--------------------------------------------------------------------------- + class Basic_SPI : public Mitov::EnabledComponent + { + typedef Mitov::EnabledComponent inherited; + + public: + OpenWire::SourcePin ChipSelectOutputPin; + + protected: + BasicSPI &FSPI; + + public: + Basic_SPI( BasicSPI &ASPI ) : + FSPI( ASPI ) + { + } + + }; +//--------------------------------------------------------------------------- + class Basic_MultiChannel_SourceSPI : public Mitov::Basic_SPI, public ClockingSupport + { + typedef Mitov::Basic_SPI inherited; + + public: + bool FModified = false; + + public: + Mitov::SimpleList FChannels; + + protected: + virtual void SystemInit(); + + protected: + virtual void DoClockReceive( void * ) override; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class Basic_SPIChannel : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + virtual void InitChannel() {} + virtual void SendOutput() = 0; + + }; +//--------------------------------------------------------------------------- + template class Basic_Typed_SPIChannel : public Mitov::Basic_SPIChannel + { + typedef Mitov::Basic_SPIChannel inherited; + + public: + float InitialValue = 0.0f; + + protected: + float FValue = 0.0f; + float FNewValue = 0.0f; + + int FIndex; + + protected: + T_OWNER &FOwner; + + protected: + virtual void DoReceive( void *_Data ) + { + FNewValue = constrain( *((float *)_Data), 0.0f, 1.0f ); + if( FNewValue == FValue ) + return; + + if( FOwner.ClockInputPin.IsConnected() ) + FOwner.FModified = true; + + else + SendOutput(); + + } + + public: + Basic_Typed_SPIChannel( T_OWNER &AOwner, int AIndex ) : + FOwner( AOwner ), + FIndex( AIndex ) + { + AOwner.FChannels.push_back( this ); + } + + }; +//--------------------------------------------------------------------------- + void Basic_MultiChannel_SourceSPI::DoClockReceive( void * ) + { + if( ! FModified ) + return; + + for( int i =0; i < FChannels.size(); ++i ) + FChannels[ i ]->SendOutput(); + } +//--------------------------------------------------------------------------- + void Basic_MultiChannel_SourceSPI::SystemInit() + { + inherited::SystemInit(); + ChipSelectOutputPin.SendValue( true ); + + for( int i =0; i < FChannels.size(); ++i ) + FChannels[ i ]->InitChannel(); + } +//--------------------------------------------------------------------------- +} +#endif diff --git a/libraries/Mitov/Mitov_BinaryDecoder.h b/libraries/Mitov/Mitov_BinaryDecoder.h new file mode 100644 index 0000000..1a5b66d --- /dev/null +++ b/libraries/Mitov/Mitov_BinaryDecoder.h @@ -0,0 +1,59 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BINARY_DECODER_h +#define _MITOV_BINARY_DECODER_h + +#include + +namespace Mitov +{ + class BinaryDecoder : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + Mitov::SimpleList OutputPins; + + public: + unsigned long InitialValue = 0; + + protected: + unsigned long FOldValue = 0; + + protected: + void SetValue( unsigned long AValue ) + { + FOldValue = AValue; + OutputPins[ FOldValue ].Notify( (void *)&GBooleanConst[ 1 ] ); + } + + protected: + virtual void DoReceive( void *_Data ) override + { + unsigned long AValue = *(unsigned long *)_Data; + if( FOldValue == AValue ) + return; + + OutputPins[ FOldValue ].Notify( (void *)&GBooleanConst[ 0 ] ); + + SetValue( AValue ); + } + + virtual void SystemInit() + { + inherited::SystemInit(); + SetValue( InitialValue ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_BinaryGenerators.h b/libraries/Mitov/Mitov_BinaryGenerators.h new file mode 100644 index 0000000..094059a --- /dev/null +++ b/libraries/Mitov/Mitov_BinaryGenerators.h @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BINARY_GENERATORS_h +#define _MITOV_BINARY_GENERATORS_h + +#include + +namespace Mitov +{ + class PulseGenerator : public Mitov::CommonGenerator + { + typedef Mitov::CommonGenerator inherited; + + public: + bool InitialValue = false; + + protected: + virtual void CalculateFields() override + { + FPeriod = ( (( 1 / ( Frequency * 2 )) * 1000000 ) + 0.5 ); // 2 times one for each switch + } + + protected: + virtual void Clock() override + { + InitialValue = !InitialValue; + OutputPin.Notify( &InitialValue ); + } + + virtual void SystemInit() override + { + inherited::SystemInit(); + + OutputPin.Notify( &InitialValue ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Button.h b/libraries/Mitov/Mitov_Button.h new file mode 100644 index 0000000..616b3e5 --- /dev/null +++ b/libraries/Mitov/Mitov_Button.h @@ -0,0 +1,54 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_BUTTON_h +#define _MITOV_BUTTON_h + +#include + +namespace Mitov +{ + class Button : public Mitov::CommonFilter + { + typedef Mitov::CommonFilter inherited; + + protected: + unsigned long FLastTime = 0; + bool FLastValue = false; + bool FValue = false; + + public: + uint32_t DebounceInterval = 50; + + protected: + virtual void DoReceive( void *_Data ) + { + bool AValue = *( bool *)_Data; + if( AValue != FLastValue ) + FLastTime = millis(); + + FLastValue = AValue; + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( FValue != FLastValue ) + if( millis() - FLastTime > DebounceInterval ) + { + FValue = FLastValue; + OutputPin.Notify( &FValue ); + } + + inherited::SystemLoopBegin( currentMicros ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Color.h b/libraries/Mitov/Mitov_Color.h new file mode 100644 index 0000000..dbd996e --- /dev/null +++ b/libraries/Mitov/Mitov_Color.h @@ -0,0 +1,150 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_COLOR_h +#define _MITOV_COLOR_h + +#include +#include "Mitov_RandomGenerator.h" + +namespace Mitov +{ +#define Min Min +#define Max Max +//--------------------------------------------------------------------------- + class RandomColor : public Mitov::CommonRandomGenerator + { + typedef Mitov::CommonRandomGenerator inherited; + + public: + virtual void GenerateValue() + { + FValue.Red = random( Min.Red, Max.Red + 1 ); + FValue.Green = random( Min.Green, Max.Green + 1 ); + FValue.Blue = random( Min.Blue, Max.Blue + 1 ); + } + + virtual void SystemInit() + { + int AMin = MitovMin( Min.Red, Max.Red ); + int AMax = MitovMax( Min.Red, Max.Red ); + + Min.Red = AMin; + Max.Red = AMax; + + AMin = MitovMin( Min.Green, Max.Green ); + AMax = MitovMax( Min.Green, Max.Green ); + + Min.Green = AMin; + Max.Green = AMax; + + AMin = MitovMin( Min.Blue, Max.Blue ); + AMax = MitovMax( Min.Blue, Max.Blue ); + + Min.Blue = AMin; + Max.Blue = AMax; + + inherited::SystemInit(); + } + + public: + RandomColor() : + inherited( 0, 0xFFFFFF ) + { + } + + }; +//--------------------------------------------------------------------------- + class BasicColorSource : public CommonSource + { + public: + TColor InitialValue; + + }; +//--------------------------------------------------------------------------- + class AnalogToColor : public BasicColorSource + { + public: + OpenWire::SinkPin RedInputPin; + OpenWire::SinkPin GreenInputPin; + OpenWire::SinkPin BlueInputPin; + + protected: + TColor FValue; + + protected: + void DoReceiveRed( void *_Data ) + { + unsigned char AValue = (*(float *)_Data ) * 255; + if( FValue.Red == AValue ) + return; + + FValue.Red = AValue; + OutputPin.Notify( &FValue ); + } + + void DoReceiveGreen( void *_Data ) + { + unsigned char AValue = (*(float *)_Data ) * 255; + if( FValue.Green == AValue ) + return; + + FValue.Green = AValue; + OutputPin.Notify( &FValue ); + } + + void DoReceiveBlue( void *_Data ) + { + unsigned char AValue = (*(float *)_Data ) * 255; + if( FValue.Blue == AValue ) + return; + + FValue.Blue = AValue; + OutputPin.Notify( &FValue ); + } + + virtual void SystemStart() + { + FValue = InitialValue; + OutputPin.Notify( &FValue ); + } + + public: + AnalogToColor() + { + RedInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&AnalogToColor::DoReceiveRed ); + GreenInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&AnalogToColor::DoReceiveGreen ); + BlueInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&AnalogToColor::DoReceiveBlue ); + } + + }; +//--------------------------------------------------------------------------- + class ColorToAnalog : public CommonSink + { + public: + OpenWire::SourcePin RedOutputPin; + OpenWire::SourcePin GreenOutputPin; + OpenWire::SourcePin BlueOutputPin; + + protected: + virtual void DoReceive( void *_Data ) + { + TColor &AColor = *(TColor *)_Data; + RedOutputPin.Notify( &AColor.Red ); + GreenOutputPin.Notify( &AColor.Green ); + BlueOutputPin.Notify( &AColor.Blue ); + } + + }; +//--------------------------------------------------------------------------- +#undef Min +#undef Max +} + +#endif diff --git a/libraries/Mitov/Mitov_CommonMux.h b/libraries/Mitov/Mitov_CommonMux.h new file mode 100644 index 0000000..f1d5ee5 --- /dev/null +++ b/libraries/Mitov/Mitov_CommonMux.h @@ -0,0 +1,123 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_COMMON_MUX_h +#define _MITOV_COMMON_MUX_h + +#include + +namespace Mitov +{ + template class ToggleSwitch : public Mitov::BasicMultiInput + { + typedef Mitov::BasicMultiInput inherited; + + public: + OpenWire::VlaueSinkPin TrueInputPin; + OpenWire::VlaueSinkPin FalseInputPin; + + OpenWire::SinkPin SelectInputPin; + + public: + bool InitialSelectValue = false; + + protected: + bool FSelectValue = false; + + protected: + virtual void SystemStart() + { + FSelectValue = InitialSelectValue; + inherited::SystemStart(); + } + + protected: + virtual void DoReceiveSelect( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( FSelectValue == AValue ) + return; + + FSelectValue = AValue; + inherited::CallCalculateSendOutput( false ); + } + + protected: + virtual T_OUT CalculateOutput() override + { + if( FSelectValue ) + return (T_OUT)TrueInputPin.Value; + + else + return (T_OUT)FalseInputPin.Value; + } + + public: + ToggleSwitch() + { + SelectInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ToggleSwitch::DoReceiveSelect ); + TrueInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ToggleSwitch::DoReceive ); + FalseInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ToggleSwitch::DoReceive ); + } + + }; +//--------------------------------------------------------------------------- + template class CommonMux : public Mitov::CommonMultiInput + { + typedef Mitov::CommonMultiInput inherited; + + protected: + unsigned int FChannel = 0; + + public: + unsigned int InitialChannel = 0; + + public: + OpenWire::SinkPin SelectInputPin; + + protected: + virtual T CalculateOutput() override + { + return inherited::InputPins[ FChannel ].Value; + } + + protected: + virtual void DoReceiveSelect( void *_Data ) + { + uint32_t AChannel = *(uint32_t *)_Data; + if( AChannel >= C_NUM_INPUTS ) + AChannel = C_NUM_INPUTS - 1; + + if( FChannel == AChannel ) + return; + +// Serial.println( AChannel ); + + FChannel = AChannel; + inherited::CallCalculateSendOutput( false ); + } + + protected: + virtual void SystemStart() + { + FChannel = InitialChannel; + inherited::SystemStart(); + } + + public: + CommonMux() + { + SelectInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&CommonMux::DoReceiveSelect ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_CompassHeading.h b/libraries/Mitov/Mitov_CompassHeading.h new file mode 100644 index 0000000..81a3867 --- /dev/null +++ b/libraries/Mitov/Mitov_CompassHeading.h @@ -0,0 +1,96 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_COMPASSHEADING_h +#define _MITOV_COMPASSHEADING_h + +#include + +namespace Mitov +{ + enum TAngleUnits { auDegree, auRadians, auNormalized }; + + class CompassHeading : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::VlaueSinkPin InputPins[ 2 ]; + OpenWire::TypedSourcePin OutputPin; + + public: + float DeclinationAngle = 0.0; + TAngleUnits Units = auDegree; + + protected: + bool FChangeOnly = false; + + protected: + virtual void SystemLoopEnd() + { + inherited::SystemLoopEnd(); + + // Hold the module so that Z is pointing 'up' and you can measure the heading with x&y + // Calculate heading when the magnetometer is level, then correct for signs of axis. + float AHeading = atan2( InputPins[ 1 ].Value, InputPins[ 0 ].Value ); // Y , X + +// Serial.println( AHeading ); + + // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location. + // Find yours here: http://www.magnetic-declination.com/ + // If you cannot find your Declination, comment out these two lines, your compass will be slightly off. + + float ADeclinationAngle; + switch( Units ) + { + case auDegree: + ADeclinationAngle = DeclinationAngle * M_PI / 180; + break; + + case auRadians: + ADeclinationAngle = DeclinationAngle; + break; + + case auNormalized: + ADeclinationAngle = DeclinationAngle * 2 * PI; + break; + + } + + AHeading += ADeclinationAngle; + + // Correct for when signs are reversed. + if(AHeading < 0) + AHeading += 2*PI; + + // Check for wrap due to addition of declination. + if(AHeading > 2*PI) + AHeading -= 2*PI; + + switch( Units ) + { + case auDegree: + AHeading *= 180 / M_PI; + break; + + case auNormalized: + AHeading /= 2 * PI; + break; + + } + + OutputPin.SetValue( AHeading, FChangeOnly ); + + FChangeOnly = true; + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Compass_AK8963.h b/libraries/Mitov/Mitov_Compass_AK8963.h new file mode 100644 index 0000000..e59a9c5 --- /dev/null +++ b/libraries/Mitov/Mitov_Compass_AK8963.h @@ -0,0 +1,192 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_AK8963_h +#define _MITOV_COMPASS_AK8963_h + +#include +#include //I2C Arduino Library +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + enum CompassAK8963Mode { cmSingleMeasurement, cm8Hz, cm100Hz, cmExternalTrigger }; +//--------------------------------------------------------------------------- + namespace CompassAK8963Const + { + const byte CompassModes[] = + { + 0b00000001, + 0b00000010, + 0b00000110, + 0b00000100 + }; + } +//--------------------------------------------------------------------------- + class CompassAK8963 : public Mitov::EnabledComponent, public Mitov::ClockingSupport + { + typedef Mitov::EnabledComponent inherited; + + protected: + static const byte MPU9150_RA_MAG_ST1 = 0x02; + static const byte MPU9150_RA_MAG_XOUT_L = 0x03; + static const byte MPU9150_RA_MAG_XOUT_H = 0x04; + static const byte MPU9150_RA_MAG_YOUT_L = 0x05; + static const byte MPU9150_RA_MAG_YOUT_H = 0x06; + static const byte MPU9150_RA_MAG_ZOUT_L = 0x07; + static const byte MPU9150_RA_MAG_ZOUT_H = 0x08; + static const byte MPU9150_RA_MAG_ST2 = 0x09; + static const byte MPU9150_RA_MAG_CNTL1 = 0x0A; + static const byte MPU9150_RA_MAG_CNTL2 = 0x0B; + + static const byte MPU9150_RA_MAG_ASAX = 0x10; + static const byte MPU9150_RA_MAG_ASAY = 0x11; + static const byte MPU9150_RA_MAG_ASAZ = 0x12; + + public: + OpenWire::SourcePin OutputPins[ 3 ]; + + OpenWire::SinkPin ResetInputPin; + OpenWire::SourcePin OverflowOutputPin; + + public: + CompassAK8963Mode Mode : 2; + bool Enabled : 1; + bool SelfTest : 1; // Added to save space as bitfield + byte Address : 2; + bool HighResolution : 1; + + protected: + float CompassAdjustmentValues[ 3 ]; + + protected: + void PerformRead() + { + const float CompassCoefficients[] = + { + 10.0f *4219.0f / 8190.0f, + 10.0f *4219.0f / 32760.0f + }; + + uint8_t AIntValues[ 7 ]; + if( ReadBytes( MPU9150_RA_MAG_XOUT_L, 7, AIntValues )) + for( int i = 0; i < 3; ++i ) + { + float AValue = (( ((int16_t)AIntValues[ i * 2 + 1 ] ) << 8 ) | AIntValues[ i * 2 ] ) * CompassCoefficients[ HighResolution & 1 ] * CompassAdjustmentValues[ i ]; + OutputPins[ i ].Notify( &AValue ); + } + + } + + void ReadSensors() + { + uint8_t AIntValue; + + if( Mode == cmSingleMeasurement ) + { + UpdateCompassControlReg(); + delay(10); + PerformRead(); + } + + if( ReadBytes( MPU9150_RA_MAG_ST1, 1, &AIntValue )) + { + OverflowOutputPin.SendValue( AIntValue & 0b00000010 ); + if( AIntValue & 0b00000001 ) + PerformRead(); + } + + } + + void UpdateCompassControlReg() + { + byte AValue; + if( Enabled ) + AValue = CompassAK8963Const::CompassModes[ Mode ]; + + else + AValue = 0; + + AValue |= ( HighResolution ? 0b00010000 : 0 ); + + WriteByte( MPU9150_RA_MAG_CNTL1, AValue ); + } + + void ReagCompassAdjustmentValues() + { + uint8_t AValues[ 3 ]; + + ReadBytes( MPU9150_RA_MAG_ASAX, sizeof( AValues ), AValues ); + for( int i = 0; i < 3; ++i ) + CompassAdjustmentValues[ i ] = (((float) AValues[ i ] ) - 128.0f) / 256.0f + 1.0f; + + } + + protected: + inline void WriteByte( byte ARegister, byte AData ) + { + I2C::WriteByte( Address + 0x0C, ARegister, AData ); + } + + bool ReadBytes( uint8_t regAddr, uint8_t length, void *data ) + { + return I2C::ReadBytes( Address + 0x0C, regAddr, length, data ); + } + + protected: + virtual void SystemStart() override + { + UpdateCompassControlReg(); + ReagCompassAdjustmentValues(); + + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + + if( Enabled ) + if( ! ClockInputPin.IsConnected() ) + ReadSensors(); + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + virtual void DoClockReceive( void *_Data ) override + { + ReadSensors(); + } + + void DoResetReceive( void *_Data ) + { + WriteByte( MPU9150_RA_MAG_CNTL2, 0b00000001 ); + } + + public: + CompassAK8963() : + Mode( cm100Hz ), + Enabled( true ), + SelfTest( false ), + HighResolution( true ), + Address( 0 ) + { + ResetInputPin.SetCallback( MAKE_CALLBACK( CompassAK8963::DoResetReceive )); + } + }; +//--------------------------------------------------------------------------- + class CompassAK8963I2C : public Mitov::CompassAK8963 + { + typedef Mitov::CompassAK8963 inherited; + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Controllino_RS485.h b/libraries/Mitov/Mitov_Controllino_RS485.h new file mode 100644 index 0000000..ebb9565 --- /dev/null +++ b/libraries/Mitov/Mitov_Controllino_RS485.h @@ -0,0 +1,98 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_CONTROLLINO_RS485_h +#define _MITOV_CONTROLLINO_RS485_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class ControllinoRS485Module : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SinkPin TransmitInputPin; + OpenWire::SinkPin ReceiveInputPin; + + public: + bool FTransmit = false; + bool FReceive = false; + + public: + bool Enabled = true; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartModule(); + + else + StopModule(); + + } + + protected: + virtual void SystemInit() + { + if( Enabled ) + StartModule(); + + inherited::SystemInit(); + } + + void StopModule() + { + } + + void StartModule() + { + Controllino_RS485Init(); + Controllino_SwitchRS485DE( FTransmit ); + Controllino_SwitchRS485RE( FReceive ); + } + + protected: + void DoTransmitInputPinReceive( void *_Data ) + { + FTransmit = *(bool *)_Data; + if( ! Enabled ) + return; + + Controllino_SwitchRS485DE( FTransmit ); + } + + void DoReceiveInputPinReceive( void *_Data ) + { + FReceive = *(bool *)_Data; + if( ! Enabled ) + return; + + Controllino_SwitchRS485RE( FReceive ); + } + + public: + ControllinoRS485Module() + { + TransmitInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ControllinoRS485Module::DoTransmitInputPinReceive ); + ReceiveInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ControllinoRS485Module::DoReceiveInputPinReceive ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Controllino_RTC.h b/libraries/Mitov/Mitov_Controllino_RTC.h new file mode 100644 index 0000000..050d8e3 --- /dev/null +++ b/libraries/Mitov/Mitov_Controllino_RTC.h @@ -0,0 +1,121 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_CONTROLLINO_RTC_h +#define _MITOV_CONTROLLINO_RTC_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class ControllinoRTCModule : public OpenWire::Component, public Mitov::ClockingSupport + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SourcePin OutputPin; + OpenWire::SinkPin SetInputPin; + + public: + bool Enabled = true; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartModule(); + + else + StopModule(); + + } + + protected: + virtual void SystemInit() + { + if( Enabled ) + StartModule(); + + inherited::SystemInit(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! ClockInputPin.IsConnected() ) + DoClockReceive( NULL ); + + inherited::SystemLoopBegin( currentMicros ); + } + + void StopModule() + { + } + + void StartModule() + { +// Serial.println( "START" ); +// SPI.begin(); +// Controllino_RTC_init( 65 ); + Controllino_RTC_init( 0 ); +// Controllino_RTCSSInit(); +// Controllino_SetRTCSS( true ); + } + + virtual void DoClockReceive( void *_Data ) override + { + if( ! Enabled ) + return; + +// Serial.println( "Test1" ); + unsigned char aDay, aWeekDay, aMonth, aYear, aHour, aMinute, aSecond; +// Controllino_PrintTimeAndDate(); + + Controllino_ReadTimeDate( &aDay, &aWeekDay, &aMonth, &aYear, &aHour, &aMinute, &aSecond ); +// Serial.println( "Test2" ); + uint16_t ALongYear = 2000 + aYear; +// Serial.println( ALongYear ); +// Serial.println( aMonth ); +// Serial.println( aDay ); + TDateTime ADateTime; +// ADateTime.TryEncodeDate( 2000 + aYear, aMonth, aDay ); +// ADateTime.TryEncodeTime( aHour, aMinute, aSecond, 0 ); + ADateTime.TryEncodeDateTime( ALongYear, aMonth, aDay, aHour, aMinute, aSecond, 0 ); + OutputPin.Notify( &ADateTime ); + } + + void DoSetTimeReceive( void *_Data ) + { + if( ! Enabled ) + return; + + uint16_t AYear, AMonth, ADay, aWeekDay, AHour, AMinute, ASecond, AMilliSecond; + +// Serial.println( "Test2" ); + ((TDateTime *)_Data)->DecodeDateTime( AYear, AMonth, ADay, aWeekDay, AHour, AMinute, ASecond, AMilliSecond ); + Controllino_SetTimeDate( ADay, aWeekDay, AMonth, AYear, AHour, AMinute, ASecond ); + + } + + public: + ControllinoRTCModule() + { + SetInputPin.SetCallback( MAKE_CALLBACK( ControllinoRTCModule::DoSetTimeReceive )); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Converters.h b/libraries/Mitov/Mitov_Converters.h new file mode 100644 index 0000000..c003cac --- /dev/null +++ b/libraries/Mitov/Mitov_Converters.h @@ -0,0 +1,465 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_CONVERTERS_h +#define _MITOV_CONVERTERS_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + template class TypedToAnalog : public CommonFilter + { + typedef CommonFilter inherited; + + public: + float Scale = 1.0; + + protected: + virtual void DoReceive( void *_Data ) override + { + float AFloatValue = ( *(T*)_Data ) * Scale; + OutputPin.Notify( &AFloatValue ); + } + + }; +//--------------------------------------------------------------------------- + class AnalogToInteger : public CommonFilter + { + typedef CommonFilter inherited; + + public: + bool Round = true; + float Scale = 1.0; + + protected: + virtual void DoReceive( void *_Data ) override + { + float AFloatValue = *(float*)_Data * Scale; + if( Round ) + AFloatValue += 0.5f; + + long AIntValue = AFloatValue; + OutputPin.Notify( &AIntValue ); + } + + }; +//--------------------------------------------------------------------------- + class AnalogToUnsigned : public CommonFilter + { + typedef CommonFilter inherited; + + public: + bool Round = true; + bool Constrain = true; + float Scale = 1.0; + + protected: + virtual void DoReceive( void *_Data ) override + { + float AFloatValue = *(float*)_Data * Scale; + if( Round ) + AFloatValue += 0.5f; + + long AIntValue = AFloatValue; + if( Constrain ) + AIntValue &= 0x7FFFFFFF; + + OutputPin.Notify( &AIntValue ); + } + + }; +//--------------------------------------------------------------------------- + class AnalogToText : public CommonFilter + { + typedef CommonFilter inherited; + + public: + int MinWidth = 1; + int Precision = 3; + + protected: + virtual void DoReceive( void *_Data ) override + { + float AFloatValue = *(float*)_Data; + char AText[ 50 ]; + dtostrf( AFloatValue, MinWidth, Precision, AText ); + OutputPin.Notify( AText ); + } + + }; +//--------------------------------------------------------------------------- + template class TypedToText : public CommonFilter + { + typedef CommonFilter inherited; + + public: + int Base = 10; + + protected: + virtual void DoReceive( void *_Data ) override + { + T AValue = *(T*)_Data; + char AText[ 50 ]; + itoa( AValue, AText, Base ); + OutputPin.Notify( AText ); + } + + }; +//--------------------------------------------------------------------------- + class DigitalToText : public CommonFilter + { + typedef CommonFilter inherited; + + public: + String TrueValue = "true"; + String FalseValue = "false"; + + protected: + virtual void DoReceive( void *_Data ) override + { + bool AValue = *(bool *)_Data; + const char *AText; + if( AValue ) + AText = TrueValue.c_str(); + + else + AText = FalseValue.c_str(); + + OutputPin.Notify( (void*)AText ); + } + + }; +//--------------------------------------------------------------------------- + template class DigitalToType : public CommonFilter + { + typedef CommonFilter inherited; + + public: + T TrueValue = C_TRUE; + T FalseValue = T_FALSE; + + protected: + virtual void DoReceive( void *_Data ) override + { + if( *(bool *)_Data ) + OutputPin.Notify( &TrueValue ); + + else + OutputPin.Notify( &FalseValue ); + + } + + }; +//--------------------------------------------------------------------------- + template class DigitalToTypeParams : public CommonFilter + { + typedef CommonFilter inherited; + + public: + T TrueValue; + T FalseValue; + + protected: + virtual void DoReceive( void *_Data ) override + { + if( *(bool *)_Data ) + OutputPin.Notify( &TrueValue ); + + else + OutputPin.Notify( &FalseValue ); + + } + + public: + DigitalToTypeParams( T ATrueValue, T AFalseValue ) : + TrueValue( ATrueValue ), + FalseValue( AFalseValue ) + { + } + }; +//--------------------------------------------------------------------------- + class TextToAnalog : public CommonFilter + { + typedef CommonFilter inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + char * AText = (char*)_Data; + float AValue = strtod( AText, NULL ); + OutputPin.Notify( &AValue ); + } + + }; +//--------------------------------------------------------------------------- + class TextToInteger : public CommonFilter + { + typedef CommonFilter inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + char * AText = (char*)_Data; + long AValue = atoi( AText ); + OutputPin.Notify( &AValue ); + } + + }; +//--------------------------------------------------------------------------- + class TextToUnsigned : public CommonFilter + { + typedef CommonFilter inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + char * AText = (char*)_Data; + unsigned long AValue = atoi( AText ); + OutputPin.Notify( &AValue ); + } + + }; +//--------------------------------------------------------------------------- + class UnsignedToInteger : public CommonFilter + { + typedef CommonFilter inherited; + + public: + bool Constrain = true; + + protected: + virtual void DoReceive( void *_Data ) override + { + unsigned long AValue = *(unsigned long*)_Data; + if( Constrain ) + AValue &= 0x7FFFFFFF; + + OutputPin.Notify( &AValue ); + } + + }; +//--------------------------------------------------------------------------- + class IntegerToUnsigned : public CommonFilter + { + typedef CommonFilter inherited; + + public: + bool Constrain = true; + + protected: + virtual void DoReceive( void *_Data ) override + { + long AValue = *(long*)_Data; + if( Constrain ) + AValue &= 0x7FFFFFFF; + + OutputPin.Notify( &AValue ); + } + + }; +//--------------------------------------------------------------------------- + template class UnsignedToDigital : public CommonSink + { + typedef CommonSink inherited; + + public: + OpenWire::SourcePin OutputPins[ C_NUM_INPUTS ]; + + public: + uint32_t InitialValue = 0; + + protected: + uint32_t FOldValue = 0; + + protected: + void SetValue( uint32_t AValue, bool AUpdate ) + { + for( long i = 0; i < C_NUM_INPUTS; ++i ) + { + unsigned long ABit = ((unsigned long)1) << i; + bool AOldBitValue = ( FOldValue & ABit ); + bool ANewBitValue = ( AValue & ABit ); + if( AUpdate || AOldBitValue != ANewBitValue ) + OutputPins[ i ].Notify( (void *)&GBooleanConst[ ANewBitValue ] ); + + } + + FOldValue = AValue; + } + + protected: + virtual void DoReceive( void *_Data ) override + { + unsigned long AValue = *(unsigned long *)_Data; + if( FOldValue == AValue ) + return; + + SetValue( AValue, false ); + } + + virtual void SystemInit() + { + inherited::SystemInit(); + SetValue( InitialValue, true ); + } + + }; +//--------------------------------------------------------------------------- + class ReversableConverter : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + public: + bool Reverse = false; + + }; +//--------------------------------------------------------------------------- + class CelsiusToFahrenheit : public ReversableConverter + { + typedef ReversableConverter inherited; + + protected: + virtual float FilterValue( float AValue ) override + { + if( Reverse ) + return ( AValue - 32.0 ) / ( 9.0/5.0 ); + + else + return AValue * ( 9.0/5.0 ) + 32.0; + } + + }; +//--------------------------------------------------------------------------- + class CelsiusToKelvin : public ReversableConverter + { + typedef ReversableConverter inherited; + + protected: + virtual float FilterValue( float AValue ) override + { + if( Reverse ) + return AValue - 273.15; + + else + return AValue + 273.15; + } + + }; +//--------------------------------------------------------------------------- + template class CharToText : public CommonImplementedEnableFilter + { + typedef CommonImplementedEnableFilter inherited; + + public: + uint32_t MaxLength = 100; + bool Truncate = false; + bool UpdateOnEachChar = false; + + protected: + byte FBuffer[ T_SIZE + 1 ]; + uint32_t FIndex = 0; + + protected: + void SendBufferNoReset() + { + FBuffer[ FIndex ] = '\0'; + inherited::OutputPin.Notify( FBuffer ); + } + + void SendBuffer() + { + SendBufferNoReset(); + FIndex = 0; + } + + virtual void ReceiveValue( void *_Data ) override + { + char AValue = *(char *)_Data; + if( AValue == '\n' ) + return; + + if( AValue == '\r' ) + { + SendBuffer(); + return; + } + + if( FIndex >= T_SIZE ) + { + if( Truncate ) + return; + + SendBuffer(); + } + + FBuffer[ FIndex++ ] = AValue; + if( UpdateOnEachChar ) + SendBufferNoReset(); + + } + + }; +//--------------------------------------------------------------------------- + class TextToChar : public CommonImplementedEnableFilter + { + typedef CommonImplementedEnableFilter inherited; + + public: + bool AddReturn = true; + bool AddNewLine = true; + + protected: + virtual void ReceiveValue( void *_Data ) override + { + char *AValue = (char *)_Data; + while( *AValue ) + { + inherited::OutputPin.Notify( AValue ); + ++AValue; + } + + if( AddReturn ) + inherited::OutputPin.SendValue( '\r' ); + + if( AddNewLine ) + inherited::OutputPin.SendValue( '\n' ); + } + }; +//--------------------------------------------------------------------------- + class PressureToAltitude : public CommonTypedFilter + { + public: + float BaseLinePressure = 0; + + protected: + virtual float FilterValue( float AValue ) override + { + return ( 44330.0 * ( 1 - pow( AValue / BaseLinePressure, 1 / 5.255 ))); + } + + }; +//--------------------------------------------------------------------------- + class AltitudePressureToSeaLevelPressure : public CommonTypedFilter + { + public: + float Altitude = 0; + + protected: + virtual float FilterValue( float AValue ) override + { + return ( AValue / pow( 1 - ( Altitude / 44330.0 ), 5.255 )); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Counter.h b/libraries/Mitov/Mitov_Counter.h new file mode 100644 index 0000000..b5d842b --- /dev/null +++ b/libraries/Mitov/Mitov_Counter.h @@ -0,0 +1,173 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_COUNTER_h +#define _MITOV_COUNTER_h + +#include + +namespace Mitov +{ +#define Min Min +#define Max Max + class CounterLimit + { + public: + long Value; + bool RollOver = true; + + public: + CounterLimit( long AValue ) : + Value( AValue ) + { + } + }; +//--------------------------------------------------------------------------- + class BasicCounter : public Mitov::CommonEnableSource + { + typedef Mitov::CommonEnableSource inherited; + + public: + OpenWire::SinkPin ResetInputPin; + + public: + long InitialValue = 0; + + public: + CounterLimit Min = -2147483648; + CounterLimit Max = 2147483647; + + protected: + long FCount = 0; + + protected: + void DoReceiveReset( void *_Data ) + { + FCount = InitialValue; + OutputPin.Notify( &FCount ); + } + + virtual void SystemInit() + { +// Serial.println( "Counter::SystemInit" ); + FCount = InitialValue; + + inherited::SystemInit(); + OutputPin.Notify( &FCount ); + } + + virtual void SystemStart() + { + inherited::SystemStart(); + if( FCount != InitialValue ) + OutputPin.Notify( &FCount ); + + } + + protected: + inline void CountUp() + { + if( Max.RollOver || ( FCount < Max.Value )) + { + ++FCount; + + if( FCount > Max.Value ) + FCount = Min.Value; + + OutputPin.Notify( &FCount ); + } + } + + inline void CountDown() + { + if( Min.RollOver || ( FCount > Min.Value )) + { + --FCount; + if( FCount < Min.Value ) + FCount = Max.Value; + + OutputPin.Notify( &FCount ); + } + } + + public: + BasicCounter() + { + ResetInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicCounter::DoReceiveReset ); + } + + }; +//--------------------------------------------------------------------------- + class Counter : public Mitov::BasicCounter + { + typedef Mitov::BasicCounter inherited; + + public: + OpenWire::SinkPin InputPin; + + public: + bool Reversed = false; + + public: + virtual void DoReceive( void *_Data ) + { + if( ! Enabled ) + return; + + if( Reversed ) + CountDown(); + + else + CountUp(); + + } + + public: + Counter() + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Counter::DoReceive ); + } + + }; +//--------------------------------------------------------------------------- + class UpDownCounter : public Mitov::BasicCounter + { + typedef Mitov::BasicCounter inherited; + + public: + OpenWire::SinkPin UpInputPin; + OpenWire::SinkPin DownInputPin; + + protected: + void DoReceiveUp( void *_Data ) + { + if( Enabled ) + CountUp(); + } + + void DoReceiveDown( void *_Data ) + { + if( Enabled ) + CountDown(); + } + + public: + UpDownCounter() + { + UpInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&UpDownCounter::DoReceiveUp ); + DownInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&UpDownCounter::DoReceiveDown ); + } + + }; +//--------------------------------------------------------------------------- +#undef Min +#undef Max +} + +#endif diff --git a/libraries/Mitov/Mitov_DHT_Sensor.h b/libraries/Mitov/Mitov_DHT_Sensor.h new file mode 100644 index 0000000..0629ca7 --- /dev/null +++ b/libraries/Mitov/Mitov_DHT_Sensor.h @@ -0,0 +1,286 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_DHT_SENSOR_h +#define _MITOV_DHT_SENSOR_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + template class BasicDHTSensor : public OpenWire::Component, public Mitov::ClockingSupport + { + typedef OpenWire::Component inherited; + + const uint32_t MIN_INTERVAL = 2000; + + public: + OpenWire::SourcePin TemperatureOutputPin; + OpenWire::SourcePin HumidityOutputPin; + + public: + bool InFahrenheit = false; + + protected: + uint8_t data[5]; + uint32_t _lastreadtime = -MIN_INTERVAL; + uint32_t _maxcycles; + bool _lastresult = false; + +#ifdef __AVR + // Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask + // for the digital pin connected to the DHT. Other platforms will use digitalRead. + uint8_t _bit, _port; +#endif + +// DHT *FSensor; + + protected: + virtual void SystemInit() override + { + pinMode( PIN_NUMBER, INPUT_PULLUP ); +// FSensor = new DHT( PIN_NUMBER, SENSOR_TYPE ); +// FSensor->begin(); + inherited::SystemInit(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ! ClockInputPin.IsConnected() ) + ReadSensor(); + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + virtual void ReadSensor() = 0; + + uint32_t expectPulse(bool level) + { + uint32_t count = 0; + // On AVR platforms use direct GPIO port access as it's much faster and better + // for catching pulses that are 10's of microseconds in length: +#ifdef __AVR + uint8_t portState = level ? _bit : 0; + while ((*portInputRegister(_port) & _bit) == portState) + // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266 + // right now, perhaps bugs in direct port access functions?). +#else + while (digitalRead(PIN_NUMBER) == level) +#endif + { + if (count++ >= _maxcycles) + return 0; // Exceeded timeout, fail. + } + + return count; + } + + bool TryRead() + { + uint32_t currenttime = millis(); + if ( (currenttime - _lastreadtime) < 2000 ) + return _lastresult; // return last correct measurement + + _lastreadtime = currenttime; + + // Reset 40 bits of received data to zero. + data[0] = data[1] = data[2] = data[3] = data[4] = 0; + + // Send start signal. See DHT datasheet for full signal diagram: + // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf + + // Go into high impedence state to let pull-up raise data line level and + // start the reading process. + digitalWrite( PIN_NUMBER, HIGH); + delay(250); + + // First set data line low for 20 milliseconds. + pinMode( PIN_NUMBER, OUTPUT); + digitalWrite( PIN_NUMBER, LOW); + delay(20); + + uint32_t cycles[80]; + { + // Turn off interrupts temporarily because the next sections are timing critical + // and we don't want any interruptions. + InterruptLock lock; + + // End the start signal by setting data line high for 40 microseconds. + digitalWrite( PIN_NUMBER, HIGH); + delayMicroseconds(40); + + // Now start reading the data line to get the value from the DHT sensor. + pinMode( PIN_NUMBER, INPUT_PULLUP ); + delayMicroseconds(10); // Delay a bit to let sensor pull data line low. + + // First expect a low signal for ~80 microseconds followed by a high signal + // for ~80 microseconds again. + if (expectPulse(LOW) == 0) + { +// DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse.")); + _lastresult = false; + return _lastresult; + } + if (expectPulse(HIGH) == 0) + { +// DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse.")); + _lastresult = false; + return _lastresult; + } + + // Now read the 40 bits sent by the sensor. Each bit is sent as a 50 + // microsecond low pulse followed by a variable length high pulse. If the + // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds + // then it's a 1. We measure the cycle count of the initial 50us low pulse + // and use that to compare to the cycle count of the high pulse to determine + // if the bit is a 0 (high state cycle count < low state cycle count), or a + // 1 (high state cycle count > low state cycle count). Note that for speed all + // the pulses are read into a array and then examined in a later step. + for (int i=0; i<80; i+=2) + { + cycles[i] = expectPulse(LOW); + cycles[i+1] = expectPulse(HIGH); + } + + } // Timing critical code is now complete. + + // Inspect pulses and determine which ones are 0 (high state cycle count < low + // state cycle count), or 1 (high state cycle count > low state cycle count). + for (int i=0; i<40; ++i) + { + uint32_t lowCycles = cycles[2*i]; + uint32_t highCycles = cycles[2*i+1]; + if ((lowCycles == 0) || (highCycles == 0)) + { +// DEBUG_PRINTLN(F("Timeout waiting for pulse.")); + _lastresult = false; + return _lastresult; + } + + data[i/8] <<= 1; + // Now compare the low and high cycle times to see if the bit is a 0 or 1. + if (highCycles > lowCycles) + // High cycles are greater than 50us low cycle count, must be a 1. + data[i/8] |= 1; + + // Else high cycles are less than (or equal to, a weird case) the 50us low + // cycle count so this must be a zero. Nothing needs to be changed in the + // stored data. + } + +/* + DEBUG_PRINTLN(F("Received:")); + DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", ")); + DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? ")); + DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX); +*/ + // Check we read 40 bits and that the checksum matches. + if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) + { + _lastresult = true; + return _lastresult; + } + + else + { + // DEBUG_PRINTLN(F("Checksum failure!")); + _lastresult = false; + return _lastresult; + } + } + + protected: + void DoClockReceive( void *_Data ) override + { + ReadSensor(); + } + + public: + BasicDHTSensor() + { + #ifdef __AVR + _bit = digitalPinToBitMask( PIN_NUMBER ); + _port = digitalPinToPort( PIN_NUMBER ); + #endif + _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for + // reading pulses from DHT sensor. + } + }; +//--------------------------------------------------------------------------- + template class DHT11Sensor : public BasicDHTSensor + { + typedef BasicDHTSensor inherited; + + protected: + virtual void ReadSensor() override + { + if( ! inherited::TryRead()) + return; + + if( inherited::TemperatureOutputPin.IsConnected() ) + { + float AValue = inherited::data[2]; + if( inherited::InFahrenheit ) + AValue = ConvertCtoF( AValue ); + + inherited::TemperatureOutputPin.Notify( &AValue ); + } + + if( inherited::HumidityOutputPin.IsConnected() ) + { + float AValue = inherited::data[0]; + inherited::HumidityOutputPin.Notify( &AValue ); + } + } + }; +//--------------------------------------------------------------------------- + template class DHT22Sensor : public BasicDHTSensor + { + typedef BasicDHTSensor inherited; + + protected: + virtual void ReadSensor() override + { + if( ! inherited::TryRead()) + return; + + if( inherited::TemperatureOutputPin.IsConnected() ) + { + float AValue = inherited::data[2] & 0x7F; + AValue *= 256; + AValue += inherited::data[3]; + AValue *= 0.1; + if( inherited::data[2] & 0x80 ) + AValue *= -1; + + if( inherited::InFahrenheit ) + AValue = ConvertCtoF( AValue ); + + inherited::TemperatureOutputPin.Notify( &AValue ); + } + + if( inherited::HumidityOutputPin.IsConnected() ) + { + float AValue = inherited::data[0]; + AValue *= 256; + AValue += inherited::data[1]; + AValue *= 0.1; + inherited::HumidityOutputPin.Notify( &AValue ); + } + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_DateTime.h b/libraries/Mitov/Mitov_DateTime.h new file mode 100644 index 0000000..c3063b5 --- /dev/null +++ b/libraries/Mitov/Mitov_DateTime.h @@ -0,0 +1,59 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_DATE_DIME_h +#define _MITOV_DATE_DIME_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class EncodeDateTime : public Mitov::BasicCommonMultiInput + { + typedef Mitov::BasicCommonMultiInput inherited; + + public: + TDateTime InitialValue; + bool OnlyModified = false; + + protected: + virtual TDateTime CalculateOutput() override + { + TDateTime ADate; + ADate.TryEncodeDateTime( InputPins[ 0 ].Value, InputPins[ 1 ].Value, InputPins[ 2 ].Value, InputPins[ 3 ].Value, InputPins[ 4 ].Value, InputPins[ 5 ].Value, InputPins[ 6 ].Value ); + return ADate; + } + + }; +//--------------------------------------------------------------------------- + class DecodeDateTime : public CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + OpenWire::SourcePin OutputPins[ 7 ]; + + protected: + virtual void DoReceive( void *_Data ) override + { + TDateTime &ADate = *(TDateTime *)_Data; + uint16_t AItem16[ 7 ]; + ADate.DecodeDateTime( AItem16[ 0 ], AItem16[ 1 ], AItem16[ 2 ], AItem16[ 3 ], AItem16[ 4 ], AItem16[ 5 ], AItem16[ 6 ] ); + for( int i = 0; i < 7; ++ i ) + { + long int AValue = AItem16[ i ]; + OutputPins[ i ].Notify( &AValue ); + } + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_DigitalsToUnsigned.h b/libraries/Mitov/Mitov_DigitalsToUnsigned.h new file mode 100644 index 0000000..74b3993 --- /dev/null +++ b/libraries/Mitov/Mitov_DigitalsToUnsigned.h @@ -0,0 +1,36 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_DIGITALS_TO_UNSIGNED_h +#define _MITOV_DIGITALS_TO_UNSIGNED_h + +#include + +namespace Mitov +{ + template class DigitalsToUnsigned : public Mitov::BasicCommonMultiInput + { + typedef Mitov::BasicCommonMultiInput inherited; + + protected: + virtual uint32_t CalculateOutput() override + { + uint32_t AValue = 0; + for( uint32_t i = C_NUM_INPUTS; i--; ) + if( inherited::InputPins[ i ].Value ) + AValue |= ((uint32_t)1) << i; + + return AValue; + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Display4DSystems.h b/libraries/Mitov/Mitov_Display4DSystems.h new file mode 100644 index 0000000..85b7325 --- /dev/null +++ b/libraries/Mitov/Mitov_Display4DSystems.h @@ -0,0 +1,625 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_DISPLAY_4D_SYSTEMS_h +#define _MITOV_DISPLAY_4D_SYSTEMS_h + +#include +#include + +namespace Mitov +{ + + +/* + void myGenieEventHandler(void) + { + Serial.println( "myGenieEventHandler" ); + } +*/ + class Display4DSystems; +//--------------------------------------------------------------------------- + class ViSiGenieBasicObject : public OpenWire::Object + { + protected: + Display4DSystems &FOwner; + + public: + virtual void Start() {} + virtual void Process() {} + + public: + ViSiGenieBasicObject( Display4DSystems &AOwner ); + + }; +//--------------------------------------------------------------------------- + class ViSiGenieBasicOutObject + { + public: + virtual bool ProcessOut( Genie &AGenie, genieFrame &Event ) = 0; + + public: + ViSiGenieBasicOutObject( Display4DSystems &AOwner ); + + }; +//--------------------------------------------------------------------------- + template class ViSiGenieBasicTypedOutObject : public ViSiGenieBasicOutObject + { + typedef ViSiGenieBasicOutObject inherited; + + protected: + virtual void PrcessInValue( uint16_t AValue ) = 0; + + public: + virtual bool ProcessOut( Genie &AGenie, genieFrame &Event ) override + { +// Serial.println( "ProcessOut" ); + if( Event.reportObject.cmd == GENIE_REPORT_EVENT ) + { +/* + Serial.println( "GENIE_REPORT_EVENT" ); + Serial.print( Event.reportObject.object ); + Serial.print( " - " ); + Serial.println( Event.reportObject.index ); +*/ + if( Event.reportObject.object == V_OBJECT ) + if( Event.reportObject.index == V_INDEX ) + { + uint16_t AValue = AGenie.GetEventData(&Event); +// Serial.println( AValue ); + PrcessInValue( AValue ); + + return true; + } + + return false; + } + } + + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedCharOut : public ViSiGenieBasicTypedOutObject + { + typedef ViSiGenieBasicTypedOutObject inherited; + + public: + OpenWire::SourcePin OutputPin; + +// public: +// bool EnterNewLine; + + protected: + virtual void PrcessInValue( uint16_t AValue ) override + { + char *ATypedValue = (char *)AValue; + OutputPin.Notify( &ATypedValue ); +// if( EnterNewLine ) +// if( *ATypedValue == '\r' ) +// OutputPin.SendValue( '\n' ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class ViSiGenieBasicIn : public ViSiGenieBasicObject + { + typedef ViSiGenieBasicObject inherited; + + public: + OpenWire::SinkPin InputPin; + + protected: + virtual void DoReceive( void *_Data ) = 0; + + public: + ViSiGenieBasicIn( Display4DSystems &AOwner ) : + inherited( AOwner ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ViSiGenieBasicIn::DoReceive ); + } + + }; +//--------------------------------------------------------------------------- + template class ViSiGenieBasicTypedIn : public ViSiGenieBasicIn + { + typedef ViSiGenieBasicIn inherited; + + public: + OpenWire::SinkPin RefreshInputPin; + + public: + bool OnlyChanged : 1; + + public: + bool FStarted : 1; + bool FReceived : 1; + + public: + T_DATA FOldValue; + T_DATA FValue; + + + protected: + virtual void DoReceive( void *_Data ); + + virtual void DoRefreshReceive( void *_Data ) + { + FStarted = false; + } + + public: + ViSiGenieBasicTypedIn( Display4DSystems &AOwner, T_DATA AInitialValue ) : + inherited( AOwner ), + FValue( AInitialValue ), + FOldValue( AInitialValue ), + FStarted( false ), + FReceived( false ), + OnlyChanged( true ) + { + RefreshInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ViSiGenieBasicTypedIn::DoRefreshReceive ); + } + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedIn : public ViSiGenieBasicTypedIn + { + typedef ViSiGenieBasicTypedIn inherited; + + protected: + virtual uint16_t GetValue() { return inherited::FValue; }; + + public: + virtual void Process(); + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedInOut : public ViSiGenieTypedIn, public ViSiGenieBasicTypedOutObject + { + typedef ViSiGenieTypedIn inherited; + + public: + OpenWire::SourcePin OutputPin; +/* + public: + virtual bool ProcessOut( Genie &AGenie, genieFrame &Event ) + { + } +*/ + protected: + virtual void PrcessInValue( uint16_t AValue ) override + { + T_DATA ATypedValue = (T_DATA)AValue; + OutputPin.Notify( &ATypedValue ); + } + + public: + ViSiGenieTypedInOut( Display4DSystems &AOwner, T_DATA AInitialValue ) : + inherited( AOwner, AInitialValue ), + ViSiGenieBasicTypedOutObject( AOwner ) + { + } + }; +//--------------------------------------------------------------------------- +/* + template class ViSiGenieTypedAnalogIn : public ViSiGenieTypedIn + { + typedef ViSiGenieTypedIn inherited; + + protected: + virtual uint16_t GetValue() { return inherited::FValue + 0.5; } override; + + public: + ViSiGenieTypedAnalogIn( Display4DSystems &AOwner ) : + inherited( AOwner, 0.0 ) + { + } + }; +*/ +//--------------------------------------------------------------------------- + template class ViSiGenieTypedUnsignedIn : public ViSiGenieTypedIn + { + typedef ViSiGenieTypedIn inherited; + + public: + using inherited::inherited; + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedUnsignedInOut : public ViSiGenieTypedInOut + { + typedef ViSiGenieTypedInOut inherited; + + public: + using inherited::inherited; + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedDigitalIn : public ViSiGenieTypedIn + { + typedef ViSiGenieTypedIn inherited; + + protected: + virtual uint16_t GetValue() override { return inherited::FValue ? 1 : 0; } + + public: + ViSiGenieTypedDigitalIn( Display4DSystems &AOwner ) : + inherited( AOwner, false ) + { + } + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedDigitalInOut : public ViSiGenieTypedInOut + { + typedef ViSiGenieTypedInOut inherited; + + protected: + virtual uint16_t GetValue() override { return inherited::FValue ? 1 : 0; } + + protected: + bool FOldReceivedValue = false; + + protected: + virtual void PrcessInValue( uint16_t AValue ) + { + bool ATypedValue = (bool)AValue; + if( ! FOldReceivedValue ) + if( ! ATypedValue ) + inherited::OutputPin.SendValue( true ); + + FOldReceivedValue = ATypedValue; + inherited::OutputPin.Notify( &ATypedValue ); + } + + public: + ViSiGenieTypedDigitalInOut( Display4DSystems &AOwner ) : + inherited( AOwner, false ) + { + } + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedColorInOut : public ViSiGenieTypedInOut + { + typedef ViSiGenieTypedInOut inherited; + + protected: + virtual uint16_t GetValue() override + { + return ( ( inherited::FValue.Red >> 3 ) << ( 6 + 5 )) | ( ( inherited::FValue.Green >> 2 ) & 0b111111 ) << 5 | ( ( inherited::FValue.Blue >> 3 ) & 0b11111 ); + } + + virtual void PrcessInValue( uint16_t AValue ) override + { + Mitov::TColor ATypedValue; // = AValue; + ATypedValue.Red = ( AValue & 0b1111100000000000 ) >> ( 6 + 5 - 3 ); //0b1111100000000000 + ATypedValue.Green = ( AValue & 0b11111100000 ) >> ( 5 - 2 ); + ATypedValue.Blue = ( AValue & 0b11111 ) << 3; + inherited::OutputPin.Notify( &ATypedValue ); + } + + public: + ViSiGenieTypedColorInOut( Display4DSystems &AOwner ) : + inherited( AOwner, false ) + { + } + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedStringIn : public ViSiGenieBasicTypedIn + { + typedef ViSiGenieBasicTypedIn inherited; + + protected: + virtual void DoReceive( void *_Data ) override; + virtual void Process() override; + + public: + ViSiGenieTypedStringIn( Display4DSystems &AOwner ) : + inherited( AOwner, "" ) + { + } + }; +//--------------------------------------------------------------------------- + template class ViSiGenieTypedClockInOut : public ViSiGenieBasicIn, public ViSiGenieBasicOutObject + { + typedef ViSiGenieBasicIn inherited; + + public: + OpenWire::SourcePin OutputPin; + + protected: + virtual void DoReceive( void *_Data ) override; + + virtual bool ProcessOut( Genie &AGenie, genieFrame &Event ) override + { +// Serial.println( "ProcessOut" ); + if( Event.reportObject.cmd == GENIE_REPORT_EVENT ) + { +/* + Serial.println( "GENIE_REPORT_EVENT" ); + Serial.print( Event.reportObject.object ); + Serial.print( " - " ); + Serial.println( Event.reportObject.index ); +*/ + if( Event.reportObject.object == V_OBJECT ) + if( Event.reportObject.index == V_INDEX ) + { + OutputPin.Notify( NULL ); +// uint16_t AValue = AGenie.GetEventData(&Event); +// Serial.println( AValue ); +// PrcessInValue( AValue ); + + return true; + } + + return false; + } + } + + public: + ViSiGenieTypedClockInOut( Display4DSystems &AOwner ) : + inherited( AOwner ), + ViSiGenieBasicOutObject( AOwner ) + { + } + }; +//--------------------------------------------------------------------------- + template class ViSiGenieSpectrum : public ViSiGenieBasicObject + { + typedef ViSiGenieBasicObject inherited; + + public: + Mitov::SimpleList > ColumnsInputPins; + + public: + virtual void Process() override; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class Display4DSystems : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SourcePin ResetOutputPin; + + public: + float Contrast = 1.0f; + + public: + Mitov::SimpleList FElements; + Mitov::SimpleList FOutElements; + bool FModified = true; + + public: + Genie FGenie; + + public: + void SetContrast( float AValue ) + { + AValue = constrain( AValue, 0.0, 1.0 ); + if( AValue == Contrast ) + return; + + Contrast = AValue; + FGenie.WriteContrast( Contrast * 15 + 0.5 ); + } + + protected: + Mitov::BasicSerialPort &FSerial; + + protected: + virtual void SystemStart() + { + FGenie.Begin( FSerial.GetStream() ); + + //FGenie.AttachEventHandler(myGenieEventHandler); // Attach the user function Event Handler for processing events + bool AValue = true; + ResetOutputPin.Notify( &AValue ); + + delay( 100 ); + + AValue = false; + ResetOutputPin.Notify( &AValue ); + + delay( 3500 ); + FGenie.WriteContrast( Contrast ); + + for( int i = 0; i < FElements.size(); ++ i ) + FElements[ i ]->Start(); + + inherited::SystemStart(); + } + + virtual void SystemLoopEnd() + { + FGenie.DoEvents(false); // This calls the library each loop to process the queued responses from the display + + if( FModified ) + for( int i = 0; i < FElements.size(); ++ i ) + FElements[ i ]->Process(); + + genieFrame AEvent; + if( FGenie.DequeueEvent(&AEvent)) + { +// Serial.println( "DequeueEvent" ); + for( int i = 0; i < FOutElements.size(); ++ i ) + if( FOutElements[ i ]->ProcessOut( FGenie, AEvent )) + break; + } + + inherited::SystemLoopEnd(); + } + + + public: + Display4DSystems( Mitov::BasicSerialPort &ASerial ) : + FSerial( ASerial ) + { + } + }; +//--------------------------------------------------------------------------- + class ViSiGenieSounds : public ViSiGenieBasicObject + { + typedef ViSiGenieBasicObject inherited; + + public: + Mitov::SimpleList TracksStartInputPins; + + public: + OpenWire::SinkPin StopInputPin; + OpenWire::SinkPin PauseInputPin; + OpenWire::SinkPin ResumeInputPin; + + public: + float Volume; + + public: + void SetVolume( float AValue ) + { + AValue = constrain( AValue, 0.0, 1.0 ); + if( AValue == Volume ) + return; + + Volume = AValue; + FOwner.FGenie.WriteObject( GENIE_OBJ_SOUND, 1, Volume * 100 + 0.5 ); + } + + public: + virtual void Start() + { + for( int i = 0; i < TracksStartInputPins.size(); i ++ ) + { + TracksStartInputPins[ i ].Index = i; + TracksStartInputPins[ i ].SetCallback( this, (OpenWire::TOnPinIndexedReceive)&ViSiGenieSounds::DoIndexReceive ); + } + + FOwner.FGenie.WriteObject( GENIE_OBJ_SOUND, 1, Volume * 100 + 0.5 ); + } + + protected: + void DoIndexReceive( int AIndex, void *_Data ) + { + FOwner.FGenie.WriteObject( GENIE_OBJ_SOUND, 0, AIndex ); + } + + void DoReceiveStop( void *_Data ) + { + FOwner.FGenie.WriteObject( GENIE_OBJ_SOUND, 4, 0 ); + } + + void DoReceivePause( void *_Data ) + { + FOwner.FGenie.WriteObject( GENIE_OBJ_SOUND, 2, 0 ); + } + + void DoReceiveResume( void *_Data ) + { + FOwner.FGenie.WriteObject( GENIE_OBJ_SOUND, 3, 0 ); + } + + public: + ViSiGenieSounds( Display4DSystems &AOwner ) : + inherited( AOwner ) + { + StopInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ViSiGenieSounds::DoReceiveStop ); + PauseInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ViSiGenieSounds::DoReceivePause ); + ResumeInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ViSiGenieSounds::DoReceiveResume ); + } + }; +//--------------------------------------------------------------------------- + ViSiGenieBasicObject::ViSiGenieBasicObject( Display4DSystems &AOwner ) : + FOwner( AOwner ) + { + FOwner.FElements.push_back( this ); + } +//--------------------------------------------------------------------------- + ViSiGenieBasicOutObject::ViSiGenieBasicOutObject( Display4DSystems &AOwner ) + { + AOwner.FOutElements.push_back( this ); + } +//--------------------------------------------------------------------------- + template void ViSiGenieBasicTypedIn::DoReceive( void *_Data ) + { + FValue = *(T_DATA *)_Data; + if( OnlyChanged && FStarted ) + if( FValue == FOldValue ) + return; + + FReceived = true; + FOwner.FModified = true; + } +//--------------------------------------------------------------------------- + template void ViSiGenieTypedIn::Process() + { + if( inherited::OnlyChanged && inherited::FStarted ) + if( inherited::FOldValue == inherited::FValue ) + return; + + if( ! inherited::FReceived ) + return; + + inherited::FStarted = true; + inherited::FOldValue = inherited::FValue; + + inherited::FOwner.FGenie.WriteObject(V_OBJECT, V_INDEX, GetValue() ); + } +//--------------------------------------------------------------------------- + template void ViSiGenieSpectrum::Process() + { + for( int i = 0; i < ColumnsInputPins.size(); i ++ ) + if( ColumnsInputPins[ i ].OldValue != ColumnsInputPins[ i ].Value ) + { + uint16_t AValue = ( i << 8 ) | ( ColumnsInputPins[ i ].Value & 0xFF ); + FOwner.FGenie.WriteObject( GENIE_OBJ_SPECTRUM, V_INDEX, AValue ); + } + + } +//--------------------------------------------------------------------------- + template void ViSiGenieTypedStringIn::DoReceive( void *_Data ) + { + inherited::FValue = (char *)_Data; + if( inherited::OnlyChanged && inherited::FStarted ) + if( inherited::FValue == inherited::FOldValue ) + return; + + inherited::FReceived = true; + inherited::FOwner.FModified = true; + } +//--------------------------------------------------------------------------- + template void ViSiGenieTypedStringIn::Process() + { + if( inherited::OnlyChanged && inherited::FStarted ) + if( inherited::FOldValue == inherited::FValue ) + return; + + if( ! inherited::FReceived ) + return; + + inherited::FStarted = true; + inherited::FOldValue = inherited::FValue; + + inherited::FOwner.FGenie.WriteStr(V_INDEX, inherited::FValue.c_str() ); + } +//--------------------------------------------------------------------------- + template void ViSiGenieTypedClockInOut::DoReceive( void *_Data ) + { + FOwner.FGenie.WriteObject( V_OBJECT, V_INDEX, 0 ); + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_ESP8266.h b/libraries/Mitov/Mitov_ESP8266.h new file mode 100644 index 0000000..cc3fae7 --- /dev/null +++ b/libraries/Mitov/Mitov_ESP8266.h @@ -0,0 +1,662 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_ESP8266_h +#define _MITOV_ESP8266_h + +#include +#include +#include + +//#define __ESP8266__DEBUG__ + +namespace Mitov +{ + class ESP8266; +//--------------------------------------------------------------------------- + class ESP8266RemoteAccessPoint + { + public: + bool Enabled = true; + String SSID; + String Password; + }; +//--------------------------------------------------------------------------- + class ESP8266Encription + { + public: + bool WPA = false; + bool WPA2 = false; + }; +//--------------------------------------------------------------------------- + class ESP8266AccessPoint + { + public: + bool Enabled = true; + String SSID; + String Password; + + unsigned long Channel = 1; + ESP8266Encription Encription; + }; +//--------------------------------------------------------------------------- + class BasicESP8266Socket : public Mitov::BasicSocket + { + typedef Mitov::BasicSocket inherited; + + protected: + ESP8266 &FModule; + bool FRunning = false; + + protected: + BufferPrint FStringPrint; + + public: + virtual bool IsEnabled() + { + return Enabled && FRunning; //FModule.Enabled; + } + + virtual Print *GetPrint() + { + return &FStringPrint; + } + + virtual void BeginPacket() + { + FStringPrint.Value.clear(); + } + + virtual void DataReceived( int connectionId, unsigned char AData ) = 0; + + public: + BasicESP8266Socket( ESP8266 &AModule ); + }; +//--------------------------------------------------------------------------- + class ESP8266 : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SourcePin AccessPointAddressOutputPin; + OpenWire::SourcePin AccessPointMACOutputPin; + + OpenWire::SourcePin StationAddressOutputPin; + OpenWire::SourcePin StationMACOutputPin; + + public: + ESP8266AccessPoint AccessPoint; + Mitov::SimpleObjectList RemoteAccessPoints; + + public: + Mitov::SimpleList Sockets; + + protected: + Mitov::BasicSerialPort &FSerial; + + protected: + Mitov::BasicESP8266Socket *FServerInstance; + + public: + Mitov::BasicESP8266Socket *FConnections[ 4 ]; + + int FReadLength = 0; + int FReadConnectionId = 0; + + public: + bool AssignServerID( BasicESP8266Socket *ASocket ) + { + bool AResult = false; + for( int i = 0; i < 4; ++i ) + if( ! FConnections[ i ] ) + { + FConnections[ i ] = ASocket; + FServerInstance = ASocket; + AResult = true; + } + + return AResult; + } + + void ReleaseServerID( BasicESP8266Socket *ASocket ) + { + if( FServerInstance == ASocket ) + FServerInstance = NULL; + + for( int i = 0; i < 4; ++i ) + if( FConnections[ i ] == ASocket ) + FConnections[ i ] = NULL; + } + + bool AssignConnectionID( BasicESP8266Socket *ASocket, int &AID ) + { + for( int i = 0; i < 4; ++i ) + if( ! FConnections[ i ] ) + { + FConnections[ i ] = ASocket; + AID = i; + return true; + } + + return false; + } + + void ReleaseConnectionID( int AID ) + { + FConnections[ AID ] = FServerInstance; + } + + void SendDirect(String data ) + { +#ifdef __ESP8266__DEBUG__ + Serial.println( data ); +#endif + FSerial.GetStream().print( data ); + WaitSentOK( 2000 ); + } + + void SendDirect( uint8_t *AData, int ASize ) + { +#ifdef __ESP8266__DEBUG__ + Serial.write( AData, ASize ); +#endif + FSerial.GetStream().write( AData, ASize ); + WaitSentOK( 2000 ); + } + + void WaitSentOK( const int timeout ) + { + String response = ""; + long int time = millis(); + + while( timeout > millis() - time) + { + while(FSerial.GetStream().available()) + { + // The esp has data so collecti it + char c = FSerial.GetStream().read(); // read the next character. + response += c; + } + + if( response.indexOf( "SEND OK\r\n" ) >= 0 ) + break; + + } + } + + String SendData(String command, String response_key, const int timeout) + { + String response = ""; + +#ifdef __ESP8266__DEBUG__ + Serial.println( command ); +#endif + FSerial.GetStream().print( command + "\r\n" ); // send the read character to the esp8266 + + long int time = millis(); + + while( timeout > millis() - time) + { + while(FSerial.GetStream().available()) + { + // The esp has data so collecti it + char c = FSerial.GetStream().read(); // read the next character. + response += c; + } + + if( response.indexOf( response_key ) >= 0 ) + break; + + } + +#ifdef __ESP8266__DEBUG__ + Serial.println( response ); +#endif + return response; + } + + bool SendData(String command, const int timeout, String &AResponse ) + { + AResponse = ""; + +#ifdef __ESP8266__DEBUG__ + Serial.println( command ); +#endif + + FSerial.GetStream().print( command + "\r\n" ); // send the read character to the esp8266 + + long int time = millis(); + + while( timeout > millis() - time) + { + while(FSerial.GetStream().available()) + { + // The esp has data so collecti it + char c = FSerial.GetStream().read(); // read the next character. + AResponse += c; + } + + if( AResponse.indexOf( "\r\nOK\r\n" ) >= 0 ) + { +#ifdef __ESP8266__DEBUG__ + Serial.println( AResponse ); +#endif + return true; + } + + if( AResponse.indexOf( "\r\nERROR\r\n" ) >= 0 ) + { +#ifdef __ESP8266__DEBUG__ + Serial.println( AResponse ); +#endif + return false; + } + + if( AResponse.indexOf( "\r\nFAIL\r\n" ) >= 0 ) + { +#ifdef __ESP8266__DEBUG__ + Serial.println( AResponse ); +#endif + return false; + } + + } + +#ifdef __ESP8266__DEBUG__ + Serial.println( AResponse ); +#endif + return false; + } + + bool SendData( String command, const int timeout ) + { + String AResponse; + return SendData( command, timeout, AResponse ); + } + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + +#ifdef __ESP8266__DEBUG__ + Serial.println( "SystemStart" ); +#endif + SendData( "AT+RST", "\r\nready\r\n", 5000 ); +// String AResponse = SendData( "AT+RST", "\r\nready\r\n", 5000 ); +// Serial.println( AResponse ); + +#ifdef __ESP8266__DEBUG__ + Serial.println( "INIT" ); +#endif + + int AMode = 0; + + for( Mitov::SimpleObjectList::iterator Iter = RemoteAccessPoints.begin(); Iter != RemoteAccessPoints.end(); ++Iter ) + if((* Iter)->Enabled ) + { + AMode = 1; + break; + } + + if( AMode == 0 || AccessPoint.Enabled ) + AMode |= 2; // Set it as access point so others can connect + +// AMode = 3; + SendData( "AT+CWMODE=" + String( AMode ), 5000 ); + +// Serial.println( "TTT" ); +// return; + + if( AccessPoint.Enabled ) +// if( AccessPoint.Encription ) + { + String ASSID; + if( AccessPoint.SSID != "" ) + ASSID = AccessPoint.SSID; + + else + ASSID = "Arduino"; + + String AEncoding; + if( AccessPoint.Encription.WPA ) + { + if( AccessPoint.Encription.WPA2 ) + AEncoding = "4"; + + else + AEncoding = "2"; + } + + else + { + if( AccessPoint.Encription.WPA2 ) + AEncoding = "3"; + + else + AEncoding = "0"; + } + + SendData( "AT+CWSAP=\"" + ASSID + "\",\"" + AccessPoint.Password + "\"," + AccessPoint.Channel + "," + AEncoding, 1000 ); + } + + for( Mitov::SimpleObjectList::iterator Iter = RemoteAccessPoints.begin(); Iter != RemoteAccessPoints.end(); ++Iter ) + if((* Iter)->Enabled ) + if((* Iter)->SSID != "" ) + if( SendData( "AT+CWJAP=\"" + (* Iter)->SSID + "\",\"" + (* Iter)->Password + "\"", 20000 )) + break; + + if( AccessPointAddressOutputPin.IsConnected() || AccessPointMACOutputPin.IsConnected() || StationAddressOutputPin.IsConnected() || StationMACOutputPin.IsConnected() ) + { +// Serial.println( "ADDRESS:" ); + String AResponse = SendData( "AT+CIFSR", "\r\nOK\r\n",1000 ); +#ifdef __ESP8266__DEBUG__ + Serial.println( AResponse ); +#endif + + int AAddressPos = AResponse.indexOf( "+CIFSR:APIP,\"" ); + + int AAddressEndPos; + if( AAddressPos >= 0 ) + { + AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 13 ); + if( AAddressEndPos >= 0 ) + { + String Addresses = AResponse.substring( AAddressPos + 13, AAddressEndPos ); + AccessPointAddressOutputPin.Notify( (void *)Addresses.c_str() ); + } + + else + AAddressEndPos = 0; + + } + + else + AAddressEndPos = 0; + + AAddressPos = AResponse.indexOf( "+CIFSR:APMAC,\"", AAddressEndPos ); + if( AAddressPos >= 0 ) + { + AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 14 ); + if( AAddressEndPos >= 0 ) + { + String Addresses = AResponse.substring( AAddressPos + 14, AAddressEndPos ); + AccessPointMACOutputPin.Notify( (void *)Addresses.c_str() ); + } + + else + AAddressEndPos = 0; + + } + else + AAddressEndPos = 0; + + AAddressPos = AResponse.indexOf( "+CIFSR:STAIP,\"", AAddressEndPos ); + if( AAddressPos >= 0 ) + { + AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 14 ); + if( AAddressEndPos >= 0 ) + { + String Addresses = AResponse.substring( AAddressPos + 14, AAddressEndPos ); + StationAddressOutputPin.Notify( (void *)Addresses.c_str() ); + } + + else + AAddressEndPos = 0; + + } + else + AAddressEndPos = 0; + + AAddressPos = AResponse.indexOf( "+CIFSR:STAMAC,\"", AAddressEndPos ); + if( AAddressPos >= 0 ) + { + AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 15 ); + if( AAddressEndPos >= 0 ) + { + String Addresses = AResponse.substring( AAddressPos + 15, AAddressEndPos ); + StationMACOutputPin.Notify( (void *)Addresses.c_str() ); + } + + else + AAddressEndPos = 0; + + } + else + AAddressEndPos = 0; + + } + + SendData( "AT+CIPMUX=1",1000 ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( FSerial.GetStream().available() ) + { +#ifdef __ESP8266__DEBUG__ +// Serial.println( "AVALIABLE" ); +#endif + if( ! FReadLength ) + if(FSerial.GetStream().find("+IPD,")) + { +#ifdef __ESP8266__DEBUG__ + Serial.println( "DATA" ); +#endif +// int connectionId = FSerial.GetStream().read() - '0'; + String AIDStr = FSerial.GetStream().readStringUntil( ',' ); + FReadConnectionId = AIDStr.toInt(); +#ifdef __ESP8266__DEBUG__ + Serial.println( AIDStr ); + Serial.println( FReadConnectionId ); +#endif +// FSerial.GetStream().find("," ); // Skip ',' +// FSerial.GetStream().read(); // Skip ',' + String ALengthStr = FSerial.GetStream().readStringUntil( ':' ); +#ifdef __ESP8266__DEBUG__ + Serial.println( "Length = " + ALengthStr ); +#endif + FReadLength = ALengthStr.toInt(); + } + + if( FReadLength ) + if( FReadConnectionId >= 0 && FReadConnectionId < 4 ) + { + while( FReadLength ) + { + if( ! FSerial.GetStream().available() ) + break; + + int AData = FSerial.GetStream().read(); +//#ifdef __ESP8266__DEBUG__ +// Serial.println( (char)AData ); +//#endif + if( FConnections[ FReadConnectionId ] ) + FConnections[ FReadConnectionId ]->DataReceived( FReadConnectionId, AData ); + + --FReadLength; + } + } + + } + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + ESP8266( Mitov::BasicSerialPort &ASerial ) : + FSerial( ASerial ) + { + memset( FConnections, 0, 4 * sizeof( FConnections[ 0 ] ) ); + } + + }; +//--------------------------------------------------------------------------- + class ESP8266TCPServerSocket : public BasicESP8266Socket + { + typedef BasicESP8266Socket inherited; + +// EthernetServer *FServer; +// EthernetClient FClient; + + int FClientCurrentID = -1; + + protected: + virtual void StartSocket() + { +#ifdef __ESP8266__DEBUG__ + Serial.println( "SERVER::StartSocket" ); +#endif +// if( FModule.AssignConnectionID( this ) ) + if( FModule.AssignServerID( this ) ) + { + FModule.SendData( "AT+CIPSERVER=1," + String( Port ), 2000 ); + FRunning = true; + } + + } + +/* + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + inherited::SystemLoopBegin( currentMicros ); + } +*/ + virtual void DataReceived( int connectionId, unsigned char AData ) + { +#ifdef __ESP8266__DEBUG__ + Serial.print( "RECEIVED: " ); + Serial.println( connectionId ); +#endif + FClientCurrentID = connectionId; + OutputPin.Notify( &AData ); +// FClientCurrentID = -1; + } + + public: + virtual void EndPacket() + { + if( FStringPrint.Value.size() == 0 ) + return; + + if( FClientCurrentID >= 0 ) + { + if( FModule.SendData( "AT+CIPSEND=" + String( FClientCurrentID ) + "," + String( FStringPrint.Value.size()), "\r\n> ", 2000 )) + FModule.SendDirect( (uint8_t *)FStringPrint.Value, FStringPrint.Value.size() ); + +// Serial.println( FStringPrint.Value ); + } + + else + { +/* + for( int i = 0; i < 4; ++ i ) + if( FModule.FConnections[ i ] == this ) + { + if( FModule.SendData( "AT+CIPSEND=" + String( i ) + "," + String( FStringPrint.Value.size()), "\r\n> ", 2000 )) + FModule.SendDirect( (uint8_t *)FStringPrint.Value, FStringPrint.Value.size() ); + + } +*/ + } + +// FStringPrint.Value.clear(); + } + + public: + virtual void StopSocket() + { + if( FRunning ) + { + FModule.SendData( "AT+CIPSERVER=0," + String( Port ), 2000 ); + FModule.ReleaseServerID( this ); + FRunning = false; + } + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class ESP8266TCPClientSocket : public BasicESP8266Socket + { + typedef BasicESP8266Socket inherited; + + public: + String URL; + int FID; + + protected: + virtual void StartSocket() + { +#ifdef __ESP8266__DEBUG__ + Serial.println( "CLIENT::StartSocket" ); +#endif + if( FModule.AssignConnectionID( this, FID ) ) + { + FModule.SendData( "AT+CIPSTART=" + String( FID ) +",\"TCP\",\"" + URL + "\"," + String( Port ), 2000 ); + FRunning = true; + } + +// Serial.println( "StartSocket" ); + } + + virtual void StopSocket() + { + if( FRunning ) + { + FModule.ReleaseConnectionID( FID ); + FModule.SendData( "AT+CIPCLOSE=" + String( FID ), 2000 ); + FRunning = false; + } +// FClient.stop(); + } + + virtual void DataReceived( int connectionId, unsigned char AData ) + { + OutputPin.Notify( &AData ); + } + + public: + virtual void EndPacket() + { + if( FStringPrint.Value.size() == 0 ) + return; + + if( FModule.SendData( "AT+CIPSEND=" + String( FID ) + "," + String( FStringPrint.Value.size()), "\r\n> ", 2000 )) + FModule.SendDirect( (uint8_t *)FStringPrint.Value, FStringPrint.Value.size() ); + +// FStringPrint.Value.clear(); + } + + public: +/* + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + inherited::SystemLoopBegin( currentMicros ); + } +*/ + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + BasicESP8266Socket::BasicESP8266Socket( ESP8266 &AModule ) : + FModule( AModule ) + { + AModule.Sockets.push_back( this ); + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_ESP8266_WiFi.h b/libraries/Mitov/Mitov_ESP8266_WiFi.h new file mode 100644 index 0000000..9175f45 --- /dev/null +++ b/libraries/Mitov/Mitov_ESP8266_WiFi.h @@ -0,0 +1,540 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_ESP8266_WIFI_h +#define _MITOV_ESP8266_WIFI_h + +#include +#include +#include +//#include "ip_addr.h" +//#include "espconn.h" + +namespace Mitov +{ + class ESP8266WiFiModule; +//--------------------------------------------------------------------------- + class ESP8266WiFiModuleOptionalDisabledElement + { + public: + bool Enabled = false; + + }; +//--------------------------------------------------------------------------- + class ESP8266WiFiModuleOptionalChannel : public ESP8266WiFiModuleOptionalDisabledElement + { + public: + unsigned long Channel = 1; + + }; +//--------------------------------------------------------------------------- + class ESP8266WiFiModuleOptionalIPConfig : public ESP8266WiFiModuleOptionalDisabledElement + { + public: + ::IPAddress IP; + + }; +//--------------------------------------------------------------------------- + class ESP8266WiFiModuleAccessPointConfig + { + public: + bool Enabled = false; + + ::IPAddress IP; + ::IPAddress Gateway; + ::IPAddress Subnet; + + }; +//--------------------------------------------------------------------------- + class ESP8266WiFiModuleRemoteConfig : public ESP8266WiFiModuleAccessPointConfig + { + public: + ESP8266WiFiModuleOptionalIPConfig DNS; + }; +//--------------------------------------------------------------------------- + class ESP8266WiFiModuleOptionalMacAddress : public ESP8266WiFiModuleOptionalDisabledElement + { + public: + TMACAddress MacAddress; + + }; +//--------------------------------------------------------------------------- + class ESP8266ModuleRemoteAccessPoint + { + public: + bool Enabled = true; + String SSID; + String Password; + ESP8266WiFiModuleOptionalChannel Channel; + ESP8266WiFiModuleOptionalMacAddress MacAddress; + ESP8266WiFiModuleRemoteConfig Config; + +// protected: +// ESP8266WiFiModule &FOwner; + + public: + bool Connect() + { + if( ! Enabled ) + return false; + + if( SSID == "" ) + return false; + + const char *APassword; + if( Password == "" ) + APassword = NULL; + + else + APassword = Password.c_str(); + + int32_t channel; + + if( Channel.Enabled ) + channel = Channel.Channel; + + else + channel = 0; + + const uint8_t* bssid; + + if( MacAddress.Enabled ) + bssid = MacAddress.MacAddress.FMacAddress; + + else + bssid = NULL; + +// Serial.println( SSID ); +// Serial.println( APassword ); + + if( Config.Enabled ) + { + if( Config.DNS.Enabled ) + WiFi.config( Config.IP, Config.Gateway, Config.Subnet, Config.DNS.IP ); + + else + WiFi.config( Config.IP, Config.Gateway, Config.Subnet); + } + + WiFi.begin( (char *)SSID.c_str(), APassword, channel, bssid ); + + for(;;) + { +// Serial.print( "." ) ; + int ARes = WiFi.status(); + if( ARes == WL_CONNECTED ) + return true; + + if( ARes == WL_CONNECT_FAILED ) + return false; + + delay(500); + } + +/* + while (WiFi.status() != WL_CONNECTED) { + WL_CONNECT_FAILED + + return ( ARes == WL_CONNECTED ); +*/ +// return ( WiFi.begin( (char *)SSID.c_str(), APassword, channel, bssid ) == WL_CONNECTED ); + + +// return ( WiFi.begin( (char *)SSID.c_str() ) == WL_CONNECTED ); + + +/* + if( Password == "" ) + return ( LWiFi.connect( SSID.c_str() ) > 0 ); + + switch( Encription ) + { + case liweAuto: + { + if( LWiFi.connectWPA( SSID.c_str(), Password.c_str() ) > 0 ) + return true; + + return( LWiFi.connectWEP( SSID.c_str(), Password.c_str() ) > 0 ); + } + + case liweWEP: + return( LWiFi.connectWEP( SSID.c_str(), Password.c_str() ) > 0 ); + + case liweWPA: + return( LWiFi.connectWPA( SSID.c_str(), Password.c_str() ) > 0 ); + } +*/ + } + + protected: + void RegisterIn( ESP8266WiFiModule &AOwner ); + + public: + ESP8266ModuleRemoteAccessPoint( ESP8266WiFiModule &AOwner, TMACAddress AMacAddress ) : + ESP8266ModuleRemoteAccessPoint( AOwner ) + { + MacAddress.MacAddress = AMacAddress; + } + + ESP8266ModuleRemoteAccessPoint( ESP8266WiFiModule &AOwner ) + { + RegisterIn( AOwner ); + } + + }; +//--------------------------------------------------------------------------- + class ESP8266WiFiModuleAccessPoint + { + protected: + ESP8266WiFiModule *FOwner; + + public: + bool Enabled = true; + String SSID; + String Password; + + unsigned long Channel = 1; + bool IsHidden = false; + + ESP8266WiFiModuleAccessPointConfig Config; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + TryStart(); + + else + WiFi.softAPdisconnect(); + + } + + public: + void TryStart(); + + public: + ESP8266WiFiModuleAccessPoint( ESP8266WiFiModule * AOwner ) : + FOwner( AOwner ) + { + } + }; +//--------------------------------------------------------------------------- + class ESP8266ModuleScanNetworksOperation : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SinkPin ScanInputPin; + + OpenWire::SourcePin CountOutputPin; + + OpenWire::SourcePin SignalStrengthOutputPin; + OpenWire::SourcePin SSIDOutputPin; + OpenWire::SourcePin ChannelOutputPin; + OpenWire::SourcePin EncryptionOutputPin; + OpenWire::SourcePin IsHiddenOutputPin; + OpenWire::SourcePin MACAddressOutputPin; + + OpenWire::TypedSourcePin ScanningOutputPin; + OpenWire::SourcePin FailedOutputPin; + OpenWire::SourcePin FoundNetworkOutputPin; + + protected: + bool FScanRequest = false; + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + inherited::SystemLoopBegin( currentMicros ); + ScanningOutputPin.SetValue( FScanRequest, true ); + if( FScanRequest ) + { + int8_t AComplete = WiFi.scanComplete(); + if( AComplete == WIFI_SCAN_FAILED ) + { + FailedOutputPin.Notify( NULL ); + CountOutputPin.SendValue( 0 ); + FScanRequest = false; + } + + else if( AComplete >= 0 ) + { + CountOutputPin.SendValue( (int)AComplete ); + for( int i = 0; i < AComplete; i ++ ) + { + String ssid; + uint8_t encryptionType; + int32_t ASetrength; + uint8_t* BSSID; + int32_t channel; + bool isHidden; + if( WiFi.getNetworkInfo( i, ssid, encryptionType, ASetrength, BSSID, channel, isHidden )) + { + String BSSIDStr = WiFi.BSSIDstr( i ); + + SSIDOutputPin.Notify( (void *)ssid.c_str() ); + SignalStrengthOutputPin.Notify( &ASetrength ); + EncryptionOutputPin.Notify( &encryptionType ); + MACAddressOutputPin.Notify( (void *)BSSIDStr.c_str() ); + ChannelOutputPin.Notify( &channel ); + IsHiddenOutputPin.Notify( &isHidden ); + } + + FoundNetworkOutputPin.Notify( NULL ); + } + + FScanRequest = false; + } + } + } + + protected: + void DoScanNetworks( void *_Data ) + { + if( WiFi.scanComplete() != WIFI_SCAN_RUNNING ) + { + WiFi.scanNetworks( true ); + FScanRequest = true; + } +/* + for( int i = 0; i < nearbyAccessPointCount; i ++ ) + { + FoundSSIDOutputPin.Notify( LWiFi.SSID( i )); + + int32_t ASetrength = LWiFi.RSSI( i ); + FoundSignalStrengthOutputPin.Notify( &ASetrength ); + } +*/ + } + + public: + ESP8266ModuleScanNetworksOperation() + { + ScanInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ESP8266ModuleScanNetworksOperation::DoScanNetworks ); + } + }; +//--------------------------------------------------------------------------- + class ESP8266WiFiModule : public Mitov::BasicEthernetShield + { + typedef Mitov::BasicEthernetShield inherited; + + public: + OpenWire::SourcePin AddressOutputPin; + OpenWire::SourcePin MACOutputPin; + + OpenWire::SourcePin BSSIDOutputPin; + OpenWire::SourcePin GatewayIPOutputPin; + OpenWire::SourcePin SubnetMaskIPOutputPin; + + OpenWire::TypedSourcePin RemoteConnectedOutputPin; + + public: + ESP8266WiFiModuleAccessPoint AccessPoint; + Mitov::SimpleObjectList AccessPoints; + + public: + bool AutoReconnect = true; + String HostName; + + public: + bool IsStarted = false; + + public: + virtual bool GetIPFromHostName( String AHostName, ::IPAddress &AAdress ) + { + bool AResult = ( WiFi.hostByName( AHostName.c_str(), AAdress ) == 1 ); + if( ! AResult ) + AAdress = INADDR_NONE; + + return AResult; + } + + protected: + void StopEthernet() + { + inherited::StopEthernet(); + + WiFi.disconnect( true ); + IsStarted = false; + } + + void StartEthernet() + { +/* + if( ! AccessPoints.length() ) + return; + + if( ! Sockets.length() ) + return; +*/ +// Serial.println( "TRY CONNECT" ); + if( HostName != "" ) + { + WiFi.hostname( HostName ); +// espconn_mdns_set_hostname( (char *) HostName.c_str() ); + } + + + bool AConnected = false; + for( int i = 0; i < AccessPoints.size(); ++i ) + if( AccessPoints[ i ]->Connect() ) + { + AConnected = true; +// Serial.println( "CONNECT" ); + + if( AddressOutputPin.IsConnected() ) + { + String IPAddress = IPAdressToString( WiFi.localIP()); + AddressOutputPin.Notify( (void *)IPAddress.c_str() ); + } + + IsStarted = true; +// MACOutputPin; + break; + } + + if( ! AConnected ) + WiFi.begin(); + + RemoteConnectedOutputPin.SetValue( AConnected, true ); + + WiFi.setAutoReconnect( AutoReconnect ); + + AccessPoint.TryStart(); + + if( BSSIDOutputPin.IsConnected() ) + BSSIDOutputPin.SendValue( WiFi.BSSIDstr() ); + + if( GatewayIPOutputPin.IsConnected() ) + GatewayIPOutputPin.SendValue( IPAdressToString( WiFi.gatewayIP() )); + + if( SubnetMaskIPOutputPin.IsConnected() ) + SubnetMaskIPOutputPin.SendValue( IPAdressToString( WiFi.subnetMask() )); + + + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( RemoteConnectedOutputPin.IsConnected() ) + RemoteConnectedOutputPin.SetValue( WiFi.isConnected(), true ); + + inherited::SystemLoopBegin( currentMicros ); + } + +/* + void DoCheckSignalStrength( void *_Data ) + { + if( IsStarted ) + if( SignalStrengthOutputPin.IsConnected() ) + { + int32_t ASetrength = WiFi.RSSI(); + SignalStrengthOutputPin.Notify( &ASetrength ); + } + + } +*/ + public: + ESP8266WiFiModule() : + AccessPoint( this ) + { +// ScanNetworksInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ESP8266WiFiModule::DoScanNetworks ); +// CheckSignalStrengthInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ESP8266WiFiModule::DoCheckSignalStrength ); + } + + }; +//--------------------------------------------------------------------------- + class ESP8266ModuleClockedOperation : public Mitov::ClockingSupport + { + protected: + ESP8266WiFiModule &FOwner; + + public: + ESP8266ModuleClockedOperation( ESP8266WiFiModule &AOwner ) : + FOwner( AOwner ) + { + } + }; +//--------------------------------------------------------------------------- + class ESP8266ModuleSignalStrengthOperation : public ESP8266ModuleClockedOperation + { + typedef ESP8266ModuleClockedOperation inherited; + + public: + OpenWire::SourcePin SignalStrengthOutputPin; + + protected: + virtual void DoClockReceive( void *_Data ) override + { + if( inherited::FOwner.IsStarted ) + if( SignalStrengthOutputPin.IsConnected() ) + { + int32_t ASetrength = WiFi.RSSI(); + SignalStrengthOutputPin.Notify( &ASetrength ); + } + + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class ESP8266ModuleReconnectOperation : public ESP8266ModuleClockedOperation + { + typedef ESP8266ModuleClockedOperation inherited; + + protected: + virtual void DoClockReceive( void *_Data ) override + { + WiFi.reconnect(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + void ESP8266WiFiModuleAccessPoint::TryStart() + { + if( FOwner->Enabled ) + if( Enabled ) + if( SSID != "" ) + { +//Serial.println( "TEST1" ); +//Serial.println( SSID ); +//Serial.println( IsHidden ); + if( Config.Enabled ) + WiFi.softAPConfig( Config.IP, Config.Gateway, Config.Subnet ); + + if( Password != "" ) + WiFi.softAP( SSID.c_str(), Password.c_str(), Channel, IsHidden ); + + else +// WiFi.softAP( SSID.c_str() ); + WiFi.softAP( SSID.c_str(), NULL, Channel, IsHidden ); + + WiFi.softAPIP(); + } + + } +//--------------------------------------------------------------------------- + void ESP8266ModuleRemoteAccessPoint::RegisterIn( ESP8266WiFiModule &AOwner ) + { + AOwner.AccessPoints.push_back( this ); + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_EthernetShield.h b/libraries/Mitov/Mitov_EthernetShield.h new file mode 100644 index 0000000..8e952c2 --- /dev/null +++ b/libraries/Mitov/Mitov_EthernetShield.h @@ -0,0 +1,148 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_ETHERNET_SHIELD_h +#define _MITOV_ETHERNET_SHIELD_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class EthernetShield : public Mitov::BasicEthernetShield + { + typedef Mitov::BasicEthernetShield inherited; + + protected: + TMACAddress FMacAddress; + + public: + ShieldIPAddress IPAddress; + bool UseDHCP; + + protected: + virtual void StartEthernet() + { +// int AIndex = ((int)Parity) * 2 * 4 + ( StopBits - 1 ) + ( DataBits - 5); +// T_SERIAL->begin( Speed ); + +// Serial.println( "StartEthernet" ); + + if( ! IPAddress.Enabled ) + Ethernet.begin( FMacAddress.FMacAddress ); + + else + { + if( UseDHCP ) + if( Ethernet.begin( FMacAddress.FMacAddress )) + return; + + if( ! IPAddress.DNS.Enabled ) + { +/* + Serial.println( "StartEthernet IP" ); + Serial.print( FMacAddress.FMacAddress[ 0 ] ); + Serial.print( FMacAddress.FMacAddress[ 1 ] ); + Serial.print( FMacAddress.FMacAddress[ 2 ] ); + Serial.print( FMacAddress.FMacAddress[ 3 ] ); + Serial.println(); + IPAddress.IP.printTo( Serial ); + Serial.println(); +*/ + Ethernet.begin( FMacAddress.FMacAddress, IPAddress.IP ); + } + + else + { + if( ! IPAddress.DNS.Gateway.Enabled ) + Ethernet.begin( FMacAddress.FMacAddress, IPAddress.IP, IPAddress.DNS.IP ); + + else + { + if( ! IPAddress.DNS.Gateway.Subnet.Enabled ) + Ethernet.begin( FMacAddress.FMacAddress, IPAddress.IP, IPAddress.DNS.IP, IPAddress.DNS.Gateway.IP ); + + else + Ethernet.begin( FMacAddress.FMacAddress, IPAddress.IP, IPAddress.DNS.IP, IPAddress.DNS.Gateway.IP, IPAddress.DNS.Gateway.Subnet.IP ); + + } + } + } + } + + public: + virtual bool GetIPFromHostName( String AHostName, ::IPAddress &AAdress ) + { + DNSClient ADNSClient; + + ADNSClient.begin( Ethernet.dnsServerIP() ); + + bool AResult = ( ADNSClient.getHostByName( AHostName.c_str(), AAdress ) == 1 ); + if( ! AResult ) + AAdress = INADDR_NONE; + + return AResult; + } + + public: + EthernetShield( TMACAddress AMacAddress ) : + FMacAddress( AMacAddress ), + UseDHCP( false ) + { + } + + EthernetShield( TMACAddress AMacAddress, bool UseDHCP, ::IPAddress local_ip) : + FMacAddress( AMacAddress ), + UseDHCP( UseDHCP ) + { + IPAddress.Enabled = true; + IPAddress.IP = local_ip; + } + + EthernetShield( TMACAddress AMacAddress, bool UseDHCP, ::IPAddress local_ip, ::IPAddress dns_server) : + FMacAddress( AMacAddress ), + UseDHCP( UseDHCP ) + { + IPAddress.Enabled = ! UseDHCP; + IPAddress.IP = local_ip; + IPAddress.DNS.Enabled = true; + IPAddress.DNS.IP = dns_server; + } + + EthernetShield( TMACAddress AMacAddress, bool UseDHCP, ::IPAddress local_ip, ::IPAddress dns_server, ::IPAddress gateway) : + FMacAddress( AMacAddress ), + UseDHCP( UseDHCP ) + { + IPAddress.Enabled = ! UseDHCP; + IPAddress.IP = local_ip; + IPAddress.DNS.Enabled = true; + IPAddress.DNS.IP = dns_server; + IPAddress.DNS.Gateway.Enabled = true; + IPAddress.DNS.Gateway.IP = dns_server; + } + + EthernetShield( TMACAddress AMacAddress, bool UseDHCP, ::IPAddress local_ip, ::IPAddress dns_server, ::IPAddress gateway, ::IPAddress subnet) : + FMacAddress( AMacAddress ), + UseDHCP( UseDHCP ) + { + IPAddress.Enabled = ! UseDHCP; + IPAddress.IP = local_ip; + IPAddress.DNS.Enabled = true; + IPAddress.DNS.IP = dns_server; + IPAddress.DNS.Gateway.Enabled = true; + IPAddress.DNS.Gateway.IP = dns_server; + IPAddress.DNS.Gateway.Subnet.Enabled = true; + IPAddress.DNS.Gateway.Subnet.IP = dns_server; + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_FormattedSerial.h b/libraries/Mitov/Mitov_FormattedSerial.h new file mode 100644 index 0000000..4445a11 --- /dev/null +++ b/libraries/Mitov/Mitov_FormattedSerial.h @@ -0,0 +1,152 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_FORMATTED_SERIAL_h +#define _MITOV_FORMATTED_SERIAL_h + +#include + +namespace Mitov +{ +#ifdef VISUINO_ESP8266 + const SerialConfig CSerialInits[] = +#else + const long CSerialInits[] = +#endif + { + SERIAL_5N1, + SERIAL_6N1, + SERIAL_7N1, + SERIAL_8N1, + SERIAL_5N2, + SERIAL_6N2, + SERIAL_7N2, + SERIAL_8N2, + SERIAL_5E1, + SERIAL_6E1, + SERIAL_7E1, + SERIAL_8E1, + SERIAL_5E2, + SERIAL_6E2, + SERIAL_7E2, + SERIAL_8E2, + SERIAL_5O1, + SERIAL_6O1, + SERIAL_7O1, + SERIAL_8O1, + SERIAL_5O2, + SERIAL_6O2, + SERIAL_7O2, + SERIAL_8O2 + }; +//--------------------------------------------------------------------------- + template class SerialPort : public Mitov::SpeedSerialPort + { + typedef Mitov::SpeedSerialPort inherited; + + public: + TArduinoSerialParity Parity : 4; + unsigned int StopBits : 4; + unsigned int DataBits : 4; + +#ifdef VISUINO_ESP8266 + bool ReceiveEnabled : 1; + bool TransmitEnabled : 1; + + void SetReceiveEnabled( bool AValue ) + { + if( ReceiveEnabled == AValue ) + return; + + ReceiveEnabled = AValue; + ResetSerial(); + } + + void SetTransmitEnabled( bool AValue ) + { + if( TransmitEnabled == AValue ) + return; + + TransmitEnabled = AValue; + ResetSerial(); + } + + protected: + void ResetSerial() + { + T_SERIAL->end(); + StartPort(); + } + + +#endif // VISUINO_ESP8266 + public: + void SetParity( TArduinoSerialParity AValue ) + { + if( Parity == AValue ) + return; + + Parity = AValue; + inherited::RestartPort(); + } + + void SetStopBits( unsigned int AValue ) + { + if( StopBits == AValue ) + return; + + StopBits = AValue; + inherited::RestartPort(); + } + + void SetDataBits( unsigned int AValue ) + { + if( DataBits == AValue ) + return; + + DataBits = AValue; + inherited::RestartPort(); + } + + protected: + virtual void StartPort() + { + int AIndex = ((int)Parity) * 8 + ( StopBits - 1 ) * 4 + ( DataBits - 5); +#ifdef VISUINO_ESP8266 + if( ReceiveEnabled && TransmitEnabled ) + T_SERIAL->begin( inherited::Speed, CSerialInits[ AIndex ], SERIAL_FULL ); + + else if( ReceiveEnabled ) + T_SERIAL->begin( inherited::Speed, CSerialInits[ AIndex ], SERIAL_RX_ONLY ); + + else if( TransmitEnabled ) + T_SERIAL->begin( inherited::Speed, CSerialInits[ AIndex ], SERIAL_TX_ONLY ); + +#else // VISUINO_ESP8266 + T_SERIAL->begin( inherited::Speed, CSerialInits[ AIndex ] ); +#endif // VISUINO_ESP8266 + } + + public: + SerialPort() : +#ifdef VISUINO_ESP8266 + ReceiveEnabled( true ), + TransmitEnabled( true ), +#endif // VISUINO_ESP8266 + Parity( spNone ), + StopBits( 1 ), + DataBits( 8 ) + { + } + }; +//--------------------------------------------------------------------------- +} // Mitov + +#endif + diff --git a/libraries/Mitov/Mitov_FrequencyMeter.h b/libraries/Mitov/Mitov_FrequencyMeter.h new file mode 100644 index 0000000..70596e7 --- /dev/null +++ b/libraries/Mitov/Mitov_FrequencyMeter.h @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_FREQUENCY_METER_h +#define _MITOV_FREQUENCY_METER_h + +#include + +namespace Mitov +{ + class FrequencyMeter : public Mitov::CommonEnableFilter + { + typedef Mitov::CommonFilter inherited; + + protected: + unsigned long FStartTime = 0; + bool FFirstTime = true; + + protected: + virtual void DoReceive( void *_Data ) + { + if( FFirstTime ) + { + FFirstTime = false; + FStartTime = micros(); + return; + } + + if( ! Enabled ) + return; + + unsigned long ANow = micros(); + unsigned long APeriod = ANow - FStartTime; + FStartTime = ANow; + + if( APeriod == 0 ) + APeriod = 1; + + float AFrequency = 1000000.0f / APeriod; + OutputPin.Notify( &AFrequency ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_GPRS.h b/libraries/Mitov/Mitov_GPRS.h new file mode 100644 index 0000000..b203a41 --- /dev/null +++ b/libraries/Mitov/Mitov_GPRS.h @@ -0,0 +1,187 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_GPRS_h +#define _MITOV_GPRS_h + +#include +#include +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class GPRSModule : public Mitov::GSMModule + { + typedef Mitov::GSMModule inherited; + + public: + Mitov::SimpleList*> Sockets; + + public: + bool Enabled = true; + + Mitov::SimpleObjectList AccessPoints; + + protected: + GSMShield &FOwner; + + protected: + GPRS FGprs; + bool FConnected = false; + + public: + bool IsStarted = false; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartEthernet(); + + else + StopEthernet(); + + } + + protected: + virtual void StartModule() + { + if( Enabled ) + StartEthernet(); + + inherited::StartModule(); + } + + void StopEthernet() + { + for( int i = 0; i < Sockets.size(); ++i ) + Sockets[ i ]->StopSocket(); + +// LWiFi.end(); + IsStarted = false; + } + + void StartEthernet() + { + if( ! FOwner.IsStarted ) + return; +/* + if( ! AccessPoints.length() ) + return; + + if( ! Sockets.length() ) + return; +*/ + TryConnect( true, 0 ); +// if( AccessPoint != "" ) +// IsStarted = FGprs.attachGPRS( (char *)AccessPoint.c_str(), (char *)UserName.c_str(), (char *)Password.c_str() ); + +// else +// AConnected = FGprs.attachGPRS(); + +/* + if( AConnected ) + { + } +*/ + } + + void TryConnect( bool FromStart, unsigned long currentMicros ) + { + for( int i = 0; i < AccessPoints.size(); i ++ ) + if( AccessPoints[ i ]->Enabled ) + { + if( ! FromStart ) + if( ! AccessPoints[ i ]->CanRetry( currentMicros ) ) + continue; + + FConnected = FGprs.attachGPRS( (char *)AccessPoints[ i ]->AccessPoint.c_str(), (char *)AccessPoints[ i ]->UserName.c_str(), (char *)AccessPoints[ i ]->Password.c_str() ); + if( FConnected ) + break; + + AccessPoints[ i ]->FLastTime = currentMicros; + ++ AccessPoints[ i ]->FRetryCount; + } + + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! FConnected ) + TryConnect( false, currentMicros ); + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + GPRSModule( GSMShield &AOwner ) : + FOwner( AOwner ) + { + AOwner.Modules.push_back( this ); + } + + }; +//--------------------------------------------------------------------------- +/* + class LinkItWiFiTCPClientSocket : public TCPClientSocket + { + typedef TCPClientSocket inherited; + + public: + virtual bool CanSend() + { + return inherited::Enabled && inherited::FOwner.Enabled && FClient; + } + + public: + LinkItWiFiTCPClientSocket( LinkItWiFiModule &AOwner, ::IPAddress AIPAddress ) : + inherited( AOwner, AIPAddress ) + { + } + + }; +//--------------------------------------------------------------------------- + class LinkItWiFiTCPServerSocket : public TCPServerSocket + { + typedef TCPServerSocket inherited; + + public: + virtual bool CanSend() + { + return inherited::Enabled && inherited::FOwner.Enabled && FClient; + } + + public: + LinkItWiFiTCPServerSocket( LinkItWiFiModule &AOwner ) : + inherited( AOwner ) + { + } + }; +//--------------------------------------------------------------------------- + class LinkItWiFiUDPSocket : public UDPSocket + { + typedef UDPSocket inherited; + + public: + LinkItWiFiUDPSocket( LinkItWiFiModule &AOwner, ::IPAddress ARemoteIPAddress ) : + inherited( AOwner, ARemoteIPAddress ) + { + } + }; +//--------------------------------------------------------------------------- +*/ +} + +#endif diff --git a/libraries/Mitov/Mitov_GSMShield.h b/libraries/Mitov/Mitov_GSMShield.h new file mode 100644 index 0000000..9e4f4fa --- /dev/null +++ b/libraries/Mitov/Mitov_GSMShield.h @@ -0,0 +1,113 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_GSM_SHIELD_h +#define _MITOV_GSM_SHIELD_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class GSMModule : public OpenWire::Component + { + public: + virtual void StartModule() + { + } + + virtual void StopModule() + { + } + }; +//--------------------------------------------------------------------------- + class GSMShield : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + bool Enabled = true; + + String PIN; + bool Restart = true; + + public: + bool IsStarted = false; + + public: + Mitov::SimpleList Modules; + + protected: + GSM FGsm; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartShield(); + + else + StopShield(); + + } + + protected: + virtual void SystemInit() + { + if( Enabled ) + StartShield(); + + inherited::SystemInit(); + } + + void StopShield() + { + for( int i = 0; i < Modules.size(); ++i ) + Modules[ i ]->StopModule(); + + FGsm.shutdown(); + IsStarted = false; + } + +/* + void RestartShield() + { + if( ! Enabled ) + return; + + StartShield(); + } +*/ + void StartShield() + { + if( PIN == "" ) + { +// if( ! Restart ) + IsStarted = ( FGsm.begin( 0, Restart ) == GSM_READY ); + +// else +// IsStarted = ( FGsm.begin() == GSM_READY ); + } + + else + IsStarted = ( FGsm.begin( (char *)PIN.c_str(), Restart ) == GSM_READY ); + + for( int i = 0; i < Modules.size(); ++i ) + Modules[ i ]->StartModule(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_GaussGenerator.h b/libraries/Mitov/Mitov_GaussGenerator.h new file mode 100644 index 0000000..1911de8 --- /dev/null +++ b/libraries/Mitov/Mitov_GaussGenerator.h @@ -0,0 +1,99 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_GAUSS_GENERATOR_h +#define _MITOV_GAUSS_GENERATOR_h + +#include +#include "Mitov_BasicGenerator.h" + +namespace Mitov +{ + template class CommonGaussGenerator : public Mitov::BasicGenerator + { + typedef Mitov::BasicGenerator inherited; + + public: + T Mean; + T StandardDeviation; + long Seed = 0; + + protected: + uint8_t FIndex = 0; + T FRandoms[ 2 ]; + + protected: + virtual void SystemStart() + { + randomSeed( Seed ); + + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! inherited::ClockInputPin.IsConnected() ) + Generate(); + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + void Generate() + { + if( inherited::Enabled ) + { + if( ! FIndex ) + { + float W; + float X1; + float X2; + do + { + X1 = random( -1147483648, 1147483647 ) / 1147483647.0; + X2 = random( -1147483648, 1147483647 ) / 1147483647.0; + W = X1 * X1 + X2 * X2; + } + while( W >= 1.0 ); + + W = StandardDeviation * sqrt( (-2.0 * log( W ) ) / W ); + Serial.println( W ); + Serial.println( Mean ); + Serial.println( X1 ); + Serial.print( "RESULT1: " ); Serial.println( Mean + X1 * W ); + Serial.println( X2 ); + Serial.print( "RESULT2: " ); Serial.println( Mean + X2 * W ); + FRandoms[ 0 ] = Mean + X1 * W; + FRandoms[ 1 ] = Mean + X2 * W; + } + + inherited::FValue = FRandoms[ FIndex ]; + FIndex = FIndex ^ 1; + } + + inherited::SendOutput(); + } + + virtual void DoClockReceive( void *_Data ) + { + Generate(); + } + + public: + CommonGaussGenerator( T AMean, T AStandardDeviation ) : + Mean( AMean ), + StandardDeviation( AStandardDeviation ) + { + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Goldilocks_DAC.h b/libraries/Mitov/Mitov_Goldilocks_DAC.h new file mode 100644 index 0000000..e873610 --- /dev/null +++ b/libraries/Mitov/Mitov_Goldilocks_DAC.h @@ -0,0 +1,58 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_GOLDILOCKS_DAC_h +#define _MITOV_GOLDILOCKS_DAC_h + +#include +#include + +namespace Mitov +{ + class GoldilocksDAC : public OpenWire::Component, public Mitov::ClockingSupport + { + typedef OpenWire::Component inherited; + + public: + OpenWire::VlaueSinkPin InputPins[ 2 ]; + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + DAC_init(TRUE); + } + + protected: + void DoReceive( void *_Data ) + { + if( ClockInputPin.IsConnected() ) + return; + + DoClockReceive( _Data ); + } + + void DoClockReceive( void *_Data ) + { + uint16_t aValue = InputPins[ 0 ].Value * 1023 + 0.5; + uint16_t bValue = InputPins[ 1 ].Value * 1023 + 0.5; + DAC_out( &aValue, &bValue ); + } + + public: + GoldilocksDAC() + { + InputPins[ 0 ].SetCallback( MAKE_CALLBACK( GoldilocksDAC::DoReceive )); + InputPins[ 1 ].SetCallback( MAKE_CALLBACK( GoldilocksDAC::DoReceive )); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_HMC5883_Compass.h b/libraries/Mitov/Mitov_HMC5883_Compass.h new file mode 100644 index 0000000..2301da8 --- /dev/null +++ b/libraries/Mitov/Mitov_HMC5883_Compass.h @@ -0,0 +1,219 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_HMC5883L_h +#define _MITOV_HMC5883L_h + +#include +#include //I2C Arduino Library + +namespace Mitov +{ + + const byte HMC5883L_Address = 0x1E; + const byte HMC5883L_StatusRegister = 9; + const byte HMC5883L_ModeRegister = 2; + const byte HMC5883_REGISTER_MAG_CRA_REG_M = 0x00; + const byte HMC5883_REGISTER_MAG_CRB_REG_M = 0x01; + const byte HMC5883_REGISTER_MAG_OUT_X_H_M = 0x03; +//--------------------------------------------------------------------------- + enum HMC5883L_AveragedSamples { cas1, cas2, cas4, cas8 }; + enum HMC5883L_Bias { cbNone, cbPositive, cbNegative }; + enum HMC5883L_Gain { cg1370, cg1090, cg820, cg660, cg440, cg390, cg330, cg230 }; +//--------------------------------------------------------------------------- + class HMC5883L_Compass : public Mitov::EnabledComponent, public Mitov::ClockingSupport + { + typedef Mitov::EnabledComponent inherited; + + public: + OpenWire::TypedSourcePin XOutputPin; + OpenWire::TypedSourcePin YOutputPin; + OpenWire::TypedSourcePin ZOutputPin; + + public: + HMC5883L_AveragedSamples AveragedSamples : 2; + HMC5883L_Bias Bias : 2; + HMC5883L_Gain Gain : 3; + bool Idle : 1; + + protected: + bool FClocked : 1; + bool FChangeOnly : 1; + + public: + void SetIdle( bool AValue ) + { + if( Idle == AValue ) + return; + + Idle = AValue; + SetIntIdle(); + } + + protected: + float FScale; + + protected: + void SetIntIdle() + { + if( Idle ) + WriteTo( HMC5883L_Address, 0b11 ); // Idle + + else + WriteTo( HMC5883L_Address, 0b00 ); // Single measurement mode +// WriteTo( HMC5883L_Address, 0b01 ); // Single measurement mode + } + + bool DataAvailable() + { + StartReadFrom( HMC5883L_StatusRegister, 1 ); + + uint8_t AStatus = Wire.read(); + return( AStatus & 1 ); + } + + void ReadCompass() + { + if( ! Enabled ) + return; + + if( ! DataAvailable() ) + return; + + FClocked = false; + + StartReadFrom( HMC5883_REGISTER_MAG_OUT_X_H_M, 6 ); + + union T16BitData + { + uint8_t Bytes[ 2 ]; + int16_t Value; + }; + + T16BitData A16BitValue; + float AValue; + + A16BitValue.Bytes[ 1 ] = Wire.read(); + A16BitValue.Bytes[ 0 ] = Wire.read(); + +/* + float _magData_x = ((int16_t)A16BitValue.Bytes[ 0 ] ) | (((int16_t)A16BitValue.Bytes[ 1 ] ) << 8); + + if( A16BitValue.Value != _magData_x ) + { + Serial.print( A16BitValue.Value ); Serial.print( " " ); Serial.println( _magData_x ); + } +*/ +// A16BitValue.Bytes[ 0 ] = 0; +// A16BitValue.Bytes[ 1 ] = 0; + +// Serial.print( "Scale: " ); Serial.println( FScale ); +// Serial.print( "Value: " ); Serial.print( A16BitValue.Bytes[ 0 ] ); Serial.print( " " ); Serial.println( A16BitValue.Bytes[ 1 ] ); +// Serial.print( "Value: " ); Serial.println( A16BitValue.Value ); + AValue = A16BitValue.Value * FScale; + + XOutputPin.SetValue( AValue, FChangeOnly ); + + A16BitValue.Bytes[ 1 ] = Wire.read(); + A16BitValue.Bytes[ 0 ] = Wire.read(); + + AValue = A16BitValue.Value * FScale; + + ZOutputPin.SetValue( AValue, FChangeOnly ); + + A16BitValue.Bytes[ 1 ] = Wire.read(); + A16BitValue.Bytes[ 0 ] = Wire.read(); + + AValue = A16BitValue.Value * FScale; + + YOutputPin.SetValue( AValue, FChangeOnly ); + + FChangeOnly = true; + } + + virtual void DoClockReceive( void *_Data ) override + { + FClocked = true; + ReadCompass(); + } + + protected: + void WriteTo( byte ARegister, byte AData ) + { +// Serial.print( "WriteTo :" ); Serial.print( ARegister ); Serial.print( " " ); Serial.println( AData ); + Wire.beginTransmission( HMC5883L_Address ); + Wire.write( ARegister ); + Wire.write( AData ); + Wire.endTransmission(); + } + + void StartReadFrom( byte ARegister, byte ALength ) + { +// Serial.print( "StartReadFrom :" ); Serial.print( ARegister ); Serial.print( " " ); Serial.println( ALength ); + Wire.beginTransmission( HMC5883L_Address ); + Wire.write( ARegister ); + Wire.endTransmission(); + + Wire.requestFrom( HMC5883L_Address, ALength ); + while (Wire.available() < ALength); + } + + virtual void SystemStart() override + { + uint8_t AValue; + + WriteTo( HMC5883L_ModeRegister, 0 ); + + AValue = ( Bias & 0b11 ) + (( AveragedSamples & 0b11 ) << 5 ); + WriteTo( HMC5883_REGISTER_MAG_CRA_REG_M, AValue ); + + AValue = ( Gain & 0b111 ) << 5; + WriteTo( HMC5883_REGISTER_MAG_CRB_REG_M, AValue ); +// Serial.println( AValue ); +// delay( 10000 ); + + switch( Gain ) + { + case cg1370: FScale = 0.73; break; + case cg1090: FScale = 0.92; break; + case cg820: FScale = 1.22; break; + case cg660: FScale = 1.52; break; + case cg440: FScale = 2.27; break; + case cg390: FScale = 2.56; break; + case cg330: FScale = 3.03; break; + case cg230: FScale = 4.35; break; + } + + SetIntIdle(); + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( Enabled ) + if( FClocked || ( ! ClockInputPin.IsConnected() )) + ReadCompass(); + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + HMC5883L_Compass() : + FClocked( false ), + FChangeOnly( false ), + AveragedSamples( cas1 ), + Bias( cbNone ), + Gain( cg1090 ), + Idle( false ) + { + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_HX711_Weight.h b/libraries/Mitov/Mitov_HX711_Weight.h new file mode 100644 index 0000000..d109d9d --- /dev/null +++ b/libraries/Mitov/Mitov_HX711_Weight.h @@ -0,0 +1,241 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_HX711_WEIGHT_h +#define _MITOV_HX711_WEIGHT_h + +#include + +namespace Mitov +{ + template class HX711_Weight : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: + OpenWire::SinkPin ZeroInputPin; + OpenWire::SinkPin CalibrateInputPin; + + public: + float ScaleDivider = 1.0f; + float Offset = 0.0f; + + bool UseChannelB : 1; + bool Gain128 : 1; + bool Powered : 1; + + int32_t Average = 1; + + public: + void SetScaleDivider( float AValue ) + { + if( ScaleDivider == AValue ) + return; + + ScaleDivider = AValue; + SendOutput(); + } + + void SetOffset( float AValue ) + { + if( Offset == AValue ) + return; + + Offset = AValue; + SendOutput(); + } + + void SetUseChannelB( bool AValue ) + { + if( UseChannelB == AValue ) + return; + + UseChannelB = AValue; + UpdateGain(); + } + + void SetGain128( bool AValue ) + { + if( Gain128 == AValue ) + return; + + Gain128 = AValue; + UpdateGain(); + } + + void SetAverage( int32_t AValue ) + { + if( AValue < 1 ) + Average = 1; + + else + Average = AValue; + + } + + void SetPowered( bool AValue ) + { + if( Powered == AValue ) + return; + + Powered = AValue; + UpdatePower(); + } + + protected: + bool FNeedsRead = false; + float FCurrentValue = 0.0f; + + protected: + virtual void SystemInit() override + { + pinMode( T_CLOCK_PIN, OUTPUT ); + UpdatePower(); + inherited::SystemInit(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( FNeedsRead || ( ! ClockInputPin.IsConnected() )) + ReadSensor(); + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + void ReadSensor() + { + if( OutputPin.IsConnected() ) + { + if( Powered ) + { +// if( SensorDataInputPin.Value ) + if( digitalRead( T_DATA_PIN ) == HIGH ) + { + FNeedsRead = true; + return; + } + + uint32_t AAccumulator = 0; + for( int i = 0; i < Average; ++i ) + AAccumulator += ReadSensorOnes(); + + FCurrentValue = AAccumulator / Average; + FNeedsRead = false; + } + + SendOutput(); + } + } + + uint32_t ReadSensorOnes() + { + while( digitalRead( T_DATA_PIN ) == HIGH ) + ; + + uint32_t AValue = 0; + for( int i = 0; i < 24; ++i ) + { + AValue <<= 1; + digitalWrite( T_CLOCK_PIN, HIGH ); +// SensorClockOutputPin.SendValue( true ); + + if( digitalRead( T_DATA_PIN ) == HIGH ) + AValue |= 1; + + digitalWrite( T_CLOCK_PIN, LOW ); +// SensorClockOutputPin.SendValue( false ); + } + +// Serial.println( AValue ); + int ACount; + if( UseChannelB ) + ACount = 2; + + else if( Gain128 ) + ACount = 1; + + else + ACount = 3; + + // set the channel and the gain factor for the next reading using the clock pin + for (int i = 0; i < ACount; i++) + { + digitalWrite( T_CLOCK_PIN, HIGH ); + digitalWrite( T_CLOCK_PIN, LOW ); +// SensorClockOutputPin.SendValue( true ); +// SensorClockOutputPin.SendValue( false ); + } + + return AValue; + } + + void SendOutput() + { + float AValue = ( FCurrentValue + Offset ) / ScaleDivider; + OutputPin.Notify( &AValue ); + } + + void UpdateGain() + { + if( ! Powered ) + return; + + digitalWrite( T_CLOCK_PIN, LOW ); +// SensorClockOutputPin.SendValue( false ); + ReadSensorOnes(); + } + + void UpdatePower() + { + digitalWrite( T_CLOCK_PIN, LOW ); +// SensorClockOutputPin.SendValue( false ); + if( Powered ) + UpdateGain(); + + else + digitalWrite( T_CLOCK_PIN, HIGH ); +// SensorClockOutputPin.SendValue( true ); + } + + protected: + virtual void DoClockReceive( void *_Data ) override + { + ReadSensor(); + } + + void DoZeroReceive( void *_Data ) + { +// Serial.print( "TEST---------------: " ); + Offset = -FCurrentValue; +// Serial.println( Offset ); + } + + void DoCalibrateReceive( void *_Data ) + { + ScaleDivider = ( FCurrentValue + Offset ); + if( ! ScaleDivider ) + ScaleDivider = 1.0; + } + + public: + HX711_Weight() : + UseChannelB( false ), + Gain128( false ), + FNeedsRead( false ), + Powered( true ) + { + ZeroInputPin.SetCallback( MAKE_CALLBACK( HX711_Weight::DoZeroReceive )); + CalibrateInputPin.SetCallback( MAKE_CALLBACK( HX711_Weight::DoCalibrateReceive )); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_HeatIndex.h b/libraries/Mitov/Mitov_HeatIndex.h new file mode 100644 index 0000000..bcb2af3 --- /dev/null +++ b/libraries/Mitov/Mitov_HeatIndex.h @@ -0,0 +1,104 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_HEAT_INDEDX_h +#define _MITOV_HEAT_INDEDX_h + +#include + +namespace Mitov +{ + class HeatIndex : public Mitov::CommonEnableSource + { + typedef Mitov::CommonEnableSource inherited; + + public: + OpenWire::SinkPin TemperatureInputPin; + OpenWire::SinkPin HumidityInputPin; + + public: + float InitialTemperature = 0.0f; + float InitialHumidity = 0.0f; + bool InFahrenheit = false; + + protected: + void DoTemperatureReceive( void *_Data ) + { + float AValue = *(float*)_Data; + if( InitialTemperature == AValue ) + return; + + InitialTemperature = AValue; + CalculateOutput(); + } + + void DoHumidityReceive( void *_Data ) + { + float AValue = *(float*)_Data; + if( InitialHumidity == AValue ) + return; + + InitialHumidity = AValue; + CalculateOutput(); + } + + void CalculateOutput() + { + // Using both Rothfusz and Steadman's equations + // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml + + float temperature = InitialTemperature; + if ( ! InFahrenheit ) + temperature = ConvertCtoF(temperature); + + float hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (InitialHumidity * 0.094)); + + if( hi > 79 ) + { + hi = -42.379 + + 2.04901523 * temperature + + 10.14333127 * InitialHumidity + + -0.22475541 * temperature * InitialHumidity + + -0.00683783 * pow(temperature, 2) + + -0.05481717 * pow(InitialHumidity, 2) + + 0.00122874 * pow(temperature, 2) * InitialHumidity + + 0.00085282 * temperature * pow(InitialHumidity, 2) + + -0.00000199 * pow(temperature, 2) * pow(InitialHumidity, 2); + + if((InitialHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0)) + hi -= ((13.0 - InitialHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882); + + else if((InitialHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0)) + hi += ((InitialHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2); + } + + if( ! InFahrenheit ) + hi = ConvertFtoC( hi ); + + inherited::OutputPin.Notify( &hi ); + } + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + CalculateOutput(); + } + + public: + HeatIndex() + { + TemperatureInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&HeatIndex::DoTemperatureReceive ); + HumidityInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&HeatIndex::DoHumidityReceive ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_InfraredAvoidanceSensor.h b/libraries/Mitov/Mitov_InfraredAvoidanceSensor.h new file mode 100644 index 0000000..75d753b --- /dev/null +++ b/libraries/Mitov/Mitov_InfraredAvoidanceSensor.h @@ -0,0 +1,94 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_INFRARED_AVOIDANCE_SENSOR_h +#define _MITOV_INFRARED_AVOIDANCE_SENSOR_h + +#include + +namespace Mitov +{ + class InfraredAvoidanceSensor : public Mitov::CommonEnableFilter + { + typedef Mitov::CommonEnableFilter inherited; + + public: + OpenWire::SinkPin EnableInputPin; + OpenWire::SourcePin EnableOutputPin; + + public: + unsigned long EnableDelay = 500; + + protected: + unsigned long FStartTime = 0; + bool FDisabled = false; + bool FCurrentValue = false; + + protected: + virtual void DoReceive( void *_Data ) + { + FCurrentValue = *(bool *)_Data; + if( ! FDisabled ) + OutputPin.Notify( &FCurrentValue ); + } + + void DoEnableReceive( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( AValue == Enabled ) + return; + + Enabled = AValue; + TryStartTimer(); + } + + + void TryStartTimer() + { + if( Enabled ) + { + FDisabled = true; + FStartTime = millis(); + } + + EnableOutputPin.Notify( &Enabled ); + } + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + TryStartTimer(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( FDisabled ) + { + unsigned long currentMilis = millis(); + if( currentMilis - FStartTime >= EnableDelay ) + { + FDisabled = false; + OutputPin.Notify( &FCurrentValue ); + } + } + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + InfraredAvoidanceSensor() + { + EnableInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&InfraredAvoidanceSensor::DoEnableReceive ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Keypad.h b/libraries/Mitov/Mitov_Keypad.h new file mode 100644 index 0000000..934b309 --- /dev/null +++ b/libraries/Mitov/Mitov_Keypad.h @@ -0,0 +1,285 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_KEYPAD_h +#define _MITOV_KEYPAD_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class KeypadBasicKeyElement; + class BasicKeypad; +//--------------------------------------------------------------------------- + class KeypadKeys + { + public: + virtual void RegisterKey( int ARow, int ACol, KeypadBasicKeyElement *AKey ) = 0; + virtual BasicKeypad *GetRootOwner() = 0; + }; +//--------------------------------------------------------------------------- + class KeypadBasicKeyElement; +//--------------------------------------------------------------------------- + class BasicKeypad : public OpenWire::Component, public KeypadKeys + { + typedef OpenWire::Component inherited; + + public: + uint32_t DebounceInterval = 50; + + }; +//--------------------------------------------------------------------------- + template< int C_X, int C_Y > class Keypad : public BasicKeypad + { + typedef BasicKeypad inherited; + + public: +// Mitov::SimpleList > RowsInputPins; + Mitov::SimpleList ColumnsOutputPins; + + public: + const uint8_t *_Pins; + + protected: + bool FInScanning = false; + + KeypadBasicKeyElement *FKeyMap[ C_X ][ C_Y ]; + + public: + virtual BasicKeypad *GetRootOwner() override + { + return this; + } + + virtual void RegisterKey( int ARow, int ACol, KeypadBasicKeyElement *AKey ) override + { + FKeyMap[ ACol ][ ARow ] = AKey; + } + + protected: + virtual void SystemInit() + { + for( int i = 0; i < C_Y ; ++i ) + pinMode( _Pins[ i ], INPUT_PULLUP ); + + inherited::SystemInit(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override; + + }; +//--------------------------------------------------------------------------- + class KeypadBasicKeyElement // : public OpenWire::Component + { + public: + virtual void SetButtonValue( unsigned long currentMicros, bool AValue ) + { + } + + }; +//--------------------------------------------------------------------------- + template class KeypadKeyElement : public KeypadBasicKeyElement + { + typedef KeypadBasicKeyElement inherited; + + protected: + T_OWNER &FOwner; + + public: + KeypadKeyElement( T_OWNER &AOwner ) : + FOwner( AOwner ) + { + } + + KeypadKeyElement( T_OWNER &AOwner, int ARow, int ACol ) : + FOwner( AOwner ) + { + AOwner.RegisterKey( ACol, ARow, this ); + } + + }; +//--------------------------------------------------------------------------- + template class KeypadBasicKey : public KeypadKeyElement + { + typedef KeypadKeyElement inherited; + +/* + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + inherited::SystemLoopBegin( currentMicros ); + } +*/ + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class DigitalKeypadKey : public KeypadBasicKey + { + typedef KeypadBasicKey inherited; + + public: + OpenWire::SourcePin OutputPin; + + protected: + unsigned long FLastTime = 0; + bool FValue : 1; + bool FLastValue : 1; + + public: + virtual void SetButtonValue( unsigned long currentMicros, bool AValue ) + { + if( AValue != FLastValue ) + FLastTime = millis(); + + FLastValue = AValue; + if( FValue != FLastValue ) + if( millis() - FLastTime > FOwner.DebounceInterval ) + { + FValue = FLastValue; + OutputPin.SendValue( ! FValue ); + } + + } + + public: + DigitalKeypadKey( BasicKeypad &AOwner, int ARow, int ACol ) : + inherited( AOwner, ARow, ACol ), + FLastValue( false ), + FValue( false ) + { + } + }; +//--------------------------------------------------------------------------- + class CharacterKeyGroup : public KeypadKeyElement, public KeypadKeys + { + typedef KeypadKeyElement inherited; + + public: + OpenWire::SourcePin OutputPin; + + public: + virtual BasicKeypad *GetRootOwner() override + { + return FOwner.GetRootOwner(); + } + + virtual void RegisterKey( int ARow, int ACol, KeypadBasicKeyElement *AKey ) override + { + FOwner.RegisterKey( ARow, ACol, AKey ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class CharKeypadKey : public KeypadBasicKey + { + typedef KeypadBasicKey inherited; + + public: + char Character = 'a'; + + protected: + unsigned long FLastTime = 0; + bool FValue = false; + bool FLastValue = false; + + BasicKeypad *FRootOwner; + + public: + virtual void SetButtonValue( unsigned long currentMicros, bool AValue ) + { + if( AValue != FLastValue ) + FLastTime = millis(); + + FLastValue = AValue; + if( FValue != FLastValue ) + if( millis() - FLastTime > FRootOwner->DebounceInterval ) + { + FValue = FLastValue; + if( ! FValue ) + FOwner.OutputPin.Notify( &Character ); + +// OutputPin.Notify( &FValue ); + } + + } + + public: + CharKeypadKey( CharacterKeyGroup &AOwner, int ARow, int ACol ) : + inherited( AOwner, ARow, ACol ) + { + FRootOwner = AOwner.GetRootOwner(); + } + }; +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + template< int C_X, int C_Y > void Keypad< C_X, C_Y >::SystemLoopBegin( unsigned long currentMicros ) + { + if( ! FInScanning ) + { + FInScanning = true; + for( int i = 0; i < C_X; ++i ) + ColumnsOutputPins[ i ].SendValue( false ); + } + + for( int i = 0; i < C_Y; ++i ) + if( ! digitalRead( _Pins[ i ] )) + FInScanning = false; + +// if( ! FInScanning ) +// Serial.println( "----------------------------" ); + + for( int i = 0; i < C_X; ++i ) + { + if( ! FInScanning ) + { + for( int j = 0; j < C_X; ++j ) + { +// Serial.print( i != j ); Serial.print( " " ); + ColumnsOutputPins[ j ].SendValue( i != j ); + } + +// Serial.println( "" ); + } + +// if( ! FInScanning ) +// Serial.println( "+++++++++++++++++++++++++" ); + + for( int j = 0; j < C_Y; ++j ) + if( FKeyMap[ i ][ j ] ) + { +// if( ! FInScanning ) +// { +// if( ! digitalRead( _Pins[ j ] ) ) +// { +// Serial.print( i ); Serial.print( "," ); Serial.println( j ); +// } +// Serial.print( i ); Serial.print( "," ); Serial.print( j ); Serial.print( " = " ); Serial.print( digitalRead( _Pins[ j ] ) ); Serial.print( " " ); +// } + + FKeyMap[ i ][ j ]->SetButtonValue( currentMicros, digitalRead( _Pins[ j ] )); + } + +// if( ! FInScanning ) +// Serial.println( "" ); + } + + inherited::SystemLoopBegin( currentMicros ); + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_L298NDualMotorDriver.h b/libraries/Mitov/Mitov_L298NDualMotorDriver.h new file mode 100644 index 0000000..4cf2390 --- /dev/null +++ b/libraries/Mitov/Mitov_L298NDualMotorDriver.h @@ -0,0 +1,86 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_L298N_DUAL_MOTOR_h +#define _MITOV_L298N_DUAL_MOTOR_h + +#include + +namespace Mitov +{ + class L298NDualMotorDriverChannel : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + OpenWire::SourcePin ForwardOutputPin; + OpenWire::SourcePin ReverseOutputPin; + OpenWire::SourcePin SpeedOutputPin; + + public: + bool Enabled = true; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateOutputs(); + } + + protected: + float FCurrentSpeed = 0.5f; + + protected: + virtual void DoReceive( void *_Data ) + { + float ASpeed = constrain( *(float *)_Data, 0.0, 1.0 ); + if( FCurrentSpeed == ASpeed ) + return; + + FCurrentSpeed = ASpeed; + UpdateOutputs(); + } + + void UpdateOutputs() + { + if( Enabled ) + { + float AOutSpeed = abs( FCurrentSpeed - 0.5 ) * 2; + bool ADirection = FCurrentSpeed > 0.5; + + ReverseOutputPin.Notify( &ADirection ); + ADirection = !ADirection; + ForwardOutputPin.Notify( &ADirection ); + + SpeedOutputPin.Notify( &AOutSpeed ); + } + + else + { + SpeedOutputPin.SendValue( 0 ); + ForwardOutputPin.SendValue( false ); + ReverseOutputPin.SendValue( false ); + } + } + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + UpdateOutputs(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_L9110SDualMotorDriver.h b/libraries/Mitov/Mitov_L9110SDualMotorDriver.h new file mode 100644 index 0000000..c7dd97d --- /dev/null +++ b/libraries/Mitov/Mitov_L9110SDualMotorDriver.h @@ -0,0 +1,84 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_L9110S_DUAL_MOTOR_h +#define _MITOV_L9110S_DUAL_MOTOR_h + +#include + +namespace Mitov +{ + class L9110SDualMotorDriverChannel : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + OpenWire::SourcePin DirectionOutputPin; + OpenWire::SourcePin SpeedOutputPin; + + public: + bool Enabled = true; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateOutputs(); + } + + protected: + float FCurrentSpeed = 0.5f; + + protected: + virtual void DoReceive( void *_Data ) override + { + float ASpeed = constrain( *(float *)_Data, 0.0, 1.0 ); + if( FCurrentSpeed == ASpeed ) + return; + + FCurrentSpeed = ASpeed; + UpdateOutputs(); + } + + void UpdateOutputs() + { + if( Enabled ) + { + float AOutSpeed = abs( FCurrentSpeed - 0.5 ) * 2; + bool ADirection = FCurrentSpeed > 0.5; + + if( ADirection ) + AOutSpeed = 1 - AOutSpeed; + + SpeedOutputPin.Notify( &AOutSpeed ); + DirectionOutputPin.Notify( &ADirection ); + } + + else + { + SpeedOutputPin.SendValue( 0 ); + DirectionOutputPin.SendValue( false ); + } + } + + protected: + virtual void SystemStart() override + { + inherited::SystemStart(); + UpdateOutputs(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_LEDBarDisplay.h b/libraries/Mitov/Mitov_LEDBarDisplay.h new file mode 100644 index 0000000..2c3ef53 --- /dev/null +++ b/libraries/Mitov/Mitov_LEDBarDisplay.h @@ -0,0 +1,98 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_LED_BAR_DISPLAY_h +#define _MITOV_LED_BAR_DISPLAY_h + +#include +#include + +namespace Mitov +{ + template class LEDBarBasicDisplay : public Mitov::BasicDisplay + { + typedef Mitov::BasicDisplay inherited; + + public: + Mitov::SimpleList BarsOutputPins; + + public: + bool InvertedBars = false; + bool SingleBar = false; + + public: + virtual void DoReceive( void *_Data ) override + { + inherited::DoReceive( _Data ); + UpdateDisplay(); + } + + protected: + virtual void UpdateDisplay() = 0; + + protected: + void DisplayValue( long AValue ) + { + for( int i = 0; i < BarsOutputPins.size(); ++i ) + { + bool ABitValue; + if( SingleBar ) + ABitValue = ( AValue == 0 ) ^ InvertedBars; + + else + ABitValue = ( AValue > 0 ) ^ InvertedBars; + + BarsOutputPins[ i ].Notify( &ABitValue ); + --AValue; + } + } + + }; +//--------------------------------------------------------------------------- + class LEDBarDisplay : public Mitov::LEDBarBasicDisplay + { + typedef Mitov::LEDBarBasicDisplay inherited; + + protected: + virtual void UpdateDisplay() override + { + int AValue = (Enabled) ? FValue : 0; + DisplayValue( AValue ); + } + + }; +//--------------------------------------------------------------------------- + class LEDBarAnalogDisplay : public Mitov::LEDBarBasicDisplay + { + typedef Mitov::LEDBarBasicDisplay inherited; + + protected: + virtual void UpdateDisplay() override + { + int AValue; + if( Enabled ) + { + if( SingleBar ) + AValue = FValue * BarsOutputPins.size(); + + else + AValue = FValue * BarsOutputPins.size() + 0.5; + } + + else + AValue = 0; + + DisplayValue( AValue ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_LEGO_RCX_LightSensor.h b/libraries/Mitov/Mitov_LEGO_RCX_LightSensor.h new file mode 100644 index 0000000..52ccca4 --- /dev/null +++ b/libraries/Mitov/Mitov_LEGO_RCX_LightSensor.h @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +// http://www.legolab.daimi.au.dk/CSaEA/RCX/Manual.dir/Sensors.dir/Sensors.html +// https://seriousrobotics.wordpress.com/2011/11/20/using-rcx-lego-sensors-with-arduino/ + +#ifndef _MITOV_LEGO_RCX_LIGHT_SENSOR_h +#define _MITOV_LEGO_RCX_LIGHT_SENSOR_h + +#include + +namespace Mitov +{ + template class LEGO_RCX_LightSensor : public Mitov::CommonEnableSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonEnableSource inherited; + + public: + uint32_t ChargePeriod = 2; + uint32_t MinValue = 90; + uint32_t MaxValue = 160; + + bool Normalize : 1; + + protected: + bool FHasValue : 1; + + float FValue; + unsigned long FStartTime; + + protected: + + virtual void SystemStart() override + { + inherited::SystemStart(); + FStartTime = micros(); + pinMode( DIGITAL_PIN_NUMBER, OUTPUT ); + digitalWrite( DIGITAL_PIN_NUMBER, HIGH ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ( currentMicros - FStartTime ) >= ChargePeriod * 1000 ) + { + pinMode( DIGITAL_PIN_NUMBER, INPUT ); + + analogRead( ANALOG_PIN_NUMBER ); // Give some settle time + FValue = analogRead( ANALOG_PIN_NUMBER ); + if( Normalize ) + FValue = ( FValue - MinValue ) / (MaxValue - MinValue); + + pinMode( DIGITAL_PIN_NUMBER, OUTPUT ); + digitalWrite( DIGITAL_PIN_NUMBER, HIGH ); + FHasValue = true; + + FStartTime = micros(); + } + + if( ! ClockInputPin.IsConnected() ) + ReadSensor(); + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + void ReadSensor() + { + if( FHasValue ) + OutputPin.Notify( &FValue ); + } + + protected: + virtual void DoClockReceive( void *_Data ) override + { + ReadSensor(); + } + + public: + LEGO_RCX_LightSensor() : + FHasValue( false ), + Normalize( true ) + { + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_LinkIt_GPRS.h b/libraries/Mitov/Mitov_LinkIt_GPRS.h new file mode 100644 index 0000000..7d79670 --- /dev/null +++ b/libraries/Mitov/Mitov_LinkIt_GPRS.h @@ -0,0 +1,108 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_LINKIT_GPRS_h +#define _MITOV_LINKIT_GPRS_h + +#include +#include +#include +#include +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class LinkItGPRSModule : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + Mitov::SimpleList*> Sockets; + + public: + bool Enabled = true; + + Mitov::SimpleObjectList AccessPoints; + + protected: + bool FConnected = false; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartEthernet(); + + else + StopEthernet(); + + } + + protected: + virtual void SystemInit() + { + if( Enabled ) + StartEthernet(); + + inherited::SystemInit(); + } + + void StopEthernet() + { + for( int i = 0; i < Sockets.size(); ++i ) + Sockets[ i ]->StopSocket(); + +// LWiFi.end(); + } + + void StartEthernet() + { + TryConnect( true, 0 ); + } + + void TryConnect( bool FromStart, unsigned long currentMicros ) + { + for( int i = 0; i < AccessPoints.size(); i ++ ) + if( AccessPoints[ i ]->Enabled ) + { + if( ! FromStart ) + if( ! AccessPoints[ i ]->CanRetry( currentMicros ) ) + continue; + + if( AccessPoints[ i ]->AccessPoint != "" ) + FConnected = LGPRS.attachGPRS( AccessPoints[ i ]->AccessPoint.c_str(), AccessPoints[ i ]->UserName.c_str(), AccessPoints[ i ]->Password.c_str() ); + + else + FConnected = LGPRS.attachGPRS(); + + if( FConnected ) + break; + } + + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! FConnected ) + TryConnect( false, currentMicros ); + + inherited::SystemLoopBegin( currentMicros ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_LinkIt_WiFi.h b/libraries/Mitov/Mitov_LinkIt_WiFi.h new file mode 100644 index 0000000..c2ac4f4 --- /dev/null +++ b/libraries/Mitov/Mitov_LinkIt_WiFi.h @@ -0,0 +1,286 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_LINKIT_WIFI_h +#define _MITOV_LINKIT_WIFI_h + +#include +#include +#include +#include +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + enum LinkItWiFiEncription { liweAuto, liweWEP, liweWPA }; +//--------------------------------------------------------------------------- + class LinkItRemoteAccessPoint + { + public: + bool Enabled = true; + String SSID; + String Password; + LinkItWiFiEncription Encription = liweAuto; + + public: + bool Connect() + { + if( ! Enabled ) + return false; + + if( SSID == "" ) + return false; + + if( Password == "" ) + return ( LWiFi.connect( SSID.c_str() ) > 0 ); + + + switch( Encription ) + { + case liweAuto: + { + if( LWiFi.connectWPA( SSID.c_str(), Password.c_str() ) > 0 ) + return true; + + return( LWiFi.connectWEP( SSID.c_str(), Password.c_str() ) > 0 ); + } + + case liweWEP: + return( LWiFi.connectWEP( SSID.c_str(), Password.c_str() ) > 0 ); + + case liweWPA: + return( LWiFi.connectWPA( SSID.c_str(), Password.c_str() ) > 0 ); + } + } + }; +//--------------------------------------------------------------------------- + class LinkItWiFiModule : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SinkPin ScanNetworksInputPin; + OpenWire::SourcePin FoundSignalStrengthOutputPin; + OpenWire::SourcePin FoundSSIDOutputPin; + + OpenWire::SourcePin AddressOutputPin; + OpenWire::SourcePin MACOutputPin; + + OpenWire::SourcePin SignalStrengthOutputPin; + OpenWire::SourcePin BSSIDOutputPin; + OpenWire::SourcePin GatewayIPOutputPin; + OpenWire::SourcePin SubnetMaskIPOutputPin; + + OpenWire::SinkPin CheckSignalStrengthInputPin; + + public: + Mitov::SimpleObjectList AccessPoints; + Mitov::SimpleList*> Sockets; + + bool Enabled = true; + + public: + bool IsStarted = false; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + StartEthernet(); + + else + StopEthernet(); + + } + + public: + virtual bool GetIPFromHostName( String AHostName, ::IPAddress &AAdress ) + { + bool AResult = ( LWiFi.hostByName( AHostName.c_str(), AAdress ) == 1 ); + if( ! AResult ) + AAdress = INADDR_NONE; + + return AResult; + } + + protected: + virtual void SystemInit() + { + if( Enabled ) + StartEthernet(); + + inherited::SystemInit(); + } + + void StopEthernet() + { + for( int i = 0; i < Sockets.size(); ++i ) + Sockets[ i ]->StopSocket(); + + LWiFi.end(); + IsStarted = false; + } + + void StartEthernet() + { +/* + if( ! AccessPoints.length() ) + return; + + if( ! Sockets.length() ) + return; +*/ + LWiFi.begin(); + for( int i = 0; i < AccessPoints.size(); ++i ) + if( AccessPoints[ i ]->Connect() ) + { + IsStarted = true; + if( MACOutputPin.IsConnected() ) + { + uint8_t AMACAddress[VM_WLAN_WNDRV_MAC_ADDRESS_LEN] = {0}; + + LWiFi.macAddress( AMACAddress ); + + char AMACString[ VM_WLAN_WNDRV_MAC_ADDRESS_LEN * 3 + 1 ]; + sprintf( AMACString, "%02X-%02X-%02X-%02X-%02X-%02X", AMACString[ 0 ], AMACString[ 1 ], AMACString[ 2 ], AMACString[ 3 ], AMACString[ 4 ], AMACString[ 5 ] ); + MACOutputPin.Notify( AMACString ); + } + + if( AddressOutputPin.IsConnected() ) + { + IPAddress ALocalIPAddress = LWiFi.localIP(); + char AIPString[ 4 * 4 + 1 ]; + sprintf( AIPString, "%u.%u.%u.%u", ALocalIPAddress[ 0 ], ALocalIPAddress[ 1 ], ALocalIPAddress[ 2 ], ALocalIPAddress[ 3 ] ); + +// String ALocalIPAddressString = String( ALocalIPAddress[ 0 ] ) + "." + String( ALocalIPAddress[ 1 ] + "." + ALocalIPAddress[ 2 ] + "." + ALocalIPAddress[ 3 ]; + AddressOutputPin.Notify( AIPString ); + } + + if( SignalStrengthOutputPin.IsConnected() ) + { + int32_t ASetrength = LWiFi.RSSI(); + SignalStrengthOutputPin.Notify( &ASetrength ); + } + + if( BSSIDOutputPin.IsConnected() ) + { + uint8_t AMACAddress[VM_WLAN_WNDRV_MAC_ADDRESS_LEN] = {0}; + + LWiFi.BSSID( AMACAddress ); + + char AMACString[ VM_WLAN_WNDRV_MAC_ADDRESS_LEN * 3 + 1 ]; + sprintf( AMACString, "%02X-%02X-%02X-%02X-%02X-%02X", AMACString[ 0 ], AMACString[ 1 ], AMACString[ 2 ], AMACString[ 3 ], AMACString[ 4 ], AMACString[ 5 ] ); + BSSIDOutputPin.Notify( AMACString ); + } + + if( GatewayIPOutputPin.IsConnected() ) + { + IPAddress ALocalIPAddress = LWiFi.gatewayIP(); + char AIPString[ 4 * 4 + 1 ]; + sprintf( AIPString, "%u.%u.%u.%u", ALocalIPAddress[ 0 ], ALocalIPAddress[ 1 ], ALocalIPAddress[ 2 ], ALocalIPAddress[ 3 ] ); + +// String ALocalIPAddressString = String( ALocalIPAddress[ 0 ] ) + "." + String( ALocalIPAddress[ 1 ] + "." + ALocalIPAddress[ 2 ] + "." + ALocalIPAddress[ 3 ]; + AddressOutputPin.Notify( AIPString ); + } + + if( SubnetMaskIPOutputPin.IsConnected() ) + { + IPAddress ALocalIPAddress = LWiFi.subnetMask(); + char AIPString[ 4 * 4 + 1 ]; + sprintf( AIPString, "%u.%u.%u.%u", ALocalIPAddress[ 0 ], ALocalIPAddress[ 1 ], ALocalIPAddress[ 2 ], ALocalIPAddress[ 3 ] ); + +// String ALocalIPAddressString = String( ALocalIPAddress[ 0 ] ) + "." + String( ALocalIPAddress[ 1 ] + "." + ALocalIPAddress[ 2 ] + "." + ALocalIPAddress[ 3 ]; + SubnetMaskIPOutputPin.Notify( AIPString ); + } + + break; + } + + } + + protected: + void DoScanNetworks( void *_Data ) + { + int nearbyAccessPointCount = LWiFi.scanNetworks(); + for( int i = 0; i < nearbyAccessPointCount; i ++ ) + { + FoundSSIDOutputPin.Notify( LWiFi.SSID( i )); + + int32_t ASetrength = LWiFi.RSSI( i ); + FoundSignalStrengthOutputPin.Notify( &ASetrength ); + } + } + + void DoCheckSignalStrength( void *_Data ) + { + if( IsStarted ) + if( SignalStrengthOutputPin.IsConnected() ) + { + int32_t ASetrength = LWiFi.RSSI(); + SignalStrengthOutputPin.Notify( &ASetrength ); + } + } + + public: + LinkItWiFiModule() + { + ScanNetworksInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LinkItWiFiModule::DoScanNetworks ); + CheckSignalStrengthInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LinkItWiFiModule::DoCheckSignalStrength ); + } + + }; +//--------------------------------------------------------------------------- + class LinkItWiFiTCPClientSocket : public TCPClientSocket + { + typedef TCPClientSocket inherited; + + public: + virtual bool CanSend() override + { + return inherited::Enabled && inherited::FOwner.Enabled && FClient; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class LinkItWiFiTCPServerSocket : public TCPServerSocket + { + typedef TCPServerSocket inherited; + + public: + virtual bool CanSend() override + { + return inherited::Enabled && inherited::FOwner.Enabled && FClient; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class LinkItWiFiUDPSocket : public UDPSocket + { + typedef UDPSocket inherited; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_LiquidCrystalDisplay.h b/libraries/Mitov/Mitov_LiquidCrystalDisplay.h new file mode 100644 index 0000000..c18930b --- /dev/null +++ b/libraries/Mitov/Mitov_LiquidCrystalDisplay.h @@ -0,0 +1,674 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_IQUID_CRYSTAL_DISPLAY_h +#define _MITOV_IQUID_CRYSTAL_DISPLAY_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class LiquidCrystalDisplay; +//--------------------------------------------------------------------------- + class LiquidCrystalElementBasic : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: // Public for the print access + LCD *FLcd; + + public: + virtual void DisplayInit() {} + virtual void DisplayStart() {} + + public: + LiquidCrystalElementBasic( Mitov::LiquidCrystalDisplay &AOwner ); + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementBasicPositionedField : public LiquidCrystalElementBasic + { + typedef Mitov::LiquidCrystalElementBasic inherited; + + public: + unsigned long Column = 0; + unsigned long Row = 0; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementBasicPositionedWidthField : public LiquidCrystalElementBasicPositionedField + { + typedef Mitov::LiquidCrystalElementBasicPositionedField inherited; + + public: + unsigned long Width = 16; + + public: + void ClearLine() + { + FLcd->setCursor( Column, Row ); + } + + void NewLine( int AClearSize ) + { + for( int i = 0; i < Width - AClearSize; ++ i ) + FLcd->print( ' ' ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementTextField : public LiquidCrystalElementBasicPositionedWidthField + { + typedef Mitov::LiquidCrystalElementBasicPositionedWidthField inherited; + + public: + String InitialValue; + + protected: + virtual void SystemStart() override + { + inherited::SystemStart(); + ClearLine(); + int AClearSize = FLcd->print( InitialValue ); + NewLine( AClearSize ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + template class LiquidCrystalElementBasicPositionedWidthTypedField : public LiquidCrystalElementBasicPositionedWidthField + { + typedef Mitov::LiquidCrystalElementBasicPositionedWidthField inherited; + + public: + T InitialValue; + + public: + OpenWire::SinkPin InputPin; + + protected: + virtual int PrintValue( T AValue ) = 0; + + void ClearPrintValue( T AValue ) + { + InitialValue = AValue; +// Serial.println( AValue ); + ClearLine(); + int AClearSize = PrintValue( AValue ); + NewLine( AClearSize ); + } + + protected: + virtual void SystemStart() override + { + inherited::SystemStart(); +// char AText[ 50 ]; +// itoa( InitialValue, AText, Base ); +// int AClearSize = FLcd->print( AText ); + ClearPrintValue( InitialValue ); + } + + void DoReceiveData( void *_Data ) + { + ClearPrintValue( *(T*)_Data ); + } + + public: + LiquidCrystalElementBasicPositionedWidthTypedField( Mitov::LiquidCrystalDisplay &AOwner, T AInitialValue ) : + inherited( AOwner ), + InitialValue( AInitialValue ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalElementBasicPositionedWidthTypedField::DoReceiveData ); + } + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementIntegerField : public LiquidCrystalElementBasicPositionedWidthTypedField + { + typedef Mitov::LiquidCrystalElementBasicPositionedWidthTypedField inherited; + + public: + int Base = 10; + + protected: + virtual int PrintValue( long AValue ) override + { + char AText[ 50 ]; + itoa( AValue, AText, Base ); + return FLcd->print( AText ); + } + + public: + LiquidCrystalElementIntegerField( Mitov::LiquidCrystalDisplay &AOwner ) : + inherited( AOwner, 0 ) + { + } + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementAnalogField : public LiquidCrystalElementBasicPositionedWidthTypedField + { + typedef Mitov::LiquidCrystalElementBasicPositionedWidthTypedField inherited; + + public: + int MinWidth = 1; + int Precision = 3; + + protected: + virtual int PrintValue( float AValue ) override + { + char AText[ 50 ]; + dtostrf( AValue, MinWidth, Precision, AText ); + return FLcd->print( AText ); + } + + public: + LiquidCrystalElementAnalogField( Mitov::LiquidCrystalDisplay &AOwner ) : + inherited( AOwner, 0 ) + { + } + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementDigitalField : public LiquidCrystalElementBasicPositionedWidthTypedField + { + typedef Mitov::LiquidCrystalElementBasicPositionedWidthTypedField inherited; + + public: + String TrueValue = "true"; + String FalseValue = "false"; + + protected: + virtual int PrintValue( bool AValue ) override + { + if( AValue ) + return FLcd->print( TrueValue ); + + return FLcd->print( FalseValue ); + } + + public: + LiquidCrystalElementDigitalField( Mitov::LiquidCrystalDisplay &AOwner ) : + inherited( AOwner, 0 ) + { + } + + }; +//--------------------------------------------------------------------------- + // TODO: Implement setCursor() and createChar() + class LiquidCrystalDisplay : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SinkPin ScrollLeftInputPin; + OpenWire::SinkPin ScrollRightInputPin; + OpenWire::SinkPin ClearInputPin; + OpenWire::SinkPin HomeInputPin; + + public: + bool Enabled : 1; + bool AutoScroll : 1; + bool RightToLeft : 1; + bool ShowCursor : 1; + bool Blink : 1; + + protected: + uint8_t FCols; + uint8_t FRows; + uint8_t FCursorLine = 0; + uint8_t FCursorPos = 0; + + public: // Public for the print access + LCD *FLcd; + Mitov::SimpleList FElements; + + public: + void ClearLine() + { + FLcd->setCursor( 0, FCursorLine ); + FCursorPos = 0; +// for( int i = 0; i < FCols; ++ i ) +// FLcd->print( ' ' ); + +// FLcd->setCursor( 0, FCursorLine ); + } + + void NewLine( int AClearSize ) + { + for( int i = 0; i < FCols - FCursorPos - AClearSize; ++ i ) + FLcd->print( ' ' ); + + ++FCursorLine; + FCursorPos = 0; + if( FCursorLine >= FRows ) + FCursorLine = 0; + +// FLcd->setCursor( 0, FCursorLine ); + } + + void MoveChars( int ACount ) + { + ++FCursorPos; + } + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateEnabled(); + } + + void SetAutoScroll( bool AValue ) + { + if( AutoScroll == AValue ) + return; + + AutoScroll = AValue; + UpdateAutoScroll(); + } + + void SetRightToLeft( bool AValue ) + { + if( RightToLeft == AValue ) + return; + + RightToLeft = AValue; + UpdateRightToLeft(); + } + + void SetShowCursor( bool AValue ) + { + if( ShowCursor == AValue ) + return; + + ShowCursor = AValue; + UpdateShowCursor(); + } + + void SetBlink( bool AValue ) + { + if( Blink == AValue ) + return; + + Blink = AValue; + UpdateBlink(); + } + + protected: + void UpdateEnabled() + { + if( Enabled ) + FLcd->display(); + + else + FLcd->noDisplay(); + + } + + void UpdateAutoScroll() + { + if( AutoScroll ) + FLcd->autoscroll(); + + else + FLcd->noAutoscroll(); + + } + + void UpdateRightToLeft() + { + if( RightToLeft ) + FLcd->rightToLeft(); + + else + FLcd->leftToRight(); + + } + + void UpdateShowCursor() + { + if( ShowCursor ) + FLcd->cursor(); + + else + FLcd->noCursor(); + + } + + void UpdateBlink() + { + if( Blink ) + FLcd->blink(); + + else + FLcd->noBlink(); + + } + + void DoScrollLeft( void * ) + { + FLcd->scrollDisplayLeft(); + } + + void DoScrollRight( void * ) + { + FLcd->scrollDisplayRight(); + } + + void DoClear( void * ) + { + FLcd->clear(); + } + + void DoHome( void * ) + { + FLcd->home(); + } + + public: + virtual void SystemInit() override + { + inherited::SystemInit(); + + FLcd->begin( FCols, FRows ); + UpdateEnabled(); + UpdateAutoScroll(); + UpdateRightToLeft(); + UpdateShowCursor(); + UpdateBlink(); + + for( Mitov::SimpleList::iterator Iter = FElements.begin(); Iter != FElements.end(); ++Iter ) + ( *Iter)->DisplayInit(); + +// FLcd->setCursor(0,0); + } + + virtual void SystemStart() override + { + inherited::SystemStart(); + + for( Mitov::SimpleList::iterator Iter = FElements.begin(); Iter != FElements.end(); ++Iter ) + ( *Iter)->DisplayStart(); + } + + public: + LiquidCrystalDisplay( LCD *ALcd, unsigned int ACols, unsigned int ARows ) : + FLcd( ALcd ), + FCols( ACols ), + FRows( ARows ), + Enabled( true ), + AutoScroll( false ), + RightToLeft( false ), + ShowCursor( false ), + Blink( false ) + { + ScrollLeftInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoScrollLeft ); + ScrollRightInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoScrollRight ); + ClearInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoClear ); + HomeInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoHome ); + } + +/* + virtual ~LiquidCrystalDisplay() + { + delete FLcd; + } +*/ + }; +//--------------------------------------------------------------------------- + class LiquidCrystalDisplayI2C : public LiquidCrystalDisplay + { + typedef Mitov::LiquidCrystalDisplay inherited; + + public: + bool Backlight = true; + + public: + void SetBacklight( bool AValue ) + { + if( Backlight == AValue ) + return; + + Backlight = AValue; + UpdateBacklight(); + } + + public: + virtual void SystemInit() override + { + inherited::SystemInit(); + UpdateBacklight(); + } + + public: + void UpdateBacklight() + { + if( Backlight ) + inherited::FLcd->setBacklight( 255 ); + + else + inherited::FLcd->setBacklight( 0 ); + + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementDefineCustomCharacter : public LiquidCrystalElementBasic + { + typedef Mitov::LiquidCrystalElementBasic inherited; + + protected: + uint8_t FCharMap[ 8 ]; + + uint8_t FIndex; + + public: + virtual void DisplayInit() override + { + FLcd->createChar( FIndex, FCharMap ); + } + + public: + LiquidCrystalElementDefineCustomCharacter( Mitov::LiquidCrystalDisplay &AOwner, uint8_t AIndex, uint8_t Byte0, uint8_t Byte1, uint8_t Byte2, uint8_t Byte3, uint8_t Byte4, uint8_t Byte5, uint8_t Byte6, uint8_t Byte7 ) : + inherited( AOwner ), + FIndex( AIndex ) + { + AOwner.FElements.push_back( this ); + + FCharMap[ 0 ] = Byte0; + FCharMap[ 1 ] = Byte1; + FCharMap[ 2 ] = Byte2; + FCharMap[ 3 ] = Byte3; + FCharMap[ 4 ] = Byte4; + FCharMap[ 5 ] = Byte5; + FCharMap[ 6 ] = Byte6; + FCharMap[ 7 ] = Byte7; + } + + }; +//--------------------------------------------------------------------------- + class LiquidCrystalElementCustomCharacterField : public LiquidCrystalElementBasicPositionedField + { + typedef Mitov::LiquidCrystalElementBasicPositionedField inherited; + + public: + long Index = 0; + + protected: + bool FModified = false; + + public: + void SetIndex( long AValue ) + { + if( AValue > 7 ) + AValue = 7; + + else if( AValue < 0 ) + AValue = 0; + + if( Index == AValue ) + return; + + Index = AValue; + FModified = true; + } + + void SetColumn( unsigned long AValue ) + { + if( AValue < 0 ) + AValue = 0; + + if( Column == AValue ) + return; + + Column = AValue; + FModified = true; + } + + void SetRow( unsigned long AValue ) + { + if( AValue < 0 ) + AValue = 0; + + if( Row == AValue ) + return; + + Row = AValue; + FModified = true; + } + + public: + virtual void DisplayStart() override + { + DisplayCharacter(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + inherited::SystemLoopBegin( currentMicros ); + if( FModified ) + { + DisplayCharacter(); + FModified = false; + } + } + + protected: + void DisplayCharacter() + { + FLcd->setCursor( Column, Row ); + FLcd->write( (uint8_t) Index ); + } + + public: + LiquidCrystalElementCustomCharacterField( Mitov::LiquidCrystalDisplay &AOwner ) : + inherited( AOwner ) + { + AOwner.FElements.push_back( this ); + } + + }; +//--------------------------------------------------------------------------- + template class LiquidCrystalDisplayInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_LCD_INSTANCE->ClearLine(); + int AClearSize = T_LCD_INSTANCE->FLcd->print( *(T*)_Data ); + T_LCD_INSTANCE->NewLine( AClearSize ); + } + }; +//--------------------------------------------------------------------------- + template class LiquidCrystalDisplayCharInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { +// Serial.print( (char*)_Data ); +// if( *(byte*)_Data < ' ' ) +// return; + + if( *(char*)_Data == '\r' ) + T_LCD_INSTANCE->NewLine( 0 ); + + else if( *(char*)_Data == '\n' ) + T_LCD_INSTANCE->ClearLine(); + + else if( *(char*)_Data >= ' ' ) + { + int AClearSize = T_LCD_INSTANCE->FLcd->print( *(char*)_Data ); + T_LCD_INSTANCE->MoveChars( AClearSize ); + } +// int AClearSize = T_LCD_INSTANCE->FLcd->print( (char*)_Data ); +// T_LCD_INSTANCE->NewLine( AClearSize ); + } + }; +//--------------------------------------------------------------------------- + template class LiquidCrystalDisplayStringInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { +// Serial.print( (char*)_Data ); +// if( *(byte*)_Data < ' ' ) +// return; + + T_LCD_INSTANCE->ClearLine(); + int AClearSize = T_LCD_INSTANCE->FLcd->print( (char*)_Data ); + T_LCD_INSTANCE->NewLine( AClearSize ); + } + }; +//--------------------------------------------------------------------------- + template class LiquidCrystalDisplayObjectInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) + { + T_LCD_INSTANCE->ClearLine(); + int AClearSize = T_LCD_INSTANCE->FLcd->print( ((T_OBJECT *)_Data)->ToString().c_str() ); + T_LCD_INSTANCE->NewLine( AClearSize ); + } + }; +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + LiquidCrystalElementBasic::LiquidCrystalElementBasic( LiquidCrystalDisplay &AOwner ) : + FLcd( AOwner.FLcd ) + { + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_LogicFlipFlops.h b/libraries/Mitov/Mitov_LogicFlipFlops.h new file mode 100644 index 0000000..febec48 --- /dev/null +++ b/libraries/Mitov/Mitov_LogicFlipFlops.h @@ -0,0 +1,214 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_LOGIC_FLIP_FLOPS_h +#define _MITOV_LOGIC_FLIP_FLOPS_h + +#include + +namespace Mitov +{ + class BasicFlipFlop : public Mitov::CommonSource + { + typedef Mitov::CommonSource inherited; + + protected: + bool FValue = false; + + public: + OpenWire::SourcePin InvertedOutputPin; + + protected: + void SetValue( bool AValue ) + { + FValue = AValue; + SendOutput(); + } + + void SendOutput() + { + OutputPin.SendValue( FValue ); + InvertedOutputPin.SendValue( !FValue ); + } + + protected: + virtual void SystemStart() override + { + inherited::SystemStart(); + SendOutput(); + } + + }; +//--------------------------------------------------------------------------- + class SRFlipFlop : public BasicFlipFlop + { + typedef Mitov::BasicFlipFlop inherited; + + public: + OpenWire::SinkPin SetInputPin; + OpenWire::SinkPin ResetInputPin; + + protected: + void DoReceiveSet( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( AValue ) + SetValue( true ); + } + + void DoReceiveReset( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( AValue ) + SetValue( false ); + } + + public: + SRFlipFlop() + { + SetInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&SRFlipFlop::DoReceiveSet ); + ResetInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&SRFlipFlop::DoReceiveReset ); + } + }; +//--------------------------------------------------------------------------- + class ClockableFlipFlop : public Mitov::SRFlipFlop + { + typedef Mitov::SRFlipFlop inherited; + + public: + OpenWire::SinkPin ClockInputPin; + + protected: + virtual void DoClock() = 0; + + protected: + void DoClockReceive( void *_Data ) + { + DoClock(); + } + + public: + ClockableFlipFlop() + { + ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ClockableFlipFlop::DoClockReceive ); + } + + }; +//--------------------------------------------------------------------------- + class TFlipFlop : public Mitov::ClockableFlipFlop + { + typedef Mitov::ClockableFlipFlop inherited; + + public: + OpenWire::SinkPin ToggleInputPin; + + protected: + bool FToggleValue = true; + + protected: + void DoReceiveToggle( void *_Data ) + { + FToggleValue = *(bool *)_Data; + } + + protected: + virtual void DoClock() override + { + if( FToggleValue ) + SetValue( !FValue ); + } + + public: + TFlipFlop() + { + ToggleInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&TFlipFlop::DoReceiveToggle ); + } + + }; +//--------------------------------------------------------------------------- + class DFlipFlop : public Mitov::ClockableFlipFlop + { + typedef Mitov::ClockableFlipFlop inherited; + + public: + OpenWire::SinkPin DataInputPin; + + protected: + bool FData = false; + + protected: + virtual void DoClock() override + { + SetValue( FData ); + } + + protected: + void DoReceiveData( void *_Data ) + { + FData = *(bool *)_Data; + } + + public: + DFlipFlop() + { + DataInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&DFlipFlop::DoReceiveData ); + } + + }; +//--------------------------------------------------------------------------- + class JKFlipFlop : public Mitov::BasicFlipFlop + { + public: + OpenWire::SinkPin JInputPin; + OpenWire::SinkPin KInputPin; + OpenWire::SinkPin ClockInputPin; + + protected: + bool FJ : 1; + bool FK : 1; + + protected: + void DoReceiveJ( void *_Data ) + { + FJ = *(bool *)_Data; + } + + void DoReceiveK( void *_Data ) + { + FK = *(bool *)_Data; + } + + void DoClockReceive( void *_Data ) + { + if( FJ && FK ) + SetValue( !FValue ); + + else if( FJ ) + SetValue( true ); + + else if( FK ) + SetValue( false ); + + } + + public: + JKFlipFlop() : + FJ( false ), + FK( false ) + { + JInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&JKFlipFlop::DoReceiveJ ); + KInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&JKFlipFlop::DoReceiveK ); + ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&JKFlipFlop::DoClockReceive ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_LogicGates.h b/libraries/Mitov/Mitov_LogicGates.h new file mode 100644 index 0000000..b6f59ab --- /dev/null +++ b/libraries/Mitov/Mitov_LogicGates.h @@ -0,0 +1,77 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_LOGIC_GATES_h +#define _MITOV_LOGIC_GATES_h + +#include + +namespace Mitov +{ + template class BooleanOr : public CommonMultiInput + { + typedef CommonMultiInput inherited; + + protected: + virtual bool CalculateOutput() override + { + bool AValue = false; + for ( int i = 0; i < C_NUM_INPUTS; ++i ) + AValue |= inherited::InputPins[ i ].Value; + + return AValue; + } + + }; +//--------------------------------------------------------------------------- + template class BooleanAnd : public CommonMultiInput + { + typedef CommonMultiInput inherited; + + protected: + virtual bool CalculateOutput() override + { + bool AValue = (C_NUM_INPUTS > 0); + for ( int i = 0; i < C_NUM_INPUTS; ++i ) + AValue &= inherited::InputPins[ i ].Value; + + return AValue; + } + + }; +//--------------------------------------------------------------------------- + template class BooleanXor : public CommonMultiInput + { + typedef CommonMultiInput inherited; + + protected: + virtual bool CalculateOutput() override + { + bool AValue = false; + for ( int i = 0; i < C_NUM_INPUTS; ++i ) + AValue ^= inherited::InputPins[ i ].Value; + + return AValue; + } + + }; +//--------------------------------------------------------------------------- + class BooleanInverter : public CommonTypedFilter + { + protected: + virtual bool FilterValue(bool AValue) override + { + return ! AValue; + } + }; +//--------------------------------------------------------------------------- + +} + +#endif diff --git a/libraries/Mitov/Mitov_MPU9250.h b/libraries/Mitov/Mitov_MPU9250.h new file mode 100644 index 0000000..f587a3c --- /dev/null +++ b/libraries/Mitov/Mitov_MPU9250.h @@ -0,0 +1,466 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MPU9250_h +#define _MITOV_MPU9250_h + +#include +#include //I2C Arduino Library +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + namespace MPU9250Const + { + const byte Adresses[ 2 ] = { 0x68, 0x68 }; + + const byte MPU9150_RA_MAG_ADDRESS = 0x0C; + + const byte MPU9150_RA_MAG_ST1 = 0x02; + const byte MPU9150_RA_MAG_XOUT_L = 0x03; + const byte MPU9150_RA_MAG_XOUT_H = 0x04; + const byte MPU9150_RA_MAG_YOUT_L = 0x05; + const byte MPU9150_RA_MAG_YOUT_H = 0x06; + const byte MPU9150_RA_MAG_ZOUT_L = 0x07; + const byte MPU9150_RA_MAG_ZOUT_H = 0x08; + const byte MPU9150_RA_MAG_ST2 = 0x09; + const byte MPU9150_RA_MAG_CNTL1 = 0x0A; + const byte MPU9150_RA_MAG_CNTL2 = 0x0B; + + const byte MPU9150_RA_MAG_ASAX = 0x10; + const byte MPU9150_RA_MAG_ASAY = 0x11; + const byte MPU9150_RA_MAG_ASAZ = 0x12; + }; +//--------------------------------------------------------------------------- + enum MPU9250ClockSource { mcsAutoSelect = 6, mcsInternal = 0, mcsGyroX = 1, mcsGyroY = 2, mcsGyroZ = 3, mcsExt32K = 4, mcsExt19M = 5, mcsReset = 7 }; +//--------------------------------------------------------------------------- + class MPU9250BasicSensor : public OpenWire::Object + { + public: + OpenWire::SourcePin OutputPins[ 3 ]; + + }; +//--------------------------------------------------------------------------- + class MPU9250OptionalSensor + { + public: + bool Enabled : 1; + bool Queue : 1; + bool SelfTest : 1; // Added to save space as bitfield + + public: + MPU9250OptionalSensor() : + Enabled( true ), + Queue( false ), + SelfTest( false ) + { + } + + }; +//--------------------------------------------------------------------------- + typedef MPU9250OptionalSensor MPU9250OptionalSelfTestSensor; +//--------------------------------------------------------------------------- + class MPU9250OptionalAxesSensor : public MPU9250BasicSensor + { + public: + MPU9250OptionalSelfTestSensor X; + MPU9250OptionalSelfTestSensor Y; + MPU9250OptionalSelfTestSensor Z; + }; +//--------------------------------------------------------------------------- + enum ArduinoMPU9250AccelerometerRange : uint8_t { ar2g, ar4g, ar8g, ar16g }; +//--------------------------------------------------------------------------- + class MPU9250Accelerometer : public MPU9250OptionalAxesSensor + { + public: + ArduinoMPU9250AccelerometerRange FullScaleRange = ar2g; + + }; +//--------------------------------------------------------------------------- + enum TArduinoMPU9250GyroscopeRange : uint8_t { gr250dps, gr500dps, gr1000dps, gr2000dps }; +//--------------------------------------------------------------------------- + class MPU9250Gyroscope : public MPU9250OptionalAxesSensor + { + public: + TArduinoMPU9250GyroscopeRange FullScaleRange = gr250dps; + + }; +//--------------------------------------------------------------------------- + class MPU9250Compass : public MPU9250BasicSensor + { + public: + CompassAK8963Mode Mode : 2; + bool Enabled : 1; + bool HighResolution : 1; + + public: + OpenWire::SinkPin ResetInputPin; + OpenWire::SourcePin OverflowOutputPin; + + protected: + void DoResetReceive( void *_Data ) + { + I2C::WriteByte( MPU9250Const::MPU9150_RA_MAG_ADDRESS, MPU9250Const::MPU9150_RA_MAG_CNTL2, 0b00000001 ); + } + + public: + MPU9250Compass() : + Mode( cm100Hz ), + Enabled( true ), + HighResolution( true ) + { + ResetInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MPU9250Compass::DoResetReceive ); + } + }; +//--------------------------------------------------------------------------- + class MPU9250Thermometer : public MPU9250OptionalSensor + { + public: + OpenWire::SourcePin OutputPin; + }; +//--------------------------------------------------------------------------- + enum MPU9250GyroscopeThermometerFilter + { + gtf_GB_8800Hz_GF_32KHz_TB_4000Hz, + gtf_GB_3600Hz_GF_32KHz_TB_4000Hz, + gtf_GB_250Hz_GF_8KHz_TB_4000Hz, + gtf_GB_184Hz_GF_1KHz_TB_188Hz, + gtf_GB_92Hz_GF_1KHz_TB_98Hz, + gtf_GB_41Hz_GF_1KHz_TB_42Hz, + gtf_GB_20Hz_GF_1KHz_TB_20Hz, + gtf_GB_10Hz_GF_1KHz_TB_10Hz, + gtf_GB_5Hz_GF_1KHz_TB_5Hz, + gtf_GB_3600Hz_GF_8KHz_TB_4000Hz + }; +//--------------------------------------------------------------------------- + enum MPU9250FrameSynchronizationLocation { fslDisabled, fslThermometer, fslGyroscopeX, fslGyroscopeY, fslGyroscopeZ, fslAccelerometerX, fslAccelerometerY, fslAccelerometerZ }; +//--------------------------------------------------------------------------- + class MPU9250FrameSynchronization + { + public: + MPU9250FrameSynchronizationLocation Location : 3; + bool EnableInterrupt : 1; + bool InterruptOnLowLevel : 1; + + public: + MPU9250FrameSynchronization() : + Location( fslDisabled ), + EnableInterrupt( false ), + InterruptOnLowLevel( false ) + { + } + }; +//--------------------------------------------------------------------------- + class MPU9250Interrupt + { + public: + bool Inverted : 1; + bool OpenDrain : 1; + bool Latch : 1; + + public: + MPU9250Interrupt() : + Inverted( false ), + OpenDrain( false ), + Latch( true ) + { + } + }; +//--------------------------------------------------------------------------- + class MPU9250Queue + { + public: + bool BlockOnFull = false; + }; +//--------------------------------------------------------------------------- + class MPU9250I2C : public Mitov::EnabledComponent, public Mitov::ClockingSupport + { + typedef Mitov::EnabledComponent inherited; + + protected: + static const byte MPU9250_RA_SMPLRT_DIV = 0x19; + static const byte MPU9250_RA_CONFIG = 0x1A; + static const byte MPU9250_RA_GYRO_CONFIG = 0x1B; + static const byte MPU9250_RA_ACCEL_CONFIG = 0x1C; + static const byte MPU9250_RA_INT_PIN_CFG = 0x37; + static const byte MPU9250_RA_ACCEL_XOUT_H = 0x3B; + static const byte MPU9250_RA_ACCEL_XOUT_L = 0x3C; + static const byte MPU9250_RA_ACCEL_YOUT_H = 0x3D; + static const byte MPU9250_RA_ACCEL_YOUT_L = 0x3E; + static const byte MPU9250_RA_ACCEL_ZOUT_H = 0x3F; + static const byte MPU9250_RA_ACCEL_ZOUT_L = 0x40; + static const byte MPU9250_RA_PWR_MGMT_1 = 0x6B; + static const byte MPU9250_RA_PWR_MGMT_2 = 0x6C; + + public: + OpenWire::SinkPin ResetInputPin; + + public: + bool Address : 1; + bool Standby : 1; + MPU9250ClockSource ClockSource : 3; + MPU9250GyroscopeThermometerFilter GyroscopeThermometerFilter : 4; + uint8_t SampleRateDivider = 0; + + public: + MPU9250Accelerometer Accelerometer; + MPU9250Gyroscope Gyroscope; + MPU9250Compass Compass; + MPU9250Thermometer Thermometer; + MPU9250FrameSynchronization FrameSynchronization; + MPU9250Queue Queue; + MPU9250Interrupt Interrupt; + + protected: + float CompassAdjustmentValues[ 3 ]; + + protected: + virtual void DoClockReceive( void *_Data ) override + { + ReadSensors(); + } + + void DoResetReceive( void *_Data ) + { + } + + protected: + void ReadSensors() + { +// Serial.println( "ReadSensors" ); + const float AccelerometerCoefficients [] = + { + 2.0f / 32768, + 4.0f / 32768, + 8.0f / 32768, + 16.0f / 32768 + }; + + const float GyroscopeCoefficients [] = + { + 250.0f / 32768, + 500.0f / 32768, + 1000.0f / 32768, + 2000.0f / 32768 + }; + + const float CompassCoefficients[] = + { + 10.0f *4219.0f / 8190.0f, + 10.0f *4219.0f / 32760.0f + }; + + uint8_t AIntValues[ 7 * 2 ]; + + if( ReadBytes( MPU9250_RA_ACCEL_XOUT_H, sizeof( AIntValues ), AIntValues )) + { + for( int i = 0; i < 3; ++i ) + { + float AValue = (( ((int16_t)AIntValues[ i * 2 ] ) << 8 ) | AIntValues[ i * 2 + 1 ] ) * AccelerometerCoefficients[ Accelerometer.FullScaleRange ]; + Accelerometer.OutputPins[ i ].Notify( &AValue ); + } + + for( int i = 0; i < 3; ++i ) + { + float AValue = (((int16_t)AIntValues[ ( i + 4 ) * 2 ] ) << 8 | AIntValues[ ( i + 4 ) * 2 + 1 ] ) * GyroscopeCoefficients[ Gyroscope.FullScaleRange & 0x11 ]; + Gyroscope.OutputPins[ i ].Notify( &AValue ); + } + + float AValue = ((((int16_t)AIntValues[ 3 * 2 ] ) << 8 ) | AIntValues[ 3 * 2 + 1 ] ) / 333.87 + 21.0; + Thermometer.OutputPin.Notify( &AValue ); + } + + if( I2C::ReadBytes( MPU9250Const::MPU9150_RA_MAG_ADDRESS, MPU9250Const::MPU9150_RA_MAG_ST1, 1, AIntValues )) + { + Compass.OverflowOutputPin.SendValue( AIntValues[ 0 ] & 0b00000010 ); + if( AIntValues[ 0 ] & 0b00000001 ) + if( I2C::ReadBytes( MPU9250Const::MPU9150_RA_MAG_ADDRESS, MPU9250Const::MPU9150_RA_MAG_XOUT_L, 7, AIntValues )) + for( int i = 0; i < 3; ++i ) + { + float AValue = (( ((int16_t)AIntValues[ i * 2 + 1 ] ) << 8 ) | AIntValues[ i * 2 ] ) * CompassCoefficients[ Compass.HighResolution & 1 ] * CompassAdjustmentValues[ i ]; + Compass.OutputPins[ i ].Notify( &AValue ); + } + } + + } + + protected: + inline void WriteTo( byte ARegister, byte AData ) + { + I2C::WriteByte( MPU9250Const::Adresses[ Address ], ARegister, AData ); + } + + bool ReadBytes( uint8_t regAddr, uint8_t length, void *data ) + { + return I2C::ReadBytes( MPU9250Const::Adresses[ Address ], regAddr, length, data ); + } + + protected: + void UpdatePowerManagementReg1() + { + uint8_t AValue; + if( ClockSource = mcsAutoSelect ) + { + if( Gyroscope.X.Enabled ) + AValue = mcsGyroX; + + else if( Gyroscope.Y.Enabled ) + AValue = mcsGyroY; + + else if( Gyroscope.Z.Enabled ) + AValue = mcsGyroZ; + + else + AValue = mcsInternal; + } + + else + AValue = ClockSource; + + AValue |= ( Enabled ? 0 : 0b01000000 ) | + ( Standby ? 0b00010000 : 0 ) | + ( Thermometer.Enabled ? 0 : 0b00001000 ); + + WriteTo( MPU9250_RA_PWR_MGMT_1, AValue ); + } + + void UpdatePowerManagementReg2() + { + uint8_t AValue = ( Accelerometer.X.Enabled ? 0 : 0b00100000 ) | + ( Accelerometer.Y.Enabled ? 0 : 0b00010000 ) | + ( Accelerometer.Z.Enabled ? 0 : 0b00001000 ) | + ( Gyroscope.X.Enabled ? 0 : 0b00000100 ) | + ( Gyroscope.Y.Enabled ? 0 : 0b00000010 ) | + ( Gyroscope.Z.Enabled ? 0 : 0b00000001 ); + + WriteTo( MPU9250_RA_PWR_MGMT_2, AValue ); + } + + void UpdateConfigReg() + { + uint8_t AValue = (( GyroscopeThermometerFilter - 2 ) & 0b111 ) | + ( Queue.BlockOnFull ? 0b01000000 : 0 ) | + (( FrameSynchronization.Location & 0b111 ) << 4 ); + + WriteTo( MPU9250_RA_CONFIG, AValue ); + } + + void UpdateGyroConfigReg() + { + uint8_t AValue; + switch( GyroscopeThermometerFilter ) + { + case gtf_GB_8800Hz_GF_32KHz_TB_4000Hz: AValue = 0b11; break; + case gtf_GB_3600Hz_GF_32KHz_TB_4000Hz: AValue = 0b10; break; + default : AValue = 0b00; + } + + AValue |= (( Gyroscope.FullScaleRange & 0b11 ) << 3 ) | + ( Gyroscope.X.SelfTest ? 0b10000000 : 0 ) | + ( Gyroscope.Y.SelfTest ? 0b01000000 : 0 ) | + ( Gyroscope.Z.SelfTest ? 0b00100000 : 0 ); + + WriteTo( MPU9250_RA_GYRO_CONFIG, AValue ); + } + + void UpdateAccelerometerConfigReg() + { + byte AValue = (( Accelerometer.FullScaleRange & 0b11 ) << 3 ) | + ( Accelerometer.X.SelfTest ? 0b10000000 : 0 ) | + ( Accelerometer.Y.SelfTest ? 0b01000000 : 0 ) | + ( Accelerometer.Z.SelfTest ? 0b00100000 : 0 ); + + WriteTo( MPU9250_RA_ACCEL_CONFIG, AValue ); + } + + void UpdatenterruptPinAndBypassConfigReg( bool ADirectCompassAccess ) + { + byte AValue = ( Interrupt.Inverted ? 0b10000000 : 0 ) | + ( Interrupt.OpenDrain ? 0b01000000 : 0 ) | + ( Interrupt.Latch ? 0b00100000 : 0 ) | + ( FrameSynchronization.InterruptOnLowLevel ? 0b00001000 : 0 ) | + ( FrameSynchronization.EnableInterrupt ? 0b00000100 : 0 ) | + ( Thermometer.Queue & ( ! ADirectCompassAccess ) ? 0 : 0b00000010 ); + +// Serial.print( "UpdatenterruptPinAndBypassConfigReg: " ); Serial.println( AValue, BIN ); + + WriteTo( MPU9250_RA_INT_PIN_CFG, AValue ); + } + + void UpdateSampleRateDividerReg() + { + WriteTo( MPU9250_RA_SMPLRT_DIV, SampleRateDivider ); + } + + void UpdateCompassControlReg() + { + byte AValue; + if( Compass.Enabled ) + AValue = CompassAK8963Const::CompassModes[ Compass.Mode ]; + + else + AValue = 0; + + AValue |= ( Compass.HighResolution ? 0b00010000 : 0 ); + + I2C::WriteByte( MPU9250Const::MPU9150_RA_MAG_ADDRESS, MPU9250Const::MPU9150_RA_MAG_CNTL1, AValue ); + } + + void ReagCompassAdjustmentValues() + { + uint8_t AValues[ 3 ]; + + I2C::ReadBytes( MPU9250Const::MPU9150_RA_MAG_ADDRESS, MPU9250Const::MPU9150_RA_MAG_ASAX, sizeof( AValues ), AValues ); + for( int i = 0; i < 3; ++i ) + CompassAdjustmentValues[ i ] = (((float) AValues[ i ] ) - 128.0f) / 256.0f + 1.0f; + + } + + protected: + virtual void SystemStart() override + { + UpdatePowerManagementReg1(); + UpdatePowerManagementReg2(); + UpdateConfigReg(); + UpdateGyroConfigReg(); + UpdateAccelerometerConfigReg(); + UpdateSampleRateDividerReg(); + UpdatenterruptPinAndBypassConfigReg( true ); + UpdateCompassControlReg(); + ReagCompassAdjustmentValues(); + UpdatenterruptPinAndBypassConfigReg( false ); + + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( Enabled ) + if( ! ClockInputPin.IsConnected() ) + ReadSensors(); + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + MPU9250I2C() : + ClockSource( mcsAutoSelect ), + GyroscopeThermometerFilter( gtf_GB_250Hz_GF_8KHz_TB_4000Hz ), + Address( false ), + Standby( false ) + { + ResetInputPin.SetCallback( MAKE_CALLBACK( MPU9250I2C::DoResetReceive )); + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Math.h b/libraries/Mitov/Mitov_Math.h new file mode 100644 index 0000000..82a8adc --- /dev/null +++ b/libraries/Mitov/Mitov_Math.h @@ -0,0 +1,533 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MATH_h +#define _MITOV_MATH_h + +#include + +namespace Mitov +{ +#define Min Min +#define Max Max +//--------------------------------------------------------------------------- + #define MITOV_PI 3.14159265359 +//--------------------------------------------------------------------------- + template class CommonValueMathFilter : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + public: + T Value; + + public: + CommonValueMathFilter( T AValue = 0 ) : Value( AValue ) {} + + }; +//--------------------------------------------------------------------------- + template class AddValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return AValue + inherited::Value; + } + + }; +//--------------------------------------------------------------------------- + template class SubtractValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return AValue - inherited::Value; + } + + }; +//--------------------------------------------------------------------------- + template class SubtractFromValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return inherited::Value - AValue; + } + + }; +//--------------------------------------------------------------------------- + template class MultiplyByValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return AValue * inherited::Value; + } + + public: + MultiplyByValue() : + inherited( 1 ) + { + } + }; +//--------------------------------------------------------------------------- + template class DivideByValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return AValue / inherited::Value; + } + + public: + DivideByValue() : + inherited( 1 ) + { + } + }; +//--------------------------------------------------------------------------- + template class DivideValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return inherited::Value / AValue; + } + + }; +//--------------------------------------------------------------------------- + template class Inverse : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return -AValue; + } + + }; +//--------------------------------------------------------------------------- + template class Abs : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + protected: + virtual T FilterValue( T AValue ) + { + return abs( AValue ); + } + + }; +//--------------------------------------------------------------------------- + class MinLimit : public CommonValueMathFilter + { + protected: + virtual float FilterValue( float AValue ) + { + return ( AValue < Value ) ? Value : AValue; + } + }; +//--------------------------------------------------------------------------- + class MaxLimit : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual float FilterValue( float AValue ) + { + return ( AValue > Value ) ? Value : AValue; + } + + public: + MaxLimit() : + inherited( 1.0 ) + { + } + }; +//--------------------------------------------------------------------------- + class Limit : public CommonTypedFilter + { + public: + float Min = 0.0; + float Max = 1.0; + + protected: + virtual float FilterValue( float AValue ) + { + return ( AValue > Max ) ? + Max : + ( AValue < Min ) ? Min : AValue; + } + + }; +//--------------------------------------------------------------------------- + enum CompareValueType { ctEqual, ctNotEqual, ctBigger, ctSmaller, ctBiggerOrEqual, ctSmallerOrEqual }; +//--------------------------------------------------------------------------- + template class CompareValue : public CommonEnableFilter + { + typedef CommonEnableFilter inherited; + + public: + T Value; + + protected: + T FCurrentValue; + + public: + CompareValueType CompareType : 3; + bool OnlyChanged : 1; + + protected: + bool FOutputValue : 1; + bool FStarted : 1; + bool FProcessedOnce : 1; + + public: + void SetValue( T AValue ) + { + if( OnlyChanged ) + if( Value == AValue ) + return; + + Value = AValue; + ProcessOutput(); + } + + protected: + void ProcessOutput() + { + if( ! inherited::Enabled ) + return; + +// Serial.print( FCurrentValue ); Serial.print( " ? " ); Serial.println( Value ); + + bool ABoolValue; + switch( CompareType ) + { + case ctEqual: + ABoolValue = ( FCurrentValue == Value ); + break; + + case ctNotEqual: + ABoolValue = ( FCurrentValue != Value ); + break; + + case ctBigger: + ABoolValue = ( FCurrentValue > Value ); + break; + + case ctSmaller: + ABoolValue = ( FCurrentValue < Value ); + break; + + case ctBiggerOrEqual: + ABoolValue = ( FCurrentValue >= Value ); + break; + + case ctSmallerOrEqual: + ABoolValue = ( FCurrentValue <= Value ); + break; + + } + + if( ! OnlyChanged ) + if( FOutputValue ) + { + FOutputValue = false; + OutputPin.SendValue( false ); + } + + if( ( !FStarted ) || ( FOutputValue != ABoolValue ) ) + { + OutputPin.Notify( &ABoolValue ); + FOutputValue = ABoolValue; + FStarted = true; + } + } + + protected: + virtual void DoReceive( void *_Data ) override + { + T AValue = *(T*)_Data; + + if( OnlyChanged ) + if( FProcessedOnce ) + if( AValue == FCurrentValue ) + return; + + FCurrentValue = AValue; + FProcessedOnce = true; + + ProcessOutput(); + } + + public: + CompareValue( T AInitialValue ) : + Value( AInitialValue ), + FCurrentValue( AInitialValue ), + CompareType( ctEqual ), + OnlyChanged( true ), + FProcessedOnce( false ), + FStarted( false ), + FOutputValue( false ) + { + } + + }; +//--------------------------------------------------------------------------- + class CompareStringValue : public CompareValue + { + typedef CompareValue inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + String AValue = String( (char*)_Data ); + + if( OnlyChanged ) + if( FProcessedOnce ) + if( AValue == FCurrentValue ) + return; + + FCurrentValue = AValue; + FProcessedOnce = true; + + ProcessOutput(); + } + + public: + CompareStringValue() : + inherited( String() ) + { + } + }; +//--------------------------------------------------------------------------- + class AveragePeriod : public CommonFilter + { + public: + unsigned long Period = 1000; + + protected: + float FSum = 0.0f; + unsigned long FCount = 0; + unsigned long FLastTime = 0; + + protected: + virtual void DoReceive( void *_Data ) override + { + FSum += *(float *)_Data; + ++FCount; + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( currentMicros - FLastTime < Period ) + return; + + if( ! FCount ) + return; + + float AValue = FSum / FCount; + + FSum = 0.0; + FCount = 0; + FLastTime = currentMicros; + + OutputPin.Notify( &AValue ); + } + + }; +//--------------------------------------------------------------------------- + template class CommonMathMultiInput : public CommonClockedMultiInput + { + typedef CommonClockedMultiInput inherited; + + public: + bool Enabled = true; + + }; +//--------------------------------------------------------------------------- + template class Add : public CommonMathMultiInput + { + typedef CommonMathMultiInput inherited; + + protected: + virtual T CalculateOutput() override + { + T AValue = 0; + for( int i = 0; i < C_NUM_INPUTS; ++i ) + AValue += inherited::InputPins[ i ].Value; + + return AValue; + } + }; +//--------------------------------------------------------------------------- + template class Multiply : public CommonMathMultiInput + { + typedef CommonMathMultiInput inherited; + + protected: + virtual T CalculateOutput() override + { + T AValue = 1; + for( int i = 0; i < C_NUM_INPUTS; ++i ) + AValue *= inherited::InputPins[ i ].Value; + + return AValue; + } + }; +//--------------------------------------------------------------------------- + class ValueRange + { + public: + float Min = 0; + float Max = 1; + + }; +//--------------------------------------------------------------------------- + class MapRange : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + public: + ValueRange InputRange; + ValueRange OutputRange; + + protected: + virtual float FilterValue( float AValue ) override + { + return (( AValue - InputRange.Min ) * (OutputRange.Max - OutputRange.Min) / (InputRange.Max - InputRange.Min)) + OutputRange.Min; + } + }; +//--------------------------------------------------------------------------- + template class RaiseToPower : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual T FilterValue( T AValue ) override + { + return pow( AValue, inherited::Value ); + } + + }; +//--------------------------------------------------------------------------- + class Sine : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + protected: + virtual float FilterValue( float AValue ) override + { + return sin( AValue ); + } + + }; +//--------------------------------------------------------------------------- + class Cosine : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + protected: + virtual float FilterValue( float AValue ) override + { + return cos( AValue ); + } + + }; +//--------------------------------------------------------------------------- + class RadToDegrees : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + protected: + virtual float FilterValue( float AValue ) override + { + return AValue * 180 / MITOV_PI; + } + + }; +//--------------------------------------------------------------------------- + class DegreesToRad : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + protected: + virtual float FilterValue( float AValue ) override + { + return AValue * MITOV_PI / 180; + } + + }; +//--------------------------------------------------------------------------- + class AndUnsignedValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual uint32_t FilterValue( uint32_t AValue ) override + { + return AValue & Value; + } + + }; +//--------------------------------------------------------------------------- + class OrUnsignedValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual uint32_t FilterValue( uint32_t AValue ) override + { + return AValue | Value; + } + + }; +//--------------------------------------------------------------------------- + class XorUnsignedValue : public CommonValueMathFilter + { + typedef CommonValueMathFilter inherited; + + protected: + virtual uint32_t FilterValue( uint32_t AValue ) override + { + return AValue ^ Value; + } + + }; +//--------------------------------------------------------------------------- + class NotUnsignedValue : public CommonTypedFilter + { + typedef CommonTypedFilter inherited; + + protected: + virtual uint32_t FilterValue( uint32_t AValue ) override + { + return ~AValue; + } + + }; +//--------------------------------------------------------------------------- +#undef Min +#undef Max +} + +#endif diff --git a/libraries/Mitov/Mitov_MaximLedControl.h b/libraries/Mitov/Mitov_MaximLedControl.h new file mode 100644 index 0000000..149c11e --- /dev/null +++ b/libraries/Mitov/Mitov_MaximLedControl.h @@ -0,0 +1,1208 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MAXIM_LED_CONTROL_h +#define _MITOV_MAXIM_LED_CONTROL_h + +#include +#include +//#include + +namespace Mitov +{ + const byte C_MaximSegments[16] = + { + 0b1111110, // = 0 + 0b0110000, // = 1 + 0b1101101, // = 2 + 0b1111001, // = 3 + 0b0110011, // = 4 + 0b1011011, // = 5 + 0b1011111, // = 6 + 0b1110000, // = 7 + 0b1111111, // = 8 + 0b1111011, // = 9 + 0b1110111, // = A + 0b0011111, // = B + 0b0001101, // = C + 0b0111101, // = D + 0b1001111, // = E + 0b1000111 // = F + }; +//--------------------------------------------------------------------------- + const byte C_MaximDecimalPoint[2] = + { + 0b00000000, + 0b10000000 + }; +//--------------------------------------------------------------------------- + class MaximLedCommonGroup; +//--------------------------------------------------------------------------- + class MaximLedGroupOwner + { + public: + Mitov::SimpleObjectList FPixelGroups; + + public: + virtual void SetPixelValue( int AIndex, bool AValue ) = 0; + virtual bool GetPixelValue( int AIndex ) = 0; + + }; +//--------------------------------------------------------------------------- + class MaximLedCommonGroup : public OpenWire::Component + { + protected: + MaximLedGroupOwner &FOwner; + + bool Enabled = true; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateDisplay(); + } + + public: + virtual void StartPixels( int &AStartPixel ) = 0; + virtual void PixelsClock( unsigned long currentMicros ) + { + } + + protected: + virtual void UpdateDisplay() {} + + public: + MaximLedCommonGroup( MaximLedGroupOwner &AOwner ) : + FOwner( AOwner ) + { + FOwner.FPixelGroups.push_back( this ); + } + }; +//--------------------------------------------------------------------------- + template class MaximLedController : public Mitov::Basic_SPI, public Mitov::ClockingSupport, public Mitov::MaximLedGroupOwner + { + typedef Mitov::Basic_SPI inherited; + + protected: + static const byte OP_DIGIT0 = 1; + static const byte OP_DECODEMODE = 9; + static const byte OP_INTENSITY = 10; + static const byte OP_SCANLIMIT = 11; + static const byte OP_SHUTDOWN = 12; + static const byte OP_DISPLAYTEST = 15; + + protected: +// int FNumDevices; + + byte FRegistersCurrent[ COUNT_CONTROLLERS * 8 ]; + byte FRegisters[ COUNT_CONTROLLERS * 8 ]; + + bool FModified = false; + + public: + float Intensity = 1.0f; + + protected: + void SetIntensity( float AValue ) + { + if( Intensity == AValue ) + return; + + Intensity = AValue; + UpdateIntensity(); + } + + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateShutDown(); + } + + public: + virtual void SetPixelValue( int AIndex, bool AValue ) + { + if( AValue ) + FRegisters[ AIndex / 8 ] |= 1 << ( AIndex & 7 ); + + else + FRegisters[ AIndex / 8 ] &= ~( 1 << ( AIndex & 7 )); + + FModified = true; + } + + virtual bool GetPixelValue( int AIndex ) + { + return FRegisters[ AIndex / 8 ] & ( 1 << ( AIndex & 7 )); + } + + protected: + void spiTransferAll( byte opcode, byte data ) + { + //enable the line + ChipSelectOutputPin.SendValue( false ); + //Now shift out the data + + for(int i = 0; i < COUNT_CONTROLLERS; ++i ) + { + FSPI.transfer( opcode ); + FSPI.transfer( data ); + } + + //latch the data onto the display + ChipSelectOutputPin.SendValue( true ); + } + +/* + void spiTransfer( int addr, byte opcode, byte data ) + { + //enable the line + ChipSelectOutputPin.SendValue( false ); + //Now shift out the data + + for(int i = 1; i < COUNT_CONTROLLERS; ++i ) + FSPI.transfer16( 0 ); // Skip one chip + + FSPI.transfer( opcode ); + FSPI.transfer( data ); + + //latch the data onto the display + ChipSelectOutputPin.SendValue( true ); + } +*/ + protected: + inline void UpdateIntensity() + { + spiTransferAll( OP_INTENSITY, Intensity * 15 + 0.5 ); + } + + inline void UpdateShutDown() + { + spiTransferAll( OP_SHUTDOWN, Enabled ); + } + + void UpdatePixels() + { + uint16_t ABuffer[ COUNT_CONTROLLERS ]; + FModified = false; + + for(;;) + { + bool HasChange = false; + for( int AControllerIndex = 0; AControllerIndex < COUNT_CONTROLLERS; ++AControllerIndex ) + { + ABuffer[ AControllerIndex ] = 0; + for( int j = 0; j < 8; ++j ) + { + int ARegIndex = AControllerIndex * 8 + j; + uint16_t ANewRegValue = FRegisters[ ARegIndex ]; + if( FRegistersCurrent[ ARegIndex ] != ANewRegValue ) + { + FRegistersCurrent[ ARegIndex ] = ANewRegValue; + ABuffer[ AControllerIndex ] = ( ANewRegValue << 8 ) | ( OP_DIGIT0 + j ); + HasChange = true; + break; + } + } + } + + if( !HasChange ) + break; + + //enable the line + ChipSelectOutputPin.SendValue( false ); + FSPI.transfer( ABuffer, COUNT_CONTROLLERS * 2 ); + + //latch the data onto the display + ChipSelectOutputPin.SendValue( true ); + } + } + + protected: + virtual void SystemInit() + { + int AStartPixel = 0; + for( int i = 0; i < FPixelGroups.size(); ++i ) + FPixelGroups[ i ]->StartPixels( AStartPixel ); + +// FNumDevices = ( AStartPixel + 63 ) / 64; + +// FRegisters.SetCount( FNumDevices * 8, 0 ); +// FRegistersCurrent.SetCount( FNumDevices * 8, 0 ); + + spiTransferAll( OP_DISPLAYTEST, 0 ); + spiTransferAll( OP_SCANLIMIT, 7 ); + spiTransferAll( OP_DECODEMODE, 0 ); + + UpdateShutDown(); + UpdateIntensity(); + +// if( FModified ) + + + for( int i = 0; i < COUNT_CONTROLLERS * 8; ++i ) + FRegistersCurrent[ i ] = FRegisters[ i ] + 1; + + UpdatePixels(); + +// spiTransferAll( OP_DIGIT0, 255 ); + inherited::SystemInit(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + for( int i = 0; i < FPixelGroups.size(); ++i ) + FPixelGroups[ i ]->PixelsClock( currentMicros ); + + inherited::SystemLoopBegin( currentMicros ); + } + + virtual void SystemLoopEnd() + { + if( FModified ) + if( ! ClockInputPin.IsConnected()) + UpdatePixels(); + + inherited::SystemLoopEnd(); + } + + protected: + virtual void DoClockReceive( void * ) + { + if( FModified ) + UpdatePixels(); + } + + public: + MaximLedController( BasicSPI &ASPI ) : + inherited( ASPI ) + { + for( int i = 0; i < COUNT_CONTROLLERS * 8; ++i ) + FRegisters[ i ] = 0; + } + }; +//--------------------------------------------------------------------------- + class MaximLedBasicGroup : public MaximLedCommonGroup + { + typedef Mitov::MaximLedCommonGroup inherited; + + public: + int CountPixels = 64; + + public: + virtual void StartPixels( int &AStartPixel ) + { +// inherited::StartPixels( AStartPixel ); + AStartPixel += CountPixels; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MaximLedBasicInitialValueGroup : public MaximLedBasicGroup + { + typedef Mitov::MaximLedBasicGroup inherited; + + public: + bool InitialValue = false; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MaximLedGroupBasicBooleanPixels : public MaximLedBasicInitialValueGroup + { + typedef Mitov::MaximLedBasicInitialValueGroup inherited; + + protected: + class PixelVlaueSinkPin : public OpenWire::VlaueSinkPin + { + typedef OpenWire::VlaueSinkPin inherited; + + public: + MaximLedGroupBasicBooleanPixels *FOwner; + int FIndex; + + public: + virtual void Receive( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( AValue != Value ) + if( FOwner->Enabled ) + FOwner->FOwner.SetPixelValue( FIndex, AValue ); + + inherited::Receive( _Data ); + } + }; + + protected: + virtual void UpdateDisplay() + { + for( int i = 0; i < InputPins.size(); ++i ) + { + if( Enabled ) + FOwner.SetPixelValue( InputPins[ i ].FIndex, InputPins[ i ].Value ); + + else + FOwner.SetPixelValue( InputPins[ i ].FIndex, false ); + } + } + + public: + Mitov::SimpleList InputPins; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MaximLedGroup : public MaximLedGroupBasicBooleanPixels + { + typedef Mitov::MaximLedGroupBasicBooleanPixels inherited; + + public: + virtual void StartPixels( int &AStartPixel ) + { + for( int i = 0; i < InputPins.size(); ++i ) + { + InputPins[ i ].FOwner = this; + InputPins[ i ].FIndex = AStartPixel + i; + InputPins[ i ].Value = InitialValue; + FOwner.SetPixelValue( AStartPixel + i, InitialValue ); + } + + inherited::StartPixels( AStartPixel ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MaximLedGroupSection7Segments : public MaximLedGroupBasicBooleanPixels + { + typedef Mitov::MaximLedGroupBasicBooleanPixels inherited; + + public: + virtual void StartPixels( int &AStartPixel ) + { + for( int i = 0; i < 7; ++i ) + { + InputPins[ i ].FOwner = this; + InputPins[ i ].FIndex = AStartPixel + 6 - i; + InputPins[ i ].Value = InitialValue; + FOwner.SetPixelValue( AStartPixel + 6 - i, InitialValue ); + } + + InputPins[ 7 ].FOwner = this; + InputPins[ 7 ].FIndex = AStartPixel + 7; + InputPins[ 7 ].Value = InitialValue; + FOwner.SetPixelValue( AStartPixel + 7, InitialValue ); + + inherited::StartPixels( AStartPixel ); + } + + public: + MaximLedGroupSection7Segments( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ) + { + InputPins.SetCount( 8 ); + CountPixels = 8; + } + }; +//--------------------------------------------------------------------------- + class MaximLedGroupValueSection7Segments : public MaximLedCommonGroup + { + typedef Mitov::MaximLedCommonGroup inherited; + + public: + OpenWire::SinkPin InputPin; + OpenWire::SinkPin DecmalPointInputPin; + + public: + int InitialValue = 0; + bool InitialDecmalPointValue = false; + + protected: + int FValue; + bool FDecmalPointValue; + + int FStartPixel; + + public: + virtual void StartPixels( int &AStartPixel ) + { +// inherited::StartPixels( AStartPixel ); + FStartPixel = AStartPixel; + AStartPixel += 8; + } + + protected: + virtual void UpdateDisplay() + { + int AValue = (Enabled) ? C_MaximSegments[ FValue & 0xF ] | C_MaximDecimalPoint[ FDecmalPointValue & 1 ] : 0; + + for( int i = 0; i < 8; ++i ) + FOwner.SetPixelValue( FStartPixel + i, ( AValue >> i ) & 1 ); + } + + protected: + void DoReceive( void *_Data ) + { + int AValue = *(int *)_Data; + if( FValue == AValue ) + return; + + FValue = AValue; + UpdateDisplay(); + } + + void DoReceiveDecmalPoint( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( FDecmalPointValue == AValue ) + return; + + FDecmalPointValue = AValue; + UpdateDisplay(); + } + + virtual void SystemStart() + { + FValue = InitialValue; + FDecmalPointValue = InitialDecmalPointValue; + inherited::SystemStart(); + UpdateDisplay(); + } + + public: + MaximLedGroupValueSection7Segments( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupValueSection7Segments::DoReceive ); + DecmalPointInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupValueSection7Segments::DoReceiveDecmalPoint ); + } + }; +//--------------------------------------------------------------------------- + class MaximLedGroupBasicMultiDigitDisplay7Segments : public MaximLedCommonGroup + { + typedef Mitov::MaximLedCommonGroup inherited; + + public: + uint32_t CountDigits = 8; + bool ReversedOrder = false; + + protected: + int FStartPixel; + + public: + virtual void StartPixels( int &AStartPixel ) + { +// inherited::StartPixels( AStartPixel ); + FStartPixel = AStartPixel; + AStartPixel += CountDigits * 8; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + template class MaximLedGroupTypedValueDisplay7Segments : public MaximLedGroupBasicMultiDigitDisplay7Segments + { + typedef Mitov::MaximLedGroupBasicMultiDigitDisplay7Segments inherited; + + public: + OpenWire::SinkPin InputPin; + + public: + T_DATA InitialValue; + + protected: + T_DATA FValue; + + protected: + virtual byte GetSegmentsValue( int &ADigit ) = 0; + + virtual void UpdateDisplay() override + { + for( int ADigit = 0; ADigit < CountDigits; ++ ADigit ) + { + byte AValue; + if( inherited::Enabled ) + AValue = GetSegmentsValue( ADigit ); + + else + AValue = 0; + + if( ReversedOrder ) + { + for( int i = 0; i < 8; ++i ) + FOwner.SetPixelValue( FStartPixel + ( CountDigits - ADigit - 1 ) * 8 + i, ( AValue >> i ) & 1 ); + } + + else + { + for( int i = 0; i < 8; ++i ) + FOwner.SetPixelValue( FStartPixel + ADigit * 8 + i, ( AValue >> i ) & 1 ); + } + } + } + + protected: + void DoReceive( void *_Data ) + { + T_DATA AValue = *(T_DATA *)_Data; + if( FValue == AValue ) + return; + + FValue = AValue; + UpdateDisplay(); + } + + virtual void SystemStart() override + { + FValue = InitialValue; + inherited::SystemStart(); + UpdateDisplay(); + } + + public: + MaximLedGroupTypedValueDisplay7Segments( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ), + InitialValue( 0 ) // Needed for specialization + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupTypedValueDisplay7Segments::DoReceive ); + } + }; +//--------------------------------------------------------------------------- + template<> MaximLedGroupTypedValueDisplay7Segments::MaximLedGroupTypedValueDisplay7Segments( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupTypedValueDisplay7Segments::DoReceive ); + } +//--------------------------------------------------------------------------- + class MaximLedGroupIntegerDisplay7Segments : public MaximLedGroupTypedValueDisplay7Segments + { + typedef Mitov::MaximLedGroupTypedValueDisplay7Segments inherited; + + public: + bool LeadingZeroes = false; + + protected: + Mitov::SimpleList FPowers; + long FMaxValue; // The biggest possible to display value + long FMinValue; // The smallest possible to display value + + protected: + virtual byte GetSegmentsValue( int &ADigit ) + { + int AValue; + if( FValue > FMaxValue ) + AValue = 0b1000000; + + else if( FValue < FMinValue ) + AValue = 0b0001000; + + else + { + AValue = ( (int)abs( FValue ) ) / FPowers[ ADigit ]; + if( ( FValue < 0 ) && ( ADigit > 0 )) + { + if( ( !LeadingZeroes ) && ( AValue == 0 ) ) + { + int APreviousValue = ( -FValue ) / FPowers[ ADigit - 1 ]; + if( APreviousValue > 0 ) + AValue = 0b0000001; + + else + AValue = 0; + + } + + else + { + if( ADigit == CountDigits - 1 ) + AValue = 0b1000000; + + else + { + int ADigitValue = AValue % 10; + AValue = C_MaximSegments[ ADigitValue ]; + } + } + } + + else + { + if( ( !LeadingZeroes ) && ( AValue == 0 ) ) + AValue = 0; + + else + { + int ADigitValue = AValue % 10; + AValue = C_MaximSegments[ ADigitValue ]; + } + } + } + + return AValue; + } + + public: + virtual void SystemStart() + { + FPowers.SetCount( CountDigits ); + for( int i = 0; i < CountDigits; ++i ) + FPowers[ i ] = pow( 10, i ) + 0.5; + + FMaxValue = pow( 10, CountDigits ) + 0.5 - 1; + FMinValue = -( pow( 10, CountDigits - 1 ) + 0.5 - 1 ); + + inherited::SystemStart(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MaximLedGroupUnsignedBitPixelsSection : public MaximLedBasicGroup + { + typedef Mitov::MaximLedBasicGroup inherited; + + public: + OpenWire::SinkPin InputPin; + + public: + uint32_t InitialValue = 0; + + protected: + uint32_t FValue = 0; + int FStartPixel; + + protected: + virtual void StartPixels( int &AStartPixel ) + { + FValue = InitialValue; + FStartPixel = AStartPixel; + inherited::StartPixels( AStartPixel ); + } + + virtual void UpdateDisplay() + { + for( int i = 0; i < CountPixels; ++i ) + FOwner.SetPixelValue( FStartPixel + i, Enabled && ( FValue >> i ) & 1 ); + + } + + void DoReceive( uint32_t *_Data ) + { + uint32_t AValue = *(uint32_t *)_Data; + if( FValue == AValue ) + return; + + FValue = AValue; + UpdateDisplay(); + } + + public: + MaximLedGroupUnsignedBitPixelsSection( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ) + { + CountPixels = 32; + + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupUnsignedBitPixelsSection::DoReceive ); + } + }; +//--------------------------------------------------------------------------- + class MaximLedGroupAnalogDisplay7Segments : public MaximLedGroupTypedValueDisplay7Segments + { + typedef Mitov::MaximLedGroupTypedValueDisplay7Segments inherited; + + public: + int Precision = 2; + + protected: + char *FBuffer; + char *FStartChar; + byte FTextLength; + byte FFirstPos; + + char FDecimalPointPos; + + public: + virtual byte GetSegmentsValue( int &ADigit ) + { + int AValue; + int ANumDigits = CountDigits; + if( ! FStartChar ) + { + FStartChar = dtostrf( FValue, 1, Precision, FBuffer ); +// Serial.println( FStartChar ); + String AText( FStartChar ); + FTextLength = AText.length(); // strlen( FStartChar ); +// FTextLength = strlen( FStartChar ); +// Serial.println( FTextLength ); + FDecimalPointPos = AText.indexOf( '.' ); + if( Precision == 0 ) + { + if( FTextLength <= ANumDigits ) + FFirstPos = FTextLength - 1; + + else + FFirstPos = ANumDigits - 1; + + +// Serial.println( FStartChar ); +// Serial.println( FTextLength ); +// Serial.println( FFirstPos ); +// Serial.println( FDecimalPointPos ); + } + + else + { + if( FTextLength <= ANumDigits + 1 ) + FFirstPos = FTextLength - 1; + + else + FFirstPos = ANumDigits + 1 - 1; + } + +// Serial.println( FFirstPos ); + } + + int ACorrectedTextLength = FTextLength; + if( Precision > 0 ) + --ACorrectedTextLength; + + if( ( ACorrectedTextLength - Precision ) > ANumDigits ) + { + if( FValue > 0 ) + AValue = 0b1000000; // Overflow + + + else + AValue = 0b0001000; // Overflow - + } + + else + { + int ATextPos = FFirstPos - ADigit; + if( ATextPos < 0 ) + AValue = 0; + + else + { + if( ATextPos < 0 ) + return( 0 ); + + bool ADecimalPoint = ( FStartChar[ ATextPos ] == '.' ); + if( ATextPos <= FDecimalPointPos ) + --ATextPos; + +// if( ADecimalPoint ) +// --ATextPos; + + if( ATextPos < 0 ) + return( 0 ); + +/* + if( FDigit == 0 ) + { + Serial.println( FStartChar ); + Serial.println( ATextPos ); + } +*/ + if( FStartChar[ ATextPos ] == '-' ) + AValue = 0b0000001; + + else + { + AValue = FStartChar[ ATextPos ] - '0'; + AValue = C_MaximSegments[ AValue ]; + } + + if( ADecimalPoint ) + AValue |= 0x80; + + } + } + + return AValue; + } + + virtual void UpdateDisplay() + { + FStartChar = NULL; + inherited::UpdateDisplay(); + } + + protected: + virtual void SystemStart() + { + FBuffer = new char[ 15 + Precision ]; + inherited::SystemStart(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MaximLedBasicValueGroup : public MaximLedBasicInitialValueGroup + { + typedef MaximLedBasicInitialValueGroup inherited; + + public: + OpenWire::SinkPin InputPin; + + protected: + bool FValue; + + protected: + int FStartPixel; + + public: + virtual void StartPixels( int &AStartPixel ) + { + FStartPixel = AStartPixel; + inherited::StartPixels( AStartPixel ); + } + + protected: + void DoReceive( void *_Data ) + { + bool AValue = *(bool *)_Data; + if( FValue == AValue ) + return; + + FValue = AValue; + UpdateDisplay(); + } + + virtual void SystemStart() + { + FValue = InitialValue; + inherited::SystemStart(); + UpdateDisplay(); + } + + public: + MaximLedBasicValueGroup( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedBasicValueGroup::DoReceive ); + } + }; +//--------------------------------------------------------------------------- + class MaximLedSingleValueGroup : public MaximLedBasicValueGroup + { + typedef MaximLedBasicValueGroup inherited; + + protected: + virtual void UpdateDisplay() override + { + for( int i = 0; i < CountPixels; ++i ) + { + if( Enabled ) + FOwner.SetPixelValue( FStartPixel + i, FValue ); + + else + FOwner.SetPixelValue( FStartPixel + i, false ); + } + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MaximLedIndexedPixelGroup : public MaximLedBasicValueGroup + { + typedef MaximLedBasicValueGroup inherited; + + public: + OpenWire::SinkPin IndexInputPin; + + public: + uint32_t InitialIndex = 0; + + protected: + unsigned long FIndex; + + protected: + void DoReceiveIndex( void *_Data ) + { + unsigned long AIndex = *(unsigned long *)_Data; + if( AIndex > CountPixels ) + AIndex = CountPixels; + + if( FIndex == AIndex ) + return; + + FIndex = AIndex; + UpdateDisplay(); + } + + virtual void UpdateDisplay() override + { + if( Enabled ) + FOwner.SetPixelValue( FStartPixel + FIndex, FValue ); + + else + FOwner.SetPixelValue( FStartPixel + FIndex, false ); + } + + public: + MaximLedIndexedPixelGroup( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ) + { + IndexInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedIndexedPixelGroup::DoReceiveIndex ); + } + }; +//--------------------------------------------------------------------------- + class MaximLedIndexed2DPixelGroup : public MaximLedBasicValueGroup + { + typedef MaximLedBasicValueGroup inherited; + + public: + OpenWire::SinkPin IndexInputPins[ 2 ]; + + public: + unsigned long Width = 8; + unsigned long InitialIndexX = 0; + unsigned long InitialIndexY = 0; + + protected: + unsigned long FIndexX; + unsigned long FIndexY; + + protected: + void DoReceiveIndexX( void *_Data ) + { + unsigned long AIndex = *(unsigned long *)_Data; + if( AIndex > Width ) + AIndex = Width; + + if( FIndexX == AIndex ) + return; + + FIndexX = AIndex; + UpdateDisplay(); + } + + void DoReceiveIndexY( void *_Data ) + { + unsigned long AIndex = *(unsigned long *)_Data; + unsigned long AHeight = ( CountPixels + Width - 1 ) / Width; + if( AIndex > AHeight ) + AIndex = AHeight; + + if( FIndexY == AIndex ) + return; + + FIndexY = AIndex; + UpdateDisplay(); + } + + virtual void UpdateDisplay() + { + unsigned long AIndex = FStartPixel + FIndexY * Width + FIndexX; + if( Enabled ) + FOwner.SetPixelValue( AIndex, FValue ); + + else + FOwner.SetPixelValue( AIndex, false ); + } + + public: + MaximLedIndexed2DPixelGroup( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ) + { + IndexInputPins[ 0 ].SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedIndexed2DPixelGroup::DoReceiveIndexX ); + IndexInputPins[ 1 ].SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedIndexed2DPixelGroup::DoReceiveIndexY ); + } + }; +//--------------------------------------------------------------------------- + class MaximLedRunningPixelGroup; +//--------------------------------------------------------------------------- + class MaximLedPixelsReversedProperty + { + protected: + MaximLedRunningPixelGroup &FOwner; + + public: + bool Reversed : 1; + bool AllPixels : 1; + + public: + void SetReversed( bool AValue ); + + public: + MaximLedPixelsReversedProperty( MaximLedRunningPixelGroup &AOwner ) : + FOwner( AOwner ), + Reversed( false ), + AllPixels( false ) + { + } + }; +//--------------------------------------------------------------------------- + class MaximLedRunningPixelGroup : public MaximLedBasicValueGroup + { + typedef MaximLedBasicValueGroup inherited; + + public: + OpenWire::ConnectSinkPin StepInputPin; + OpenWire::SourcePin OutputPin; + + public: + MaximLedPixelsReversedProperty Reversed; + + public: + void ReversePixels() + { + for( int i = 0; i < CountPixels / 2; ++i ) + { + bool AOldValue1 = FOwner.GetPixelValue( FStartPixel + ( CountPixels - i - 1 )); + bool AOldValue2 = FOwner.GetPixelValue( FStartPixel + i ); + + FOwner.SetPixelValue( FStartPixel + i, AOldValue1 ); + FOwner.SetPixelValue( FStartPixel + ( CountPixels - i - 1 ), AOldValue2 ); + } + } + + protected: + void AnimatePixels() + { + if( Reversed.Reversed ) + { + bool AOldValue = FOwner.GetPixelValue( FStartPixel ); + OutputPin.Notify( &AOldValue ); + for( int i = 0; i < CountPixels - 1; ++i ) + { + AOldValue = FOwner.GetPixelValue( FStartPixel + i + 1 ); + FOwner.SetPixelValue( FStartPixel + i, AOldValue ); + } + + FOwner.SetPixelValue( FStartPixel + CountPixels - 1, FValue ); + } + + else + { + bool AOldValue = FOwner.GetPixelValue( FStartPixel + CountPixels - 1 ); + OutputPin.Notify( &AOldValue ); + for( int i = CountPixels - 1; i--; ) + { + AOldValue = FOwner.GetPixelValue( FStartPixel + i ); + FOwner.SetPixelValue( FStartPixel + i + 1, AOldValue ); + } + + FOwner.SetPixelValue( FStartPixel, FValue ); + } +// FOwner->FModified = true; + } + + void DoReceiveStep( void *_Data ) + { + AnimatePixels(); + } + + public: + virtual void PixelsClock( unsigned long currentMicros ) + { + if( StepInputPin.IsConnected()) + return; + + AnimatePixels(); + } + + public: + MaximLedRunningPixelGroup( MaximLedGroupOwner &AOwner ) : + inherited( AOwner ), + Reversed( *this ) + { + StepInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedRunningPixelGroup::DoReceiveStep ); + } + }; +//--------------------------------------------------------------------------- + inline void MaximLedPixelsReversedProperty::SetReversed( bool AValue ) + { + if( Reversed == AValue ) + return; + + Reversed = AValue; + if( AllPixels ) + FOwner.ReversePixels(); + + } +//--------------------------------------------------------------------------- + class MaximLedRepeatGroup : public MaximLedBasicInitialValueGroup, public MaximLedGroupOwner + { + typedef MaximLedBasicInitialValueGroup inherited; + + protected: + int FSubPixelCount; + int FRepeatCount; + int FStartPixel; + + public: + virtual void SetPixelValue( int AIndex, bool AValue ) + { + for( int i = 0; i < FRepeatCount; ++i ) + FOwner.SetPixelValue( FStartPixel + AIndex + i * FSubPixelCount, AValue ); + } + + virtual bool GetPixelValue( int AIndex ) + { + return FOwner.GetPixelValue( FStartPixel + AIndex ); + } + + public: + virtual void StartPixels( int &AStartPixel ) + { + FStartPixel = AStartPixel; + inherited::StartPixels( AStartPixel ); + + FSubPixelCount = 0; + for( int i = 0; i < FPixelGroups.size(); ++i ) + FPixelGroups[ i ]->StartPixels( FSubPixelCount ); + + if( FSubPixelCount == 0 ) + FRepeatCount = 0; + + else + FRepeatCount = ( CountPixels + FSubPixelCount - 1 ) / FSubPixelCount; + + } + + virtual void PixelsClock( unsigned long currentMicros ) + { + inherited::PixelsClock( currentMicros ); + + for( int i = 0; i < FPixelGroups.size(); ++i ) + FPixelGroups[ i ]->PixelsClock( currentMicros ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_MaximLedControl_7SegmentText.h b/libraries/Mitov/Mitov_MaximLedControl_7SegmentText.h new file mode 100644 index 0000000..42c0e30 --- /dev/null +++ b/libraries/Mitov/Mitov_MaximLedControl_7SegmentText.h @@ -0,0 +1,171 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MAXIM_LED_CONTROL_7SEGMENT_TEXT_h +#define _MITOV_MAXIM_LED_CONTROL_7SEGMENT_TEXT_h + +#include +#include +//#include + +namespace Mitov +{ + const static byte C_MaximText7Segments[] PROGMEM = + { + B10100000, // ! + B00100010, // " + B00000000, // # + B01011011, // $ + B00100101, // % + B01111111, // & + B00000010, // ' + + B01001110, // ( + B01111000, // ) + B01100011, // * + B00110001, // + + B00000100, // , + B00000001, // - + B10000000, // . + B00100101, // / + + B01111110, // 0 + B00110000, // 1 + B01101101, // 2 + B01111001, // 3 + B00110011, // 4 + B01011011, // 5 + B01011111, // 6 + B01110000, // 7 + + B01111111, // 8 + B01111011, // 9 + B00000000, // : + B00000000, // ; + B00000000, // < + B01000001, // = + B00000000, // > + B01100101, // ? + + B01101111, // @ + B01110111, // A + B00011111, // B + B00001101, // C + B00111101, // D + B01001111, // E + B01000111, // F + B01011110, // G + + B00110111, // H + B00110000, // I + B00111100, // J + B00110111, // K ??? + B00001110, // L + B00000000, // M ??? + B00010101, // N + B01111110, // O + + B01100111, // P + B01111110, // Q + B00000101, // R + B01011011, // S + B00001111, // T + B00111110, // U + B00111110, // V + B00000000, // W ??? + + B00110111, // X + B00110011, // Y + B01101101, // Z + B01001110, // [ + B00010011, // backslash + B01111000, // ] + B01100010, // ^ + B00001000, // _ + + B00100000, // ` + B01110111, // a + B00011111, // b + B00001101, // c + B00111101, // d + B01001111, // e + B01000111, // f + B01111011, // g + + B00010111, // h + B00010000, // i + B00111100, // j + B00110111, // k ??? + B00110000, // l + B00000000, // m ??? + B00010101, // n + B00011101, // o + + B01100111, // P + B01110011, // q + B00000101, // r + B01011011, // s + B00001111, // t + B00011100, // u + B00011100, // v + B00000000, // w ??? + + B00110111, // x + B00110011, // y + B01101101, // z + B01001110, // { + B00000110, // | + B01111000, // } + B00010011 // ~ + }; +//--------------------------------------------------------------------------- + class MaximLedGroupTextDisplay7Segments : public MaximLedGroupTypedValueDisplay7Segments + { + typedef Mitov::MaximLedGroupTypedValueDisplay7Segments inherited; + + protected: + virtual byte GetSegmentsValue( int &ADigit ) + { + int ARealDigit = CountDigits - ADigit - 1; + if( ARealDigit >= FValue.length() ) + return 0; + + byte AValue = FValue[ ARealDigit ]; + + if( AValue <= ' ' ) + return 0; + + if( AValue > 126 ) + return 0; + +// byte AResult = C_MaximText7Segments[ AValue ]; + byte AResult = pgm_read_byte_near( C_MaximText7Segments + AValue - ' ' - 1 ); + if( AResult & 0x80 ) + return AResult; + + if( ARealDigit + 1 >= FValue.length() ) + return AResult; + + if( C_MaximText7Segments[ FValue[ ARealDigit + 1 ]] != '.' ) + return AResult; + + ++ARealDigit; + AResult |= 0x80; + + return AResult; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Maxim_MAX521X.h b/libraries/Mitov/Mitov_Maxim_MAX521X.h new file mode 100644 index 0000000..dcd6f03 --- /dev/null +++ b/libraries/Mitov/Mitov_Maxim_MAX521X.h @@ -0,0 +1,125 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MAXIM_MAX521X_h +#define _MITOV_MAXIM_MAX521X_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + enum Maxim_MAX521X_ShutDownMode { msdmHighImpedance, msdm100K, msdm1K }; +//--------------------------------------------------------------------------- + class Maxim_MAX521X : public Mitov::Basic_SPI, public ClockingSupport + { + typedef Mitov::Basic_SPI inherited; + + public: + OpenWire::SinkPin InputPin; + + public: + Maxim_MAX521X_ShutDownMode ShutDownMode = msdmHighImpedance; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + SPI_write( 2, 0 ); + + else + SPI_write( 2, ( ((word)ShutDownMode) + 1 ) << 10 ); + + } + + protected: + word FValue = 0; + + protected: + void UpdateValue() + { + SPI_write( 1, FValue ); + } + + virtual void DoClockReceive( void *_Data ) override + { + UpdateValue(); + } + + protected: + virtual void SPI_transfer( byte AAddress, word AData ) = 0; + + void SPI_write( byte AAddress, word AData ) + { + ChipSelectOutputPin.SendValue( false ); + SPI_transfer( AAddress, AData ); + ChipSelectOutputPin.SendValue( true ); + } + + void DoReceive( void *_Data ) + { + FValue = constrain( *(float*)_Data, 0, 1 ) * 65536 + 0.5; + if( ! ClockInputPin.IsConnected() ) + UpdateValue(); + } + + public: + Maxim_MAX521X( BasicSPI &ASPI ) : + inherited( ASPI ) + { + InputPin.SetCallback( MAKE_CALLBACK( Maxim_MAX521X::DoReceive )); + } + }; +//--------------------------------------------------------------------------- + class Maxim_MAX5214 : public Mitov::Maxim_MAX521X + { + typedef Mitov::Maxim_MAX521X inherited; + + protected: + virtual void SPI_transfer( byte AAddress, word AData ) + { + AData >>= 2; + AData |= ((word)AAddress) << 14; + FSPI.transfer16( AData ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class Maxim_MAX5216 : public Mitov::Maxim_MAX521X + { + typedef Mitov::Maxim_MAX521X inherited; + + protected: + virtual void SPI_transfer( byte AAddress, word AData ) + { + byte AHighByte = AData >> 10; + AHighByte |= AAddress << 6; + + AData <<= 6; + + FSPI.transfer( AHighByte ); + FSPI.transfer16( AData ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Maxim_MAX7300.h b/libraries/Mitov/Mitov_Maxim_MAX7300.h new file mode 100644 index 0000000..8a8164c --- /dev/null +++ b/libraries/Mitov/Mitov_Maxim_MAX7300.h @@ -0,0 +1,290 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MAXIM_MAX7300_h +#define _MITOV_MAXIM_MAX7300_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class Maxim_MAX7300_Channel; +//--------------------------------------------------------------------------- + class Maxim_MAX7300 : public Mitov::EnableBasicGPIO + { + typedef Mitov::EnableBasicGPIO inherited; + + public: + byte Address = 0; + + protected: + bool FModifiedMap = false; + bool FModifiedPorts = false; + byte FConfigMap[ 7 ][ 2 ]; + uint32_t FPorts[ 2 ]; + uint32_t FReadMap = 0; + uint32_t FReadRegistersMap = 0; + uint32_t FReadBits; + + protected: + void BeginTransmissionAt( byte ARegister ) + { + byte AAddress = 0b01000000 | ( Address & 0b1111 ); + + Wire.beginTransmission( AAddress ); + + Wire.write( ARegister ); + } + + void WriteRegister( byte ARegister, byte AValue ) + { +// Serial.print( "WriteRegister: " ); Serial.print( ARegister ); Serial.print( " " ); Serial.println( AValue ); + + BeginTransmissionAt( ARegister ); + Wire.write( AValue ); + Wire.endTransmission(); + } + + virtual void UpdateEnable() + { + if( Enabled ) + WriteRegister( 4, 1 ); + + else + WriteRegister( 4, 0 ); + + } + + void UpdateConfigMap() + { +// Serial.println( "UpdateConfigMap" ); + bool AInUpdate = false; + for( int i = 0; i < 7; ++i ) + { + if( FConfigMap[ i ][ 0 ] != FConfigMap[ i ][ 1 ] ) + { + if( ! AInUpdate ) + { +// Serial.print( "BeginTransmissionAt: " ); Serial.println( 9 + i ); + BeginTransmissionAt( 9 + i ); + AInUpdate = true; + } + +// Serial.println( i ); +// Serial.println( FConfigMap[ i ][ 0 ] ); + + Wire.write( FConfigMap[ i ][ 0 ] ); + FConfigMap[ i ][ 1 ] = FConfigMap[ i ][ 0 ]; + } + + else if( AInUpdate ) + { + Wire.endTransmission(); + AInUpdate = false; + } + } + + if( AInUpdate ) + Wire.endTransmission(); + + FReadRegistersMap = 0; + for( int i = 0; i <= 0x58 - 0x44; ++i ) + if( FReadMap & ((uint32_t)0xFF) << i ) + { + FReadRegistersMap |= ((uint32_t)1 ) << i; + i += 7; + } + +// Serial.print( "FReadRegistersMap: " ); Serial.println( FReadRegistersMap ); + + FModifiedMap = false; + } + + void UpdatePorts() + { +// Serial.println( "UpdatePorts" ); +// Serial.println( FPorts[ 0 ] ); +// Serial.println( FPorts[ 1 ] ); + for( int i = 0; i < 28; ++i ) + { + uint32_t AMask = ((uint32_t)1) << i; +// Serial.println( AMask ); + if( ( FPorts[ 0 ] & AMask ) != ( FPorts[ 1 ] & AMask ) ) + { +// Serial.println( i ); +// Serial.println( AMask ); + WriteRegister( 0x44 + i, FPorts[ 0 ] >> i ); + i += 8; +// for( int j = i / 8; j < 4; j ++ ) +// WriteRegister( 0x44 + j * 8, FPorts[ 0 ] >> j * 8 ); + +// break; + } + } + + FPorts[ 1 ] = FPorts[ 0 ]; + FModifiedPorts = false; + } + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + UpdateEnable(); + + for( int i = 0; i < 7; ++i ) + FConfigMap[ i ][ 1 ] = ~FConfigMap[ i ][ 0 ]; + + FPorts[ 1 ] = ~FPorts[ 0 ]; + + UpdateConfigMap(); + UpdatePorts(); + +// UpdateOutput(); + } + + virtual void SystemLoopUpdateHardware() + { + if( FModifiedMap ) +// if( ! ClockInputPin.IsConnected() ) + UpdateConfigMap(); + + if( FModifiedPorts ) + UpdatePorts(); + + inherited::SystemLoopUpdateHardware(); + } + + public: + bool GetBitValue( uint32_t AIndex ) + { + return( ( FReadBits & ( ((uint32_t)1 ) << AIndex )) != 0 ); + } + + void SetChannelValue( int AIndex, bool AValue ) + { +// AIndex += 4; + +// Serial.println( "SetChannelValue" ); +// Serial.println( AIndex ); +// Serial.println( AValue ); + + FPorts[ 0 ] &= ~( ((uint32_t)0b1 ) << AIndex ); + FPorts[ 0 ] |= ( ((uint32_t)AValue ) & 1 ) << AIndex; + FModifiedPorts = true; + } + + void SetChannelMode( int AIndex, int AMode ) + { +// AIndex += 4; + +// Serial.println( "SetChannelMode" ); +// Serial.println( AIndex ); +// Serial.println( AMode ); + + int AConfigIndex = AIndex / 4; + int AOffset = ( AIndex % 4 ) * 2; + +// Serial.println( AConfigIndex ); +// Serial.println( AOffset ); + + FConfigMap[ AConfigIndex ][ 0 ] &= ~( ((uint32_t)0b11) << AOffset ); + FConfigMap[ AConfigIndex ][ 0 ] |= ((uint32_t)AMode) << AOffset; + + if( AMode & 0b10 ) // Check if it is input + FReadMap |= ((uint32_t)1) << AIndex; + + else + FReadMap &= ~( ((uint32_t)1) << AIndex ); + + FModifiedMap = true; + } + + protected: + virtual void PerformRead() + { + if( ! FReadRegistersMap) + return; + + FReadBits = 0; + for( int i = 0; i <= 0x58 - 0x44; ++i ) + if( (((uint32_t)1 ) << i ) & FReadRegistersMap ) + { + BeginTransmissionAt( 0x44 + i ); + Wire.endTransmission(); + Wire.requestFrom( 0b01000000 | ( Address & 0b1111 ), 1 ); + while (Wire.available() < 1 ); + + uint32_t ARegister = Wire.read(); + + FReadBits |= ARegister << i; + +// Serial.print( i ); Serial.print( ": " ); Serial.println( ARegister ); + + i += 7; + } + + for( int i = 0; i < inherited::FChannels.size(); ++i ) + inherited::FChannels[ i ]->UpdateInput(); + + } + + public: + Maxim_MAX7300() + { + for( int i = 0; i < 7; ++i ) + FConfigMap[ i ][ 0 ] = 0b10101010; + } + + }; +//--------------------------------------------------------------------------- + class Maxim_MAX7300_Channel : public OwnedBasicGPIOChannel + { + typedef OwnedBasicGPIOChannel inherited; + + + public: + virtual void UpdateInput() + { + UpdateOutput( FOwner.GetBitValue( FIndex )); + } + + protected: + virtual void PinDirectionsInit() + { + if( FIsOutput ) + { + FOwner.SetChannelMode( FIndex, 1 ); //pinMode( FPinNumber, OUTPUT ); + FOwner.SetChannelValue( FIndex, FValue ); + } + + else + { + if( FIsPullUp ) + FOwner.SetChannelMode( FIndex, 3 ); //pinMode( FPinNumber, INPUT_PULLUP ); + + else + FOwner.SetChannelMode( FIndex, 2 ); //pinMode( FPinNumber, INPUT ); + } + } + + public: + Maxim_MAX7300_Channel( Maxim_MAX7300 &AOwner, int AIndex, bool AInitialValue, bool AIsOutput, bool AIsPullUp, bool AIsCombinedInOut ) : + inherited( AOwner, AIndex, AInitialValue, AIsOutput, AIsPullUp, AIsCombinedInOut ) + { + PinDirectionsInit(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Maxim_MotorDriverShield.h b/libraries/Mitov/Mitov_Maxim_MotorDriverShield.h new file mode 100644 index 0000000..d55daf1 --- /dev/null +++ b/libraries/Mitov/Mitov_Maxim_MotorDriverShield.h @@ -0,0 +1,400 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MAXIM_MOTOR_DRIVER_SHIELD_h +#define _MITOV_MAXIM_MOTOR_DRIVER_SHIELD_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + enum TArduinoMaximMotorCurrentRegulationMode { crmRipple25, crmFastDecay, crmSlowDecay }; +//--------------------------------------------------------------------------- + class Maxim_MotorDriverBasicChannel; +//--------------------------------------------------------------------------- + class Maxim_MotorDriverBasicShield : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + Mitov::SimpleList FChannels; + byte FChanged = 0xFF; + bool FModified = true; + + protected: + byte F_MAX7300; + byte F_MAX5387_1; + byte F_MAX5387_2; + + protected: + void DoPotentiometerTransmission( byte Address, byte ARegister, byte AData ) + { + byte AAddress = 0b0101000 | (( Address & 0b111 ) << 1 ); + +// Serial.print( AAddress ); +// Serial.print( " " ); +// Serial.print( ARegister ); +// Serial.print( " " ); +// Serial.println( AData ); + + Wire.beginTransmission( AAddress ); + Wire.write( ARegister ); + Wire.write( AData ); + Wire.endTransmission(); + } + + void DoGPIOTransmissionAt( byte ARegister, byte AData ) + { + byte AAddress = 0b01000000 | ( F_MAX7300 & 0b1111 ); + + Wire.beginTransmission( AAddress ); + Wire.write( ARegister ); + Wire.write( AData ); + Wire.endTransmission(); + } + + byte DoGPIOReadAt( byte ARegister ) + { + byte AAddress = 0b01000000 | ( F_MAX7300 & 0b1111 ); + + Wire.beginTransmission( AAddress ); + Wire.write( ARegister ); + Wire.endTransmission(); + Wire.requestFrom( AAddress, (byte)1 ); + return Wire.read(); + } + + protected: + void UpdateSettings(); + + virtual void SystemStart(); + + virtual void SystemLoopUpdateHardware() override + { + if( FModified ) + UpdateSettings(); + + inherited::SystemLoopUpdateHardware(); + } + + void UpdateFailures(); + + public: + Maxim_MotorDriverBasicShield( byte A_MAX7300, byte A_MAX5387_1, byte A_MAX5387_2 ) : + F_MAX7300( A_MAX7300 ), + F_MAX5387_1( A_MAX5387_1 ), + F_MAX5387_2( A_MAX5387_2 ) + { + } + + }; +//--------------------------------------------------------------------------- + class Maxim_MotorDriverShieldComponent : public Maxim_MotorDriverBasicShield + { + typedef Maxim_MotorDriverBasicShield inherited; + + public: + OpenWire::SinkPin FaultInputPin; + + protected: + bool FFaultReceived = false; + + protected: + void DoFaultReceive( void * _Data ) + { + if( *(bool *)_Data ) + UpdateFailures(); + } + + public: + Maxim_MotorDriverShieldComponent( byte A_MAX7300, byte A_MAX5387_1, byte A_MAX5387_2 ) : + inherited( A_MAX7300, A_MAX5387_1, A_MAX5387_2 ) + { + FaultInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Maxim_MotorDriverShieldComponent::DoFaultReceive ); + } + }; +//--------------------------------------------------------------------------- + class Maxim_MotorDriverShield : public Maxim_MotorDriverBasicShield + { + typedef Maxim_MotorDriverBasicShield inherited; + + protected: + int FFailureChangePin; + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + inherited::SystemLoopBegin( currentMicros ); + if( digitalRead( FFailureChangePin ) == HIGH ) + UpdateFailures(); + } + + public: + Maxim_MotorDriverShield( byte A_MAX7300, byte A_MAX5387_1, byte A_MAX5387_2, int AFailureChangePin ) : + inherited( A_MAX7300, A_MAX5387_1, A_MAX5387_2 ), + FFailureChangePin( AFailureChangePin ) + { + } + }; +//--------------------------------------------------------------------------- + class Maxim_MotorDriverBasicChannel : public OpenWire::Object + { + public: + OpenWire::SinkPin SpeedInputPin; + OpenWire::SourcePin FaultOutputPin; + + public: + bool Enabled = true; + float MaxCurrent = 0.0f; + TArduinoMaximMotorCurrentRegulationMode CurrentRegulationMode = crmRipple25; + bool FFailure = false; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + FOwner.FChanged |= 0b00010000 << FIndex; + FOwner.FModified = true; + } + + void SetMaxCurrent( float AValue ) + { + AValue = constrain( AValue, 0, 2.6 ); + if( MaxCurrent == AValue ) + return; + + MaxCurrent = AValue; + FOwner.FChanged |= 0b1 << FIndex; + FOwner.FModified = true; + } + + void SetCurrentRegulationMode( TArduinoMaximMotorCurrentRegulationMode AValue ) + { + if( CurrentRegulationMode == AValue ) + return; + + CurrentRegulationMode = AValue; + FOwner.FChanged |= 0b00010000 << FIndex; + FOwner.FModified = true; + } + + protected: + Maxim_MotorDriverBasicShield &FOwner; + int FIndex; + + float FSpeed; + float FSenseResistor; + + protected: + void DoSpeedReceive( void * _Data ) + { + float AValue = constrain( *(float *)_Data, 0, 1.0 ); +// Serial.println( AValue ); + if( FSpeed == AValue ) + return; + + if(( AValue > 0.5 && FSpeed <= 0.5 ) || ( AValue <= 0.5 && FSpeed > 0.5 )) + FOwner.FChanged |= 0b00010000 << FIndex; + + FSpeed = AValue; + + FOwner.FModified = true; + +// FOwner.SetChannelValue( FIndex, AValue ); + } + + public: + byte GetRegisterPins() + { + byte Result; + if( Enabled ) + Result = 0; + + else + Result = 1; + + if( FSpeed > 0.5 ) + Result |= 0b10; + + switch( CurrentRegulationMode ) + { + case crmRipple25: + Result |= 0b1000; + + case crmFastDecay: + Result |= 0b1100; + + case crmSlowDecay: + Result |= 0b0100; + + } + + return Result; + } + + byte GetPotentiometer() + { +// byte ATest1 = Reference * 255 + 0.5; +// Serial.println( ATest1 ); + return ( MaxCurrent * FSenseResistor / 2.6 ) * 255 + 0.5; +// return Reference * 255 + 0.5; +// return abs( FSpeed - 0.5 ) * 2 * 255 + 0.5; + } + + virtual void UpdateSpeed() = 0; + + void UpdateFailure( bool AValue ) + { + if( FFailure == AValue ) + return; + + FFailure = AValue; + FaultOutputPin.Notify( &FFailure ); + } + + void InitFailure() + { + FaultOutputPin.Notify( &FFailure ); + } + + public: + Maxim_MotorDriverBasicChannel( Maxim_MotorDriverBasicShield &AOwner, int AIndex, float AInitialSpeed, float ASenseResistor ) : + FOwner( AOwner ), + FIndex( AIndex ), + FSpeed( AInitialSpeed ), + FSenseResistor( ASenseResistor * 10 ) + { +// Serial.println( "---" ); + FOwner.FChannels.push_back( this ); + +// Serial.println( "---" ); + SpeedInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Maxim_MotorDriverBasicChannel::DoSpeedReceive ); + } + + }; +//--------------------------------------------------------------------------- + class Maxim_MotorDriverChannel : public Maxim_MotorDriverBasicChannel + { + typedef Maxim_MotorDriverBasicChannel inherited; + + protected: + int FPWMPin; + + protected: + virtual void UpdateSpeed() + { + byte AValue = abs( FSpeed - 0.5 ) * 2 * 255 + 0.5; +// Serial.println( AValue ); +// Serial.println( FPWMPin ); + analogWrite( FPWMPin, AValue ); +// Serial.println( "---" ); + } + + public: + Maxim_MotorDriverChannel( Maxim_MotorDriverBasicShield &AOwner, int AIndex, int APWMPin, float AInitialSpeed, float ASenseResistor ) : + inherited( AOwner, AIndex, AInitialSpeed, ASenseResistor ), + FPWMPin( APWMPin ) + { + } + }; +//--------------------------------------------------------------------------- + class Maxim_MotorDriverComponentChannel : public Maxim_MotorDriverBasicChannel + { + typedef Maxim_MotorDriverBasicChannel inherited; + + public: + OpenWire::SourcePin MotorControlOutputPin; + + protected: + virtual void UpdateSpeed() + { + float AValue = abs( FSpeed - 0.5 ) * 2; +// Serial.println( FSpeed ); + MotorControlOutputPin.Notify( &AValue ); + } + + public: + using inherited::inherited; + }; +//--------------------------------------------------------------------------- + void Maxim_MotorDriverBasicShield::SystemStart() + { + inherited::SystemStart(); + DoGPIOTransmissionAt( 0x4, 0b10000001 ); // Enable and enable the interrupts + for( int i = 0x9; i < 0x9 + 4; ++i ) + DoGPIOTransmissionAt( i, 0b01010101 ); // All Output + + DoGPIOTransmissionAt( 0x0E, 0xFF ); // All inputs + DoGPIOTransmissionAt( 0x0E, 0b01111111 ); // P31 Poutput, the rest inputs + + UpdateSettings(); + + for( int i = 0; i < FChannels.size(); ++i ) + FChannels[ i ]->InitFailure(); + + } +//--------------------------------------------------------------------------- + void Maxim_MotorDriverBasicShield::UpdateFailures() + { + DoGPIOReadAt( 6 ); // Clear the interrupt bit + + byte AFailureFlags = DoGPIOReadAt( 0x5B ); // Read pins 27 and up + for( int i = 0; i < FChannels.size(); ++ i ) + FChannels[ i ]->UpdateFailure( AFailureFlags & ( 1 << i ) == 0 ); + + } +//--------------------------------------------------------------------------- + void Maxim_MotorDriverBasicShield::UpdateSettings() + { + if( FChanged & 0b00110000 ) + { + byte MAX7300Reg = FChannels[ 0 ]->GetRegisterPins() | ( FChannels[ 1 ]->GetRegisterPins() << 4 ); +// Serial.println( MAX7300Reg ); + DoGPIOTransmissionAt( 0x44, MAX7300Reg ); + } + + if( FChanged & 0b11000000 ) + { + byte MAX7300Reg = FChannels[ 2 ]->GetRegisterPins() | ( FChannels[ 3 ]->GetRegisterPins() << 4 ); + DoGPIOTransmissionAt( 0x4C, MAX7300Reg ); + } + + if( FChanged & 0b00000011 ) + { + if( FChanged & 0b00000001 ) + DoPotentiometerTransmission( F_MAX5387_1, 0b00010001, FChannels[ 0 ]->GetPotentiometer() ); + + if( FChanged & 0b00000010 ) + DoPotentiometerTransmission( F_MAX5387_1, 0b00010010, FChannels[ 1 ]->GetPotentiometer() ); + + } + + if( FChanged & 0b00001100 ) + { + if( FChanged & 0b00000100 ) + DoPotentiometerTransmission( F_MAX5387_2, 0b00010001, FChannels[ 2 ]->GetPotentiometer() ); + + if( FChanged & 0b00001000 ) + DoPotentiometerTransmission( F_MAX5387_2, 0b00010010, FChannels[ 3 ]->GetPotentiometer() ); + } + + for( int i = 0; i < FChannels.size(); ++i ) + FChannels[ i ]->UpdateSpeed(); + + FChanged = 0; + FModified = false; + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Maxim_OneWire_Thermometer.h b/libraries/Mitov/Mitov_Maxim_OneWire_Thermometer.h new file mode 100644 index 0000000..9c0fed4 --- /dev/null +++ b/libraries/Mitov/Mitov_Maxim_OneWire_Thermometer.h @@ -0,0 +1,234 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MAXIM_ONEWIRE_THERMOMETER_h +#define _MITOV_MAXIM_ONEWIRE_THERMOMETER_h + +#include + +namespace Mitov +{ + class OneWireThermometer : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: + OpenWire::SinkPin OneWireInputPin; + OpenWire::SourcePin OneWireOutputPin; + + OpenWire::SourcePin AddressOutputPin; + + OpenWire::SourcePin AlarmOutputPin; + + public: + bool AutoDiscover : 1; + bool InFahrenheit : 1; + uint8_t Resolution = 9; + + float AlarmHighTemperature = 100.0f; + float AlarmLowTemperature = 0.0f; + + public: + void SetResolution( uint8_t AValue ) + { + if( Resolution == AValue ) + return; + + Resolution = AValue; + if( FThermometer ) + FThermometer->setResolution( FAddress, Resolution ); + } + + protected: +// bool FIsChained; + int FDigitalPin; + int FIndex; +// float FCurrentValue; + + protected: + OneWire *FOneWire = nullptr; + // Migrate to direct OpenWire with DallasTemperature rewrite! + DallasTemperature *FThermometer = nullptr; + DeviceAddress FAddress; + + protected: + virtual void SystemInit() + { + if( FIndex ) + { +// OneWireOutputPin.Notify( &FOneWire ); + // Migrate to OpenWire with DallasTemperature rewrite! + OneWireOutputPin.Notify( &FThermometer ); + } + + else + { + GetOneWire(); + + FThermometer = new DallasTemperature( FOneWire ); + FThermometer->begin(); + } + + if( AutoDiscover ) + FThermometer->getAddress( FAddress, FIndex ); + + FThermometer->setResolution( FAddress, Resolution ); + + +/* + if( FIndex ) + { + Serial.println( FThermometer->getDeviceCount() ); + Serial.println( FIndex ); + for (uint8_t i = 0; i < 8; i++) + Serial.println( FAddress[ i ] ); + } +*/ + inherited::SystemInit(); + } + + virtual void SystemStart() + { + if( FIndex == 0 ) + { + FThermometer->setCheckForConversion( true ); + FThermometer->requestTemperatures(); + FThermometer->setCheckForConversion( false ); + } + + if( AddressOutputPin.IsConnected() ) + { +/* + String AAddress = String( FAddress[ 0 ], HEX ); + for( int i = 1; i < 8; ++i ) + AAddress += '-' + String( FAddress[ i ], HEX ); + + AddressOutputPin.Notify( (void *)AAddress.c_str() ); +*/ + char format[ 24 ]; + sprintf( format, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", FAddress[ 0 ], FAddress[ 1 ], FAddress[ 2 ], FAddress[ 3 ], FAddress[ 4 ], FAddress[ 5 ], FAddress[ 6 ], FAddress[ 7 ] ); + AddressOutputPin.Notify( format ); + } + + if( AlarmOutputPin.IsConnected() ) + { + FThermometer->setHighAlarmTemp( FAddress, (char)( AlarmHighTemperature + 0.5 )); + FThermometer->setLowAlarmTemp( FAddress, (char)( AlarmLowTemperature + 0.5 )); + +// float AValue = ( AlarmHighTemperature - (-55) ) / ( 125 - -55 ) * 255; +// FThermometer->setHighAlarmTemp( FAddress, (char)( AValue + 0.5 )); + +// AValue = ( AlarmLowTemperature - (-55) ) / ( 125 - -55 ) * 255; +// FThermometer->setLowAlarmTemp( FAddress, (char)( AValue + 0.5 )); + } + + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! ClockInputPin.IsConnected() ) + ReadTemperature(); + + // Needs to be changed to handle when the clock is different for the thermometers! + if( FIndex == 0 ) + FThermometer->requestTemperatures(); + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + void GetOneWire() + { + if( ! FOneWire ) + FOneWire = new OneWire( FDigitalPin ); + } + + void ReadTemperature() + { + if( AlarmOutputPin.IsConnected() ) + { + bool AValue = FThermometer->hasAlarm( FAddress ); + AlarmOutputPin.Notify( &AValue ); + } + + float AValue = (InFahrenheit) + ? FThermometer->getTempF( FAddress ) + : FThermometer->getTempC( FAddress ); + + OutputPin.Notify( &AValue ); + } + + protected: + void DoOneWireReceive( void *_Data ) + { + if( FIndex ) + OneWireOutputPin.Notify( _Data ); + + else + { + GetOneWire(); +// *(OneWire**)_Data = FOneWire; + // Migrate to OpenWire with DallasTemperature rewrite! + *(DallasTemperature**)_Data = FThermometer; + } + } + + virtual void DoClockReceive( void *_Data ) override + { + ReadTemperature(); + } + + public: + OneWireThermometer( int ADigitalPin, int AIndex ) : + FDigitalPin( ADigitalPin ), + FIndex( AIndex ), + AutoDiscover( true ), + InFahrenheit( false ) + { + memset( FAddress, 0, 8 ); + + OneWireInputPin.SetCallback( MAKE_CALLBACK( OneWireThermometer::DoOneWireReceive )); + } + + OneWireThermometer( int ADigitalPin, int AIndex, uint8_t AByte0, uint8_t AByte1, uint8_t AByte2, uint8_t AByte3, uint8_t AByte4, uint8_t AByte5, uint8_t AByte6, uint8_t AByte7 ) : + FDigitalPin( ADigitalPin ), + FIndex( AIndex ), + AutoDiscover( true ), + InFahrenheit( false ) + { + FAddress[ 0 ] = AByte0; + FAddress[ 1 ] = AByte1; + FAddress[ 2 ] = AByte2; + FAddress[ 3 ] = AByte3; + FAddress[ 4 ] = AByte4; + FAddress[ 5 ] = AByte5; + FAddress[ 6 ] = AByte6; + FAddress[ 7 ] = AByte7; + + OneWireInputPin.SetCallback( MAKE_CALLBACK( OneWireThermometer::DoOneWireReceive )); + } + +/* + virtual ~OneWireThermometer() + { + if( FIndex == 0 ) + { + if( FThermometer ) + delete FThermometer; + + if( FOneWire ) + delete FOneWire; + } + } +*/ + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Maxim_Potentiometer_I2C.h b/libraries/Mitov/Mitov_Maxim_Potentiometer_I2C.h new file mode 100644 index 0000000..40e0291 --- /dev/null +++ b/libraries/Mitov/Mitov_Maxim_Potentiometer_I2C.h @@ -0,0 +1,124 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MAXIM_POTENTIOMETER_I2C_h +#define _MITOV_MAXIM_POTENTIOMETER_I2C_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class PotentiometerSPIChannel; +//--------------------------------------------------------------------------- + class Maxim_Potentiometer_I2C : public Mitov::Basic_MultiChannel_SourceI2C + { + typedef Mitov::Basic_MultiChannel_SourceI2C inherited; + + public: + byte Address = 0; + + protected: + void TransmitAt( byte ARegister, byte Adata ) + { + byte AAddress = 0b0101000 | (( Address & 0b111 ) << 1 ); + Wire.beginTransmission( AAddress ); + + Wire.write( ARegister ); + Wire.write( Adata ); + + Wire.endTransmission(); + } + + protected: + virtual void UpdateOutput() + { + float ANewValue = FChannels[ 0 ]->FNewValue; + + TransmitAt( 0b00010001, (byte)ANewValue ); + + FChannels[ 0 ]->FValue = ANewValue; + } + + protected: + virtual void SystemStart() override + { + inherited::SystemStart(); + UpdateOutput(); + } + + virtual void SystemLoopUpdateHardware() override + { + if( FModified ) + if( ! ClockInputPin.IsConnected() ) + UpdateOutput(); + + inherited::SystemLoopUpdateHardware(); + } + + protected: + void DoClockReceive( void * ) + { + if( FModified ) + UpdateOutput(); + + } + + }; +//--------------------------------------------------------------------------- + class Maxim_Potentiometer_I2C2Channel : public Mitov::Maxim_Potentiometer_I2C + { + typedef Mitov::Maxim_Potentiometer_I2C2Channel inherited; + + protected: + virtual void UpdateOutput() + { + float ANewValue = FChannels[ 0 ]->FNewValue; + if( ANewValue == FChannels[ 1 ]->FNewValue ) + // Update both channels at once + TransmitAt( 0b00010011, (byte)ANewValue ); + + else + { + if( ANewValue != FChannels[ 0 ]->FValue ) + TransmitAt( 0b00010001, (byte)ANewValue ); + + if( FChannels[ 1 ]->FNewValue != FChannels[ 1 ]->FValue ) + TransmitAt( 0b00010010, (byte)FChannels[ 1 ]->FNewValue ); + } + + FChannels[ 0 ]->FValue = ANewValue; + FChannels[ 1 ]->FValue = FChannels[ 1 ]->FNewValue; + } + + }; +//--------------------------------------------------------------------------- + template class Maxim_Potentiometer_I2C_Channel : public Mitov::Basic_Typed_I2CChannel + { + typedef Mitov::Basic_Typed_I2CChannel inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + FNewValue = constrain( *((float *)_Data), 0, 1 ) * T_MULTIPLIER; + if( FNewValue == FValue ) + return; + + FOwner.FModified = true; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_MicroSDCard.h b/libraries/Mitov/Mitov_MicroSDCard.h new file mode 100644 index 0000000..8e091ef --- /dev/null +++ b/libraries/Mitov/Mitov_MicroSDCard.h @@ -0,0 +1,695 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MICRO_SD_CARD_h +#define _MITOV_MICRO_SD_CARD_h + +#include + +#include +#include + +namespace Mitov +{ + class MicroSDCard_Intf + { + public: + virtual bool DoExists( String APathName ) = 0; + virtual bool DoCreate( String APathName ) = 0; + virtual bool DoRemove( String APathName ) = 0; + virtual bool DoOpen( String APathName, uint8_t mode, File &AFile ) = 0; + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementBasic : public OpenWire::Object + { + typedef OpenWire::Object inherited; + + public: + String PathName; + + protected: + Mitov::MicroSDCard_Intf &FOwner; + + public: + MicroSDCardElementBasic( Mitov::MicroSDCard_Intf &AOwner ) : + FOwner( AOwner ) + { + } + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementOperation : public OpenWire::Object + { + public: + OpenWire::SinkPin ClockInputPin; + OpenWire::SourcePin OutputPin; + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementDirectory : public MicroSDCardElementBasic, public MicroSDCard_Intf + { + typedef Mitov::MicroSDCardElementBasic inherited; + + public: + MicroSDCardElementOperation CheckExists; + MicroSDCardElementOperation Create; + MicroSDCardElementOperation Remove; + + public: + virtual bool DoExists( String APathName ) override + { + return FOwner.DoExists( JoinPath( APathName )); + } + + virtual bool DoCreate( String APathName ) override + { + return FOwner.DoCreate( JoinPath( APathName )); + } + + virtual bool DoRemove( String APathName ) override + { + return FOwner.DoRemove( JoinPath( APathName )); + } + + virtual bool DoOpen( String APathName, uint8_t mode, File &AFile ) override + { + return FOwner.DoOpen( JoinPath( APathName ), mode, AFile ); + } + + protected: + String JoinPath( String AValue ) + { + String APath = PathName; + if( ! APath.endsWith( "/" ) ) + APath = APath + "/"; + + if( AValue.startsWith( "/" ) ) + AValue.remove( 0, 1 ); + + return APath + AValue; + } + + protected: + void DoCheckExistsClockReceive( void *_Data ) + { + CheckExists.OutputPin.SendValue( FOwner.DoExists( PathName )); + } + + void DoCreateClockReceive( void *_Data ) + { + Create.OutputPin.SendValue( FOwner.DoCreate( PathName )); + } + + void DoRemoveClockReceive( void *_Data ) + { + Remove.OutputPin.SendValue( FOwner.DoRemove( PathName )); + } + + public: + MicroSDCardElementDirectory( Mitov::MicroSDCard_Intf &AOwner ) : + inherited( AOwner ) + { + CheckExists.ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardElementDirectory::DoCheckExistsClockReceive ); + Create.ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardElementDirectory::DoCreateClockReceive ); + Remove.ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardElementDirectory::DoRemoveClockReceive ); + } + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementClocked : public MicroSDCardElementBasic + { + typedef Mitov::MicroSDCardElementBasic inherited; + + public: + OpenWire::SinkPin ClockInputPin; + + protected: + virtual void DoClockReceive( void *_Data ) = 0; + + public: + MicroSDCardElementClocked( Mitov::MicroSDCard_Intf &AOwner ) : + inherited( AOwner ) + { + ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardElementClocked::DoClockReceive ); + } + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementClockedResult : public MicroSDCardElementClocked + { + typedef Mitov::MicroSDCardElementClocked inherited; + + public: + OpenWire::SourcePin OutputPin; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementList : public MicroSDCardElementClockedResult + { + typedef Mitov::MicroSDCardElementClockedResult inherited; + + public: + OpenWire::SourcePin FailedOutputPin; + + public: + bool Recursive = false; + + protected: + void ProcessLevel( String APath, String APrefix ) + { + File AFile; + if( ! FOwner.DoOpen( APath, FILE_READ, AFile )) + { + FailedOutputPin.Notify( NULL ); + return; + } + + if( APath.endsWith( "/" )) + APath = APath.substring( 0, APath.length() - 1 ); + + while (true) + { + File AEntry = AFile.openNextFile(); + if (! AEntry) + // no more files + break; + + String AItemName = APrefix + AEntry.name(); + OutputPin.Notify( (char *)AItemName.c_str() ); + + if( Recursive ) + if( AEntry.isDirectory()) + ProcessLevel( APath + '/' + AEntry.name(), AItemName + '/' ); + + AEntry.close(); + } + + AFile.close(); + } + + protected: + virtual void DoClockReceive( void *_Data ) + { +// Serial.println( "" ); +// Serial.println( PathName ); +// Serial.println( "" ); + if( PathName = "" ) + ProcessLevel( "/", "" ); + + else + ProcessLevel( PathName, "" ); +/* + File AFile; + if( ! FOwner.DoOpen( PathName, FILE_READ, AFile )) + { + FailedOutputPin.Notify( NULL ); + return; + } + + while (true) + { + File AEntry = AFile.openNextFile(); + if (! AEntry) + // no more files + break; + + OutputPin.Notify( AEntry.name() ); + AEntry.close(); + } + + AFile.close(); +*/ + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementFile : public MicroSDCardElementBasic + { + typedef Mitov::MicroSDCardElementBasic inherited; + + public: + OpenWire::SourcePin ReadPositionOutputPin; + OpenWire::SourcePin WritePositionOutputPin; + + OpenWire::SinkPin CloseInputPin; + OpenWire::SinkPin FlushInputPin; + + public: + bool Enabled : 1; + bool NewLine : 1; + bool KeepFlushed : 1; + bool KeepClosed : 1; + + public: + bool FHasWrite : 1; + + protected: + bool FWriteMoved : 1; + bool FReadMoved : 1; + + uint32_t FWritePosition = 0; + uint32_t FReadPosition = 0; + + public: + File FFile; + + public: + template void Print( T AValue ) + { + if( ! TryOpen() ) + return; + + PrepareWrite(); + +// Serial.println( "TEST2" ); + if( NewLine ) + FFile.println( AValue ); + + else + FFile.print( AValue ); + + UpdateWrite(); + } + + void Write( void *_Data, size_t ASize ) + { + if( ! TryOpen() ) + return; + + PrepareWrite(); + FFile.write( (uint8_t *)_Data, ASize ); + UpdateWrite(); + } + + void BeginRead() + { + if( ! FWriteMoved ) + { + FWritePosition = FFile.position(); + FWriteMoved = true; + } + + if( FReadMoved ) + { + FFile.seek( FReadPosition ); + FReadMoved = false; + } + } + + inline void ResetReadPosition() + { + FFile.seek( FReadPosition ); + } + + protected: + void PrepareWrite() + { + if( ! FReadMoved ) + { + FReadPosition = FFile.position(); + FReadMoved = true; + } + + if( FWriteMoved ) + { + FFile.seek( FWritePosition ); + FWriteMoved = false; + } + } + + void UpdateWrite() + { + if( KeepFlushed ) + FFile.flush(); + + if( KeepClosed ) + FFile.close(); + + UpdateWritePosition(); + } + + public: + bool TryOpen() + { + if( FFile ) + return true; + +// Serial.println( "OPEN1" ); + if( ! Enabled ) + return false; + + if( PathName == "" ) + return false; + +// Serial.println( PathName ); +// Serial.println( FHasWrite ); + if( FHasWrite ) + return FOwner.DoOpen( PathName, FILE_WRITE, FFile ); + + else + return FOwner.DoOpen( PathName, FILE_READ, FFile ); + } + + protected: + void UpdateWritePosition() + { + if( WritePositionOutputPin.IsConnected() ) + WritePositionOutputPin.SendValue( FFile.position() ); + } + + protected: + void DoCloseReceive( void *_Data ) + { + FFile.close(); + } + + void DoFlushReceive( void *_Data ) + { + FFile.flush(); + } + + public: + MicroSDCardElementFile( Mitov::MicroSDCard_Intf &AOwner, bool AHasWrite ) : + inherited( AOwner ), + Enabled( true ), + NewLine( true ), + KeepFlushed( true ), + KeepClosed( true ), + FHasWrite( AHasWrite ), + FReadMoved( false ), + FWriteMoved( false ) + { + CloseInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardElementFile::DoCloseReceive ); + FlushInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardElementFile::DoFlushReceive ); + } + + }; +//--------------------------------------------------------------------------- + class MicroSDCardFileElementBasic : public OpenWire::Object + { + typedef OpenWire::Object inherited; + + protected: + MicroSDCardElementFile &FOwner; + + public: + MicroSDCardFileElementBasic( Mitov::MicroSDCardElementFile &AOwner ) : + FOwner( AOwner ) + { + } + + }; +//--------------------------------------------------------------------------- + class MicroSDCardFileElementBasicClocked : public MicroSDCardFileElementBasic + { + typedef MicroSDCardFileElementBasic inherited; + + public: + OpenWire::SinkPin ClockInputPin; + OpenWire::SourcePin OutputPin; + + protected: + virtual void DoClockReceive( void *_Data ) = 0; + + public: + MicroSDCardFileElementBasicClocked( Mitov::MicroSDCardElementFile &AOwner ) : + inherited( AOwner ) + { + ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardFileElementBasicClocked::DoClockReceive ); + } + + }; +//--------------------------------------------------------------------------- + class MicroSDCardFileElementReadTextLine : public MicroSDCardFileElementBasicClocked + { + typedef MicroSDCardFileElementBasicClocked inherited; + + protected: + bool readStringLine( String &AResult ) + { +// AResult = ""; + int c = FOwner.FFile.read(); +// Serial.println( c ); + if( c < 0 ) + return false; + +// Serial.println( "R1" ); + while (c >= 0 && c != '\n' && c != '\r' ) + { + AResult += (char)c; + c = FOwner.FFile.read(); + } + + while ( c >= 0 ) + { + c = FOwner.FFile.peek(); + if( c != '\n' && c != '\r' ) + break; + + FOwner.FFile.read(); + } +/* + while ( c >= 0 && ( c == '\n' || c == '\r' )) + c = FOwner.FFile.read(); +*/ + return true; + } + + protected: + virtual void DoClockReceive( void *_Data ) override + { + if( ! FOwner.TryOpen() ) + return; + + String ALine; + FOwner.BeginRead(); +// Serial.println( "READ1" ); + if( readStringLine( ALine )) + OutputPin.Notify( (void *)ALine.c_str() ); + + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + template class MicroSDCardFileElementReadTyped : public MicroSDCardFileElementBasicClocked + { + typedef MicroSDCardFileElementBasicClocked inherited; + + protected: + virtual void DoClockReceive( void *_Data ) + { + if( ! FOwner.TryOpen() ) + return; + + FOwner.BeginRead(); + + T AData; + size_t AReadSize = FOwner.FFile.readBytes( (uint8_t *)&AData, sizeof( AData )); + if( AReadSize == sizeof( AData ) ) + OutputPin.Notify( &AData ); + +// else +// FOwner.ResetReadPosition(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + template class MicroSDCardFileElementWriteTyped : public MicroSDCardFileElementBasic + { + typedef MicroSDCardFileElementBasic inherited; + + public: + OpenWire::SinkPin InputPin; + + protected: + void DoDataReceive( void *_Data ) + { + FOwner.Write( _Data, sizeof( T )); + } + + public: + MicroSDCardFileElementWriteTyped( Mitov::MicroSDCardElementFile &AOwner ) : + inherited( AOwner ) + { + AOwner.FHasWrite = true; + + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MicroSDCardFileElementWriteTyped::DoDataReceive ); + } + + }; +//--------------------------------------------------------------------------- + class MicroSDCardElementExists : public MicroSDCardElementClockedResult + { + typedef Mitov::MicroSDCardElementClockedResult inherited; + + protected: + virtual void DoClockReceive( void *_Data ) override + { + OutputPin.SendValue( FOwner.DoExists( PathName )); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +// MicroSDCardElementDirectory + template class MicroSDCard : public Mitov::EnabledComponent, public MicroSDCard_Intf + { + typedef Mitov::EnabledComponent inherited; + + public: + OpenWire::SourcePin FailedOutputPin; + OpenWire::SourcePin SuccessOutputPin; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateEnabled(); + } + + public: + virtual bool DoExists( String APathName ) + { + if( !FCard ) + return false; + +// Serial.println( "COOL1" ); +// Serial.println( APathName ); + char *ATmp = new char[ APathName.length() + 1 ]; + memcpy( ATmp, APathName.c_str(), APathName.length() + 1 ); + + bool AResult = FCard->exists( ATmp ); + + delete [] ATmp; + + return AResult; + } + + virtual bool DoCreate( String APathName ) + { + if( !FCard ) + return false; + + char *ATmp = new char[ APathName.length() + 1 ]; + memcpy( ATmp, APathName.c_str(), APathName.length() + 1 ); + + bool AResult = FCard->mkdir( ATmp ); + + delete [] ATmp; + + return AResult; + } + + virtual bool DoRemove( String APathName ) + { + if( !FCard ) + return false; + + char *ATmp = new char[ APathName.length() + 1 ]; + memcpy( ATmp, APathName.c_str(), APathName.length() + 1 ); + + bool AResult = FCard->rmdir( ATmp ); + + delete [] ATmp; + + return AResult; + } + + virtual bool DoOpen( String APathName, uint8_t mode, File &AFile ) + { +// Serial.print( "O1 :" ); + if( !FCard ) + return false; + + if( ! APathName.startsWith( "/" )) + APathName = String( "/" ) + APathName; + + char *ATmp = new char[ APathName.length() + 1 ]; + memcpy( ATmp, APathName.c_str(), APathName.length() + 1 ); + +// Serial.print( "T1 :" ); +// Serial.println( ATmp ); + AFile = FCard->open( ATmp, mode ); + delete [] ATmp; + + return AFile; + } + + protected: + SDClass *FCard = nullptr; + + protected: + void UpdateEnabled() + { + if( Enabled ) + { +// Serial.println( "TEST1" ); + FCard = new SDClass; + if( FCard->begin( PIN_NUMBER ) ) + SuccessOutputPin.Notify( NULL ); + + else + { +// Serial.println( "FAIL" ); + FailedOutputPin.Notify( NULL ); + Enabled = false; + UpdateEnabled(); + } +// Serial.println( "COOL" ); + } + else + { + delete FCard; + FCard = nullptr; + } + } + + protected: + virtual void SystemInit() + { + UpdateEnabled(); + inherited::SystemInit(); + } +/* + virtual void SystemStart() + { +// FServo.attach( PIN_NUMBER ); + inherited::SystemStart(); + } +*/ + +/* + virtual ~MicroSDCard() + { + if( FCard ) + delete FCard; + } +*/ + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Microchip_DAC_SPI.h b/libraries/Mitov/Mitov_Microchip_DAC_SPI.h new file mode 100644 index 0000000..36a0084 --- /dev/null +++ b/libraries/Mitov/Mitov_Microchip_DAC_SPI.h @@ -0,0 +1,134 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MICROCHIP_DAC_SPI_h +#define _MITOV_MICROCHIP_DAC_SPI_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class Microchip_DAC_SPI : public Mitov::Basic_MultiChannel_SourceSPI + { + typedef Mitov::Basic_MultiChannel_SourceSPI inherited; + + public: + OpenWire::SourcePin LatchOutputPin; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + for( int i =0; i < FChannels.size(); ++i ) + FChannels[ i ]->InitChannel(); + } + + protected: + void UpdateLatch() + { + LatchOutputPin.SendValue( false ); + LatchOutputPin.SendValue( true ); + } + + protected: + virtual void SystemLoopEnd() + { + inherited::SystemLoopEnd(); + + if( ! ClockInputPin.IsConnected() ) + UpdateLatch(); + } + + virtual void DoClockReceive( void *_Data ) + { + inherited::DoClockReceive( _Data ); + + UpdateLatch(); + } + + public: + void SPI_write( word APacket ) + { + ChipSelectOutputPin.SendValue( false ); + FSPI.transfer( APacket >> 8 ); + FSPI.transfer( APacket & 0xFF ); + ChipSelectOutputPin.SendValue( true ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class Microchip_DACSPIChannel : public Mitov::Basic_Typed_SPIChannel + { + typedef Mitov::Basic_Typed_SPIChannel inherited; + + public: + bool Enabled : 1; + bool Gain : 1; + + public: + void SendOutput() + { + if( FNewValue == FValue ) + return; + + word volt_digits = FNewValue * 4095 + 0.5; + + word packet = volt_digits & 0b111111111111; //shift voltage setting digits + if( Enabled ) + packet |= 1 << 12; + + if( Gain ) + packet |= 1 << 13; //add gain setting + + if( FIndex ) + packet |= 1 << 15; //add gain setting + + FOwner.SPI_write( packet ); + } + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + InitChannel(); + } + + void SetGain( bool AValue ) + { + if( Gain == AValue ) + return; + + Gain = AValue; + InitChannel(); + } + + public: + Microchip_DACSPIChannel( Microchip_DAC_SPI &AOwner, int AIndex, int ABits ) : + inherited( AOwner, AIndex ), + Enabled( true ), + Gain( false ) + { + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Microchip_MCP23017.h b/libraries/Mitov/Mitov_Microchip_MCP23017.h new file mode 100644 index 0000000..84d4e66 --- /dev/null +++ b/libraries/Mitov/Mitov_Microchip_MCP23017.h @@ -0,0 +1,233 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MICROCHIP_MCP23017_h +#define _MITOV_MICROCHIP_MCP23017_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class Microchip_MCP23017 : public Mitov::BasicGPIO + { + typedef Mitov::BasicGPIO inherited; + + public: + byte Address = 0; + + public: + enum TRegisterIndex { riDirection, riPullUp, riInvert, riValue }; + + protected: + uint16_t FRegValues[ 4 ][ 2 ]; + uint16_t FReadRegisterMap = 0; + uint16_t FReadBits = 0; + + + protected: + void BeginTransmissionAt( byte ARegister ) + { + byte AAddress = 0b0100000 | ( Address & 0b111 ); + + Wire.beginTransmission( AAddress ); + + Wire.write( ARegister ); + } + + void WriteAt( byte ARegister, uint16_t AData ) + { +// Serial.print( "WriteAt: " ); Serial.print( ARegister ); Serial.print( " " ); Serial.println( AData ); + BeginTransmissionAt( ARegister ); + + Wire.write( (byte *)&AData, 2 ); + + Wire.endTransmission(); + } + + void StartReadFrom( byte ARegister, int ALength ) + { + BeginTransmissionAt( ARegister ); + Wire.endTransmission(); + Wire.requestFrom( 0b0100000 | ( Address & 0b111 ), ALength ); + while( Wire.available() < ALength ); + } + + void UpdateAll() + { + const byte CPorts[] = + { + 0x00, // IODIR register + 0x02, // IPOL register + 0x0C, // GPPU register + 0x14 // OLAT register + }; + + for( int i = 0; i < 4; ++i ) + if( FRegValues[ i ][ 0 ] != FRegValues[ i ][ 1 ] ) + { + WriteAt( CPorts[ i ], FRegValues[ i ][ 0 ] ); + FRegValues[ i ][ 1 ] = FRegValues[ i ][ 0 ]; + } + +/* + // Read the port + BeginTransmissionAt( 0x12 ); // GPIO register + Wire.endTransmission(); + + Wire.requestFrom( 0b0100000 | ( Address & 0b111 ), 2 ); + uint16_t AValue; + ((byte *)&AValue )[ 0 ] = Wire.read(); + ((byte *)&AValue )[ 1 ] = Wire.read(); + + for( int i = 0; i < FChannels.size(); ++i ) + FChannels[ i ]->UpdateOutput( AValue & ( 1 << i ) != 0 ); +*/ + } + + virtual void PerformRead() + { + if( ! FReadRegisterMap ) + return; + +// Serial.println( FReadRegisterMap ); + + if( FReadRegisterMap & 0x0F ) + { + if( FReadRegisterMap & 0xF0 ) + { + StartReadFrom( 0x12, 2 ); // GPIO register + ((byte *)&FReadBits )[ 0 ] = Wire.read(); + ((byte *)&FReadBits )[ 1 ] = Wire.read(); + } + + else + { + StartReadFrom( 0x12, 1 ); // GPIO register + ((byte *)&FReadBits )[ 0 ] = Wire.read(); + ((byte *)&FReadBits )[ 1 ] = 0; + +// Serial.print( "FReadBits: " ); Serial.println( FReadBits ); + } + } + else + { + // Read the port + StartReadFrom( 0x13, 1 ); // GPIO register + ((byte *)&FReadBits )[ 0 ] = 0; + ((byte *)&FReadBits )[ 1 ] = Wire.read(); + } + + for( int i = 0; i < FChannels.size(); ++i ) + FChannels[ i ]->UpdateInput(); + + } + + public: + bool GetBitValue( uint32_t AIndex ) + { + return( ( FReadBits & ( ((uint32_t)1 ) << AIndex )) != 0 ); + } + + public: + void SetChannelValue( int AIndex, bool AValue ) + { + SetChannelRegisterValue( AIndex, Microchip_MCP23017::riValue, AValue ); + } + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + + for( int i = 0; i < 4; ++i ) + FRegValues[ i ][ 1 ] = ~FRegValues[ i ][ 0 ]; + + UpdateAll(); + + for( int i = 0; i < FChannels.size(); ++i ) + FChannels[ i ]->SendOutput(); + } + + virtual void SystemLoopUpdateHardware() + { + UpdateAll(); + inherited::SystemLoopUpdateHardware(); + } + + public: + void SetChannelRegisterValue( int AIndex, int ARegisterIndex, bool AValue ) + { + FRegValues[ ARegisterIndex ][ 0 ] &= ~( ((uint16_t) 0b1 ) << AIndex ); + FRegValues[ ARegisterIndex ][ 0 ] |= ( (uint16_t)( AValue & 1 ) ) << AIndex; + + if( ARegisterIndex == Microchip_MCP23017::riDirection ) + { + if( AValue ) + FReadRegisterMap |= ((uint16_t) 1) << AIndex; + + else + FReadRegisterMap &= ~( ((uint16_t) 1) << AIndex ); + } + } + + public: + Microchip_MCP23017() + { + for( int i = 0; i < 4; ++i ) + FRegValues[ i ][ 0 ] = 0; + } + + }; +//--------------------------------------------------------------------------- + class Microchip_MCP23017_Channel : public OwnedBasicGPIOChannel + { + typedef OwnedBasicGPIOChannel inherited; + + public: + void SetIsInverted( bool AValue ) + { + if( FIsInverted == AValue ) + return; + + FIsInverted = AValue; + PinDirectionsInit(); + } + + protected: + bool FIsInverted; + + public: + virtual void UpdateInput() + { + UpdateOutput( FOwner.GetBitValue( FIndex )); + } + + protected: + virtual void PinDirectionsInit() + { + FOwner.SetChannelRegisterValue( FIndex, Microchip_MCP23017::riDirection, ! FIsOutput ); + FOwner.SetChannelRegisterValue( FIndex, Microchip_MCP23017::riPullUp, FIsPullUp ); + FOwner.SetChannelRegisterValue( FIndex, Microchip_MCP23017::riInvert, FIsInverted ); + } + + public: + Microchip_MCP23017_Channel( Microchip_MCP23017 &AOwner, int AIndex, bool AInitialValue, bool AIsOutput, bool AIsPullUp, bool AIsCombinedInOut, bool AIsInverted ) : + inherited( AOwner, AIndex, AInitialValue, AIsOutput, AIsPullUp, AIsCombinedInOut ), + FIsInverted( AIsInverted ) + { + PinDirectionsInit(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_MultiMerger.h b/libraries/Mitov/Mitov_MultiMerger.h new file mode 100644 index 0000000..ebb1960 --- /dev/null +++ b/libraries/Mitov/Mitov_MultiMerger.h @@ -0,0 +1,43 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_MULTI_MERGER_h +#define _MITOV_MULTI_MERGER_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + template class MultiMerger : public Mitov::CommonSource + { + typedef Mitov::CommonSource inherited; + + public: + OpenWire::SinkPin InputPins[ C_NUM_INPUTS ]; + + protected: + void DoReceive( void *_Data ) + { + OutputPin.Notify( _Data ); + } + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + + for( int i = 0; i < C_NUM_INPUTS; ++i ) + InputPins[ i ].SetCallback( this, (OpenWire::TOnPinReceive)&MultiMerger::DoReceive ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_NeoPixel.h b/libraries/Mitov/Mitov_NeoPixel.h new file mode 100644 index 0000000..ece97cc --- /dev/null +++ b/libraries/Mitov/Mitov_NeoPixel.h @@ -0,0 +1,509 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_NEO_PIXEL_h +#define _MITOV_NEO_PIXEL_h + +#include + +#include + +namespace Mitov +{ + class NeoPixelsRunningColorGroup; +//--------------------------------------------------------------------------- + class NeoPixelsController + { + public: + virtual void SetPixelColor( int AIndex, TColor AColor ) = 0; + virtual TColor GetPixelColor( int AIndex ) = 0; + + }; +//--------------------------------------------------------------------------- + class NeoPixelsCommonGroup : public OpenWire::Component + { + public: + NeoPixelsController *FOwner; + int FStartPixel; + + public: + virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel ) + { + FOwner = AOwner; + FStartPixel = AStartPixel; + } + + virtual void PixelsClock( unsigned long currentMicros ) + { + } + + }; +//--------------------------------------------------------------------------- + class NeoPixelsBasicGroup : public NeoPixelsCommonGroup + { + typedef NeoPixelsCommonGroup inherited; + + public: + int CountPixels = 10; + + public: + virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel ) + { + inherited::StartPixels( AOwner, AStartPixel ); + AStartPixel += CountPixels; + } + + }; +//--------------------------------------------------------------------------- + class NeoPixels : public OpenWire::Component, public NeoPixelsController, public Mitov::ClockingSupport + { + typedef OpenWire::Component inherited; + + public: + float Brightness = 1.0f; + Mitov::SimpleObjectList PixelGroups; + + public: + bool FModified; + + protected: + int FPinNumber; + + public: + void SetBrightness( float AValue ) + { + if( Brightness == AValue ) + return; + + IntSetBrightness( AValue ); + } + + public: + void SetPixelColor( int AIndex, TColor AColor ) + { + FPixel.setPixelColor( AIndex, AColor.Red, AColor.Green, AColor.Blue ); + FModified = true; + } + + TColor GetPixelColor( int AIndex ) + { + return TColor( FPixel.getPixelColor( AIndex ), true ); + } + + protected: + MitovEmbedded_Adafruit_NeoPixel &FPixel; + + protected: + void IntSetBrightness( float AValue ) + { + Brightness = AValue; + FPixel.setBrightness( AValue * 255 ); + FModified = true; + } + + virtual void SystemInit() + { + FPixel.setPin( FPinNumber ); + + FPixel.begin(); + IntSetBrightness( Brightness ); + + int AStartPixel = 0; + for( int i = 0; i < PixelGroups.size(); ++i ) + PixelGroups[ i ]->StartPixels( this, AStartPixel ); + + + inherited::SystemInit(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + for( int i = 0; i < PixelGroups.size(); ++i ) + PixelGroups[ i ]->PixelsClock( currentMicros ); + + inherited::SystemLoopBegin( currentMicros ); + } + + virtual void SystemLoopEnd() + { + if( FModified ) + if( ! ClockInputPin.IsConnected()) + { + FPixel.show(); + FModified = false; + } + + inherited::SystemLoopEnd(); + } + + virtual void DoClockReceive(void *) override + { + if( FModified ) + { + FPixel.show(); + FModified = false; + } + } + + public: + NeoPixels( int APinNumber, MitovEmbedded_Adafruit_NeoPixel &APixel ) : + FPinNumber( APinNumber ), + FPixel( APixel ) + { + } + + }; +//--------------------------------------------------------------------------- + class NeoPixelsBasicInitialColorGroup : public NeoPixelsBasicGroup + { + typedef NeoPixelsBasicGroup inherited; + + public: + TColor InitialColor; + + virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel ) + { + inherited::StartPixels( AOwner, AStartPixel ); + + for( int i = 0; i < CountPixels; ++i ) + FOwner->SetPixelColor( FStartPixel + i, InitialColor ); + } + + }; +//--------------------------------------------------------------------------- + class NeoPixelsBasicColorGroup : public NeoPixelsBasicInitialColorGroup + { + typedef NeoPixelsBasicInitialColorGroup inherited; + + protected: + TColor FColor; + + public: + OpenWire::SinkPin ColorInputPin; + + public: + void SetInitialColor( TColor AValue ) + { + if( InitialColor == AValue ) + return; + + InitialColor = AValue; + FColor = AValue; + ApplyColorsAll(); +// FOwner->FModified = true; + } + + protected: + virtual void ApplyColorsAll() + { + for( int i = 0; i < CountPixels; ++i ) + FOwner->SetPixelColor( FStartPixel + i, FColor ); + } + + virtual void ApplyColors() {} + + void IntSetColor( TColor AValue ) + { + if( FColor == AValue ) + return; + + FColor = AValue; + ApplyColors(); +// FOwner->FModified = true; + } + + void DoReceiveColor( void *_Data ) + { + IntSetColor( *(TColor *)_Data ); + } + + protected: + virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel ) + { + inherited::StartPixels( AOwner, AStartPixel ); +// Serial.println( CountPixels ); + IntSetColor( InitialColor ); +// FOwner->FModified = true; +// Serial.println( FStartPixel ); + } + + public: + NeoPixelsBasicColorGroup() + { + ColorInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsBasicColorGroup::DoReceiveColor ); + } + + }; +//--------------------------------------------------------------------------- + class NeoPixelsGroup : public NeoPixelsBasicInitialColorGroup + { + typedef NeoPixelsBasicInitialColorGroup inherited; + + protected: + class PixelVlaueSinkPin : public OpenWire::VlaueSinkPin + { + typedef OpenWire::VlaueSinkPin inherited; + + public: + NeoPixelsGroup *FOwner; + int FIndex; + + public: + virtual void Receive( void *_Data ) + { + TColor AValue = *(TColor *)_Data; + if( AValue != Value ) + FOwner->FOwner->SetPixelColor( FIndex, AValue ); + + inherited::Receive( _Data ); + } + }; + + public: + Mitov::SimpleList InputPins; + + protected: + virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel ) + { + inherited::StartPixels( AOwner, AStartPixel ); + for( int i = 0; i < InputPins.size(); ++i ) + { + InputPins[ i ].FOwner = this; + InputPins[ i ].FIndex = FStartPixel + i; + InputPins[ i ].Value = InitialColor; +// FOwner->SetPixelColor( FStartPixel + i, InitialColor ); +// Iter->SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsGroup::DoReceive ); +// Iter->Value = T_VALUE; + } + + } + + }; +//--------------------------------------------------------------------------- + class NeoPixelsRepeatGroup : public NeoPixelsBasicInitialColorGroup, public NeoPixelsController + { + typedef NeoPixelsBasicInitialColorGroup inherited; + + public: + Mitov::SimpleObjectList PixelGroups; + + protected: + int FSubPixelCount; + int FRepeatCount; + + public: + virtual void SetPixelColor( int AIndex, TColor AColor ) + { + for( int i = 0; i < FRepeatCount; ++i ) + FOwner->SetPixelColor( FStartPixel + AIndex + i * FSubPixelCount, AColor ); + } + + virtual TColor GetPixelColor( int AIndex ) + { + return FOwner->GetPixelColor( FStartPixel + AIndex ); + } + + public: + virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel ) + { + inherited::StartPixels( AOwner, AStartPixel ); + + FSubPixelCount = 0; + for( int i = 0; i < PixelGroups.size(); ++i ) + PixelGroups[ i ]->StartPixels( this, FSubPixelCount ); + + if( FSubPixelCount == 0 ) + FRepeatCount = 0; + + else + FRepeatCount = ( CountPixels + FSubPixelCount - 1 ) / FSubPixelCount; + + } + + virtual void PixelsClock( unsigned long currentMicros ) + { + inherited::PixelsClock( currentMicros ); + + for( int i = 0; i < PixelGroups.size(); ++i ) + PixelGroups[ i ]->PixelsClock( currentMicros ); + } + }; +//--------------------------------------------------------------------------- + class NeoPixelsSingleColorGroup : public NeoPixelsBasicColorGroup + { + typedef NeoPixelsBasicColorGroup inherited; + + protected: + virtual void ApplyColors() override + { + ApplyColorsAll(); + } + + }; +//--------------------------------------------------------------------------- + class NeoPixelsReversedProperty + { + protected: + NeoPixelsRunningColorGroup &FOwner; + + public: + bool Reversed : 1; + bool AllPixels : 1; + + public: + void SetReversed( bool AValue ); + + public: + NeoPixelsReversedProperty( NeoPixelsRunningColorGroup &AOwner ) : + FOwner( AOwner ), + Reversed( false ), + AllPixels( false ) + { + } + }; +//--------------------------------------------------------------------------- + class NeoPixelsRunningColorGroup : public NeoPixelsBasicColorGroup + { + typedef NeoPixelsBasicColorGroup inherited; + + public: + OpenWire::ConnectSinkPin StepInputPin; + OpenWire::SourcePin ColorOutputPin; + + public: + NeoPixelsReversedProperty Reversed; + + public: + void ReversePixels() + { + for( int i = 0; i < CountPixels / 2; ++i ) + { + TColor AOldColor1 = FOwner->GetPixelColor( FStartPixel + ( CountPixels - i - 1 )); + TColor AOldColor2 = FOwner->GetPixelColor( FStartPixel + i ); + + FOwner->SetPixelColor( FStartPixel + i, AOldColor1 ); + FOwner->SetPixelColor( FStartPixel + ( CountPixels - i - 1 ), AOldColor2 ); + } + } + + protected: + void AnimatePixels() + { + if( Reversed.Reversed ) + { + TColor AOldColor = FOwner->GetPixelColor( FStartPixel ); + ColorOutputPin.Notify( &AOldColor ); + for( int i = 0; i < CountPixels - 1; ++i ) + { + AOldColor = FOwner->GetPixelColor( FStartPixel + i + 1 ); + FOwner->SetPixelColor( FStartPixel + i, AOldColor ); + } + + FOwner->SetPixelColor( FStartPixel + CountPixels - 1, FColor ); + } + + else + { + TColor AOldColor = FOwner->GetPixelColor( FStartPixel + CountPixels - 1 ); + ColorOutputPin.Notify( &AOldColor ); + for( int i = CountPixels - 1; i--; ) + { + AOldColor = FOwner->GetPixelColor( FStartPixel + i ); + FOwner->SetPixelColor( FStartPixel + i + 1, AOldColor ); + } + + FOwner->SetPixelColor( FStartPixel, FColor ); + } +// FOwner->FModified = true; + } + + void DoReceiveStep( void *_Data ) + { + AnimatePixels(); + } + + protected: + virtual void PixelsClock( unsigned long currentMicros ) override + { + if( StepInputPin.IsConnected()) + return; + + AnimatePixels(); + } + + public: + NeoPixelsRunningColorGroup() : + Reversed( *this ) + { + StepInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsRunningColorGroup::DoReceiveStep ); + } + }; +//--------------------------------------------------------------------------- + inline void NeoPixelsReversedProperty::SetReversed( bool AValue ) + { + if( Reversed == AValue ) + return; + + Reversed = AValue; + if( AllPixels ) + FOwner.ReversePixels(); + + } +//--------------------------------------------------------------------------- + class NeoPixelsColorPixelGroup : public NeoPixelsBasicColorGroup + { + public: + OpenWire::SinkPin IndexInputPin; + + public: + uint32_t InitialIndex = 0; + + protected: + unsigned long FIndex; + bool FModified; + + protected: + void DoReceiveIndex( void *_Data ) + { + unsigned long AIndex = *(unsigned long *)_Data; + if( AIndex > CountPixels ) + AIndex = CountPixels; + + if( FIndex == AIndex ) + return; + + FIndex = AIndex; + FModified = true; + } + + virtual void PixelsClock( unsigned long currentMicros ) + { + if( FModified ) + { + FOwner->SetPixelColor( FStartPixel + FIndex, FColor ); +// FOwner->FModified = true; + FModified = false; + } + } + + virtual void ApplyColors() + { + FModified = true; + } + + public: + NeoPixelsColorPixelGroup() + { + IndexInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsColorPixelGroup::DoReceiveIndex ); + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_PIDController.h b/libraries/Mitov/Mitov_PIDController.h new file mode 100644 index 0000000..4ff68df --- /dev/null +++ b/libraries/Mitov/Mitov_PIDController.h @@ -0,0 +1,129 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PID_CONTROLLER_h +#define _MITOV_PID_CONTROLLER_h + +#include + +namespace Mitov +{ + class PIDController : public Mitov::CommonEnableFilter, public Mitov::ClockingSupport + { + typedef Mitov::CommonEnableFilter inherited; + + public: + OpenWire::SinkPin ManualControlInputPin; + + public: + float ProportionalGain = 0.1f; + float IntegralGain = 0.1f; + float DerivativeGain = 0.1f; + + float SetPoint = 0.0f; + + float InitialValue = 0.0f; + + protected: + unsigned long FLastTime; + float FOutput = 0.0f; + float FInput; + float FLastInput; + float FITerm; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + if( Enabled ) + Initialize(); + + } + + protected: + virtual void DoReceive( void *_Data ) + { + FInput = *(float *)_Data; + } + + void DoManualControlReceive( void *_Data ) + { + if( Enabled ) + return; + + FOutput = *(float *)_Data; + } + + virtual void DoClockReceive( void *_Data ) override + { + OutputPin.Notify( &FOutput ); + } + + protected: + void Initialize() + { + FITerm = FOutput; + FLastInput = FInput; + FLastTime = micros(); + } + + protected: + virtual void SystemStart() + { + FInput = InitialValue; + Initialize(); + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + inherited::SystemLoopBegin( currentMicros ); + if( ! Enabled ) + return; + + unsigned long timeChange = ( currentMicros - FLastTime ); + float ANormalizedTime = timeChange / 1000000; + + // Compute all the working error variables + double error = SetPoint - FInput; +// ITerm += ( ki * error ) * ANormalizedTime; + FITerm = constrain( FITerm + ( IntegralGain * error ) * ANormalizedTime, 0, 1 ); + + double dInput = ( FInput - FLastInput ) * ANormalizedTime; + + // Compute PID Output + float AOutput = constrain( ProportionalGain * error + FITerm - DerivativeGain * dInput, 0, 1 ); + + // Remember some variables for next time + FLastInput = FInput; + FLastTime = currentMicros; + + if( AOutput == FOutput ) + return; + + if( ClockInputPin.IsConnected() ) + return; + + OutputPin.Notify( &FOutput ); + } + + public: + PIDController() + { + ManualControlInputPin.SetCallback( MAKE_CALLBACK( PIDController::DoManualControlReceive )); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_PS2_Controller.h b/libraries/Mitov/Mitov_PS2_Controller.h new file mode 100644 index 0000000..0b5c040 --- /dev/null +++ b/libraries/Mitov/Mitov_PS2_Controller.h @@ -0,0 +1,99 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PS2_CONTROLLER_h +#define _MITOV_PS2_CONTROLLER_h + +#include +#include +#include + +namespace Mitov +{ + class PS2BasicControllerDirect : public Mitov::PS2BasicController + { + typedef Mitov::PS2BasicController inherited; + + protected: + PS2X Fps2x; + + public: + virtual bool ReadDigital( unsigned int AIndex ) + { + return Fps2x.Button( AIndex ); + } + + virtual float ReadAnalog( unsigned int AIndex ) + { + return ((float)Fps2x.Analog( AIndex )) / 255; + } + + public: + PS2BasicControllerDirect( int ADataPinNumber, int ACommandPinNumber, int AAttentionPinNumber, int AClockPinNumber ) + { + Fps2x.config_gamepad( AClockPinNumber, ACommandPinNumber, AAttentionPinNumber, ADataPinNumber, true, true ); + } + + }; +//--------------------------------------------------------------------------- + class PS2Controller : public PS2BasicControllerDirect + { + typedef PS2BasicControllerDirect inherited; + + public: + OpenWire::SinkPin SmallVibrateMotorInputPin; + OpenWire::SinkPin LargeVibrateMotorInputPin; + + protected: + bool FSmallMotor = false; + int8_t FLargeMotor = 0; + + protected: + void DoSmallVibrateMotorReceive( void *_Data ) + { + FSmallMotor = *(bool *)_Data; + } + + void DoLargeVibrateMotorReceive( void *_Data ) + { + FLargeMotor = (int8_t)( constrain( *(float *)_Data, 0, 1 ) * 255 + 0.5 ); + } + + virtual void ReadController() override + { + Fps2x.read_gamepad( FSmallMotor, FLargeMotor ); + } + + public: + PS2Controller( int ADataPinNumber, int ACommandPinNumber, int AAttentionPinNumber, int AClockPinNumber ) : + inherited( ADataPinNumber, ACommandPinNumber, AAttentionPinNumber, AClockPinNumber ) + { + SmallVibrateMotorInputPin.SetCallback( MAKE_CALLBACK( PS2Controller::DoSmallVibrateMotorReceive )); + LargeVibrateMotorInputPin.SetCallback( MAKE_CALLBACK( PS2Controller::DoLargeVibrateMotorReceive )); + } + + }; +//--------------------------------------------------------------------------- + class PS2Guitar : public PS2BasicControllerDirect + { + typedef PS2BasicControllerDirect inherited; + + virtual void ReadController() override + { + Fps2x.read_gamepad( false, 0 ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_PS2_Controller_Basic.h b/libraries/Mitov/Mitov_PS2_Controller_Basic.h new file mode 100644 index 0000000..a1fe1ae --- /dev/null +++ b/libraries/Mitov/Mitov_PS2_Controller_Basic.h @@ -0,0 +1,157 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PS2_CONTROLLER_BASIC_h +#define _MITOV_PS2_CONTROLLER_BASIC_h + +#include + +namespace Mitov +{ + class PS2BasicController : public Mitov::EnabledComponent, public Mitov::ClockingSupport + { + typedef Mitov::EnabledComponent inherited; + + public: + virtual bool ReadDigital( unsigned int AIndex ) = 0; + virtual float ReadAnalog( unsigned int AIndex ) = 0; + + public: + class BaseSensor : public OpenWire::SourcePin + { + protected: + unsigned int FIndex; + + public: + virtual void Process( PS2BasicController *AOwner ) = 0; + virtual void StartProcess( PS2BasicController *AOwner ) = 0; + + public: + BaseSensor( unsigned int AIndex ) : + FIndex( AIndex ) + { + } + + }; + + class DigitalSensor : public BaseSensor + { + typedef BaseSensor inherited; + + protected: + bool FValue; + + public: + virtual void Process( PS2BasicController *AOwner ) override + { + bool AValue = AOwner->ReadDigital( FIndex ); + + if( FValue == AValue ) + return; + + FValue = AValue; + Notify( &FValue ); + } + + virtual void StartProcess( PS2BasicController *AOwner ) override + { + bool AValue = AOwner->ReadDigital( FIndex ); + FValue = AValue; + Notify( &FValue ); + } + + public: + using inherited::inherited; + + }; + + class AnalogSensor : public BaseSensor + { + typedef BaseSensor inherited; + + protected: + float FValue; + + public: + virtual void Process( PS2BasicController *AOwner ) override + { + float AValue = AOwner->ReadAnalog( FIndex ); + + if( FValue == AValue ) + return; + + FValue = AValue; + Notify( &FValue ); + } + + virtual void StartProcess( PS2BasicController *AOwner ) override + { + float AValue = AOwner->ReadAnalog( FIndex ); + + FValue = AValue; + Notify( &FValue ); + } + + public: + using inherited::inherited; + + }; + + public: + Mitov::SimpleList Sensors; + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ! ClockInputPin.IsConnected() ) + ReadData(); + + inherited::SystemLoopBegin( currentMicros ); + } + + virtual void SystemStart() override + { + ReadController(); + for( int i = 0; i < Sensors.size(); ++i ) + Sensors[ i ]->StartProcess( this ); + + inherited::SystemStart(); + } + + protected: + virtual void DoClockReceive( void *_Data ) override + { + ReadData(); + } + + void ReadData() + { + if( ! Enabled ) + return; + + ReadController(); + + for( int i = 0; i < Sensors.size(); ++i ) + Sensors[ i ]->Process( this ); + } + + virtual void ReadController() = 0; + +/* + virtual ~PS2BasicController() + { + for( int i = 0; i < Sensors.size(); ++i ) + delete Sensors[ i ]; + } +*/ + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_PS2_Controller_Serial.h b/libraries/Mitov/Mitov_PS2_Controller_Serial.h new file mode 100644 index 0000000..0f7cf8b --- /dev/null +++ b/libraries/Mitov/Mitov_PS2_Controller_Serial.h @@ -0,0 +1,145 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PS2_CONTROLLER_SERIAL_h +#define _MITOV_PS2_CONTROLLER_SERIAL_h + +#include +#include + +namespace Mitov +{ + class PS2BasicControllerSerial : public Mitov::PS2BasicController + { + typedef Mitov::PS2BasicController inherited; + + protected: + Mitov::BasicSerialPort &FSerial; + + protected: + void WriteByte( byte AValue ) + { + while( FSerial.GetStream().available() > 0 ) + Serial.read(); + + FSerial.GetStream().write( AValue ); + FSerial.GetStream().flush(); //wait for all data transmitted + } + + byte ReadByte() + { + long waitcount=0; + + while(true) + { + if( FSerial.GetStream().available() > 0 ) + { + byte rec_data = FSerial.GetStream().read(); +// SERIAL_ERR=false; + return(rec_data); + } + waitcount++; + if(waitcount>50000) + { +// SERIAL_ERR=true; + return (0xFF); + } + + } + } + + public: + virtual bool ReadDigital( unsigned int AIndex ) override + { + WriteByte( AIndex ); + return ( ReadByte() == 0 ); + } + + virtual float ReadAnalog( unsigned int AIndex ) override + { + WriteByte( AIndex ); + return ((float)ReadByte()) / 255; +// return ((float)Fps2x.Analog( AIndex )) / 255; + } + + public: + PS2BasicControllerSerial( Mitov::BasicSerialPort &ASerial ) : + FSerial( ASerial ) + { + } + + }; +//--------------------------------------------------------------------------- + class PS2ControllerSerial : public PS2BasicControllerSerial + { + typedef PS2BasicControllerSerial inherited; + + public: + OpenWire::SinkPin SmallVibrateMotorInputPin; + OpenWire::SinkPin LargeVibrateMotorInputPin; + + protected: + bool FSmallMotor = false; + int8_t FLargeMotor = 0; + + protected: + void DoSmallVibrateMotorReceive( void *_Data ) + { + FSmallMotor = *(bool *)_Data; + } + + void DoLargeVibrateMotorReceive( void *_Data ) + { + FLargeMotor = (int8_t)( constrain( *(float *)_Data, 0, 1 ) * 255 + 0.5 ); + } + + virtual void ReadController() + { + WriteByte( 29 ); // Small Motor + if( FSmallMotor ) + WriteByte( 1 ); + + else + WriteByte( 0 ); + + WriteByte( 30 ); // Large Motor + WriteByte( FLargeMotor ); + } + + public: + PS2ControllerSerial( Mitov::BasicSerialPort &ASerial ) : + inherited( ASerial ) + { + SmallVibrateMotorInputPin.SetCallback( MAKE_CALLBACK( PS2ControllerSerial::DoSmallVibrateMotorReceive )); + LargeVibrateMotorInputPin.SetCallback( MAKE_CALLBACK( PS2ControllerSerial::DoLargeVibrateMotorReceive )); + } + + }; +//--------------------------------------------------------------------------- +/* + class PS2GuitarSerial : public PS2BasicControllerSerial + { + typedef PS2BasicControllerSerial inherited; + + virtual void ReadController() + { + Fps2x.read_gamepad( false, 0 ); + } + + public: + PS2GuitarSerial( int ADataPinNumber, int ACommandPinNumber, int AAttentionPinNumber, int AClockPinNumber ) : + inherited( ADataPinNumber, ACommandPinNumber, AAttentionPinNumber, AClockPinNumber ) + { + } + }; +*/ +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Packet.h b/libraries/Mitov/Mitov_Packet.h new file mode 100644 index 0000000..38847a7 --- /dev/null +++ b/libraries/Mitov/Mitov_Packet.h @@ -0,0 +1,999 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PACKET_h +#define _MITOV_PACKET_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class TPacketAccumulator : public Mitov::SimpleList + { + public: + bool SkipBytes( int ACount ) + { + if( size() < ACount ) + return false; + + pop_front( ACount ); + return true; + } + + bool FindBytes( int ASize, unsigned char *ABytesPtr, int AStartPos, int ASearchSize, int &APosition ) + { + for( APosition = AStartPos; APosition < MitovMin( (int)( _size - ASize ), ASearchSize ); ++APosition ) + if( memcmp( ABytesPtr, _list + APosition, ASize ) == 0 ) + { + APosition += ASize; + return true; + } + + return false; + } + + bool FindBytes( int ASize, unsigned char *ABytesPtr, int &APosition ) + { + return FindBytes( ASize, ABytesPtr, 0, _size, APosition ); + } + + bool ExtractBytes( int ASize, void *ABytesPtr ) + { + if( size() < ASize ) + return false; + + memcpy( ABytesPtr, _list, ASize ); + pop_front( ASize ); + return true; + } + + bool PeekBytes( int ASize, void *ABytesPtr ) + { + if( size() < ASize ) + return false; + + memcpy( ABytesPtr, _list, ASize ); + return true; + } + + }; +//--------------------------------------------------------------------------- + class BasicPacketElement : public OpenWire::Component + { + public: + virtual int GetSize( bool &Alligned ) { Alligned = true; return 0; } + virtual bool GetIsPopulated() { return true; } + virtual bool GetIsModified() { return false; } + virtual void ClearModified() {} + virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) {} + virtual bool Expand( unsigned char *AInBuffer, unsigned char *AOutBuffer, int &ASize ) { return false; } + }; +//--------------------------------------------------------------------------- + class BasicUnpacketElement : public OpenWire::Component + { + public: + virtual int Start( bool &AAllign ) { AAllign = false; return 0; } + virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) { return false; } + virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) { return true; } + + }; +//--------------------------------------------------------------------------- + class BasicPacketSinkElement : public BasicPacketElement + { + public: + OpenWire::SinkPin InputPin; + + protected: + virtual void DoReceive( void *_Data ) = 0; + + public: + BasicPacketSinkElement() + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicPacketSinkElement::DoReceive ); + } + + }; +//--------------------------------------------------------------------------- + template class BasicTypedPacketSinkElement : public BasicPacketSinkElement + { + protected: + T FValue; + bool FPopulated : 1; + bool FModified : 1; + +/* + public: + T InitialValue; + + virtual void SystemInit() + { + inherited::SystemInit(); + FValue = InitialValue; + } +*/ + public: + virtual int GetSize( bool &Alligned ) override + { + Alligned = true; +// Serial.println( sizeof( double ) ); + return sizeof( T ) * 8; + } + + virtual bool GetIsPopulated() override + { + return FPopulated; + } + + virtual bool GetIsModified() override + { + return FModified; + } + + virtual void ClearModified() override + { + FModified = false; + } + + virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override + { + if( AOffset ) + { + ++AData; + AOffset = 0; + } + + *(T*)AData = FValue; +// memcpy( AData, &FValue, sizeof( T )); + AData += sizeof( T ); + } + + protected: + virtual void DoReceive( void *_Data ) override + { + T AValue = *(T*)_Data; + FPopulated = true; + if( AValue == FValue ) + return; + + FValue = AValue; + FModified = true; + } + + public: + BasicTypedPacketSinkElement() : + FPopulated( false ), + FModified( false ) + { + } + + }; +//--------------------------------------------------------------------------- + template class BasicTypedUnpacketSourceElement : public BasicUnpacketElement + { + public: + OpenWire::SourcePin OutputPin; + + public: + virtual int Start( bool &AAllign ) override + { + AAllign = true; + return sizeof( T ) * 8; + } + + virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override + { + if( AOffset ) + { + if( ! AAccumulator->SkipBytes( 1 )) + return false; + + AOffset = 0; + } + + T AValue; + if( ! AAccumulator->ExtractBytes( sizeof( T ), &AValue )) + return false; + + OutputPin.Notify( &AValue ); + + return true; + } + + virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override + { + APosition = ( APosition + 7 ) / 8; + APosition *= 8; + APosition += sizeof( T ) * 8; + return false; + } + }; +//--------------------------------------------------------------------------- + class UnpacketDigitalBinaryElement : public BasicTypedUnpacketSourceElement + { + public: + virtual int Start( bool &AAllign ) override + { + AAllign = false; + return 1; + } + + virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override + { + unsigned char AValue; + if( ! AAccumulator->PeekBytes( 1, &AValue )) + return false; + + bool ABoolValue = (( AValue & ( 1 << AOffset )) != 0 ); + ++AOffset; + + if( AOffset == 8 ) + { + AOffset = 0; + if( ! AAccumulator->SkipBytes( 1 )) + return false; + + } + + OutputPin.Notify( &ABoolValue ); + + return true; + } + + virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override + { + ++ APosition; + return false; + } + }; +//--------------------------------------------------------------------------- + class PacketBasicMarkerBinaryElement : public BasicPacketElement + { + public: + Mitov::Bytes Bytes; + + }; +//--------------------------------------------------------------------------- + class UnpacketBasicMarkerBinaryElement : public BasicUnpacketElement + { + public: + Mitov::Bytes Bytes; + + public: + virtual int Start( bool &AAllign ) override + { + AAllign = true; + return Bytes._BytesSize * 2 * 8; + } + +/* + virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override + { + return false; + } + + virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override { return true; } +*/ + + }; +//--------------------------------------------------------------------------- + class UnpacketMarkerBinaryElement : public UnpacketBasicMarkerBinaryElement + { + public: + virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override + { + APosition = ( APosition + 7 ) / 8; + APosition *= 8; + + int ABytesSize = Bytes._BytesSize; + int ASearchPos; + if( ! AInAccumulator->FindBytes( ABytesSize, Bytes._Bytes, APosition / 8, Bytes._BytesSize, ASearchPos )) + AIsCorruptedPacket = true; + + else if( ASearchPos != APosition / 8 + ABytesSize ) + AIsCorruptedPacket = true; + + APosition += ABytesSize * 8; + return false; + } + + virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override + { + if( AOffset != 0 ) + { + if( !AAccumulator->SkipBytes( 1 )) + return false; + + AOffset = 0; + } + + if( ! AAccumulator->SkipBytes( Bytes._BytesSize )) + return false; + + return true; + } + }; +//--------------------------------------------------------------------------- + class UnpacketChecksumElement : public BasicUnpacketElement + { + virtual int Start( bool &AAllign ) override + { + AAllign = true; + return 8; + } + + virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override + { + APosition = ( APosition + 7 ) / 8; + APosition *= 8; + + unsigned char *ABytes = new unsigned char[ APosition / 8 + 1 ]; +// SetLength( ABytes, APosition + 1 ); + + if( ! AInAccumulator->PeekBytes( APosition / 8 + 1, ABytes )) + { + AIsValid = false; + delete [] ABytes; + return false; + } + + unsigned char AChecksum = 0; + +// for AByte in ABytes do +// AChecksum ^= AByte; + for( int i = 0; i < APosition / 8 + 1; ++i ) + AChecksum ^= ABytes[ i ]; + + delete [] ABytes; + + if( AChecksum ) + { + AIsCorruptedPacket = true; + return false; + } + + APosition += 8; + return false; + } + + virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override + { + if( AOffset ) + { + if( ! AAccumulator->SkipBytes( 1 )) + return false; + + AOffset = 0; + } + + AAccumulator->SkipBytes( 1 ); + return true; + } + }; +//--------------------------------------------------------------------------- + class PacketMarkerBinaryElement : public PacketBasicMarkerBinaryElement + { + public: + virtual int GetSize( bool &Alligned ) override + { + Alligned = true; + return Bytes._BytesSize * 8; + } + + virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override + { + if( Bytes._BytesSize == 0 ) + return; + + if( AOffset ) + { + ++AData; + AOffset = 0; + } + + memcpy( AData, Bytes._Bytes, Bytes._BytesSize ); + AData += Bytes._BytesSize; + } + + }; +//--------------------------------------------------------------------------- + class PacketChecksumElement : public BasicPacketElement + { + public: + bool Enabled = true; + + public: + virtual int GetSize( bool &Alligned ) override + { + if( Enabled ) + { + Alligned = true; + return 8; + } + + return 0; + } + + virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override + { + if( !Enabled ) + return; + + if( AOffset ) + { + ++AData; + AOffset = 0; + } + + unsigned char AChecksum = 0; + for( ;ADataStart < AData; ++ADataStart ) + AChecksum ^= *ADataStart; + + *AData = AChecksum; + ++AData; + } + + }; +//--------------------------------------------------------------------------- + class UnpacketHeadMarkerBinaryElement : public UnpacketBasicMarkerBinaryElement + { + protected: + Mitov::SimpleList FDoubledBytes; + + public: + virtual int Start( bool &AAllign ) override + { + for( int i = 0; i < Bytes._BytesSize; ++i ) + FDoubledBytes.push_back( Bytes._Bytes[ i ] ); + + for( int i = 0; i < Bytes._BytesSize; ++i ) + FDoubledBytes.push_back( Bytes._Bytes[ i ] ); + + AAllign = true; + return Bytes._BytesSize * 2 * 8; + } + + virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override + { + if( AOffset ) + { + if( ! AAccumulator->SkipBytes( 1 )) + return false; + + AOffset = 0; + } + + // AOldDebugBuf := AAccumulator.GetAsBuffer(); + AAccumulator->SkipBytes( FDoubledBytes.size() ); + return true; + } + + virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override + { + APosition = ( APosition + 7 ) / 8; + APosition *= 8; + + int ABytesSize = Bytes._BytesSize; + if( !ABytesSize ) + return false; + + unsigned char *ABytes = Bytes._Bytes; + // if( not AInAccumulator.FindSkipBytes( ABytesSize * 2, @FDoubledBytes[ 0 ], ASkipped )) then + // Exit( False ); + + int AFindPosition; + + if( !AInAccumulator->FindBytes( ABytesSize * 2, FDoubledBytes.begin(), AFindPosition )) + { + AIsValid = false; + return false; + } + + AFindPosition -= ABytesSize * 2; + AInAccumulator->SkipBytes( AFindPosition ); + + APosition += ABytesSize * 2 * 8; + + // Dec( ASize, AFindPosition ); + + // if( ASize <= ABytesSize * 2 ) then + // Exit( False ); + + // ANewDebugBuf := AInAccumulator.GetAsBuffer(); + + if( !AInAccumulator->FindBytes( ABytesSize, ABytes, ABytesSize * 2, ASize - ABytesSize * 2, AFindPosition )) + return false; + + // ANewDebugBuf := AInAccumulator.GetAsBuffer(); +// AMarkerBuffer := TSLBlockBuffer.CreateData( ABytes, ABytesSize ); + + // if( not AInAccumulator.FindBytes( ABytesSize, ABytes, ASize - ABytesSize * 2, AFindPosition )) then + // Exit( False ); + + AOutAccumulator->append( ABytes, ABytesSize ); + AOutAccumulator->append( ABytes, ABytesSize ); + + for(;;) + { + Mitov::SimpleList ABuffer; + ABuffer.AddCount( AFindPosition ); +// ABuffer := TSLBlockBuffer.CreateSize( AFindPosition ); + AInAccumulator->ExtractBytes( AFindPosition, ABuffer ); + AOutAccumulator->append( ABuffer, AFindPosition ); + + unsigned char ACount; + AInAccumulator->ExtractBytes( 1, &ACount ); + + for( int i = 0; i <= ACount; ++i ) + AOutAccumulator->append( ABytes, ABytesSize ); + + ASize = ABytesSize * ACount + 1; + + if( ! AInAccumulator->FindBytes( ABytesSize, ABytes, AFindPosition, ASize - AFindPosition, AFindPosition )) + return true; + + } + + return true; + } + + public: + void SkipHeader( TPacketAccumulator *AAccumulator ) + { + AAccumulator->SkipBytes( Bytes._BytesSize * 2 ); + } + + }; +//--------------------------------------------------------------------------- + class PacketHeadMarkerBinaryElement : public PacketMarkerBinaryElement + { + public: + virtual int GetSize( bool &Alligned ) override + { + Alligned = true; + return Bytes._BytesSize * 2 * 8; + } + + virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override + { + if( Bytes._BytesSize == 0 ) + return; + + if( AOffset ) + { + ++AData; + AOffset = 0; + } + + memcpy( AData, Bytes._Bytes, Bytes._BytesSize ); + AData += Bytes._BytesSize; + + memcpy( AData, Bytes._Bytes, Bytes._BytesSize ); + AData += Bytes._BytesSize; + } + + virtual bool Expand( unsigned char *AInBuffer, unsigned char *AOutBuffer, int &ASize ) override + { + if( Bytes._BytesSize == 0 ) + return false; + +// memcpy( AOutBuffer, AInBuffer, ASize ); +// return true; + + unsigned char *ABytes = Bytes._Bytes; + int ABytesSize = Bytes._BytesSize; + + int AOutSize = ABytesSize * 2; + + memcpy( AOutBuffer, AInBuffer, AOutSize ); + AOutBuffer += AOutSize; + AInBuffer += AOutSize; + + int i = AOutSize; + for( ; i < ASize - ABytesSize * 2 + 1; ++i ) + { + if( memcmp( AInBuffer, ABytes, ABytesSize ) == 0 ) + if( memcmp( AInBuffer + ABytesSize, ABytes, ABytesSize ) == 0 ) + { + memcpy( AOutBuffer, AInBuffer, ABytesSize ); + AInBuffer += ABytesSize * 2; + +// Serial.println( "START" ); + AOutBuffer += ABytesSize; + unsigned char ACount = 0; + i += ABytesSize; + for( ; i < ASize - ABytesSize + 1; i += ABytesSize ) + { + if( memcmp( AInBuffer, ABytes, ABytesSize ) != 0 ) + break; + +// Serial.println( "INC" ); + ++ACount; + if( ACount == 255 ) + break; + + AInBuffer += ABytesSize; + } + + if( ACount == *ABytes ) + { + if( ACount > 0 ) + { +// Serial.println( "DEC" ); + --ACount; + AInBuffer -= ABytesSize; + i -= ABytesSize; + } + } + + *AOutBuffer++ = ACount; + AOutSize += ABytesSize + 1; + continue; + } + + *AOutBuffer++ = *AInBuffer++; +//Serial.print( "++AOutSize" ); + ++AOutSize; + } + + int ACorrection = ASize - i; + memcpy( AOutBuffer, AInBuffer, ACorrection ); +// *AOutBuffer = 5; + +// Serial.print( "ADebugCount : " ); +// Serial.println( ADebugCount ); + +// Serial.print( "AOutSize : " ); +// Serial.println( AOutSize ); + +// Serial.print( "TEST : " ); +// Serial.println( ACorrection ); +// Serial.println( i ); + + ASize = AOutSize + ACorrection; + return true; + } + + }; +//--------------------------------------------------------------------------- + class PacketDigitalBinaryElement : public BasicTypedPacketSinkElement + { + public: + virtual int GetSize( bool &Alligned ) override + { + Alligned = false; + return 1; + } + + virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override + { + *AData &= 0xFF >> ( 8 - AOffset ); // Zero the upper bits + if( FValue ) + *AData |= 1 << AOffset; // Set the bit + + ++AOffset; + if( AOffset == 8 ) + { + AOffset = 0; + ++AData; + } + } + }; +//--------------------------------------------------------------------------- + class Packet : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: + Mitov::SimpleObjectList Elements; + + bool OnlyModified = false; + + PacketHeadMarkerBinaryElement HeadMarker; + PacketChecksumElement Checksum; + + protected: + int FBufferSize; + + unsigned char *FBuffers[ 2 ]; + Mitov::SimpleList FAllElements; + + protected: + virtual void DoClockReceive( void *_Data ) override + { +// Serial.println( "++++++" ); + int AElementCount = FAllElements.size(); + if( OnlyModified ) + { + bool AModified = false; + for( int i = 0; i < AElementCount; ++i ) + if( FAllElements[ i ]->GetIsModified() ) + { + AModified = true; + break; + } + + if( !AModified ) + return; + } + else + { + for( int i = 0; i < AElementCount; ++i ) + if( ! FAllElements[ i ]->GetIsPopulated() ) + return; + + } + + unsigned char *ADataPtr = FBuffers[ 0 ]; + unsigned char AOffset = 0; + for( int i = 0; i < AElementCount; ++i ) + { + FAllElements[ i ]->GetData( FBuffers[ 0 ], ADataPtr, AOffset ); +// while( AElementSize-- ) +// OutputPin.Notify( AData++ ); + + + } + + int ASize = FBufferSize; +// Serial.println( ASize ); + int ABufferIndex = 0; +// Serial.println( "--------" ); + for( int i = 0; i < AElementCount; ++i ) + { +// Serial.println( ABufferIndex & 1 ); +// Serial.println( 1 ^ ( ABufferIndex & 1 ) ); + unsigned char *AInBuffer = FBuffers[ ABufferIndex & 1 ]; + unsigned char *AOutBuffer = FBuffers[ 1 ^ ( ABufferIndex & 1 )]; + if( FAllElements[ i ]->Expand( AInBuffer, AOutBuffer, ASize )) + ++ ABufferIndex; + } + + ADataPtr = FBuffers[ ABufferIndex & 1 ]; + OutputPin.SendValue( Mitov::TDataBlock( ASize, ADataPtr )); + +// Serial.println( ASize ); +// while( ASize-- ) +// OutputPin.Notify( ADataPtr++ ); + + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( !ClockInputPin.IsConnected() ) + DoClockReceive( NULL ); + +// delay( 1000 ); + inherited::SystemLoopBegin( currentMicros ); + } + + virtual void SystemStart() + { + FBufferSize = 0; + FAllElements.push_back( &HeadMarker ); + for( int i = 0; i < Elements.size(); ++i ) + FAllElements.push_back( Elements[ i ] ); + + FAllElements.push_back( &Checksum ); + + for( int i = 0; i < FAllElements.size(); ++i ) + { + bool AAlligned = false; + FBufferSize += FAllElements[ i ]->GetSize( AAlligned ); +// Serial.println( FBufferSize ); + if( AAlligned ) + { + FBufferSize = ( FBufferSize + 7 ) / 8; + FBufferSize *= 8; + } + + } + +// Serial.println( FBufferSize ); + + FBufferSize = ( FBufferSize + 7 ) / 8; + FBuffers[ 0 ] = new unsigned char[ FBufferSize * 2 ]; + FBuffers[ 1 ] = new unsigned char[ FBufferSize * 2 ]; + + inherited::SystemStart(); + } + +/* + virtual ~Packet() + { + delete []FBuffers[ 1 ]; + delete []FBuffers[ 0 ]; + } +*/ + }; +//--------------------------------------------------------------------------- + class Unpacket : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + Mitov::SimpleObjectList Elements; + + UnpacketHeadMarkerBinaryElement HeadMarker; + UnpacketChecksumElement Checksum; + + protected: + TPacketAccumulator FAccumulator; + int FMinSize = 0; + Mitov::SimpleList FAllElements; + + protected: + virtual void DoReceive( void *_Data ) override + { + if( FMinSize == 0 ) + return; + +// Serial.println( "FMinSize" ); +// Serial.println( FMinSize ); +/// Serial.println( "T0:" ); +/// Serial.println( FAccumulator.size() ); + Mitov::TDataBlock ABlock = *(Mitov::TDataBlock *)_Data; + while( ABlock.Size-- ) + FAccumulator.push_back( *ABlock.Data++ ); + +/// Serial.println( FAccumulator.size() ); + +// Serial.println( "T1" ); + + TPacketAccumulator AOldAccumulator; + TPacketAccumulator *AInAccumulator; + TPacketAccumulator ARealOutAccumulator; + TPacketAccumulator *AOutAccumulator = &ARealOutAccumulator; + TPacketAccumulator *AAccumulator; + +// while( FAccumulator.size() >= FMinSize ) + while( FAccumulator.size() >= FMinSize ) + { +// Serial.println( "FMinSize" ); +// Serial.println( FMinSize ); +/// Serial.println( "T2" ); +//AOldAccumulator.clear(); +//AOldAccumulator.append( FAccumulator, FAccumulator.size() ); +//return; + AOldAccumulator = FAccumulator; +//return; + AInAccumulator = &FAccumulator; + + AOutAccumulator->clear(); + AAccumulator = &FAccumulator; + int ASize = FMinSize; + bool AIsValid = true; + + bool AIsCorruptedPacket = false; + int APosition = 0; +//return; + for( int i = 0; i < FAllElements.size(); ++i ) + { +// Serial.println( "enter" ); +// Serial.println( FAccumulator.size() ); + if( FAllElements[ i ]->ExpandBuffers( AInAccumulator, AOutAccumulator, ASize, APosition, AIsValid, AIsCorruptedPacket )) + { +// Serial.println( "ExpandBuffers" ); +//return; + if( AIsCorruptedPacket ) + { + FAccumulator = AOldAccumulator; + HeadMarker.SkipHeader( &FAccumulator ); + break; + } + + AAccumulator = AOutAccumulator; + if( AAccumulator == &FAccumulator ) + { +// Serial.println( "AAccumulator == &FAccumulator" ); + AInAccumulator = AOutAccumulator; + AOutAccumulator->clear(); + } + + else + swap( AInAccumulator, AOutAccumulator ); + + } + +// Serial.println( "Step1" ); + if( AIsCorruptedPacket ) + { +// Serial.println( "AIsCorruptedPacket" ); + FAccumulator = AOldAccumulator; + HeadMarker.SkipHeader( &FAccumulator ); + break; + } + + if( ! AIsValid ) + { + FAccumulator = AOldAccumulator; + return; + } + + } + +// Serial.println( "ExpandBuffers OUT" ); + if( AIsCorruptedPacket ) + { +// Serial.println( "AIsCorruptedPacket SKIPPING" ); +//return; +// if( ! HeadMarker.Bytes._BytesSize ) + FAccumulator.SkipBytes( 1 ); + + continue; + } + + if( AAccumulator->size() < FMinSize ) + { + FAccumulator = AOldAccumulator; + return; + } + + if( ASize < FMinSize ) + // for AItem in FAllElements do + // if( not AItem.CanProcess( AAccumulator )) then + { + FAccumulator = AOldAccumulator; + return; + } + +// Serial.println( "PROCESS" ); + unsigned char AOffset = 0; + for( int i = 0; i < FAllElements.size(); ++i ) + { + if( ! FAllElements[ i ]->Process( AAccumulator, AOffset )) + break; + +//break; + } + + +// Serial.println( "exit" ); +// Serial.println( FAllElements.size() ); +// return; + + } + } + + virtual void SystemStart() override + { +// Serial.println( "FMinSize" ); + FAllElements.push_back( &HeadMarker ); + + for( int i = 0; i < Elements.size(); ++i ) + FAllElements.push_back( Elements[ i ] ); + + FAllElements.push_back( &Checksum ); + + FMinSize = 0; + for( int i = 0; i < FAllElements.size(); ++i ) + { + bool AAlligned = false; + FMinSize += FAllElements[ i ]->Start( AAlligned ); + if( AAlligned ) + { + FMinSize = ( FMinSize + 7 ) / 8; + FMinSize = FMinSize * 8; + } + } + + FMinSize = ( FMinSize + 7 ) / 8; + +// Serial.println( "FMinSize" ); +// Serial.println( FMinSize ); + + inherited::SystemStart(); + } + }; +//--------------------------------------------------------------------------- + +} + +#endif \ No newline at end of file diff --git a/libraries/Mitov/Mitov_Potentiometer_SPI.h b/libraries/Mitov/Mitov_Potentiometer_SPI.h new file mode 100644 index 0000000..8649a60 --- /dev/null +++ b/libraries/Mitov/Mitov_Potentiometer_SPI.h @@ -0,0 +1,215 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_POTENTIOMETER_SPI_h +#define _MITOV_POTENTIOMETER_SPI_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class PotentiometerSPIChannel; +//--------------------------------------------------------------------------- + class Potentiometer_SPI : public Mitov::Basic_MultiChannel_SourceSPI + { + typedef Mitov::Basic_MultiChannel_SourceSPI inherited; + + protected: + static const uint8_t kADR_WIPER0 = B00000000; + static const uint8_t kADR_WIPER1 = B00010000; + + static const uint8_t kCMD_READ = B00001100; + static const uint8_t kCMD_WRITE = B00000000; + + static const uint8_t kADR_VOLATILE = B00000000; + static const uint8_t kADR_NON_VOLATILE = B00100000; + + static const uint8_t kTCON_REGISTER = B01000000; + static const uint8_t kSTATUS_REGISTER = B01010000; + + protected: + uint16_t byte2uint16(byte high_byte, byte low_byte) + { + return (uint16_t)high_byte<<8 | (uint16_t)low_byte; + } + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + for( int i =0; i < FChannels.size(); ++i ) + FChannels[ i ]->InitChannel(); + } + + public: + void SPI_write(byte cmd_byte, byte data_byte) + { + cmd_byte |= kCMD_WRITE; + ChipSelectOutputPin.SendValue( false ); + FSPI.transfer(cmd_byte); + FSPI.transfer(data_byte); + ChipSelectOutputPin.SendValue( true ); + } + + uint16_t SPI_read(byte cmd_byte) + { + cmd_byte |= kCMD_READ; + ChipSelectOutputPin.SendValue( false ); + byte high_byte = FSPI.transfer(cmd_byte); + byte low_byte = FSPI.transfer(0xFF); + ChipSelectOutputPin.SendValue( true ); + return byte2uint16(high_byte, low_byte); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class PotentiometerSPIChannel : public Mitov::Basic_Typed_SPIChannel + { + typedef Mitov::Basic_Typed_SPIChannel inherited; + + public: + bool Enabled = true; + + bool ConnectTerminalA = true; + bool ConnectWiper = true; + bool ConnectTerminalB = true; + bool NonVolatile = false; + + protected: + int FMultiplier; + + public: + virtual void InitChannel() + { + uint16_t ATerminalControlValue = FOwner.SPI_read( 4 ); + uint16_t ANewValue; + if( ConnectTerminalB ) + ANewValue = 1; + + else + ANewValue = 0; + + if( ConnectWiper ) + ANewValue |= B10; + + if( ConnectTerminalA ) + ANewValue |= B100; + + if( ! Enabled ) + ANewValue |= B1000; + + if( FIndex == 1 ) + { + ATerminalControlValue &= 0xFF0F; + ATerminalControlValue |= ( ANewValue << 4 ); + } + else + { + ATerminalControlValue &= 0xFFF0; + ATerminalControlValue |= ANewValue; + } + + FOwner.SPI_write( 4, ATerminalControlValue ); + } + + virtual void SendOutput() + { + if( FNewValue == FValue ) + return; + + int wiper_pos = ( FValue * FMultiplier ); + + wiper_pos = constrain( wiper_pos, 0, FMultiplier ); + + FValue = FNewValue; + byte data_byte; + byte cmd_byte = FIndex; + + // Calculate the 9-bit data value to send + data_byte = (byte)(wiper_pos & 0x00FF); + if(wiper_pos > FMultiplier - 1) + if( FMultiplier == 256 ) + cmd_byte |= B00000001; // Table 5-1 (page 36) + + FOwner.SPI_write( cmd_byte, data_byte ); + + if( NonVolatile ) + { + // EEPROM write cycles take 4ms each. So we block with delay(5); after any NV Writes + FOwner.SPI_write( cmd_byte | B10, data_byte ); + delay(5); + } + } + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + InitChannel(); + } + + void SetConnectTerminalA( bool AValue ) + { + if( ConnectTerminalA == AValue ) + return; + + ConnectTerminalA = AValue; + InitChannel(); + } + + void SetConnectWiper( bool AValue ) + { + if( ConnectWiper == AValue ) + return; + + ConnectWiper = AValue; + InitChannel(); + } + + void SetConnectTerminalB( bool AValue ) + { + if( ConnectTerminalB == AValue ) + return; + + ConnectTerminalB = AValue; + InitChannel(); + } + + void SetNonVolatile( bool AValue ) + { + if( NonVolatile == AValue ) + return; + + NonVolatile = AValue; + InitChannel(); + } + + public: + PotentiometerSPIChannel( Potentiometer_SPI &AOwner, int AIndex, int AMultiplier ) : + inherited( AOwner, AIndex ), + FMultiplier( AMultiplier ) + { + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_PriorityEncoder.h b/libraries/Mitov/Mitov_PriorityEncoder.h new file mode 100644 index 0000000..8ea3dd9 --- /dev/null +++ b/libraries/Mitov/Mitov_PriorityEncoder.h @@ -0,0 +1,35 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PRIORITY_ENCODER_h +#define _MITOV_PRIORITY_ENCODER_h + +#include + +namespace Mitov +{ + template class PriorityEncoder : public Mitov::BasicCommonMultiInput + { + typedef Mitov::BasicCommonMultiInput inherited; + + protected: + virtual uint32_t CalculateOutput() override + { + for( uint32_t i = C_NUM_INPUTS; i--; ) + if( inherited::InputPins[ i ].Value ) + return i; + + return 0; + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_PulseMeter.h b/libraries/Mitov/Mitov_PulseMeter.h new file mode 100644 index 0000000..9bf0b18 --- /dev/null +++ b/libraries/Mitov/Mitov_PulseMeter.h @@ -0,0 +1,51 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PULSE_METER_h +#define _MITOV_PULSE_METER_h + +#include + +namespace Mitov +{ + class PulseMeter : public Mitov::CommonEnableFilter + { + typedef Mitov::CommonEnableFilter inherited; + + protected: + unsigned long FStartTime = 0; + bool FOldValue = false; + + protected: + virtual void DoReceive( void *_Data ) + { + if( ! Enabled ) + return; + + bool AValue = *(bool *)_Data; + if( FOldValue == AValue ) + return; + + unsigned long ANow = micros(); + FOldValue = AValue; + if( AValue ) + { + FStartTime = ANow; + return; + } + + int APeriod = ANow - FStartTime; + + OutputPin.Notify( &APeriod ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_PulseWideModulation.h b/libraries/Mitov/Mitov_PulseWideModulation.h new file mode 100644 index 0000000..c211458 --- /dev/null +++ b/libraries/Mitov/Mitov_PulseWideModulation.h @@ -0,0 +1,49 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_PULSE_WIDE_MODULATION_h +#define _MITOV_PULSE_WIDE_MODULATION_h + +#include + +namespace Mitov +{ + class PulseWideModulation : public Mitov::CommonFilter + { + typedef Mitov::CommonFilter inherited; + + protected: + float FValue = 0.0f; + + public: + float Period; + + protected: + virtual void DoReceive( OpenWire::Data &_Data ) override + { + FValue = ((OpenWire::ValueData*)&_Data)->Value; +/* + if(((OpenWire::ValueData*)&_Data)->Value ) + digitalWrite( PinNumber, HIGH ); + + else + digitalWrite( PinNumber, LOW ); +*/ + } + + public: + PulseWideModulation( float _period = 20 ) : + Period( _period ) + { + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_RCServoMeter.h b/libraries/Mitov/Mitov_RCServoMeter.h new file mode 100644 index 0000000..8b873a0 --- /dev/null +++ b/libraries/Mitov/Mitov_RCServoMeter.h @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_RC_SERVO_METER_h +#define _MITOV_RC_SERVO_METER_h + +#include + +namespace Mitov +{ + class RCServoMeter : public Mitov::CommonEnableFilter + { + typedef Mitov::CommonEnableFilter inherited; + + protected: + unsigned long FStartTime = 0; + bool FOldValue = false; + + protected: + virtual void DoReceive( void *_Data ) override + { + if( ! Enabled ) + return; + + bool AValue = *(bool *)_Data; + if( FOldValue == AValue ) + return; + + unsigned long ANow = micros(); + FOldValue = AValue; + if( AValue ) + { + FStartTime = ANow; + return; + } + + float APeriod = ANow - FStartTime; + float AFloatValue = MitovMin( ( APeriod - 1000 ) / 1000, 1 ); + + OutputPin.Notify( &AFloatValue ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_RTC_DS1302.h b/libraries/Mitov/Mitov_RTC_DS1302.h new file mode 100644 index 0000000..e43bc2b --- /dev/null +++ b/libraries/Mitov/Mitov_RTC_DS1302.h @@ -0,0 +1,240 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +// Derived from https://github.com/msparks/arduino-ds1302 + +#ifndef _MITOV_RTC_DS1302_h +#define _MITOV_RTC_DS1302_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + template class RTC_DS1302 : public BasicHaltRTC + { + typedef BasicHaltRTC inherited; + + enum Register + { + kSecondReg = 0, + kMinuteReg = 1, + kHourReg = 2, + kDateReg = 3, + kMonthReg = 4, + kDayReg = 5, + kYearReg = 6, + kWriteProtectReg = 7, + + // The RAM register space follows the clock register space. + kRamAddress0 = 32 + }; + + enum Command + { + kClockBurstRead = 0xBF, + kClockBurstWrite = 0xBE, + kRamBurstRead = 0xFF, + kRamBurstWrite = 0xFE + }; + + class SPISession + { + public: + SPISession() + { + digitalWrite(T_CLOCK_PIN, LOW); + digitalWrite( T_ENABLE_PIN, HIGH ); + delayMicroseconds(4); // tCC + } + + ~SPISession() + { + digitalWrite( T_ENABLE_PIN, LOW ); + delayMicroseconds(4); // tCWH + } + }; + + public: + bool WriteProtect = false; + + protected: + Mitov::TDateTime FLastDateTime; + + public: + void SetWriteProtect( bool AValue ) + { + if( WriteProtect == AValue ) + return; + + WriteProtect = AValue; + UpdateWriteProtect(); + } + + protected: + virtual void SystemInit() + { + pinMode( T_ENABLE_PIN, OUTPUT ); + pinMode( T_CLOCK_PIN, OUTPUT ); +// pinMode( 10, OUTPUT ); + +// Serial.println( "INIT" ); + UpdateHalt(); +// Serial.println( "INIT1" ); + + inherited::SystemInit(); + } + + protected: + void writeOut(const uint8_t value) + { + pinMode( T_DATA_PIN, OUTPUT); + // This assumes that shiftOut is 'slow' enough for the DS1302 to read the + // bits. The datasheet specifies that SCLK must be in its high and low states + // for at least 0.25us at 5V or 1us at 2V. Experimentally, a 16MHz Arduino + // seems to spend ~4us high and ~12us low when shifting. + shiftOut( T_DATA_PIN, T_CLOCK_PIN, LSBFIRST, value); + } + + uint8_t readIn() + { + uint8_t input_value = 0; + uint8_t bit = 0; + pinMode( T_DATA_PIN, INPUT); + + // Bits from the DS1302 are output on the falling edge of the clock + // cycle. This method is called after a previous call to writeOut() or + // readIn(), which will have already set the clock low. + for (int i = 0; i < 8; ++i) + { + bit = digitalRead( T_DATA_PIN ); + input_value |= (bit << i); // Bits are read LSB first. + + // See the note in writeOut() about timing. digitalWrite() is slow enough to + // not require extra delays for tCH and tCL. + digitalWrite( T_CLOCK_PIN, HIGH); + digitalWrite( T_CLOCK_PIN, LOW); + } + + return input_value; + } + + virtual void UpdateHalt() + { + uint8_t sec = readRegister( kSecondReg ); + +// Serial.println( sec ); + + sec &= ~(1 << 7); + sec |= ( ( Halt & 1 ) << 7 ); + writeRegister( kSecondReg, sec ); + } + + void UpdateWriteProtect() + { + writeRegister(kWriteProtectReg, ( ( WriteProtect & 1 ) << 7)); + } + + uint8_t readRegister(const uint8_t reg) + { + const SPISession s; + + const uint8_t cmd_byte = (0x81 | (reg << 1)); + writeOut(cmd_byte); + return readIn(); + } + + void writeRegister( const uint8_t reg, const uint8_t value ) + { + const SPISession s; + + const uint8_t cmd_byte = (0x80 | (reg << 1)); + writeOut(cmd_byte); + writeOut(value); + } + + uint8_t hourFromRegisterValue(const uint8_t value) + { + uint8_t adj; + if (value & 128) // 12-hour mode + adj = 12 * ((value & 32) >> 5); + + else // 24-hour mode + adj = 10 * ((value & (32 + 16)) >> 4); + + return (value & 15) + adj; + } + + virtual void ReadTime() + { + if( ! OutputPin.IsConnected() ) + return; + + const SPISession s; + + writeOut(kClockBurstRead); + uint16_t ASecond = FromBcdToDec(readIn() & 0x7F); + uint16_t AMinute = FromBcdToDec(readIn()); + uint16_t AHour = hourFromRegisterValue(readIn()); + uint16_t ADate = FromBcdToDec(readIn()); + uint16_t AMonth = FromBcdToDec(readIn()); + uint16_t ADay = FromBcdToDec(readIn()); + uint16_t AYear = 2000 + FromBcdToDec(readIn()); + + Mitov::TDateTime ADateTime; + + if( ADateTime.TryEncodeDateTime( AYear, AMonth, ADate, AHour, AMinute, ASecond, 0 )) + { + if( FLastDateTime != ADateTime ) + { + FLastDateTime = ADateTime; + OutputPin.Notify( &ADateTime ); + } + } + + } + + protected: + virtual void DoSetReceive( void *_Data ) + { + if( WriteProtect ) + return; + + Mitov::TDateTime &ADateTime = *(Mitov::TDateTime *)_Data; + + uint16_t AYear; + uint16_t AMonth; + uint16_t ADay; + uint16_t AWeekDay; + uint16_t AHour; + uint16_t AMinute; + uint16_t ASecond; + uint16_t AMilliSecond; + ADateTime.DecodeDateTime( AYear, AMonth, ADay, AWeekDay, AHour, AMinute, ASecond, AMilliSecond ); + + const SPISession s; + + writeOut(kClockBurstWrite); + writeOut( ( ( Halt & 1 ) << 7 ) | FromDecToBcd( ASecond )); + writeOut(FromDecToBcd( AMinute )); + writeOut(FromDecToBcd( AHour )); + writeOut(FromDecToBcd( ADay )); + writeOut(FromDecToBcd( AMonth )); + writeOut(FromDecToBcd( AWeekDay )); + writeOut(FromDecToBcd( AYear - 2000)); + // All clock registers *and* the WP register have to be written for the time + // to be set. + writeOut(0); // Write protection register. + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_RTC_DS1307.h b/libraries/Mitov/Mitov_RTC_DS1307.h new file mode 100644 index 0000000..08cf0d0 --- /dev/null +++ b/libraries/Mitov/Mitov_RTC_DS1307.h @@ -0,0 +1,184 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_RTC_DS1307_h +#define _MITOV_RTC_DS1307_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + enum DS1307ClockFrequency { rtc1307fDisabledLow, rtc1307fDisabledHigh, rtc1307f1Hz, rtc1307f4096Hz, rtc1307f8192Hz, rtc1307f32768Hz }; +//--------------------------------------------------------------------------- + class RTC_DS1307 : public BasicHaltRTC + { + typedef BasicHaltRTC inherited; + + enum Register + { + kSecondReg = 0, + kMinuteReg = 1, + kHourReg = 2, + kDayReg = 3, + kDateReg = 4, + kMonthReg = 5, + kYearReg = 6, + kClockReg = 7, + + // The RAM register space follows the clock register space. + kRamAddress0 = 8 + }; + + const uint8_t DS1307_ADDRESS = 0x68; + + public: + DS1307ClockFrequency ClockFrequency : 3; + + public: + void SetClockFrequency( DS1307ClockFrequency AValue ) + { + if( ClockFrequency == AValue ) + return; + + ClockFrequency = AValue; + UpdateClockFrequency(); + } + + protected: + Mitov::TDateTime FLastDateTime; + + protected: + uint8_t readRegister(const uint8_t reg) + { + Wire.beginTransmission(DS1307_ADDRESS); + Wire.write( reg ); + Wire.endTransmission(); + + Wire.requestFrom(DS1307_ADDRESS, (uint8_t)1 ); + + return Wire.read(); + } + + void writeRegister( const uint8_t reg, const uint8_t value ) + { + Wire.beginTransmission(DS1307_ADDRESS); + Wire.write( reg ); + Wire.write( value ); + Wire.endTransmission(); + } + + uint8_t hourFromRegisterValue(const uint8_t value) + { + uint8_t adj; + if (value & 128) // 12-hour mode + adj = 12 * ((value & 32) >> 5); + + else // 24-hour mode + adj = 10 * ((value & (32 + 16)) >> 4); + + return (value & 15) + adj; + } + + void UpdateClockFrequency() + { + const uint8_t CValues [] = { 0x00, 0x80, 0x40, 0x41, 0x42, 0x43 }; + writeRegister( kClockReg, CValues[ ClockFrequency ] ); + } + + virtual void ReadTime() + { + if( ! OutputPin.IsConnected() ) + return; + + Wire.beginTransmission(DS1307_ADDRESS); + Wire.write((byte)0); + Wire.endTransmission(); + + Wire.requestFrom(DS1307_ADDRESS, (byte)7); + uint16_t ASecond = FromBcdToDec(Wire.read() & 0x7F); + uint16_t AMinute = FromBcdToDec(Wire.read()); + uint16_t AHour = hourFromRegisterValue( Wire.read() ); + uint16_t ADay = Wire.read(); + uint16_t ADate = FromBcdToDec(Wire.read()); + uint16_t AMonth = FromBcdToDec(Wire.read()); + uint16_t AYear = FromBcdToDec(Wire.read()) + 2000; + + Mitov::TDateTime ADateTime; + + if( ADateTime.TryEncodeDateTime( AYear, AMonth, ADate, AHour, AMinute, ASecond, 0 )) + { + if( FLastDateTime != ADateTime ) + { + FLastDateTime = ADateTime; + OutputPin.Notify( &ADateTime ); + } + } + + } + + virtual void UpdateHalt() + { + uint8_t sec = readRegister( kSecondReg ); + + sec &= ~(1 << 7); + sec |= ( ( Halt & 1 ) << 7 ); + writeRegister( kSecondReg, sec ); + } + + protected: + virtual void DoSetReceive( void *_Data ) + { +// if( WriteProtect ) +// return; + + Mitov::TDateTime &ADateTime = *(Mitov::TDateTime *)_Data; + + uint16_t AYear; + uint16_t AMonth; + uint16_t ADay; + uint16_t AWeekDay; + uint16_t AHour; + uint16_t AMinute; + uint16_t ASecond; + uint16_t AMilliSecond; + ADateTime.DecodeDateTime( AYear, AMonth, ADay, AWeekDay, AHour, AMinute, ASecond, AMilliSecond ); + + Wire.beginTransmission(DS1307_ADDRESS); + Wire.write((byte)0); // start at location 0 + + Wire.write( ( ( Halt & 1 ) << 7 ) | FromDecToBcd( ASecond )); + Wire.write(FromDecToBcd( AMinute )); + Wire.write(FromDecToBcd( AHour )); + Wire.write(FromDecToBcd( AWeekDay )); + Wire.write(FromDecToBcd( ADay )); + Wire.write(FromDecToBcd( AMonth )); + Wire.write(FromDecToBcd( AYear - 2000)); + + Wire.endTransmission(); + } + + protected: + virtual void SystemInit() + { + UpdateHalt(); + UpdateClockFrequency(); + inherited::SystemInit(); + } + + public: + RTC_DS1307() : + ClockFrequency( rtc1307fDisabledLow ) + { + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_RTC_DS3231.h b/libraries/Mitov/Mitov_RTC_DS3231.h new file mode 100644 index 0000000..1273417 --- /dev/null +++ b/libraries/Mitov/Mitov_RTC_DS3231.h @@ -0,0 +1,177 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_RTC_DS3231_h +#define _MITOV_RTC_DS3231_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- +// enum DS3231ClockFrequency { rtc3231fDisabled, rtc3231f1Hz, rtc3231f1024Hz, rtc3231f4096Hz, rtc3231f8192Hz }; +//--------------------------------------------------------------------------- + class RTC_DS3231 : public BasicHaltRTC + { + typedef BasicHaltRTC inherited; + + enum Register + { + kSecondReg = 0, + kMinuteReg = 1, + kHourReg = 2, + kDayReg = 3, + kDateReg = 4, + kMonthReg = 5, + kYearReg = 6, + kControlReg = 0xE +// kClockReg = 7, + + // The RAM register space follows the clock register space. +// kRamAddress0 = 8 + }; + + const uint8_t DS3231_ADDRESS = 0x68; + + protected: + Mitov::TDateTime FLastDateTime; + + protected: + uint8_t readRegister(const uint8_t reg) + { + Wire.beginTransmission(DS3231_ADDRESS); + Wire.write( reg ); + Wire.endTransmission(); + + Wire.requestFrom(DS3231_ADDRESS, (uint8_t)1 ); + + return Wire.read(); + } + + void writeRegister( const uint8_t reg, const uint8_t value ) + { + Wire.beginTransmission(DS3231_ADDRESS); + Wire.write( reg ); + Wire.write( value ); + Wire.endTransmission(); + } + + uint8_t hourFromRegisterValue(const uint8_t value) + { + uint8_t adj; + if (value & 128) // 12-hour mode + adj = 12 * ((value & 32) >> 5); + + else // 24-hour mode + adj = 10 * ((value & (32 + 16)) >> 4); + + return (value & 15) + adj; + } + + virtual void ReadTime() + { + if( ! OutputPin.IsConnected() ) + return; + + Wire.beginTransmission(DS3231_ADDRESS); + Wire.write((byte)0); + Wire.endTransmission(); + + Wire.requestFrom(DS3231_ADDRESS, (byte)7); + uint16_t ASecond = FromBcdToDec(Wire.read() & 0x7F); + uint16_t AMinute = FromBcdToDec(Wire.read()); + uint16_t AHour = hourFromRegisterValue( Wire.read() ); + uint16_t ADay = Wire.read(); + uint16_t ADate = FromBcdToDec(Wire.read()); + uint16_t AMonth = FromBcdToDec(Wire.read()); + uint16_t AYear = FromBcdToDec(Wire.read()) + 2000; + + Mitov::TDateTime ADateTime; + + if( ADateTime.TryEncodeDateTime( AYear, AMonth, ADate, AHour, AMinute, ASecond, 0 )) + { + if( FLastDateTime != ADateTime ) + { + FLastDateTime = ADateTime; + OutputPin.Notify( &ADateTime ); + } + } + + } + + virtual void UpdateHalt() + { + uint8_t sec = readRegister( kSecondReg ); + + sec &= ~(1 << 7); + sec |= ( ( Halt & 1 ) << 7 ); + writeRegister( kSecondReg, sec ); + } + +/* + void UpdateClockFrequency() + { + const uint8_t CValues [] = { 0x00, 0x80, 0x40, 0x41, 0x42, 0x43 }; + + uint8_t AValue = readRegister( kControlReg ); + + sec &= ~(1 << 7); + sec |= ( ( Halt & 1 ) << 7 ); + writeRegister( kSecondReg, sec ); + + writeRegister( kControlReg, CValues[ ClockFrequency ] ); + } +*/ + protected: + virtual void DoSetReceive( void *_Data ) + { + Mitov::TDateTime &ADateTime = *(Mitov::TDateTime *)_Data; + + uint16_t AYear; + uint16_t AMonth; + uint16_t ADay; + uint16_t AWeekDay; + uint16_t AHour; + uint16_t AMinute; + uint16_t ASecond; + uint16_t AMilliSecond; + ADateTime.DecodeDateTime( AYear, AMonth, ADay, AWeekDay, AHour, AMinute, ASecond, AMilliSecond ); + + Wire.beginTransmission(DS3231_ADDRESS); + Wire.write((byte)0); // start at location 0 + + Wire.write( ( ( Halt & 1 ) << 7 ) | FromDecToBcd( ASecond )); + Wire.write(FromDecToBcd( AMinute )); + Wire.write(FromDecToBcd( AHour )); + Wire.write(FromDecToBcd( AWeekDay )); + Wire.write(FromDecToBcd( ADay )); + Wire.write(FromDecToBcd( AMonth )); + Wire.write(FromDecToBcd( AYear - 2000)); + + Wire.endTransmission(); + } + + protected: + virtual void SystemInit() + { + UpdateHalt(); +// UpdateClockFrequency(); + inherited::SystemInit(); + } + + public: + RTC_DS3231()// : +// ClockFrequency( rtc3231fDisabled ) + { + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_RampToValue.h b/libraries/Mitov/Mitov_RampToValue.h new file mode 100644 index 0000000..892ba79 --- /dev/null +++ b/libraries/Mitov/Mitov_RampToValue.h @@ -0,0 +1,100 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_RAMP_TO_VALUE_h +#define _MITOV_RAMP_TO_VALUE_h + +#include + +namespace Mitov +{ + class RampToValue : public Mitov::CommonEnableFilter, public Mitov::ClockingSupport + { + typedef Mitov::CommonEnableFilter inherited; + + public: + float InitialValue = 0.0f; + float Slope = 1.0f; + + protected: + unsigned long FLastTime = 0; + float FCurrentValue = 0.0f; + float FTargetValue = 0.0f; + + protected: + virtual void DoReceive( void *_Data ) + { + bool AValue = *(float *)_Data; + if( FTargetValue == AValue ) + return; + + FTargetValue = AValue; +// FStartTime = micros(); + } + + virtual void DoClockReceive( void *_Data ) override + { + Generate( micros(), true ); + } + + void Generate( unsigned long currentMicros, bool FromClock ) + { + if( FCurrentValue != FTargetValue ) + { + if( inherited::Enabled ) + { + float ARamp = abs( ( currentMicros - FLastTime ) * Slope / 1000000 ); + if( FCurrentValue < FTargetValue ) + { + FCurrentValue += ARamp; + if( FCurrentValue > FTargetValue ) + FCurrentValue = FTargetValue; + + } + else + { + FCurrentValue -= ARamp; + if( FCurrentValue < FTargetValue ) + FCurrentValue = FTargetValue; + + } + + inherited::OutputPin.Notify( &FCurrentValue ); + } + } + + else if( FromClock ) + inherited::OutputPin.Notify( &FCurrentValue ); + + FLastTime = currentMicros; +// inherited::SendOutput(); + } + + protected: + virtual void SystemStart() override + { + FCurrentValue = InitialValue; + FTargetValue = InitialValue; + + inherited::OutputPin.Notify( &FCurrentValue ); + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ! ClockInputPin.IsConnected() ) + Generate( currentMicros, false ); + + inherited::SystemLoopBegin( currentMicros ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_RandomGenerator.h b/libraries/Mitov/Mitov_RandomGenerator.h new file mode 100644 index 0000000..4d6328e --- /dev/null +++ b/libraries/Mitov/Mitov_RandomGenerator.h @@ -0,0 +1,184 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_RANDOM_GENERATOR_h +#define _MITOV_RANDOM_GENERATOR_h + +#include +#include "Mitov_BasicGenerator.h" + +namespace Mitov +{ +#define Min Min +#define Max Max + template class CommonRandomGenerator : public Mitov::BasicGenerator + { + typedef Mitov::BasicGenerator inherited; + + public: + T Min; + T Max; + long Seed = 0; + + protected: + virtual void SystemStart() + { + randomSeed( Seed ); + + inherited::SystemStart(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! inherited::ClockInputPin.IsConnected() ) + Generate(); + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + virtual void GenerateValue() = 0; + + void Generate() + { + if( inherited::Enabled ) + { + if( Min == Max ) + inherited::FValue = Min; + + else + GenerateValue(); + } + + inherited::SendOutput(); + } + + virtual void DoClockReceive( void *_Data ) + { + Generate(); + } + + public: + CommonRandomGenerator( T AMin, T AMax ) : + Min( AMin ), + Max( AMax ) + { + } + + }; +//--------------------------------------------------------------------------- + class RandomAnalogGenerator : public Mitov::CommonRandomGenerator + { + typedef Mitov::CommonRandomGenerator inherited; + + protected: + virtual void GenerateValue() + { + float AMin = MitovMin( Min, Max ); + float AMax = MitovMax( Min, Max ); +// double ARandom = random( -2147483648, 2147483647 ); + double ARandom = random( -1147483648, 1147483647 ); +// FValue = ARandom; + ARandom += 1147483648; + FValue = AMin + ( ARandom / ( (double)1147483647 + (double)1147483648 )) * (AMax - AMin); + } + + public: + RandomAnalogGenerator() : + inherited( 0, 1 ) + { + } + + }; +//--------------------------------------------------------------------------- + class RandomIntegerGenerator : public Mitov::CommonRandomGenerator + { + typedef Mitov::CommonRandomGenerator inherited; + + protected: + virtual void GenerateValue() + { + long AMin = MitovMin( Min, Max ); + long AMax = MitovMax( Min, Max ); + FValue = random( AMin, AMax + 1 ); + } + + public: + RandomIntegerGenerator() : + inherited( -1000, 1000 ) + { + } + + }; +//--------------------------------------------------------------------------- + class RandomUnsignedGenerator : public Mitov::CommonRandomGenerator + { + typedef Mitov::CommonRandomGenerator inherited; + + protected: + virtual void GenerateValue() + { + unsigned long AMin = MitovMin( Min, Max ); + unsigned long AMax = MitovMax( Min, Max ); + FValue = random( AMin, AMax + 1 ); + } + + public: + RandomUnsignedGenerator() : + inherited( 0, 1000 ) + { + } + + }; +//--------------------------------------------------------------------------- + class RandomDateTimeGenerator : public Mitov::CommonRandomGenerator + { + typedef Mitov::CommonRandomGenerator inherited; + + protected: + virtual void GenerateValue() + { + uint32_t ARandomDate = random( Min.Date, Max.Date ); + uint32_t ARandomTime; + if( ARandomDate == Min.Date ) + ARandomTime = random( Min.Time, MSecsPerDay ); + + else if( ARandomDate == Max.Date ) + ARandomTime = random( 0, Max.Time ); + + else + ARandomTime = random( 0, MSecsPerDay ); + + FValue.Date = ARandomDate; + FValue.Time = ARandomTime; +/* + float AMin = MitovMin( Min.Value, Max.Value ); + float AMax = MitovMax( Min.Value, Max.Value ); +// double ARandom = random( -2147483648, 2147483647 ); + double ARandom = random( -1147483648, 1147483647 ); +// FValue = ARandom; + ARandom += 1147483648; + FValue.Value = AMin + ( ARandom / ( (double)1147483647 + (double)1147483648 )) * (AMax - AMin); +*/ + } + + public: + RandomDateTimeGenerator() : + inherited( Mitov::TDateTime( 693594, 0 ), Mitov::TDateTime( 693694, 0 ) ) + { +// Min( ) + } + + }; +//--------------------------------------------------------------------------- +#undef Min +#undef Max +} + +#endif diff --git a/libraries/Mitov/Mitov_Remember.h b/libraries/Mitov/Mitov_Remember.h new file mode 100644 index 0000000..f9c1853 --- /dev/null +++ b/libraries/Mitov/Mitov_Remember.h @@ -0,0 +1,61 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_REMEMBER_h +#define _MITOV_REMEMBER_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + template class Remember : public CommonEnableFilter + { + typedef CommonFilter inherited; + + public: + OpenWire::SinkPin RememberInputPin; + OpenWire::SinkPin RecallInputPin; + + protected: + T_STORE FInData; + T_STORE FSavedData; + + protected: + virtual void DoReceive( void *_Data ) override + { + FInData = *(T_DATA*)_Data; + } + + protected: + void DoReceiveRemember( void *_Data ) + { + if( Enabled ) + FSavedData = FInData; + } + + void DoRecallSnapshot( void *_Data ) + { + if( Enabled ) + OutputPin.SendValue( FSavedData ); + } + + public: + Remember( T_STORE AData ) : + FInData( AData ), + FSavedData( AData ) + { + RememberInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Remember::DoReceiveRemember ); + RecallInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Remember::DoRecallSnapshot ); + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_RotaryEncoderSensor.h b/libraries/Mitov/Mitov_RotaryEncoderSensor.h new file mode 100644 index 0000000..b7e7345 --- /dev/null +++ b/libraries/Mitov/Mitov_RotaryEncoderSensor.h @@ -0,0 +1,151 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_ROTARY_ENCODER_SENSOR_h +#define _MITOV_ROTARY_ENCODER_SENSOR_h + +#include + +namespace Mitov +{ + class BasicRotaryEncoderSensor : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SinkPin AInputPin; + OpenWire::SinkPin BInputPin; + + OpenWire::SourcePin UpOutputPin; + OpenWire::SourcePin DownOutputPin; + + public: + bool Enabled = true; + + protected: + bool FAValue = false; + bool FBValue = false; + bool FAPopulated = false; + bool FBPopulated = false; + + protected: + void DoValueReceiveA( bool AValue ) + { + FAPopulated = true; + if( FAValue == AValue ) + return; + + FAValue = AValue; + if( Enabled && AValue && FBPopulated ) + { + if( FBValue ) + DownOutputPin.Notify( NULL ); + + else + UpOutputPin.Notify( NULL ); + } + } + + void DoValueReceiveB( bool AValue ) + { + FBPopulated = true; + if( FBValue == AValue ) + return; + + FBValue = AValue; + } + + protected: + virtual void DoReceiveA( void *_Data ) = 0; + virtual void DoReceiveB( void *_Data ) = 0; + + public: + BasicRotaryEncoderSensor() + { + AInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicRotaryEncoderSensor::DoReceiveA ); + BInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicRotaryEncoderSensor::DoReceiveB ); + } + + }; +//--------------------------------------------------------------------------- + class RotaryEncoderSensor : public BasicRotaryEncoderSensor + { + typedef BasicRotaryEncoderSensor inherited; + + protected: + virtual void DoReceiveA( void *_Data ) override + { + DoValueReceiveA( *(bool*)_Data ); + } + + virtual void DoReceiveB( void *_Data ) override + { + DoValueReceiveB( *(bool*)_Data ); + } + + }; +//--------------------------------------------------------------------------- + class RotaryEncoderSensor_Debounce : public BasicRotaryEncoderSensor + { + typedef BasicRotaryEncoderSensor inherited; + + public: + uint32_t DebounceInterval = 0; + + protected: + bool FALastValue : 1; + bool FBLastValue : 1; + + unsigned long FALastTime = 0; + unsigned long FBLastTime = 0; + + protected: + virtual void DoReceiveA( void *_Data ) + { + bool AValue = *( bool *)_Data; + if( AValue != FALastValue ) + FALastTime = millis(); + + FALastValue = AValue; + } + + virtual void DoReceiveB( void *_Data ) + { + bool AValue = *( bool *)_Data; + if( AValue != FBLastValue ) + FBLastTime = millis(); + + FBLastValue = AValue; + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( FAValue != FALastValue ) + if( millis() - FALastTime > DebounceInterval ) + DoValueReceiveA( FALastValue ); + + if( FBValue != FBLastValue ) + if( millis() - FBLastTime > DebounceInterval ) + DoValueReceiveB( FBLastValue ); + + inherited::SystemLoopBegin( currentMicros ); + } + + public: + RotaryEncoderSensor_Debounce() : + FALastValue( false ), + FBLastValue( false ) + { + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Sabertooth_DualMotor.h b/libraries/Mitov/Mitov_Sabertooth_DualMotor.h new file mode 100644 index 0000000..2983ad5 --- /dev/null +++ b/libraries/Mitov/Mitov_Sabertooth_DualMotor.h @@ -0,0 +1,367 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SABERTOOTH_DUALMOTOR_h +#define _MITOV_SABERTOOTH_DUALMOTOR_h + +#include + +namespace Mitov +{ + class SabertoothDualMotorBasic : public Mitov::EnabledComponent + { + typedef Mitov::EnabledComponent inherited; + + public: + OpenWire::SinkPin MotorsInputPins[ 2 ]; + + public: + void SetEnabled( bool AValue ) + { + if( AValue == Enabled ) + return; + + Enabled = AValue; + if( Enabled ) + SendStart(); + + else + SendStop(); + } + + protected: + Mitov::BasicSerialPort &FSerial; + + protected: + float FSpeeds[2] = { -1.0, -1.0 }; + + protected: + virtual void SendStart() = 0; + virtual void SendStop() = 0; + virtual void SetSpeed( int AIndex, float ASpeed ) = 0; + + protected: + void DoMotor1Receive( void *_Data ) + { + SetSpeed( 0, *(float *)_Data ); + } + + void DoMotor2Receive( void *_Data ) + { + SetSpeed( 1, *(float *)_Data ); + } + + public: + SabertoothDualMotorBasic( Mitov::BasicSerialPort &ASerial ) : + FSerial( ASerial ) + { + MotorsInputPins[ 0 ].SetCallback( this, (OpenWire::TOnPinReceive)&SabertoothDualMotorBasic::DoMotor1Receive ); + MotorsInputPins[ 1 ].SetCallback( this, (OpenWire::TOnPinReceive)&SabertoothDualMotorBasic::DoMotor2Receive ); + } + + }; +//--------------------------------------------------------------------------- + class SabertoothDualMotorSimple : public SabertoothDualMotorBasic + { + typedef SabertoothDualMotorBasic inherited; + + public: + OpenWire::SourcePin SlaveSelectOutputPin; + + protected: + virtual void SendStart() + { + float AValue = FSpeeds[ 0 ]; + FSpeeds[ 0 ] = -1; + SetSpeed( 0, AValue ); + + AValue = FSpeeds[ 1 ]; + FSpeeds[ 1 ] = -1; + SetSpeed( 1, AValue ); + } + + virtual void SendStop() + { + SendValue( 0 ); + } + + virtual void SetSpeed( int AIndex, float ASpeed ) + { + ASpeed = constrain( ASpeed, 0, 1 ); + if( FSpeeds[ AIndex ] == ASpeed ) + return; + + FSpeeds[ AIndex ] = ASpeed; + if( ! Enabled ) + return; + + byte AValue = ASpeed * 126; + + if( AIndex ) + AValue += 128; + + else + ++ AValue; + + SendValue( AValue ); + } + + void SendValue( byte AValue ) + { + SlaveSelectOutputPin.SendValue( true ); + + FSerial.GetStream().write( AValue ); + + if( SlaveSelectOutputPin.IsConnected() ) + { + delayMicroseconds( 50 ); + SlaveSelectOutputPin.SendValue( false ); + } + } + + protected: + virtual void SystemStart() override + { + SlaveSelectOutputPin.SendValue( false ); + inherited::SystemStart(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class SabertoothDualMotorPacket : public SabertoothDualMotorBasic + { + typedef SabertoothDualMotorBasic inherited; + +/* + public: + class Motor : public OpenWire::Object + { + public: + OpenWire::SinkPin InputPin; + protected: + bool FEnabled; + + protected: + SabertoothDualMotorPacket &FOwner; + int FIndex; + float FSpeed; + + public: + void SetEnabled( bool AValue ) + { + if( AValue == FEnabled ) + return; + + FEnabled = AValue; + if( FEnabled ) + SendStart(); + + else + SendStop(); + } + + protected: + virtual void SendStart() + { + byte AValue = FSpeed * 255 + 0.5; + byte ACommand = FIndex << 2; // 0 or 4 + if( ( AValue & B10000000 ) == 0 ) + ACommand |= 1; + + FOwner.SendCommand( ACommand, AValue & B01111111 ); + } + + virtual void SendStop() + { + } + + protected: + void DoMotorReceive( void *_Data ) + { + float ASpeed = constrain( *(float *)_Data, 0, 1 ); + if( ASpeed == FSpeed ) + return; + + FSpeed = ASpeed; + if( Enabled ) + SendStart(); + } + + public: + Motor( SabertoothDualMotorPacket &AOwner, int AIndex ) : + FOwner( AOwner ), + FIndex( AIndex ), + FEnabled( true ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Motor::DoMotorReceive ); + } + }; +*/ + public: + byte Address = 128; + + float MinVoltage = 6.0f; + float MaxVoltage = 25.0; + + byte Ramping = 0; + + bool DirectionalMode = false; + uint16_t SerialTimeout = 0; + byte Deadband = 0; + + public: + void SetMinVoltage( float AValue ) + { + AValue = constrain( AValue, 6.0, 30.0 ); + if( MinVoltage == AValue ) + return; + + MinVoltage = AValue; + SendCommand( 2, ( MinVoltage - 6 ) * 5 ); + } + + void SetMaxVoltage( float AValue ) + { + AValue = constrain( AValue, 0.0, 25.0 ); + if( MaxVoltage == AValue ) + return; + + MaxVoltage = AValue; + SendCommand( 3, MinVoltage * 5.12 ); + } + + void SetRamping( byte AValue ) + { + AValue = constrain( AValue, 0, 80 ); + if( Ramping == AValue ) + return; + + Ramping = AValue; + SendCommand( 16, Ramping ); + } + + void SetSerialTimeout( uint16_t AValue ) + { + AValue = constrain( AValue, 0, 12700 ); + if( SerialTimeout == AValue ) + return; + + SerialTimeout = AValue; + SendSerialTimeout(); + } + + void SetDeadband( byte AValue ) + { + AValue = constrain( AValue, 0, 127 ); + if( Deadband == AValue ) + return; + + Deadband = AValue; + SendCommand( 17, Deadband ); + } + + protected: + void SendSerialTimeout() + { + SendCommand( 14, (SerialTimeout + 99) / 100 ); + } + + virtual void SendStart() + { + SendStartOne( 0 ); + SendStartOne( 1 ); + } + + void SendStartOne( int AIndex ) + { + int AValue = ( FSpeeds[ AIndex ] * 255 + 0.5 ) - 128; + byte ACommand; + if( DirectionalMode ) + { + if( AIndex == 0 ) + ACommand = 10; + + else + ACommand = 8; + } + + else + ACommand = AIndex << 2; // 0 or 4 + + if( AValue < 0 ) + { + AValue = -AValue; + ACommand |= 1; + } + + SendCommand( ACommand, AValue & B01111111 ); + } + + virtual void SendStop() + { + // Shut down both motors + SendCommand( 0, 0 ); + SendCommand( 4, 0 ); + } + + virtual void SetSpeed( int AIndex, float ASpeed ) + { + ASpeed = constrain( ASpeed, 0, 1 ); + if( ASpeed == FSpeeds[ AIndex ] ) + return; + + FSpeeds[ AIndex ] = ASpeed; + if( Enabled ) + SendStart(); + } + + protected: + void SendCommand(byte ACommand, byte AValue) + { + Stream &AStream = FSerial.GetStream(); + + byte AAddress = Address | B10000000; + AStream.write( AAddress ); + AStream.write( ACommand ); + AStream.write( AValue ); + AStream.write(( AAddress + ACommand + AValue ) & B01111111); + } + + protected: + virtual void SystemStart() + { + if( MinVoltage != 6.0 ) + SendCommand( 2, ( MinVoltage - 6 ) * 5 ); + + if( MaxVoltage != 25.0 ) + SendCommand( 3, MinVoltage * 5.12 ); + + if( Ramping ) + SendCommand( 16, Ramping ); + + if( SerialTimeout ) + SendSerialTimeout(); + + if( Deadband ) + SendCommand( 17, Deadband ); + + inherited::SystemStart(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_SchmittTrigger.h b/libraries/Mitov/Mitov_SchmittTrigger.h new file mode 100644 index 0000000..452494b --- /dev/null +++ b/libraries/Mitov/Mitov_SchmittTrigger.h @@ -0,0 +1,118 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SCHMITT_TRIGGER_h +#define _MITOV_SCHMITT_TRIGGER_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + template class SchmittTrigger : public CommonEnableFilter + { + typedef CommonEnableFilter inherited; + + public: + bool InitialValue : 1; + bool Inverted : 1; + + protected: + T FValue; + T FThreshold; + T FCurrentValue; + + public: + void SetValue( T AValue ) + { + if( FValue == AValue ) + return; + + FValue = AValue; + ProcessOutput(); + } + + void SetThreshold( T AValue ) + { + if( FThreshold == AValue ) + return; + + FThreshold = AValue; + ProcessOutput(); + } + + void SetInverted( bool AValue ) + { + if( Inverted == AValue ) + return; + + Inverted = AValue; + ProcessOutput(); + } + + protected: + void ProcessOutput() + { + if( ! inherited::Enabled ) + return; + + bool AValue; + + if( Inverted ) + { + if( InitialValue ) + AValue = ( FCurrentValue < FValue + FThreshold ); + + else + AValue = ( FCurrentValue < FValue - FThreshold ); + + } + + else + { + if( InitialValue ) + AValue = ( FCurrentValue > FValue - FThreshold ); + + else + AValue = ( FCurrentValue > FValue + FThreshold ); + + } + + if( InitialValue == AValue ) + return; + + InitialValue = AValue; + OutputPin.Notify( &AValue ); + } + + protected: + virtual void DoReceive( void *_Data ) + { + T AValue = *(T*)_Data; + if( AValue == FCurrentValue ) + return; + + FCurrentValue = AValue; + ProcessOutput(); + } + + public: + SchmittTrigger( T AValue, T AThreshold ) : + FValue( AValue ), + FThreshold( AThreshold ), + InitialValue( false ), + Inverted( false ) + { + } + + }; +//--------------------------------------------------------------------------- +} + +#endif \ No newline at end of file diff --git a/libraries/Mitov/Mitov_Servo.h b/libraries/Mitov/Mitov_Servo.h new file mode 100644 index 0000000..02e1ed1 --- /dev/null +++ b/libraries/Mitov/Mitov_Servo.h @@ -0,0 +1,42 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SERVO_h +#define _MITOV_SERVO_h + +#include + +#include + +namespace Mitov +{ + template class MitovServo : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + Servo FServo; + + protected: + virtual void DoReceive( void *_Data ) override + { + float AValue = constrain( *((float *)_Data), 0.0f, 1.0f ) * 180; + FServo.write( AValue ); + } + + virtual void SystemStart() override + { + FServo.attach( PIN_NUMBER ); + inherited::SystemStart(); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_SimpleList.h b/libraries/Mitov/Mitov_SimpleList.h new file mode 100644 index 0000000..500f733 --- /dev/null +++ b/libraries/Mitov/Mitov_SimpleList.h @@ -0,0 +1,264 @@ +// SimpleList.h + +#ifndef _MITOV_SIMPLELIST_h +#define _MITOV_SIMPLELIST_h + +//#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +//#else +//#include "WProgram.h" +//#endif + +#ifndef NULL +#define NULL 0 +#endif + +namespace Mitov +{ + +template +class SimpleList +{ +public: + ~SimpleList() + { + delete[] _list; + _list = NULL; + _size = 0; + } + + void AddCount( int ACount ) + { + for( int i = 0; i < ACount; ++i ) + push_back( T() ); + } + + void SetCount( int ACount ) + { + while( _size < ACount ) + push_back( T() ); + + while( _size > ACount ) + pop_back(); + } + + void SetCount( int ACount, T AValue ) + { + while( _size < ACount ) + push_back( AValue ); + + while( _size > ACount ) + pop_back(); + } + + void push_back(T obj) + { + ++_size; + + T* newBuffer = new T[_size]; + + if( _list ) + { + for (unsigned int i = 0; i < _size - 1; ++i) + newBuffer[i] = _list[i]; + + delete[] _list; + } + + newBuffer[_size - 1] = obj; + _list = newBuffer; + } + + void append(T *obj, int ACount ) + { + if( ! obj ) + return; + + if( !ACount ) + return; + + int AOldSize = _size; + _size += ACount; + + T* newBuffer = new T[_size]; + if( _list ) + { + memcpy( newBuffer, _list, AOldSize * sizeof( T )); + delete[] _list; + } + + memcpy( newBuffer + AOldSize, obj, ACount * sizeof( T )); + + _list = newBuffer; + } + + void push_front(T obj) + { + ++_size; + T* newBuffer = new T[_size]; + + if( _list ) + { + for (unsigned int i = _size - 1; i > 0; --i) + newBuffer[i] = _list[i - 1]; + + delete[] _list; + } + + newBuffer[0] = obj; + _list = newBuffer; + } + + void pop_back() + { + if (empty()) + return; + + --_size; + if (empty()) + { + delete[] _list; + _list = NULL; + return; + } + + T* newBuffer = new T[_size]; + for (unsigned int i = 0; i < _size; ++i) + newBuffer[i] = _list[i]; + + delete[] _list; + _list = newBuffer; + } + + void pop_front( int ACount = 1 ) + { + if (empty()) + return; + + int AOldSize = _size; + _size -= ACount; + if (empty()) + { + delete[] _list; + _list = NULL; + return; + } + + T* newBuffer = new T[_size]; + + memmove( newBuffer, _list + ACount, AOldSize * sizeof( T )); + + delete[] _list; + _list = newBuffer; + } + +/* + void reserve(unsigned int size) + { + if (size <= _size) + return; + + _preAlloc = size; + + T* newBuffer = new T[_preAlloc]; + + for (unsigned int i = 0; i < _size; ++i) + newBuffer[i] = _list[i]; + + delete[] _list; + _list = newBuffer; + } +*/ + typedef T* iterator; + + iterator erase(iterator &itr) + { + if (empty()) + return NULL; + + --_size; + if (empty()) + { + delete[] _list; + _list = NULL; + + return NULL; + } + + T* newBuffer = new T[_size]; + + bool sum = false; + unsigned int pos = 0; + for (unsigned int i = 0; i < _size; ++i) + { + if (_list + i == itr) + { + sum = true; + pos = i; + } + + if (sum) + newBuffer[i] = _list[i + 1]; + + else + newBuffer[i] = _list[i]; + } + + delete[] _list; + _list = newBuffer; + + itr = _list + pos; + + return itr; + } + + inline iterator begin() { return (empty() ? NULL : _list); } + inline iterator end() { return (empty() ? NULL : _list + _size); } + + void clear() + { + if (_list) + { + delete[] _list; + _list = NULL; + } + + _size = 0; + } + + inline bool empty() const { return !_size; } + inline unsigned int size() const { return _size; } + inline operator T*() const { return _list; } + + SimpleList & operator = ( const SimpleList &other ) + { + if( &other == this ) + return *this; + + clear(); + append( other, other.size() ); + + return *this; + } + +protected: + T* _list = nullptr; + unsigned int _size = 0; +}; + +template +class SimpleObjectList : public SimpleList +{ + typedef SimpleList inherited; + +public: + ~SimpleObjectList() + { + for( int i = 0; i < inherited::_size; ++i ) + delete inherited::_list[ i ]; + } +}; + +} // Mitov + +#endif diff --git a/libraries/Mitov/Mitov_SineGenerator.h b/libraries/Mitov/Mitov_SineGenerator.h new file mode 100644 index 0000000..c41a219 --- /dev/null +++ b/libraries/Mitov/Mitov_SineGenerator.h @@ -0,0 +1,70 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SINE_GENERATOR_h +#define _MITOV_SINE_GENERATOR_h + +#include +#include "Mitov_BasicGenerator.h" + +namespace Mitov +{ + class SineAnalogGenerator : public Mitov::BasicFrequencyGenerator + { + typedef Mitov::BasicFrequencyGenerator inherited; + + protected: + virtual void CalculateValue() override + { + FValue = sin( FPhase * 2 * PI ) * Amplitude + Offset; + } + + public: + SineAnalogGenerator() : + inherited( 0.5, 0.5 ) + { + } + }; +//--------------------------------------------------------------------------- + class SineIntegerGenerator : public Mitov::BasicFrequencyGenerator + { + typedef Mitov::BasicFrequencyGenerator inherited; + + protected: + virtual void CalculateValue() override + { + FValue = sin( FPhase * 2 * PI ) * Amplitude + Offset + 0.5; + } + + public: + SineIntegerGenerator() : + inherited( 1000, 0 ) + { + } + }; +//--------------------------------------------------------------------------- + class SineUnsignedGenerator : public Mitov::BasicFrequencyGenerator + { + typedef Mitov::BasicFrequencyGenerator inherited; + + protected: + virtual void CalculateValue() override + { + FValue = sin( FPhase * 2 * PI ) * Amplitude + Offset + 0.5; + } + + public: + SineUnsignedGenerator() : + inherited( 1000, 1000 ) + { + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Snapshot.h b/libraries/Mitov/Mitov_Snapshot.h new file mode 100644 index 0000000..b97da6c --- /dev/null +++ b/libraries/Mitov/Mitov_Snapshot.h @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SNAPSHOT_h +#define _MITOV_SNAPSHOT_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + template class Snapshot : public CommonEnableFilter + { + typedef CommonFilter inherited; + + public: + OpenWire::SinkPin SnapshotInputPin; + + protected: + T_STORE FData; + + protected: + virtual void DoReceive( void *_Data ) override + { + FData = *(T_DATA*)_Data; + } + + protected: + void TakeSnapshot() + { + OutputPin.SendValue( FData ); + } + + protected: + void DoReceiveSnapshot( void *_Data ) + { + if( Enabled ) + TakeSnapshot(); + } + + public: + Snapshot( T_STORE AData ) : + FData( AData ) + { + SnapshotInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Snapshot::DoReceiveSnapshot ); + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_SoftwareSPI.h b/libraries/Mitov/Mitov_SoftwareSPI.h new file mode 100644 index 0000000..e5b51c4 --- /dev/null +++ b/libraries/Mitov/Mitov_SoftwareSPI.h @@ -0,0 +1,65 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SOFTWARE_SPI_h +#define _MITOV_SOFTWARE_SPI_h + +#include +#include + +namespace Mitov +{ + template class VisuinoSoftwareSPI : public Mitov::BasicSPI + { + typedef Mitov::BasicSPI inherited; + + public: + virtual uint16_t transfer16(uint16_t data) + { + shiftOut( MOSI_PIN_NUMBER, CLOCK_PIN_NUMBER, MSBFIRST, data >> 8 ); + shiftOut( MOSI_PIN_NUMBER, CLOCK_PIN_NUMBER, MSBFIRST, data ); + + return 0; + } + + virtual uint8_t transfer(uint8_t data) + { + shiftOut( MOSI_PIN_NUMBER, CLOCK_PIN_NUMBER, MSBFIRST, data ); + + return 0; + } + + virtual void transfer(void *buf, size_t count) + { + for( int i = 0; i < count; ++i ) + shiftOut( MOSI_PIN_NUMBER, CLOCK_PIN_NUMBER, MSBFIRST, ((byte *)buf)[ i ] ); + } + + virtual void beginTransaction(SPISettings settings) + { + } + + virtual void endTransaction() + { + } + + + protected: + virtual void SystemInit() + { + pinMode( MOSI_PIN_NUMBER, OUTPUT ); + pinMode( CLOCK_PIN_NUMBER, OUTPUT ); + + inherited::SystemInit(); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_SoftwareSerial.h b/libraries/Mitov/Mitov_SoftwareSerial.h new file mode 100644 index 0000000..9874fb7 --- /dev/null +++ b/libraries/Mitov/Mitov_SoftwareSerial.h @@ -0,0 +1,99 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SOFTWARE_SERIAL_h +#define _MITOV_SOFTWARE_SERIAL_h + +#include +#include + +namespace Mitov +{ + template class VisuinoSoftwareSerial : public Mitov::BasicSerialPort + { + typedef Mitov::BasicSerialPort inherited; + + public: + OpenWire::SourcePin OutputPin; + + public: + unsigned Speed = 9600; + + protected: + SoftwareSerial *FSerial = nullptr; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateSerial(); + } + + public: + virtual Stream &GetStream() { return *FSerial; } + + protected: + void UpdateSerial() + { + if( Enabled ) + { + if( ! FSerial ) + { + FSerial = new SoftwareSerial( RX_PIN_NUMBER, TX_PIN_NUMBER ); + FSerial->begin( Speed ); + } + } + else + { + if( FSerial ) + { + delete FSerial; + FSerial = nullptr; + } + } + } + + protected: + virtual void SystemInit() + { + UpdateSerial(); + + inherited::SystemInit(); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( Enabled ) + { + int AData = FSerial->read(); + if( AData >= 0 ) + { + unsigned char AByte = AData; + OutputPin.SendValue( Mitov::TDataBlock( 1, &AByte )); +// OutputPin.Notify( &AByte ); + } + } + + inherited::SystemLoopBegin( currentMicros ); + } + +/* + virtual ~VisuinoSoftwareSerial() + { + if( FSerial ) + delete FSerial; + } +*/ + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_SpeedToClock.h b/libraries/Mitov/Mitov_SpeedToClock.h new file mode 100644 index 0000000..4b43ff9 --- /dev/null +++ b/libraries/Mitov/Mitov_SpeedToClock.h @@ -0,0 +1,88 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SPEED_TO_CLOCK_h +#define _MITOV_SPEED_TO_CLOCK_h + +#include + +namespace Mitov +{ + class SpeedToClock : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + OpenWire::SourcePin DirectionOutputPin; + OpenWire::SourcePin ClockOutputPin; + + public: + bool Enabled = true; + float MaxFrequency = 100.0f; + + protected: + unsigned long FLastTime = 0; + unsigned long FPeriod = 0; +// bool FDirection; + bool FSendOutput = false; + + protected: +/* + virtual void CalculateFields() + { + FPeriod = ( (( 1 / Frequency ) * 1000000 ) + 0.5 ); + } +*/ + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ! FSendOutput ) + FLastTime = currentMicros; + + else + while( currentMicros - FLastTime >= FPeriod ) + { + if( Enabled ) + ClockOutputPin.Notify( NULL ); + + FLastTime += FPeriod; + } + + inherited::SystemLoopBegin( currentMicros ); + } + + virtual void SystemStart() override + { + inherited::SystemStart(); + FLastTime = micros(); + } + + protected: + virtual void DoReceive( void *_Data ) override + { + float ASpeed = constrain( *(float *)_Data, 0.0, 1.0 ); + float AFrequency = abs( ASpeed - 0.5 ) * 2; + FSendOutput = ( AFrequency != 0 ); + if( FSendOutput ) + { + AFrequency *= MaxFrequency; + FPeriod = ( (( 1 / AFrequency ) * 1000000 ) + 0.5 ); + } + + else + FPeriod = 0; + + bool ADirection = ASpeed > 0.5; + + DirectionOutputPin.Notify( &ADirection ); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_SpeedToSpeedAndDirection.h b/libraries/Mitov/Mitov_SpeedToSpeedAndDirection.h new file mode 100644 index 0000000..6bad54f --- /dev/null +++ b/libraries/Mitov/Mitov_SpeedToSpeedAndDirection.h @@ -0,0 +1,120 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SPEED_TO_SPEED_AND_DIRECTION_h +#define _MITOV_SPEED_TO_SPEED_AND_DIRECTION_h + +#include + +namespace Mitov +{ + class SpeedToSpeedAndDirection : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + OpenWire::SourcePin DirectionOutputPin; + OpenWire::SourcePin SpeedOutputPin; + + public: + bool Enabled : 1; + bool InverseForward : 1; + bool InverseReverse : 1; + + public: + void SetEnabled( bool AValue ) + { + if( Enabled == AValue ) + return; + + Enabled = AValue; + UpdateOutputs(); + } + + void SetInverseForward( bool AValue ) + { + if( InverseForward == AValue ) + return; + + InverseForward = AValue; + UpdateOutputs(); + } + + void SetInverseReverse( bool AValue ) + { + if( InverseReverse == AValue ) + return; + + InverseReverse = AValue; + UpdateOutputs(); + } + + protected: + float FCurrentSpeed = 0.5f; + + protected: + virtual void DoReceive( void *_Data ) + { + float ASpeed = constrain( *(float *)_Data, 0.0, 1.0 ); + if( FCurrentSpeed == ASpeed ) + return; + + FCurrentSpeed = ASpeed; + UpdateOutputs(); + } + + void UpdateOutputs() + { + if( Enabled ) + { + float AOutSpeed = abs( FCurrentSpeed - 0.5 ) * 2; + bool ADirection = FCurrentSpeed > 0.5; + + if( ADirection ) + { + if( InverseForward ) + AOutSpeed = 1 - AOutSpeed; + } + + else + { + if( InverseReverse ) + AOutSpeed = 1 - AOutSpeed; + } + + SpeedOutputPin.Notify( &AOutSpeed ); + DirectionOutputPin.Notify( &ADirection ); + } + + else + { + SpeedOutputPin.SendValue( 0 ); + DirectionOutputPin.SendValue( false ); + } + } + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + UpdateOutputs(); + } + + public: + SpeedToSpeedAndDirection() : + Enabled( true ), + InverseForward( false ), + InverseReverse( false ) + { + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_SquareGenerator.h b/libraries/Mitov/Mitov_SquareGenerator.h new file mode 100644 index 0000000..710725b --- /dev/null +++ b/libraries/Mitov/Mitov_SquareGenerator.h @@ -0,0 +1,40 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_SQUARE_GENERATOR_h +#define _MITOV_SQUARE_GENERATOR_h + +#include +#include "Mitov_BasicGenerator.h" + +namespace Mitov +{ + template class TypedSquareGenerator : public Mitov::AsymmetricGenerator + { + typedef Mitov::AsymmetricGenerator inherited; + + protected: + virtual void CalculateValue() override + { + if( inherited::FPhase < 0.5 + inherited::Asymmetry / 2 ) + inherited::FValue = inherited::Offset - inherited::Amplitude; + + else + inherited::FValue = inherited::Offset + inherited::Amplitude; + + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Steering_Differential.h b/libraries/Mitov/Mitov_Steering_Differential.h new file mode 100644 index 0000000..c54a98e --- /dev/null +++ b/libraries/Mitov/Mitov_Steering_Differential.h @@ -0,0 +1,97 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_STEERING_DIFFERENTIAL_h +#define _MITOV_STEERING_DIFFERENTIAL_h + +#include + +namespace Mitov +{ + class SteeringDifferential : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + OpenWire::SinkPin SteeringInputPins[ 2 ]; + OpenWire::SourcePin MotorsOutputPins[ 2 ]; + + protected: + float FDirection = 0.5f; + float FSpeed = 0.5f; + + protected: + void UpdateMotors() + { + float ADirOffset = FDirection - 0.5; + + float ALeftMotor = FSpeed + ADirOffset; + float ARightMotor = FSpeed - ADirOffset; + + if( ALeftMotor > 1.0 ) + { + ARightMotor -= ( ALeftMotor - 1 ); + ALeftMotor = 1.0; + } + + else if( ALeftMotor < 0.0 ) + { + ARightMotor -= ALeftMotor; + ALeftMotor = 0.0; + } + + else if( ARightMotor > 1.0 ) + { + ALeftMotor -= ( ARightMotor - 1 ); + ARightMotor = 1.0; + } + + else if( ARightMotor < 0.0 ) + { + ALeftMotor -= ARightMotor; + ARightMotor = 0.0; + } + + MotorsOutputPins[ 0 ].Notify( &ALeftMotor ); + MotorsOutputPins[ 1 ].Notify( &ARightMotor ); + } + + protected: + void DoDirectionReceive( void *_Data ) + { + float AValue = constrain( *(float *)_Data, 0, 1 ); + if( FDirection == AValue ) + return; + + FDirection = AValue; + UpdateMotors(); + } + + void DoSpeedReceive( void *_Data ) + { + float AValue = constrain( *(float *)_Data, 0, 1 ); + if( FSpeed == AValue ) + return; + + FSpeed = AValue; + UpdateMotors(); + } + + public: + SteeringDifferential() + { + SteeringInputPins[ 0 ].SetCallback( this, (OpenWire::TOnPinReceive)&SteeringDifferential::DoDirectionReceive ); + SteeringInputPins[ 1 ].SetCallback( this, (OpenWire::TOnPinReceive)&SteeringDifferential::DoSpeedReceive ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Stepper.h b/libraries/Mitov/Mitov_Stepper.h new file mode 100644 index 0000000..75cc68c --- /dev/null +++ b/libraries/Mitov/Mitov_Stepper.h @@ -0,0 +1,154 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_STEPPER_h +#define _MITOV_STEPPER_h + +#include + +namespace Mitov +{ + +/* + enum StepperMotorType = + { + smtDirectional, + smtFull2Wire, + smtFull3Wire, + smtFull4Wire, + smtHalf3Wire, + smtHalf4Wire + }; +*/ + const unsigned char C_StepperBits4[] = + { + 0b1100, + 0b0110, + 0b0011, + 0b1001 + }; + + const unsigned char C_StepperBits8[] = + { + 0b1000, + 0b1100, + 0b0100, + 0b0110, + 0b0010, + 0b0011, + 0b0001, + 0b1001 + }; +//--------------------------------------------------------------------------- + template class BasicStepperMotor : public OpenWire::Component + { + public: + OpenWire::SourcePin OutputPins[ C_NUMOUTPINS ]; + OpenWire::SinkPin StepInputPin; + + protected: + unsigned long FLastTime = 0; + uint8_t FStep : 4; + + public: + bool Enabled : 1; + bool Reversed : 1; + float StepsPerSecond = 300.f; + + protected: + virtual void UpdatePins() = 0; + + void DoStepReceive( void *_Data ) + { + Step(); + } + + void SetPinsValue( unsigned char AValue ) + { + for( int i = 0; i < C_NUMOUTPINS; ++i ) + { + bool APinValue = ( AValue & 1 ); + OutputPins[ i ].Notify( &APinValue ); + AValue >>= 1; + } + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( !Enabled ) + FLastTime = currentMicros; + + else + { + unsigned long APeriod = ( 1000000 / abs( StepsPerSecond )) + 0.5; + if( ( currentMicros - FLastTime ) >= APeriod ) + { + FLastTime += APeriod; + if(( StepsPerSecond > 0 ) ^ Reversed ) + ++FStep; + + else + --FStep; + + UpdatePins(); + } + } + } + + public: + BasicStepperMotor() : + Enabled( true ), + Reversed( true ), + FStep( 0 ) + { + StepInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicStepperMotor::DoStepReceive ); + } + + public: + void Step() + { + if( Reversed ) //^ ( StepsPerSecond > 0 ) ) + --FStep; + + else + ++FStep; + + UpdatePins(); + } + }; +//--------------------------------------------------------------------------- + class StepperMotorDirectional : public BasicStepperMotor<2> + { + }; +//--------------------------------------------------------------------------- + template class BasicStepperMotorHalfStep : public BasicStepperMotor + { + public: + bool HalfStep = true; + + }; +//--------------------------------------------------------------------------- + class StepperMotor2Wire : public BasicStepperMotorHalfStep<2> + { + }; +//--------------------------------------------------------------------------- + class StepperMotor4Wire : public BasicStepperMotorHalfStep<4> + { + protected: + virtual void UpdatePins() override + { + unsigned char AValue = HalfStep ? C_StepperBits8[ FStep & 0b0111 ] : C_StepperBits4[ FStep & 0b0011 ]; + SetPinsValue( AValue ); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_StringPrint.h b/libraries/Mitov/Mitov_StringPrint.h new file mode 100644 index 0000000..039e835 --- /dev/null +++ b/libraries/Mitov/Mitov_StringPrint.h @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_STRING_PRINT_h +#define _MITOV_STRING_PRINT_h + +#include + +namespace Mitov +{ + class StringPrint : public Print + { + typedef Print inherited; + + public: + String Value; + + public: + virtual size_t write( uint8_t AChar ) + { + Value += (char)AChar; + return 1; + } + }; +//--------------------------------------------------------------------------- + class BufferPrint : public Print + { + typedef Print inherited; + + public: + Mitov::SimpleList Value; + + public: + virtual size_t write( uint8_t AChar ) + { + Value.push_back( AChar ); + return 1; + } + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_Structure.h b/libraries/Mitov/Mitov_Structure.h new file mode 100644 index 0000000..47eeb3a --- /dev/null +++ b/libraries/Mitov/Mitov_Structure.h @@ -0,0 +1,321 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_STRUCTURE_h +#define _MITOV_STRUCTURE_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class BasicMakeStructureElement : public OpenWire::Component + { + public: + virtual bool GetIsPopulated() { return true; } + virtual bool GetIsModified() { return false; } + virtual void ClearModified() {} + virtual void GetData( unsigned char *&AData, unsigned char &AOffset ) {} + }; +//--------------------------------------------------------------------------- + class BasicSplitStructureElement : public OpenWire::Component + { + public: + virtual void Extract( unsigned char *&AData, unsigned char &AOffset ) {} + + }; +//--------------------------------------------------------------------------- + template class BasicTypedStructureSinkElement : public BasicMakeStructureElement + { + public: + OpenWire::SinkPin InputPin; + + protected: + T FValue = 0; + bool FPopulated : 1; + bool FModified : 1; + +/* + public: + T InitialValue; + + virtual void SystemInit() + { + inherited::SystemInit(); + FValue = InitialValue; + } +*/ + public: + virtual bool GetIsPopulated() override + { + return FPopulated; + } + + virtual bool GetIsModified() override + { + return FModified; + } + + virtual void ClearModified() override + { + FModified = false; + } + + virtual void GetData( unsigned char *&AData, unsigned char &AOffset ) override + { + if( AOffset ) + { +// Serial.println( "TTT" ); + ++AData; + AOffset = 0; + } + +#ifdef VISUINO_ESP8266 + memcpy( AData, &FValue, sizeof( T )); +#else + *(T*)AData = FValue; +#endif +// memcpy( AData, &FValue, sizeof( T )); + AData += sizeof( T ); + FModified = false; + } + + protected: + virtual void DoReceive( void *_Data ) + { + T AValue = *(T*)_Data; + FPopulated = true; + if( AValue == FValue ) + return; + + FValue = AValue; + FModified = true; + } + + public: + BasicTypedStructureSinkElement() : + FPopulated( false ), + FModified( false ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicTypedStructureSinkElement::DoReceive ); + } + + }; +//--------------------------------------------------------------------------- + template class BasicTypedStructureSourceElement : public BasicSplitStructureElement + { + public: + OpenWire::SourcePin OutputPin; + + public: + virtual void Extract( unsigned char *&AData, unsigned char &AOffset ) override + { + if( AOffset ) + { + ++ AData; + AOffset = 0; + } + + T AValue; + AValue = *((T *)AData ); + OutputPin.Notify( &AValue ); + + AData += sizeof( T ); + } + }; +//--------------------------------------------------------------------------- + class DigitalStructureSourceElement : public BasicTypedStructureSourceElement + { + public: +/* + virtual int Start( bool &AAllign ) override + { + AAllign = false; + return 1; + } +*/ + virtual void Extract( unsigned char *&AData, unsigned char &AOffset ) override + { + unsigned char AValue = *AData; + bool ABoolValue = (( AValue & ( 1 << AOffset )) != 0 ); + ++AOffset; + + if( AOffset == 8 ) + { + AOffset = 0; + ++AData; + } + + OutputPin.Notify( &ABoolValue ); + } + }; +//--------------------------------------------------------------------------- + class DigitalStructureSinkElement : public BasicTypedStructureSinkElement + { + public: + virtual void GetData( unsigned char *&AData, unsigned char &AOffset ) override + { + *AData &= 0xFF >> ( 8 - AOffset ); // Zero the upper bits + if( FValue ) + *AData |= 1 << AOffset; // Set the bit + + ++AOffset; + if( AOffset == 8 ) + { + AOffset = 0; + ++AData; + } + } + }; +//--------------------------------------------------------------------------- + template class MakeStructure : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: + Mitov::SimpleObjectList Elements; + + bool OnlyModified = false; + + protected: + byte FBuffer[ T_BUFFER_SIZE ]; + + protected: + virtual void DoClockReceive( void *_Data ) override + { +// Serial.println( "++++++" ); + int AElementCount = Elements.size(); + if( OnlyModified ) + { + bool AModified = false; + for( int i = 0; i < AElementCount; ++i ) + if( Elements[ i ]->GetIsModified() ) + { + AModified = true; + break; + } + + if( !AModified ) + return; + } + + else + { + for( int i = 0; i < AElementCount; ++i ) + if( ! Elements[ i ]->GetIsPopulated() ) + return; + + } + + byte *ADataPtr = FBuffer; + unsigned char AOffset = 0; + for( int i = 0; i < AElementCount; ++i ) + Elements[ i ]->GetData( ADataPtr, AOffset ); + +// Serial.println( ASize ); + + + OutputPin.SendValue( Mitov::TDataBlock( T_BUFFER_SIZE, FBuffer )); + +/* + ADataPtr = FBuffer; + int ASize = T_BUFFER_SIZE; + + while( ASize-- ) + OutputPin.Notify( ADataPtr++ ); +*/ + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( !ClockInputPin.IsConnected() ) + DoClockReceive( NULL ); + +// delay( 1000 ); + inherited::SystemLoopBegin( currentMicros ); + } +/* + virtual void SystemStart() + { + FBufferSize = 0; + FAllElements.push_back( &HeadMarker ); + for( int i = 0; i < Elements.size(); ++i ) + FAllElements.push_back( Elements[ i ] ); + + FAllElements.push_back( &Checksum ); + + for( int i = 0; i < FAllElements.size(); ++i ) + { + bool AAlligned = false; + FBufferSize += FAllElements[ i ]->GetSize( AAlligned ); +// Serial.println( FBufferSize ); + if( AAlligned ) + { + FBufferSize = ( FBufferSize + 7 ) / 8; + FBufferSize *= 8; + } + + } + +// Serial.println( FBufferSize ); + + FBufferSize = ( FBufferSize + 7 ) / 8; + FBuffers[ 0 ] = new unsigned char[ FBufferSize * 2 ]; + FBuffers[ 1 ] = new unsigned char[ FBufferSize * 2 ]; + + inherited::SystemStart(); + } +*/ + }; +//--------------------------------------------------------------------------- + template class SplitStructure : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + public: + Mitov::SimpleObjectList Elements; + + protected: + byte FBuffer[ T_BUFFER_SIZE ]; + byte *FDataPtr = FBuffer; + + protected: + virtual void DoReceive( void *_Data ) + { + Mitov::TDataBlock ABlock = *(Mitov::TDataBlock *)_Data; + while( ABlock.Size -- ) + { + *FDataPtr ++ = *ABlock.Data ++; + + if( ( FDataPtr - FBuffer ) >= T_BUFFER_SIZE ) + { + unsigned char AOffset = 0; + byte *ADataPtr = FBuffer; + for( int i = 0; i < Elements.size(); ++i ) + Elements[ i ]->Extract( ADataPtr, AOffset ); + + FDataPtr = FBuffer; + } + } + } + +/* + virtual void SystemStart() override + { + FDataPtr = FBuffer; + inherited::SystemStart(); + } +*/ + }; +//--------------------------------------------------------------------------- + +} + +#endif \ No newline at end of file diff --git a/libraries/Mitov/Mitov_TVOut_RCA.h b/libraries/Mitov/Mitov_TVOut_RCA.h new file mode 100644 index 0000000..9fa2812 --- /dev/null +++ b/libraries/Mitov/Mitov_TVOut_RCA.h @@ -0,0 +1,638 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_TVOUT_RCA_h +#define _MITOV_TVOUT_RCA_h + +#include +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class TVOut_RCA_Intf; +//--------------------------------------------------------------------------- + class TVOutRCAElementBasic : public OpenWire::Component + { + typedef OpenWire::Component inherited; + + public: + virtual void Render() = 0; + virtual void TVBegin() = 0; + + public: // Public for the print access + Mitov::TVOut_RCA_Intf &FOwner; + + public: + TVOutRCAElementBasic( Mitov::TVOut_RCA_Intf &AOwner ); + + }; +//--------------------------------------------------------------------------- + class TVOut_RCA_Intf + { + public: + virtual void RegisterRender( TVOutRCAElementBasic *AItem ) {} + virtual bool IsEnabled() = 0; + virtual TVout &GetTV() = 0; + + virtual void TV_shift( bool _InVertical, int32_t _Distance ) = 0; + virtual void TV_draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, char c) = 0; + virtual void TV_bitmap(uint8_t x, uint8_t y, const unsigned char * bmp, uint16_t i = 0, uint8_t width = 0, uint8_t lines = 0) = 0; + virtual void TV_set_cursor(uint8_t, uint8_t) = 0; + virtual void TV_draw_circle(uint8_t x0, uint8_t y0, uint8_t radius, char c, char fc = -1) = 0; + virtual void TV_draw_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, char c, char fc = -1) = 0; + virtual void TV_set_pixel(uint8_t x, uint8_t y, char c) = 0; + virtual unsigned char TV_get_pixel(uint8_t x, uint8_t y) = 0; + + }; +//--------------------------------------------------------------------------- + enum TArduinoTVOutRCAElementColor { tvcBlack, tvcWhite, tvcInvert, tvcNone = -1 }; +//--------------------------------------------------------------------------- + class TVOutRCAElementClocked : public Mitov::TVOutRCAElementBasic, public Mitov::ClockingSupport + { + typedef Mitov::TVOutRCAElementBasic inherited; + + public: + virtual void DoClockReceive( void *_Data ) override + { + Render(); + } + + public: + virtual void TVBegin() override + { + if( ! ClockInputPin.IsConnected() ) + Render(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementColored : public TVOutRCAElementClocked + { + typedef Mitov::TVOutRCAElementClocked inherited; + + public: + TArduinoTVOutRCAElementColor Color = tvcWhite; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementFillColored : public TVOutRCAElementClocked + { + typedef Mitov::TVOutRCAElementClocked inherited; + + public: + TArduinoTVOutRCAElementColor BorderColor = tvcWhite; + TArduinoTVOutRCAElementColor FillColor = tvcBlack; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOut_RCA : public OpenWire::Component, public TVOut_RCA_Intf + { + typedef OpenWire::Component inherited; + + public: + bool Enabled : 1; + bool IsPAL : 1; + int32_t Width = 128; + int32_t Height = 96; + + public: + void SetEnabled( bool AVelue ) + { + if( Enabled == AVelue ) + return; + + Enabled = AVelue; + + if( Enabled ) + TVBegin(); + + else + FTV.end(); + } + + public: + TVout FTV; + + protected: + Mitov::SimpleList FElements; + + public: + virtual void RegisterRender( TVOutRCAElementBasic *AItem ) override + { + FElements.push_back( AItem ); + } + + virtual void TV_shift( bool _InVertical, int32_t _Distance ) override + { + if( ! Enabled ) + return; + + uint8_t ADistance = abs( _Distance ); + uint8_t ADirection; + if( _InVertical ) + { + if( _Distance < 0 ) + ADirection = UP; + + else + ADirection = DOWN; + + } + else + { + if( _Distance < 0 ) + ADirection = LEFT; + + else + ADirection = RIGHT; + + } + + FTV.shift( ADistance, ADirection ); + } + + virtual void TV_draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, char c) override + { + if( Enabled ) + FTV.draw_line( x0, y0, x1, y1, c ); + } + + virtual void TV_draw_circle(uint8_t x0, uint8_t y0, uint8_t radius, char c, char fc = -1) override + { + if( Enabled ) + FTV.draw_circle( x0, y0, radius, c, fc ); + } + + virtual void TV_draw_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, char c, char fc = -1) override + { + if( Enabled ) + FTV.draw_rect( x0, y0, w, h, c, fc ); + } + + virtual void TV_set_pixel(uint8_t x, uint8_t y, char c) override + { + if( Enabled ) + FTV.set_pixel( x, y, c ); + } + + virtual unsigned char TV_get_pixel(uint8_t x, uint8_t y) override + { + return FTV.get_pixel( x, y ); + } + + virtual void TV_bitmap(uint8_t x, uint8_t y, const unsigned char * bmp, uint16_t i = 0, uint8_t width = 0, uint8_t lines = 0) override + { + if( Enabled ) + FTV.bitmap( x, y, bmp, i, width, lines ); + } + + virtual void TV_set_cursor( uint8_t x, uint8_t y ) override + { + if( Enabled ) + FTV.set_cursor( x, y ); + } + + public: + virtual bool IsEnabled() override + { + return Enabled; + } + + virtual TVout &GetTV() override + { + return FTV; + } + + protected: + void TVBegin() + { + FTV.begin( IsPAL ? PAL : NTSC, Width, Height ); + + for( int i = 0; i < FElements.size(); i ++ ) + FElements[ i ]->TVBegin(); + +// FTV.select_font( font4x6 ); + } + + protected: + virtual void SystemInit() override + { + if( Enabled ) + FTV.begin( IsPAL ? PAL : NTSC, Width, Height ); + + inherited::SystemInit(); + } + + virtual void SystemStart() override + { + if( Enabled ) + for( int i = 0; i < FElements.size(); i ++ ) + FElements[ i ]->TVBegin(); + + inherited::SystemStart(); + } + + public: + TVOut_RCA() : + IsPAL( false ), + Enabled( true ) + { + } + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementFillScreen : public TVOutRCAElementColored + { + typedef Mitov::TVOutRCAElementColored inherited; + + public: + TArduinoTVOutRCAElementColor Color = tvcBlack; + + public: + virtual void Render() override + { + if( FOwner.IsEnabled() ) + FOwner.GetTV().fill( (int)Color ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementPlayTone : public TVOutRCAElementClocked + { + typedef Mitov::TVOutRCAElementClocked inherited; + + public: + unsigned int Frequency = 1760; + unsigned long Duration = 1000; + + public: + virtual void Render() override + { + if( FOwner.IsEnabled() ) + { + if( Frequency == 0 ) + FOwner.GetTV().noTone(); + + else + FOwner.GetTV().tone( Frequency, Duration ); + } + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementDrawCircle : public TVOutRCAElementFillColored + { + typedef Mitov::TVOutRCAElementFillColored inherited; + + public: + int32_t X = 10; + int32_t Y = 10; + int32_t Radius = 10; + + public: + virtual void Render() override + { + FOwner.TV_draw_circle( X, Y, Radius, (int)BorderColor, (int)FillColor ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementDrawRectangle : public TVOutRCAElementFillColored + { + typedef Mitov::TVOutRCAElementFillColored inherited; + + public: + int32_t X = 0; + int32_t Y = 0; + int32_t Width = 10; + int32_t Height = 10; + + public: + virtual void Render() override + { + FOwner.TV_draw_rect( X, Y, Width, Height, (int)BorderColor, (int)FillColor ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementDrawLine : public TVOutRCAElementColored + { + typedef Mitov::TVOutRCAElementColored inherited; + + public: + int32_t X1 = 0; + int32_t Y1 = 0; + int32_t X2 = 10; + int32_t Y2 = 10; + + public: + virtual void Render() override + { + FOwner.TV_draw_line( X1, Y1, X2, Y2, (int)Color ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementDrawPixel : public TVOutRCAElementColored + { + typedef Mitov::TVOutRCAElementColored inherited; + + public: + int32_t X = 0; + int32_t Y = 0; + + public: + virtual void Render() override + { + FOwner.TV_set_pixel( X, Y, (int)Color ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementShiftScreen : public Mitov::TVOutRCAElementClocked + { + typedef Mitov::TVOutRCAElementClocked inherited; + + public: + int32_t Distance = 1; + bool InVertical = false; + + public: + virtual void Render() override + { + FOwner.TV_shift( InVertical, Distance ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementBasicPosition : public Mitov::TVOutRCAElementClocked + { + typedef Mitov::TVOutRCAElementClocked inherited; + + public: + OpenWire::SourcePin OutputPin; + + public: + int32_t X = 0; + int32_t Y = 0; + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementDrawScene : public Mitov::TVOutRCAElementBasicPosition, public TVOut_RCA_Intf + { + typedef Mitov::TVOutRCAElementBasicPosition inherited; + + protected: + Mitov::SimpleList FElements; + + public: + virtual void RegisterRender( TVOutRCAElementBasic *AItem ) + { + FElements.push_back( AItem ); + } + + virtual bool IsEnabled() + { + return FOwner.IsEnabled(); + } + + virtual TVout &GetTV() + { + return FOwner.GetTV(); + } + + virtual void TV_shift( bool _InVertical, int32_t _Distance ) + { + FOwner.TV_shift( _InVertical, _Distance ); + } + + virtual void TV_draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, char c) + { + FOwner.TV_draw_line( X + x0, Y + y0, X + x1, Y + y1, c ); + } + + virtual void TV_bitmap(uint8_t x, uint8_t y, const unsigned char * bmp, uint16_t i = 0, uint8_t width = 0, uint8_t lines = 0) + { + FOwner.TV_bitmap( X + x , Y + y, bmp, i, width, lines ); + } + + virtual void TV_set_cursor( uint8_t x, uint8_t y ) + { + FOwner.TV_set_cursor( X + x , Y + y ); + } + + virtual void TV_draw_circle(uint8_t x0, uint8_t y0, uint8_t radius, char c, char fc = -1) + { + FOwner.TV_draw_circle( X + x0, Y + y0, radius, c, fc ); + } + + virtual void TV_draw_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, char c, char fc = -1) + { + FOwner.TV_draw_rect( X + x0, Y + y0, w, h, c, fc ); + } + + virtual void TV_set_pixel(uint8_t x, uint8_t y, char c) + { + FOwner.TV_set_pixel( X + x , Y + y, c ); + } + + virtual unsigned char TV_get_pixel(uint8_t x, uint8_t y) + { + return FOwner.TV_get_pixel( X + x , Y + y ); + } + + public: + virtual void Render() override + { + for( int i = 0; i < FElements.size(); i ++ ) + FElements[ i ]->Render(); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementCheckPixel : public Mitov::TVOutRCAElementBasicPosition + { + typedef Mitov::TVOutRCAElementBasicPosition inherited; + + public: + OpenWire::SourcePin OutputPin; + + public: + virtual void Render() override + { + if( FOwner.IsEnabled() ) + OutputPin.SendValue( FOwner.TV_get_pixel( X, Y ) > 0 ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementDrawBitmap : public Mitov::TVOutRCAElementBasicPosition + { + typedef Mitov::TVOutRCAElementBasicPosition inherited; + + public: + uint8_t Width; + uint8_t Height; + + const unsigned char *_Bytes; + + public: + virtual void Render() override + { + FOwner.TV_bitmap( X, Y, _Bytes, 0, Width, Height ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementSetCursor : public Mitov::TVOutRCAElementBasicPosition + { + typedef Mitov::TVOutRCAElementBasicPosition inherited; + + public: + virtual void Render() override + { + FOwner.TV_set_cursor( X, Y ); + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementPrintText : public Mitov::TVOutRCAElementBasic + { + typedef Mitov::TVOutRCAElementBasic inherited; + + public: + bool NewLine = true; + + protected: + const unsigned char *FFont; + + public: + template void Print( T AValue ) + { + if( FOwner.IsEnabled() ) + { + FOwner.GetTV().select_font( FFont ); + if( NewLine ) + FOwner.GetTV().println( AValue ); + + else + FOwner.GetTV().print( AValue ); + } + } + + public: + TVOutRCAElementPrintText( Mitov::TVOut_RCA_Intf &AOwner, const unsigned char * AFont ) : + inherited( AOwner ), + FFont( AFont ) + { + } + + }; +//--------------------------------------------------------------------------- + class TVOutRCAElementTextAt : public Mitov::TVOutRCAElementClocked + { + typedef Mitov::TVOutRCAElementClocked inherited; + + public: + int32_t X = 0; + int32_t Y = 0; + String InitialValue; + + protected: + const unsigned char *FFont; + String FValue; + + public: + template void Print( T AValue ) + { + FValue = String( AValue ); + } + + public: + virtual void Render() override + { + if( FOwner.IsEnabled() ) + { + FOwner.GetTV().select_font( FFont ); + FOwner.TV_set_cursor( X, Y ); + FOwner.GetTV().print( FValue.c_str() ); + } + } + + protected: + virtual void SystemInit() + { + FValue = InitialValue; + inherited::SystemInit(); + } + + public: + TVOutRCAElementTextAt( Mitov::TVOut_RCA_Intf &AOwner, const unsigned char * AFont ) : + inherited( AOwner ), + FFont( AFont ) + { + } + + }; +//--------------------------------------------------------------------------- + TVOutRCAElementBasic::TVOutRCAElementBasic( Mitov::TVOut_RCA_Intf &AOwner ) : + FOwner( AOwner ) + { + FOwner.RegisterRender( this ); + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_TeensySerial.h b/libraries/Mitov/Mitov_TeensySerial.h new file mode 100644 index 0000000..2955d74 --- /dev/null +++ b/libraries/Mitov/Mitov_TeensySerial.h @@ -0,0 +1,161 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_TEENSY_SERIAL_h +#define _MITOV_TEENSY_SERIAL_h + +#include + +namespace Mitov +{ + const long CTeensySerialInits[] = + { + SERIAL_7E1, + SERIAL_7E1, + SERIAL_7O1, + SERIAL_8N1, + SERIAL_8E1, + SERIAL_8O1, + + SERIAL_8N2, + SERIAL_8N2, + SERIAL_8N2, + SERIAL_8N2, + SERIAL_8N2, + SERIAL_8N2 +/* + SERIAL_7E1_RXINV, + SERIAL_7E1_RXINV, + SERIAL_7O1_RXINV, + SERIAL_8N1_RXINV, + SERIAL_8E1_RXINV, + SERIAL_8O1_RXINV, + + SERIAL_8N2_RXINV, + SERIAL_8N2_RXINV, + SERIAL_8N2_RXINV, + SERIAL_8N2_RXINV, + SERIAL_8N2_RXINV, + SERIAL_8N2_RXINV, + + SERIAL_7E1_TXINV, + SERIAL_7E1_TXINV, + SERIAL_7O1_TXINV, + SERIAL_8N1_TXINV, + SERIAL_8E1_TXINV, + SERIAL_8O1_TXINV, + + SERIAL_8N2_TXINV, + SERIAL_8N2_TXINV, + SERIAL_8N2_TXINV, + SERIAL_8N2_TXINV, + SERIAL_8N2_TXINV, + SERIAL_8N2_TXINV, + + SERIAL_7E1_RXINV_TXINV, + SERIAL_7E1_RXINV_TXINV, + SERIAL_7O1_RXINV_TXINV, + SERIAL_8N1_RXINV_TXINV, + SERIAL_8E1_RXINV_TXINV, + SERIAL_8O1_RXINV_TXINV, + + SERIAL_8N2_RXINV_TXINV, + SERIAL_8N2_RXINV_TXINV, + SERIAL_8N2_RXINV_TXINV, + SERIAL_8N2_RXINV_TXINV, + SERIAL_8N2_RXINV_TXINV, + SERIAL_8N2_RXINV_TXINV +*/ +/* +#ifdef SERIAL_9BIT_SUPPORT +#define SERIAL_9N1 0x84 +#define SERIAL_9E1 0x8E +#define SERIAL_9O1 0x8F +#define SERIAL_9N1_RXINV 0x94 +#define SERIAL_9E1_RXINV 0x9E +#define SERIAL_9O1_RXINV 0x9F +#define SERIAL_9N1_TXINV 0xA4 +#define SERIAL_9E1_TXINV 0xAE +#define SERIAL_9O1_TXINV 0xAF +#define SERIAL_9N1_RXINV_TXINV 0xB4 +#define SERIAL_9E1_RXINV_TXINV 0xBE +#define SERIAL_9O1_RXINV_TXINV 0xBF +#endif +*/ + }; +//--------------------------------------------------------------------------- + template class TeensySerialPort : public Mitov::SpeedSerialPort + { + typedef Mitov::SpeedSerialPort inherited; + + public: + TArduinoSerialParity Parity : 3; + unsigned int StopBits : 2; + unsigned int DataBits : 3; + bool InvertedRX : 1; + bool InvertedTX : 1; + + public: + void SetParity( TArduinoSerialParity AValue ) + { + if( Parity == AValue ) + return; + + Parity = AValue; + inherited::RestartPort(); + } + + void SetStopBits( unsigned int AValue ) + { + if( StopBits == AValue ) + return; + + StopBits = AValue; + inherited::RestartPort(); + } + + void SetDataBits( unsigned int AValue ) + { + if( DataBits == AValue ) + return; + + DataBits = AValue; + inherited::RestartPort(); + } + + protected: + virtual void StartPort() + { +// int AIndex = ((int)Parity) * 8 + ( StopBits - 1 ) * 4 + ( DataBits - 5); + int AIndex = ( StopBits - 1 ) * 6 + ( DataBits - 5) * 3 + ((int)Parity); + long AValue = CTeensySerialInits[ AIndex ]; + if( InvertedRX ) + AValue |= 0x10; + + if( InvertedTX ) + AValue |= 0x20; + + T_SERIAL->begin( inherited::Speed, AValue ); + } + + public: + TeensySerialPort() : + Parity( spNone ), + StopBits( 1 ), + DataBits( 8 ), + InvertedRX( false ), + InvertedTX( false ) + { + } + }; +//--------------------------------------------------------------------------- +} // Mitov + +#endif + diff --git a/libraries/Mitov/Mitov_TexasInstruments_Thermometer.h b/libraries/Mitov/Mitov_TexasInstruments_Thermometer.h new file mode 100644 index 0000000..46a4301 --- /dev/null +++ b/libraries/Mitov/Mitov_TexasInstruments_Thermometer.h @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_TEXAS_INSTUMENTS_THERMOMETER_h +#define _MITOV_TEXAS_INSTUMENTS_THERMOMETER_h + +#include + +namespace Mitov +{ + class TexasInstruments_Thermometer : public Mitov::CommonFilter + { + typedef Mitov::CommonFilter inherited; + + public: + bool InFahrenheit = false; + + protected: + virtual void DoReceive( void *_Data ) override + { + float AValue = (*(float *)_Data) * 500; + + if( InFahrenheit ) + AValue = AValue * ( 9.0/5.0 ) + 32.0; + + OutputPin.Notify( &AValue ); + } + + }; + +} + +#endif diff --git a/libraries/Mitov/Mitov_Text.h b/libraries/Mitov/Mitov_Text.h new file mode 100644 index 0000000..54a6e03 --- /dev/null +++ b/libraries/Mitov/Mitov_Text.h @@ -0,0 +1,513 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_TEXT_h +#define _MITOV_TEXT_h + +#include + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class TextValue : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: + String Value; + + protected: + virtual void SystemStart() override + { + inherited::SystemStart(); + OutputPin.Notify( (void *)Value.c_str() ); + } + + virtual void DoClockReceive( void *_Data ) override + { + OutputPin.Notify( (void *)Value.c_str() ); + } + + public: + TextValue( char *AValue ) : + Value( AValue ) + { + } + + }; +//--------------------------------------------------------------------------- + class BindableTextValue : public TextValue + { + typedef TextValue inherited; + + protected: + String OldValue = inherited::Value; + + protected: + virtual void SystemInit() + { + inherited::SystemInit(); + OldValue = inherited::Value; + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( inherited::Value == OldValue ) + return; + + OldValue = inherited::Value; + inherited::OutputPin.Notify( (void *)OldValue.c_str() ); + } + + public: + BindableTextValue( char *AValue ) : + inherited( AValue ), + OldValue( AValue ) + { + } + + }; +//--------------------------------------------------------------------------- + class BasicFormattedText; +//--------------------------------------------------------------------------- + class FormattedTextElementBasic : public OpenWire::Object // : public OpenWire::Component + { +// typedef OpenWire::Component inherited; + protected: + BasicFormattedText &FOwner; + + public: + virtual String GetText() = 0; + + virtual void SystemStart() + { + } + + public: + FormattedTextElementBasic( BasicFormattedText &AOwner ); + + }; +//--------------------------------------------------------------------------- + class BasicFormattedText : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + public: + Mitov::SimpleList FElements; + + protected: + bool FModified = false; + + public: + inline void SetModified() + { + FModified = true; + } + + }; +//--------------------------------------------------------------------------- + template class BasicTypedFormattedText : public Mitov::BasicFormattedText + { + typedef Mitov::BasicFormattedText inherited; + + protected: + struct TStringItem + { + T_STRING Text; + FormattedTextElementBasic *Element; + }; + + protected: + Mitov::SimpleList FReadyElements; + + public: + void AddReadyElement( T_STRING ATextItem, int AIndex ) + { +// Serial.print( "AddElement: " ); Serial.print( ATextItem ); Serial.println( AIndex ); + + TStringItem *AItem = new TStringItem; + AItem->Text = ATextItem; +// Serial.print( "AddElement: " ); Serial.println( AItem->Text ); + if( AIndex < FElements.size() ) + AItem->Element = FElements[ AIndex ]; + + else + AItem->Element = NULL; + + FReadyElements.push_back( AItem ); + +// Serial.println( FReadyElements[ FReadyElements.size() - 1 ]->Text ); +// Serial.println( "DEBUG>>" ); +// for( Mitov::SimpleList::iterator Iter = FReadyElements.begin(); Iter != FReadyElements.end(); ++Iter ) +// Serial.println( ( *Iter )->Text ); + +// Serial.println( "<::iterator Iter = FReadyElements.begin(); Iter != FReadyElements.end(); ++Iter ) + { +// Serial.println( ( *Iter )->Text ); + AText += ( *Iter )->Text; + if( ( *Iter )->Element ) + AText += ( *Iter )->Element->GetText(); + } + +// Serial.println( AText ); + inherited::OutputPin.Notify( (void *)AText.c_str() ); + FModified = false; + } + + protected: + virtual void SystemLoopEnd() override + { + if( FModified ) + if( ! ClockInputPin.IsConnected() ) + ProcessSendOutput(); + + inherited::SystemLoopEnd(); + } + + protected: + virtual void DoClockReceive( void *_Data ) override + { + ProcessSendOutput(); + } + + }; +//--------------------------------------------------------------------------- + class FormattedText_Fixed : public Mitov::BasicTypedFormattedText + { + typedef Mitov::BasicTypedFormattedText inherited; + + public: + void AddNullElement( char *ATextItem ) + { + TStringItem *AItem = new TStringItem; + + AItem->Text = ATextItem; + AItem->Element = NULL; + + inherited::FReadyElements.push_back( AItem ); + } + + protected: + virtual void SystemStart() override + { + for( Mitov::SimpleList::iterator Iter = FElements.begin(); Iter != FElements.end(); ++Iter ) + (*Iter )->SystemStart(); + + inherited::SystemStart(); + ProcessSendOutput(); + } + + }; +//--------------------------------------------------------------------------- + class FormattedText : public Mitov::BasicTypedFormattedText + { + typedef Mitov::BasicTypedFormattedText inherited; + + public: + String Text; + + protected: + void InitElements() + { + FReadyElements.clear(); + String ATextItem; + String AIndexText; + bool AInEscape = false; + +// Serial.println( "INIT" ); +// Serial.println( Text ); +// delay( 1000 ); + + for( int i = 0; i < Text.length(); ++ i ) + { + char AChar = Text[ i ]; + if( AInEscape ) + { + if( AChar >= '0' && AChar <= '9' ) + AIndexText += AChar; + + else + { + if( AChar == '%' ) + { + if( AIndexText.length() == 0 ) + ATextItem += '%'; + + else + { + AddReadyElement( ATextItem, AIndexText.toInt() ); + ATextItem = ""; + } + + } + + else + { + if( AIndexText.length() == 0 ) + ATextItem += '%'; + + else + { + AddReadyElement( ATextItem, AIndexText.toInt() ); + ATextItem = ""; + } + + ATextItem += AChar; + } + + AInEscape = false; + } + } + + else + { + if( AChar == '%' ) + { + AInEscape = true; + AIndexText = ""; + } + + else + ATextItem += AChar; + + } + + } + + if( AInEscape ) + AddReadyElement( ATextItem, AIndexText.toInt() ); + + else if( ATextItem.length() ) + { + TStringItem *AItem = new TStringItem; + + AItem->Text = ATextItem; + AItem->Element = NULL; + + FReadyElements.push_back( AItem ); + } + +// Serial.println( "DEBUG>>" ); +// for( Mitov::SimpleList::iterator Iter = FReadyElements.begin(); Iter != FReadyElements.end(); ++Iter ) +// Serial.println( ( *Iter )->Text ); + +// Serial.println( "<::iterator Iter = FElements.begin(); Iter != FElements.end(); ++Iter ) + (*Iter )->SystemStart(); + + InitElements(); + inherited::SystemStart(); + ProcessSendOutput(); + } + + }; +//--------------------------------------------------------------------------- + template class TextFormatElementInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_LCD_INSTANCE->SetValue( String( *(T*)_Data )); + } + }; +//--------------------------------------------------------------------------- + template class TextFormatElementStringInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_LCD_INSTANCE->SetValue( (char*)_Data ); + } + }; +//--------------------------------------------------------------------------- + template class TextFormatElementObjectInput : public Mitov::CommonSink + { + typedef Mitov::CommonSink inherited; + + protected: + virtual void DoReceive( void *_Data ) override + { + T_LCD_INSTANCE->SetValue( ((T_OBJECT *)_Data)->ToString() ); + } + }; +//--------------------------------------------------------------------------- + class FormattedTextElementText : public FormattedTextElementBasic + { + typedef Mitov::FormattedTextElementBasic inherited; + + public: + String InitialValue; + String FValue; + + public: + void SetValue( String AValue ) + { + FOwner.SetModified(); + FValue = AValue; + } + + public: + virtual String GetText() + { + return FValue; + } + + public: + virtual void SystemStart() + { +// inherited::SystemStart(); + FValue = InitialValue; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class FormattedTextInputElement : public FormattedTextElementBasic + { + typedef Mitov::FormattedTextElementBasic inherited; + + public: + OpenWire::SinkPin InputPin; + + protected: + virtual void DoReceive( void *_Data ) = 0; + + public: + FormattedTextInputElement( BasicFormattedText &AOwner ) : + inherited( AOwner ) + { + InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&FormattedTextInputElement::DoReceive ); + } + + }; +//--------------------------------------------------------------------------- + template class FormattedTextElementTyped : public FormattedTextInputElement + { + typedef Mitov::FormattedTextInputElement inherited; + + public: + T InitialValue; + T FValue; + + public: + virtual void SystemStart() + { +// inherited::SystemStart(); + FValue = InitialValue; + } + + protected: + virtual void DoReceive( void *_Data ) + { + FOwner.SetModified(); + FValue = *(T *)_Data; + InitialValue = FValue; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class FormattedTextElementInteger : public Mitov::FormattedTextElementTyped + { + typedef Mitov::FormattedTextElementTyped inherited; + + public: + int Base = 10; + + public: + virtual String GetText() + { + char AText[ 50 ]; + itoa( FValue, AText, Base ); + + return AText; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class FormattedTextElementAnalog : public Mitov::FormattedTextElementTyped + { + typedef Mitov::FormattedTextElementTyped inherited; + + public: + int MinWidth = 1; + int Precision = 3; + + public: + virtual String GetText() + { + char AText[ 50 ]; + dtostrf( FValue, MinWidth, Precision, AText ); + + return AText; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- + class FormattedTextElementDigital : public Mitov::FormattedTextElementTyped + { + typedef Mitov::FormattedTextElementTyped inherited; + + public: + String TrueValue = "true"; + String FalseValue = "false"; + + public: + virtual String GetText() + { + if( FValue ) + return TrueValue; + + return FalseValue; + } + + public: + using inherited::inherited; + + }; +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + FormattedTextElementBasic::FormattedTextElementBasic( BasicFormattedText &AOwner ) : + FOwner( AOwner ) + { + AOwner.FElements.push_back( this ); + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Timing.h b/libraries/Mitov/Mitov_Timing.h new file mode 100644 index 0000000..3c7b743 --- /dev/null +++ b/libraries/Mitov/Mitov_Timing.h @@ -0,0 +1,226 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_TIMING_h +#define _MITOV_TIMING_h + +#include + +namespace Mitov +{ + class ClockGenerator : public Mitov::CommonGenerator + { + protected: + virtual void Clock() + { + OutputPin.Notify( NULL ); + } + + }; +//--------------------------------------------------------------------------- + class Timer : public Mitov::CommonEnableSource + { + typedef Mitov::CommonEnableSource inherited; + + public: + OpenWire::SinkPin StartInputPin; + OpenWire::SinkPin ResetInputPin; + + public: + uint32_t Interval = 1000000; + bool AutoRepeat : 1; + bool CanRestart : 1; + + protected: + bool FValue : 1; + + uint32_t FStartTime; + + protected: + virtual void SystemStart() + { + inherited::SystemStart(); + OutputPin.SendValue( FValue ); + } + + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( ! AutoRepeat ) + if( ! FValue ) + { + inherited::SystemLoopBegin( currentMicros ); + return; + } + + if( FValue ) + if( ! Enabled ) + { + FValue = false; + OutputPin.SendValue( FValue ); + inherited::SystemLoopBegin( currentMicros ); + return; + } + + currentMicros = micros(); // Use micros(); to make sure the DoReceiveStart is not from the same clock event! + if( currentMicros - FStartTime >= Interval ) + { + FValue = !FValue; + OutputPin.SendValue( FValue ); + if( AutoRepeat ) + FStartTime += Interval; + } + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + virtual void DoReceiveStart( void *_Data ) + { + if( ! Enabled ) + return; + + if( !CanRestart ) + if( FValue ) + return; + + FStartTime = micros(); + if( FValue ) + return; + + FValue = true; + OutputPin.SendValue( FValue ); + } + + void DoReceiveClear( void *_Data ) + { + if( FValue ) + { + FValue = false; + OutputPin.SendValue( FValue ); + + if( AutoRepeat ) + FStartTime = micros(); + } + } + + public: + Timer() : + AutoRepeat( false ), + CanRestart( true ), + FValue( false ) + { + StartInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Timer::DoReceiveStart ); + ResetInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Timer::DoReceiveClear ); + } + }; +//--------------------------------------------------------------------------- + class Delay : public Mitov::CommonEnableSource + { + typedef Mitov::CommonEnableSource inherited; + + public: + OpenWire::SinkPin StartInputPin; + OpenWire::SinkPin ResetInputPin; + + public: + unsigned long Interval = 1000000; + bool CanRestart : 1; + + protected: + bool FValue : 1; + unsigned long FStartTime; + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) + { + if( FValue ) + { + if( ! Enabled ) + FValue = false; + + else + { + unsigned long ACurrentMicros = micros(); // Use micros(); to make sure the DoReceiveStart is not from the same clock event! + if( ACurrentMicros - FStartTime >= Interval ) + { + FValue = false; + OutputPin.Notify( NULL ); + } + } + } + + inherited::SystemLoopBegin( currentMicros ); + } + + protected: + virtual void DoReceiveStart( void *_Data ) + { + if( ! Enabled ) + return; + + if( !CanRestart ) + if( FValue ) + return; + + FStartTime = micros(); + if( FValue ) + return; + + FValue = true; + } + + void DoReceiveClear( void *_Data ) + { + FValue = false; + } + + public: + Delay() : + CanRestart( true ), + FValue( false ) + { + StartInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Delay::DoReceiveStart ); + ResetInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Delay::DoReceiveClear ); + } + }; +//--------------------------------------------------------------------------- + class DetectEdge : public Mitov::CommonEnableFilter + { + public: + bool Rising : 1; + + protected: + bool FLastValue : 1; + + protected: + virtual void DoReceive( void *_Data ) override + { + bool AValue = *(bool *)_Data; + if( AValue == FLastValue ) + return; + + FLastValue = AValue; + if( Rising == AValue ) + OutputPin.Notify( NULL ); + + } + + public: + DetectEdge() : + FLastValue( false ), + Rising( true ) + { + } + + }; + +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_TriangleGenerator.h b/libraries/Mitov/Mitov_TriangleGenerator.h new file mode 100644 index 0000000..7e7973c --- /dev/null +++ b/libraries/Mitov/Mitov_TriangleGenerator.h @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_TRIANGLE_GENERATOR_h +#define _MITOV_TRIANGLE_GENERATOR_h + +#include +#include "Mitov_BasicGenerator.h" + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class TriangleAnalogGenerator : public Mitov::AsymmetricGenerator + { + typedef Mitov::AsymmetricGenerator inherited; + + protected: + virtual void CalculateValue() override + { + float AAssymetryPount = 0.5 + Asymmetry / 2; + if( FPhase < AAssymetryPount ) + FValue = Offset - Amplitude + Amplitude * 2 * ( FPhase / AAssymetryPount ); + + else + FValue = Offset - Amplitude + Amplitude * 2 * ( 1 - (( FPhase - AAssymetryPount ) / ( 1 - AAssymetryPount ))); + + } + + public: + TriangleAnalogGenerator() : + inherited( 0.5, 0.5 ) + { + } + + }; +//--------------------------------------------------------------------------- + class TriangleIntegerGenerator : public Mitov::AsymmetricGenerator + { + typedef Mitov::AsymmetricGenerator inherited; + + protected: + virtual void CalculateValue() override + { + float AAssymetryPount = 0.5 + Asymmetry / 2; + if( FPhase < AAssymetryPount ) + FValue = ( Offset - Amplitude + ((float)Amplitude) * 2 * ( FPhase / AAssymetryPount ) ) + 0.5; + + else + FValue = ( Offset - Amplitude + ((float)Amplitude) * 2 * ( 1 - (( FPhase - AAssymetryPount ) / ( 1 - AAssymetryPount ))) ) + 0.5; + + } + + public: + TriangleIntegerGenerator() : + inherited( 1000, 0 ) + { + } + + }; +//--------------------------------------------------------------------------- + class TriangleUnsignedGenerator : public Mitov::AsymmetricGenerator + { + typedef Mitov::AsymmetricGenerator inherited; + + protected: + virtual void CalculateValue() override + { + float AAssymetryPount = 0.5 + Asymmetry / 2; + if( FPhase < AAssymetryPount ) + FValue = ( Offset - Amplitude + ((float)Amplitude) * 2 * ( FPhase / AAssymetryPount ) ) + 0.5; + + else + FValue = ( Offset - Amplitude + ((float)Amplitude) * 2 * ( 1 - (( FPhase - AAssymetryPount ) / ( 1 - AAssymetryPount ))) ) + 0.5; + + } + + public: + TriangleUnsignedGenerator() : + inherited( 1000, 1000 ) + { + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_UARTSerial.h b/libraries/Mitov/Mitov_UARTSerial.h new file mode 100644 index 0000000..602f454 --- /dev/null +++ b/libraries/Mitov/Mitov_UARTSerial.h @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_UART_SERIAL_h +#define _MITOV_UART_SERIAL_h + +#include + +namespace Mitov +{ + const UARTClass::UARTModes CUARTSerialInits[] = + { + SERIAL_8N1, + SERIAL_8E1, + SERIAL_8O1, + SERIAL_8M1, + SERIAL_8S1 + }; +//--------------------------------------------------------------------------- + template class UARTSerialPort : public Mitov::SpeedSerialPort + { + typedef Mitov::SpeedSerialPort inherited; + + public: + TArduinoSerialParity Parity = spNone; + + public: + void SetParity( TArduinoSerialParity AValue ) + { + if( Parity == AValue ) + return; + + Parity = AValue; + inherited::RestartPort(); + } + + protected: + virtual void StartPort() override + { + int AIndex = ((int)Parity); + T_SERIAL->begin( inherited::Speed, CUARTSerialInits[ AIndex ] ); + } + + }; +//--------------------------------------------------------------------------- +} // Mitov + +#endif + diff --git a/libraries/Mitov/Mitov_USARTSerial.h b/libraries/Mitov/Mitov_USARTSerial.h new file mode 100644 index 0000000..d671e4e --- /dev/null +++ b/libraries/Mitov/Mitov_USARTSerial.h @@ -0,0 +1,126 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_USART_SERIAL_h +#define _MITOV_USART_SERIAL_h + +#include + +namespace Mitov +{ + const USARTClass::USARTModes CUSARTSerialInits[] = + { + SERIAL_5N1, + SERIAL_6N1, + SERIAL_7N1, + SERIAL_8N2, + + SERIAL_5N2, + SERIAL_6N2, + SERIAL_7N2, + SERIAL_8N2, + + SERIAL_5E1, + SERIAL_6E1, + SERIAL_7E1, + SERIAL_8E2, + + SERIAL_5E2, + SERIAL_6E2, + SERIAL_7E2, + SERIAL_8E2, + + SERIAL_5O1, + SERIAL_6O1, + SERIAL_7O1, + SERIAL_8O2, + + SERIAL_5O2, + SERIAL_6O2, + SERIAL_7O2, + SERIAL_8O2, + + SERIAL_5M1, + SERIAL_6M1, + SERIAL_7M1, + SERIAL_8M2, + + SERIAL_5M2, + SERIAL_6M2, + SERIAL_7M2, + SERIAL_8M2, + + SERIAL_5S1, + SERIAL_6S1, + SERIAL_7S1, + SERIAL_8S2, + + SERIAL_5S2, + SERIAL_6S2, + SERIAL_7S2, + SERIAL_8S2 + }; +//--------------------------------------------------------------------------- + template class USARTSerialPort : public Mitov::SpeedSerialPort + { + typedef Mitov::SpeedSerialPort inherited; + + public: + TArduinoSerialParity Parity : 3; + unsigned int StopBits : 2; + unsigned int DataBits : 3; + + public: + void SetParity( TArduinoSerialParity AValue ) + { + if( Parity == AValue ) + return; + + Parity = AValue; + inherited::RestartPort(); + } + + void SetStopBits( unsigned int AValue ) + { + if( StopBits == AValue ) + return; + + StopBits = AValue; + inherited::RestartPort(); + } + + void SetDataBits( unsigned int AValue ) + { + if( DataBits == AValue ) + return; + + DataBits = AValue; + inherited::RestartPort(); + } + + protected: + virtual void StartPort() override + { + int AIndex = ((int)Parity) * 8 + ( StopBits - 1 ) * 4 + ( DataBits - 5); + T_SERIAL->begin( inherited::Speed, CUSARTSerialInits[ AIndex ] ); + } + + public: + USARTSerialPort() : + Parity( spNone ), + StopBits( 2 ), + DataBits( 8 ) + { + } + }; +//--------------------------------------------------------------------------- +} // Mitov + +#endif + diff --git a/libraries/Mitov/Mitov_UltrasonicRanger.h b/libraries/Mitov/Mitov_UltrasonicRanger.h new file mode 100644 index 0000000..05d3f5b --- /dev/null +++ b/libraries/Mitov/Mitov_UltrasonicRanger.h @@ -0,0 +1,176 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_ULTRASONIC_RANGE_h +#define _MITOV_ULTRASONIC_RANGE_h + +#include + +namespace Mitov +{ + enum UltrasonicRangerUnits { rdTime, rdCm, rdInch }; + + class UltrasonicRanger : public Mitov::CommonSource, public Mitov::ClockingSupport + { + typedef Mitov::CommonSource inherited; + + enum State { sStartUp, sStartDown, sListeningEdgeUp, sListeningEdgeDown, sEchoDetected, sPause }; + + public: + OpenWire::SinkPin EchoInputPin; + OpenWire::SourcePin PingOutputPin; + OpenWire::SourcePin TimeoutOutputPin; + + public: + int Timeout = 1000; + int PingTime = 2; + int PauseTime = 100; + float TimeoutValue = -1; + + UltrasonicRangerUnits Units : 2; + + bool Enabled : 1; + + protected: + State FState : 3; + bool FClocked : 1; + + unsigned long FStartTime; + unsigned long FEchoStartTime; + unsigned long FEndTime; + + protected: + void DoReceive( void *_Data ) + { + if( ( FState != sListeningEdgeUp ) && ( FState != sListeningEdgeDown ) ) + return; + + bool AValue = *(bool *)_Data; + if( FState == sListeningEdgeDown ) + { + if( AValue ) + return; + + FEndTime = micros(); + FState = sEchoDetected; + } + + else + { + if( ! AValue ) + return; + + FState = sListeningEdgeDown; + FEchoStartTime = micros(); + } + + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( !Enabled ) + return; + + switch ( FState ) + { + case sPause: + { + if( ( currentMicros - FStartTime ) < ((unsigned long)PauseTime ) * 1000 ) + return; + + if( ClockInputPin.IsConnected() ) + if( ! FClocked ) + return; + + FClocked = false; + } + + case sStartUp: + { +// Serial.println( "start" ); + bool AValue = true; + PingOutputPin.Notify( &AValue ); + FStartTime = currentMicros; + FState = sStartDown; + break; + } + + case sStartDown: + { + if( ( currentMicros - FStartTime ) < PingTime ) + return; + + bool AValue = false; + PingOutputPin.Notify( &AValue ); + FStartTime = currentMicros; + FState = sListeningEdgeUp; + break; + } + + case sListeningEdgeUp: + case sListeningEdgeDown: + { + if( ( currentMicros - FStartTime ) < ((unsigned long)Timeout ) * 1000 ) + return; + + OutputPin.Notify( &TimeoutValue ); + bool ABoolValue = true; + TimeoutOutputPin.Notify( &ABoolValue ); + FState = sPause; + break; + } + + case sEchoDetected: + { + unsigned long APeriod = FEndTime - FEchoStartTime; + float AValue; + switch( Units ) + { + case rdTime: + AValue = APeriod; + break; + + case rdCm: + AValue = ((float)APeriod) / 29 / 2; // / 58.2; + break; + + case rdInch: + AValue = ((float)APeriod) / 74 / 2; + break; + } + + OutputPin.Notify( &AValue ); + bool ABoolValue = false; + TimeoutOutputPin.Notify( &ABoolValue ); + FState = sPause; + break; + } + } + } + + virtual void DoClockReceive( void *_Data ) override + { + FClocked = true; + } + + public: + UltrasonicRanger() : + FState( sStartUp ), + Enabled( true ), + Units( rdCm ), + FClocked( false ) + { + EchoInputPin.SetCallback( MAKE_CALLBACK( UltrasonicRanger::DoReceive )); + } + + }; +} + +#endif diff --git a/libraries/Mitov/Mitov_WiFiShield.h b/libraries/Mitov/Mitov_WiFiShield.h new file mode 100644 index 0000000..f7d2fe8 --- /dev/null +++ b/libraries/Mitov/Mitov_WiFiShield.h @@ -0,0 +1,267 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_WIFI_SHIELD_h +#define _MITOV_WIFI_SHIELD_h + +#include +#include + +namespace Mitov +{ +// class BasicEthernetSocket; +//--------------------------------------------------------------------------- + class WiFiRemoteAccessPoint + { + public: + bool Enabled = true; + String SSID; + + public: + bool Connect() + { + if( ! Enabled ) + return false; + +// if( SSID == "" ) +// return ( WiFi.begin() == WL_CONNECTED ); + + return IntConnect(); + } + + protected: + virtual bool IntConnect() + { + return ( WiFi.begin( (char *)SSID.c_str() ) == WL_CONNECTED ); + } + + }; +//--------------------------------------------------------------------------- + class WiFiRemoteAccessPointWPA : public WiFiRemoteAccessPoint + { + public: + String Password; + + protected: + virtual bool IntConnect() + { + return ( WiFi.begin( (char *)SSID.c_str(), (char *)Password.c_str() ) == WL_CONNECTED ); + } + }; +//--------------------------------------------------------------------------- + class WiFiRemoteAccessPointWEP : public WiFiRemoteAccessPoint + { + public: + String Key; + int KeyIndex = 0; + + protected: + virtual bool IntConnect() + { + return ( WiFi.begin( (char *)SSID.c_str(), KeyIndex, (char *)Key.c_str() ) == WL_CONNECTED ); + } + + }; +//--------------------------------------------------------------------------- + class WiFiShield : public Mitov::BasicEthernetShield + { + typedef Mitov::BasicEthernetShield inherited; + + public: + OpenWire::SinkPin ScanNetworksInputPin; + OpenWire::SourcePin FoundSignalStrengthOutputPin; + OpenWire::SourcePin FoundSSIDOutputPin; + + OpenWire::SourcePin AddressOutputPin; + OpenWire::SourcePin MACOutputPin; + + OpenWire::SourcePin SignalStrengthOutputPin; + OpenWire::SourcePin BSSIDOutputPin; + OpenWire::SourcePin GatewayIPOutputPin; + OpenWire::SourcePin SubnetMaskIPOutputPin; + + OpenWire::SinkPin CheckSignalStrengthInputPin; + + public: + ShieldIPDNS2Address IPAddress; + + public: + Mitov::SimpleObjectList AccessPoints; + + public: + bool IsStarted = false; + + public: + virtual bool GetIPFromHostName( String AHostName, ::IPAddress &AAdress ) + { + bool AResult = ( WiFi.hostByName( AHostName.c_str(), AAdress ) == 1 ); + if( ! AResult ) + AAdress = INADDR_NONE; + + return AResult; + } + + protected: + virtual void StartEthernet() + { +// int AIndex = ((int)Parity) * 2 * 4 + ( StopBits - 1 ) + ( DataBits - 5); +// T_SERIAL->begin( Speed ); + +// Serial.println( "StartEthernet" ); + for( int i = 0; i < AccessPoints.size(); ++i ) + if( AccessPoints[ i ]->Connect() ) + { + IsStarted = true; + if( IPAddress.Enabled ) + { + if( ! IPAddress.DNS.Enabled ) + WiFi.config( IPAddress.IP ); + + else + { + if( ! IPAddress.DNS.Gateway.Enabled ) + WiFi.config( IPAddress.IP, IPAddress.DNS.IP ); + + else + { + if( ! IPAddress.DNS.Gateway.Subnet.Enabled ) + WiFi.config( IPAddress.IP, IPAddress.DNS.IP, IPAddress.DNS.Gateway.IP ); + + else + WiFi.config( IPAddress.IP, IPAddress.DNS.IP, IPAddress.DNS.Gateway.IP, IPAddress.DNS.Gateway.Subnet.IP ); + } + + if( IPAddress.DNS2.Enabled ) + WiFi.setDNS( IPAddress.DNS.IP, IPAddress.DNS2.IP ); + + } + } + + if( MACOutputPin.IsConnected() ) + { + uint8_t AMACAddress[6] = {0}; + + WiFi.macAddress( AMACAddress ); + + char AMACString[ 6 * 3 + 1 ]; + sprintf( AMACString, "%02X-%02X-%02X-%02X-%02X-%02X", AMACString[ 0 ], AMACString[ 1 ], AMACString[ 2 ], AMACString[ 3 ], AMACString[ 4 ], AMACString[ 5 ] ); + MACOutputPin.Notify( AMACString ); + } + + if( AddressOutputPin.IsConnected() ) + { + String AIPString = IPAdressToString( WiFi.localIP()); + AddressOutputPin.Notify( (void *)AIPString.c_str() ); + } + + if( SignalStrengthOutputPin.IsConnected() ) + { + int32_t ASetrength = WiFi.RSSI(); + SignalStrengthOutputPin.Notify( &ASetrength ); + } + + if( BSSIDOutputPin.IsConnected() ) + { + uint8_t AMACAddress[6] = {0}; + + WiFi.BSSID( AMACAddress ); + + char AMACString[ 6 * 3 + 1 ]; + sprintf( AMACString, "%02X-%02X-%02X-%02X-%02X-%02X", AMACString[ 0 ], AMACString[ 1 ], AMACString[ 2 ], AMACString[ 3 ], AMACString[ 4 ], AMACString[ 5 ] ); + BSSIDOutputPin.Notify( AMACString ); + } + + if( GatewayIPOutputPin.IsConnected() ) + { + String AIPString = IPAdressToString( WiFi.gatewayIP()); + AddressOutputPin.Notify( (void *)AIPString.c_str() ); + } + + if( SubnetMaskIPOutputPin.IsConnected() ) + { + String AIPString = IPAdressToString( WiFi.subnetMask()); + SubnetMaskIPOutputPin.Notify( (void *)AIPString.c_str() ); + } + + break; + } + + } + + virtual void StopEthernet() + { + inherited::StopEthernet(); + WiFi.disconnect(); + IsStarted = false; + } + + protected: + void DoScanNetworks( void *_Data ) + { + int nearbyAccessPointCount = WiFi.scanNetworks(); + for( int i = 0; i < nearbyAccessPointCount; i ++ ) + { + FoundSSIDOutputPin.Notify( WiFi.SSID( i )); + + int32_t ASetrength = WiFi.RSSI( i ); + FoundSignalStrengthOutputPin.Notify( &ASetrength ); + } + } + + void DoCheckSignalStrength( void *_Data ) + { + if( IsStarted ) + if( SignalStrengthOutputPin.IsConnected() ) + { + int32_t ASetrength = WiFi.RSSI(); + SignalStrengthOutputPin.Notify( &ASetrength ); + } + } + + public: + WiFiShield() + { + ScanNetworksInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&WiFiShield::DoScanNetworks ); + } + + WiFiShield( ::IPAddress local_ip) : + WiFiShield() + { + IPAddress.Enabled = true; + IPAddress.IP = local_ip; + + CheckSignalStrengthInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&WiFiShield::DoCheckSignalStrength ); + } + + WiFiShield( ::IPAddress local_ip, ::IPAddress dns_server) : + WiFiShield( local_ip ) + { + + IPAddress.DNS.Enabled = true; + IPAddress.DNS.IP = dns_server; + } + + WiFiShield( ::IPAddress local_ip, ::IPAddress dns_server, ::IPAddress gateway) : + WiFiShield( local_ip, dns_server ) + { + IPAddress.DNS.Gateway.Enabled = true; + IPAddress.DNS.Gateway.IP = gateway; + } + + WiFiShield( ::IPAddress local_ip, ::IPAddress dns_server, ::IPAddress gateway, ::IPAddress subnet) : + WiFiShield( local_ip, dns_server, gateway ) + { + IPAddress.DNS.Gateway.Subnet.Enabled = true; + IPAddress.DNS.Gateway.Subnet.IP = subnet; + } + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/Mitov_Wii_Controller.h b/libraries/Mitov/Mitov_Wii_Controller.h new file mode 100644 index 0000000..6683363 --- /dev/null +++ b/libraries/Mitov/Mitov_Wii_Controller.h @@ -0,0 +1,139 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _MITOV_WII_CONTROLLER_h +#define _MITOV_WII_CONTROLLER_h + +#include + +// http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck + +namespace Mitov +{ +//--------------------------------------------------------------------------- + class WiiNunchuck : public Mitov::EnabledComponent, public Mitov::ClockingSupport + { + typedef Mitov::EnabledComponent inherited; + + private: + const byte WII_NUNCHUK_I2C_ADDRESS = 0x52; + + public: + OpenWire::TypedSourcePin AngleOutputPins[ 3 ]; + OpenWire::TypedSourcePin StickOutputPins[ 2 ]; + OpenWire::TypedSourcePin ButtonOutputPins[ 2 ]; + + public: + uint32_t ReadDelay = 100; + + protected: + bool FStarted = false; + unsigned long FLastTime = 0; + int FClockedCount = 0; + + protected: + void DoClockReceive( void *_Data ) override + { + ++ FClockedCount; + StartRead(); + } + + void ReadData( bool AChangeOnly ) + { + if( ! Enabled ) + return; + + ReadController( AChangeOnly ); + } + + void StartRead() + { + Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS); + Wire.write(0x00); + Wire.endTransmission(); + + delayMicroseconds( 10 ); + + Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS); + Wire.write(0x00); + Wire.endTransmission(); + FLastTime = micros(); + } + + void ReadController( bool AChangeOnly ) + { + uint8_t AData[6]; + Wire.requestFrom(WII_NUNCHUK_I2C_ADDRESS, (byte)6); + + for( int i = 0; i < 6; ++i ) + AData[ i ] = Wire.read(); + + float AStickX = (float)AData[0] / 255; + float AStickY = (float)AData[1] / 255; + StickOutputPins[ 0 ].SetValue( AStickX, AChangeOnly ); + StickOutputPins[ 1 ].SetValue( AStickY, AChangeOnly ); + + float AAngleX = ((float)(((uint16_t)AData[2] ) << 2) + ((AData[5] >> 2) & 0x03)) / 1023; + float AAngleY = ((float)(((uint16_t)AData[3] ) << 2) + ((AData[5] >> 4) & 0x03)) / 1023; + float AAngleZ = ((float)(((uint16_t)AData[4] ) << 2) + ((AData[5] >> 6) & 0x03)) / 1023; + + AngleOutputPins[ 0 ].SetValue( AAngleX, AChangeOnly ); + AngleOutputPins[ 1 ].SetValue( AAngleY, AChangeOnly ); + AngleOutputPins[ 2 ].SetValue( AAngleZ, AChangeOnly ); + + bool AButtonValue = !( AData[5] & 0b10 ); + ButtonOutputPins[ 0 ].SetValue( AButtonValue, AChangeOnly ); + + AButtonValue = !( AData[5] & 1 ); + ButtonOutputPins[ 1 ].SetValue( AButtonValue, AChangeOnly ); + + if( ( ! ClockInputPin.IsConnected() ) || FClockedCount ) + StartRead(); + } + + protected: + virtual void SystemLoopBegin( unsigned long currentMicros ) override + { + if( ! FClockedCount ) + if( ! ClockInputPin.IsConnected() ) + ++ FClockedCount; + + if( FClockedCount ) + if( currentMicros - FLastTime > ReadDelay ) + { + -- FClockedCount; + ReadData( FStarted ); + FStarted = true; + } + + inherited::SystemLoopBegin( currentMicros ); + } + + virtual void SystemStart() override + { + // Init the controller + Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS); + Wire.write(0xF0); + Wire.write(0x55); + Wire.endTransmission(); + + Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS); + Wire.write(0xFB); + Wire.write(0x00); + Wire.endTransmission(); + + StartRead(); + inherited::SystemStart(); + } + + }; +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/OpenWire.h b/libraries/Mitov/OpenWire.h new file mode 100644 index 0000000..dcf0c06 --- /dev/null +++ b/libraries/Mitov/OpenWire.h @@ -0,0 +1,362 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// This software is supplied under the terms of a license agreement or // +// nondisclosure agreement with Mitov Software and may not be copied // +// or disclosed except in accordance with the terms of that agreement. // +// Copyright(c) 2002-2016 Mitov Software. All Rights Reserved. // +// // +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _OPENWIRE_h +#define _OPENWIRE_h + +#include + +namespace OpenWire +{ + class Object + { + }; +//--------------------------------------------------------------------------- + class VirtualObject : public Object + { + public: + virtual ~VirtualObject() {} + }; +//--------------------------------------------------------------------------- + class Component : public VirtualObject + { + public: + static void _SystemInit(); + static void _SystemLoop(); + + protected: + virtual void CalculateFields() {} + virtual void SystemInit() + { + CalculateFields(); + } + + virtual void SystemStart() {} + virtual void SystemLoopBegin( unsigned long currentMicros ) {} + virtual void SystemLoopEnd() {} + virtual void SystemLoopUpdateHardware() {} + + public: + Component(); + virtual ~Component(); + + }; +//--------------------------------------------------------------------------- + typedef void (Object::*TOnPinReceive) ( void *_Data ); +//--------------------------------------------------------------------------- + typedef void (Object::*TOnPinIndexedReceive) ( int AIndex, void *_Data ); +//--------------------------------------------------------------------------- + class Pin : public Object + { + public: + virtual void InternalConnect( Pin &_other ) {} + + public: + virtual void Connect( Pin &_other ) + { + InternalConnect( _other ); + _other.InternalConnect( *this ); + } + + virtual void Receive( void *_Data ) {} + }; +//--------------------------------------------------------------------------- + class CallbackPin : public Pin + { + protected: + Object *OnReceiveObject = nullptr; + TOnPinReceive OnReceive = nullptr; + + public: + void SetCallback( Object *AOnReceiveObject, TOnPinReceive AOnReceive ) + { + OnReceiveObject = AOnReceiveObject; + OnReceive = AOnReceive; + } + + public: + virtual void InternalConnect( Pin &_other ) {} + + public: + virtual void Receive( void *_Data ) override + { + if( OnReceive ) + ( OnReceiveObject->*OnReceive )( _Data ); + + } + + }; +//--------------------------------------------------------------------------- + class StreamPin : public Pin + { + public: + Mitov::SimpleList Pins; + + public: + template void SendValue( T AValue ) + { + Notify( &AValue ); + } + + void SendValue( String AValue ) + { + Notify( (char *)AValue.c_str() ); + } + + public: + virtual void InternalConnect( Pin &_other ) override + { + Pins.push_back( &_other ); + } + + public: + virtual bool IsConnected() + { + return ( Pins.size() > 0 ); + } + + public: + virtual void Notify( void *_data ) + { + for( Mitov::SimpleList::iterator Iter = Pins.begin(); Iter != Pins.end(); ++Iter ) + ( *Iter )->Receive( _data ); + + } + }; +//--------------------------------------------------------------------------- + class SourcePin : public StreamPin + { + }; +//--------------------------------------------------------------------------- + class SinkPin : public CallbackPin + { + }; +//--------------------------------------------------------------------------- + class ConnectSinkPin : public CallbackPin + { + typedef CallbackPin inherited; + + protected: + bool FIsConnected = false; + + public: + virtual void InternalConnect( Pin &_other ) + { + inherited::InternalConnect( _other ); + FIsConnected = true; + } + + virtual bool IsConnected() + { + return FIsConnected; + } + + }; +//--------------------------------------------------------------------------- + template class TypedSourcePin : public SourcePin + { + typedef SourcePin inherited; + + protected: + T FValue; + + public: + void SetValue( T AValue, bool AChangeOnly ) + { + if( AChangeOnly ) + if( AValue == FValue ) + return; + + FValue = AValue; + Notify( &FValue ); + } + + }; +//--------------------------------------------------------------------------- + template class VlaueSinkPin : public SinkPin + { + typedef SinkPin inherited; + + public: + T Value = T( 0 ); + + public: + virtual void Receive( void *_Data ) override + { + Value = *(T*)_Data; + inherited::Receive( _Data ); + } + }; +//--------------------------------------------------------------------------- + template<> class VlaueSinkPin : public SinkPin + { + typedef SinkPin inherited; + + public: + String Value; + + public: + virtual void Receive( void *_Data ) override + { + Value = (char *)_Data; + inherited::Receive( _Data ); + } + }; +//--------------------------------------------------------------------------- + template<> class VlaueSinkPin : public SinkPin + { + typedef SinkPin inherited; + + public: + String Value; + + public: + virtual void Receive( void *_Data ) override + { + Value = (char*)_Data; + inherited::Receive( _Data ); + } + + }; +//--------------------------------------------------------------------------- + template class VlaueChangeSinkPin : public SinkPin + { + typedef SinkPin inherited; + + public: + T Value = 0; + T OldValue = 0; + + public: + virtual void Receive( void *_Data ) override + { + Value = *(T*)_Data; + inherited::Receive( _Data ); + } + + }; +//--------------------------------------------------------------------------- + template<> class VlaueChangeSinkPin : public SinkPin + { + typedef SinkPin inherited; + + public: + String Value; + String OldValue; + + public: + virtual void Receive( void *_Data ) override + { + Value = (char *)_Data; + inherited::Receive( _Data ); + } + + }; +//--------------------------------------------------------------------------- + template<> class VlaueChangeSinkPin : public SinkPin + { + typedef SinkPin inherited; + + public: + String Value; + String OldValue; + + public: + virtual void Receive( void *_Data ) override + { + Value = (char *)_Data; + inherited::Receive( _Data ); + } + + }; +//--------------------------------------------------------------------------- + class IndexedSinkPin : public SinkPin + { + typedef SinkPin inherited; + + public: + int Index = 0; + + public: + TOnPinIndexedReceive OnIndexedReceive = nullptr; + + protected: + virtual void Receive( void *_Data ) override + { + if( OnIndexedReceive ) + ( OnReceiveObject->*OnIndexedReceive )( Index, _Data ); + + inherited::Receive( _Data ); + } + + }; +//--------------------------------------------------------------------------- + template class LiveBindingSink : public OpenWire::Pin + { + protected: + void (*FFunc)( T AData ); + + protected: + virtual void Receive( void *_Data ) override + { + FFunc(*(T*)_Data ); + } + + public: + LiveBindingSink( void (*AFunc)( T AData ) ) : + FFunc( AFunc ) + { + } + }; +//--------------------------------------------------------------------------- + static Mitov::SimpleList _Components; +//--------------------------------------------------------------------------- + Component::Component() + { + _Components.push_back(this); + } +//--------------------------------------------------------------------------- + Component::~Component() + { + for( Mitov::SimpleList::iterator Iter = OpenWire::_Components.begin(); Iter != OpenWire::_Components.end(); ++Iter ) + if( *Iter == this ) + { + _Components.erase(Iter); + break; + } + + } +//--------------------------------------------------------------------------- + void Component::_SystemInit() + { + for( Mitov::SimpleList::iterator Iter = OpenWire::_Components.begin(); Iter != OpenWire::_Components.end(); ++Iter ) + ( *Iter )->SystemInit(); + + for( Mitov::SimpleList::iterator Iter = OpenWire::_Components.begin(); Iter != OpenWire::_Components.end(); ++Iter ) + ( *Iter )->SystemStart(); + + } +//--------------------------------------------------------------------------- + void Component::_SystemLoop() + { + unsigned long currentMicros = micros(); + for( Mitov::SimpleList::iterator Iter = OpenWire::_Components.begin(); Iter != OpenWire::_Components.end(); ++Iter ) + ( *Iter )->SystemLoopBegin( currentMicros ); + + for( Mitov::SimpleList::iterator Iter = OpenWire::_Components.begin(); Iter != OpenWire::_Components.end(); ++Iter ) + ( *Iter )->SystemLoopEnd(); + + for( Mitov::SimpleList::iterator Iter = OpenWire::_Components.begin(); Iter != OpenWire::_Components.end(); ++Iter ) + ( *Iter )->SystemLoopUpdateHardware(); + + } +//--------------------------------------------------------------------------- +} + +#endif diff --git a/libraries/Mitov/README.md b/libraries/Mitov/README.md new file mode 100644 index 0000000..6e0b5d4 --- /dev/null +++ b/libraries/Mitov/README.md @@ -0,0 +1,21 @@ +#Component Development Libraries# +##For Visuino the Arduino Visual Programming Environment## +##by Mitov Software## + +###What these files are### +**These are the the Visuino Component Libraries, these libraries are used by the Visuino generated code** + +They are updated when a new version of Visuino is released and are Open Source. + +These Libraries can be used to see what has changed in some of the core code used to build Visuino. + + + + +###What these files are not### + +They are not a way to build your own version of Visuino. + +They are not an SDK. The SDK is a separate release that is shared with the Google Plus Visuino DEV Community, which can be found here: (https://plus.google.com/communities/116125623808250792822) + +They are not a free version of Visuino. You can get a trial version here: (https://www.visuino.com/download) \ No newline at end of file diff --git a/libraries/Mitov/avr/ServoTimers.h b/libraries/Mitov/avr/ServoTimers.h new file mode 100644 index 0000000..29c1ae2 --- /dev/null +++ b/libraries/Mitov/avr/ServoTimers.h @@ -0,0 +1,59 @@ +/* + Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 + Copyright (c) 2009 Michael Margolis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* + * Defines for 16 bit timers used with Servo library + * + * If _useTimerX is defined then TimerX is a 16 bit timer on the current board + * timer16_Sequence_t enumerates the sequence that the timers should be allocated + * _Nbr_16timers indicates how many 16 bit timers are available. + */ + +/** + * AVR Only definitions + * -------------------- + */ + +// Say which 16 bit timers can be used and in what order +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define _useTimer5 +#define _useTimer1 +#define _useTimer3 +#define _useTimer4 +typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t; + +#elif defined(__AVR_ATmega32U4__) +#define _useTimer1 +typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t; + +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +#define _useTimer3 +#define _useTimer1 +typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t; + +#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__) +#define _useTimer3 +#define _useTimer1 +typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t; + +#else // everything else +#define _useTimer1 +typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t; +#endif + diff --git a/libraries/Mitov/sam/ServoTimers.h b/libraries/Mitov/sam/ServoTimers.h new file mode 100644 index 0000000..13f736a --- /dev/null +++ b/libraries/Mitov/sam/ServoTimers.h @@ -0,0 +1,88 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* + * Defines for 16 bit timers used with Servo library + * + * If _useTimerX is defined then TimerX is a 16 bit timer on the current board + * timer16_Sequence_t enumerates the sequence that the timers should be allocated + * _Nbr_16timers indicates how many 16 bit timers are available. + */ + +/** + * SAM Only definitions + * -------------------- + */ + +// For SAM3X: +#define _useTimer1 +#define _useTimer2 +#define _useTimer3 +#define _useTimer4 +#define _useTimer5 + +/* + TC0, chan 0 => TC0_Handler + TC0, chan 1 => TC1_Handler + TC0, chan 2 => TC2_Handler + TC1, chan 0 => TC3_Handler + TC1, chan 1 => TC4_Handler + TC1, chan 2 => TC5_Handler + TC2, chan 0 => TC6_Handler + TC2, chan 1 => TC7_Handler + TC2, chan 2 => TC8_Handler + */ + +#if defined (_useTimer1) +#define TC_FOR_TIMER1 TC1 +#define CHANNEL_FOR_TIMER1 0 +#define ID_TC_FOR_TIMER1 ID_TC3 +#define IRQn_FOR_TIMER1 TC3_IRQn +#define HANDLER_FOR_TIMER1 TC3_Handler +#endif +#if defined (_useTimer2) +#define TC_FOR_TIMER2 TC1 +#define CHANNEL_FOR_TIMER2 1 +#define ID_TC_FOR_TIMER2 ID_TC4 +#define IRQn_FOR_TIMER2 TC4_IRQn +#define HANDLER_FOR_TIMER2 TC4_Handler +#endif +#if defined (_useTimer3) +#define TC_FOR_TIMER3 TC1 +#define CHANNEL_FOR_TIMER3 2 +#define ID_TC_FOR_TIMER3 ID_TC5 +#define IRQn_FOR_TIMER3 TC5_IRQn +#define HANDLER_FOR_TIMER3 TC5_Handler +#endif +#if defined (_useTimer4) +#define TC_FOR_TIMER4 TC0 +#define CHANNEL_FOR_TIMER4 2 +#define ID_TC_FOR_TIMER4 ID_TC2 +#define IRQn_FOR_TIMER4 TC2_IRQn +#define HANDLER_FOR_TIMER4 TC2_Handler +#endif +#if defined (_useTimer5) +#define TC_FOR_TIMER5 TC0 +#define CHANNEL_FOR_TIMER5 0 +#define ID_TC_FOR_TIMER5 ID_TC0 +#define IRQn_FOR_TIMER5 TC0_IRQn +#define HANDLER_FOR_TIMER5 TC0_Handler +#endif + +typedef enum { _timer1, _timer2, _timer3, _timer4, _timer5, _Nbr_16timers } timer16_Sequence_t ; + diff --git a/libraries/OneWire/OneWire.cpp b/libraries/OneWire/OneWire.cpp new file mode 100644 index 0000000..efd6949 --- /dev/null +++ b/libraries/OneWire/OneWire.cpp @@ -0,0 +1,577 @@ +/* +Copyright (c) 2007, Jim Studt (original old version - many contributors since) + +The latest version of this library may be found at: + http://www.pjrc.com/teensy/td_libs_OneWire.html + +OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since +January 2010. At the time, it was in need of many bug fixes, but had +been abandoned the original author (Jim Studt). None of the known +contributors were interested in maintaining OneWire. Paul typically +works on OneWire every 6 to 12 months. Patches usually wait that +long. If anyone is interested in more actively maintaining OneWire, +please contact Paul. + +Version 2.3: + Unknonw chip fallback mode, Roger Clark + Teensy-LC compatibility, Paul Stoffregen + Search bug fix, Love Nystrom + +Version 2.2: + Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com + Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030 + Fix DS18B20 example negative temperature + Fix DS18B20 example's low res modes, Ken Butcher + Improve reset timing, Mark Tillotson + Add const qualifiers, Bertrik Sikken + Add initial value input to crc16, Bertrik Sikken + Add target_search() function, Scott Roberts + +Version 2.1: + Arduino 1.0 compatibility, Paul Stoffregen + Improve temperature example, Paul Stoffregen + DS250x_PROM example, Guillermo Lovato + PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com + Improvements from Glenn Trewitt: + - crc16() now works + - check_crc16() does all of calculation/checking work. + - Added read_bytes() and write_bytes(), to reduce tedious loops. + - Added ds2408 example. + Delete very old, out-of-date readme file (info is here) + +Version 2.0: Modifications by Paul Stoffregen, January 2010: +http://www.pjrc.com/teensy/td_libs_OneWire.html + Search fix from Robin James + http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 + Use direct optimized I/O in all cases + Disable interrupts during timing critical sections + (this solves many random communication errors) + Disable interrupts during read-modify-write I/O + Reduce RAM consumption by eliminating unnecessary + variables and trimming many to 8 bits + Optimize both crc8 - table version moved to flash + +Modified to work with larger numbers of devices - avoids loop. +Tested in Arduino 11 alpha with 12 sensors. +26 Sept 2008 -- Robin James +http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 + +Updated to work with arduino-0008 and to include skip() as of +2007/07/06. --RJL20 + +Modified to calculate the 8-bit CRC directly, avoiding the need for +the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010 +-- Tom Pollard, Jan 23, 2008 + +Jim Studt's original library was modified by Josh Larios. + +Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008 + +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: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +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. + +Much of the code was inspired by Derek Yerger's code, though I don't +think much of that remains. In any event that was.. + (copyleft) 2006 by Derek Yerger - Free to distribute freely. + +The CRC code was excerpted and inspired by the Dallas Semiconductor +sample code bearing this copyright. +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// 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: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// 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 DALLAS SEMICONDUCTOR 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. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//-------------------------------------------------------------------------- +*/ + +#include "OneWire.h" + + +OneWire::OneWire(uint8_t pin) +{ + pinMode(pin, INPUT); + bitmask = PIN_TO_BITMASK(pin); + baseReg = PIN_TO_BASEREG(pin); +#if ONEWIRE_SEARCH + reset_search(); +#endif +} + + +// Perform the onewire reset function. We will wait up to 250uS for +// the bus to come high, if it doesn't then it is broken or shorted +// and we return a 0; +// +// Returns 1 if a device asserted a presence pulse, 0 otherwise. +// +uint8_t OneWire::reset(void) +{ + IO_REG_TYPE mask = bitmask; + volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; + uint8_t r; + uint8_t retries = 125; + + noInterrupts(); + DIRECT_MODE_INPUT(reg, mask); + interrupts(); + // wait until the wire is high... just in case + do { + if (--retries == 0) return 0; + delayMicroseconds(2); + } while ( !DIRECT_READ(reg, mask)); + + noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + interrupts(); + delayMicroseconds(480); + noInterrupts(); + DIRECT_MODE_INPUT(reg, mask); // allow it to float + delayMicroseconds(70); + r = !DIRECT_READ(reg, mask); + interrupts(); + delayMicroseconds(410); + return r; +} + +// +// Write a bit. Port and bit is used to cut lookup time and provide +// more certain timing. +// +void OneWire::write_bit(uint8_t v) +{ + IO_REG_TYPE mask=bitmask; + volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; + + if (v & 1) { + noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(10); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + interrupts(); + delayMicroseconds(55); + } else { + noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(65); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + interrupts(); + delayMicroseconds(5); + } +} + +// +// Read a bit. Port and bit is used to cut lookup time and provide +// more certain timing. +// +uint8_t OneWire::read_bit(void) +{ + IO_REG_TYPE mask=bitmask; + volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; + uint8_t r; + + noInterrupts(); + DIRECT_MODE_OUTPUT(reg, mask); + DIRECT_WRITE_LOW(reg, mask); + delayMicroseconds(3); + DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise + delayMicroseconds(10); + r = DIRECT_READ(reg, mask); + interrupts(); + delayMicroseconds(53); + return r; +} + +// +// Write a byte. The writing code uses the active drivers to raise the +// pin high, if you need power after the write (e.g. DS18S20 in +// parasite power mode) then set 'power' to 1, otherwise the pin will +// go tri-state at the end of the write to avoid heating in a short or +// other mishap. +// +void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { + uint8_t bitMask; + + for (bitMask = 0x01; bitMask; bitMask <<= 1) { + OneWire::write_bit( (bitMask & v)?1:0); + } + if ( !power) { + noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + DIRECT_WRITE_LOW(baseReg, bitmask); + interrupts(); + } +} + +void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) { + for (uint16_t i = 0 ; i < count ; i++) + write(buf[i]); + if (!power) { + noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + DIRECT_WRITE_LOW(baseReg, bitmask); + interrupts(); + } +} + +// +// Read a byte +// +uint8_t OneWire::read() { + uint8_t bitMask; + uint8_t r = 0; + + for (bitMask = 0x01; bitMask; bitMask <<= 1) { + if ( OneWire::read_bit()) r |= bitMask; + } + return r; +} + +void OneWire::read_bytes(uint8_t *buf, uint16_t count) { + for (uint16_t i = 0 ; i < count ; i++) + buf[i] = read(); +} + +// +// Do a ROM select +// +void OneWire::select(const uint8_t rom[8]) +{ + uint8_t i; + + write(0x55); // Choose ROM + + for (i = 0; i < 8; i++) write(rom[i]); +} + +// +// Do a ROM skip +// +void OneWire::skip() +{ + write(0xCC); // Skip ROM +} + +void OneWire::depower() +{ + noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + interrupts(); +} + +#if ONEWIRE_SEARCH + +// +// You need to use this function to start a search again from the beginning. +// You do not need to do it for the first search, though you could. +// +void OneWire::reset_search() +{ + // reset the search state + LastDiscrepancy = 0; + LastDeviceFlag = FALSE; + LastFamilyDiscrepancy = 0; + for(int i = 7; ; i--) { + ROM_NO[i] = 0; + if ( i == 0) break; + } +} + +// Setup the search to find the device type 'family_code' on the next call +// to search(*newAddr) if it is present. +// +void OneWire::target_search(uint8_t family_code) +{ + // set the search state to find SearchFamily type devices + ROM_NO[0] = family_code; + for (uint8_t i = 1; i < 8; i++) + ROM_NO[i] = 0; + LastDiscrepancy = 64; + LastFamilyDiscrepancy = 0; + LastDeviceFlag = FALSE; +} + +// +// Perform a search. If this function returns a '1' then it has +// enumerated the next device and you may retrieve the ROM from the +// OneWire::address variable. If there are no devices, no further +// devices, or something horrible happens in the middle of the +// enumeration then a 0 is returned. If a new device is found then +// its address is copied to newAddr. Use OneWire::reset_search() to +// start over. +// +// --- Replaced by the one from the Dallas Semiconductor web site --- +//-------------------------------------------------------------------------- +// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing +// search state. +// Return TRUE : device found, ROM number in ROM_NO buffer +// FALSE : device not found, end of search +// +uint8_t OneWire::search(uint8_t *newAddr, bool search_mode /* = true */) +{ + uint8_t id_bit_number; + uint8_t last_zero, rom_byte_number, search_result; + uint8_t id_bit, cmp_id_bit; + + unsigned char rom_byte_mask, search_direction; + + // initialize for search + id_bit_number = 1; + last_zero = 0; + rom_byte_number = 0; + rom_byte_mask = 1; + search_result = 0; + + // if the last call was not the last one + if (!LastDeviceFlag) + { + // 1-Wire reset + if (!reset()) + { + // reset the search + LastDiscrepancy = 0; + LastDeviceFlag = FALSE; + LastFamilyDiscrepancy = 0; + return FALSE; + } + + // issue the search command + if (search_mode == true) { + write(0xF0); // NORMAL SEARCH + } else { + write(0xEC); // CONDITIONAL SEARCH + } + + // loop to do the search + do + { + // read a bit and its complement + id_bit = read_bit(); + cmp_id_bit = read_bit(); + + // check for no devices on 1-wire + if ((id_bit == 1) && (cmp_id_bit == 1)) + break; + else + { + // all devices coupled have 0 or 1 + if (id_bit != cmp_id_bit) + search_direction = id_bit; // bit write value for search + else + { + // if this discrepancy if before the Last Discrepancy + // on a previous next then pick the same as last time + if (id_bit_number < LastDiscrepancy) + search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0); + else + // if equal to last pick 1, if not then pick 0 + search_direction = (id_bit_number == LastDiscrepancy); + + // if 0 was picked then record its position in LastZero + if (search_direction == 0) + { + last_zero = id_bit_number; + + // check for Last discrepancy in family + if (last_zero < 9) + LastFamilyDiscrepancy = last_zero; + } + } + + // set or clear the bit in the ROM byte rom_byte_number + // with mask rom_byte_mask + if (search_direction == 1) + ROM_NO[rom_byte_number] |= rom_byte_mask; + else + ROM_NO[rom_byte_number] &= ~rom_byte_mask; + + // serial number search direction write bit + write_bit(search_direction); + + // increment the byte counter id_bit_number + // and shift the mask rom_byte_mask + id_bit_number++; + rom_byte_mask <<= 1; + + // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask + if (rom_byte_mask == 0) + { + rom_byte_number++; + rom_byte_mask = 1; + } + } + } + while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 + + // if the search was successful then + if (!(id_bit_number < 65)) + { + // search successful so set LastDiscrepancy,LastDeviceFlag,search_result + LastDiscrepancy = last_zero; + + // check for last device + if (LastDiscrepancy == 0) + LastDeviceFlag = TRUE; + + search_result = TRUE; + } + } + + // if no device found then reset counters so next 'search' will be like a first + if (!search_result || !ROM_NO[0]) + { + LastDiscrepancy = 0; + LastDeviceFlag = FALSE; + LastFamilyDiscrepancy = 0; + search_result = FALSE; + } else { + for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; + } + return search_result; + } + +#endif + +#if ONEWIRE_CRC +// The 1-Wire CRC scheme is described in Maxim Application Note 27: +// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" +// + +#if ONEWIRE_CRC8_TABLE +// This table comes from Dallas sample code where it is freely reusable, +// though Copyright (C) 2000 Dallas Semiconductor Corporation +static const uint8_t PROGMEM dscrc_table[] = { + 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, + 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, + 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, + 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, + 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, + 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, + 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, + 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, + 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, + 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, + 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, + 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, + 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, + 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, + 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, + 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; + +// +// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM +// and the registers. (note: this might better be done without to +// table, it would probably be smaller and certainly fast enough +// compared to all those delayMicrosecond() calls. But I got +// confused, so I use this table from the examples.) +// +uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + + while (len--) { + crc = pgm_read_byte(dscrc_table + (crc ^ *addr++)); + } + return crc; +} +#else +// +// Compute a Dallas Semiconductor 8 bit CRC directly. +// this is much slower, but much smaller, than the lookup table. +// +uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + + while (len--) { +#if defined(__AVR__) + crc = _crc_ibutton_update(crc, *addr++); +#else + uint8_t inbyte = *addr++; + for (uint8_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) crc ^= 0x8C; + inbyte >>= 1; + } +#endif + } + return crc; +} +#endif + +#if ONEWIRE_CRC16 +bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc) +{ + crc = ~crc16(input, len, crc); + return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1]; +} + +uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc) +{ +#if defined(__AVR__) + for (uint16_t i = 0 ; i < len ; i++) { + crc = _crc16_update(crc, input[i]); + } +#else + static const uint8_t oddparity[16] = + { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; + + for (uint16_t i = 0 ; i < len ; i++) { + // Even though we're just copying a byte from the input, + // we'll be doing 16-bit computation with it. + uint16_t cdata = input[i]; + cdata = (cdata ^ crc) & 0xff; + crc >>= 8; + + if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4]) + crc ^= 0xC001; + + cdata <<= 6; + crc ^= cdata; + cdata <<= 1; + crc ^= cdata; + } +#endif + return crc; +} +#endif + +#endif diff --git a/libraries/OneWire/OneWire.h b/libraries/OneWire/OneWire.h new file mode 100644 index 0000000..b66b7eb --- /dev/null +++ b/libraries/OneWire/OneWire.h @@ -0,0 +1,371 @@ +#ifndef OneWire_h +#define OneWire_h + +#include + +#if defined(__AVR__) +#include +#endif + +#if ARDUINO >= 100 +#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc +#else +#include "WProgram.h" // for delayMicroseconds +#include "pins_arduino.h" // for digitalPinToBitMask, etc +#endif + +// You can exclude certain features from OneWire. In theory, this +// might save some space. In practice, the compiler automatically +// removes unused code (technically, the linker, using -fdata-sections +// and -ffunction-sections when compiling, and Wl,--gc-sections +// when linking), so most of these will not result in any code size +// reduction. Well, unless you try to use the missing features +// and redesign your program to not need them! ONEWIRE_CRC8_TABLE +// is the exception, because it selects a fast but large algorithm +// or a small but slow algorithm. + +// you can exclude onewire_search by defining that to 0 +#ifndef ONEWIRE_SEARCH +#define ONEWIRE_SEARCH 1 +#endif + +// You can exclude CRC checks altogether by defining this to 0 +#ifndef ONEWIRE_CRC +#define ONEWIRE_CRC 1 +#endif + +// Select the table-lookup method of computing the 8-bit CRC +// by setting this to 1. The lookup table enlarges code size by +// about 250 bytes. It does NOT consume RAM (but did in very +// old versions of OneWire). If you disable this, a slower +// but very compact algorithm is used. +#ifndef ONEWIRE_CRC8_TABLE +#define ONEWIRE_CRC8_TABLE 1 +#endif + +// You can allow 16-bit CRC checks by defining this to 1 +// (Note that ONEWIRE_CRC must also be 1.) +#ifndef ONEWIRE_CRC16 +#define ONEWIRE_CRC16 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +// Platform specific I/O definitions + +#if defined(__AVR__) +#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint8_t +#define IO_REG_ASM asm("r30") +#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) +#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) +#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) +#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) + +#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) +#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) +#define PIN_TO_BITMASK(pin) (1) +#define IO_REG_TYPE uint8_t +#define IO_REG_ASM +#define DIRECT_READ(base, mask) (*((base)+512)) +#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) +#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) +#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) +#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) + +#elif defined(__MKL26Z64__) +#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint8_t +#define IO_REG_ASM +#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask)) +#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask)) +#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask)) + +#elif defined(__SAM3X8E__) +// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due. +// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268 +// If you have trouble with OneWire on Arduino Due, please check the +// status of delayMicroseconds() before reporting a bug in OneWire! +#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER)) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint32_t +#define IO_REG_ASM +#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) +#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) +#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) +#ifndef PROGMEM +#define PROGMEM +#endif +#ifndef pgm_read_byte +#define pgm_read_byte(addr) (*(const uint8_t *)(addr)) +#endif + +#elif defined(__PIC32MX__) +#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint32_t +#define IO_REG_ASM +#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 +#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 +#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 +#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 +#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 + +#elif defined(ARDUINO_ARCH_ESP8266) +#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) +#define PIN_TO_BITMASK(pin) (1 << pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_ASM +#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS +#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS +#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS +#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS +#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS + +#elif defined(__SAMD21G18A__) +#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin)) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint32_t +#define IO_REG_ASM +#define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask)) +#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask)) +#define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask)) + +#elif defined(RBL_NRF51822) +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_ASM +#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin) +#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin) +#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin) +#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL) +#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin) + +#elif defined(__arc__) /* Arduino101/Genuino101 specifics */ + +#include "scss_registers.h" +#include "portable.h" +#include "avr/pgmspace.h" + +#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId) +#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType) +#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase) +#define DIR_OFFSET_SS 0x01 +#define DIR_OFFSET_SOC 0x04 +#define EXT_PORT_OFFSET_SS 0x0A +#define EXT_PORT_OFFSET_SOC 0x50 + +/* GPIO registers base address */ +#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase) +#define PIN_TO_BITMASK(pin) pin +#define IO_REG_TYPE uint32_t +#define IO_REG_ASM + +static inline __attribute__((always_inline)) +IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + IO_REG_TYPE ret; + if (SS_GPIO == GPIO_TYPE(pin)) { + ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS)); + } else { + ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC); + } + return ((ret >> GPIO_ID(pin)) & 0x01); +} + +static inline __attribute__((always_inline)) +void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), + ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); + } else { + MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin)); + } +} + +static inline __attribute__((always_inline)) +void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), + ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); + } else { + MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin)); + } +} + +static inline __attribute__((always_inline)) +void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base); + } else { + MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin)); + } +} + +static inline __attribute__((always_inline)) +void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base); + } else { + MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin)); + } +} + +#define DIRECT_READ(base, pin) directRead(base, pin) +#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin) +#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin) +#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin) +#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin) + +#else +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE unsigned int +#define IO_REG_ASM +#define DIRECT_READ(base, pin) digitalRead(pin) +#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW) +#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH) +#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT) +#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT) +#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture." + +#endif + + +class OneWire +{ + private: + IO_REG_TYPE bitmask; + volatile IO_REG_TYPE *baseReg; + +#if ONEWIRE_SEARCH + // global search state + unsigned char ROM_NO[8]; + uint8_t LastDiscrepancy; + uint8_t LastFamilyDiscrepancy; + uint8_t LastDeviceFlag; +#endif + + public: + OneWire( uint8_t pin); + + // Perform a 1-Wire reset cycle. Returns 1 if a device responds + // with a presence pulse. Returns 0 if there is no device or the + // bus is shorted or otherwise held low for more than 250uS + uint8_t reset(void); + + // Issue a 1-Wire rom select command, you do the reset first. + void select(const uint8_t rom[8]); + + // Issue a 1-Wire rom skip command, to address all on bus. + void skip(void); + + // Write a byte. If 'power' is one then the wire is held high at + // the end for parasitically powered devices. You are responsible + // for eventually depowering it by calling depower() or doing + // another read or write. + void write(uint8_t v, uint8_t power = 0); + + void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); + + // Read a byte. + uint8_t read(void); + + void read_bytes(uint8_t *buf, uint16_t count); + + // Write a bit. The bus is always left powered at the end, see + // note in write() about that. + void write_bit(uint8_t v); + + // Read a bit. + uint8_t read_bit(void); + + // Stop forcing power onto the bus. You only need to do this if + // you used the 'power' flag to write() or used a write_bit() call + // and aren't about to do another read or write. You would rather + // not leave this powered if you don't have to, just in case + // someone shorts your bus. + void depower(void); + +#if ONEWIRE_SEARCH + // Clear the search state so that if will start from the beginning again. + void reset_search(); + + // Setup the search to find the device type 'family_code' on the next call + // to search(*newAddr) if it is present. + void target_search(uint8_t family_code); + + // Look for the next device. Returns 1 if a new address has been + // returned. A zero might mean that the bus is shorted, there are + // no devices, or you have already retrieved all of them. It + // might be a good idea to check the CRC to make sure you didn't + // get garbage. The order is deterministic. You will always get + // the same devices in the same order. + uint8_t search(uint8_t *newAddr, bool search_mode = true); +#endif + +#if ONEWIRE_CRC + // Compute a Dallas Semiconductor 8 bit CRC, these are used in the + // ROM and scratchpad registers. + static uint8_t crc8(const uint8_t *addr, uint8_t len); + +#if ONEWIRE_CRC16 + // Compute the 1-Wire CRC16 and compare it against the received CRC. + // Example usage (reading a DS2408): + // // Put everything in a buffer so we can compute the CRC easily. + // uint8_t buf[13]; + // buf[0] = 0xF0; // Read PIO Registers + // buf[1] = 0x88; // LSB address + // buf[2] = 0x00; // MSB address + // WriteBytes(net, buf, 3); // Write 3 cmd bytes + // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 + // if (!CheckCRC16(buf, 11, &buf[11])) { + // // Handle error. + // } + // + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param inverted_crc - The two CRC16 bytes in the received data. + // This should just point into the received data, + // *not* at a 16-bit integer. + // @param crc - The crc starting value (optional) + // @return True, iff the CRC matches. + static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); + + // Compute a Dallas Semiconductor 16 bit CRC. This is required to check + // the integrity of data received from many 1-Wire devices. Note that the + // CRC computed here is *not* what you'll get from the 1-Wire network, + // for two reasons: + // 1) The CRC is transmitted bitwise inverted. + // 2) Depending on the endian-ness of your processor, the binary + // representation of the two-byte return value may have a different + // byte order than the two bytes you get from 1-Wire. + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param crc - The crc starting value (optional) + // @return The CRC16, as defined by Dallas Semiconductor. + static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); +#endif +#endif +}; + +#endif diff --git a/libraries/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/libraries/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde new file mode 100644 index 0000000..68ca194 --- /dev/null +++ b/libraries/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde @@ -0,0 +1,112 @@ +#include + +// OneWire DS18S20, DS18B20, DS1822 Temperature Example +// +// http://www.pjrc.com/teensy/td_libs_OneWire.html +// +// The DallasTemperature library can do all this work for you! +// http://milesburton.com/Dallas_Temperature_Control_Library + +OneWire ds(10); // on pin 10 (a 4.7K resistor is necessary) + +void setup(void) { + Serial.begin(9600); +} + +void loop(void) { + byte i; + byte present = 0; + byte type_s; + byte data[12]; + byte addr[8]; + float celsius, fahrenheit; + + if ( !ds.search(addr)) { + Serial.println("No more addresses."); + Serial.println(); + ds.reset_search(); + delay(250); + return; + } + + Serial.print("ROM ="); + for( i = 0; i < 8; i++) { + Serial.write(' '); + Serial.print(addr[i], HEX); + } + + if (OneWire::crc8(addr, 7) != addr[7]) { + Serial.println("CRC is not valid!"); + return; + } + Serial.println(); + + // the first ROM byte indicates which chip + switch (addr[0]) { + case 0x10: + Serial.println(" Chip = DS18S20"); // or old DS1820 + type_s = 1; + break; + case 0x28: + Serial.println(" Chip = DS18B20"); + type_s = 0; + break; + case 0x22: + Serial.println(" Chip = DS1822"); + type_s = 0; + break; + default: + Serial.println("Device is not a DS18x20 family device."); + return; + } + + ds.reset(); + ds.select(addr); + ds.write(0x44, 1); // start conversion, with parasite power on at the end + + delay(1000); // maybe 750ms is enough, maybe not + // we might do a ds.depower() here, but the reset will take care of it. + + present = ds.reset(); + ds.select(addr); + ds.write(0xBE); // Read Scratchpad + + Serial.print(" Data = "); + Serial.print(present, HEX); + Serial.print(" "); + for ( i = 0; i < 9; i++) { // we need 9 bytes + data[i] = ds.read(); + Serial.print(data[i], HEX); + Serial.print(" "); + } + Serial.print(" CRC="); + Serial.print(OneWire::crc8(data, 8), HEX); + Serial.println(); + + // Convert the data to actual temperature + // because the result is a 16 bit signed integer, it should + // be stored to an "int16_t" type, which is always 16 bits + // even when compiled on a 32 bit processor. + int16_t raw = (data[1] << 8) | data[0]; + if (type_s) { + raw = raw << 3; // 9 bit resolution default + if (data[7] == 0x10) { + // "count remain" gives full 12 bit resolution + raw = (raw & 0xFFF0) + 12 - data[6]; + } + } else { + byte cfg = (data[4] & 0x60); + // at lower res, the low bits are undefined, so let's zero them + if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms + else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms + else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms + //// default is 12 bit resolution, 750 ms conversion time + } + celsius = (float)raw / 16.0; + fahrenheit = celsius * 1.8 + 32.0; + Serial.print(" Temperature = "); + Serial.print(celsius); + Serial.print(" Celsius, "); + Serial.print(fahrenheit); + Serial.println(" Fahrenheit"); +} diff --git a/libraries/OneWire/examples/DS2408_Switch/DS2408_Switch.pde b/libraries/OneWire/examples/DS2408_Switch/DS2408_Switch.pde new file mode 100644 index 0000000..d171f9b --- /dev/null +++ b/libraries/OneWire/examples/DS2408_Switch/DS2408_Switch.pde @@ -0,0 +1,77 @@ +#include + +/* + * DS2408 8-Channel Addressable Switch + * + * Writte by Glenn Trewitt, glenn at trewitt dot org + * + * Some notes about the DS2408: + * - Unlike most input/output ports, the DS2408 doesn't have mode bits to + * set whether the pins are input or output. If you issue a read command, + * they're inputs. If you write to them, they're outputs. + * - For reading from a switch, you should use 10K pull-up resisters. + */ + +void PrintBytes(uint8_t* addr, uint8_t count, bool newline=0) { + for (uint8_t i = 0; i < count; i++) { + Serial.print(addr[i]>>4, HEX); + Serial.print(addr[i]&0x0f, HEX); + } + if (newline) + Serial.println(); +} + +void ReadAndReport(OneWire* net, uint8_t* addr) { + Serial.print(" Reading DS2408 "); + PrintBytes(addr, 8); + Serial.println(); + + uint8_t buf[13]; // Put everything in the buffer so we can compute CRC easily. + buf[0] = 0xF0; // Read PIO Registers + buf[1] = 0x88; // LSB address + buf[2] = 0x00; // MSB address + net->write_bytes(buf, 3); + net->read_bytes(buf+3, 10); // 3 cmd bytes, 6 data bytes, 2 0xFF, 2 CRC16 + net->reset(); + + if (!OneWire::check_crc16(buf, 11, &buf[11])) { + Serial.print("CRC failure in DS2408 at "); + PrintBytes(addr, 8, true); + return; + } + Serial.print(" DS2408 data = "); + // First 3 bytes contain command, register address. + Serial.println(buf[3], BIN); +} + +OneWire net(10); // on pin 10 + +void setup(void) { + Serial.begin(9600); +} + +void loop(void) { + byte i; + byte present = 0; + byte addr[8]; + + if (!net.search(addr)) { + Serial.print("No more addresses.\n"); + net.reset_search(); + delay(1000); + return; + } + + if (OneWire::crc8(addr, 7) != addr[7]) { + Serial.print("CRC is not valid!\n"); + return; + } + + if (addr[0] != 0x29) { + PrintBytes(addr, 8); + Serial.print(" is not a DS2408.\n"); + return; + } + + ReadAndReport(&net, addr); +} diff --git a/libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde b/libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde new file mode 100644 index 0000000..a85b1c2 --- /dev/null +++ b/libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde @@ -0,0 +1,90 @@ +/* +DS250x add-only programmable memory reader w/SKIP ROM. + + The DS250x is a 512/1024bit add-only PROM(you can add data but cannot change the old one) that's used mainly for device identification purposes + like serial number, mfgr data, unique identifiers, etc. It uses the Maxim 1-wire bus. + + This sketch will use the SKIP ROM function that skips the 1-Wire search phase since we only have one device connected in the bus on digital pin 6. + If more than one device is connected to the bus, it will fail. + Sketch will not verify if device connected is from the DS250x family since the skip rom function effectively skips the family-id byte readout. + thus it is possible to run this sketch with any Maxim OneWire device in which case the command CRC will most likely fail. + Sketch will only read the first page of memory(32bits) starting from the lower address(0000h), if more than 1 device is present, then use the sketch with search functions. + Remember to put a 4.7K pullup resistor between pin 6 and +Vcc + + To change the range or ammount of data to read, simply change the data array size, LSB/MSB addresses and for loop iterations + + This example code is in the public domain and is provided AS-IS. + + Built with Arduino 0022 and PJRC OneWire 2.0 library http://www.pjrc.com/teensy/td_libs_OneWire.html + + created by Guillermo Lovato + march/2011 + + */ + +#include +OneWire ds(6); // OneWire bus on digital pin 6 +void setup() { + Serial.begin (9600); +} + +void loop() { + byte i; // This is for the for loops + boolean present; // device present var + byte data[32]; // container for the data from device + byte leemem[3] = { // array with the commands to initiate a read, DS250x devices expect 3 bytes to start a read: command,LSB&MSB adresses + 0xF0 , 0x00 , 0x00 }; // 0xF0 is the Read Data command, followed by 00h 00h as starting address(the beginning, 0000h) + byte ccrc; // Variable to store the command CRC + byte ccrc_calc; + + present = ds.reset(); // OneWire bus reset, always needed to start operation on the bus, returns a 1/TRUE if there's a device present. + ds.skip(); // Skip ROM search + + if (present == TRUE){ // We only try to read the data if there's a device present + Serial.println("DS250x device present"); + ds.write(leemem[0],1); // Read data command, leave ghost power on + ds.write(leemem[1],1); // LSB starting address, leave ghost power on + ds.write(leemem[2],1); // MSB starting address, leave ghost power on + + ccrc = ds.read(); // DS250x generates a CRC for the command we sent, we assign a read slot and store it's value + ccrc_calc = OneWire::crc8(leemem, 3); // We calculate the CRC of the commands we sent using the library function and store it + + if ( ccrc_calc != ccrc) { // Then we compare it to the value the ds250x calculated, if it fails, we print debug messages and abort + Serial.println("Invalid command CRC!"); + Serial.print("Calculated CRC:"); + Serial.println(ccrc_calc,HEX); // HEX makes it easier to observe and compare + Serial.print("DS250x readback CRC:"); + Serial.println(ccrc,HEX); + return; // Since CRC failed, we abort the rest of the loop and start over + } + Serial.println("Data is: "); // For the printout of the data + for ( i = 0; i < 32; i++) { // Now it's time to read the PROM data itself, each page is 32 bytes so we need 32 read commands + data[i] = ds.read(); // we store each read byte to a different position in the data array + Serial.print(data[i]); // printout in ASCII + Serial.print(" "); // blank space + } + Serial.println(); + delay(5000); // Delay so we don't saturate the serial output + } + else { // Nothing is connected in the bus + Serial.println("Nothing connected"); + delay(3000); + } +} + + + + + + + + + + + + + + + + + diff --git a/libraries/OneWire/keywords.txt b/libraries/OneWire/keywords.txt new file mode 100644 index 0000000..bee5d90 --- /dev/null +++ b/libraries/OneWire/keywords.txt @@ -0,0 +1,38 @@ +####################################### +# Syntax Coloring Map For OneWire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +OneWire KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +reset KEYWORD2 +write_bit KEYWORD2 +read_bit KEYWORD2 +write KEYWORD2 +write_bytes KEYWORD2 +read KEYWORD2 +read_bytes KEYWORD2 +select KEYWORD2 +skip KEYWORD2 +depower KEYWORD2 +reset_search KEYWORD2 +search KEYWORD2 +crc8 KEYWORD2 +crc16 KEYWORD2 +check_crc16 KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/OneWire/library.json b/libraries/OneWire/library.json new file mode 100644 index 0000000..ed23250 --- /dev/null +++ b/libraries/OneWire/library.json @@ -0,0 +1,58 @@ +{ +"name": "OneWire", +"frameworks": "Arduino", +"keywords": "onewire, 1-wire, bus, sensor, temperature, ibutton", +"description": "Control 1-Wire protocol (DS18S20, DS18B20, DS2408 and etc)", +"authors": +[ + { + "name": "Paul Stoffregen", + "email": "paul@pjrc.com", + "url": "http://www.pjrc.com", + "maintainer": true + }, + { + "name": "Jim Studt" + }, + { + "name": "Tom Pollard", + "email": "pollard@alum.mit.edu" + }, + { + "name": "Derek Yerger" + }, + { + "name": "Josh Larios" + }, + { + "name": "Robin James" + }, + { + "name": "Glenn Trewitt" + }, + { + "name": "Jason Dangel", + "email": "dangel.jason AT gmail.com" + }, + { + "name": "Guillermo Lovato" + }, + { + "name": "Ken Butcher" + }, + { + "name": "Mark Tillotson" + }, + { + "name": "Bertrik Sikken" + }, + { + "name": "Scott Roberts" + } +], +"repository": +{ + "type": "git", + "url": "https://github.com/PaulStoffregen/OneWire" +} +} diff --git a/libraries/OneWire/library.properties b/libraries/OneWire/library.properties new file mode 100644 index 0000000..0946c9a --- /dev/null +++ b/libraries/OneWire/library.properties @@ -0,0 +1,10 @@ +name=OneWire +version=2.3.2 +author=Jim Studt, Tom Pollard, Robin James, Glenn Trewitt, Jason Dangel, Guillermo Lovato, Paul Stoffregen, Scott Roberts, Bertrik Sikken, Mark Tillotson, Ken Butcher, Roger Clark, Love Nystrom +maintainer=Paul Stoffregen +sentence=Access 1-wire temperature sensors, memory and other chips. +paragraph= +category=Communication +url=http://www.pjrc.com/teensy/td_libs_OneWire.html +architectures=* + diff --git a/libraries/VirtualWire/CHANGES b/libraries/VirtualWire/CHANGES new file mode 100644 index 0000000..3a12f6e --- /dev/null +++ b/libraries/VirtualWire/CHANGES @@ -0,0 +1,16 @@ +1.3 2009-04-01 + Fixed a compatibility problem with ATMEGA328 of the new arduino + Now use SIGNAL(TIMER1_COMPA_vect) instead of ISR(SIG_OUTPUT_COMPARE1A) + as discussed in + http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1237714550/11 + and reported by Jaime Castro. + +1.2 2009-03-30 + Fixed a problem that prevented compiling with arduino-0015 + Reported by Jaime Castro + +1.1 2008-06-24 + Now can compile for atmega8 + Reported by creatrope + +1.0 Original release diff --git a/libraries/VirtualWire/LICENSE b/libraries/VirtualWire/LICENSE new file mode 100644 index 0000000..da124e1 --- /dev/null +++ b/libraries/VirtualWire/LICENSE @@ -0,0 +1,17 @@ +This software is Copyright (C) 2008 Mike McCauley. Use is subject to license +conditions. The main licensing options available are GPL V2 or Commercial: + +Open Source Licensing GPL V2 + +This is the appropriate option if you want to share the source code of your +application with everyone you distribute it to, and you also want to give them +the right to share who uses it. If you wish to use this software under Open +Source Licensing, you must contribute all your source code to the open source +community in accordance with the GPL Version 2 when your application is +distributed. See http://www.gnu.org/copyleft/gpl.html + +Commercial Licensing + +This is the appropriate option if you are creating proprietary applications +and you are not prepared to distribute and share the source code of your +application. Contact info@open.com.au for details. diff --git a/libraries/VirtualWire/MANIFEST b/libraries/VirtualWire/MANIFEST new file mode 100644 index 0000000..dd9c5ae --- /dev/null +++ b/libraries/VirtualWire/MANIFEST @@ -0,0 +1,12 @@ +VirtualWire/MANIFEST +VirtualWire/README +VirtualWire/LICENSE +VirtualWire/CHANGES +VirtualWire/VirtualWire.cpp +VirtualWire/VirtualWire.h +VirtualWire/examples/client/client.pde +VirtualWire/examples/server/server.pde +VirtualWire/examples/receiver/receiver.pde +VirtualWire/examples/transmitter/transmitter.pde + + diff --git a/libraries/VirtualWire/Makefile b/libraries/VirtualWire/Makefile new file mode 100644 index 0000000..fb53d5c --- /dev/null +++ b/libraries/VirtualWire/Makefile @@ -0,0 +1,26 @@ +# Makefile +# +# Makefile for the Arduino VirtualWire project +# +# Author: Mike McCauley (mikem@airspayce.com) +# Copyright (C) 2011 Mike McCauley +# $Id: Makefile,v 1.1 2013/01/14 06:49:29 mikem Exp mikem $ + +PROJNAME = VirtualWire +# Dont forget to also change the version at the top of RF22.h: +DISTFILE = $(PROJNAME)-1.15.zip + +all: doxygen dist upload + +doxygen: + doxygen project.cfg + +ci: + (cd ..;ci -l `cat $(PROJNAME)/MANIFEST`) + +dist: + (cd ..; zip $(PROJNAME)/$(DISTFILE) `cat $(PROJNAME)/MANIFEST`) + +upload: + rsync -avz $(DISTFILE) doc/ www.airspayce.com:public_html/mikem/arduino/$(PROJNAME) + rsync -avz ../../doc/VirtualWire.pdf doc/ www.airspayce.com:public_html/mikem/arduino/ diff --git a/libraries/VirtualWire/README b/libraries/VirtualWire/README new file mode 100644 index 0000000..1ea8627 --- /dev/null +++ b/libraries/VirtualWire/README @@ -0,0 +1,8 @@ +Virtual Wire + +This is the VirtualWire library for Arduino +It provides a simple message passing protocol for a range of inexpensive +transmitter and receiver modules. + +See http://www.open.com.au/mikem/arduino/VirtualWire.pdf for full documentation. + diff --git a/libraries/VirtualWire/VWutil/crc16.h b/libraries/VirtualWire/VWutil/crc16.h new file mode 100644 index 0000000..18c173c --- /dev/null +++ b/libraries/VirtualWire/VWutil/crc16.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz + Copyright (c) 2005, 2007 Joerg Wunsch + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ + +// Port to Energia / MPS430 by Yannick DEVOS XV4Y - (c) 2013 +// http://xv4y.radioclub.asia/ +// + +/* $Id: crc16.h 2136 2010-06-08 12:03:38Z joerg_wunsch $ */ + +#ifndef _UTIL_CRC16_H_ +#define _UTIL_CRC16_H_ + +#include + +#define lo8(x) ((x)&0xff) +#define hi8(x) ((x)>>8) + + uint16_t crc16_update(uint16_t crc, uint8_t a) + { + int i; + + crc ^= a; + for (i = 0; i < 8; ++i) + { + if (crc & 1) + crc = (crc >> 1) ^ 0xA001; + else + crc = (crc >> 1); + } + + return crc; + } + + uint16_t crc_xmodem_update (uint16_t crc, uint8_t data) + { + int i; + + crc = crc ^ ((uint16_t)data << 8); + for (i=0; i<8; i++) + { + if (crc & 0x8000) + crc = (crc << 1) ^ 0x1021; + else + crc <<= 1; + } + + return crc; + } + uint16_t _crc_ccitt_update (uint16_t crc, uint8_t data) + { + data ^= lo8 (crc); + data ^= data << 4; + + return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) + ^ ((uint16_t)data << 3)); + } + + uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data) + { + uint8_t i; + + crc = crc ^ data; + for (i = 0; i < 8; i++) + { + if (crc & 0x01) + crc = (crc >> 1) ^ 0x8C; + else + crc >>= 1; + } + + return crc; + } + + +#endif /* _UTIL_CRC16_H_ */ diff --git a/libraries/VirtualWire/VirtualWire.cpp b/libraries/VirtualWire/VirtualWire.cpp new file mode 100644 index 0000000..7e90873 --- /dev/null +++ b/libraries/VirtualWire/VirtualWire.cpp @@ -0,0 +1,478 @@ +// VirtualWire.cpp +// +// Virtual Wire implementation for Arduino +// See the README file in this directory fdor documentation +// +// Changes: +// 2008-05-25: fixed a bug that could prevent messages with certain +// bytes sequences being received (false message start detected) +// +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: VirtualWire.cpp,v 1.4 2009/03/31 20:49:41 mikem Exp mikem $ + +#include "WProgram.h" +#include "VirtualWire.h" +#include + +static uint8_t vw_tx_buf[(VW_MAX_MESSAGE_LEN * 2) + VW_HEADER_LEN] + = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c}; + +// Number of symbols in vw_tx_buf to be sent; +static uint8_t vw_tx_len = 0; + +// Index of the next symbol to send. Ranges from 0 to vw_tx_len +static uint8_t vw_tx_index = 0; + +// Bit number of next bit to send +static uint8_t vw_tx_bit = 0; + +// Sample number for the transmitter. Runs 0 to 7 during one bit interval +static uint8_t vw_tx_sample = 0; + +// Flag to indicated the transmitter is active +static volatile uint8_t vw_tx_enabled = 0; + +// Total number of messages sent +static uint16_t vw_tx_msg_count = 0; + +// The digital IO pin number of the press to talk, enables the transmitter hardware +static uint8_t vw_ptt_pin = 10; +static uint8_t vw_ptt_inverted = 0; + +// The digital IO pin number of the receiver data +static uint8_t vw_rx_pin = 11; + +// The digital IO pin number of the transmitter data +static uint8_t vw_tx_pin = 12; + +// Current receiver sample +static uint8_t vw_rx_sample = 0; + +// Last receiver sample +static uint8_t vw_rx_last_sample = 0; + +// PLL ramp, varies between 0 and VW_RX_RAMP_LEN-1 (159) over +// VW_RX_SAMPLES_PER_BIT (8) samples per nominal bit time. +// When the PLL is synchronised, bit transitions happen at about the +// 0 mark. +static uint8_t vw_rx_pll_ramp = 0; + +// This is the integrate and dump integral. If there are <5 0 samples in the PLL cycle +// the bit is declared a 0, else a 1 +static uint8_t vw_rx_integrator = 0; + +// Flag indictate if we have seen the start symbol of a new message and are +// in the processes of reading and decoding it +static uint8_t vw_rx_active = 0; + +// Flag to indicate that a new message is available +static volatile uint8_t vw_rx_done = 0; + +// Flag to indicate the receiver PLL is to run +static uint8_t vw_rx_enabled = 0; + +// Last 12 bits received, so we can look for the start symbol +static uint16_t vw_rx_bits = 0; + +// How many bits of message we have received. Ranges from 0 to 12 +static uint8_t vw_rx_bit_count = 0; + +// The incoming message buffer +static uint8_t vw_rx_buf[VW_MAX_MESSAGE_LEN]; + +// The incoming message expected length +static uint8_t vw_rx_count = 0; + +// The incoming message buffer length received so far +static volatile uint8_t vw_rx_len = 0; + +// Number of bad messages received and dropped due to bad lengths +static uint8_t vw_rx_bad = 0; + +// Number of good messages received +static uint8_t vw_rx_good = 0; + +// 4 bit to 6 bit symbol converter table +// Used to convert the high and low nybbles of the transmitted data +// into 6 bit symbols for transmission. Each 6-bit symbol has 3 1s and 3 0s +// with at most 2 consecutive identical bits +static uint8_t symbols[] = +{ + 0xd, 0xe, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, + 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34 +}; + +// Cant really do this as a real C++ class, since we need to have +// an ISR +extern "C" +{ + +// Compute CRC over count bytes. +// This should only be ever called at user level, not interrupt level +uint16_t vw_crc(uint8_t *ptr, uint8_t count) +{ + uint16_t crc = 0xffff; + + while (count-- > 0) + crc = _crc_ccitt_update(crc, *ptr++); + return crc; +} + +// Convert a 6 bit encoded symbol into its 4 bit decoded equivalent +uint8_t vw_symbol_6to4(uint8_t symbol) +{ + uint8_t i; + + // Linear search :-( Could have a 64 byte reverse lookup table? + for (i = 0; i < 16; i++) + if (symbol == symbols[i]) return i; + return 0; // Not found +} + +// Set the output pin number for transmitter data +void vw_set_tx_pin(uint8_t pin) +{ + vw_tx_pin = pin; +} + +// Set the pin number for input receiver data +void vw_set_rx_pin(uint8_t pin) +{ + vw_rx_pin = pin; +} + +// Set the output pin number for transmitter PTT enable +void vw_set_ptt_pin(uint8_t pin) +{ + vw_ptt_pin = pin; +} + +// Set the ptt pin inverted (low to transmit) +void vw_set_ptt_inverted(uint8_t inverted) +{ + vw_ptt_inverted = inverted; +} + +// Called 8 times per bit period +// Phase locked loop tries to synchronise with the transmitter so that bit +// transitions occur at about the time vw_rx_pll_ramp is 0; +// Then the average is computed over each bit period to deduce the bit value +void vw_pll() +{ + // Integrate each sample + if (vw_rx_sample) + vw_rx_integrator++; + + if (vw_rx_sample != vw_rx_last_sample) + { + // Transition, advance if ramp > 80, retard if < 80 + vw_rx_pll_ramp += ((vw_rx_pll_ramp < VW_RAMP_TRANSITION) + ? VW_RAMP_INC_RETARD + : VW_RAMP_INC_ADVANCE); + vw_rx_last_sample = vw_rx_sample; + } + else + { + // No transition + // Advance ramp by standard 20 (== 160/8 samples) + vw_rx_pll_ramp += VW_RAMP_INC; + } + if (vw_rx_pll_ramp >= VW_RX_RAMP_LEN) + { + // Add this to the 12th bit of vw_rx_bits, LSB first + // The last 12 bits are kept + vw_rx_bits >>= 1; + + // Check the integrator to see how many samples in this cycle were high. + // If < 5 out of 8, then its declared a 0 bit, else a 1; + if (vw_rx_integrator >= 5) + vw_rx_bits |= 0x800; + + vw_rx_pll_ramp -= VW_RX_RAMP_LEN; + vw_rx_integrator = 0; // Clear the integral for the next cycle + + if (vw_rx_active) + { + // We have the start symbol and now we are collecting message bits, + // 6 per symbol, each which has to be decoded to 4 bits + if (++vw_rx_bit_count >= 12) + { + // Have 12 bits of encoded message == 1 byte encoded + // Decode as 2 lots of 6 bits into 2 lots of 4 bits + // The 6 lsbits are the high nybble + uint8_t this_byte = + (vw_symbol_6to4(vw_rx_bits & 0x3f)) << 4 + | vw_symbol_6to4(vw_rx_bits >> 6); + + // The first decoded byte is the byte count of the following message + // the count includes the byte count and the 2 trailing FCS bytes + // REVISIT: may also include the ACK flag at 0x40 + if (vw_rx_len == 0) + { + // The first byte is the byte count + // Check it for sensibility. It cant be less than 4, since it + // includes the bytes count itself and the 2 byte FCS + vw_rx_count = this_byte; + if (vw_rx_count < 4 || vw_rx_count > VW_MAX_MESSAGE_LEN) + { + // Stupid message length, drop the whole thing + vw_rx_active = false; + vw_rx_bad++; + return; + } + } + vw_rx_buf[vw_rx_len++] = this_byte; + + if (vw_rx_len >= vw_rx_count) + { + // Got all the bytes now + vw_rx_active = false; + vw_rx_good++; + vw_rx_done = true; // Better come get it before the next one starts + } + vw_rx_bit_count = 0; + } + } + // Not in a message, see if we have a start symbol + else if (vw_rx_bits == 0xb38) + { + // Have start symbol, start collecting message + vw_rx_active = true; + vw_rx_bit_count = 0; + vw_rx_len = 0; + vw_rx_done = false; // Too bad if you missed the last message + } + } +} + +// Speed is in bits per sec RF rate +void vw_setup(uint16_t speed) +{ + // Calculate the OCR1A overflow count based on the required bit speed + // and CPU clock rate + uint16_t ocr1a = (F_CPU / 8UL) / speed; + +#ifndef TEST + // Set up timer1 for a tick every 62.50 microseconds + // for 2000 bits per sec + TCCR1A = 0; + TCCR1B = _BV(WGM12) | _BV(CS10); + // Caution: special procedures for setting 16 bit regs + OCR1A = ocr1a; + // Enable interrupt +#ifdef TIMSK1 + // atmega168 + TIMSK1 |= _BV(OCIE1A); +#else + // others + TIMSK |= _BV(OCIE1A); +#endif + +#endif + + // Set up digital IO pins + pinMode(vw_tx_pin, OUTPUT); + pinMode(vw_rx_pin, INPUT); + pinMode(vw_ptt_pin, OUTPUT); + digitalWrite(vw_ptt_pin, vw_ptt_inverted); +} + +// Start the transmitter, call when the tx buffer is ready to go and vw_tx_len is +// set to the total number of symbols to send +void vw_tx_start() +{ + vw_tx_index = 0; + vw_tx_bit = 0; + vw_tx_sample = 0; + + // Disable the receiver PLL + vw_rx_enabled = false; + + // Enable the transmitter hardware + digitalWrite(vw_ptt_pin, true ^ vw_ptt_inverted); + + // Next tick interrupt will send the first bit + vw_tx_enabled = true; +} + +// Stop the transmitter, call when all bits are sent +void vw_tx_stop() +{ + // Disable the transmitter hardware + digitalWrite(vw_ptt_pin, false ^ vw_ptt_inverted); + digitalWrite(vw_tx_pin, false); + + // No more ticks for the transmitter + vw_tx_enabled = false; + + // Enable the receiver PLL + vw_rx_enabled = true; +} + +// Enable the receiver. When a message becomes available, vw_rx_done flag +// is set, and vw_wait_rx() will return. +void vw_rx_start() +{ + if (!vw_rx_enabled) + { + vw_rx_enabled = true; + vw_rx_active = false; // Never restart a partial message + } +} + +// Disable the receiver +void vw_rx_stop() +{ + vw_rx_enabled = false; +} + +// Wait for the transmitter to become available +// Busy-wait loop until the ISR says the message has been sent +void vw_wait_tx() +{ + while (vw_tx_enabled) + ; +} + +// Wait for the receiver to get a message +// Busy-wait loop until the ISR says a message is available +// can then call vw_get_message() +void vw_wait_rx() +{ + while (!vw_rx_done) + ; +} + +// Wait at most max milliseconds for the receiver to receive a message +// Return the truth of whether there is a message +uint8_t vw_wait_rx_max(unsigned long milliseconds) +{ + unsigned long start = millis(); + + while (!vw_rx_done && ((millis() - start) < milliseconds)) + ; + return vw_rx_done; +} + +// Wait until transmitter is available and encode and queue the message +// into vw_tx_buf +// The message is raw bytes, with no packet structure imposed +// It is transmitted preceded a byte count and followed by 2 FCS bytes +uint8_t vw_send(uint8_t* buf, uint8_t len) +{ + uint8_t i; + uint8_t index = 0; + uint16_t crc = 0xffff; + uint8_t *p = vw_tx_buf + VW_HEADER_LEN; // start of the message area + uint8_t count = len + 3; // Added byte count and FCS to get total number of bytes + + if (len > VW_MAX_PAYLOAD) + return false; + + // Wait for transmitter to become available + vw_wait_tx(); + + // Encode the message length + crc = _crc_ccitt_update(crc, count); + p[index++] = symbols[count >> 4]; + p[index++] = symbols[count & 0xf]; + + // Encode the message into 6 bit symbols. Each byte is converted into + // 2 6-bit symbols, high nybble first, low nybble second + for (i = 0; i < len; i++) + { + crc = _crc_ccitt_update(crc, buf[i]); + p[index++] = symbols[buf[i] >> 4]; + p[index++] = symbols[buf[i] & 0xf]; + } + + // Append the fcs, 16 bits before encoding (4 6-bit symbols after encoding) + // Caution: VW expects the _ones_complement_ of the CCITT CRC-16 as the FCS + // VW sends FCS as low byte then hi byte + crc = ~crc; + p[index++] = symbols[(crc >> 4) & 0xf]; + p[index++] = symbols[crc & 0xf]; + p[index++] = symbols[(crc >> 12) & 0xf]; + p[index++] = symbols[(crc >> 8) & 0xf]; + + // Total number of 6-bit symbols to send + vw_tx_len = index + VW_HEADER_LEN; + + // Start the low level interrupt handler sending symbols + vw_tx_start(); + + return true; +} + +// This is the interrupt service routine called when timer1 overflows +// Its job is to output the next bit from the transmitter (every 8 calls) +// and to call the PLL code if the receiver is enabled +//ISR(SIG_OUTPUT_COMPARE1A) +SIGNAL(TIMER1_COMPA_vect) +{ + vw_rx_sample = digitalRead(vw_rx_pin); + + // Do transmitter stuff first to reduce transmitter bit jitter due + // to variable receiver processing + if (vw_tx_enabled && vw_tx_sample++ == 0) + { + // Send next bit + // Symbols are sent LSB first + // Finished sending the whole message? (after waiting one bit period + // since the last bit) + if (vw_tx_index >= vw_tx_len) + { + vw_tx_stop(); + vw_tx_msg_count++; + } + else + { + digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++)); + if (vw_tx_bit >= 6) + { + vw_tx_bit = 0; + vw_tx_index++; + } + } + } + if (vw_tx_sample > 7) + vw_tx_sample = 0; + + if (vw_rx_enabled) + vw_pll(); +} + +// Return true if there is a message available +uint8_t vw_have_message() +{ + return vw_rx_done; +} + +// Get the last message received (without byte count or FCS) +// Copy at most *len bytes, set *len to the actual number copied +// Return true if there is a message and the FCS is OK +uint8_t vw_get_message(uint8_t* buf, uint8_t* len) +{ + uint8_t rxlen; + + // Message available? + if (!vw_rx_done) + return false; + + // Wait until vw_rx_done is set before reading vw_rx_len + // then remove bytecount and FCS + rxlen = vw_rx_len - 3; + + // Copy message (good or bad) + if (*len > rxlen) + *len = rxlen; + memcpy(buf, vw_rx_buf + 1, *len); + + vw_rx_done = false; // OK, got that message thanks + + // Check the FCS, return goodness + return (vw_crc(vw_rx_buf, vw_rx_len) == 0xf0b8); // FCS OK? +} + +} diff --git a/libraries/VirtualWire/VirtualWire.h b/libraries/VirtualWire/VirtualWire.h new file mode 100644 index 0000000..63f0b41 --- /dev/null +++ b/libraries/VirtualWire/VirtualWire.h @@ -0,0 +1,107 @@ +// VirtualWire.h +// +// Virtual Wire implementation for Arduino +// See the README file in this directory fdor documentation +// +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: VirtualWire.h,v 1.3 2009/03/30 00:07:24 mikem Exp $ + +#ifndef VirtualWire_h +#define VirtualWire_h + +#include +#include + +// Maximum number of bytes in a message, counting the byte count and FCS +#define VW_MAX_MESSAGE_LEN 30 + +// The maximum payload length +#define VW_MAX_PAYLOAD VW_MAX_MESSAGE_LEN-3 + +// The size of the receiver ramp. Ramp wraps modulu this number +#define VW_RX_RAMP_LEN 160 + +// Number of samples per bit +#define VW_RX_SAMPLES_PER_BIT 8 + +// Ramp adjustment parameters +// Standard is if a transition occurs before VW_RAMP_TRANSITION (80) in the ramp, +// the ramp is retarded by adding VW_RAMP_INC_RETARD (11) +// else by adding VW_RAMP_INC_ADVANCE (29) +// If there is no transition it is adjusted by VW_RAMP_INC (20) +#define VW_RAMP_INC (VW_RX_RAMP_LEN/VW_RX_SAMPLES_PER_BIT) +#define VW_RAMP_TRANSITION VW_RX_RAMP_LEN/2 +#define VW_RAMP_ADJUST 9 +#define VW_RAMP_INC_RETARD (VW_RAMP_INC-VW_RAMP_ADJUST) +#define VW_RAMP_INC_ADVANCE (VW_RAMP_INC+VW_RAMP_ADJUST) + +// Outgoing message bits grouped as 6-bit words +// 36 alternating 1/0 bits, followed by 12 bits of start symbol +// Followed immediately by the 4-6 bit encoded byte count, +// message buffer and 2 byte FCS +// Each byte from the byte count on is translated into 2x6-bit words +// Caution, each symbol is transmitted LSBit first, +// but each byte is transmitted high nybble first +#define VW_HEADER_LEN 8 + +// Cant really do this as a real C++ class, since we need to have +// an ISR +extern "C" +{ + // Set the digital IO pin to be for transmit data + // Defaults to 12 + extern void vw_set_tx_pin(uint8_t pin); + + // Set the digital IO pin to be for receive data + // Defaults to 11 + extern void vw_set_rx_pin(uint8_t pin); + + // Set the digital IO pin to enable the transmitter (press to talk) + // Defaults to 10 + extern void vw_set_ptt_pin(uint8_t pin); + + // By default the PTT pin goes high when the transmitter is enabled. + // This flag forces it low when the transmitter is enabled. + extern void vw_set_ptt_inverted(uint8_t inverted); + + // Initialise the VirtualWire software, to operate at speed bits per second + // Call this one in your setup() after any vw_set_* calls + // Must call vw_rx_start() before you will get any messages + extern void vw_setup(uint16_t speed); + + // Start the Phase Locked Loop listening to the receiver + // Must do this before you can receive any messages + // When a message is available (good checksum or not), vw_have_message(); + // will return true. + extern void vw_rx_start(); + + // Stop the Phase Locked Loop listening to the receiver + // No messages will be received until vw_rx_start() is called again + // Saves interrupt processing cycles + extern void vw_rx_stop(); + + // Block until the transmitter is idle + extern void vw_wait_tx(); + + // Block until a message is available + extern void vw_wait_rx(); + // or for a max time + extern uint8_t vw_wait_rx_max(unsigned long milliseconds); + + // Send a message with the given length. Returns almost immediately, + // and message will be sent at the right timing by interrupts + // Returns true if the message was accepted for transmissions + // Returns false if the message is too long (>VW_MAX_MESSAGE_LEN - 3) + extern uint8_t vw_send(uint8_t* buf, uint8_t len); + + // Returns true if an unread message is available + extern uint8_t vw_have_message(); + + // If a message is available (good checksum or not), copies + // up to *len octets to buf. + // Returns true if there was a message and the checksum was good + extern uint8_t vw_get_message(uint8_t* buf, uint8_t* len); +} + +#endif diff --git a/libraries/VirtualWire/VirtualWire.o b/libraries/VirtualWire/VirtualWire.o new file mode 100644 index 0000000000000000000000000000000000000000..51c259641c41f60479ca51f4f2ba0cfbcb85b8ea GIT binary patch literal 24448 zcmd6vdtjBto%iR-2_al0AzTCm3E?W2oCE_ZT8P|4ixRm>K|Q%0LfnwVBp@mkqUfSU zn{bFy#7k}ErRxRX+HKXg$ZNGXTW!16b-P;6x@_xf?Gn4#wO-18zcatzIddM87v6XO zd8d8OeC9X5`ORankXC)K#^<*`yoG9P4!2~RARsYcs#Jol)~g0d2oZ34JtNbp-#NtHPKu#mLdb+3EaCQ^K(+zxt?fLbAsT~Ayk_>&RjYqiVmIT zMu#!ey-q=A&6ouRV~Qu)$ov+Cv+SVDw&O8dM`$?C%IZr|B&$z-W1Gp!hL0#2pg4vf zehT&3O1G#@l+vzDrQM!VcS>n@rqW(dX&CPRnM?tdsvJEWag!SzNtoy$OC~M-0^q8{+8wbb1_x!B0{}i~PY6{Bw{$ zTRa#%1CZ002$~YXP>znA>O@eJ2znkM+V1I6+HceT9%N_vGHK6sDW~Wo+J7@1aM zp2P9*F?6Q#XMvfP)pxqpE?~hv7zJ1>tzbAceZk1EV02h8HY_Nr>7zDgFwa?@NKbsr zQ^Mt}m%hgIutqd2m>Cw#3JWd_3+9Cd3&MiMY5$$;mxeW#hTF0%tzlcS9t*DR>oL;$ z<*Om_+qNoQ!d0>+Tk5`Bu^@-eKS=_@ppmdm-xvtZ-Ii~&mZ>3uib|Q z>*qwPT531dH#W^EDJh*5-GI~$RW0#oTT@d*YqV-}OSGZBI$Bp#6D=<0|0$_&tZCR( z8#n)*!qH7_^$kX=yBd|WRJGK{Td!VS-_o|Js^O~ombfuqqPV8H*$LLrryS9-+J0uPy9w~8l*0V}MrCw>QwS-%twW&AZd@ZN>s^6QQ>Zk8gV%WTQ8_Pnjg9Ui&{@FGbZx8l)F86@K`ESEvk~HHCDOT5%;Iu zSGV*ghKH&a)_hHCIZdA`U-djE_N7`7Hm1tjf^e+)p0WR(GB#Rg0(R7H&6+K7c2?xE z)WpdST1BkZwCPaW=c(NsQp=b0*&(@_3CCgQHSIb7X3BZ(iEyk&y+VIUEu`A_Is{c& zjcERu)ASgXa0i}c@E!;LWY8J-bq_V9jrlZ)9-DW}9BJ>IGC8ZbsH<>W;lxPs%xF

lJCfVmr<@sdKNKsyx1%&T-jTdB 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/VirtualWire_Config.h b/libraries/VirtualWire/VirtualWire_Config.h new file mode 100644 index 0000000..7aa3289 --- /dev/null +++ b/libraries/VirtualWire/VirtualWire_Config.h @@ -0,0 +1,152 @@ +#ifndef VirtualWire_Config_h +#define VirtualWire_Config_h +////////////////////////////////////////////////////////////////////////// +// The following configurations are intented only if VW_PLATFORM == VW_PLATFORM_GENERIC_AVR8 + +// Uncomment this to select the platform as generic AVR8 +//#define VW_PLATFORM VW_PLATFORM_GENERIC_AVR8 + +// OPTIONAL: Define the IO pin used for PTT (push to talk) +// If no PTT port will be defined, the PTT feature will be disabled +//#define VW_PTT_PORT PORT# +//#define VW_PTT_DDR DDR# +//#define VW_PTT_PIN PIN#? + +// Define the IO pin used for transmitting data +//#define VW_TX_PORT PORT# +//#define VW_TX_DDR DDR# +//#define VW_TX_PIN PIN#? + +// Define the IO pin used for receiving data +//#define VW_RX_PORT PIN# +//#define VW_RX_DDR DDR# +//#define VW_RX_PIN PIN#? + +// Define the 16 bits timer index to be used by the library (e.g. 1) +// The default timer configuration will use TIMSKn as interrupt mask register, +// OCRnA as compare register and TIMERn_COMPA_vect as interrupt vector +// If one of the above doesn't suite your current platform, please redefine +// the timer setup routine, as indicated below +//#define VW_TIMER_INDEX 1 + +// +// EXAMPLE: configuration suitable for At90USB162 or ATMega32U2 +// + +/* + // Select AVR8 platform + #define VW_PLATFORM VW_PLATFORM_GENERIC_AVR8 + + // My radio doesn't have PTT feature => VW_PTT_PORT/DDR/PIN will be left undefined + //#define VW_PTT_PORT + //#define VW_PTT_DDR + //#define VW_PTT_PIN + + // VirtualWire TX + #define VW_TX_PORT PORTD + #define VW_TX_DDR DDRD + #define VW_TX_PIN PIND7 + + // VirtualWire RX + #define VW_RX_PORT PIND + #define VW_RX_DDR DDRD + #define VW_RX_PIN PIND6 + + // Reduce message length, saves up memory + #define VW_MAX_MESSAGE_LEN 40 + + // Select Timer 1 as the 16 bits timer used by the library + #define VW_TIMER_INDEX 1 +*/ + +// +// OPTIONAL: Alternative pin setup for advanced configurations +// Instead of defining VW_PTT_PORT/DDR/PIN, VW_TX_PORT/DDR/PIN or VW_RX_PORT/DDR/PIN +// the user can use the following preprocessor directives to control the way +// VirtualWire library reads the RX and writes to the TX or PTT +// + +//#define vw_pinSetup() +//#define vw_digitalWrite_ptt(value) +//#define vw_digitalRead_rx() +//#define vw_digitalWrite_tx(value) + +// +// EXAMPLE: Advanced pin configuration that lights up a LED when PTT is high +// RX=PORTD7, PTT=PORTD6, LED=PORTD5, TX=PORTD4 +// + +/* + // Select AVR8 platform + #define VW_PLATFORM VW_PLATFORM_GENERIC_AVR8 + + #define vw_pinSetup()\ + DDRD |= (1< + + // Select AVR8 platform + #define VW_PLATFORM VW_PLATFORM_GENERIC_AVR8 + + // Declare my own timer setup function + static inline void my_vw_timerSetup(uint8_t speed) __attribute__ ((always_inline)); + + // VirtualWire has a special routine for detecting prescaler and the number of ticks + // automatically, but needs to be declared first in order to be used + uint8_t vw_timer_calc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks); + + // Instruct VirtualWire to use my timer setup routine and my interrupt vector + #define vw_timerSetup(speed) my_vw_timerSetup(speed); + #define VW_TIMER_VECTOR TIMER1_COMPB_vect + + // Define my setup timer routine, that uses OCR1B as compare register + static inline void my_vw_timerSetup(uint8_t speed) + { + // Figure out prescaler value and counter match value + prescaler = vw_timer_calc(speed, (uint16_t)-1, &nticks); + if (!prescaler) + { + return; // fault + } + + TCCR1A = 0; // Output Compare pins disconnected + TCCR1B = _BV(WGM12); // Turn on CTC mode + + // Convert prescaler index to TCCR1B prescaler bits CS10, CS11, CS12 + TCCR1B |= prescaler; + + // Caution: special procedures for setting 16 bit regs + // is handled by the compiler + OCR1B = nticks; + + // Enable interrupt + TIMSK1 |= _BV(OCIE1B); + } +*/ + +#endif /* VirtualWire_Config_h */ \ No newline at end of file diff --git a/libraries/VirtualWire/examples/client/client.pde b/libraries/VirtualWire/examples/client/client.pde new file mode 100644 index 0000000..5c0fa58 --- /dev/null +++ b/libraries/VirtualWire/examples/client/client.pde @@ -0,0 +1,63 @@ +// client.pde +// +// Simple example of how to use VirtualWire to send and receive messages +// with a DR3100 module. +// Send a message to another arduino running the 'server' example, which +// should send a reply, which we will check +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: client.pde,v 1.1 2008/04/20 09:24:17 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + vw_rx_start(); // Start the receiver PLL running +} + +void loop() +{ + const char *msg = "hello"; + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + digitalWrite(13, true); // Flash a light to show transmitting + vw_send((uint8_t *)msg, strlen(msg)); + vw_wait_tx(); // Wait until the whole message is gone + Serial.println("Sent"); + digitalWrite(13, false); + + // Wait at most 200ms for a reply + if (vw_wait_rx_max(200)) + { + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + for (i = 0; i < buflen; i++) + { + Serial.print(buf[i], HEX); + Serial.print(" "); + } + Serial.println(""); + } + } + else + Serial.println("Timout"); + +} diff --git a/libraries/VirtualWire/examples/receiver/applet/HardwareSerial.cpp.o b/libraries/VirtualWire/examples/receiver/applet/HardwareSerial.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..a158266b658eba4fcf1efd18787ff9da200adb64 GIT binary patch literal 14308 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 ayZFqdWa;x2!sWz>6KroA^8W&A=o)nZ literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/Print.cpp.o b/libraries/VirtualWire/examples/receiver/applet/Print.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..a2dfdf4bf45fe8b6545c8e535392022202904fd7 GIT binary patch literal 22848 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/WInterrupts.c.o b/libraries/VirtualWire/examples/receiver/applet/WInterrupts.c.o new file mode 100644 index 0000000000000000000000000000000000000000..c2031a371035fb6329678505f40b9ecf9b8983be GIT binary patch literal 5572 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 YcsKlZEZxIgQ;x+w79-ZN`V`auZ}>rz3;+NC literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/WMath.cpp.o b/libraries/VirtualWire/examples/receiver/applet/WMath.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..5318e4c4ae2664873526baebc3c6aee42e8b7cc4 GIT binary patch literal 6980 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 VH#t)asRw4AO`ejQIU~Rf`(HDl>h}Nu literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/core.a b/libraries/VirtualWire/examples/receiver/applet/core.a new file mode 100644 index 0000000000000000000000000000000000000000..2d77b4d369a6c1f8a51513a7b086778009a7bb69 GIT binary patch literal 96278 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/pins_arduino.c.o b/libraries/VirtualWire/examples/receiver/applet/pins_arduino.c.o new file mode 100644 index 0000000000000000000000000000000000000000..d5c85bcd7871d5bab1b43a8a4011bad7a457b212 GIT binary patch literal 3012 zcma)8O>7%Q6n?X|6Q^!Wg85YiN+Attfpyx33W8{%Q5u2*L{uOIhGp$toNeu0vtE}b zR4PJnLr^#%A@L_JfCLgJRB-``E8+l1aNxiVIB>{;BEcbiZ+2#PvjLGO&%W<{Z|1$3 zowqYSzp#8l2tir|out$vYLtjxf^$}On5HorB{44cRcn<(bzEF7#)gQDNvc$if*>kf zMTP2I<<81dji{*jGEpgpL_)dZZwdugdwuMm}I;~}M`+OgfnE~1esc#!WFOvI3R zi*icYc}dz3NRFKR5bKBWGz4-Xu~G8;NIA|ev%?r>hf&0OSjAR3w#u;;M=Ob;k|+<| zgKjUQ4fCT&C1Y4dHcpB6L5Pw}I&uy;=GVpN|H_Br+Z;bM4dNFx8M>y%zaaj~^!oug zj{7FwahfmXKNSaZJn_T~dY!|FOMmRbQ*Nv{J6E?uXW;q4tur$RZ>z7ude#ozdK3hm ze%(G3);nIa-fp$(rpZ5MJipZ$I4(Up*T@cT=)sLv5W0QsBkD&EUb(r-)zkC*zNJQ) zt#}Vh@lFbHt(+zAuMmG%QB7)=u)#ql=_WcL(LS1{n3?xQ2Zq=KJf6w{KTwz*gUkuifH7DU`sfeV0#vnXmq<3 z#rdV1bIU2Q>);XXV>&xwy`FT}$n39mBfAM5g|S}MD00t6WH$SKG99-$Xj^u(8MK(oAo7k)gGfFZYWG`$yq^do}5$Uuo6!dkC^ zT|Z%w7eHPH%rSUQV`w92*?1igzk}1F<7r##EMKGzKBW>VYfM zpX5g~_6@*yWo$mW(;D5_<(~#c~vLF3$g+d6MlXxsT7EJDwP5% zXE`!LaJRp;3+Q-QcT#1H{#-xTD1H%m SO7UDr@1p7VBi}8*RLDOy;Ja%8 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/receiver.cpp b/libraries/VirtualWire/examples/receiver/applet/receiver.cpp new file mode 100644 index 0000000..5878978 --- /dev/null +++ b/libraries/VirtualWire/examples/receiver/applet/receiver.cpp @@ -0,0 +1,68 @@ +// receiver.pde +// +// Simple example of how to use VirtualWire to receive messages +// Implements a simplex (one-way) receiver with an Rx-B1 module +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: receiver.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +#include "WProgram.h" +void setup(); +void loop(); +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + + vw_rx_start(); // Start the receiver PLL running +} + +void loop() +{ + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + + digitalWrite(13, true); // Flash a light to show received good message + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + + Serial.println((char*)buf); + //for (i = 0; i < buflen; i++) + //{ + // Serial.print(buf[i], HEX); + // Serial.print(" "); + //} + Serial.println(""); + digitalWrite(13, false); + } +} + +int main(void) +{ + init(); + + setup(); + + for (;;) + loop(); + + return 0; +} + diff --git a/libraries/VirtualWire/examples/receiver/applet/receiver.cpp.o b/libraries/VirtualWire/examples/receiver/applet/receiver.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..aee10bd2c3fdb0dfbe392f32a71ae3a313769263 GIT binary patch literal 5040 zcmb7HU5r%a8GgT+-DTNXc9&TM3RMQdLdDK5vQ%BIU=ab?$Oej4v*vJS<}iDj*_r8? zGl-;yYGYE9LZEBQjfq^C^r9EuG^H9N#+Zf}(VI5Cu+_Dx#*3Ojnl?2x**?$rGjsMd zCiTsJ=X>6t@A=;EfA;j=sRxu&;zY?2>1rag%S4`qb3zAfmG!b#_BGEhV@u7J-yU23KM}rYkX=- zTQCW5^yuhJzX|KtTCZkT1qM(u=L#>Q>MOO6i@KRG^E1s^D5|Cz&vD3cbPUF^DvPb;WvB7--(sHiqMQ0O>CV5-+HXktIi-eiOUmOS z9fQ+dPfqVLOr;oHq+>wj*RY5g!Px-*&(I2d&FVqNuAkp9|Ka?5^H(o@aH(-&__zOl z{)5ZIuV1}<_M_*1a#js_8xCDjud9Z4`q0qxB0t@vuAN!%7l?nnaBkt)LbHQ^r_$Cl z@YB}#WtaE8^BaW~1WC}yQOA+ykGjYd=61Tc5oAA#olu#QUPHWU-x zy#?3{h3pivepNAD?R)5GVb8X0g^A*h;_W7ncD)r=>p`VZ#tDI`UM+M?ylKAl9DTI| z(m62teCXjW=|*?_zrEw|$9Ha8zc4PK$adkkz(t~x!5nEjw4gg zIur*dV<}er*q36d)dCDk?W*UON>Ok^icwJWttqS@Z!9s?!g^p0WGU*EH7&GmW<6oh z15Z*OkNi1DVft;hOLf?gN1|sx^6S-<&6!LyjOPE}6YCL*%_#cyKs}LaN*`q-3Nh|8 zEsR@XF)J6h1(;8Ti@T4`gt$2FZine+++PT+INvVl4%2lLm4v~;NtnCm1PY#)`{CrB z#Fvjgp2ukv*9K5-!V!BvVQ}yud`Z6h@lX{kAD>Xi=L55io4?O7aCb^!?({VSoaC#l z6nO_W=C|DXnBNakl6);Ra;F`x4qpv8$v2+IZ2}wl@S~)Y-!s5TzF(tJ^46e_@)Syv z?*;IU!$v-?GkwhO=P0fXpu7ghZUQTg;|z3%>3Roz`%#mRFTdk^2{_631sp}#oH*Z$ zFeLd_;hAARJ2N z|7Pt3Wc4a_RQS1bx{}o^pVZgLgI!gx%cCiM*6O@N^2l#4<^NGie=en;OX)AA^jEFU zJ0*|tzLE0(Ii+7q>7S=`^PhydQ}URvf$rky@h$x|?0H8H@7?El0x<3EcVJ3`J$t5g z9nUqrD5z?DDu@~#rPA=qjpmb{exN;%YAx_1k59FJZ%;hoRfE{WliBjCfmFh37~|)9 z6vl!3-QYd;(9Y=yzY%se`Q1Bxuq++h9okl_YpZ#&;oCm3^e4p5Qcw-+duxL35ac!E z*bD3U4vTh!I118%5b;^RC6*dw(KE4Ea7H<|PIB7=@T!e@2WL z?!kXpd>J+Opt4s@7W>WRnX`B;{G%3s9eBOP%yW~)lfc_7egJrf#nZrdTRa22$6}7_ zpv9brqr`Sxk6YXWdtfo|-Z_g4z-^1a0sNH3Mc`*GW^QLJ=KNeBwsZ1g0{_Zl_Vu#G z{lJ$j=DhL$j64?|GLDjgk@<7aCzW;`E z)?UM2Ywfj%Gwr)`+2SQ9NhyU*jyPLbY%Ykg4k4}poGU^iAf}6ak)!xMwg6yRwm#C4 zXIUPPfhJ^3@zx^CBZDM!lm5ModBNW~p3>m?~z7G?N^a0xC%-Eh|4%71L0kQ6y71s8=A36;SD%K*8jqNA|t* zyS^76edf`EzFYe4>3jQ?kNTXw>0LS9cg(*h^Is1R>$~Iid-~+w3Ej8My(jbKgZX`r z|K-`fw7tc0_1AOil8d_g*UB{UpYQ&aW)!K~g`qDN-+ zhT_-A;*uHrWAR?OBOFWg%2<4-?27M_(?^}ZziVFp{_9?rd#~-gIxm*kB}0jwGO+ii z3%Zb}OxMD!16%io;@8WH_-;ABcUo^nVmG9&hn8M>MaA^}3szc6*K(H1@1})>+*&f^ zz}NQ1;x{O(H^^-jSqJKqn!3wxZu`z__w;=ttNLP{*N>X9zdBsGv#Ro`gH?T3_R-EY zy)Pf^>f08d4&Ke-f}LI9b@fdyFYXOpHe*&Sz77^HJP=CUC^wgHskyeYYJYxr0+w%5 z_HIJWDf348{=Qew|Fk-EIqSX-by^3R8|C$*YK;81l>E13XJ0I_7T({WN?s4i-E!;M zH&&f`fSiQldbk)pzreX2V_lOZqGJBP4uVyokj0_AS-tj?(K|EpXQXYhM_5evN@=0d8;#ZYVVwB zCDV%Y_%AdiUbDO8{DZN+>0hg;9s>JC@w_R%9XINBQ3xCT2-%Z zcvsY&*PZv1yzYX@<%va!>O?rvlDI6fBXM)$uEe8>cM^vZv3L&3zmOJ7T!T7Xi#q(~ z-B^5^iqAILS+o1SzW8B=UU`D?x5UHo>iD8~c|5Nx?~%N&qOQ@sH=#Gx^sRiO{f+G} zcOe4DrssFZ#MNlOPEnD#T7(i?#XGO>M~~aQGIlvVt%XzzB9@~f#@yLSnj2Bwwl5|2 zC7!we#rs=!<^AM?o);g@d*qo%x4(S#<=bU$xTyL``G{-@Usj#lb2>bJYX5b8)V(8Z z^DEtbEBh`){@MWZ51{4`soW|>eJF4p_>^qf>FV7Ve<`k8mc7b(Wmw;nvg(a7L z3fbqKC*^8Wx)XS>i2dg-z+5M{=LD(C<@U@=%k9|&%F)gz`wrjwRq-c8UwopoKVIbQ zLyN9_gO+Bc--I>@IbHEd&h$}7WgfNvm8G9nS6yC_C~`uHiO%8MEb?U*e@ile}17i}`B!&i~i-)27f;0IjyQXT>Z3sP<~JD zLc~_4KPCSt<*r+Y+%sfG`NHzk%Fms4@+ZrC<<46t+%w@dIsNk2<=dTyIy-A(m%n+% zM^}V8kAtqKW$qSd@7BECss~P=6*9c1W!?bvSZCH&XYYx5=PKzfvtpOO6yK*>;ZWB* zT`zU*>w2{7uCA=!kL4{_+;hdGtGC6w`W*D|-rlQv*~4Rp-rtwD<-IHVX0NKg^)VhiPdy1xvToo>R1Bw1n3FS6GuDKFq`-!m+d*> zma4m}{F1TwG0^xGXgn4g7bWe2ngBHcYGP48yPZbc%J=QO;+;)4^=!Fs^U5th+j3tg z&Q~CR1pLyP*>i?Eo;#*7N`*|gMJMU1@8|NRY{-^l8@m09`pa=F| zU9v5a)w?Zz^(?|u%Gv8TpUd)-<4-3wef7L>^@nn9{0PkH#U+*RmQ+kS5R1pej*aPi zCs$PJ{5NBXm>9ixQpK19TkhMj5qBGqLhhSeewMR$sw#1}Dlx5M21+205_gM#H=ez{ z?6W*uQ{LM5%cN(&G@hLpUwhtV)gPg*yGzC#2w@Ibu=gMB-__+^eVhZfEMrs{yKQk= z+Jfr}uToFp>bUEpA!V6Uhd#UUleA|~eKzA+5gL1-wYRqSvg)kf_YZdUcJ|(k+^w&S zExTjf!{a`YIeYIYdbsHAqC-WujrwustC{a*hW6h!?#J1$X1|xcs%T@;)}q}-V|yA8 zuIz2?jrDf*-Y9=4e zcU03dt)BUErm}kbsQWYX_uoG5{%l%V-uwN7wD42;479U{q<0;N_st&C^Fhy{eJ8iH zFANFM7HRKj71_a=DlI5AccOn27@Ct?IAY|OvExgoOr0^abPgW`#BqTi;_N7eY3j_= ze3Kh*puGk5!kM@^CSC!!6vvfNGTbLW)Zi9U{szch0yr`tL^0q3z*mi&zGoL=8T2vL z;200LmMcu37z0PV0#(}I4FDH|wjXc-;B-8&cKPdAtLH`Vt3aPP1Z@uZ0N@@#n-;?-bOj`~jBthK30^;%@1 zqpiI*+OB%1#amj%omz5ZZ6hsrRd?% z3D4Wwp|cxkIJ_ZJ-`)}pS5}JKJ#4!0kjC30%?;ukXcH7w_Tl6D+D+mCP0}+1!^g(f z1A@=tYk)Piz|3RFXrbRDx4srZW8yQd9uC_O_NP;PSs;c%`6;#0hK;q+$k~x-V{OyI zg{ioRA6_IMLn*b?!i9B_)$ri>0XVfAY8#ts>zX1WG5|LkscjH955QQ})X}y^JT?Gl zW3;h7B37e%x(ebVWD&i(j#aB7Q5A)56$K93(=az}L=}u zg11Ohvv{gMX*Rs`NqxOP>AODC86E5E;O7Q-?JX>B_Yq+8IUh-U;v+!jWDMvOJ-7M@ zkok>|BtGyFAagthbc&w)d<4jRD>_yn2u z#`TeCMYsj?z^bMeOgAkZXzk%JW;pdtE%ocd^%vDQMcTwvmu~FBtT-BnBRJ3T%Cs98 z=A+YF8X{r?9cWzL*k0Rop6Y_#P+$mWu^TgeABQ7yi}Yl_16XTI6q8F!cs+E4Yfe60 zeAh#4Y;NsnSJX#6)RvBROa3#+#s=p+DpCrm=um%N9VW8%wQcK^N)TPbej_c&YIrjY58t3`pHf{)H?ehd}4h*7hiHW-}gQfeR@&gjXTiMyc%Jw{R9B z#~~wE{t;)nM9Mtcu*vBP@tT$2X9xvvAtP4}dmmsrj>3(GK_E96m3ge0O;EvWT>e8K zRN)x@3!G%57$Ga@)|J3if*h}WBY6pwSJEfB20|*c&BzD{@nWcjwk3rQQd74_h?hq# z)SVRi18DMk-rMnB1e$oQ9QBH#CWXF9^i~S+rVl~{qaOj@fXtZJ=+>_&eF2WKtmkjR zQ%Zil3KHX5fe!lx=ojJ;g_L+3q)&0kU%T8bgifGM z$V*~IW;JEbO;RB=xh8g z;FGqq=u@gFhhs52#|zMrfx_}nGJih!AA(je8<~vegltL3;p`n5bqQIYkg9{chyo4^ z*bahvUrPT=C4J#-vZ{BKw3{SxPC$xwHEH9ZTqn?q5f z@Iw!T;uKD&G{d7v-U%b}>;4Mx_Gj8VnpFo-3S*OIvaVrCd?m6N5zmqGAp^wc0|ewv zfa#CHXZaz$XJj*BD#SC`W4gI%i&QM#Oj6Ep#D=|yP|i=3qW=VzYMd+F(^TB4hTNt9Tk>w?b>q7)Z< zA*;2-4Irpmtiq*5#d?BzauD*YrJ$q-npmQgI?vT5ZY1F?5|(MJ>qt13etk_#;7z9} z<(QKfXu`KZP)2@fjpT{avnkND`PR7TKVh?&AGCPijHC#lK99Aa^5CV^J6#%j{FOFQi`pto;V&P zQ~&#*#-?YHc?NfM=0YC09eCj4BXPDDa&x`cSAToiALx<}6>HFj={LaA7CD)b&A6HF zOkvh35gB^1Hn9URns^nd4b@aF(btomJc!9vL22q4l`1#ic;11tt3Pl>hT;vCi{t-O+#EXbzDaSZWgudnM#1} zkLSa#jH>KiE_Gy*D#oy}C$*C&`Mf=TDYN&p0^|22v&ALnfmgDGr{j2<&(kcPLOhM& zX(&&JpswTqPkh%z>XPpR zEx84!Y4_svC=N^*eF`wEl<;|f1}*&o$4uJISe1~g6LKaU$!JK(2=esI+|A6OtK`j~ za}ToKMVWtPk4+R5hPc!Y9}Mw?KQuRGk5Wt5r4fk|)qViF?zQ$$VzRt}wa zu!G7~qM`y0Ns98lB*gieWa=7(gS6oswfC3srnjUGr>X1<9>(9+MPa#;7ae)Onkdo( z#ZF9As_{INlYvYR?2$1cPR5ObBYqB#&9&%bxMb6GM7bdd0sT;^u0_t@cP&yA(;KK^ zhTI2BGPHtczIMnYRc0|}mO15EGJotc*LaxoVr24iX-Y2kFe{qL{7;vurY>W1W)_)4 zQ8`ocB?JmKUn2Rumk|qDoMc-1*Uu$=QIeizd{Kq!IRQvMkPe`+@tb5`s^HA58&A%S(NuoDN#7#I~05{Rl>T}`3#jmH!!o~pUC_#m$}#zqJ`a5n~$IypOs?9PIO7~TNreR)sJchNz5IL8l;f|j`A|UT^ zMGj>7f^yb)D*1J)gcz#Z@VZ9&V6?L+ZdBAIFnAHNGKl8R;rzmk%&ikLq?#m;Jut|= zD34AR!C;=k_RcTh(_+B~kb@*UraV7Y5)Y~BW?ux^GbQI;k122~R49hMtyEBrni2T& zvyf_=;dvpAT#1YrR)CyMm^j!`3&-KKn_^Rtxd)lyUS)DxK@aE!*W$!#zXq5`-$!sX za022-5$NLE)RD<3JPtjhP|cY%@iCRs^i+t>XN$}(co=BGk8o1fl8h8V=|g-G}SHvcLmj+&ug(#m?WhrR8CN`nbOOZWD-r06eBofZG!39sDoR*B{0qE zeVvhL2ck4vaT)eiFUj!P;P7YF_`L=;zMf*^Dr2LbA-oHS7{M9ACdl)pv+L8pP#&GH zk)7`y`jpa+>%8qag42gh&{Pj`SCa#GMxk%@a_*Q3WXwvOWG@xpg4|g3#IuWqoNaO( zZso40HE{}}g9|wqjvwOheP2m! z_>_o?5uBlIf@Xd-a5dLJ88v@{nl}Lv!#E+?1bKc`DCCXQPH+p?BXcLkMsRMo31a-v z;HrJjsBPh7^(m0yUaj)Ng14cy;5D3}i5CK!pow27TuoDPe?bRNp@Yppbk{tEiXQ-) z+M`bUd_8IeFE2L1B;)Iv+;2=?MU$hkdRCjfiYDiCF|Cu9HXE*w*q*9|UrbyrXRzS; z5R-RM{RW~(qOJ8^-E%;TI9TMpt+TwW!$GU|0HNr=^@B*;NDjXbOrQ_V$Fcz2)+ClR<8w&)TVmU+f-r%FR3;maQr6Z zR(Tgnv#rje(|6HE$*)u8UD;=h>~)lVkFtXI#E#emXVT>F>C($M+0=*eab^Jo{&BaG z@+UMhOETi>4l-lCkm{9FW&xa%vrB0_OMaVTA;~$L-_KF)A-n^&2{=D(4ei9KFbA1y zkf}sQWXqdabb+z}TqTI}6HXAej-urgAsK8pNF9(IWqcux$EYP&{)}4AKp~x=fuGIt z*0%|HI#nbfmOm5Glhs6n`teS8ngXw@vYH<(h8aDguoF4u?!VEH7@i_~W>Rhh<$}8V ztxd>v2|0pwRIhGx8E3xz^iI`jIqQUPA6ar2%k)TwlS>Xz zX5@O3#^tdV>4CXUOpIb(MqWZz5|`2pY#@ zjmzOWPJrLHoJ-Ufuh0K#OlG9Ztc>5lo}4QK{IHmL3y~vC-?^R01j$NrO$92t4rYd^ zPeJ1;Ga8?>hyIFE3YDv}@wHFLiR1-eBfW^(>}X`Qkg9MFmHh?BaA*paQe-0Iocn^x zQW_tjawx&EbxcyKh*Ehu53Fg+I(dGQforM@Ru^Mbr&2^n8>UN{bgw&BR+DNUq1 znOO{jvsT^)0_M3j07EXpDT~2yE|&b33_3}g&X71!`CCnoT6)HG*jE=Ke z@{1+PUrD(?;FQG}IlJXBgaPy$l5|GOxm)t1G3a+%x{w8ON^W6xAa`7Dfjmo|n~|RZ z!O0>!`&bYWU6V!ew2>l^yD{AQzk)TXkB$O>d$Vm5aGv|7ctTMSMm?}I3{4A>q zukT$XI~yJb=ZZ?G%*lfrG?rT?jE3|O?ws<R2_Dmhtwnve1Fs1uBE4AI9>e z6izUb%d*c$!QqMyff24tt{%J&wthH}8Rb@p=;&;OieVk&){Q2{dQH$BycDGK<6WP% z2|Uk~fn$-0F8|adu_)IJZ8w&lA?2xs6q`9ooLX3pfX>pr1H;Y}6a;JbJP6>8=~M;WPWDB+ znC&-iBW0KhpF?7f$1w7~3a5+1;|WK!HoRstWaGpKO&z1}-W5YlOOZke7s3(c^z&`diE z&7uRY+EVKpmEvuacVv~>ep?Q@nHbrhE41UTl1gv)qr~6Z{oH2CaAS~c^Gw@OvUEoo zk|Hz5^p>G1RJL-qZRMaF{2W_v)&Fem& z8hb;U-JS z*kWwxzEfbw)i6DKVq_$vi()C!qGwpuz$lLN`fV>}iYWfvNHZBrLnobsiPqx{+`0+9qo-x!kSwF zBhlJuW29}x(#B|e2bK;uMk9F0bCI(8)>eV%50)#(0=&xkWorcL(AM67#kM++n`S&; zs!E#N76YY$V+>4l9<(_b_~WIPJ<1RfACuc|pvA`;ywJe@C3YLmNCQV0=<2-ruoD0D znG$@&_yHscX{8L1R=5;ZTVd{AL!pOUZbymZ0a=2tz8H!N47~x6HCt==?SP|!Z#A$B zkmYYM{96qE9fRKqNcl$q#{qJoYv9M1F=)>t%V50%SO@sF%Q|3Kd>uhn1{#lECZ9`p12e@SivMD~8YCuu%SO!++o49~#KTvYsZppP(YuhHSOj`3GV*c*MTp6U#UFL?7L%@k77!7WX*+ zLehDLo!;w@Xa!h5+~k-UD@w?uL6GCVP; z*npS06_HJ~>s#?tn-$SWeWVe;%2`p{3LHNxv;=$c^Iq&ye_DnMplTD{GP(sArXvup z?SO31Za{{cD{9#scN_ethW`X0``2#)8D_4!r977eYK_cI1Lc6>;FXk;#0w&20S^ia zp9sj3#Rli{Tdje)CEyTJ0?%v;RshmRF57|RXEyBy3{^+G^na^qQ+mJ(;rr#EYCtql z`9Q7aZPjx1gRp^GlaYxcLdyWzN?gDgsOIz$HIx`2+l>oV2)Vqm3h-_~9eqG?1t^4e z;$bTgXNi9#{NJ+3+V-L@PXn@UqjBrYx)mG96>P-0(4Mf#z|DZJ&wIdOH2l$VCBAJW z>{MwXb$a7yHMk}3G7?2TNi9J?eg@7KK$hJDNZnkKLET)4s3n7bIcz(^DrXfL{2g0c7tIFkX{FkE>R=-_bT!Yp2Kj{&51 zuDjA@m|F`97gYsLqb%1?oes#wORnWsQ0PGbzd+KtvkXl2lBG6)b1@(-T?$BvEe7(_ zx~ugPqa*NO@|NKOLrPUk)88{3UZ{x&wk8YNhap}($g+ip`HI+~5cnwhWVO?X*rKj; zOAUwB@G5mBdIpiO=3U8C29b0nwi=1R@ixHc4r-UpLyxRyfmOClg^$zU6B{a9)=F6D zdUV2Jb!|2hffKC#a}1@wwy*iL1+a;PuEnvwGS)NKlN)?xt#%7tNzPAle_^uQ*ofcfuP&>H2cPl&gL44qx;K+5g5xf+T z!;@=B+(6lGV?${Nunm-jwjJG)r$HB6#g??tU&1z@pYCd^HJSop+nERRBG*U`#-HQ! z$+gjBI3WXV|F!ihHFUq1R!(bT?7j<0LY8a-q(l^uB{u=GzLy$&i{Wnv zeKUPHZXuH8$>)kbtB^Tr-)s8aNK`CzF%DZKVDbEU}p%Tv}XZ~L$H_Y5E3U*2E8kWb$B7pu=- zJ{RrgwLh4@{`m6Oa=eM@GxmrxS^q7*6g29$_&Gk@E6)ovUaTp3zrFp?&&xxV;S=X% z&oy4uPn;9)9_01zSo{@-$zewsy^l^f+)&$I>yq0{7W-_4qj=Fr6q{gi_YCB)Hx;+t z;__9!)t41-Q||)wIiVkSlHKW+<+om~n*bGV0vBeo+3a_@l9dCk3HVx<51gg?Vt9{gT!K4v* zs>mm$zNt1P*0-%Ty%fb#D%nyWtyG;>Zi&CDi9eSa##9d*&@8c%E%2tFFwP0qs0�W6T4bKuF>Ub% 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 bTtsd296qXtTgNS9fh#nJ1< +#undef int +#undef abs +#undef double +#undef float +#undef round +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + + vw_rx_start(); // Start the receiver PLL running +} + +void loop() +{ + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + + digitalWrite(13, true); // Flash a light to show received good message + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + for (i = 0; i < buflen; i++) + { + Serial.print(buf[i], HEX); + Serial.print(" "); + } + Serial.println(""); + digitalWrite(13, false); + } +} diff --git a/libraries/VirtualWire/examples/receiver/applet/wiring.c.o b/libraries/VirtualWire/examples/receiver/applet/wiring.c.o new file mode 100644 index 0000000000000000000000000000000000000000..3e2ff047c935974112466e21d7e591a2f2e2d7ef GIT binary patch literal 8800 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/wiring_digital.c.o b/libraries/VirtualWire/examples/receiver/applet/wiring_digital.c.o new file mode 100644 index 0000000000000000000000000000000000000000..31e01c8591fbeb7bf20d802527de79c4129b7597 GIT binary patch literal 8220 zcmb`Ldu&|A6~lmu z^(Hh_V&u8=n=@z5oH;Xh=B^KJy=9x$TDhcEyYg#FJ#mRrUq$0uqp(UXQHzwGtuL#a zQxmS6t#|3$D`r(F6>3s7HJc$)D%_yLb!|1*)Z8>jsWOpQDphV#sfwt!3M*?PH5y7Y z$^$(rqx#xf*FIa<>sU2)s-RP8t%fjOwcjOFtyIlguT`m9R6GYRse!lknkMReIs42E zRAF(JRa9#BOiYEo*RNA7<^)DYx4BDn>l~WgQ*)>BeqOn1g<3<<@0*N<^?bh8H_hSr z3mOr_h5o45)^4m-YSHCp6t$oXQ8Ym=Gw}~Df)Vo(((n`^Hhkb}BSB~p=TLbzSCoeP z;%o@bU_+>^+!nT0X=|0XX04U$igI0P4C}Qzd>s0wSzmP}yH;9vmUs?@4oCK(QZ=Xo2^N_QD)eh9N~XOO%Ze2j`!iTg7!HfZ11Yr^1G?>0Xk zW`JNkZuYcx`C4Xd-KFM^7?bv)@9cu^yl=2p5~eSm7bYulVQMfz(J8$-U=Q&*j_qgT zljLlftjArf+K{A)R+=Gtai~CNEAR5-U^+r8pm(LGm-c69tm?FHZMUbD@vWHwjkW2K z*w+v3l1SK{)X&aLcDI;ng$u)cHhvFX7pR5Q39o-16|EOB4pwsY&q^g5UhyUK8Gyf_ z?hLfOYa3rhVGV37!`ly&zGPE_FHwzH!jSqM%xL}oKdbRHC$_$)tvOjp4`p-t)h#Wp z>zaE}+n+3Cnv3~--(YicxX|2}O*Qv)bu~w${G%kB>*^ayXVjjyj$r2w*SVuBU&su) zwoj?nq166tA)D(-q_aKQVzMvV#nWuCn8vXb?d6ryjPqhJAwxohW?Ty9i3tg{NI9>h zoG*1(Hk7pc7E&cGpJZu)=!HAn*iLidMJ%*R`zQM_bP)@#r{}}X|E~{QN_@clxsyT) z_YC;Mx=Zl1n*?>GRyDUwp3x)m!?BO_(eX&UCH8?H9e;F%e&=t^?@XSZIkjvu{!Z+f z@fXIsSLpY~#t$Dmv|?6;TP88;XYAjh=EIYZ&OE-%MwPJ}8|O%)7^e~C8C`kIoOM%3 zTIqvLwGn&vVU3t#$mT3$1?dEGu>Pcx+J{!Xftta9D1c7uf})h)>Y*>XzzCj}Rv!8t zvKK%ns!+WXI?LeCkOW#OC@c^Y=5R;8r-P;n71@*=?cE*_IJ~w*?+_Yz2)N|*+8_vs)$Vyp^+Le;l}j7X$2hX<160qT z@p^kWugRe~{2#jkM9;7;@0wY1j*%bjP9-{I=vCa>=!wf*@#bWSL!0`p54e=ijSf*9WMcg}oMnB-i!|>Op&B zutz=G!&da{odvr-K=lXMTSbuM+WwAu(B4Vd>x7K<=1Uvr`w=qxcs^nAk2oXJ#wugv z-btW3g3dEa^eCq&@H(ibdZi)|EQZ{TI}40unr82Yx%iEE0eeuJmI5l6-?^z^V|ZF* zXg}x)>tO|V0_%Bhit*U&896uA1l|;=uLk>P)w!v4UK`=u)OC3JK9%|tTmg>Hlf+M9 z`@arP5H?Zqs?g_~=%=v%H8Qse+a26uV9S=cDU1CB_`>Khd>~WEdzExP(Ul*#H(~DiM1s}6OtO&R zjqk4Ql25Du_1Wcps=3c2@2hLtg??y7u_-(@cuUNY<*KDuwR>+gW-$vOh z+ypuA9NKvc<*@J?$R8Bu`~R5mF_i32eeRj3$mU-pN_}5AhVmqtFE!F>Wa`(z&L4%Z z2ER>~zW)$r)tr6M=Uc+FjD0UfIgbnl>MRsSlUgo1)L$)3eU3pNDBnaz$3@`lgg*z~ zMwYSm2(#}!!aN@jl6koyJuJ-kyzN*BR~ePIwJj zBSuVbBD?qNY=GYvW~_K_QwQBu1!D^4J5ndicZC1+rF;W;sc;OuiY$A(CBPemX+I{+ zwb(8k0mp@#z~;S!9qz-F$a%NlEzEbJAiM*7KzJ|sA>nTD*M+%<`K?6XxNlDg9|1ol z%=h<)WZ7>o1o)&d{r|Zz{r`<{1pKlvTrFH{iOgTV_%py-MHAk-ng{y#-%H6T#gk&{2xboxiHs-@uHmTy9PN7rf=&-&b7W? zfDE1h3{^r2av0U9|6-h?vo1S zs?RD82p;Fn{T&9MKxtwQJ^*e(4uRWHat)}%IBXO-_s@2bQ=f65{%(}JM9z6LE|hno z{4z4_P(OuCc^}HVMLvu&CvxgMgk05#2hu2VweV3e`<_5K7g_Uz1&QnK&Xy*!$T>%M zCaev}IWPCF0lmIu!i+c1cXt-?3z*D(#AP6FM#(xkhLZQL8*7~~?J#zfL(RmE%r)OB z^2brO3v*s6GUmwCjZCH;-YaCS>;nszZXHpPxvUoibN N_QmF6>VxU?e*sCEpOyds literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/wiring_pulse.c.o b/libraries/VirtualWire/examples/receiver/applet/wiring_pulse.c.o new file mode 100644 index 0000000000000000000000000000000000000000..b0118cb341dbea86e53e337e36ff8fdb348c6176 GIT binary patch literal 6400 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 GefST>!uC-B literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/wiring_serial.c.o b/libraries/VirtualWire/examples/receiver/applet/wiring_serial.c.o new file mode 100644 index 0000000000000000000000000000000000000000..b05b13bd0c389922795f87d732b20995253b3bf0 GIT binary patch literal 7048 zcmbVQ4QyOT5#GJC5kH zXFGpwl?!eQl!*B9>J}uVP@#%K1yukcp$1}!QYjIr2n7{^Kt=*lpps(*0fEZ#efwtb zt8%@$3x2B1u>P3dY%S=)81d~7 zmfQc0;lBBvP(2gc^ z>7L$fE2GIn<1ZxpJkSU@-ZpUHZ86H%hK*CNWV&Y zJ9F6r&pxr(nF~EK;$cTDmyOEyc07n;TxPD6-g*We6Eb3VV7bd@*qP26AHczdRD;RH zzv`BhGJ(t}HG8&rHtIEckL%NV?M&-T=S`tas8ow^!+_T)T6k z6>G)OiiO$2#lowFbA>a7lZ9*{QP@}LD6|x!lhGeUCmSbMOw}R@MTl1VWK(TiQMZx< zaP_5S`r0!6?lL`Ark{XrrB?NOdcf0zp3ZpYN#aPYdeqYiPapDhGO*e?S`7v;W1;P} zN?B-ot@T=1}olf>CUWvZTj-m0P{q34bzQse#o>74q6t0e|W z@WedR7?uH}Qum_yfmRruKTHsXiJ>qd6efbg1W??A_bvbbufI35)nFU$2FHg-GXulv zzIZP#(s`#jlpP+3mxlSC+xgK0@on+8=FQEwsZ?^jFF2Wm*?9R`msa$TY95#G>*vX= zv~an=%*9Q7@9*;ODZl#-6G_~?x@lL4zjwMxdYIGDZ zof;oVBvYwe`iN@IrH7JY$_)2s=NX1F!)Y;)rP(c3f1)wFXR*K>lic^!_($K)^A|8Z=__se%5z{MKWPUvby-+Xx@a4QTk@CJ?b>9ndZ2&}t~W zrL0)k4nuG$DD}Gr_~Ncu2Rpw5ImUau3(d{}RIkA2tB%3KJs5NO)H0&42JF>_p;GLlGKV(G74UI?{C$4 z$1hdOHx2CawINyd%EnNM?=@hT@5|t8g^hgmGRFPCh34|@0H1sHbByvcG?(wE;N#ho z52aIz?~lN4Jx_xVB~ud1_wM`jTZRdC4oS#2Qeq2Ys)v&s-!6PFPQs7zAvLA=Hk9$T zq7dn4#jdrkjPDoVdl^pTeXM0zd=vo9UOz@Pe$|a&=}9N z{3|e#*x$W_X=JFAAWn#eh2z)!57d! zEchk#hXnI4uYSSgK1_`NAW}YwM$FoJk{F!i_%tzJB9PCc(f&pBQ^ZmHK&TV5X1+lT ze?I%)A%;KKxkyY0$PdwoS(iU1h7aW}G|fYT{0fbjwf6_Xyc7Q{xE=jJh_M#;&B7$l zD)juXoMur%_+K?*syB!apKSW^|B{qO!6$(Et|Dg|xKl9S^$!z+pK0wUz6AjCnAmw{ z$B1t*X7!}lABFlXv0Nt)LDzEWCyC|!GlE$!HWzz=kBgmqJSCX-!e<4i&=&*`qBpsa zJbs0C$81#FEqff*IQ*f|;^j!FK|i+`<1o z;8C%60Y5JIAn=4>)&^4>lWUvLsl^fCFwTu<%T^&ZfX^X=L7{lQ6;cC?m6&#(ON<8s zF>}So%oQKz$#NPV@N+Jg3E`~Bu@Wr|%rpET+G45CIB>P#jlg!T+kkBh9}$f1x-pdY zB75XH*x1NVOdoREwU|r0_j?4>XBS!s=g)Iy4s6VhZ;RhUl#%JrW&#?~@OT7V>VyF|h?yhe5%eY= zc{WWvQa>H^5xh+>>zwDn*tkEQ12Jou_Y`Abip?DYJOq49?A+56g1Ij1O4s5C;$p60 z&yca&bBhym5Ms^~>rz_L?3tMO-E&|eL(Dk{jzG8kT%I_G-mEL|iby?qx iVJ-SNvBbc$AZC4;*kS;XjcE4HZzY!4%$Wo8S^f|I-3hAz literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/receiver/applet/wiring_shift.c.o b/libraries/VirtualWire/examples/receiver/applet/wiring_shift.c.o new file mode 100644 index 0000000000000000000000000000000000000000..5719d00fdb75f205f9a298cfb15dacba3e00f74f GIT binary patch literal 4032 zcma)9OKenC82-;pTPiJu@={VB13^HAJ4H|lC=d}rK|ly$}6S4v`~X*(>H#l`gN-cQV|Fil4=bI$i9TWZ;IPcc?ztC%i_$k_N5bX7pBr zvkcCjfYv_6*ykC<63xMK#RN?T{&&li+M+=hxioNP;M&0Tfw6(9g9`?)3|<@j&AI7( z;tY>`I}%Gy8#z64*}1y>VnW^cOf@?)+&h#XntU#HLxwM?Lfgwtmz4|;4V@l3I260_ zxpI5XtY|qWa(0C~65s)i3*WljezjiRxYmEAe?kA${;}%y>b2^X>ZNMqkVrG8HU?3m zPAqOtXdNakrz`;~>9U%V{gzr((izf}r52TBL%PpWi%Qa#HpqcN--aat(tKHxwF3Pn9y$Nqkc}(p1-r4&6Oon zC}j@q@`}=1ta$liE}O`py`@kp<`Xp&Py3b~dlQ=ytDRNOgOYW9cU%qwbjpA8aOV6q zDL;JUFpgQ_)2KzKAWr3Ix9_HbemTG{%lurQFAk?6PP$S7&82(uDL0)i=MIZg&J|o^ z@`|0MafX6d%ozi#IJKRKW_6a`ZW|Sp#xjj7)6<(SA_k9+Jj^Y-#ry=DH3enx0uwgz zb}IXZeWt&Nz~Jr(Gi(noG;#VDT~bYLM9Bu4CEqxWY|qp2ESm0Ceacw0NKIzqhgB6u&T$q7pF0hMJrS+$>>-#CO&RuSU)-w>T&&Sp1D9q$L4^9zkNo>7D0c^cm?$z01v+zqhqUT zK9bR~@#lBqeE7DZ#Pvyy>O5(o#PzB~b#{6vaowp=ot+j+T<=m;=T3(b#|~@{RlOF` zYnuCV(D->?rei*p3Gowud8JZ&c5mL2N(soW)K*KjYqDw6E{%S7PpX{DYkn+OF4dH5 zDU~Vp98KwKD3zjG$hqYdFQnS7lJ)YQ?-rgfd$@J^9a3gl*uQF~NH>uENluxEq0Fl< zBTcfb{fe*omSmG)qUDzaE-C=06uOw_vdL0#&At`V@x+6K)$o(=?E`?GoJ5) zB@<Q`q#B7Q1ZHAu& z@?C5^*OWW~%tg3oxDV9#Dq_glLySKR +#undef int +#undef abs +#undef double +#undef float +#undef round +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + + vw_rx_start(); // Start the receiver PLL running +} + +void loop() +{ + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + + digitalWrite(13, true); // Flash a light to show received good message + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + for (i = 0; i < buflen; i++) + { + Serial.print(buf[i], HEX); + Serial.print(" "); + } + Serial.println(""); + digitalWrite(13, false); + } +} diff --git a/libraries/VirtualWire/examples/server/applet/HardwareSerial.cpp.o b/libraries/VirtualWire/examples/server/applet/HardwareSerial.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..effb11067f6154b43612c2f3cc1b856518dc84d2 GIT binary patch literal 14308 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 bp0Qo5vz{z{zD&3rv1zZgk#mCWZAbh+-_8=p literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/Print.cpp.o b/libraries/VirtualWire/examples/server/applet/Print.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..95252ab17cf4eefe93d9cc44e9d18cee1bb3d801 GIT binary patch literal 22848 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/WInterrupts.c.o b/libraries/VirtualWire/examples/server/applet/WInterrupts.c.o new file mode 100644 index 0000000000000000000000000000000000000000..e618a1cd61316fba4d94cdae8b453d0d4d6a1b24 GIT binary patch literal 5572 zcmcIoZETxY6+YLFlQdsWTH3YUO584MH@ewr$XE%Znfj5oqFST1We5emb!;cGl-Q|b zr|X22v}I^Rn;O@us0Px6_yN*{hJ@HJv`y3a0}}890TP-h6G+{Uu@r3+;zQwi?t89% zV>VWPaFq8w&pG#;=broV-uHEuj+_`X#)uOmr=($tywNW56dH$Zz`c@?9b)>-Jw2N` zqdk4*F>|K1w^bxEAf25D;1Y>$k!a6I=jS?)ZxU%yKUiWR6lskkmW^$jWlxt#d(w<{ zg(-Ww`pic2NQXh|hFF~^f*v|NvqPjaDa}bDUB(>W#N6(ka(q*&Q>16OL4vIKgYaV{ z$1uc*9Z`!NtUqGw<}G5-EyiQr~B5*Nl1&(37p1T+N7b zP5E4ZM|&7LMJ_WVonenZ^`q4HGvC)$LHrOr-MkrzMcS~oKzEP9j@e0x?_$QwxJBd_ zY%?Fc-+{Z`PG)K(l`dr~`9kr5!NGkGreQnUHV)O043N+$V7 zPri_utz>gDHZtKSPq^fXOtF+(aBa64HX-u(@j^LQDplso3&{+ZexaPj8YXAB*;D89 zrF>yJm@nlQ)8!nTc5lSO9fHw>=z!|YO?rpg`EpT66y zUK}*<$!p8iyga+~wY|%=yxe@g{Tl7V@iYCrF021-_{q}9x_Mn*d;7Z2+IOk(-wpn9@8T1{2sEAdz2EBz~5|BuX=HJn|t1~Fom2D%c~hRezr?re9m z8^E`}{2{iBH8S(x;b}C7oAU%#>STr36qqz9>W za|mtWAs_O#SerKvgu($(SUAP$(E8u*&6PD*zgWy?$0~))c)28aN(rS>SjbNoa@j-% zXMxNX3)6|Z3o&x^(KCrdiQ(j@lS5Kj$d%S7F~a8jXCh9h^8TPKbH&>}cP7>!Ck^^^vZ6IU(p}-DLrbjDtBFTjdbLI3Tbh#Aj8HdWbC(4q{rpswbPA)6}<|ZrC zL3(nslv|W!DL0!|SH3V+T<4h07jo(#OR{;w!(`jkyf$8wH>eNu4%xDj7>}KMzo4m7 zdd?LPRy|wHtgCRoGFd)s*m?rjgG!%1&Iw z_9X}XQE_|F#t(vzi?gp@#5p0~>&}37{f>H=%^%?61MbAZ5jYwTsK{)u$aOS+5`KPt zu#IQUI4+k1CBa`zPoU!3A^<*LFZkTLZAC2G$aiNG-x2T) zDi@XG+tS2$0(?)Po%LEP&xa{cxK^I7rv-oR%19(+zbYUi@r_qWKcHNP=hAARVJuB(LoMTL8oXHh7();PBZ zoC&_2z@PW*PXP~m_D~%Y+*)I9qo(G1{1s*Y*i4>8g(px$qL>w)R}^L%JL}f8x2Qc4 ze4CTokZ^Rq%~fki)IK@B&7I$nsNK1~&Dm*4)UKd!--Tb)4dJ>@HcX*?PVF)1jTqlW zwRc;)Q}C^8g=g7DoKW9hXJfV2e~tvfsmG2S4FY_5oEi^~IdH;)Lx;w#F3-&erQEc| zPv%NRHQdWP2(rZ>Q=GpL*zb+doXw?60lz$&KOdUE8N3gLI>e^HVy&bz8C|}6HHN=X9#H%o^oU~aKb}?O$wQx1{5R+?Dn1DP6~(`V&MIDn z<{B`UXCQ6j1oSr)bDg*j#{LQxxu%$F_8nrxccZo!iE)lleu#_yv(T?AX5McUL)rce z$svElMa*@7hgdoPsrW7EDEcs*Fo-=jfw?bw=|?>C?jYt10AkNVV8(n#W9|n&NR0O$ z<@dNu#6tNqv5wK!p!j|D^O^gXVm=u$@*sw1CdW_A^I)^$B=8Q!od0_ibKX+KI`)S= zJgS&|9aYRSPAcZm9#_m70>zxSJh9HtImNr+zo3})TvWUt_!-5VAN&)gK5ySr%-ruP zX6}oMnfoKf%;oe&P~>4~?(Gdax2(HE@fMA7?-v(;7ySIs8Tl;_=41f4l{T>DP|Wd? zKMFtRfzwA!KY3ig?8Eg-t`@C<&k-?77w&@y=89t(R6mqG%Uz7iWnC_p?3SQlK`>xC~k-Cc-Rdw`?dVaY3B-f XH~h9Q-NRf{_QgGxAlAMH6x082ln|2} literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/WMath.cpp.o b/libraries/VirtualWire/examples/server/applet/WMath.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..61dcc12fc9a5bd419a69cc73764926f49e99c2d4 GIT binary patch literal 6980 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 W;Mx)d6_sj2 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/pins_arduino.c.o b/libraries/VirtualWire/examples/server/applet/pins_arduino.c.o new file mode 100644 index 0000000000000000000000000000000000000000..e80a64d57f0063103c7bf3099537d5b7c1ae5feb GIT binary patch literal 3012 zcma)8O>Epm6n^8~O*Y*oBrLzGKq;glE#OVtP(ctaG)h8HfQSkXuwcAvcjI=~UcBBy zLZu=EHw1+P5)uW(g%*Lt2~}JGaY8~I5E2}?0|yQ{&;uO8_r^1}(Q6phj_i7~Nnq*^JAjESqo=m3#1L6yo;5JZLR zs4y~Hxwo=ZB`PYuOjL>?(SQ(3RRQPVURtWwDn#X(cuHxhdTh6`i)d&P9@M)73o&Hf zqFhpTU6M8gilZj~i1owxH3Vv*uu<~-NIA|fv%?r^8d3dFA%GIdqWe_8yMiTepS z&ifADaau3sKNAOXJn_N|dW+MDD}V07uiRL1a<*oNPT%u`JEx})-c?(L^}HRrwI~SM zy_$U{thK#Ht<`MSOq2hZ@%(1H@3^!uThC6e>&f+I5V}3>BkDyCUb(r--P85_o~34) z&3F$>@lFbHqg*BLuMmHapqtbxVS|HA&~0=;qJ1<)w@Y*@P11fUDlw!KqzI!}9v#2` zrC7(mm@BQV*X_=euNf!=Tl1JEmht_7-=y-|+2@o1{c7-pC!v9z=2P>t2n|+H@-W zSf0UPERP=O|BBlSA0Hn77dMF*of}Z*TVeVyQbz$L$kb%7k)fbfFX}D480eC^fQvb!a#|h!dgEA zyMDn#o(FjqFz4VkjbaR8Wb?H_`~gmj&ZljyvwV>@_>@Ydu;tBg{_INFF38%)k{KJD ze3Bo{*tY=Rm$CWiPJ47?lP~C0Ha0m|x~BYkvOB=_sZ%iA!><@r%RvgD)20oOre*|90*!g?WvQ9iUzi3$m zuwp%^!LkH%b1PCuovszSEs59NFh~q1u$n=4&5}ovWwF_I?a<AdaQpJonEHieCht SR6O_5`xyHD$al*x74i?>NxHuP literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/server.cpp b/libraries/VirtualWire/examples/server/applet/server.cpp new file mode 100644 index 0000000..8542c93 --- /dev/null +++ b/libraries/VirtualWire/examples/server/applet/server.cpp @@ -0,0 +1,75 @@ +// server.pde +// +// Simple example of how to use VirtualWire to send and receive messages +// with a DR3100 module. +// Wait for a message from another arduino running the 'client' example, +// and send a reply. +// You can use this as the basis of a remote control/remote sensing system +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: server.pde,v 1.1 2008/04/20 09:24:17 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +#include "WProgram.h" +void setup(); +void loop(); +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + vw_rx_start(); // Start the receiver PLL running +} + +void loop() +{ + const char *msg = "hello"; + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + // Wait for a message + vw_wait_rx(); + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + const char *msg = "goodbye"; + + digitalWrite(13, true); // Flash a light to show received good message + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + for (i = 0; i < buflen; i++) + { + Serial.print(buf[i], HEX); + Serial.print(" "); + } + Serial.println(""); + + // Send a reply + vw_send((uint8_t *)msg, strlen(msg)); + digitalWrite(13, false); + } +} + +int main(void) +{ + init(); + + setup(); + + for (;;) + loop(); + + return 0; +} + diff --git a/libraries/VirtualWire/examples/server/applet/server.cpp.o b/libraries/VirtualWire/examples/server/applet/server.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..33c0372399a2b2b1b978ac77fc22c34f0337b3ed GIT binary patch literal 5968 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/server.eep b/libraries/VirtualWire/examples/server/applet/server.eep new file mode 100644 index 0000000..7c166a1 --- /dev/null +++ b/libraries/VirtualWire/examples/server/applet/server.eep @@ -0,0 +1 @@ +:00000001FF diff --git a/libraries/VirtualWire/examples/server/applet/server.elf b/libraries/VirtualWire/examples/server/applet/server.elf new file mode 100644 index 0000000000000000000000000000000000000000..d9ae48dd571958226c97e47cd4e9be4aadeb2aad GIT binary patch literal 37298 zcmdsg34B%6wfElVW`cwagqc9XJjDzMh*%|}C@7LRBLy!RE)Wb!Om0A_EjNM|ENX6U z0^-0_r_xs8RcmXlrq0R||_x0`b_bLfip3NfZd57%Q?xFU9Y$834bPsn2Aj znU`l-784=G3nIxgg(P!61%42Go;=>bY55r)RU)I~uFrUGm#50EP1dwKeW&tVy|g=0 zj1l9R5Tj7K2`V*0j27cWk~ti8_|zetq_pgUvXF-QiY%$ZLAiWMEPy(uC*_RHe}2#5 z*Q39C;pZ>pM7KqEN8dg8Nz~~|ZtK*)K^YqcC1Dju1U>6z(164N~cRg!-W+UWxqa=))|Uyk!hU; z;SM=`#JD4&@K$-RKNQ(2L*Z?*ExcWh?SI3Ow#nH??%pT6z7}1d6^d+^1(9vi*Y)6y zZAeq5ZCcu~bzKGF9kL|+bvdPTOlL{t>yX+3EnDRsC1a0FU1TY3^O-BVofaOF>qhiA z_QkGH_+e%BVY#6s?O1h8Q+x5&<|qERJNmIKi-ub7>p$*DxxaK{S?Mb$%A$8hY3Hua zeJ9$Y8^UA3+v?BR*alu(bY$`H&VtqBCWOK*uyFISg2*HC_Tse_Un?y;lHL9gEI+F3 zJ&KZ3=0Ne0=)rlPlozaF*;`Pi7RWpz@9SS-wQ+Cz#K1a05n(mJyu`H`u`AHotTJ&sL8xm)Cjicss= z{%OYw)|9oTzLOJOQ~W(y5zXw_AgGg`6(62{_5=k?Khh9c9l1BMHS%QSg~;K^$w(;NANe0h2}L?k zhE9~>wWFc%Mir@zvbAFKd(rSFaPE@_`Y$??+0lmdW|ZK5DL1x7?w6s+W;qOXKLE4` zRdp^}y=YWw(Td`#&W6U6(Th7*j9D^faTfnA8np|pcx3dw&UZS;qs{K0|4DhM zH53^ppKRRKxMTkFp2*Li`Q0-Oo3g(9e#h@#$a?t5?I-1BYf2*HoPx+$=gj@<$@Ul8_q4y&ZtH@*s7|hu zUqkEev+>()&$ad4^fURa9FD%vc97YTpIWfs{L9PA{pGL9@5{&KCbX9P)K}zhrQEc= z$L=2Eil-G{UVQDCOFy39DK~B(vU|uM<=8cE%R{XvTU#qaYYyJ=;T;977ed#oGIOod zwJvM38coJdC@{QNWmY%zP;1&cr|aUZYnAlc386J?pSC96YTMKHLfez5k&ooIJ9ghO zZ2g9CThzg5)!F&gPL5WglgIZYt$pu~=vj-_q;=l@PB_{YIm-z}3Y~QanJz}U$hqU) zHl$0DE^*eX^w~&HbV4dU8R@JC_UcBD0W*2}U-=hD{2BetKg<i@@S9F_*~0C z(QS!+Xaj0tMbgW--jk%M#qHDE%iI0!4ehJj?`_}Oo>9m%g7p%pVn*Oke|x$%CF0Ic<^z` z`w}tkXw3`fZO_}C=jE`S)X6W)AN6@HX|=`-%C6c4uX*D0BSbN+V_(|QwE8})lV+dTcA6e* z+sW3pd)rpGHMIHL%G;*56{FpFd%(M@2dq4q)pelt@2$F?mhbP;ncXQmk90&k_T?ST zlS6Wb{6cuD zML>^$9sxZv(;0(%VS?nmEf;Mo+f|k*846zljh8~>ENGk^vkPhj)Cj1N*{9fTHQE*( zxA$`I9sHJ#wNKx^XzdTzKHZAz9Z27SYb&mY)Lo+$ca41qV)u_$;!%Yw&Y#IyOPWfN zcJLibGxr>o2lwiwp*7j)a4tKY?&oF-ND{uVwy`;a6jtF1y}e{(+nnJ{!+b z!$*`J9Z@puSSTD4_pVIt8d*}R(_aonLSjJIu#$nt);@jjN<8aB3aKxz{b8@J(JIF- zm19iFIOISYId+NP8_y2S`!vs%7B@zJ7W3?9#81~R6s3;txp(EqNqcASP1!371|4hctn6G} zp4NH%L|bQT=T@Y)?;ljObMOxae=K`-?aco{{-OMn`8)c5C-o1h@1+(T*)jM#>3>Ln zFMVC)Sg(>+1MHCZ0meLeoOvP?lG2E2$-)hePIk7u^+0mzYbC_f%X%? zseqpV;uAvbSb&rxveK-4Mye3243|6}gm;4eON9x%yX%AYc?`fg4;n@Teg&|eL~}d` z=!gekQu{-4w&4-J3;7bjydFXn8F~TWWx)G+@I}BGOCHFg4$IFlcphLIf;rdVmT&D9 zfc`u18Al$LpLrU+l(`tEBi=?4wf|}9LPW{HL3=!|(?DEfAn6An7c@A5u9y75R?h-B zT?YDtfcFDV=_SM#Kzq!DPiP7_SeFBVtyt-=ZmJdwbh7!@Kb6? zFcMmbpOcnXB4|8_=sp$ZiWj@#tZb?c2E-B+PZvSl ziX@^})v|bTph-ocT}6SN_HuNWm54$`Q*C{4+O$Rju_cjkFp)49QSfG|s~4}FN;(VP zB}gqimGoEwX>QB%D)_kqUVAf(M-vFJ`9=ase4Idl%%vFE;`D4!AVB7|1d@0^fdH8q z7?tAmJe@#*%!di2OX?abgW?c|wz!-_5p*vBIeBcysfVI-(Tg?$bNk5@u@m_6+Pb>h zX7QRzRyQ>?i~gv|nm}FUt>S5$x}uhxKy^cXO|$qDsI~RALGdvX!P@14rV@Vx#(~9k z4H#}3T2R}4V9ao;>l&(W@>kzlT^DE;qg}eO3$x-poQ~i)mxl`93=HGZ6%923v4RfN zE~yPx)?KffU^^5T!c}a>JidX`5$EOW!Tw%gjSWp0TpIk#p~GKs=@sHJ53#nsu_dUe zFL5|^VWt*lbvb{J?>K3qkPBOcXla!nb%#kUT%=9Rve5)#Ob!3{Kly6e@wsE8+rEaEZ zS~BlZPFiXQK=McAe0V+cF9J)pB^W3UN0lPS+K!_AcI!Ml)brc`>yL%0gj%ON9E{uWm`N6IYP zu!qxDzS5zvCinMPFG$ zx9$X{4#@G&*N?YAc_)36OCh8Z8;p#A5O0QBXhTfs1U0pLgm`<@LhUi3Ux6m?7ry{DsS1OD_7E9EnWwJV`TroP@M#EFVuH&wFnQTIyg1P{rukj~=54(q1Ur|}v z9fz}VybT@M$SnU$W={eC1JH7KgHEZB$cBjQ!`6{f6_M2usT#-uWXNC!+dxq6uYe{C zC4J#zvMP5IX%9-`d}LO%^`s4!#QFFPTE3h`+A`%7X?%MFC}e}uGfZ`#MkP5AmPfHJ7Qxt3oN|R6%|1|v zbUX1|WetGt2*b&F8R$WBTBYe8`SJ@iaDXg!7nt<5{Q8=7g@-zVx6QXb_v*c?6<|IVnR7wo5PNt4d5Y8g6 za2GupMNg7_n<;h)#m17C>|01e7bTRJ$-XTl+(pfWTB1J*6_hB}gaIUckrER%0rN7V z@P{N!)`V>&6q0bBCTu5xtyWIg1We0`!ucdzqzMm^(7`O1X#ayGJVj4uYYBWM7KOto zF-MmL(|)25H+vz=wZy|9s8TFOwWwGRQEv`HUUeNP$-WiLQAnNF>Ku=d@MjX{X{(r! z6NMMhuPrsY0-@@4weN$E2An zO^gWPF@xwBjovOrDy@DGXBsc7MGq&nCyUeD8G1d6&oiADXp$LIkk=`=S)q&oS=m?Fb`7%xt9jVctzKoP)prbUJ;mepq?r6r<8IkGBNGErU zMzeewe;{|PMzehxIpmJhXpXO!RNjL5tl&d98FxQc8|Z&G(F!=UR~G}`Tj8nfar zB1b;YXx^R;7vvvZ6LTOdddtNme=Q0T=93btwJGo}B(JSMoMp7-5SN!DFCp*29aKHp zrRU1OlD_jL(w%Ja1LiZXQ$HSds?p>mi_urAq|D@tHvH=6G=SgF`7+S{6z=CR`vB)2 z5C$?iNb<9VoakeY!FX(&$hyxvM-i!V2s+Fp`ii{Q10Pz6OHzUFzX0;zf*2E03}pTS zhFey{QN>|GYE?~CmA96JCWboiT^i8Izq?6+xM=F&mKr=+YJn@10Nu~aPy#CXN0-_= zMim2D*~4~{C;4)ocNLS*umE|l$CATGTo2xeIlNrR%M@NF@KV4_UtW6hauVuB9OH!_ zCWepTEf2>?c^A0S&(6*dU+nPEJ_-R0Fn|-m9UXz}L@;YuJxfM>gIc!XGUh2-boCCLWWDds2e znUUe+w?UMiUpETbrc}%63+${H*`jWrgAkn$R7_xRvj=kUi-()zW+lS@W)Fz)+lMQ% z9$1m(vbr|1y0$Z;n84m>59H*x5jW>kl$pSeNpJZT6Cy|AME(OK2 zDawzS5a&0Q(Y#%db`Yn0W(1#*M>OLynr*?u_~)7^ESK`8BcD+NMY6BZ35inGpT~1B zkjcKsWk`ri@l@f6C_FazBHrumF&0q{Wk5i`fvS6v^S`?nsey^l=qd6eSdsW zR8nOcV`iD7rjhv_m$}r#oO~OZyj_}{Gd;|bWn})vWvZde*c{I_VX`L*XL7!UK*1(^ zvAq7j5eqpy#SCT$GMo%-os7%!p$>iH>HyUeiCG%F7sfyS`&Y>5b=fS8CFCww5 ze87r}!bRIC`2BbZ>sIS4RQ^Wy%oa9i`8St2(-Wd;_fTy%f^K}CqnWBeUwWE3&+4Ap za5tHkxlC_xXB{Q8&Sg?wLSWEPfCFJe=H@N1LyIqlE=p=DLxoQBt z|3$on=&9@QZjJ}iXlGVF*0I%RVBw^Yd>iY<@r4PQStVqFs*)_WzznuUd0xB-I`b&j zcXo~gM$Y??gCrZKydho^Z?x*oKxD9G%9W>ZOH?R&A5to)MvVykQkqM($KZJ`jbxyF zqIV8b_Q1fwhMGGVmwa$@M=j?1b6@ zR688piBx;T76>SXF;bjD{!IQSxH2 zRDC=Q#n0iC4-_#pY)&y!Tm)2o%zz8?aLUILq84Ms<-t=VY&Api5MJ`dP$#u7$2)tV zIFEwi7N-h+u{ame$yGo^UygqEfIPp~yYlxL`ButzQNB0(uRS2o&-uB0)cPH`x#dV4 zS86$K+5=+z#P6ydiHOjRmYEQl1Eh~vt6Z7$H)zc{hzlI#Aj`Vpv>`NcZot*F%4nL# zv2X`9u@^iF(We;4^Hs!SXngega)h=AG;@l<)%=Fh{3UAs1c>O(0m&Ya=L|$HAEfeN zDwnUrlaLU7IkwvaVw{z5)h>Vti{8M&YAujHUaj)xoI}u>^G95ui8lfkn=_u!#OVxI z)3=PKS#&VQ9Aw*b*5 zze+HaIKAR(d7T-rg_zt)^&b&E8+EOp>NqQ#Kc47QRMqO9OE zu_HFYnItJem8+4oM-=^Ic@6~rb&ryAKg&HqGUDn9GG)1t>ibk`FPcA#p~7Uv9*Px6 zHcw8rqu4$8EMO1doCoXKipypcq~~2oJi`*D%a@sTs4Bl)Ke5B>Ke3UKx|?OSuf){FX)JO%d6bWmMmJGv#4=cLVh51K#}!NLCBH zo5zuF1-(;cn$I#}q9jfJn0Y!R!^xh2JpF1(8l1&aB>OIKLZUy*((g%<^9*?g$o>9{ zlp%(42`FL!9s(Tk4(iM_oW4lfqW~JGVnNKA8jg>XVa{z8$Y;JYewI&TG9_82r6i+s z$w|`3S;*Aa*>=u0ZRfW{hDa8Y3oua7n_#Agnm5X$%oaqar(k}C%EjrJ8WeIUc^Lyq z&u22dDS!`@DswL?TZXd_G-WKJfuW3ZW;Uf&M$B0CqC^wUFT|wsDV3$9l+N9(^z0Ro zxf5rm(lm-PW@P5XfadJ9Jm$Skxfzq*`CFn(&r*Lw1O3Pj8 z#zPrkJSg!TPTp;_)K#vOvMsAcpAZzj1gUJ4N8V5k*}iv!B(g~;z^TKezIexlNmFc? z`pNx_O_k)J%GkV)6Y<%M+oz6CWg*pO!50;hYN9$MHB9P|1eol_{1@ZoEQj{I+Kq$C zmf@+RK*O(aNo5oeZa zFw2>_965ArQD}+{Lw_~kxzmsym!X=F{ayHA}2m|Q%$LNfd zvrBS@8T2PCUC10cDl<3TmpM2yM_whbP03Dy;7F04egTMxu1O+$Qa|C#oR)rG`s`fH z7!^s26r@WK@Dbh;;N>I_l2#7Tln*%pzel zBp2Wol2s&2b8}F}vYxbzuaBj zo`Fb{!;A+89q#cU8P8xQw%}rnbP?tpHN<#;ctCWtHzy5^F=aNI$9h75+~cI2olCLt z!^G^|Vgz)8ZXFndJV8OQ&YBDXd@&uZfZNFa(I#fwjax}6ra-D)u$h^b!zxPiI01Ki z*c$8U5d%HlHmeNnUN2j$Ok1ohTdeF@C8gVX%W+AziqPO3w3RPppuxE=OwS zsU)|rVIhw%Gd-PMgaJ?K6>E!AQP5QDahmnGhxNFp6U#V6)m3^P>R@WmiKwj%uND$| z>E<>Gp3+KYGDIiA=`1GDv0|+;T?^#6gs+yNyv)=)jy5}2Q*+~}bJDNqIRqT^K)R91SPfNazC2kJT+pqo{M`Q&5+& zfE-O7#<6TthDL^S02-nD@JQFH+X6?q`q`zteFz~PV~3ux@q^SjJ4lVUgVY2%;HoXO zu2CsIM#aV+phdPN7lZC;@Fm)DS4pY2`LRp5Zeuh+HRQdRs{7Fcu?pWrt6ai(cD;l zXmYOC|9rK%5g(H=+qCXeM$FhfJk1@-#$@P5gi$lT-D2$2x6<@@-EN!1&DtB%UY??& zf?+xvPySI_hebraXa$v@i-Y;~d&=w>m- zj1uSpww>U<(|s9x#FvqeIkst`jOlLJ)B}&@VN`ZoN2XgImL|)CBDUxoy6xoH(X+QM zE_y~Ry2ut6EjBt#kur+?ynfr88TtKf!yYgUZPD|so38;(wF5xFuLyC#<;zFw#`nR2yhsa9wRv zum#JIYnuXi>vEBz>c&QaR~Y6i#$vwGDMd>K%FrCF!NOgg#xpfuKUE=3YOR6Nz<~xP zIp4P_>HF?Ra;@|DMO)$T)Ibz8Gy{eFJlbFjfP$W$dWBH{2<@};Oh)*17!aD4S$=#A2#?C zfRuk8a4;Yj&HBExnnC+Dk_^^BqJwiV_MTnYRA+GlIy{?3qBy)#>T-fW;^t{hDNUI^<9L0SiI@#eQt?n_LzD=?{hKq!KZ!34XrjN?F z6h^zrl<%90$s{fED+`6VJcal)1IrA32B6N&ll;iSct&Az(pOmtBNalgLh$Ku`COb=!ngUn{nB@4rsX7jq8z;$Tkh!Lc+I|Aa zqQ9)g?pI=5Cn+BLi`DFt{-NVJ7xtGB-8g*hmSdBMvC$zwC~8$+QLD+vS4T{j0j63HL6; z6Q>pH_BOX5a7*R#M*M7NL35x9zwcR4*$50jP}Hcs@p*4_@jp?+%}>SM8-0doGD0;J zkf9w8$Vwg!$PjW>E~{b|Agf?LAmxIF9|Ft)&J`<^yC0DGA2xih=w-g20P6Z?YCI^f z8V=Vh)6(03%=xatj~V#Bfn2$(H86EGBnhdT(|Lp`fYiXHERg)vYF~kF?TEMj->UYw z*0De&{K8OGFe+=>+7zJt|qy(WW@pVICt0luiD`}zC;O2bNM8@{8wqo* z0H*?wmaYM$#C!v}rpeWMo6+I>zG@^iaHAo`t7W#w!MPuhcLXk1@~u;uzKbMZl(?XY zH<5#Y%*@p>y#f2-4VqcF_JL8E0qFZsy>)R_(?*bP1Y}k&=y9F94itLCVi3lAL`uhL zBu;o71Sz?TeXFCabPS{>JpeWy$; z)u}#TguE z;tki%{h)N`NxT(GaC{=PW1jClRna8vFf7|=_+IE0wOMR&EpClu8F}_2=CgF)pJOKY zUQCu1<=ZH6w2(Hn82Yn-?7>``#qP=FCvKqFY#3V`N=gv7fwIunqnq>c zgq&7GVh&qG%^9d~$8n8BT$Lw*A_26&iY?msU<|V(cD+ zBq4Ji1f;|fK;}FS$ntXC8*vAp`^nD$wT`4<4fvrlcx!&Fn=qXa+i`}SvR@pzopP2O+z5;(Q#7h~;Ev){a&b@%wp zNO0IDWaO3^$i+a692fi$a?uYX*J1b%0_wVDil49useub@2)TrY@Hs$g=mKQ>dkIj# z`|mXpQ9#}!4;uWqfezM1( z;nDN>_o8756%vHa|Z_Vp(1c zM>0;HIBw!GKEEM)aq_+T`H_&zW~_dGryK6U`4#RD9-JS<#(Qvn)50S}EI(Lk-z%$+ zpMB;V`Na5@As@d{ykz*q`2}IB2j_PHE?1+z#QY)J#ar7d!za!I!-10T4(Hn+R|Qd@ z<&RCkxtP(*$L3NooNr&FJviU7>J6UgUjbsvBO536b%*n1p~S=Ii$IYFM^Y4ca6Z^$ z`Bj`gFP~57Y%^YaFcF6*=BKPz-nL)*%jev=3H-$TiRJV9!)H$0UTpaj^JjiWe-q;y zLfhm+Ow{;CoQL(_;@5%3@>%?v1l%jn8#6w;DfvWuN1%TJ6qOl1aSrxe9!CAdIq+^l zTJOTeAApz?cCOL;_4xfYmBC7v+-#EA&&%J0kAOt6*%o){Kni^`RLQ-My^G}L3WAH7)_CjEj_{VI!hlP)b-SJ@o&yJp}8_w{2| zyP;TcX>GH=>egVu>}+H|@r_h{6W2rC0ru0(IdAJASoM8uXx;T(+yt z>F8)`pq@KwDO+|ov`gn+TX4~Y2?dji&MulLTI!o?m(&Mp3aat>l?vi^F$2!s(X=ks zLDMY^r|U&5JKbRrN~h>3ppe#fb7Mez;N1)jDp@0RDz+aRXvjtbu}{I>f8$M@$^`kKHkdRw;yv+l?9?jzRy zS8?-=Tz$<^JHw%h8UFZhr^4S-)zq}q6PKxiuSIqvHUIp%rIX^bOjf(H&0Hb$c5mHD zsNLCSLhGry&y8&b2Mq{vQ^2oU=TdH-)s6gQWo2fa@LxKoe8z=y{QlXDCJMuS-qg-< zdY3p*Q93{3SR2HicD1Vl{zehRwsRt8@$}OTaj%98;>)Wd=;z*n!P;t9J+Ov)e`S4* zzb4QeY-&MM16~3T8k=exus7JPf<0fruj<->j&q&R`_}nes+*fCK?A4)z&-+KxO5*$ z$etRuNh~QM2G(Ttar+!tsSnoG&#bt-8k?V?w{c&=Q`yzs&{Uuk)Tqizpw)JhcUdgdwp!F?EJkBbu;_8nWU( zKh>_MU`EDMEJN`WsYM9SxX$vj$CB;n*ZE=6kG$5u}=i z7H*#CnsmiVOBGd@eCG0{qF!$;SXJ2^5W$8D8nj#AC2Wd!+HoenJH$Sebhm+?+IMfc z+KtaMh)l5-&8B*K_da!v+qqBOugu-5p|0lYt7cyMStEJMyR6+~&$Dr!-(Oi%(^NXe z?w+T&>^t37dI|KnZS)d&?iPC1YHVje#ft40X!5D80j;RJ-ybuHU`tbd`QpVD*I$7E zVsf;lE~xek{H%dUcwNI|l{!*{{!x{S>rKflZefbh8 z;u023s`x-vsa)mjo?p?2X+bc=K@xJVKDH)Tw7fkleY?sC0E0Zxlsea{*>k0Wn_ z)DNOk#H{kgYXMGcwF~Lv3dir*@PkLL0JsciiqN>#&U}qHrC3Zb2qIDhIN#4#HBhY} zIiod~K7Nf;9h__Dd^)}XOTs#wHXKZIjy)AT6)z%scd8ANupOrrW||Z4F<~Nn zOQvRPjk|et;Y<G743 zBI0o?C*AF|JxP~4ubZSL{r^}te$d#f>QgsMrmw;qe`5U9hY#>FI3A#z=`rb-pv;AI zhUl)zpDu1^qI*WJ(~0ss3V#V_tAy!Q3P0Ug9^ZqlUeADKNmixBE%b=;s|%-Rttiuj z@a4odVy5{e#`3KSH=hn4^Yv45brHGT9V?iZ8)n%2OwUqye5bK`t(=Q@FXt%&KLl}B z*Jfq<#%@fwa@u8U!a|$h#m{J(-xM_l2dBuAG9H@aWjRm0>J+LifVGN7NTt8V>1mIgp1xh>ofnZeM5MkC*t{0nl3Cos z_>x$vg^9UrYqER`|1m8#m%RyE{2$YDI$u7UR(=KK47V*I)2}N$zTH!f^WX8lk@BXZ z{v(6T={%0tZKGkK_0ZxLCYDn@7GW5)dEm}#&aYd2OdnIYeuUzTyTG@` z6rpj>xTkn<>ksuXUwo-;?s%%z5l>CjWN-XdhsAAfi`#q_+LE|<_X9=u*4-L?AeJ+^ted9q0{kE~WC z5qIhFfwc7Q182Gan#%q3KzLretl3Y`kYV2QbPut4EcDz9E$MU*``uT7z8`iUt!{ih zHAL}GDx4Xp!s*G%x#O>B()|FOEAViM?uaLG%6I@~5YP%I0dO+G(;$g{L6Mf)5_5j{ zMlHoD-IsOJa<2pWlp@t~x|UP5o;OHxUc#AJFq`|cLQYw7%84hZCwX$(G4UXc@5J_C zn(x0nInBtE(~CU$mdcYaUG`v_(}jr#X?!8#$>~C#YMF3?AZdIGPCQ8CjK%RX1vIoHiVsA^e)^%<4*OYpZV4BFUI zRbPp}Lu2vU`o#@4U0GGt6j))gx>`(XnOuu8ixxv*(9-e8F>KP9iFtbF#9)Z|y231Hq=rE9{NV=IK0^cX@)`-u^<|RKOhiuyWS}wP|wB!=(Jfov4MZZCiprJBHZU!}1t^ zn-=dIbznJ8~i(_dfj-HHf z=SNS@^6)-v#6zthGKn}c|_Bq?14SUg8i5;;J_?sTQ z5%>`gz83f)555U_3WKQ*NBzmTPb`Y^yac{IK96{McRu_)?EUIu^Er`N0v~-#x{HpAWpsgUBf z;1aj2OFa6rfb+qaFB6m>2R!JJ=ij?{5xRIV|7F1K^A+(cf%8Fh3;4{x5V+U>THtog zA^G(Q{8hm18b9(mtz`34|D(VMDBraHZv$7K){Q-Gy`@$c?h{VEkIa=QEWZUpj#EMIWyt%D?-8+xEutJ)VF+1^fa}e7k_3 zL_B%WUv4$ay0rR#3!EPs@Oq;3{~ov-A1Mw3cl$?@;5M#a|33i!1oGPUl#5tBZtSx> z1Ay~|eZ0{>0l2q)lmP$0jQ=dp`JVj5F9PnhSDt`>5jbD$qelM{-~#=D2iqrqEo#?H zvwlMf`8NPRuB3H;@%{ka@8>EOzaNV^uCDOUvI#6)1LdNNDijPZZ^TlMB`Uot(9~d% z#I=w9`E$;(3tEvrS1(iKnn8nMC7i)ZOUz2F3Kj|3 z)rq8@qp9A-tt3y<wK;37&-GyNv%4jP-7R2DSiDnI(|{N?-l|qVn?F|^Pg8&QSCQ%hl}&zp7V?V4Xfd%R zbq!UOb$xD3MFWmf1(&in@Uxt) z8-GB3?(;4ii#dY7=5ESn|FASdbLvvj$+6Y9e)J!;?zpL`r7Mlhh}~S*SaMvqf z|NLvNOI#aG=h1_0Hv}38pbaip!AvN8-1%LYBoTfaXw|s&iez^|Zj8yX$JXEE*xy(7to_tW@DUDAIc%wP zJ_UXm?$x9{dtY&E?Lp3VZIL2+ev(v!&s{ eVAEVqZqw{`s%O}Gu#Bm$&_rfH3-k`};(q{xChsHw literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/server.hex b/libraries/VirtualWire/examples/server/applet/server.hex new file mode 100644 index 0000000..e0d9271 --- /dev/null +++ b/libraries/VirtualWire/examples/server/applet/server.hex @@ -0,0 +1,244 @@ +:100000000C9462000C948A000C948A000C948A0070 +:100010000C948A000C948A000C948A000C948A0038 +:100020000C948A000C948A000C948A000C94A10110 +:100030000C948A000C948A000C948A000C948A0018 +:100040000C9484050C948A000C9486030C948A000A +:100050000C948A000C948A000C948A000C948A00F8 +:100060000C948A000C948A000000000024002700F1 +:100070002A0000000000250028002B0000000000DE +:1000800023002600290004040404040404040202DA +:100090000202020203030303030301020408102007 +:1000A0004080010204081020010204081020000012 +:1000B0000007000201000003040600000000000029 +:1000C00000003F0411241FBECFEFD4E0DEBFCDBF40 +:1000D00011E0A0E0B1E0ECEAFEE002C005900D9274 +:1000E000A437B107D9F712E0A4E7B1E001C01D922F +:1000F000AA34B107E1F710E0C4ECD0E004C02297C5 +:10010000FE010E945007C23CD107C9F70E947F033D +:100110000C9454070C940000FB01DC0102C0019018 +:100120000D9241505040D8F7089580939E01089554 +:1001300020919401222329F080919F018F5F809369 +:100140009F018091A0019091A101281759F090354D +:1001500010F08DE101C08BE0890F8093A101209305 +:10016000A00103C09C5E9093A1019091A101903ADF +:1001700008F488C02091A2013091A30136952795FB +:100180003093A3012093A20180919F01853028F034 +:1001900038603093A3012093A201905A9093A1015B +:1001A00010929F0180919D01882309F45BC080918A +:1001B000A4018F5F8093A4018C3008F463C0209168 +:1001C000A2013091A301922F9F73AEE5B1E0FD0132 +:1001D00040E08081981729F04F5F31964031C9F790 +:1001E00040E086E0369527958A95E1F790E08C917E +:1001F000281729F09F5F11969031C9F790E0242FBE +:100200002295207F292B80917501882371F42093FA +:10021000A501822F84508B3140F010929D01809176 +:10022000A6018F5F8093A601089580917501E82F44 +:10023000F0E0EA58FE4F20838F5F80937501909124 +:1002400075018091A501981750F010929D01809141 +:10025000A7018F5F8093A70181E0809374011092C2 +:10026000A40108958091A2019091A30188539B401D +:1002700049F481E080939D011092A40110927501D0 +:1002800010927401089580919C01882329F481E0E3 +:1002900080939C0110929D010895809174018823A0 +:1002A000E1F308950F931F93382FFB0180917401A0 +:1002B000882309F432C020917501235080812817CA +:1002C00008F42083408107E711E0832FB80150E054 +:1002D0000E948C0010927401909175012FEF3FEFF6 +:1002E000F801319713C081912827022E2295207F93 +:1002F0002025032E322F22952F7002262695322795 +:100300002327220F220F220F20259150992359F7DE +:1003100080E0285B304F09F481E01F910F91089530 +:1003200080915D0160919E010E944E0680911801AE +:1003300060E00E944E061092950181E080939C013E +:1003400008951F920F920FB60F9211242F933F938F +:100350004F935F936F937F938F939F93AF93BF93CD +:10036000EF93FF93809117010E949B068093940165 +:10037000809195018823D1F1809196018F5F8093C0 +:100380009601815099F5E091970180919801E817C5 +:1003900060F00E9490018091990190919A010196DC +:1003A00090939A018093990121C0809118019091B6 +:1003B0009B0121E030E0092E02C0220F331F0A9476 +:1003C000E2F7F0E0E75EFE4F608162239F5F90936B +:1003D0009B010E944E0680919B01863038F010925E +:1003E0009B01809197018F5F809397018091960187 +:1003F000883010F01092960180919C01882311F0B2 +:100400000E949800FF91EF91BF91AF919F918F91C2 +:100410007F916F915F914F913F912F910F900FBE00 +:100420000F901F9018951F931092970110929B01A7 +:100430001092960110929C0160919E0111E061273B +:1004400080915D010E944E06109395011F910895C1 +:10045000CF93DF93482F562F6C3110F080E0A1C06E +:10046000809195018823E1F7A52FAD5F6FEF7FEFB6 +:100470006A27062E6295607F6025072E762F62958B +:100480006F700626669576276727660F660F660FDC +:100490006025B0E0FD0124E0F595E7952A95E1F7A8 +:1004A000E25AFE4F808180932101AF70B070A25A52 +:1004B000BE4F8C9180932201C3E2D1E0242F392FCB +:1004C000C901DC0125C0EC916E27062E6295607F84 +:1004D0006025072E762F62956F7006266695762723 +:1004E0006727660F660F660F6025F0E094E0F595CC +:1004F000E7959A95E1F7E25AFE4F80818883ED9166 +:10050000F0E0EF70F070E25AFE4F8081898322960E +:100510008A2F841B8517B8F25F5F550F9B012095CA +:100520003095A52FB0E0AF5DBE4FF90184E0F695A0 +:10053000E7958A95E1F7EF70F070E25AFE4F8081FF +:100540008C93A52FAF5F8A2F90E08F5D9E4FF901AE +:10055000EF70F070E25AFE4F4081FC014083AF5FC4 +:100560008A2F90E08F5D9E4FF901EF2FFF27E295D4 +:10057000EF70E25AFE4F4081FC014083AF5FB0E074 +:10058000AF5DBE4F232F33272F703070225A3E4F5E +:10059000F90180818C93545F509398010E9413025B +:1005A00081E0DF91CF9108959C0140E050E060E848 +:1005B00074E88EE190E00E94FD061092800089E0D0 +:1005C000809381003093890020938800EFE6F0E06B +:1005D0008081826080838091180161E00E942E06F4 +:1005E0008091170160E00E942E0680915D0161E01C +:1005F0000E942E0680915D0160919E010E944E0630 +:100600000895EF92FF920F931F93DF93CF93CDB78F +:10061000DEB76F970FB6F894DEBF0FBECDBF8EE189 +:1006200089830E944D0182E0E82EF12CEC0EFD1E24 +:10063000C701BE016F5F7F4F0E9452018823B1F155 +:100640008DE061E00E944E068CE292E060E071E095 +:100650000E94760400E010E015C0F701E00FF11FE2 +:10066000408150E060E070E08CE292E020E130E018 +:100670000E946F058CE292E066E071E00E947604D1 +:100680000F5F1F4F898190E00817190734F38CE240 +:1006900092E068E071E00E94A50489E091E067E0E3 +:1006A0000E9428028DE060E00E944E066F960FB611 +:1006B000F894DEBF0FBECDBFCF91DF911F910F9198 +:1006C000FF90EF9008950F931F930CE212E0C80182 +:1006D00040E855E260E070E00E94C303C80161E1B8 +:1006E00071E00E94A50481E00E94950080ED97E0F2 +:1006F0000E94D4020E9443011F910F9108950E940D +:10070000F4050E9463030E940103FDCF1F920F9224 +:100710000FB60F9211242F933F934F935F936F93D4 +:100720007F938F939F93AF93BF93EF93FF934091EA +:10073000C600E0912802F0912902CF01019660E8FD +:1007400070E00E94EA069C0180912A0290912B029F +:100750002817390739F0E855FE4F408330932902B6 +:1007600020932802FF91EF91BF91AF919F918F91BC +:100770007F916F915F914F913F912F910F900FBE9D +:100780000F901F901895AF92BF92CF92DF92EF9289 +:10079000FF920F931F93CF93DF936C017A018B012C +:1007A000DC011496AD90BC901597CB01BA0122E004 +:1007B00030E040E050E00E941F07205C3D4B404F7E +:1007C0005F4FCA01B901A80197010E941F07C90123 +:1007D000DA010197A109B109292F3A2F4B2F55278B +:1007E00047FD5A950196A11DB11DE5012883E6013B +:1007F000EE81FF8181508083EA85FB85208141E085 +:1008000050E0CA010E8402C0880F991F0A94E2F7D3 +:10081000282B2083EA85FB852081CA010F8402C032 +:10082000880F991F0A94E2F7282B2083EA85FB851D +:100830008081088802C0440F551F0A94E2F7842B78 +:100840008083DF91CF911F910F91FF90EF90DF9008 +:10085000CF90BF90AF900895FC01A085B18521890C +:100860008C9190E0022E02C0959587950A94E2F74C +:1008700080FFF6CF0484F585E02D6083089582E73C +:1008800091E090932D0280932C0288EA91E090935E +:100890002F0280932E0285EC90E09093310280939A +:1008A000300284EC90E0909333028093320280EC2B +:1008B00090E0909335028093340281EC90E0909325 +:1008C00037028093360286EC90E090933902809351 +:1008D000380284E080933A0283E080933B0287E011 +:1008E00080933C0285E080933D0208950F931F930F +:1008F000CF93DF938C01EB0109C02196D801ED91D4 +:10090000FC910190F081E02DC80109956881662372 +:10091000A1F7DF91CF911F910F9108950F931F932E +:100920008C01DC01ED91FC910190F081E02D6DE0F6 +:100930000995D801ED91FC910190F081E02DC8015D +:100940006AE009951F910F9108950F931F938C01F1 +:100950000E947604C8010E948E041F910F91089591 +:100960002F923F924F925F926F927F928F929F92BF +:10097000AF92BF92CF92DF92EF92FF920F931F93AD +:10098000DF93CF93CDB7DEB7A0970FB6F894DEBF55 +:100990000FBECDBF1C016A017B01411551056105E8 +:1009A000710549F4DC01ED91FC910190F081E02D9D +:1009B00060E3099554C0882499245401422E55249B +:1009C0006624772401E010E00C0F1D1F080D191D8F +:1009D000C701B601A30192010E94FD06F8016083E0 +:1009E0000894811C911CA11CB11CC701B601A30174 +:1009F00092010E94FD06C901DA016C017D01C1145A +:100A0000D104E104F104F1F681E0E82EF12CEC0EC2 +:100A1000FD1EE80CF91C3E010894611C711CD501F7 +:100A2000C4010197A109B1096C01C818D90814C003 +:100A3000F601EE0DFF1D60816A3010F4605D01C0AB +:100A4000695CD101ED91FC910190F081E02DC10133 +:100A500009950894E108F1086E147F0449F7A096FF +:100A60000FB6F894DEBF0FBECDBFCF91DF911F91BF +:100A70000F91FF90EF90DF90CF90BF90AF909F903D +:100A80008F907F906F905F904F903F902F90089540 +:100A9000EF92FF920F931F93CF93DF93EC017A01B4 +:100AA0008B0177FF0FC0E881F9810190F081E02D83 +:100AB0006DE2099510950095F094E094E11CF11C0D +:100AC000011D111DCE01B801A7012AE00E94B0044A +:100AD000DF91CF911F910F91FF90EF900895DC016E +:100AE0002115310541F4ED91FC910190F081E02D4B +:100AF000642F099508952A30310519F40E9448059C +:100B000008950E94B00408951F920F920FB60F929D +:100B100011242F938F939F93AF93BF9380913E02A5 +:100B200090913F02A0914002B09141020196A11D17 +:100B3000B11D80933E0290933F02A0934002B09378 +:100B400041028091420290914302A0914402B091EF +:100B500045028050904CAF4FBF4F8093420290931C +:100B60004302A0934402B093450227C08091420201 +:100B700090914302A0914402B091450280589E4357 +:100B8000A040B0408093420290934302A09344025D +:100B9000B09345028091460290914702A09148028D +:100BA000B09149020196A11DB11D80934602909318 +:100BB0004702A0934802B09349028091420290916B +:100BC0004302A0914402B091450281589E43A04047 +:100BD000B04060F6BF91AF919F918F912F910F9090 +:100BE0000FBE0F901F901895789484B5826084BDD5 +:100BF00084B5816084BD85B5826085BD85B5816021 +:100C000085BDEEE6F0E0808181608083E1E8F0E080 +:100C1000808182608083808181608083E0E8F0E071 +:100C2000808181608083E1EBF0E08081846080835B +:100C3000E0EBF0E0808181608083EAE7F0E0808192 +:100C400084608083808182608083808181608083F2 +:100C50008081806880831092C1000895282F30E041 +:100C6000C90186569F4FFC0194912A573F4FF901C5 +:100C70008491882391F0E82FF0E0EE0FFF1FE859F0 +:100C8000FF4FA591B491662329F48C919095892307 +:100C90008C9308958C91892B8C930895482F50E064 +:100CA000CA0182559F4FFC012491CA0186569F4F6D +:100CB000FC0194914A575F4FFA0134913323D1F1EB +:100CC000222331F1233021F4809180008F7705C0F9 +:100CD000243031F4809180008F7D8093800018C093 +:100CE000213019F484B58F7704C0223021F484B503 +:100CF0008F7D84BD0DC0263021F48091B0008F77A8 +:100D000005C0273029F48091B0008F7D8093B0001A +:100D1000E32FF0E0EE0FFF1FEE58FF4FA591B491C7 +:100D2000662329F48C91909589238C9308958C9156 +:100D3000892B8C930895682F70E0CB0182559F4FCB +:100D4000FC012491CB0186569F4FFC0144916A57C8 +:100D50007F4FFB019491992319F420E030E038C0D3 +:100D6000222331F1233021F4809180008F7705C058 +:100D7000243031F4809180008F7D8093800018C0F2 +:100D8000213019F484B58F7704C0223021F484B562 +:100D90008F7D84BD0DC0263021F48091B0008F7707 +:100DA00005C0273029F48091B0008F7D8093B0007A +:100DB000892F90E0880F991F84589F4FFC01A591BF +:100DC000B4918C9120E030E0842311F021E030E0F8 +:100DD000C901089597FB092E07260AD077FD04D094 +:100DE00049D006D000201AF4709561957F4F089580 +:100DF000F6F7909581959F4F0895A1E21A2EAA1BB0 +:100E0000BB1BFD010DC0AA1FBB1FEE1FFF1FA217BA +:100E1000B307E407F50720F0A21BB30BE40BF50BB7 +:100E2000661F771F881F991F1A9469F76095709540 +:100E3000809590959B01AC01BD01CF01089597FB72 +:100E4000092E05260ED057FD04D0D7DF0AD0001C8E +:100E500038F450954095309521953F4F4F4F5F4F57 +:100E60000895F6F790958095709561957F4F8F4F17 +:100E70009F4F0895AA1BBB1B51E107C0AA1FBB1FB0 +:100E8000A617B70710F0A61BB70B881F991F5A9516 +:100E9000A9F780959095BC01CD010895EE0FFF1F35 +:0C0EA0000590F491E02D0994F894FFCF28 +:100EAC00476F743A2000200000676F6F64627965A9 +:100EBC00007365747570000B0C2A2A2A2A2A2A38AA +:100ECC002C000000000000000000000000000000EA +:100EDC000000000000000000000000000000000006 +:100EEC0000000000000000000000000000000000F6 +:100EFC00000000000000000000000000000A0D0EC1 +:100F0C00131516191A1C232526292A2C32340000F5 +:040F1C0000002C04A1 +:00000001FF diff --git a/libraries/VirtualWire/examples/server/applet/server.pde b/libraries/VirtualWire/examples/server/applet/server.pde new file mode 100644 index 0000000..f03502d --- /dev/null +++ b/libraries/VirtualWire/examples/server/applet/server.pde @@ -0,0 +1,59 @@ +// server.pde +// +// Simple example of how to use VirtualWire to send and receive messages +// with a DR3100 module. +// Wait for a message from another arduino running the 'client' example, +// and send a reply. +// You can use this as the basis of a remote control/remote sensing system +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: server.pde,v 1.1 2008/04/20 09:24:17 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + vw_rx_start(); // Start the receiver PLL running +} + +void loop() +{ + const char *msg = "hello"; + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + // Wait for a message + vw_wait_rx(); + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + const char *msg = "goodbye"; + + digitalWrite(13, true); // Flash a light to show received good message + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + for (i = 0; i < buflen; i++) + { + Serial.print(buf[i], HEX); + Serial.print(" "); + } + Serial.println(""); + + // Send a reply + vw_send((uint8_t *)msg, strlen(msg)); + digitalWrite(13, false); + } +} diff --git a/libraries/VirtualWire/examples/server/applet/wiring.c.o b/libraries/VirtualWire/examples/server/applet/wiring.c.o new file mode 100644 index 0000000000000000000000000000000000000000..10c122b3cf3bb30822a20257926b3cb1e1795f8c GIT binary patch literal 8800 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 tO_?Hi*p^G~T(z;mz(A_ScL!#{{gj|=x+c3 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/wiring_digital.c.o b/libraries/VirtualWire/examples/server/applet/wiring_digital.c.o new file mode 100644 index 0000000000000000000000000000000000000000..3ad4053a4e9ca21912af22bcf1b865134b939eed GIT binary patch literal 8220 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/applet/wiring_shift.c.o b/libraries/VirtualWire/examples/server/applet/wiring_shift.c.o new file mode 100644 index 0000000000000000000000000000000000000000..35a215f942b2ca94f4a38e551dd428fb83bd8563 GIT binary patch literal 4032 zcma)9OKenC82-;pTPiJu@={VB1L38@og%0N6o|+}Ay6S`B9-CJqtgr1nP%n|T7m&F ziVFinOEqqc3ym&hXV3%_x-g0xD?Sq4*shEVBQ~jQOswB`?m08Jl^}mO{l5Qs&pqcq z_Y7xt?A@u95-Um$N>vkCQz!BooEvn&YFQxjMK!AxO>-KeP0i|nI#f3cA(7?M(69w2 zk?4GhHf?Iy-0;jCks4#K7pZmB*2ciIst6f!Xl%}+h9EqFZU5~=m_zCd7|(ghcs7-aI}ZQR;^kAho^(cbZfXxFx7+0Q zRH2wDS>HW|wTqneie5gOD0O-rzLVlcl>9VS)ahi$!~-`Jy+gIZKH)V27B^`17Na*C zoM&+U6twmk#=giPmS_Q%Dw>o93KX9-YAr`41kvDBiHjw(%9YEenLN)KCVQAyI$IypL^+<{61D>-Ui7V9K8 zpt`CdEpPl`EuIQu(95K#>e^fVAvc`X~#mwNQ~GybwjtDt~74*2Y{^CfMMr% z9z0y{H0r$vn-%NhoWu1_qu!seu^y&csrNRx%>k8#NLoT-#QOT7hwJ5L2J6pypp|+b zgWDWX*^HzZi4p7j5PG;?FN)arZ8kox-w=k)0hPl@Vw@H0y9PtJUK#aTVdMOGP0`1C z-(WC@K1vCWUjnNC(#OF$*q*23IW*m!`joL~k&4X4534eaoZ~zUK6e%ddm>!#eQfGk z*sQS5og{3pk+F$zOmx!9uzq+Z)T8>@Jad7JO)LPZ{`MK0SO)z`;}z6@7`*z;7@JsM z@sW&8Og_I;=fk(HN>rcJu+EcKm8f2ou+C1eN>q1hSZAkIC8~ERtaGQU62%Vet*Ux0 z!q+tS<(TpFyv)XYN>k#e{_;vB4j$OCE0GY8w#05r_G+?ydz(hTt2=iAQVSHpQe|1dlTylwbO;6H{x1gygWWG>gN$#AaCe8Z1`FE+dbe5K)e zaK~`IFZUv1>Nw#1-`WP?W5(VJ+-U6kfKM6D{dpFHxlaQRV9YijK)$o($q>(hGoJ5) zB@<4+Wfz4eOig_@^b&nyw7dGyVjo%iE*%jh@3_lCx zyV!WHDR~T-331PGAE@tD#E`Rx7=HrDy(eD?eA96LeyStq0fK}%+s;0hKHD>TO(L`e Pzkh6uK7*)#4)%Wm!3NH; literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/server/server.pde b/libraries/VirtualWire/examples/server/server.pde new file mode 100644 index 0000000..f03502d --- /dev/null +++ b/libraries/VirtualWire/examples/server/server.pde @@ -0,0 +1,59 @@ +// server.pde +// +// Simple example of how to use VirtualWire to send and receive messages +// with a DR3100 module. +// Wait for a message from another arduino running the 'client' example, +// and send a reply. +// You can use this as the basis of a remote control/remote sensing system +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: server.pde,v 1.1 2008/04/20 09:24:17 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + vw_rx_start(); // Start the receiver PLL running +} + +void loop() +{ + const char *msg = "hello"; + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + // Wait for a message + vw_wait_rx(); + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + const char *msg = "goodbye"; + + digitalWrite(13, true); // Flash a light to show received good message + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + for (i = 0; i < buflen; i++) + { + Serial.print(buf[i], HEX); + Serial.print(" "); + } + Serial.println(""); + + // Send a reply + vw_send((uint8_t *)msg, strlen(msg)); + digitalWrite(13, false); + } +} diff --git a/libraries/VirtualWire/examples/transmitter/applet/HardwareSerial.cpp.o b/libraries/VirtualWire/examples/transmitter/applet/HardwareSerial.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..effb11067f6154b43612c2f3cc1b856518dc84d2 GIT binary patch literal 14308 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 bp0Qo5vz{z{zD&3rv1zZgk#mCWZAbh+-_8=p literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/Print.cpp.o b/libraries/VirtualWire/examples/transmitter/applet/Print.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..95252ab17cf4eefe93d9cc44e9d18cee1bb3d801 GIT binary patch literal 22848 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/WInterrupts.c.o b/libraries/VirtualWire/examples/transmitter/applet/WInterrupts.c.o new file mode 100644 index 0000000000000000000000000000000000000000..e618a1cd61316fba4d94cdae8b453d0d4d6a1b24 GIT binary patch literal 5572 zcmcIoZETxY6+YLFlQdsWTH3YUO584MH@ewr$XE%Znfj5oqFST1We5emb!;cGl-Q|b zr|X22v}I^Rn;O@us0Px6_yN*{hJ@HJv`y3a0}}890TP-h6G+{Uu@r3+;zQwi?t89% zV>VWPaFq8w&pG#;=broV-uHEuj+_`X#)uOmr=($tywNW56dH$Zz`c@?9b)>-Jw2N` zqdk4*F>|K1w^bxEAf25D;1Y>$k!a6I=jS?)ZxU%yKUiWR6lskkmW^$jWlxt#d(w<{ zg(-Ww`pic2NQXh|hFF~^f*v|NvqPjaDa}bDUB(>W#N6(ka(q*&Q>16OL4vIKgYaV{ z$1uc*9Z`!NtUqGw<}G5-EyiQr~B5*Nl1&(37p1T+N7b zP5E4ZM|&7LMJ_WVonenZ^`q4HGvC)$LHrOr-MkrzMcS~oKzEP9j@e0x?_$QwxJBd_ zY%?Fc-+{Z`PG)K(l`dr~`9kr5!NGkGreQnUHV)O043N+$V7 zPri_utz>gDHZtKSPq^fXOtF+(aBa64HX-u(@j^LQDplso3&{+ZexaPj8YXAB*;D89 zrF>yJm@nlQ)8!nTc5lSO9fHw>=z!|YO?rpg`EpT66y zUK}*<$!p8iyga+~wY|%=yxe@g{Tl7V@iYCrF021-_{q}9x_Mn*d;7Z2+IOk(-wpn9@8T1{2sEAdz2EBz~5|BuX=HJn|t1~Fom2D%c~hRezr?re9m z8^E`}{2{iBH8S(x;b}C7oAU%#>STr36qqz9>W za|mtWAs_O#SerKvgu($(SUAP$(E8u*&6PD*zgWy?$0~))c)28aN(rS>SjbNoa@j-% zXMxNX3)6|Z3o&x^(KCrdiQ(j@lS5Kj$d%S7F~a8jXCh9h^8TPKbH&>}cP7>!Ck^^^vZ6IU(p}-DLrbjDtBFTjdbLI3Tbh#Aj8HdWbC(4q{rpswbPA)6}<|ZrC zL3(nslv|W!DL0!|SH3V+T<4h07jo(#OR{;w!(`jkyf$8wH>eNu4%xDj7>}KMzo4m7 zdd?LPRy|wHtgCRoGFd)s*m?rjgG!%1&Iw z_9X}XQE_|F#t(vzi?gp@#5p0~>&}37{f>H=%^%?61MbAZ5jYwTsK{)u$aOS+5`KPt zu#IQUI4+k1CBa`zPoU!3A^<*LFZkTLZAC2G$aiNG-x2T) zDi@XG+tS2$0(?)Po%LEP&xa{cxK^I7rv-oR%19(+zbYUi@r_qWKcHNP=hAARVJuB(LoMTL8oXHh7();PBZ zoC&_2z@PW*PXP~m_D~%Y+*)I9qo(G1{1s*Y*i4>8g(px$qL>w)R}^L%JL}f8x2Qc4 ze4CTokZ^Rq%~fki)IK@B&7I$nsNK1~&Dm*4)UKd!--Tb)4dJ>@HcX*?PVF)1jTqlW zwRc;)Q}C^8g=g7DoKW9hXJfV2e~tvfsmG2S4FY_5oEi^~IdH;)Lx;w#F3-&erQEc| zPv%NRHQdWP2(rZ>Q=GpL*zb+doXw?60lz$&KOdUE8N3gLI>e^HVy&bz8C|}6HHN=X9#H%o^oU~aKb}?O$wQx1{5R+?Dn1DP6~(`V&MIDn z<{B`UXCQ6j1oSr)bDg*j#{LQxxu%$F_8nrxccZo!iE)lleu#_yv(T?AX5McUL)rce z$svElMa*@7hgdoPsrW7EDEcs*Fo-=jfw?bw=|?>C?jYt10AkNVV8(n#W9|n&NR0O$ z<@dNu#6tNqv5wK!p!j|D^O^gXVm=u$@*sw1CdW_A^I)^$B=8Q!od0_ibKX+KI`)S= zJgS&|9aYRSPAcZm9#_m70>zxSJh9HtImNr+zo3})TvWUt_!-5VAN&)gK5ySr%-ruP zX6}oMnfoKf%;oe&P~>4~?(Gdax2(HE@fMA7?-v(;7ySIs8Tl;_=41f4l{T>DP|Wd? zKMFtRfzwA!KY3ig?8Eg-t`@C<&k-?77w&@y=89t(R6mqG%Uz7iWnC_p?3SQlK`>xC~k-Cc-Rdw`?dVaY3B-f XH~h9Q-NRf{_QgGxAlAMH6x082ln|2} literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/WMath.cpp.o b/libraries/VirtualWire/examples/transmitter/applet/WMath.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..61dcc12fc9a5bd419a69cc73764926f49e99c2d4 GIT binary patch literal 6980 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 W;Mx)d6_sj2 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/pins_arduino.c.o b/libraries/VirtualWire/examples/transmitter/applet/pins_arduino.c.o new file mode 100644 index 0000000000000000000000000000000000000000..e80a64d57f0063103c7bf3099537d5b7c1ae5feb GIT binary patch literal 3012 zcma)8O>Epm6n^8~O*Y*oBrLzGKq;glE#OVtP(ctaG)h8HfQSkXuwcAvcjI=~UcBBy zLZu=EHw1+P5)uW(g%*Lt2~}JGaY8~I5E2}?0|yQ{&;uO8_r^1}(Q6phj_i7~Nnq*^JAjESqo=m3#1L6yo;5JZLR zs4y~Hxwo=ZB`PYuOjL>?(SQ(3RRQPVURtWwDn#X(cuHxhdTh6`i)d&P9@M)73o&Hf zqFhpTU6M8gilZj~i1owxH3Vv*uu<~-NIA|fv%?r^8d3dFA%GIdqWe_8yMiTepS z&ifADaau3sKNAOXJn_N|dW+MDD}V07uiRL1a<*oNPT%u`JEx})-c?(L^}HRrwI~SM zy_$U{thK#Ht<`MSOq2hZ@%(1H@3^!uThC6e>&f+I5V}3>BkDyCUb(r--P85_o~34) z&3F$>@lFbHqg*BLuMmHapqtbxVS|HA&~0=;qJ1<)w@Y*@P11fUDlw!KqzI!}9v#2` zrC7(mm@BQV*X_=euNf!=Tl1JEmht_7-=y-|+2@o1{c7-pC!v9z=2P>t2n|+H@-W zSf0UPERP=O|BBlSA0Hn77dMF*of}Z*TVeVyQbz$L$kb%7k)fbfFX}D480eC^fQvb!a#|h!dgEA zyMDn#o(FjqFz4VkjbaR8Wb?H_`~gmj&ZljyvwV>@_>@Ydu;tBg{_INFF38%)k{KJD ze3Bo{*tY=Rm$CWiPJ47?lP~C0Ha0m|x~BYkvOB=_sZ%iA!><@r%RvgD)20oOre*|90*!g?WvQ9iUzi3$m zuwp%^!LkH%b1PCuovszSEs59NFh~q1u$n=4&5}ovWwF_I?a<AdaQpJonEHieCht SR6O_5`xyHD$al*x74i?>NxHuP literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/transmitter.cpp b/libraries/VirtualWire/examples/transmitter/applet/transmitter.cpp new file mode 100644 index 0000000..8073bc9 --- /dev/null +++ b/libraries/VirtualWire/examples/transmitter/applet/transmitter.cpp @@ -0,0 +1,52 @@ +// transmitter.pde +// +// Simple example of how to use VirtualWire to transmit messages +// Implements a simplex (one-way) transmitter with an TX-C1 module +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: transmitter.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +#include "WProgram.h" +void setup(); +void loop(); +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec +} + +void loop() +{ + const char *msg = "hello"; + + digitalWrite(13, true); // Flash a light to show transmitting + vw_send((uint8_t *)msg, strlen(msg)); + vw_wait_tx(); // Wait until the whole message is gone + digitalWrite(13, false); + delay(200); +} + +int main(void) +{ + init(); + + setup(); + + for (;;) + loop(); + + return 0; +} + diff --git a/libraries/VirtualWire/examples/transmitter/applet/transmitter.cpp.o b/libraries/VirtualWire/examples/transmitter/applet/transmitter.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..939b61210f856b084ceb57ed6fb4cbaca861039b GIT binary patch literal 4524 zcmb_gYiJx*6h5K$Q2HM(|))HE)SR#|zWK0G(yX)+v z4^bKm`bR3&)+a@O_`*Mepn{-S&>#7sPy|s>WD$`H3P$h&3i12yoSU7j3KcwX_k8D^ zd%rpN&bjwaa&p)H+Z@LcD~=qJx+Su+MdT3#drXJ5vP2fis9!9WrRqoH6>++qYdhz+ zr#riygU;cWdFY;6CGG9E!X=Vcm=S5pJKH$GnpH!-q zo^+}?C`FQLYNnNPFcT`I4%KA3q%v_VW2~6cS;h{O)S27_RP$JML>vR9CG{vgt&ibH z2{R@SX8}A$FlbKfy6$@GgND0}rqj;f)Ry;%9dXe$C9fOf*I(M;GOy0Lt#`l+hsT3b z`GyS}Hf|mmg>}pe{ehu!=vQq_{#?yy8;aMk9%X4BAij^m8xSw z6#3zRSAi=MN%-bNXuYHqUTjyZ$bG1|Is-Yzwr{o7CBw>YMtjqCTeGDzCpB3*9Hw9{h?B0 zgucvEU1yh{mD;@8q|h;wpP zM^0#4VX-9bo(3D6Pu8Kui+>U59<*Y)T#+XM;?4UC(3lsLphU>1d&St+M@@DLS^ulV zkNW>gFIkPI@^&9MoZGQ}eXb{eV}4US#qm-#7%BO~xgqQXxJo0r85cLXne;4=>GSuF zaVf_PCd$!uQd-F;&E5eb`Ra+W$SXicVXQ|jiu~h|xCnElT6MP$sx$2gBJv2+?)Mqb_}4r0b?TJuy7w@Nxnw(oILY@o_>w1v<$FlSKpA-!d>eqshozk1<3VM|0Lppr^%1DpIi7}X zF+-E!+XGELOnrv$W#A;=SK!OTXT`=|gd@o}uRDI9vZgq`Hu557V8nBNr|Bj1;39Ak4TV9+11tuV&M zIbkVg!#W;6fUD9UfByCoHUDBpK6Fz)aZ`l+QK67G=$8+&GdC2TJE zBSC3bQ4rhQAL5f@ONGD1(ysn}LosjUR-(uaN=N-L^35~iJKkLEK`DsLoe=-A5T7Lu z%E80>uxf~TXIxFZ06&lwXpWW~&lvW34*Dj=pF?x6&|ibzsW^h>eMSE%=!1$sg1%ev ztI)3EGPF;u7eSzyHTO6%cs_+brx;3}C+5Ko;XO^vntF{G{n__TViqCfZ8Ty&;(cQD z`2qSv#q_;HtVhNLV$FwVsl^u+XQ01OoQ19_<{5WM@iOS26!Sa#cg37n3WtWxzfCbu zi>zYuELNNYUa5FB@H)kL;7y7-_ie;F-<=7(UorXbP|W-X6my#9*}NPejJ4?D%)c;O z6|-NK2PQQeKh_|0Wpym`%Pyri=4|02Kv-L?ip|*N#*P0J#Lr@!JbV^0DY7~IKvtq< zR~TsiUdhs-l3f)8lfTvj^UvzL>i|w;P3T*I=I9a0=h}Bl3hQ4>tUO#(>)%SOYs>r` w5<`-hVasXwl_y8Pjs={lG3IRRjrrNJq$Xya7*6Fe`2#aA!>^oND_h%t0hU+*LjV8( literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/transmitter.eep b/libraries/VirtualWire/examples/transmitter/applet/transmitter.eep new file mode 100644 index 0000000..7c166a1 --- /dev/null +++ b/libraries/VirtualWire/examples/transmitter/applet/transmitter.eep @@ -0,0 +1 @@ +:00000001FF diff --git a/libraries/VirtualWire/examples/transmitter/applet/transmitter.elf b/libraries/VirtualWire/examples/transmitter/applet/transmitter.elf new file mode 100644 index 0000000000000000000000000000000000000000..90d7981119061c577e3d078d676d8db2f891816c GIT binary patch literal 36028 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/transmitter.hex b/libraries/VirtualWire/examples/transmitter/applet/transmitter.hex new file mode 100644 index 0000000..522cc6e --- /dev/null +++ b/libraries/VirtualWire/examples/transmitter/applet/transmitter.hex @@ -0,0 +1,202 @@ +:100000000C9462000C948A000C948A000C948A0070 +:100010000C948A000C948A000C948A000C948A0038 +:100020000C948A000C948A000C948A000C94500161 +:100030000C948A000C948A000C948A000C948A0018 +:100040000C9411040C948A000C94E7020C948A001E +:100050000C948A000C948A000C948A000C948A00F8 +:100060000C948A000C948A000000000024002700F1 +:100070002A0000000000250028002B0000000000DE +:1000800023002600290004040404040404040202DA +:100090000202020203030303030301020408102007 +:1000A0004080010204081020010204081020000012 +:1000B0000007000201000003040600000000000029 +:1000C0000000A00311241FBECFEFD8E0DEBFCDBFDC +:1000D00011E0A0E0B1E0EAE1FCE002C005900D9281 +:1000E000AA36B107D9F712E0AAE6B1E001C01D9225 +:1000F000A034B107E1F710E0C4ECD0E004C02297CF +:10010000FE010E940706C23CD107C9F70E94E00227 +:100110000C940B060C940000809394010895209198 +:100120008A01222329F0809195018F5F80939501A8 +:100130008091960190919701281759F0903510F011 +:100140008DE101C08BE0890F809397012093960188 +:1001500003C09C5E9093970190919701903A08F4A8 +:1001600088C0209198013091990136952795309358 +:1001700099012093980180919501853028F038608D +:100180003093990120939801905A9093970110927F +:10019000950180919301882309F45BC080919A01B5 +:1001A0008F5F80939A018C3008F463C0209198018E +:1001B00030919901922F9F73A3E5B1E0FD0140E0DA +:1001C0008081981729F04F5F31964031C9F740E0A0 +:1001D00086E0369527958A95E1F790E08C9128176F +:1001E00029F09F5F11969031C9F790E0242F229556 +:1001F000207F292B80916B01882371F420939B0130 +:10020000822F84508B3140F01092930180919C0199 +:100210008F5F80939C01089580916B01E82FF0E03F +:10022000E459FE4F20838F5F80936B0190916B01A7 +:1002300080919B01981750F01092930180919D013D +:100240008F5F80939D0181E080936A0110929A01F3 +:100250000895809198019091990188539B4049F4A9 +:1002600081E08093930110929A0110926B01109299 +:100270006A01089580918B018823E1F708958091A8 +:100280005201609194010E94050580910D0160E08A +:100290000E94050510928B0181E0809392010895E0 +:1002A0001F920F920FB60F9211242F933F934F93EB +:1002B0005F936F937F938F939F93AF93BF93EF93CE +:1002C000FF9380910C010E94520580938A018091D6 +:1002D0008B018823D1F180918C018F5F80938C01F9 +:1002E000815099F5E0918D0180918E01E81760F0C1 +:1002F0000E943F0180918F0190919001019690930F +:10030000900180938F0121C080910D019091910106 +:1003100021E030E0092E02C0220F331F0A94E2F7D9 +:10032000F0E0E25FFE4F608162239F5F9093910156 +:100330000E94050580919101863038F0109291015C +:1003400080918D018F5F80938D0180918C01883029 +:1003500010F010928C0180919201882311F00E947C +:100360008F00FF91EF91BF91AF919F918F917F91FE +:100370006F915F914F913F912F910F900FBE0F9012 +:100380001F9018951F9310928D0110929101109259 +:100390008C01109292016091940111E0612780918B +:1003A00052010E94050510938B011F910895CF9370 +:1003B000DF93482F562F6C3110F080E0A1C0809160 +:1003C0008B018823E1F7A52FAD5F6FEF7FEF6A27E1 +:1003D000062E6295607F6025072E762F62956F70DE +:1003E0000626669576276727660F660F660F6025D7 +:1003F000B0E0FD0124E0F595E7952A95E1F7ED5A87 +:10040000FE4F808180931601AF70B070AD5ABE4F21 +:100410008C9180931701C8E1D1E0242F392FC901B5 +:10042000DC0125C0EC916E27062E6295607F602569 +:10043000072E762F62956F700626669576276727BA +:10044000660F660F660F6025F0E094E0F595E7957E +:100450009A95E1F7ED5AFE4F80818883ED91F0E0A7 +:10046000EF70F070ED5AFE4F8081898322968A2FBB +:10047000841B8517B8F25F5F550F9B01209530955F +:10048000A52FB0E0AA5EBE4FF90184E0F695E7958E +:100490008A95E1F7EF70F070ED5AFE4F80818C93F2 +:1004A000A52FAF5F8A2F90E08A5E9E4FF901EF7013 +:1004B000F070ED5AFE4F4081FC014083AF5F8A2F00 +:1004C00090E08A5E9E4FF901EF2FFF27E295EF70D3 +:1004D000ED5AFE4F4081FC014083AF5FB0E0AA5E61 +:1004E000BE4F232F33272F7030702D5A3E4FF90106 +:1004F00080818C93545F50938E010E94C20181E0F1 +:10050000DF91CF9108959C0140E050E060E874E8ED +:100510008EE190E00E94B4051092800089E0809303 +:1005200081003093890020938800EFE6F0E080811D +:100530008260808380910D0161E00E94E5048091DA +:100540000C0160E00E94E5048091520161E00E948C +:10055000E50480915201609194010E94050508957F +:100560008DE061E00E94050580E091E065E00E9479 +:10057000D7010E943A018DE060E00E94050568EC19 +:1005800070E080E090E00E94810408950F931F9333 +:1005900002E212E0C80140E855E260E070E00E942B +:1005A0002403C80166E071E00E94060481E00E9415 +:1005B0008C0080ED97E00E9483021F910F910895B7 +:1005C0000E94AB040E94C6020E94B002FDCF1F929F +:1005D0000F920FB60F9211242F933F934F935F9377 +:1005E0006F937F938F939F93AF93BF93EF93FF93FB +:1005F0004091C600E0911E02F0911F02CF010196CA +:1006000060E870E00E94A1059C0180912002909119 +:1006100021022817390739F0E256FE4F4083309304 +:100620001F0220931E02FF91EF91BF91AF919F9106 +:100630008F917F916F915F914F913F912F910F908B +:100640000FBE0F901F901895AF92BF92CF92DF927E +:10065000EF92FF920F931F93CF93DF936C017A0178 +:100660008B01DC011496AD90BC901597CB01BA01BB +:1006700022E030E040E050E00E94D605205C3D4B97 +:10068000404F5F4FCA01B901A80197010E94D605EA +:10069000C901DA010197A109B109292F3A2F4B2F7E +:1006A000552747FD5A950196A11DB11DE5012883E7 +:1006B000E601EE81FF8181508083EA85FB85208100 +:1006C00041E050E0CA010E8402C0880F991F0A94CD +:1006D000E2F7282B2083EA85FB852081CA010F845D +:1006E00002C0880F991F0A94E2F7282B2083EA851D +:1006F000FB858081088802C0440F551F0A94E2F7E9 +:10070000842B8083DF91CF911F910F91FF90EF9009 +:10071000DF90CF90BF90AF900895FC01A085B18588 +:1007200021898C9190E0022E02C0959587950A94BC +:10073000E2F780FFF6CF0484F585E02D608308950D +:1007400087E691E090932302809322028EE991E064 +:10075000909325028093240285EC90E090932702E9 +:100760008093260284EC90E09093290280932802E3 +:1007700080EC90E090932B0280932A0281EC90E031 +:1007800090932D0280932C0286EC90E090932F02A0 +:1007900080932E0284E08093300283E080933102C4 +:1007A00087E08093320285E08093330208950F93AF +:1007B0001F93CF93DF938C01EB0109C02196D801E1 +:1007C000ED91FC910190F081E02DC80109956881BF +:1007D0006623A1F7DF91CF911F910F9108950F9399 +:1007E0001F938C01DC01ED91FC910190F081E02DD3 +:1007F0006DE00995D801ED91FC910190F081E02D1B +:10080000C8016AE009951F910F9108950F931F93F6 +:100810008C010E94D703C8010E94EF031F910F9122 +:1008200008951F920F920FB60F9211242F938F935A +:100830009F93AF93BF938091340290913502A09122 +:100840003602B09137020196A11DB11D809334028A +:1008500090933502A0933602B0933702809138020C +:1008600090913902A0913A02B0913B028050904C95 +:10087000AF4FBF4F8093380290933902A0933A0252 +:10088000B0933B0227C08091380290913902A09129 +:100890003A02B0913B0280589E43A040B040809302 +:1008A000380290933902A0933A02B0933B028091B0 +:1008B0003C0290913D02A0913E02B0913F02019610 +:1008C000A11DB11D80933C0290933D02A0933E0276 +:1008D000B0933F028091380290913902A0913A0280 +:1008E000B0913B0281589E43A040B04060F6BF915A +:1008F000AF919F918F912F910F900FBE0F901F90EE +:100900001895EF92FF920F931F937B018C018FB785 +:10091000F89440913C0250913D0260913E027091EA +:100920003F028FBF2FB7F89480913C0290913D0217 +:10093000A0913E02B0913F022FBF841B950BA60BE6 +:10094000B70BE816F9060A071B0760F71F910F910E +:10095000FF90EF900895789484B5826084BD84B54B +:10096000816084BD85B5826085BD85B5816085BDAA +:10097000EEE6F0E0808181608083E1E8F0E0808154 +:1009800082608083808181608083E0E8F0E0808104 +:1009900081608083E1EBF0E0808184608083E0EB24 +:1009A000F0E0808181608083EAE7F0E0808184600C +:1009B0008083808182608083808181608083808168 +:1009C000806880831092C1000895282F30E0C9010B +:1009D00086569F4FFC0194912A573F4FF90184910D +:1009E000882391F0E82FF0E0EE0FFF1FE859FF4F4A +:1009F000A591B491662329F48C91909589238C93C9 +:100A000008958C91892B8C930895482F50E0CA014A +:100A100082559F4FFC012491CA0186569F4FFC01CD +:100A200094914A575F4FFA0134913323D1F1222335 +:100A300031F1233021F4809180008F7705C024307C +:100A400031F4809180008F7D8093800018C0213028 +:100A500019F484B58F7704C0223021F484B58F7DDA +:100A600084BD0DC0263021F48091B0008F7705C081 +:100A7000273029F48091B0008F7D8093B000E32F60 +:100A8000F0E0EE0FFF1FEE58FF4FA591B4916623E3 +:100A900029F48C91909589238C9308958C91892BBE +:100AA0008C930895682F70E0CB0182559F4FFC0115 +:100AB0002491CB0186569F4FFC0144916A577F4F8A +:100AC000FB019491992319F420E030E038C02223EF +:100AD00031F1233021F4809180008F7705C02430DC +:100AE00031F4809180008F7D8093800018C0213088 +:100AF00019F484B58F7704C0223021F484B58F7D3A +:100B000084BD0DC0263021F48091B0008F7705C0E0 +:100B1000273029F48091B0008F7D8093B000892F19 +:100B200090E0880F991F84589F4FFC01A591B491C4 +:100B30008C9120E030E0842311F021E030E0C90105 +:100B4000089597FB092E07260AD077FD04D049D0D7 +:100B500006D000201AF4709561957F4F0895F6F73E +:100B6000909581959F4F0895A1E21A2EAA1BBB1B59 +:100B7000FD010DC0AA1FBB1FEE1FFF1FA217B30769 +:100B8000E407F50720F0A21BB30BE40BF50B661F7F +:100B9000771F881F991F1A9469F760957095809543 +:100BA00090959B01AC01BD01CF01089597FB092EE3 +:100BB00005260ED057FD04D0D7DF0AD0001C38F42C +:100BC00050954095309521953F4F4F4F5F4F089579 +:100BD000F6F790958095709561957F4F8F4F9F4F59 +:100BE0000895AA1BBB1B51E107C0AA1FBB1FA61774 +:100BF000B70710F0A61BB70B881F991F5A95A9F7C6 +:100C000080959095BC01CD010895EE0FFF1F0590D2 +:0A0C1000F491E02D0994F894FFCF51 +:100C1A0068656C6C6F007365747570000B0C2A2A1A +:100C2A002A2A2A2A382C00000000000000000000AE +:100C3A0000000000000000000000000000000000AA +:100C4A00000000000000000000000000000000009A +:100C5A00000000000000000000000000000000008A +:100C6A0000000A0D0E131516191A1C232526292A07 +:0A0C7A002C3234000000008D03004E +:00000001FF diff --git a/libraries/VirtualWire/examples/transmitter/applet/transmitter.pde b/libraries/VirtualWire/examples/transmitter/applet/transmitter.pde new file mode 100644 index 0000000..a7ef3ed --- /dev/null +++ b/libraries/VirtualWire/examples/transmitter/applet/transmitter.pde @@ -0,0 +1,36 @@ +// transmitter.pde +// +// Simple example of how to use VirtualWire to transmit messages +// Implements a simplex (one-way) transmitter with an TX-C1 module +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: transmitter.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec +} + +void loop() +{ + const char *msg = "hello"; + + digitalWrite(13, true); // Flash a light to show transmitting + vw_send((uint8_t *)msg, strlen(msg)); + vw_wait_tx(); // Wait until the whole message is gone + digitalWrite(13, false); + delay(200); +} diff --git a/libraries/VirtualWire/examples/transmitter/applet/wiring.c.o b/libraries/VirtualWire/examples/transmitter/applet/wiring.c.o new file mode 100644 index 0000000000000000000000000000000000000000..10c122b3cf3bb30822a20257926b3cb1e1795f8c GIT binary patch literal 8800 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 tO_?Hi*p^G~T(z;mz(A_ScL!#{{gj|=x+c3 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/wiring_digital.c.o b/libraries/VirtualWire/examples/transmitter/applet/wiring_digital.c.o new file mode 100644 index 0000000000000000000000000000000000000000..3ad4053a4e9ca21912af22bcf1b865134b939eed GIT binary patch literal 8220 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 literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/applet/wiring_shift.c.o b/libraries/VirtualWire/examples/transmitter/applet/wiring_shift.c.o new file mode 100644 index 0000000000000000000000000000000000000000..35a215f942b2ca94f4a38e551dd428fb83bd8563 GIT binary patch literal 4032 zcma)9OKenC82-;pTPiJu@={VB1L38@og%0N6o|+}Ay6S`B9-CJqtgr1nP%n|T7m&F ziVFinOEqqc3ym&hXV3%_x-g0xD?Sq4*shEVBQ~jQOswB`?m08Jl^}mO{l5Qs&pqcq z_Y7xt?A@u95-Um$N>vkCQz!BooEvn&YFQxjMK!AxO>-KeP0i|nI#f3cA(7?M(69w2 zk?4GhHf?Iy-0;jCks4#K7pZmB*2ciIst6f!Xl%}+h9EqFZU5~=m_zCd7|(ghcs7-aI}ZQR;^kAho^(cbZfXxFx7+0Q zRH2wDS>HW|wTqneie5gOD0O-rzLVlcl>9VS)ahi$!~-`Jy+gIZKH)V27B^`17Na*C zoM&+U6twmk#=giPmS_Q%Dw>o93KX9-YAr`41kvDBiHjw(%9YEenLN)KCVQAyI$IypL^+<{61D>-Ui7V9K8 zpt`CdEpPl`EuIQu(95K#>e^fVAvc`X~#mwNQ~GybwjtDt~74*2Y{^CfMMr% z9z0y{H0r$vn-%NhoWu1_qu!seu^y&csrNRx%>k8#NLoT-#QOT7hwJ5L2J6pypp|+b zgWDWX*^HzZi4p7j5PG;?FN)arZ8kox-w=k)0hPl@Vw@H0y9PtJUK#aTVdMOGP0`1C z-(WC@K1vCWUjnNC(#OF$*q*23IW*m!`joL~k&4X4534eaoZ~zUK6e%ddm>!#eQfGk z*sQS5og{3pk+F$zOmx!9uzq+Z)T8>@Jad7JO)LPZ{`MK0SO)z`;}z6@7`*z;7@JsM z@sW&8Og_I;=fk(HN>rcJu+EcKm8f2ou+C1eN>q1hSZAkIC8~ERtaGQU62%Vet*Ux0 z!q+tS<(TpFyv)XYN>k#e{_;vB4j$OCE0GY8w#05r_G+?ydz(hTt2=iAQVSHpQe|1dlTylwbO;6H{x1gygWWG>gN$#AaCe8Z1`FE+dbe5K)e zaK~`IFZUv1>Nw#1-`WP?W5(VJ+-U6kfKM6D{dpFHxlaQRV9YijK)$o($q>(hGoJ5) zB@<4+Wfz4eOig_@^b&nyw7dGyVjo%iE*%jh@3_lCx zyV!WHDR~T-331PGAE@tD#E`Rx7=HrDy(eD?eA96LeyStq0fK}%+s;0hKHD>TO(L`e Pzkh6uK7*)#4)%Wm!3NH; literal 0 HcmV?d00001 diff --git a/libraries/VirtualWire/examples/transmitter/transmitter.pde b/libraries/VirtualWire/examples/transmitter/transmitter.pde new file mode 100644 index 0000000..a7ef3ed --- /dev/null +++ b/libraries/VirtualWire/examples/transmitter/transmitter.pde @@ -0,0 +1,36 @@ +// transmitter.pde +// +// Simple example of how to use VirtualWire to transmit messages +// Implements a simplex (one-way) transmitter with an TX-C1 module +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@open.com.au) +// Copyright (C) 2008 Mike McCauley +// $Id: transmitter.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $ + +#include +#undef int +#undef abs +#undef double +#undef float +#undef round +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec +} + +void loop() +{ + const char *msg = "hello"; + + digitalWrite(13, true); // Flash a light to show transmitting + vw_send((uint8_t *)msg, strlen(msg)); + vw_wait_tx(); // Wait until the whole message is gone + digitalWrite(13, false); + delay(200); +} diff --git a/libraries/VirtualWire/keywords.txt b/libraries/VirtualWire/keywords.txt new file mode 100644 index 0000000..fe3382e --- /dev/null +++ b/libraries/VirtualWire/keywords.txt @@ -0,0 +1,20 @@ +VirtualWire KEYWORD1 + +VW_MAX_MESSAGE_LEN LITERAL1 +VW_MAX_PAYLOAD LITERAL1 + +vw_set_tx_pin KEYWORD1 +vw_set_rx_pin KEYWORD1 +vw_set_ptt_pin KEYWORD1 +vw_set_ptt_inverted KEYWORD1 +vw_setup KEYWORD1 +vw_rx_start KEYWORD1 +vw_rx_stop KEYWORD1 +vx_tx_active KEYWORD1 +vw_wait_tx KEYWORD1 +vw_wait_rx KEYWORD1 +vw_wait_rx_max KEYWORD1 +vw_send KEYWORD1 +vw_have_message KEYWORD1 +vw_get_message KEYWORD1 + diff --git a/libraries/VirtualWire/util/crc16.h b/libraries/VirtualWire/util/crc16.h new file mode 100644 index 0000000..18c173c --- /dev/null +++ b/libraries/VirtualWire/util/crc16.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz + Copyright (c) 2005, 2007 Joerg Wunsch + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ + +// Port to Energia / MPS430 by Yannick DEVOS XV4Y - (c) 2013 +// http://xv4y.radioclub.asia/ +// + +/* $Id: crc16.h 2136 2010-06-08 12:03:38Z joerg_wunsch $ */ + +#ifndef _UTIL_CRC16_H_ +#define _UTIL_CRC16_H_ + +#include + +#define lo8(x) ((x)&0xff) +#define hi8(x) ((x)>>8) + + uint16_t crc16_update(uint16_t crc, uint8_t a) + { + int i; + + crc ^= a; + for (i = 0; i < 8; ++i) + { + if (crc & 1) + crc = (crc >> 1) ^ 0xA001; + else + crc = (crc >> 1); + } + + return crc; + } + + uint16_t crc_xmodem_update (uint16_t crc, uint8_t data) + { + int i; + + crc = crc ^ ((uint16_t)data << 8); + for (i=0; i<8; i++) + { + if (crc & 0x8000) + crc = (crc << 1) ^ 0x1021; + else + crc <<= 1; + } + + return crc; + } + uint16_t _crc_ccitt_update (uint16_t crc, uint8_t data) + { + data ^= lo8 (crc); + data ^= data << 4; + + return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) + ^ ((uint16_t)data << 3)); + } + + uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data) + { + uint8_t i; + + crc = crc ^ data; + for (i = 0; i < 8; i++) + { + if (crc & 0x01) + crc = (crc >> 1) ^ 0x8C; + else + crc >>= 1; + } + + return crc; + } + + +#endif /* _UTIL_CRC16_H_ */ diff --git a/libraries/Visuino_LiquidCrystal/Visuino_FastIO.cpp b/libraries/Visuino_LiquidCrystal/Visuino_FastIO.cpp new file mode 100644 index 0000000..72945bb --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_FastIO.cpp @@ -0,0 +1,267 @@ +// --------------------------------------------------------------------------- +// Created by Florian Fida on 20/01/12 +// Copyright 2012 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// http://creativecommons.org/licenses/by-sa/3.0/ +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// --------------------------------------------------------------------------- +// fio_shiftOut1 functions are based on Shif1 protocol developed by Roman Black +// (http://www.romanblack.com/shift1.htm) +// +// Thread Safe: No +// Extendable: Yes +// +// @file FastIO.h +// This file implements basic fast IO routines. +// +// @brief +// +// @version API 1.0.0 +// +// @author Florian Fida - +// +// 2012-03-16 bperrybap updated fio_shiftout() to be smaller & faster +// +// @todo: +// support chipkit: +// (https://github.com/chipKIT32/chipKIT32-MAX/blob/master/hardware/pic32/ +// cores/pic32/wiring_digital.c) +// --------------------------------------------------------------------------- +#include "Visuino_FastIO.h" + + +fio_register fio_pinToOutputRegister(uint8_t pin, uint8_t initial_state) +{ + pinMode(pin, OUTPUT); + + if(initial_state != SKIP) + { + digitalWrite(pin, initial_state); // also turns off pwm timer + } +#ifdef FIO_FALLBACK + // just wasting memory if not using fast io... + return 0; +#else + return portOutputRegister(digitalPinToPort(pin)); +#endif +} + + +fio_register fio_pinToInputRegister(uint8_t pin) +{ + pinMode(pin, INPUT); + digitalWrite(pin, LOW); // also turns off pwm timer and pullup +#ifdef FIO_FALLBACK + // just wasting memory if not using fast io... + return 0; +#else + return portInputRegister(digitalPinToPort(pin)); +#endif +} + + +fio_bit fio_pinToBit(uint8_t pin) +{ +#ifdef FIO_FALLBACK + // (ab)use the bit variable to store the pin + return pin; +#else + return digitalPinToBitMask(pin); +#endif +} + + +void fio_digitalWrite(fio_register pinRegister, fio_bit pinBit, uint8_t value) +{ +#ifdef FIO_FALLBACK + digitalWrite(pinBit, value); +#else + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if(value == LOW) + { + fio_digitalWrite_LOW(pinRegister,pinBit); + } + else + { + fio_digitalWrite_HIGH(pinRegister,pinBit); + } + } +#endif +} + +int fio_digitalRead(fio_register pinRegister, uint8_t pinBit) +{ +#ifdef FIO_FALLBACK + return digitalRead (pinBit); +#else + if (*pinRegister & pinBit) + { + return HIGH; + } + return LOW; +#endif +} + +void fio_shiftOut (fio_register dataRegister, fio_bit dataBit, + fio_register clockRegister, fio_bit clockBit, + uint8_t value, uint8_t bitOrder) +{ + // # disable interrupts + int8_t i; + + if(bitOrder == LSBFIRST) + { + for(i = 0; i < 8; i++) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if(value & 1) + { + fio_digitalWrite_HIGH(dataRegister, dataBit); + } + else + { + fio_digitalWrite_LOW(dataRegister, dataBit); + } + value >>= 1; + fio_digitalWrite_HIGH (clockRegister, clockBit); + fio_digitalWrite_LOW (clockRegister,clockBit); + } + } + + } + else + { + for(i = 0; i < 8; i++) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if(value & 0x80) + { + fio_digitalWrite_HIGH(dataRegister, dataBit); + } + else + { + fio_digitalWrite_LOW(dataRegister, dataBit); + } + value <<= 1; + fio_digitalWrite_HIGH (clockRegister, clockBit); + fio_digitalWrite_LOW (clockRegister,clockBit); + } + } + } +} + + +void fio_shiftOut(fio_register dataRegister, fio_bit dataBit, + fio_register clockRegister, fio_bit clockBit) +{ + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + // shift out 0x0 (B00000000) fast, byte order is irrelevant + fio_digitalWrite_LOW (dataRegister, dataBit); + + for(uint8_t i = 0; i<8; ++i) + { + fio_digitalWrite_HIGH (clockRegister, clockBit); + fio_digitalWrite_SWITCH (clockRegister, clockBit); + } + } +} + + +void fio_shiftOut1_init(uint8_t pin) +{ + fio_shiftOut1_init(fio_pinToOutputRegister(pin,HIGH),fio_pinToBit(pin)); +} + +void fio_shiftOut1_init(fio_register shift1Register, fio_bit shift1Bit) +{ + // Make sure that capacitors are charged + // 300us is an educated guess... + fio_digitalWrite(shift1Register,shift1Bit,HIGH); + delayMicroseconds(300); +} + + +void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value, + boolean noLatch) +{ + /* + * this function are based on Shif1 protocol developed by Roman Black + * (http://www.romanblack.com/shift1.htm) + * + * test sketches: + * http://pastebin.com/raw.php?i=2hnC9v2Z + * http://pastebin.com/raw.php?i=bGg4DhXQ + * http://pastebin.com/raw.php?i=tg1ZFiM5 + * http://pastebin.com/raw.php?i=93ExPDD3 - cascading + * tested with: + * TPIC6595N - seems to work fine (circuit: http://www.3guys1laser.com/ + * arduino-one-wire-shift-register-prototype) + * 7HC595N + */ + + // iterate but ignore last bit (is it correct now?) + for(int8_t i = 7; i>=0; --i) + { + + // assume that pin is HIGH (smokin' pot all day... :) - requires + // initialization + if(value & _BV(i)) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + // HIGH = 1 Bit + fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW); + //hold pin LOW for 1us - done! :) + fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH); + } // end critical section + //hold pin HIGH for 15us + delayMicroseconds(15); + } + else + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + // LOW = 0 Bit + fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW); + // hold pin LOW for 15us + delayMicroseconds(15); + fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH); + } // end critical section + + // hold pin HIGH for 30us + delayMicroseconds(30); + } + if(!noLatch && i==1) + { + break; + } + } + + if(!noLatch) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + // send last bit (=LOW) and Latch command + fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW); + } // end critical section + delayMicroseconds(199); // Hold pin low for 200us + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + fio_digitalWrite_HIGH(shift1Register,shift1Bit); + } // end critical section + delayMicroseconds(299); // Hold pin high for 300us and leave it that + // way - using explicit HIGH here, just in case. + } +} + +void fio_shiftOut1(uint8_t pin, uint8_t value, boolean noLatch) +{ + fio_shiftOut1(fio_pinToOutputRegister(pin, SKIP),fio_pinToBit(pin),value, noLatch); +} diff --git a/libraries/Visuino_LiquidCrystal/Visuino_FastIO.h b/libraries/Visuino_LiquidCrystal/Visuino_FastIO.h new file mode 100644 index 0000000..81e8f30 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_FastIO.h @@ -0,0 +1,219 @@ +// --------------------------------------------------------------------------- +// Created by Florian Fida on 20/01/12 +// Copyright 2012 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// http://creativecommons.org/licenses/by-sa/3.0/ +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// --------------------------------------------------------------------------- +// fio_shiftOut1 functions are based on Shif1 protocol developed by Roman Black +// (http://www.romanblack.com/shift1.htm) +// +// Thread Safe: No +// Extendable: Yes +// +// @file FastIO.h +// This file implements basic fast IO routines. +// +// @brief +// +// @version API 1.0.0 +// +// @author Florian Fida - +// 2012-03-16 bperrybap mods for chipkit32 (pic32) Arduino +// support chipkit: +// (https://github.com/chipKIT32/chipKIT32-MAX/blob/master/hardware/pic32/ +// cores/pic32/wiring_digital.c) +// --------------------------------------------------------------------------- +#ifndef _FAST_IO_H_ +#define _FAST_IO_H_ + +#if (ARDUINO < 100) +#include +#else +#include +#endif + +#include // pleasing sanguino core +#include + + +#define SKIP 0x23 + +#if defined (__AVR__) +#include // for critical section management +typedef uint8_t fio_bit; +typedef volatile uint8_t *fio_register; + + +#elif defined(__PIC32MX__) +typedef uint32_t fio_bit; +typedef volatile uint32_t *fio_register; + + +#else +// fallback to Arduino standard digital i/o routines +#define FIO_FALLBACK +#define ATOMIC_BLOCK(dummy) if(true) +#define ATOMIC_RESTORESTATE +typedef uint8_t fio_bit; +typedef uint8_t fio_register; +#endif + + + +#if !defined(FIO_FALLBACK) && !defined(ATOMIC_BLOCK) +/* + * Define an ATOMIC_BLOCK that implements ATOMIC_FORCEON type + * Using the portable Arduino interrupts() and noInterrupts() + */ +#define ATOMIC_RESTORESTATE ATOMIC_FORCEON // sorry, no support for save/restore yet. +#define ATOMIC_FORCEON uint8_t sreg_save \ + __attribute__((__cleanup__(__iSeiParam))) = 0 + +static __inline__ uint8_t __iCliRetVal(void) +{ + noInterrupts(); + return(1); +} +static __inline__ void __iSeiParam(const uint8_t *__s) +{ + interrupts(); +} +#define ATOMIC_BLOCK(type) for(type, __Todo = __iCliRetVal(); __Todo; __Todo = 0) + +#endif // end of block to create compatible ATOMIC_BLOCK() + + + +/*! + @function + @abstract Get the output register for specified pin. + @discussion if fast digital IO is disabled this function returns NULL + @param pin[in] Number of a digital pin + @result Register + */ +fio_register fio_pinToOutputRegister(uint8_t pin, uint8_t initial_state = LOW); + +/*! + @function + @abstract Get the input register for specified pin. + @discussion if fast digital IO is disabled this function returns NULL + @param pin[in] Number of a digital pin + @result Register + */ +fio_register fio_pinToInputRegister(uint8_t pin); + +/*! + @function + @abstract Find the bit which belongs to specified pin + @discussion if fast digitalWrite is disabled this function returns the pin + @param pin[in] Number of a digital pin + @result Bit + */ +fio_bit fio_pinToBit(uint8_t pin); + + +/*! + @method + @abstract direct digital write + @discussion without any checks + @discussion falls back to normal digitalWrite if fast io is disabled + @param pinRegister[in] Register - ignored if fast digital write is disabled + @param pinBit[in] Bit - Pin if fast digital write is disabled + @param value[in] desired output + */ +// __attribute__ ((always_inline)) /* let the optimizer decide that for now */ +void fio_digitalWrite ( fio_register pinRegister, fio_bit pinBit, uint8_t value ); + +/** + * This is where the magic happens that makes things fast. + * Implemented as preprocessor directives to force inlining + * SWITCH is fast for FIO but probably slow for FIO_FALLBACK so SWITCHTO is recommended if the value is known. + */ + +#ifndef FIO_FALLBACK +#define fio_digitalWrite_LOW(reg,bit) *reg &= ~bit +#define fio_digitalWrite_HIGH(reg,bit) *reg |= bit +#define fio_digitalWrite_SWITCH(reg,bit) *reg ^= bit +#define fio_digitalWrite_SWITCHTO(reg,bit,val) fio_digitalWrite_SWITCH(reg,bit) +#else +// reg -> dummy NULL, bit -> pin +#define fio_digitalWrite_HIGH(reg,bit) digitalWrite(bit,HIGH) +#define fio_digitalWrite_LOW(reg,bit) digitalWrite(bit,LOW) +#define fio_digitalWrite_SWITCH(reg,bit) digitalWrite(bit, !digitalRead(bit)) +#define fio_digitalWrite_SWITCHTO(reg,bit,val) digitalWrite(bit,val); +#endif + +/*! + @function + @abstract direct digital read + @discussion without any checks + @discussion falls back to normal digitalRead if fast io is disabled + @param pinRegister[in] Register - ignored if fast io is disabled + @param pinBit[in] Bit - Pin if fast io is disabled + @result Value read from pin + */ +int fio_digitalRead ( fio_register pinRegister, fio_bit pinBit ); + +/*! + @method + @abstract faster shift out + @discussion using fast digital write + @discussion falls back to normal digitalWrite if fastio is disabled + @param dataRegister[in] Register of data pin - ignored if fast digital write is disabled + @param dataBit[in] Bit of data pin - Pin if fast digital write is disabled + @param clockRegister[in] Register of data pin - ignored if fast digital write is disabled + @param clockBit[in] Bit of data pin - Pin if fast digital write is disabled + @param bitOrder[in] bit order + */ +void fio_shiftOut( fio_register dataRegister, fio_bit dataBit, fio_register clockRegister, + fio_bit clockBit, uint8_t value, uint8_t bitOrder ); + +/*! + @method + @abstract faster shift out clear + @discussion using fast digital write + @discussion falls back to normal digitalWrite if fastio is disabled + @param dataRegister[in] Register of data pin - ignored if fast digital write is disabled + @param dataBit[in] Bit of data pin - Pin if fast digital write is disabled + @param clockRegister[in] Register of data pin - ignored if fast digital write is disabled + @param clockBit[in] Bit of data pin - Pin if fast digital write is disabled + */ +void fio_shiftOut(fio_register dataRegister, fio_bit dataBit, fio_register clockRegister, fio_bit clockBit); + +/*! + * @method + * @abstract one wire shift out + * @discussion protocol needs initialisation (fio_shiftOut1_init) + * @param shift1Register[in] pins register + * @param shift1Bit[in] pins bit + * @param value[in] value to shift out, last byte is ignored and always shifted out LOW + */ +void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value, boolean noLatch = false); +/*! + * @method + * @abstract one wire shift out + * @discussion protocol needs initialisation (fio_shiftOut1_init) + * @param pin[in] digital pin + * @param value[in] value to shift out, last byte is ignored and always shifted out LOW + */ +void fio_shiftOut1(uint8_t pin, uint8_t value, boolean noLatch = false); +/*! + * @method + * @abstract initializes one wire shift out protocol + * @discussion Puts pin to HIGH state and delays until Capacitors are charged. + * @param shift1Register[in] pins register + * @param shift1Bit[in] pins bit + */ +void fio_shiftOut1_init(fio_register shift1Register, fio_bit shift1Bit); +/*! + * @method + * @abstract initializes one wire shift out protocol + * @discussion Puts pin to HIGH state and delays until Capacitors are charged. + * @param pin[in] digital pin + */ +void fio_shiftOut1_init(uint8_t pin); + +#endif // FAST_IO_H diff --git a/libraries/Visuino_LiquidCrystal/Visuino_I2CIO.cpp b/libraries/Visuino_LiquidCrystal/Visuino_I2CIO.cpp new file mode 100644 index 0000000..4b4d02d --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_I2CIO.cpp @@ -0,0 +1,198 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file I2CIO.h +// This file implements a basic IO library using the PCF8574 I2C IO Expander +// chip. +// +// @brief +// Implement a basic IO library to drive the PCF8574* I2C IO Expander ASIC. +// The library implements basic IO general methods to configure IO pin direction +// read and write uint8_t operations and basic pin level routines to set or read +// a particular IO port. +// +// +// @version API 1.0.0 +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#if (ARDUINO < 100) +#include +#else +#include +#endif + +#include + +#include +#include "Visuino_I2CIO.h" + +// CLASS VARIABLES +// --------------------------------------------------------------------------- + + +// CONSTRUCTOR +// --------------------------------------------------------------------------- +I2CIO::I2CIO ( ) +{ + _i2cAddr = 0x0; + _dirMask = 0xFF; // mark all as INPUTs + _shadow = 0x0; // no values set + _initialised = false; +} + +// PUBLIC METHODS +// --------------------------------------------------------------------------- + +// +// begin +int I2CIO::begin ( uint8_t i2cAddr ) +{ + _i2cAddr = i2cAddr; + + Wire.begin ( ); + + _initialised = Wire.requestFrom ( _i2cAddr, (uint8_t)1 ); + +#if (ARDUINO < 100) + _shadow = Wire.receive (); +#else + _shadow = Wire.read (); // Remove the byte read don't need it. +#endif + + return ( _initialised ); +} + +// +// pinMode +void I2CIO::pinMode ( uint8_t pin, uint8_t dir ) +{ + if ( _initialised ) + { + if ( OUTPUT == dir ) + { + _dirMask &= ~( 1 << pin ); + } + else + { + _dirMask |= ( 1 << pin ); + } + } +} + +// +// portMode +void I2CIO::portMode ( uint8_t dir ) +{ + + if ( _initialised ) + { + if ( dir == INPUT ) + { + _dirMask = 0xFF; + } + else + { + _dirMask = 0x00; + } + } +} + +// +// read +uint8_t I2CIO::read ( void ) +{ + uint8_t retVal = 0; + + if ( _initialised ) + { + Wire.requestFrom ( _i2cAddr, (uint8_t)1 ); +#if (ARDUINO < 100) + retVal = ( _dirMask & Wire.receive ( ) ); +#else + retVal = ( _dirMask & Wire.read ( ) ); +#endif + + } + return ( retVal ); +} + +// +// write +int I2CIO::write ( uint8_t value ) +{ + int status = 0; + + if ( _initialised ) + { + // Only write HIGH the values of the ports that have been initialised as + // outputs updating the output shadow of the device + _shadow = ( value & ~(_dirMask) ); + + Wire.beginTransmission ( _i2cAddr ); +#if (ARDUINO < 100) + Wire.send ( _shadow ); +#else + Wire.write ( _shadow ); +#endif + status = Wire.endTransmission (); + } + return ( (status == 0) ); +} + +// +// digitalRead +uint8_t I2CIO::digitalRead ( uint8_t pin ) +{ + uint8_t pinVal = 0; + + // Check if initialised and that the pin is within range of the device + // ------------------------------------------------------------------- + if ( ( _initialised ) && ( pin <= 7 ) ) + { + // Remove the values which are not inputs and get the value of the pin + pinVal = this->read() & _dirMask; + pinVal = ( pinVal >> pin ) & 0x01; // Get the pin value + } + return (pinVal); +} + +// +// digitalWrite +int I2CIO::digitalWrite ( uint8_t pin, uint8_t level ) +{ + uint8_t writeVal; + int status = 0; + + // Check if initialised and that the pin is within range of the device + // ------------------------------------------------------------------- + if ( ( _initialised ) && ( pin <= 7 ) ) + { + // Only write to HIGH the port if the port has been configured as + // an OUTPUT pin. Add the new state of the pin to the shadow + writeVal = ( 1 << pin ) & ~_dirMask; + if ( level == HIGH ) + { + _shadow |= writeVal; + + } + else + { + _shadow &= ~writeVal; + } + status = this->write ( _shadow ); + } + return ( status ); +} + +// +// PRIVATE METHODS +// --------------------------------------------------------------------------- diff --git a/libraries/Visuino_LiquidCrystal/Visuino_I2CIO.h b/libraries/Visuino_LiquidCrystal/Visuino_I2CIO.h new file mode 100644 index 0000000..e05f16b --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_I2CIO.h @@ -0,0 +1,148 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file I2CIO.h +// This file implements a basic IO library using the PCF8574 I2C IO Expander +// chip. +// +// @brief +// Implement a basic IO library to drive the PCF8574* I2C IO Expander ASIC. +// The library implements basic IO general methods to configure IO pin direction +// read and write uint8_t operations and basic pin level routines to set or read +// a particular IO port. +// +// @version API 1.0.0 +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- + +#ifndef _I2CIO_H_ +#define _I2CIO_H_ + +#include + +#define _I2CIO_VERSION "1.0.0" + +/*! + @class + @abstract I2CIO + @discussion Library driver to control PCF8574 based ASICs. Implementing + library calls to set/get port through I2C bus. + */ + +class I2CIO +{ +public: + /*! + @method + @abstract Constructor method + @discussion Class constructor constructor. + */ + I2CIO ( ); + + /*! + @method + @abstract Initializes the device. + @discussion This method initializes the device allocating an I2C address. + This method is the first method that should be call prior to calling any + other method form this class. On initialization all pins are configured + as INPUT on the device. + + @param i2cAddr: I2C Address where the device is located. + @result 1 if the device was initialized correctly, 0 otherwise + */ + int begin ( uint8_t i2cAddr ); + + /*! + @method + @abstract Sets the mode of a particular pin. + @discussion Sets the mode of a particular pin to INPUT, OUTPUT. digitalWrite + has no effect on pins which are not declared as output. + + @param pin[in] Pin from the I2C IO expander to be configured. Range 0..7 + @param dir[in] Pin direction (INPUT, OUTPUT). + */ + void pinMode ( uint8_t pin, uint8_t dir ); + + /*! + @method + @abstract Sets all the pins of the device in a particular direction. + @discussion This method sets all the pins of the device in a particular + direction. This method is useful to set all the pins of the device to be + either inputs or outputs. + @param dir[in] Direction of all the pins of the device (INPUT, OUTPUT). + */ + void portMode ( uint8_t dir ); + + /*! + @method + @abstract Reads all the pins of the device that are configured as INPUT. + @discussion Reads from the device the status of the pins that are configured + as INPUT. During initialization all pins are configured as INPUTs by default. + Please refer to pinMode or portMode. + + @param none + */ + uint8_t read ( void ); + + /*! + @method + @abstract Read a pin from the device. + @discussion Reads a particular pin from the device. To read a particular + pin it has to be configured as INPUT. During initialization all pins are + configured as INPUTs by default. Please refer to pinMode or portMode. + + @param pin[in] Pin from the port to read its status. Range (0..7) + @result Returns the pin status (HIGH, LOW) if the pin is configured + as an output, reading its value will always return LOW regardless of its + real state. + */ + uint8_t digitalRead ( uint8_t pin ); + + /*! + @method + @abstract Write a value to the device. + @discussion Writes to a set of pins in the device. The value is the binary + representation of all the pins in device. The value written is masked with + the configuration of the direction of the pins; to change the state of + a particular pin with this method, such pin has to be configured as OUTPUT + using the portMode or pinMode methods. If no pins have been configured as + OUTPUTs this method will have no effect. + + @param value[in] value to be written to the device. + @result 1 on success, 0 otherwise + */ + int write ( uint8_t value ); + + /*! + @method + @abstract Writes a digital level to a particular pin. + @discussion Write a level to the indicated pin of the device. For this + method to have effect, the pin has to be configured as OUTPUT using the + pinMode or portMode methods. + + @param pin[in] device pin to change level. Range (0..7). + @para level[in] logic level to set the pin at (HIGH, LOW). + @result 1 on success, 0 otherwise. + */ + int digitalWrite ( uint8_t pin, uint8_t level ); + + + +private: + uint8_t _shadow; // Shadow output + uint8_t _dirMask; // Direction mask + uint8_t _i2cAddr; // I2C address + bool _initialised; // Initialised object + +}; + +#endif \ No newline at end of file diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LCD.cpp b/libraries/Visuino_LiquidCrystal/Visuino_LCD.cpp new file mode 100644 index 0000000..df04c22 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LCD.cpp @@ -0,0 +1,347 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LCD.cpp +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK. +// +// @brief +// This is a basic implementation of the HD44780 library of the +// Arduino SDK. This library is a refactored version of the one supplied +// in the Arduino SDK in such a way that it simplifies its extension +// to support other mechanism to communicate to LCDs such as I2C, Serial, SR, ... +// The original library has been reworked in such a way that this will be +// the base class implementing all generic methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets. +// +// This base class is a pure abstract class and needs to be extended. As reference, +// it has been extended to drive 4 and 8 bit mode control, LCDs and I2C extension +// backpacks such as the I2CLCDextraIO using the PCF8574* I2C IO Expander ASIC. +// +// +// @version API 1.1.0 +// +// 2012.03.29 bperrybap - changed comparision to use LCD_5x8DOTS rather than 0 +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#include +#include +#include + +#if (ARDUINO < 100) +#include +#else +#include +#endif +#include "Visuino_LCD.h" + +// CLASS CONSTRUCTORS +// --------------------------------------------------------------------------- +// Constructor +LCD::LCD () +{ + +} + +// PUBLIC METHODS +// --------------------------------------------------------------------------- +// When the display powers up, it is configured as follows: +// +// 1. Display clear +// 2. Function set: +// DL = 1; 8-bit interface data +// N = 0; 1-line display +// F = 0; 5x8 dot character font +// 3. Display on/off control: +// D = 0; Display off +// C = 0; Cursor off +// B = 0; Blinking off +// 4. Entry mode set: +// I/D = 1; Increment by 1 +// S = 0; No shift +// +// Note, however, that resetting the Arduino doesn't reset the LCD, so we +// can't assume that its in that state when a sketch starts (and the +// LiquidCrystal constructor is called). +// A call to begin() will reinitialize the LCD. +// +void LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) +{ + if (lines > 1) + { + _displayfunction |= LCD_2LINE; + } + _numlines = lines; + _cols = cols; + + // for some 1 line displays you can select a 10 pixel high font + // ------------------------------------------------------------ + if ((dotsize != LCD_5x8DOTS) && (lines == 1)) + { + _displayfunction |= LCD_5x10DOTS; + } + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way before 4.5V so we'll wait + // 50 + // --------------------------------------------------------------------------- + delay (100); // 100ms delay + + //put the LCD into 4 bit or 8 bit mode + // ------------------------------------- + if (! (_displayfunction & LCD_8BITMODE)) + { + // this is according to the hitachi HD44780 datasheet + // figure 24, pg 46 + + // we start in 8bit mode, try to set 4 bit mode + send(0x03, FOUR_BITS); + delayMicroseconds(4500); // wait min 4.1ms + + // second try + send ( 0x03, FOUR_BITS ); + delayMicroseconds(4500); // wait min 4.1ms + + // third go! + send( 0x03, FOUR_BITS ); + delayMicroseconds(150); + + // finally, set to 4-bit interface + send ( 0x02, FOUR_BITS ); + } + else + { + // this is according to the hitachi HD44780 datasheet + // page 45 figure 23 + + // Send function set command sequence + command(LCD_FUNCTIONSET | _displayfunction); + delayMicroseconds(4500); // wait more than 4.1ms + + // second try + command(LCD_FUNCTIONSET | _displayfunction); + delayMicroseconds(150); + + // third go + command(LCD_FUNCTIONSET | _displayfunction); + } + + // finally, set # lines, font size, etc. + command(LCD_FUNCTIONSET | _displayfunction); + + // turn the display on with no cursor or blinking default + _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; + display(); + + // clear the LCD + clear(); + + // Initialize to default text direction (for romance languages) + _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; + // set the entry mode + command(LCD_ENTRYMODESET | _displaymode); + + backlight(); + +} + +// Common LCD Commands +// --------------------------------------------------------------------------- +void LCD::clear() +{ + command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero + delayMicroseconds(HOME_CLEAR_EXEC); // this command is time consuming +} + +void LCD::home() +{ + command(LCD_RETURNHOME); // set cursor position to zero + delayMicroseconds(HOME_CLEAR_EXEC); // This command is time consuming +} + +void LCD::setCursor(uint8_t col, uint8_t row) +{ + const byte row_offsetsDef[] = { 0x00, 0x40, 0x14, 0x54 }; // For regular LCDs + const byte row_offsetsLarge[] = { 0x00, 0x40, 0x10, 0x50 }; // For 16x4 LCDs + + if ( row >= _numlines ) + { + row = _numlines-1; // rows start at 0 + } + + // 16x4 LCDs have special memory map layout + // ---------------------------------------- + if ( _cols == 16 && _numlines == 4 ) + { + command(LCD_SETDDRAMADDR | (col + row_offsetsLarge[row])); + } + else + { + command(LCD_SETDDRAMADDR | (col + row_offsetsDef[row])); + } + +} + +// Turn the display on/off +void LCD::noDisplay() +{ + _displaycontrol &= ~LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void LCD::display() +{ + _displaycontrol |= LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turns the underline cursor on/off +void LCD::noCursor() +{ + _displaycontrol &= ~LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} +void LCD::cursor() +{ + _displaycontrol |= LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turns on/off the blinking cursor +void LCD::noBlink() +{ + _displaycontrol &= ~LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void LCD::blink() +{ + _displaycontrol |= LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// These commands scroll the display without changing the RAM +void LCD::scrollDisplayLeft(void) +{ + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +} + +void LCD::scrollDisplayRight(void) +{ + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); +} + +// This is for text that flows Left to Right +void LCD::leftToRight(void) +{ + _displaymode |= LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This is for text that flows Right to Left +void LCD::rightToLeft(void) +{ + _displaymode &= ~LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This method moves the cursor one space to the right +void LCD::moveCursorRight(void) +{ + command(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVERIGHT); +} + +// This method moves the cursor one space to the left +void LCD::moveCursorLeft(void) +{ + command(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVELEFT); +} + + +// This will 'right justify' text from the cursor +void LCD::autoscroll(void) +{ + _displaymode |= LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'left justify' text from the cursor +void LCD::noAutoscroll(void) +{ + _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// Write to CGRAM of new characters +void LCD::createChar(uint8_t location, uint8_t charmap[]) +{ + location &= 0x7; // we only have 8 locations 0-7 + + command(LCD_SETCGRAMADDR | (location << 3)); + delayMicroseconds(30); + + for (int i=0; i<8; i++) + { + write(charmap[i]); // call the virtual write method + delayMicroseconds(40); + } +} + +// +// Switch on the backlight +void LCD::backlight ( void ) +{ + setBacklight(255); +} + +// +// Switch off the backlight +void LCD::noBacklight ( void ) +{ + setBacklight(0); +} + +// +// Switch fully on the LCD (backlight and LCD) +void LCD::on ( void ) +{ + display(); + backlight(); +} + +// +// Switch fully off the LCD (backlight and LCD) +void LCD::off ( void ) +{ + noBacklight(); + noDisplay(); +} + +// General LCD commands - generic methods used by the rest of the commands +// --------------------------------------------------------------------------- +void LCD::command(uint8_t value) +{ + send(value, COMMAND); +} + +#if (ARDUINO < 100) +void LCD::write(uint8_t value) +{ + send(value, DATA); +} +#else +size_t LCD::write(uint8_t value) +{ + send(value, DATA); + return 1; // assume OK +} +#endif diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LCD.h b/libraries/Visuino_LiquidCrystal/Visuino_LCD.h new file mode 100644 index 0000000..88a58ad --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LCD.h @@ -0,0 +1,536 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LCD.h +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK. +// +// @brief +// This is a basic implementation of the LiquidCrystal library of the +// Arduino SDK. This library is a refactored version of the one supplied +// in the Arduino SDK in such a way that it simplifies its extension +// to support other mechanism to communicate to LCDs such as I2C, Serial, SR, +// The original library has been reworked in such a way that this will be +// the base class implementing all generic methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets. +// +// This base class is a pure abstract class and needs to be extended. As reference, +// it has been extended to drive 4 and 8 bit mode control, LCDs and I2C extension +// backpacks such as the I2CLCDextraIO using the PCF8574* I2C IO Expander ASIC. +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library. +// +// @version API 1.1.0 +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#ifndef _LCD_H_ +#define _LCD_H_ + +#if (ARDUINO < 100) +#include +#else +#include +#endif + +#include +#include + + +/*! + @defined + @abstract Enables disables fast waits for write operations for LCD + @discussion If defined, the library will avoid doing un-necessary waits. + this can be done, because the time taken by Arduino's slow digitalWrite + operations. If fast digitalIO operations, comment this line out or undefine + the mode. + */ +#ifdef __AVR__ +#define FAST_MODE +#endif + +/*! + @function + @abstract waits for a given time in microseconds (compilation dependent). + @discussion Waits for a given time defined in microseconds depending on + the FAST_MODE define. If the FAST_MODE is defined the call will return + inmediatelly. + @param uSec[in] time in microseconds. + @result None + */ +inline static void waitUsec ( uint16_t uSec ) +{ +#ifndef FAST_MODE + delayMicroseconds ( uSec ); +#endif // FAST_MODE +} + + +/*! + @defined + @abstract All these definitions shouldn't be used unless you are writing + a driver. + @discussion All these definitions are for driver implementation only and + shouldn't be used by applications. + */ +// LCD Commands +// --------------------------------------------------------------------------- +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +// --------------------------------------------------------------------------- +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off and cursor control +// --------------------------------------------------------------------------- +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +// --------------------------------------------------------------------------- +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +// --------------------------------------------------------------------------- +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + + +// Define COMMAND and DATA LCD Rs (used by send method). +// --------------------------------------------------------------------------- +#define COMMAND 0 +#define DATA 1 +#define FOUR_BITS 2 + + +/*! + @defined + @abstract Defines the duration of the home and clear commands + @discussion This constant defines the time it takes for the home and clear + commands in the LCD - Time in microseconds. + */ +#define HOME_CLEAR_EXEC 2000 + +/*! + @defined + @abstract Backlight off constant declaration + @discussion Used in combination with the setBacklight to swith off the + LCD backlight. @set setBacklight +*/ +#define BACKLIGHT_OFF 0 + +/*! + @defined + @abstract Backlight on constant declaration + @discussion Used in combination with the setBacklight to swith on the + LCD backlight. @set setBacklight + */ +#define BACKLIGHT_ON 255 + + +/*! + @typedef + @abstract Define backlight control polarity + @discussion Backlight control polarity. @see setBacklightPin. + */ +typedef enum { POSITIVE, NEGATIVE } t_backlighPol; + +class LCD : public Print +{ +public: + + /*! + @method + @abstract LiquidCrystal abstract constructor. + @discussion LiquidCrystal class abstract constructor needed to create + the base abstract class. + */ + LCD ( ); + + /*! + @function + @abstract LCD initialization. + @discussion Initializes the LCD to a given size (col, row). This methods + initializes the LCD, therefore, it MUST be called prior to using any other + method from this class. + + This method is abstract, a base implementation is available common to all LCD + drivers. Should it not be compatible with some other LCD driver, a derived + implementation should be done on the driver specif class. + + @param cols[in] the number of columns that the display has + @param rows[in] the number of rows that the display has + @param charsize[in] character size, default==LCD_5x8DOTS + */ + virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + + /*! + @function + @abstract Clears the LCD. + @discussion Clears the LCD screen and positions the cursor in the upper-left + corner. + + This operation is time consuming for the LCD. + + @param none + */ + void clear(); + + /*! + @function + @abstract Sets the cursor to the upper-left corner. + @discussion Positions the cursor in the upper-left of the LCD. + That is, use that location in outputting subsequent text to the display. + To also clear the display, use the clear() function instead. + + This operation is time consuming for the LCD. + + @param none + */ + void home(); + + /*! + @function + @abstract Turns off the LCD display. + @discussion Turns off the LCD display, without losing the text currently + being displayed on it. + + @param none + */ + void noDisplay(); + + /*! + @function + @abstract Turns on the LCD display. + @discussion Turns on the LCD display, after it's been turned off with + noDisplay(). This will restore the text (and cursor location) that was on + the display prior to calling noDisplay(). + + @param none + */ + void display(); + + /*! + @function + @abstract Turns off the blinking of the LCD cursor. + + @param none + */ + void noBlink(); + + /*! + @function + @abstract Display the cursor of the LCD. + @discussion Display the blinking LCD cursor. If used in combination with + the cursor() function, the result will depend on the particular display. + + @param none + */ + void blink(); + + /*! + @function + @abstract Hides the LCD cursor. + + @param none + */ + void noCursor(); + + /*! + @function + @abstract Display the LCD cursor. + @discussion Display the LCD cursor: an underscore (line) at the location + where the next character will be written. + + @param none + */ + void cursor(); + + /*! + @function + @abstract Scrolls the contents of the display (text and cursor) one space + to the left. + + @param none + */ + void scrollDisplayLeft(); + + /*! + @function + @abstract Scrolls the contents of the display (text and cursor) one space + to the right. + + @param none + */ + void scrollDisplayRight(); + + /*! + @function + @abstract Set the direction for text written to the LCD to left-to-right. + @discussion Set the direction for text written to the LCD to left-to-right. + All subsequent characters written to the display will go from left to right, + but does not affect previously-output text. + + This is the default configuration. + + @param none + */ + void leftToRight(); + + /*! + @function + @abstract Set the direction for text written to the LCD to right-to-left. + @discussion Set the direction for text written to the LCD to right-to-left. + All subsequent characters written to the display will go from right to left, + but does not affect previously-output text. + + left-to-right is the default configuration. + + @param none + */ + void rightToLeft(); + + /*! + @function + @abstract Moves the cursor one space to the left. + @discussion + @param none + */ + void moveCursorLeft(); + + + /*! + @function + @abstract Moves the cursor one space to the right. + + @param none + */ + void moveCursorRight(); + + /*! + @function + @abstract Turns on automatic scrolling of the LCD. + @discussion Turns on automatic scrolling of the LCD. This causes each + character output to the display to push previous characters over by one + space. If the current text direction is left-to-right (the default), + the display scrolls to the left; if the current direction is right-to-left, + the display scrolls to the right. + This has the effect of outputting each new character to the same location on + the LCD. + + @param none + */ + void autoscroll(); + + /*! + @function + @abstract Turns off automatic scrolling of the LCD. + @discussion Turns off automatic scrolling of the LCD, this is the default + configuration of the LCD. + + @param none + */ + void noAutoscroll(); + + /*! + @function + @abstract Creates a custom character for use on the LCD. + @discussion Create a custom character (glyph) for use on the LCD. + Most chipsets only support up to eight characters of 5x8 pixels. Therefore, + this methods has been limited to locations (numbered 0 to 7). + + The appearance of each custom character is specified by an array of eight + bytes, one for each row. The five least significant bits of each byte + determine the pixels in that row. To display a custom character on screen, + write()/print() its number, i.e. lcd.print (char(x)); // Where x is 0..7. + + @param location[in] LCD memory location of the character to create + (0 to 7) + @param charmap[in] the bitmap array representing each row of the character. + */ + void createChar(uint8_t location, uint8_t charmap[]); + + /*! + @function + @abstract Position the LCD cursor. + @discussion Sets the position of the LCD cursor. Set the location at which + subsequent text written to the LCD will be displayed. + + @param col[in] LCD column + @param row[in] LCD row - line. + */ + void setCursor(uint8_t col, uint8_t row); + + /*! + @function + @abstract Switch-on the LCD backlight. + @discussion Switch-on the LCD backlight. + The setBacklightPin has to be called before setting the backlight for + this method to work. @see setBacklightPin. + */ + void backlight ( void ); + + /*! + @function + @abstract Switch-off the LCD backlight. + @discussion Switch-off the LCD backlight. + The setBacklightPin has to be called before setting the backlight for + this method to work. @see setBacklightPin. + */ + void noBacklight ( void ); + + /*! + @function + @abstract Switch on the LCD module. + @discussion Switch on the LCD module, it will switch on the LCD controller + and the backlight. This method has the same effect of calling display and + backlight. @see display, @see backlight + */ + void on ( void ); + + /*! + @function + @abstract Switch off the LCD module. + @discussion Switch off the LCD module, it will switch off the LCD controller + and the backlight. This method has the same effect of calling noDisplay and + noBacklight. @see display, @see backlight + */ + void off ( void ); + + // + // virtual class methods + // -------------------------------------------------------------------------- + /*! + @function + @abstract Sets the pin to control the backlight. + @discussion Sets the pin in the device to control the backlight. + This method is device dependent and can be programmed on each subclass. An + empty function call is provided that does nothing. + + @param value: pin associated to backlight control. + @param pol: backlight polarity control (POSITIVE, NEGATIVE) + */ + virtual void setBacklightPin ( uint8_t value, t_backlighPol pol ) { }; + + /*! + @function + @abstract Sets the pin to control the backlight. + @discussion Sets the pin in the device to control the backlight. The behaviour + of this method is very dependent on the device. Some controllers support + dimming some don't. Please read the actual header file for each individual + device. The setBacklightPin method has to be called before setting the backlight + or the adequate backlight control constructor. + @see setBacklightPin. + + NOTE: The prefered methods to control the backlight are "backlight" and + "noBacklight". + + @param 0..255 - the value is very dependent on the LCD. However, + BACKLIGHT_OFF will be interpreted as off and BACKLIGHT_ON will drive the + backlight on. + */ + virtual void setBacklight ( uint8_t value ) { }; + + /*! + @function + @abstract Writes to the LCD. + @discussion This method writes character to the LCD in the current cursor + position. + + This is the virtual write method, implemented in the Print class, therefore + all Print class methods will end up calling this method. + + @param value[in] Value to write to the LCD. + */ +#if (ARDUINO < 100) + virtual void write(uint8_t value); +#else + virtual size_t write(uint8_t value); +#endif + +#if (ARDUINO < 100) + using Print::write; +#else + using Print::write; +#endif + +protected: + // Internal LCD variables to control the LCD shared between all derived + // classes. + uint8_t _displayfunction; // LCD_5x10DOTS or LCD_5x8DOTS, LCD_4BITMODE or + // LCD_8BITMODE, LCD_1LINE or LCD_2LINE + uint8_t _displaycontrol; // LCD base control command LCD on/off, blink, cursor + // all commands are "ored" to its contents. + uint8_t _displaymode; // Text entry mode to the LCD + uint8_t _numlines; // Number of lines of the LCD, initialized with begin() + uint8_t _cols; // Number of columns in the LCD + t_backlighPol _polarity; // Backlight polarity + +private: + /*! + @function + @abstract Send a command to the LCD. + @discussion This method sends a command to the LCD by setting the Register + select line of the LCD. + + This command shouldn't be used to drive the LCD, only to implement any other + feature that is not available on this library. + + @param value[in] Command value to send to the LCD (COMMAND, DATA or + FOUR_BITS). + */ + void command(uint8_t value); + + /*! + @function + @abstract Send a particular value to the LCD. + @discussion Sends a particular value to the LCD. This is a pure abstract + method, therefore, it is implementation dependent of each derived class how + to physically write to the LCD. + + Users should never call this method. + + @param value[in] Value to send to the LCD. + @result mode LOW - write to the LCD CGRAM, HIGH - write a command to + the LCD. + */ +#if (ARDUINO < 100) + virtual void send(uint8_t value, uint8_t mode) { }; +#else + virtual void send(uint8_t value, uint8_t mode) = 0; +#endif + +}; + +#endif diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.cpp b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.cpp new file mode 100644 index 0000000..b5dac07 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.cpp @@ -0,0 +1,299 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal.cpp +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK. +// +// @brief +// This is a basic implementation of the LiquidCrystal library of the +// Arduino SDK. The original library has been reworked in such a way that +// this class implements the all methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets using the parallel port of +// the LCD (4 bit and 8 bit). +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library. +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#include +#include +#include + +#if (ARDUINO < 100) +#include +#else +#include +#endif +#include "Visuino_LiquidCrystal.h" + +// CONSTANT definitions +// --------------------------------------------------------------------------- +#define LCD_NOBACKLIGHT 0xFF + +// LCD driver configuration (4bit or 8bit driver control) +#define LCD_4BIT 1 +#define LCD_8BIT 0 + +// STATIC helper functions +// --------------------------------------------------------------------------- + + +// CONSTRUCTORS +// --------------------------------------------------------------------------- + +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) +{ + init(LCD_8BIT, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7); +} + +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) +{ + init(LCD_8BIT, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); +} + +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) +{ + init(LCD_4BIT, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0); +} + +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) +{ + init(LCD_4BIT, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); +} + +// Contructors with backlight control +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t backlightPin, t_backlighPol pol) +{ + init(LCD_8BIT, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7); + setBacklightPin ( backlightPin, pol ); +} + +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t backlightPin, t_backlighPol pol) +{ + init(LCD_8BIT, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); + setBacklightPin ( backlightPin, pol ); +} + +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t backlightPin, t_backlighPol pol) +{ + init(LCD_4BIT, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0); + setBacklightPin ( backlightPin, pol ); +} + +LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t backlightPin, t_backlighPol pol) +{ + init(LCD_4BIT, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); + setBacklightPin ( backlightPin, pol ); +} + +// PUBLIC METHODS +// --------------------------------------------------------------------------- + +/************ low level data pushing commands **********/ +// +// send +void LiquidCrystal::send(uint8_t value, uint8_t mode) +{ + // Only interested in COMMAND or DATA + digitalWrite( _rs_pin, ( mode == DATA ) ); + + // if there is a RW pin indicated, set it low to Write + // --------------------------------------------------- + if (_rw_pin != 255) + { + digitalWrite(_rw_pin, LOW); + } + + if ( mode != FOUR_BITS ) + { + if ( (_displayfunction & LCD_8BITMODE ) ) + { + writeNbits(value, 8); + } + else + { + writeNbits ( value >> 4, 4 ); + writeNbits ( value, 4 ); + } + } + else + { + writeNbits ( value, 4 ); + } + waitUsec ( EXEC_TIME ); // wait for the command to execute by the LCD +} + +// +// setBacklightPin +void LiquidCrystal::setBacklightPin ( uint8_t pin, t_backlighPol pol ) +{ + pinMode ( pin, OUTPUT ); // Difine the backlight pin as output + _backlightPin = pin; + _polarity = pol; + setBacklight(BACKLIGHT_OFF); // Set the backlight low by default +} + +// +// setBackligh +void LiquidCrystal::setBacklight ( uint8_t value ) +{ + // Check if there is a pin assigned to the backlight + // --------------------------------------------------- + if ( _backlightPin != LCD_NOBACKLIGHT ) + { + // Check if the pin is associated to a timer, i.e. PWM + // --------------------------------------------------- + if(digitalPinToTimer(_backlightPin) != NOT_ON_TIMER) + { + // Check for control polarity inversion + // --------------------------------------------------- + if ( _polarity == POSITIVE ) + { + analogWrite ( _backlightPin, value ); + } + else + { + analogWrite ( _backlightPin, 255 - value ); + } + } + // Not a PWM pin, set the backlight pin for POSI or NEG + // polarity + // -------------------------------------------------------- + else if (((value > 0) && (_polarity == POSITIVE)) || + ((value == 0) && (_polarity == NEGATIVE))) + { + digitalWrite( _backlightPin, HIGH); + } + else + { + digitalWrite( _backlightPin, LOW); + } + } +} + +// PRIVATE METHODS +// --------------------------------------------------------------------------- + + +// init +void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) +{ + uint8_t i; + + // Initialize the IO pins + // ----------------------- + + _rs_pin = rs; + _rw_pin = rw; + _enable_pin = enable; + + _data_pins[0] = d0; + _data_pins[1] = d1; + _data_pins[2] = d2; + _data_pins[3] = d3; + _data_pins[4] = d4; + _data_pins[5] = d5; + _data_pins[6] = d6; + _data_pins[7] = d7; + + // Initialize the IO port direction to OUTPUT + // ------------------------------------------ + + for ( i = 0; i < 4; i++ ) + { + pinMode ( _data_pins[i], OUTPUT ); + } + + // Initialize the rest of the ports if it is an 8bit controlled LCD + // ---------------------------------------------------------------- + + if ( !fourbitmode ) + { + for ( i = 4; i < 8; i++ ) + { + pinMode ( _data_pins[i], OUTPUT ); + } + } + pinMode(_rs_pin, OUTPUT); + + // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin# + if (_rw_pin != 255) + { + pinMode(_rw_pin, OUTPUT); + } + + pinMode(_enable_pin, OUTPUT); + + // Initialise displaymode functions to defaults: LCD_1LINE and LCD_5x8DOTS + // ------------------------------------------------------------------------- + if (fourbitmode) + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + else + _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; + + // Now we pull both RS and R/W low to begin commands + digitalWrite(_rs_pin, LOW); + digitalWrite(_enable_pin, LOW); + + if (_rw_pin != 255) + { + digitalWrite(_rw_pin, LOW); + } + + // Initialise the backlight pin no nothing + _backlightPin = LCD_NOBACKLIGHT; + _polarity = POSITIVE; +} + +// +// pulseEnable +void LiquidCrystal::pulseEnable(void) +{ + // There is no need for the delays, since the digitalWrite operation + // takes longer. + digitalWrite(_enable_pin, HIGH); + waitUsec(1); // enable pulse must be > 450ns + digitalWrite(_enable_pin, LOW); +} + +// +// write4bits +void LiquidCrystal::writeNbits(uint8_t value, uint8_t numBits) +{ + for (uint8_t i = 0; i < numBits; i++) + { + digitalWrite(_data_pins[i], (value >> i) & 0x01); + } + pulseEnable(); +} + + diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.h b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.h new file mode 100644 index 0000000..66e6332 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal.h @@ -0,0 +1,161 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal.h +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK. +// +// @brief +// This is a basic implementation of the LiquidCrystal library of the +// Arduino SDK. The original library has been reworked in such a way that +// this class implements the all methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets using the parallel port of +// the LCD (4 bit and 8 bit). +// +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#ifndef LiquidCrystal_4bit_h +#define LiquidCrystal_4bit_h + +#include + +#include "Visuino_LCD.h" +#include "Visuino_FastIO.h" + + +/*! + @defined + @abstract Command execution time on the LCD. + @discussion This defines how long a command takes to execute by the LCD. + The time is expressed in micro-seconds. + */ +#define EXEC_TIME 37 + +class LiquidCrystal : public LCD +{ +public: + /*! + @method + @abstract 8 bit LCD constructors. + @discussion Defines the pin assignment that the LCD will have. + The constructor does not initialize the LCD. + */ + LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); + LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); + + // Constructors with backlight control + LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t backlightPin, t_backlighPol pol); + LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t backlightPin, t_backlighPol pol); + /*! + @method + @abstract 4 bit LCD constructors. + @discussion Defines the pin assignment that the LCD will have. + The constructor does not initialize the LCD. + */ + LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); + LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); + + // Constructors with backlight control + LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t backlightPin, t_backlighPol pol); + LiquidCrystal(uint8_t rs, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t backlightPin, t_backlighPol pol); + /*! + @function + @abstract Send a particular value to the LCD. + @discussion Sends a particular value to the LCD for writing to the LCD or + as an LCD command. + + Users should never call this method. + + @param value Value to send to the LCD. + @result mode LOW - write to the LCD CGRAM, HIGH - write a command to + the LCD. + */ + virtual void send(uint8_t value, uint8_t mode); + + /*! + @function + @abstract Sets the pin to control the backlight. + @discussion Sets the pin in the device to control the backlight. + + @param pin: pin assigned to the backlight + @param pol: backlight pin control polarity (POSITIVE, NEGATIVE). + */ + void setBacklightPin ( uint8_t pin, t_backlighPol pol ); + + /*! + @function + @abstract Switch-on/off the LCD backlight. + @discussion Switch-on/off the LCD backlight. + The setBacklightPin has to be called before setting the backlight for + this method to work. @see setBacklightPin. For dimming control of the + backlight, the configuration pin must be a PWM output pin. Dim control + is achieved by passing a value from 1 to 255 as a parameter. If the + pin configured when calling the setBacklightPin does not support PWM, + then: (0) backlight off, (1..255) backlight on. + + @param value: backlight value. 0: off, 1..255: dim control of the + backlight. For negative logic 255: off, 254..0: dim control. + */ + void setBacklight ( uint8_t value ); + +private: + + /*! + @method + @abstract Initializes the LCD pin allocation and associated HW + @discussion Initializes the LCD pin allocation and configuration. + */ + void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); + + /*! + @method + @abstract Writes numBits bits from value value to the LCD. + @discussion Writes numBists bits (the least significant) to the LCD control + data lines. + */ + void writeNbits(uint8_t value, uint8_t numBits); + + /*! + @method + @abstract Pulse the LCD enable line (En). + @discussion Sends a pulse of 1 uS to the Enable pin to execute an command + or write operation. + */ + void pulseEnable(); + + uint8_t _rs_pin; // LOW: command. HIGH: character. + uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD. + uint8_t _enable_pin; // activated by a HIGH pulse. + uint8_t _data_pins[8]; // Data pins. + uint8_t _backlightPin; // Pin associated to control the LCD backlight +}; + +#endif diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.cpp b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.cpp new file mode 100644 index 0000000..2be11fe --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.cpp @@ -0,0 +1,291 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal_I2C.c +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK but using an I2C IO extension board. +// +// @brief +// This is a basic implementation of the LiquidCrystal library of the +// Arduino SDK. The original library has been reworked in such a way that +// this class implements the all methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets using I2C extension +// backpacks such as the I2CLCDextraIO with the PCF8574* I2C IO Expander ASIC. +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library. +// +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#if (ARDUINO < 100) +#include +#else +#include +#endif +#include +#include "Visuino_I2CIO.h" +#include "Visuino_LiquidCrystal_I2C.h" + +// CONSTANT definitions +// --------------------------------------------------------------------------- + +// flags for backlight control +/*! + @defined + @abstract LCD_NOBACKLIGHT + @discussion NO BACKLIGHT MASK + */ +#define LCD_NOBACKLIGHT 0x00 + +/*! + @defined + @abstract LCD_BACKLIGHT + @discussion BACKLIGHT MASK used when backlight is on + */ +#define LCD_BACKLIGHT 0xFF + + +// Default library configuration parameters used by class constructor with +// only the I2C address field. +// --------------------------------------------------------------------------- +/*! + @defined + @abstract Enable bit of the LCD + @discussion Defines the IO of the expander connected to the LCD Enable + */ +#define EN 6 // Enable bit + +/*! + @defined + @abstract Read/Write bit of the LCD + @discussion Defines the IO of the expander connected to the LCD Rw pin + */ +#define RW 5 // Read/Write bit + +/*! + @defined + @abstract Register bit of the LCD + @discussion Defines the IO of the expander connected to the LCD Register select pin + */ +#define RS 4 // Register select bit + +/*! + @defined + @abstract LCD dataline allocation this library only supports 4 bit LCD control + mode. + @discussion D4, D5, D6, D7 LCD data lines pin mapping of the extender module + */ +#define D4 0 +#define D5 1 +#define D6 2 +#define D7 3 + + +// CONSTRUCTORS +// --------------------------------------------------------------------------- +LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr ) +{ + config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7); +} + + +LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t backlighPin, + t_backlighPol pol = POSITIVE) +{ + config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7); + setBacklightPin(backlighPin, pol); +} + +LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, + uint8_t Rs) +{ + config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7); +} + +LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, + uint8_t Rs, uint8_t backlighPin, + t_backlighPol pol = POSITIVE) +{ + config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7); + setBacklightPin(backlighPin, pol); +} + +LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, + uint8_t Rs, uint8_t d4, uint8_t d5, + uint8_t d6, uint8_t d7 ) +{ + config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7); +} + +LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, + uint8_t Rs, uint8_t d4, uint8_t d5, + uint8_t d6, uint8_t d7, uint8_t backlighPin, + t_backlighPol pol = POSITIVE ) +{ + config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7); + setBacklightPin(backlighPin, pol); +} + +// PUBLIC METHODS +// --------------------------------------------------------------------------- + +// +// begin +void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) +{ + + init(); // Initialise the I2C expander interface + LCD::begin ( cols, lines, dotsize ); +} + + +// User commands - users can expand this section +//---------------------------------------------------------------------------- +// Turn the (optional) backlight off/on + +// +// setBacklightPin +void LiquidCrystal_I2C::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE ) +{ + _backlightPinMask = ( 1 << value ); + _polarity = pol; + setBacklight(BACKLIGHT_OFF); +} + +// +// setBacklight +void LiquidCrystal_I2C::setBacklight( uint8_t value ) +{ + // Check if backlight is available + // ---------------------------------------------------- + if ( _backlightPinMask != 0x0 ) + { + // Check for polarity to configure mask accordingly + // ---------------------------------------------------------- + if (((_polarity == POSITIVE) && (value > 0)) || + ((_polarity == NEGATIVE ) && ( value == 0 ))) + { + _backlightStsMask = _backlightPinMask & LCD_BACKLIGHT; + } + else + { + _backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT; + } + _i2cio.write( _backlightStsMask ); + } +} + + +// PRIVATE METHODS +// --------------------------------------------------------------------------- + +// +// init +int LiquidCrystal_I2C::init() +{ + int status = 0; + + // initialize the backpack IO expander + // and display functions. + // ------------------------------------------------------------------------ + if ( _i2cio.begin ( _Addr ) == 1 ) + { + _i2cio.portMode ( OUTPUT ); // Set the entire IO extender to OUTPUT + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + status = 1; + _i2cio.write(0); // Set the entire port to LOW + } + return ( status ); +} + +// +// config +void LiquidCrystal_I2C::config (uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 ) +{ + _Addr = lcd_Addr; + + _backlightPinMask = 0; + _backlightStsMask = LCD_NOBACKLIGHT; + _polarity = POSITIVE; + + _En = ( 1 << En ); + _Rw = ( 1 << Rw ); + _Rs = ( 1 << Rs ); + + // Initialise pin mapping + _data_pins[0] = ( 1 << d4 ); + _data_pins[1] = ( 1 << d5 ); + _data_pins[2] = ( 1 << d6 ); + _data_pins[3] = ( 1 << d7 ); +} + + + +// low level data pushing commands +//---------------------------------------------------------------------------- + +// +// send - write either command or data +void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) +{ + // No need to use the delay routines since the time taken to write takes + // longer that what is needed both for toggling and enable pin an to execute + // the command. + + if ( mode == FOUR_BITS ) + { + write4bits( (value & 0x0F), COMMAND ); + } + else + { + write4bits( (value >> 4), mode ); + write4bits( (value & 0x0F), mode); + } +} + +// +// write4bits +void LiquidCrystal_I2C::write4bits ( uint8_t value, uint8_t mode ) +{ + uint8_t pinMapValue = 0; + + // Map the value to LCD pin mapping + // -------------------------------- + for ( uint8_t i = 0; i < 4; i++ ) + { + if ( ( value & 0x1 ) == 1 ) + { + pinMapValue |= _data_pins[i]; + } + value = ( value >> 1 ); + } + + // Is it a command or data + // ----------------------- + if ( mode == DATA ) + { + mode = _Rs; + } + + pinMapValue |= mode | _backlightStsMask; + pulseEnable ( pinMapValue ); +} + +// +// pulseEnable +void LiquidCrystal_I2C::pulseEnable (uint8_t data) +{ + _i2cio.write (data | _En); // En HIGH + _i2cio.write (data & ~_En); // En LOW +} \ No newline at end of file diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.h b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.h new file mode 100644 index 0000000..eec4cfa --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_I2C.h @@ -0,0 +1,204 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal_I2C.h +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK but using an I2C IO extension board. +// +// @brief +// This is a basic implementation of the LiquidCrystal library of the +// Arduino SDK. The original library has been reworked in such a way that +// this class implements the all methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets using I2C extension +// backpacks such as the I2CLCDextraIO with the PCF8574* I2C IO Expander ASIC. +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library. +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#ifndef LiquidCrystal_I2C_h +#define LiquidCrystal_I2C_h +#include +#include + +#include "Visuino_I2CIO.h" +#include "Visuino_LCD.h" + + +class LiquidCrystal_I2C : public LCD +{ +public: + + /*! + @method + @abstract Class constructor. + @discussion Initializes class variables and defines the I2C address of the + LCD. The constructor does not initialize the LCD. + + @param lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO, + the address can be configured using the on board jumpers. + */ + LiquidCrystal_I2C (uint8_t lcd_Addr); + // Constructor with backlight control + LiquidCrystal_I2C (uint8_t lcd_Addr, uint8_t backlighPin, t_backlighPol pol); + + /*! + @method + @abstract Class constructor. + @discussion Initializes class variables and defines the I2C address of the + LCD. The constructor does not initialize the LCD. + + @param lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO, + the address can be configured using the on board jumpers. + @param En[in] LCD En (Enable) pin connected to the IO extender module + @param Rw[in] LCD Rw (Read/write) pin connected to the IO extender module + @param Rs[in] LCD Rs (Reset) pin connected to the IO extender module + */ + LiquidCrystal_I2C( uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs); + // Constructor with backlight control + LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t backlighPin, t_backlighPol pol); + + /*! + @method + @abstract Class constructor. + @discussion Initializes class variables and defines the I2C address of the + LCD. The constructor does not initialize the LCD. + + @param lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO, + the address can be configured using the on board jumpers. + @param En[in] LCD En (Enable) pin connected to the IO extender module + @param Rw[in] LCD Rw (Read/write) pin connected to the IO extender module + @param Rs[in] LCD Rs (Reset) pin connected to the IO extender module + @param d4[in] LCD data 0 pin map on IO extender module + @param d5[in] LCD data 1 pin map on IO extender module + @param d6[in] LCD data 2 pin map on IO extender module + @param d7[in] LCD data 3 pin map on IO extender module + */ + LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 ); + // Constructor with backlight control + LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t backlighPin, t_backlighPol pol); + /*! + @function + @abstract LCD initialization and associated HW. + @discussion Initializes the LCD to a given size (col, row). This methods + initializes the LCD, therefore, it MUST be called prior to using any other + method from this class or parent class. + + The begin method can be overloaded if necessary to initialize any HW that + is implemented by a library and can't be done during construction, here + we use the Wire class. + + @param cols[in] the number of columns that the display has + @param rows[in] the number of rows that the display has + @param charsize[in] size of the characters of the LCD: LCD_5x8DOTS or + LCD_5x10DOTS. + */ + virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + + /*! + @function + @abstract Send a particular value to the LCD. + @discussion Sends a particular value to the LCD for writing to the LCD or + as an LCD command. + + Users should never call this method. + + @param value[in] Value to send to the LCD. + @param mode[in] DATA - write to the LCD CGRAM, COMMAND - write a + command to the LCD. + */ + virtual void send(uint8_t value, uint8_t mode); + + /*! + @function + @abstract Sets the pin to control the backlight. + @discussion Sets the pin in the device to control the backlight. This device + doesn't support dimming backlight capability. + + @param 0: backlight off, 1..255: backlight on. + */ + void setBacklightPin ( uint8_t value, t_backlighPol pol ); + + /*! + @function + @abstract Switch-on/off the LCD backlight. + @discussion Switch-on/off the LCD backlight. + The setBacklightPin has to be called before setting the backlight for + this method to work. @see setBacklightPin. + + @param value: backlight mode (HIGH|LOW) + */ + void setBacklight ( uint8_t value ); + +private: + + /*! + @method + @abstract Initializes the LCD class + @discussion Initializes the LCD class and IO expansion module. + */ + int init(); + + /*! + @function + @abstract Initialises class private variables + @discussion This is the class single point for initialising private variables. + + @param lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO, + the address can be configured using the on board jumpers. + @param En[in] LCD En (Enable) pin connected to the IO extender module + @param Rw[in] LCD Rw (Read/write) pin connected to the IO extender module + @param Rs[in] LCD Rs (Reset) pin connected to the IO extender module + @param d4[in] LCD data 0 pin map on IO extender module + @param d5[in] LCD data 1 pin map on IO extender module + @param d6[in] LCD data 2 pin map on IO extender module + @param d7[in] LCD data 3 pin map on IO extender module + */ + void config (uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 ); + + /*! + @method + @abstract Writes an 4 bit value to the LCD. + @discussion Writes 4 bits (the least significant) to the LCD control data lines. + @param value[in] Value to write to the LCD + @param more[in] Value to distinguish between command and data. + COMMAND == command, DATA == data. + */ + void write4bits(uint8_t value, uint8_t mode); + + /*! + @method + @abstract Pulse the LCD enable line (En). + @discussion Sends a pulse of 1 uS to the Enable pin to execute an command + or write operation. + */ + void pulseEnable(uint8_t); + + + uint8_t _Addr; // I2C Address of the IO expander + uint8_t _backlightPinMask; // Backlight IO pin mask + uint8_t _backlightStsMask; // Backlight status mask + I2CIO _i2cio; // I2CIO PCF8574* expansion module driver I2CLCDextraIO + uint8_t _En; // LCD expander word for enable pin + uint8_t _Rw; // LCD expander word for R/W pin + uint8_t _Rs; // LCD expander word for Register Select pin + uint8_t _data_pins[4]; // LCD data lines + +}; + +#endif diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.cpp b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.cpp new file mode 100644 index 0000000..227a210 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.cpp @@ -0,0 +1,209 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal_SR.h +// Connects an LCD using 2 or 3 pins from the Arduino, via an 8-bit +// ShiftRegister (SR from now on). +// +// @brief +// This is a port of the ShiftRegLCD library from raron and ported to the +// LCD library. +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library and can +// be used as such. +// +// Modified to work serially with the shiftOut() function, an 8-bit +// unlatched, no-tristate, unidirectional SIPO (Serial-In-Parallel-Out) +// shift register (IE a very simple SR), and an LCD in 4-bit mode. +// Any such shift register should do (pref. 74LS family IC's for 2-wire). +// I used 74LS164, for the reason that's what I had at hand. +// +// Connection description: +// +// SR output: +// Bit #0 - N/C - not connected, used to hold a zero +// Bit #1 - N/C +// Bit #2 - connects to RS (Register Select) on the LCD +// Bits #3-6 - connects to LCD data inputs D4 - D7. +// Bit #7 - enables the LCD enable-puls (via the diode-resistor AND "gate") +// +// 2 or 3 Pins required from the Arduino for Data, Clock and (optional) Enable +// If not using Enable, the Data pin is used for the enable signal by defining +// the same pin for Enable as for Data. Data and Clock outputs/pins goes to +// the shiftregister. +// LCD RW-pin hardwired to LOW (only writing to LCD). +// Busy Flag (BF, data bit D7) is not read. +// +// Original project homepage: http://code.google.com/p/arduinoshiftreglcd/ +// +// +// History +// 2012.03.29 bperrybap - Added delays for faster fio shiftout (it got too fast) +// AVR needed delay. cmd/write delays are based on CPU speed so it works on pic32. +// Added code to support indicating two wire mode by using enable=data pin +// (documentation indicated this as working) +// Fixed incorrect use of 5x10 for default font - now matches original LQ library. +// can now eliminate enable pin in constructor for two wire mode. +// 2012.01.16 Florian Fida - faster digitalWrite/shiftOut +// 2011.10.29 fmalpartida - adaption of the library to the LCD class hierarchy. +// 2011.07.02 Fixed a minor flaw in setCursor function. No functional change, +// just a bit more memory efficient. +// Thanks to CapnBry (from google code and github) who noticed it. +// URL to his version of shiftregLCD: +// https://github.com/CapnBry/HeaterMeter/commit/c6beba1b46b092ab0b33bcbd0a30a201fd1f28c1 +// 2009.07.30 raron - minor corrections to the comments. +// Fixed timing to datasheet safe. Fixed keyword highlights. +// 2009.07.28 Mircho / raron - a new modification to the schematics, and a +// more streamlined interface +// 2009.07.27 Thanks to an excellent suggestion from mircho at the Arduino +// playgrond forum, the number of wires now required is only two! +// 2009.07.25 raron - Fixed comments. I really messed up the comments before +// posting this, so I had to fix it. +// Renamed a function, but no improvements or functional changes. +// 2009.07.23 Incorporated some proper initialization routines +// inspired (lets say copy-paste-tweaked) from LiquidCrystal +// library improvements from LadyAda. +// 2009.05.23 raron - first version, but based mostly (as in almost verbatim) +// on the "official" LiquidCrystal library. +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#include +#include +#include + +#if (ARDUINO < 100) +#include +#else +#include +#endif +#include "Visuino_LiquidCrystal_SR.h" + +#include "Visuino_FastIO.h" + + +// CONSTRUCTORS +// --------------------------------------------------------------------------- +// Assuming 1 line 8 pixel high font +LiquidCrystal_SR::LiquidCrystal_SR (uint8_t srdata, uint8_t srclock, + uint8_t enable ) +{ + init ( srdata, srclock, enable, 1, 0 ); +} + + +// PRIVATE METHODS +// --------------------------------------------------------------------------- + +// +// init +void LiquidCrystal_SR::init(uint8_t srdata, uint8_t srclock, uint8_t enable, + uint8_t lines, uint8_t font) +{ + // Initialise private variables + _two_wire = 0; + + _srDataRegister = fio_pinToOutputRegister(srdata); + _srDataBit = fio_pinToBit(srdata); + _srClockRegister = fio_pinToOutputRegister(srclock); + _srClockBit = fio_pinToBit(srclock); + + if ((enable == TWO_WIRE) || (enable == srdata)) + { + _two_wire = 1; + _srEnableRegister = _srDataRegister; + _srEnableBit = _srDataBit; + } + else + { + _srEnableRegister = fio_pinToOutputRegister(enable); + _srEnableBit = fio_pinToBit(enable); + } + + // Configure control pins as outputs + // ------------------------------------------------------------------------ + + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; +} + +// +// shiftIt +void LiquidCrystal_SR::shiftIt(uint8_t val) +{ + if (_two_wire) + { + // Clear to get Enable LOW + fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit); + } + fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit, val, MSBFIRST); + + // LCD ENABLE PULSE + // + // While this library is written with a shift register without an output + // latch in mind, it can work in 3-wire mode with a shiftregister with a + // latch. The shiftregister latch pin (STR, RCL or similar) is then + // connected to the LCD enable pin. The LCD is (very likely) slower + // to read the Enable pulse, and then reads the new contents of the SR. + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + fio_digitalWrite_HIGH(_srEnableRegister, _srEnableBit); + waitUsec (1); // enable pulse must be >450ns + fio_digitalWrite_SWITCHTO(_srEnableRegister, _srEnableBit, LOW); + } // end critical section +} + +// PUBLIC METHODS +// --------------------------------------------------------------------------- + + +/************ low level data pushing commands **********/ +// +// send +void LiquidCrystal_SR::send(uint8_t value, uint8_t mode) +{ + // Divide byte in two nibbles include the RS signal + // and format it for shiftregister output wiring to the LCD + // We are only interested in my COMMAND or DATA for myMode + uint8_t myMode = ( mode == DATA ) ? SR_RS_BIT : 0; // RS bit; LOW: command. HIGH: character. + + if ( mode != FOUR_BITS ) + { + shiftIt(myMode | SR_EN_BIT | ((value >> 1) & 0x78)); // upper nibble + } + + shiftIt(myMode | SR_EN_BIT | ((value << 3) & 0x78)); // lower nibble + /* + * Add some delay since this code is so fast it needs some added delay + * even on AVRs because the shiftout is shorter than the LCD command execution time. + */ +#if (F_CPU <= 16000000) + if(_two_wire) + delayMicroseconds ( 10 ); + else + delayMicroseconds ( 17 ); // 3 wire mode is faster so it must delay longer +#else + delayMicroseconds ( 37 ); // commands & data writes need > 37us to complete +#endif + +} + +// +// setBacklightPin +void LiquidCrystal_SR::setBacklightPin ( uint8_t pin, t_backlighPol pol ) +{ } + +// +// setBacklight +void LiquidCrystal_SR::setBacklight ( uint8_t mode ) +{ } + diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.h b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.h new file mode 100644 index 0000000..df31ea6 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR.h @@ -0,0 +1,176 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 20/08/11. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal_SR.h +// Connects an LCD using 2 or 3 pins from the Arduino, via an 8-bit +// ShiftRegister (SR from now on). +// +// @brief +// This is a port of the ShiftRegLCD library from raron and ported to the +// LCD library. +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library and can +// be used as such. +// +// Modified to work serially with the shiftOut() function, an 8-bit +// unlatched, no-tristate, unidirectional SIPO (Serial-In-Parallel-Out) +// shift register (IE a very simple SR), and an LCD in 4-bit mode. +// Any such shift register should do (pref. 74LS family IC's for 2-wire). +// I used 74LS164, for the reason that's what I had at hand. +// +// Connection description: +// +// SR output: +// Bit #0 - N/C - not connected, used to hold a zero +// Bit #1 - N/C +// Bit #2 - connects to RS (Register Select) on the LCD +// Bits #3-6 - connects to LCD data inputs D4 - D7. +// Bit #7 - enables the LCD enable-puls (via the diode-resistor AND "gate") +// +// 2 or 3 Pins required from the Arduino for Data, Clock and (optional) Enable +// If not using Enable, the Data pin will be used for the enable signal. +// 2 wire mode can be indicated by: +// - ommitting the enable pin in constructor +// - defining the same pin for Enable as for Data in constructor +// - by using the token TWO_WIRE for the enable pin. +// +// Data and Clock outputs/pins goes to the shiftregister. +// LCD RW-pin hardwired to LOW (only writing to LCD). +// Busy Flag (BF, data bit D7) is not read. +// +// Original project homepage: http://code.google.com/p/arduinoshiftreglcd/ +// +// +// History +// 2012.03.29 bperrybap - can now eliminate enable pin in constructor for two wire mode. +// 2011.10.29 fmalpartida - adaption of the library to the LCD class hierarchy. +// 2011.07.02 Fixed a minor flaw in setCursor function. No functional change, +// just a bit more memory efficient. +// Thanks to CapnBry (from google code and github) who noticed it. +// URL to his version of shiftregLCD: +// https://github.com/CapnBry/HeaterMeter/commit/c6beba1b46b092ab0b33bcbd0a30a201fd1f28c1 +// 2009.07.30 raron - minor corrections to the comments. +// Fixed timing to datasheet safe. Fixed keyword highlights. +// 2009.07.28 Mircho / raron - a new modification to the schematics, and a +// more streamlined interface +// 2009.07.27 Thanks to an excellent suggestion from mircho at the Arduiono +// playgrond forum, the number of wires now required is only two! +// 2009.07.25 raron - Fixed comments. I really messed up the comments before +// posting this, so I had to fix it. +// Renamed a function, but no improvements or functional changes. +// 2009.07.23 Incorporated some proper initialization routines +// inspired (lets say copy-paste-tweaked) from LiquidCrystal +// library improvements from LadyAda. +// 2009.05.23 raron - first version, but based mostly (as in almost verbatim) +// on the "official" LiquidCrystal library. +// +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#ifndef _LIQUIDCRYSTAL_SR_ +#define _LIQUIDCRYSTAL_SR_ + +#include +#include "Visuino_LCD.h" +#include "Visuino_FastIO.h" + + +// two-wire indicator constant +// --------------------------------------------------------------------------- +#define TWO_WIRE 204 +#define SR_RS_BIT 0x04 +#define SR_EN_BIT 0x80 + +class LiquidCrystal_SR : public LCD +{ +public: + /*! + @method + @abstract LCD SHIFT REGISTER constructors. + @discussion Defines the pin assignment that the LCD will have. + The constructor does not initialize the LCD. Assuming 1 line 8 pixel high + font. + + @param srdata[in] pin for shiftregister data line. + @param srclock[in] pin for shiftregister clock line. + @param enable[in] optional direct enable pin for the LCD + */ + LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock, uint8_t enable=TWO_WIRE ); + + /*! + @function + @abstract Send a particular value to the LCD. + @discussion Sends a particular value to the LCD for writing to the LCD or + as an LCD command using the shift register. + + Users should never call this method. + + @param value[in] Value to send to the LCD. + @result mode LOW - write to the LCD CGRAM, HIGH - write a command to + the LCD. + */ + virtual void send(uint8_t value, uint8_t mode); + + + /*! + @function + @abstract Sets the pin to control the backlight. + @discussion Sets the pin in the device to control the backlight. + @warning Currently not supported + + @param mode: backlight mode (HIGH|LOW) + @param pol: backlight polarity + */ + void setBacklightPin ( uint8_t pin, t_backlighPol pol ); + + /*! + @function + @abstract Switch-on/off the LCD backlight. + @discussion Switch-on/off the LCD backlight. + The setBacklightPin has to be called before setting the backlight for + this method to work. @see setBacklightPin. + + @param mode: backlight mode (HIGH|LOW) + */ + void setBacklight ( uint8_t mode ); + +private: + + /*! + @method + @abstract Initializes the LCD pin allocation + @discussion Initializes the LCD pin allocation and configuration. + */ + void init ( uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, + uint8_t font ); + + /*! + * @method + * @abstract takes care of shifting and the enable pulse + */ + void shiftIt (uint8_t val); + + uint8_t _enable_pin; // Enable Pin + uint8_t _two_wire; // two wire mode + + fio_register _srDataRegister; // Serial Data pin + fio_bit _srDataBit; + fio_register _srClockRegister; // Clock Pin + fio_bit _srClockBit; + fio_register _srEnableRegister; // Enable Pin + fio_bit _srEnableBit; + +}; + +#endif + diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.cpp b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.cpp new file mode 100644 index 0000000..c2f45e4 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.cpp @@ -0,0 +1,135 @@ +// --------------------------------------------------------------------------- +// Created/Adapted by Bill Perry 2012-03-16 +// Copyright 2012 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal_SR2W.cpp +// Connects a hd44780 LCD using 2 pins from the Arduino, via an 8-bit +// ShiftRegister (SR2W from now on). +// +// @brief +// This is a port of the ShiftRegLCD library from raron and ported to the +// LCD library. +// +// +// See the corresponding SR2W header file for full details. +// +// History +// 2012.03.29 bperrybap - Fixed incorrect use of 5x10 for default font +// (now matches original LQ library) +// Fixed typo in SR2W mask define names +// changed default backlight state to on +// 2012.03.16 bperrybap - created/modified from SR sources to create SR2W +// @author B. Perry - bperrybap@opensource.billsworld.billandterrie.com +// --------------------------------------------------------------------------- + +#include "Visuino_LiquidCrystal_SR2W.h" + +// CONSTRUCTORS +// --------------------------------------------------------------------------- +// Assuming 1 line 8 pixel high font +LiquidCrystal_SR2W::LiquidCrystal_SR2W (uint8_t srdata, uint8_t srclock, t_backlighPol blpol) +{ + init ( srdata, srclock, blpol, 1, 0 ); +} + + +// PRIVATE METHODS +// --------------------------------------------------------------------------- + +// +// init +void LiquidCrystal_SR2W::init(uint8_t srdata, uint8_t srclock, t_backlighPol blpol, uint8_t lines, uint8_t font) +{ + _srDataRegister = fio_pinToOutputRegister(srdata); + _srDataMask = fio_pinToBit(srdata); + _srClockRegister = fio_pinToOutputRegister(srclock); + _srClockMask = fio_pinToBit(srclock); + + _blPolarity = blpol; + + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + + backlight(); // set default backlight state to on +} + +// +// loadSR +void LiquidCrystal_SR2W::loadSR(uint8_t val) +{ + // Clear to keep Enable LOW while clocking in new bits + fio_shiftOut(_srDataRegister, _srDataMask, _srClockRegister, _srClockMask); + + + // clock out SR data byte + fio_shiftOut(_srDataRegister, _srDataMask, _srClockRegister, _srClockMask, val, MSBFIRST); + + + // strobe LCD enable which can now be toggled by the data line + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + fio_digitalWrite_HIGH(_srDataRegister, _srDataMask); + waitUsec (1); // enable pulse must be >450ns + fio_digitalWrite_SWITCHTO(_srDataRegister, _srDataMask, LOW); + } // end critical section +} + +// PUBLIC METHODS +// --------------------------------------------------------------------------- + + +/************ low level data pushing commands **********/ +// +// send +void LiquidCrystal_SR2W::send(uint8_t value, uint8_t mode) +{ + uint8_t myMode = ( mode == DATA ) ? SR2W_RS_MASK : 0; + + myMode = myMode | SR2W_EN_MASK | _blMask; + + if ( mode != FOUR_BITS ) + { + loadSR(myMode | ((value >> 1) & SR2W_DATA_MASK)); // upper nibble + } + + loadSR(myMode | ((value << 3) & SR2W_DATA_MASK)); // lower nibble + + /* + * Don't call waitUsec() + * do our own delay optmization since this code is so fast it needs some added delay + * even on slower AVRs. + */ +#if (F_CPU <= 16000000) + delayMicroseconds ( 10 ); // commands & data writes need > 37us to complete +#else + delayMicroseconds ( 37 ); // commands & data writes need > 37us to complete +#endif +} + +// +// setBacklight +void LiquidCrystal_SR2W::setBacklight ( uint8_t value ) +{ + // Check for polarity to configure mask accordingly + // ---------------------------------------------------------- + if ( ((_blPolarity == POSITIVE) && (value > 0)) || + ((_blPolarity == NEGATIVE ) && ( value == 0 )) ) + { + _blMask = SR2W_BL_MASK; + } + else + { + _blMask = 0; + } + + // send dummy data of blMask to set BL pin + // Note: loadSR() will strobe the data line trying to pulse EN + // but E will not strobe because the EN output bit is not set. + loadSR(_blMask); +} diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.h b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.h new file mode 100644 index 0000000..205c5fe --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR2W.h @@ -0,0 +1,202 @@ +// --------------------------------------------------------------------------- +// Created/Adapted by Bill Perry 2012-03-16 +// Copyright 2012 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// @file LiquidCrystal_SR2W.h +// Connects a hd44780 LCD using 2 pins from the Arduino, via an 8-bit +// ShiftRegister (SR2W from now on). +// +// @brief +// This is the 2 wire shift register interface class for the LCD library +// +// The functionality provided by this class and its base class is a superset of +// the original functionality of the Arduino LiquidCrystal library and can +// be used as such. +// See the LCD class for a full description of the API functions available. +// +// It works with a 8-bit unlatched, no-tristate, unidirectional SIPO (Serial-In-Parallel-Out) +// shift register (IE a very simple SR), and an hd44780 LCD in 4-bit mode. +// Any such shift register should do (pref. 74LS family IC's for 2-wire). +// 74LS164 and 74HC595 have been exstensively tested. +// +// +// 2 Pins required from the Arduino: +// - Data/Enable +// - Clock +// The Data pin is also used to control the enable signal +// LCD RW-pin hardwired to LOW (only writing to LCD). +// Busy Flag (BF, data bit D7) is not read. +// +// Original project homepage: http://code.google.com/p/arduinoshiftreglcd/ +// +// Shift register bits +// Bit #0 - (cannot be used on 74HC595) +// Bit #1 - optional backlight control +// Bit #2 - connects to RS (Register Select) on the LCD +// Bit #3 - connects to LCD data inputs D4 +// Bit #4 - connects to LCD data inputs D5 +// Bit #5 - connects to LCD data inputs D6 +// Bit #6 - connects to LCD data inputs D7 +// Bit #7 - enables the LCD enable-puls (via the diode-resistor AND "gate") +// +// Wiring for a 74LS164 +// --------------------- +// 1k/4.7k +// +--------[ Resistor ]--------+---(LCD Enable) +// | | +// | 74LS164 (VCC) | +// | +----u----+ | _V_ diode +// (data pin)---+---+--1-|A VCC|-14-+ | +// | | | | +// +--2-|B Q7|-13------+ +// 3-|Q0 Q6|-12--(LCD D7) +// (BL Circuit)--------4-|Q1 Q5|-11--(LCD D6) +// (LCD RS)------------5-|Q2 Q4|-10--(LCD D5) +// (LCD D4)------------6-|Q3 /MR|--9--(VCC) +// +-7-|GND CP|--8--(clock pin) +// | +---------+ +// | 0.1uf +// (gnd)-----||----(vcc) +// +// Wiring for a 74HC595 +// -------------------- +// NOTE: the 74HC595 is a latching shift register. In order to get it to operate +// in a "non latching" mode, RCLK and SCLK are tied together. The side effect of this +// is that the latched output is one clock behind behind the internal shift register bits. +// To compensate for this the wiring is offset by one bit position lower. +// For example, while the backlight is hooked to Q0 it is still using bit 1 of +// of the shift register because the outputs are 1 clock behind the real internal shift +// register. +// +// 74HC595 (VCC) +// +----u----+ | +-----------------------(BL circuit) +// (LCD RS)------------1-|Q1 VCC|-16-+ | +--------------------(data pin) +// (LCD D4)------------2-|Q2 Q0|-15----+ | 1k/4.7k +// (LCD D5)------------3-|Q3 SER|-14-------+---[ Resistor ]--+--(LCD Enable) +// (LCD D6)------------4-|Q4 /OE|-13--(gnd) | +// (LCD D7)------------5-|Q5 RCLK|-12-------+ | +// | | | | +// +------6-|Q6 SCLK|-11-------+--(clock pin) | +// | 7-|Q7 /MR|-10--(VCC) | +// | +-8-|GND Q6'|--9 | +// | | +---------+ diode _V_ +// | | 0.1uf | +// | (gnd)-----||----(vcc) | +// +-----------------------------------------------+ +// +// +// Backlight Control circuit +// ------------------------- +// Because the shift resiter is not latching the outputs, the backlight circuitry +// will "see" the output bits as they are shifted into the shift register which +// can cause the backlight to flicker rather than remain constantly on/off. +// The circuit below slows down the transitions to the transistor to remove +// the visible flicker. When the BL input is HIGH the LCD backlight will turn on. +// +// (value depends on LCD, 100ohm is usually safe) +// (LCD BL anode)---[ resistor ]---(vcc) +// +// (LCD BL cathode)-------------------------------+ +// | +// D +// | +// (BL input)----[ 4.7k Resistor ]----+-------G-|-< (2N7000 FET) +// | | +// (0.1uf) = S +// | | +// (gnd) (gnd) +// +// +// +// +// History +// 2012.03.16 bperrybap - creation/adaption from SR header to create SR2W header. +// Fixed typo in SR2W mask define names +// @author B. Perry - bperrybap@opensource.billsworld.billandterrie.com +// -------------------------------------------------------------------------------- +#ifndef _LIQUIDCRYSTAL_SR2W_ +#define _LIQUIDCRYSTAL_SR2W_ + +#include +#include "Visuino_LCD.h" +#include "Visuino_FastIO.h" + + +// two-wire SR output bit constants +// --------------------------------------------------------------------------- + +#define SR2W_BL_MASK 0x02 +#define SR2W_RS_MASK 0x04 +#define SR2W_DATA_MASK 0x78 // data bits are hard coded to be SR bits 6,5,4,3 +#define SR2W_EN_MASK 0x80 // cannot ever be changed + +class LiquidCrystal_SR2W : public LCD +{ +public: + /*! + @method + @abstract LCD 2 wire SHIFT REGISTER constructor. + @discussion Defines the pin assignments that connect to the shift register. + The constructor does not initialize the LCD. Assuming 1 line 8 pixel high + font. + + @param srdata[in] Arduino pin for shift register data line. + @param srclock[in] Arduino pin for shift register clock line. + @param blpol[in] optional backlight polarity (default = POSITIVE) + */ + LiquidCrystal_SR2W (uint8_t srdata, uint8_t srclock, t_backlighPol blpol = POSITIVE); + + /*! + @function + @abstract Send a particular value to the LCD. + @discussion Sends a particular value to the LCD for writing to the LCD or + as an LCD command using the shift register. + + Users should never call this method. + + @param value[in] Value to send to the LCD. + @param mode[in] DATA=8bit data, COMMAND=8bit cmd, FOUR_BITS=4bit cmd + the LCD. + */ + virtual void send(uint8_t value, uint8_t mode); + + + /*! + @function + @abstract Switch-on/off the LCD backlight. + @discussion Switch-on/off the LCD backlight. + The setBacklightPin has to be called before setting the backlight for + this method to work. @see setBacklightPin. + + @param mode[in] backlight mode (0 off, non-zero on) + */ + void setBacklight ( uint8_t mode ); + +private: + + /*! + @method + @abstract Initializes the LCD pin allocation + @discussion Initializes the LCD pin allocation and configuration. + */ + void init ( uint8_t srdata, uint8_t srclock, t_backlighPol blpol, uint8_t lines, uint8_t font ); + + /*! + * @method + * @abstract takes care of shifting and the enable pulse + */ + void loadSR (uint8_t val); + + fio_register _srDataRegister; // Serial Data pin + fio_bit _srDataMask; + fio_register _srClockRegister; // Clock Pin + fio_bit _srClockMask; + + uint8_t _blPolarity; + uint8_t _blMask; +}; +#endif diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.cpp b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.cpp new file mode 100644 index 0000000..8486942 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.cpp @@ -0,0 +1,283 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 7.3.2012. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal_SRG.h +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK but using a generic SHIFT REGISTER extension board. +// +// @brief +// This is a basic implementation of the LiquidCrystal library of the +// Arduino SDK. The original library has been reworked in such a way that +// this class implements the all methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets using a 3 wire latching +// shift register. While it has been tested with a 74HC595N shift register +// it should also work with other latching shift registers such as the MC14094 +// and the HEF4094 +// +// This particular driver has been created as generic as possible to enable +// users to configure and connect their LCDs using just 3 digital IOs from the +// AVR or Arduino, and connect the LCD to the outputs of the shiftregister +// in any configuration. The library is configured by passing the IO pins +// that control the strobe, data and clock of the shift register and a map +// of how the shiftregister is connected to the LCD. +// +// +// +--------------------------------------------+ +// | MCU | +// | IO1 IO2 IO3 | +// +----+-------------+-------------+-----------+ +// | | | +// | | | +// +----+-------------+-------------+-----------+ +// | Strobe Data Clock | +// | 8-bit shift/latch register | 74HC595N +// | Qa0 Qb1 Qc2 Qd3 Qe4 Qf5 Qg6 Qh7 | +// +----+----+----+----+----+----+----+----+----+ +// | | | | | | | +// |11 |12 |13 |14 |6 |5 |4 (LCD pins) +// +----+----+----+----+----+----+----+----+----+ +// | DB4 DB5 DB6 DB7 E Rw RS | +// | LCD Module | +// +// NOTE: Rw is not used by the driver so it can be connected to GND. +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library. +// +// +// History +// 2012.03.29 bperrybap - fixed constructors not properly using Rs +// Fixed incorrect use of 5x10 for default font +// - now matches original LQ library. +// moved delay to send() so it is per cmd/write vs shiftout() +// NOTE: delay is on hairy edge of working when FAST_MODE is on. +// because of waitUsec(). +// There is margin at 16Mhz AVR but might fail on 20Mhz AVRs. +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +// flags for backlight control +#include +#include +#include + +#if (ARDUINO < 100) +#include +#else +#include +#endif +#include "Visuino_LiquidCrystal_SR3W.h" + +#include "Visuino_FastIO.h" + +/*! + @defined + @abstract LCD_NOBACKLIGHT + @discussion No BACKLIGHT MASK + */ +#define LCD_NOBACKLIGHT 0x00 + +/*! + @defined + @abstract LCD_BACKLIGHT + @discussion BACKLIGHT MASK used when backlight is on + */ +#define LCD_BACKLIGHT 0xFF + + +// Default library configuration parameters used by class constructor with +// only the I2C address field. +// --------------------------------------------------------------------------- +/*! + @defined + @abstract Enable bit of the LCD + @discussion Defines the IO of the expander connected to the LCD's Enable + */ +#define EN 4 // Enable bit + +/*! + @defined + @abstract Read/Write bit of the LCD + @discussion Defines the IO of the expander connected to the LCD's Rw pin + */ +#define RW 5 // Read/Write bit + +/*! + @defined + @abstract Register bit of the LCD + @discussion Defines the IO of the expander connected to the LCD's Register select pin + */ +#define RS 6 // Register select bit + +/*! + @defined + @abstract LCD dataline allocation this library only supports 4 bit LCD control + mode. + @discussion D4, D5, D6, D7 LCD data lines pin mapping of the extender module + */ +#define D4 0 +#define D5 1 +#define D6 2 +#define D7 3 + + + +LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe) +{ + init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 ); +} + +LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t backlighPin, t_backlighPol pol) +{ + init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 ); + setBacklightPin(backlighPin, pol); +} + +LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 ) +{ + init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 ); +} + +LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t backlighPin, t_backlighPol pol) +{ + init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 ); + setBacklightPin(backlighPin, pol); +} + + +void LiquidCrystal_SR3W::send(uint8_t value, uint8_t mode) +{ + + if ( mode != FOUR_BITS ) + { + write4bits( (value >> 4), mode ); // upper nibble + } + write4bits( (value & 0x0F), mode); // lower nibble + + +#if (F_CPU <= 16000000) + // No need to use the delay routines on AVR since the time taken to write + // on AVR with SR pin mapping even with fio is longer than LCD command execution. + waitUsec(37); //goes away on AVRs +#else + delayMicroseconds ( 37 ); // commands & data writes need > 37us to complete +#endif + +} + + +void LiquidCrystal_SR3W::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE ) +{ + _backlightPinMask = ( 1 << value ); + _backlightStsMask = LCD_NOBACKLIGHT; + _polarity = pol; + setBacklight (BACKLIGHT_OFF); // Set backlight to off as initial setup +} + +void LiquidCrystal_SR3W::setBacklight ( uint8_t value ) +{ + // Check if backlight is available + // ---------------------------------------------------- + if ( _backlightPinMask != 0x0 ) + { + // Check for polarity to configure mask accordingly + // ---------------------------------------------------------- + if (((_polarity == POSITIVE) && (value > 0)) || + ((_polarity == NEGATIVE ) && ( value == 0 ))) + { + _backlightStsMask = _backlightPinMask & LCD_BACKLIGHT; + } + else + { + _backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT; + } + loadSR( _backlightStsMask ); + } +} + + +// PRIVATE METHODS +// ----------------------------------------------------------------------------- + +int LiquidCrystal_SR3W::init(uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t Rs, uint8_t Rw, uint8_t En, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) +{ + _data = fio_pinToBit(data); + _clk = fio_pinToBit(clk); + _strobe = fio_pinToBit(strobe); + _data_reg = fio_pinToOutputRegister(data); + _clk_reg = fio_pinToOutputRegister(clk); + _strobe_reg = fio_pinToOutputRegister(strobe); + + // LCD pin mapping + _backlightPinMask = 0; + _backlightStsMask = LCD_NOBACKLIGHT; + _polarity = POSITIVE; + + _En = ( 1 << En ); + _Rw = ( 1 << Rw ); + _Rs = ( 1 << Rs ); + + // Initialise pin mapping + _data_pins[0] = ( 1 << d4 ); + _data_pins[1] = ( 1 << d5 ); + _data_pins[2] = ( 1 << d6 ); + _data_pins[3] = ( 1 << d7 ); + + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + + return (1); +} + +void LiquidCrystal_SR3W::write4bits(uint8_t value, uint8_t mode) +{ + uint8_t pinMapValue = 0; + + // Map the value to LCD pin mapping + // -------------------------------- + for ( uint8_t i = 0; i < 4; i++ ) + { + if ( ( value & 0x1 ) == 1 ) + { + pinMapValue |= _data_pins[i]; + } + value = ( value >> 1 ); + } + + // Is it a command or data + // ----------------------- + mode = ( mode == DATA ) ? _Rs : 0; + + pinMapValue |= mode | _backlightStsMask; + loadSR ( pinMapValue | _En ); // Send with enable high + loadSR ( pinMapValue); // Send with enable low +} + + +void LiquidCrystal_SR3W::loadSR(uint8_t value) +{ + // Load the shift register with information + fio_shiftOut(_data_reg, _data, _clk_reg, _clk, value, MSBFIRST); + + // Strobe the data into the latch + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + fio_digitalWrite_HIGH(_strobe_reg, _strobe); + fio_digitalWrite_SWITCHTO(_strobe_reg, _strobe, LOW); + } +} diff --git a/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.h b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.h new file mode 100644 index 0000000..378c7c0 --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/Visuino_LiquidCrystal_SR3W.h @@ -0,0 +1,202 @@ +// --------------------------------------------------------------------------- +// Created by Francisco Malpartida on 7.3.2012. +// Copyright 2011 - Under creative commons license 3.0: +// Attribution-ShareAlike CC BY-SA +// +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// Thread Safe: No +// Extendable: Yes +// +// @file LiquidCrystal_SR3W.h +// This file implements a basic liquid crystal library that comes as standard +// in the Arduino SDK but using a generic SHIFT REGISTER extension board. +// +// @brief +// This is a basic implementation of the LiquidCrystal library of the +// Arduino SDK. The original library has been reworked in such a way that +// this class implements the all methods to command an LCD based +// on the Hitachi HD44780 and compatible chipsets using a 3 wire latching +// shift register. While it has been tested with a 74HC595N shift register +// it should also work with other latching shift registers such as the MC14094 +// and the HEF4094 +// +// This particular driver has been created as generic as possible to enable +// users to configure and connect their LCDs using just 3 digital IOs from the +// AVR or Arduino, and connect the LCD to the outputs of the shiftregister +// in any configuration. The library is configured by passing the IO pins +// that control the strobe, data and clock of the shift register and a map +// of how the shiftregister is connected to the LCD. +// +// +// +--------------------------------------------+ +// | MCU | +// | IO1 IO2 IO3 | +// +----+-------------+-------------+-----------+ +// | | | +// | | | +// +----+-------------+-------------+-----------+ +// | Strobe Data Clock | +// | 8-bit shift/latch register | 74HC595N +// | Qa0 Qb1 Qc2 Qd3 Qe4 Qf5 Qg6 Qh7 | +// +----+----+----+----+----+----+----+----+----+ +// | | | | | | | +// |11 |12 |13 |14 |6 |5 |4 (LCD pins) +// +----+----+----+----+----+----+----+----+----+ +// | DB4 DB5 DB6 DB7 E Rw RS | +// | LCD Module | +// +// NOTE: Rw is not used by the driver so it can be connected to GND. +// +// The functionality provided by this class and its base class is identical +// to the original functionality of the Arduino LiquidCrystal library. +// +// +// @author F. Malpartida - fmalpartida@gmail.com +// --------------------------------------------------------------------------- +#ifndef _LIQUIDCRYSTAL_SR3W_H_ +#define _LIQUIDCRYSTAL_SR3W_H_ + +#include +#include "Visuino_LCD.h" +#include "Visuino_FastIO.h" + + +class LiquidCrystal_SR3W : public LCD +{ +public: + + /*! + @method + @abstract Class constructor. + @discussion Initializes class variables and defines the IO driving the + shift register. The constructor does not initialize the LCD. + Default configuration: + Shift register LCD + QA - 0 DB4 + QB - 1 DB5 + QC - 2 DB6 + QD - 3 DB7 + QE - 4 E + QF - 5 + QG - 6 Rs + GND Rw + + @param strobe[in] digital IO connected to shiftregister strobe pin. + @param data[in] digital IO connected to the shiftregister data pin. + @param clk[in] digital IO connected to the shiftregister clock pin. + */ + LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe); + // Constructor with backlight control + LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t backlighPin, t_backlighPol pol); + + /*! + @method + @abstract Class constructor. + @discussion Initializes class variables and defines the control lines of + the LCD and the shiftregister. The constructor does not initialize the LCD. + + @param strobe[in] digital IO connected to shiftregister strobe pin. + @param data[in] digital IO connected to shiftregister data pin. + @param clk[in] digital IO connected to shiftregister clock pin. + @param En[in] LCD En (Enable) pin connected to SR output pin. + @param Rw[in] LCD Rw (Read/write) pin connected to SR output pin. + @param Rs[in] LCD Rs (Reg Select) pin connected to SR output pin. + @param d4[in] LCD data 4 pin map to the SR output pin. + @param d5[in] LCD data 5 pin map to the SR output pin. + @param d6[in] LCD data 6 pin map to the SR output pin. + @param d7[in] LCD data 7 pin map to the SR output pin. + */ + LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 ); + // Constructor with backlight control + LiquidCrystal_SR3W( uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t En, uint8_t Rw, uint8_t Rs, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t backlighPin, t_backlighPol pol); + + /*! + @function + @abstract Send a particular value to the LCD. + @discussion Sends a particular value to the LCD for writing to the LCD or + as an LCD command. + + Users should never call this method. + + @param value[in] Value to send to the LCD. + @param mode[in] DATA - write to the LCD CGRAM, COMMAND - write a + command to the LCD. + */ + virtual void send(uint8_t value, uint8_t mode); + + /*! + @function + @abstract Sets the pin to control the backlight. + @discussion Sets the pin in the device to control the backlight. This device + doesn't support dimming backlight capability. + + @param 0: backlight off, 1..255: backlight on. + */ + void setBacklightPin ( uint8_t value, t_backlighPol pol ); + + /*! + @function + @abstract Switch-on/off the LCD backlight. + @discussion Switch-on/off the LCD backlight. + The setBacklightPin has to be called before setting the backlight for + this method to work. @see setBacklightPin. + + @param value: backlight mode (HIGH|LOW) + */ + void setBacklight ( uint8_t value ); + +private: + + /*! + @method + @abstract Initializes the LCD class + @discussion Initializes the LCD class and IO expansion module. + */ + int init(uint8_t data, uint8_t clk, uint8_t strobe, + uint8_t Rs, uint8_t Rw, uint8_t En, + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); + + /*! + @method + @abstract Writes an 4 bit value to the LCD. + @discussion Writes 4 bits (the least significant) to the LCD control data lines. + @param value[in] Value to write to the LCD + @param more[in] Value to distinguish between command and data. + COMMAND == command, DATA == data. + */ + void write4bits(uint8_t value, uint8_t mode); + + /*! + @function + @abstract load into the shift register a byte + @discussion loads into the shift register a byte + @param value[in]: value to be loaded into the shiftregister. + */ + void loadSR(uint8_t value); + + + fio_bit _strobe; // shift register strobe pin + fio_register _strobe_reg; // SR strobe pin MCU register + fio_bit _data; // shift register data pin + fio_register _data_reg; // SR data pin MCU register + fio_bit _clk; // shift register clock pin + fio_register _clk_reg; // SR clock pin MCU register + uint8_t _En; // LCD expander word for enable pin + uint8_t _Rw; // LCD expander word for R/W pin + uint8_t _Rs; // LCD expander word for Register Select pin + uint8_t _data_pins[4]; // LCD data lines + uint8_t _backlightPinMask; // Backlight IO pin mask + uint8_t _backlightStsMask; // Backlight status mask + +}; + +#endif + diff --git a/libraries/Visuino_LiquidCrystal/keywords.txt b/libraries/Visuino_LiquidCrystal/keywords.txt new file mode 100644 index 0000000..c13f5ae --- /dev/null +++ b/libraries/Visuino_LiquidCrystal/keywords.txt @@ -0,0 +1,52 @@ +########################################### +# Syntax Coloring Map For LiquidCrystal_I2C +########################################### + +########################################### +# Datatypes (KEYWORD1) +########################################### + +LiquidCrystal_SR KEYWORD1 +LiquidCrystal_I2C KEYWORD1 +LiquidCrystal_SR3W KEYWORD1 +LiquidCrystal KEYWORD1 +LCD KEYWORD1 + +########################################### +# Methods and Functions (KEYWORD2) +########################################### +begin KEYWORD2 +clear KEYWORD2 +home KEYWORD2 +noDisplay KEYWORD2 +display KEYWORD2 +noBlink KEYWORD2 +blink KEYWORD2 +noCursor KEYWORD2 +cursor KEYWORD2 +scrollDisplayLeft KEYWORD2 +scrollDisplayRight KEYWORD2 +leftToRight KEYWORD2 +rightToLeft KEYWORD2 +moveCursorLeft KEYWORD2 +moveCursorRight KEYWORD2 +autoscroll KEYWORD2 +noAutoscroll KEYWORD2 +createChar KEYWORD2 +setCursor KEYWORD2 +print KEYWORD2 +write KEYWORD2 +println KEYWORD2 +backlight KEYWORD2 +noBacklight KEYWORD2 +on KEYWORD2 +off KEYWORD2 +setBacklightPin KEYWORD2 +setBacklight KEYWORD2 +########################################### +# Constants (LITERAL1) +########################################### +POSITIVE LITERAL1 +NEGATIVE LITERAL1 +BACKLIGHT_ON LITERAL1 +BACKLIGHT_OFF LITERAL1 \ No newline at end of file diff --git a/libraries/bmp180/bmp180.cpp b/libraries/bmp180/bmp180.cpp new file mode 100644 index 0000000..36345df --- /dev/null +++ b/libraries/bmp180/bmp180.cpp @@ -0,0 +1,153 @@ +#include "Arduino.h" +#include "bmp180.h" + +bmp180::bmp180(int pin) { + pinMode(pin, OUTPUT); + _pin = pin; + Wire.begin(); + calibrate(); +} + +//Calabration of Barometic sensor +void bmp180::calibrate() { + _ac1 = readInt(0xAA); + _ac2 = readInt(0xAC); + _ac3 = readInt(0xAE); + _ac4 = readInt(0xB0); + _ac5 = readInt(0xB2); + _ac6 = readInt(0xB4); + _b1 = readInt(0xB6); + _b2 = readInt(0xB8); + _mb = readInt(0xBA); + _mc = readInt(0xBC); + _md = readInt(0xBE); +} + + + +// Read 1 byte from BMP180 +char bmp180::read(unsigned char address) { + + unsigned char data; + + Wire.beginTransmission(bmppin); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(bmppin, 1); + while(!Wire.available()); + + return Wire.read(); +} + +// Read 2 bytes from the BMP180. First byte from 'address', second from 'address'+1 +int bmp180::readInt(unsigned char address) { + + unsigned char msb, lsb; + + Wire.beginTransmission(bmppin); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(bmppin, 2); + while(Wire.available()<2) + ; + msb = Wire.read(); + lsb = Wire.read(); + + return (int) msb<<8 | lsb; +} + +// Read the compensated temperature value +unsigned int bmp180::readTemperature(){ + unsigned int ut; + + // Write 0x2E into Register 0xF4 + // This requests a temperature reading + Wire.beginTransmission(bmppin); + Wire.write(0xF4); + Wire.write(0x2E); + Wire.endTransmission(); + + // Wait at least 4.5ms + delay(5); + + // Read two bytes from registers 0xF6 and 0xF7 + ut = readInt(0xF6); + + long x1, x2; + + x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; + x2 = ((long)mc << 11)/(x1 + md); + b5 = x1 + x2; + + float temp = ((b5 + 8)>>4); + temp = temp /10; + + return temp; +} + + + + + + +// Calculate pressure given up (Uncompensated Pressure) +// calibration values must be known +// b5 is also required so bmp180GetTemperature(...) must be called first. +// Value returned will be pressure in units of Pa. + +// Read the compensated pressure value +unsigned long bmp180::readPressure(){ + + unsigned char msb, lsb, xlsb; + unsigned long up = 0; + + // Write 0x34+(OSS<<6) into register 0xF4 + // Request a pressure reading w/ oversampling setting + Wire.beginTransmission(bmppin); + Wire.write(0xF4); + Wire.write(0x34 + (OSS<<6)); + Wire.endTransmission(); + + // Wait for conversion, delay time dependent on OSS + delay(2 + (3<> (8-OSS); // Calculate uncompensated pressure + + + long x1, x2, x3, b3, b6, p; + unsigned long b4, b7; + + b6 = b5 - 4000; + // Calculate B3 + x1 = (b2 * (b6 * b6)>>12)>>11; + x2 = (ac2 * b6)>>11; + x3 = x1 + x2; + b3 = (((((long)ac1)*4 + x3)<>2; + + // Calculate B4 + x1 = (ac3 * b6)>>13; + x2 = (b1 * ((b6 * b6)>>12))>>16; + x3 = ((x1 + x2) + 2)>>2; + b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; + + b7 = ((unsigned long)(up - b3) * (50000>>OSS)); + if (b7 < 0x80000000) + p = (b7<<1)/b4; + else + p = (b7/b4)<<1; + + x1 = (p>>8) * (p>>8); + x1 = (x1 * 3038)>>16; + x2 = (-7357 * p)>>16; + p += (x1 + x2 + 3791)>>4; + + long pressure = p; + return pressure; +} diff --git a/libraries/bmp180/bmp180.h b/libraries/bmp180/bmp180.h new file mode 100644 index 0000000..ffc002c --- /dev/null +++ b/libraries/bmp180/bmp180.h @@ -0,0 +1,36 @@ +/* +* bmp180.h - Library for communicating with BMP180 sensor +* Created by Andrew Lorimer, original code by Leo Nutz (http://www.ALTDuino.de) +*/ + +#ifndef bmp180_h +#define bmp180_h + + #include "Arduino.h" + #include // Used for BMP180 + #include // Used for BMP180 (I2C communication) + + class bmp180 { + public: + bmp180(int pin); + void readTemperature(); + void readPressure(); + + private: + int _pin; + const unsigned char _OSS = 0; // Oversampling Setting + int _ac1; // Calibration values + int _ac2; + int _ac3; + unsigned int _ac4; + unsigned int _ac5; + unsigned int _ac6; + int _b1; + int _b2; + int _mb; + int _mc; + int _md; + long _b5; + } + +#endif diff --git a/libraries/rc-switch-2.52/RCSwitch.cpp b/libraries/rc-switch-2.52/RCSwitch.cpp new file mode 100644 index 0000000..762ebd0 --- /dev/null +++ b/libraries/rc-switch-2.52/RCSwitch.cpp @@ -0,0 +1,823 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Andreas Steinel / A.(at)gmail(dot)com + + Project home: http://code.google.com/p/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "RCSwitch.h" + +#if not defined( RCSwitchDisableReceiving ) +unsigned long RCSwitch::nReceivedValue = NULL; +unsigned int RCSwitch::nReceivedBitlength = 0; +unsigned int RCSwitch::nReceivedDelay = 0; +unsigned int RCSwitch::nReceivedProtocol = 0; +int RCSwitch::nReceiveTolerance = 60; +#endif +unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; + +RCSwitch::RCSwitch() { + this->nTransmitterPin = -1; + this->setPulseLength(350); + this->setRepeatTransmit(10); + this->setProtocol(1); + #if not defined( RCSwitchDisableReceiving ) + this->nReceiverInterrupt = -1; + this->setReceiveTolerance(60); + RCSwitch::nReceivedValue = NULL; + #endif +} + +/** + * Sets the protocol to send. + */ +void RCSwitch::setProtocol(int nProtocol) { + this->nProtocol = nProtocol; + if (nProtocol == 1){ + this->setPulseLength(350); + } + else if (nProtocol == 2) { + this->setPulseLength(650); + } + else if (nProtocol == 3) { + this->setPulseLength(100); + } +} + +/** + * Sets the protocol to send with pulse length in microseconds. + */ +void RCSwitch::setProtocol(int nProtocol, int nPulseLength) { + this->nProtocol = nProtocol; + this->setPulseLength(nPulseLength); +} + + +/** + * Sets pulse length in microseconds + */ +void RCSwitch::setPulseLength(int nPulseLength) { + this->nPulseLength = nPulseLength; +} + +/** + * Sets Repeat Transmits + */ +void RCSwitch::setRepeatTransmit(int nRepeatTransmit) { + this->nRepeatTransmit = nRepeatTransmit; +} + +/** + * Set Receiving Tolerance + */ +#if not defined( RCSwitchDisableReceiving ) +void RCSwitch::setReceiveTolerance(int nPercent) { + RCSwitch::nReceiveTolerance = nPercent; +} +#endif + + +/** + * Enable transmissions + * + * @param nTransmitterPin Arduino Pin to which the sender is connected to + */ +void RCSwitch::enableTransmit(int nTransmitterPin) { + this->nTransmitterPin = nTransmitterPin; + pinMode(this->nTransmitterPin, OUTPUT); +} + +/** + * Disable transmissions + */ +void RCSwitch::disableTransmit() { + this->nTransmitterPin = -1; +} + +/** + * Switch a remote switch on (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOn(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOff(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOn(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) ); +} + +/** + * Switch a remote switch off (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOff(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) ); +} + +/** + * Deprecated, use switchOn(char* sGroup, char* sDevice) instead! + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOn(char* sGroup, int nChannel) { + char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOn(sGroup, code[nChannel]); +} + +/** + * Deprecated, use switchOff(char* sGroup, char* sDevice) instead! + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOff(char* sGroup, int nChannel) { + char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOff(sGroup, code[nChannel]); +} + +/** + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOn(char* sGroup, char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) ); +} + +/** + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOff(char* sGroup, char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) ); +} + +/** + * Returns a char[13], representing the Code Word to be send. + * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used. + * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit) + * + * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ + * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | F | F | on=FF off=F0 | S | + * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + * @param bStatus Wether to switch on (true) or off (false) + * + * @return char[13] + */ +char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, boolean bStatus) { + int nReturnPos = 0; + static char sReturn[13]; + + char* code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" }; + if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { + return '\0'; + } + for (int i = 0; i<4; i++) { + sReturn[nReturnPos++] = code[nAddressCode][i]; + } + + for (int i = 0; i<4; i++) { + sReturn[nReturnPos++] = code[nChannelCode][i]; + } + + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + if (bStatus) { + sReturn[nReturnPos++] = 'F'; + } else { + sReturn[nReturnPos++] = '0'; + } + + sReturn[nReturnPos] = '\0'; + + return sReturn; +} + +/** + * Returns a char[13], representing the Code Word to be send. + * + * getCodeWordA(char*, char*) + * + */ +char* RCSwitch::getCodeWordA(char* sGroup, char* sDevice, boolean bOn) { + static char sDipSwitches[13]; + int i = 0; + int j = 0; + + for (i=0; i < 5; i++) { + if (sGroup[i] == '0') { + sDipSwitches[j++] = 'F'; + } else { + sDipSwitches[j++] = '0'; + } + } + + for (i=0; i < 5; i++) { + if (sDevice[i] == '0') { + sDipSwitches[j++] = 'F'; + } else { + sDipSwitches[j++] = '0'; + } + } + + if ( bOn ) { + sDipSwitches[j++] = '0'; + sDipSwitches[j++] = 'F'; + } else { + sDipSwitches[j++] = 'F'; + sDipSwitches[j++] = '0'; + } + + sDipSwitches[j] = '\0'; + + return sDipSwitches; +} + +/** + * Like getCodeWord (Type C = Intertechno) + */ +char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + if ( (byte)sFamily < 97 || (byte)sFamily > 112 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { + return '\0'; + } + + char* sDeviceGroupCode = dec2binWzerofill( (nDevice-1) + (nGroup-1)*4, 4 ); + char familycode[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" }; + for (int i = 0; i<4; i++) { + sReturn[nReturnPos++] = familycode[ (int)sFamily - 97 ][i]; + } + for (int i = 0; i<4; i++) { + sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0'); + } + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + if (bStatus) { + sReturn[nReturnPos++] = 'F'; + } else { + sReturn[nReturnPos++] = '0'; + } + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Decoding for the REV Switch Type + * + * Returns a char[13], representing the Tristate to be send. + * A Code Word consists of 7 address bits and 5 command data bits. + * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high) + * + * +-------------------------------+--------------------------------+-----------------------+ + * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | on=00010 off=00001 | + * +-------------------------------+--------------------------------+-----------------------+ + * + * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ + * + * @param sGroup Name of the switch group (A..D, resp. a..d) + * @param nDevice Number of the switch itself (1..3) + * @param bStatus Wether to switch on (true) or off (false) + * + * @return char[13] + */ + +char* RCSwitch::getCodeWordD(char sGroup, int nDevice, boolean bStatus){ + static char sReturn[13]; + int nReturnPos = 0; + + // Building 4 bits address + // (Potential problem if dec2binWcharfill not returning correct string) + char *sGroupCode; + switch(sGroup){ + case 'a': + case 'A': + sGroupCode = dec2binWcharfill(8, 4, 'F'); break; + case 'b': + case 'B': + sGroupCode = dec2binWcharfill(4, 4, 'F'); break; + case 'c': + case 'C': + sGroupCode = dec2binWcharfill(2, 4, 'F'); break; + case 'd': + case 'D': + sGroupCode = dec2binWcharfill(1, 4, 'F'); break; + default: + return '\0'; + } + + for (int i = 0; i<4; i++) + { + sReturn[nReturnPos++] = sGroupCode[i]; + } + + + // Building 3 bits address + // (Potential problem if dec2binWcharfill not returning correct string) + char *sDevice; + switch(nDevice) { + case 1: + sDevice = dec2binWcharfill(4, 3, 'F'); break; + case 2: + sDevice = dec2binWcharfill(2, 3, 'F'); break; + case 3: + sDevice = dec2binWcharfill(1, 3, 'F'); break; + default: + return '\0'; + } + + for (int i = 0; i<3; i++) + sReturn[nReturnPos++] = sDevice[i]; + + // fill up rest with zeros + for (int i = 0; i<5; i++) + sReturn[nReturnPos++] = '0'; + + // encode on or off + if (bStatus) + sReturn[10] = '1'; + else + sReturn[11] = '1'; + + // last position terminate string + sReturn[12] = '\0'; + return sReturn; + +} + +/** + * @param sCodeWord /^[10FS]*$/ -> see getCodeWord + */ +void RCSwitch::sendTriState(char* sCodeWord) { + for (int nRepeat=0; nRepeatsendT0(); + break; + case 'F': + this->sendTF(); + break; + case '1': + this->sendT1(); + break; + } + i++; + } + this->sendSync(); + } +} + +void RCSwitch::send(unsigned long Code, unsigned int length) { + this->send( this->dec2binWzerofill(Code, length) ); +} + +void RCSwitch::send(char* sCodeWord) { + for (int nRepeat=0; nRepeatsend0(); + break; + case '1': + this->send1(); + break; + } + i++; + } + this->sendSync(); + } +} + +void RCSwitch::transmit(int nHighPulses, int nLowPulses) { + #if not defined ( RCSwitchDisableReceiving ) + boolean disabled_Receive = false; + int nReceiverInterrupt_backup = nReceiverInterrupt; + #endif + if (this->nTransmitterPin != -1) { + #if not defined( RCSwitchDisableReceiving ) + if (this->nReceiverInterrupt != -1) { + this->disableReceive(); + disabled_Receive = true; + } + #endif + digitalWrite(this->nTransmitterPin, HIGH); + delayMicroseconds( this->nPulseLength * nHighPulses); + digitalWrite(this->nTransmitterPin, LOW); + delayMicroseconds( this->nPulseLength * nLowPulses); + + #if not defined( RCSwitchDisableReceiving ) + if(disabled_Receive){ + this->enableReceive(nReceiverInterrupt_backup); + } + #endif + } +} +/** + * Sends a "0" Bit + * _ + * Waveform Protocol 1: | |___ + * _ + * Waveform Protocol 2: | |__ + */ +void RCSwitch::send0() { + if (this->nProtocol == 1){ + this->transmit(1,3); + } + else if (this->nProtocol == 2) { + this->transmit(1,2); + } + else if (this->nProtocol == 3) { + this->transmit(4,11); + } +} + +/** + * Sends a "1" Bit + * ___ + * Waveform Protocol 1: | |_ + * __ + * Waveform Protocol 2: | |_ + */ +void RCSwitch::send1() { + if (this->nProtocol == 1){ + this->transmit(3,1); + } + else if (this->nProtocol == 2) { + this->transmit(2,1); + } + else if (this->nProtocol == 3) { + this->transmit(9,6); + } +} + + +/** + * Sends a Tri-State "0" Bit + * _ _ + * Waveform: | |___| |___ + */ +void RCSwitch::sendT0() { + this->transmit(1,3); + this->transmit(1,3); +} + +/** + * Sends a Tri-State "1" Bit + * ___ ___ + * Waveform: | |_| |_ + */ +void RCSwitch::sendT1() { + this->transmit(3,1); + this->transmit(3,1); +} + +/** + * Sends a Tri-State "F" Bit + * _ ___ + * Waveform: | |___| |_ + */ +void RCSwitch::sendTF() { + this->transmit(1,3); + this->transmit(3,1); +} + +/** + * Sends a "Sync" Bit + * _ + * Waveform Protocol 1: | |_______________________________ + * _ + * Waveform Protocol 2: | |__________ + */ +void RCSwitch::sendSync() { + + if (this->nProtocol == 1){ + this->transmit(1,31); + } + else if (this->nProtocol == 2) { + this->transmit(1,10); + } + else if (this->nProtocol == 3) { + this->transmit(1,71); + } +} + +#if not defined( RCSwitchDisableReceiving ) +/** + * Enable receiving data + */ +void RCSwitch::enableReceive(int interrupt) { + this->nReceiverInterrupt = interrupt; + this->enableReceive(); +} + +void RCSwitch::enableReceive() { + if (this->nReceiverInterrupt != -1) { + RCSwitch::nReceivedValue = NULL; + RCSwitch::nReceivedBitlength = NULL; + attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); + } +} + +/** + * Disable receiving data + */ +void RCSwitch::disableReceive() { + detachInterrupt(this->nReceiverInterrupt); + this->nReceiverInterrupt = -1; +} + +bool RCSwitch::available() { + return RCSwitch::nReceivedValue != NULL; +} + +void RCSwitch::resetAvailable() { + RCSwitch::nReceivedValue = NULL; +} + +unsigned long RCSwitch::getReceivedValue() { + return RCSwitch::nReceivedValue; +} + +unsigned int RCSwitch::getReceivedBitlength() { + return RCSwitch::nReceivedBitlength; +} + +unsigned int RCSwitch::getReceivedDelay() { + return RCSwitch::nReceivedDelay; +} + +unsigned int RCSwitch::getReceivedProtocol() { + return RCSwitch::nReceivedProtocol; +} + +unsigned int* RCSwitch::getReceivedRawdata() { + return RCSwitch::timings; +} + +/** + * + */ +bool RCSwitch::receiveProtocol1(unsigned int changeCount){ + + unsigned long code = 0; + unsigned long delay = RCSwitch::timings[0] / 31; + unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01; + + for (int i = 1; i delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*3-delayTolerance && RCSwitch::timings[i+1] < delay*3+delayTolerance) { + code = code << 1; + } else if (RCSwitch::timings[i] > delay*3-delayTolerance && RCSwitch::timings[i] < delay*3+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) { + code+=1; + code = code << 1; + } else { + // Failed + i = changeCount; + code = 0; + } + } + code = code >> 1; + if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = changeCount / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = 1; + } + + if (code == 0){ + return false; + }else if (code != 0){ + return true; + } + + +} + +bool RCSwitch::receiveProtocol2(unsigned int changeCount){ + + unsigned long code = 0; + unsigned long delay = RCSwitch::timings[0] / 10; + unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01; + + for (int i = 1; i delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*2-delayTolerance && RCSwitch::timings[i+1] < delay*2+delayTolerance) { + code = code << 1; + } else if (RCSwitch::timings[i] > delay*2-delayTolerance && RCSwitch::timings[i] < delay*2+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) { + code+=1; + code = code << 1; + } else { + // Failed + i = changeCount; + code = 0; + } + } + code = code >> 1; + if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = changeCount / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = 2; + } + + if (code == 0){ + return false; + }else if (code != 0){ + return true; + } + +} + +/** Protocol 3 is used by BL35P02. + * + */ +bool RCSwitch::receiveProtocol3(unsigned int changeCount){ + + unsigned long code = 0; + unsigned long delay = RCSwitch::timings[0] / PROTOCOL3_SYNC_FACTOR; + unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01; + + for (int i = 1; i delay*PROTOCOL3_0_HIGH_CYCLES - delayTolerance + && RCSwitch::timings[i] < delay*PROTOCOL3_0_HIGH_CYCLES + delayTolerance + && RCSwitch::timings[i+1] > delay*PROTOCOL3_0_LOW_CYCLES - delayTolerance + && RCSwitch::timings[i+1] < delay*PROTOCOL3_0_LOW_CYCLES + delayTolerance) { + code = code << 1; + } else if (RCSwitch::timings[i] > delay*PROTOCOL3_1_HIGH_CYCLES - delayTolerance + && RCSwitch::timings[i] < delay*PROTOCOL3_1_HIGH_CYCLES + delayTolerance + && RCSwitch::timings[i+1] > delay*PROTOCOL3_1_LOW_CYCLES - delayTolerance + && RCSwitch::timings[i+1] < delay*PROTOCOL3_1_LOW_CYCLES + delayTolerance) { + code+=1; + code = code << 1; + } else { + // Failed + i = changeCount; + code = 0; + } + } + code = code >> 1; + if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = changeCount / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = 3; + } + + if (code == 0){ + return false; + }else if (code != 0){ + return true; + } +} + +void RCSwitch::handleInterrupt() { + + static unsigned int duration; + static unsigned int changeCount; + static unsigned long lastTime; + static unsigned int repeatCount; + + + long time = micros(); + duration = time - lastTime; + + if (duration > 5000 && duration > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) { + repeatCount++; + changeCount--; + if (repeatCount == 2) { + if (receiveProtocol1(changeCount) == false){ + if (receiveProtocol2(changeCount) == false){ + if (receiveProtocol3(changeCount) == false){ + //failed + } + } + } + repeatCount = 0; + } + changeCount = 0; + } else if (duration > 5000) { + changeCount = 0; + } + + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + RCSwitch::timings[changeCount++] = duration; + lastTime = time; +} +#endif + +/** + * Turns a decimal value to its binary representation + */ +char* RCSwitch::dec2binWzerofill(unsigned long Dec, unsigned int bitLength){ + return dec2binWcharfill(Dec, bitLength, '0'); +} + +char* RCSwitch::dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill){ + static char bin[64]; + unsigned int i=0; + + while (Dec > 0) { + bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill; + Dec = Dec >> 1; + } + + for (unsigned int j = 0; j< bitLength; j++) { + if (j >= bitLength - i) { + bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; + }else { + bin[j] = fill; + } + } + bin[bitLength] = '\0'; + + return bin; +} + + + diff --git a/libraries/rc-switch-2.52/RCSwitch.h b/libraries/rc-switch-2.52/RCSwitch.h new file mode 100644 index 0000000..247315a --- /dev/null +++ b/libraries/rc-switch-2.52/RCSwitch.h @@ -0,0 +1,144 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + + Project home: http://code.google.com/p/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _RCSwitch_h +#define _RCSwitch_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific + #include "Energia.h" +#else + #include "WProgram.h" +#endif + + +// At least for the ATTiny X4/X5, receiving has to be disabled due to +// missing libm depencies (udivmodhi4) +#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ ) +#define RCSwitchDisableReceiving +#endif + +// Number of maximum High/Low changes per packet. +// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync +#define RCSWITCH_MAX_CHANGES 67 + +#define PROTOCOL3_SYNC_FACTOR 71 +#define PROTOCOL3_0_HIGH_CYCLES 4 +#define PROTOCOL3_0_LOW_CYCLES 11 +#define PROTOCOL3_1_HIGH_CYCLES 9 +#define PROTOCOL3_1_LOW_CYCLES 6 + +class RCSwitch { + + public: + RCSwitch(); + + void switchOn(int nGroupNumber, int nSwitchNumber); + void switchOff(int nGroupNumber, int nSwitchNumber); + void switchOn(char* sGroup, int nSwitchNumber); + void switchOff(char* sGroup, int nSwitchNumber); + void switchOn(char sFamily, int nGroup, int nDevice); + void switchOff(char sFamily, int nGroup, int nDevice); + void switchOn(char* sGroup, char* sDevice); + void switchOff(char* sGroup, char* sDevice); + void switchOn(char sGroup, int nDevice); + void switchOff(char sGroup, int nDevice); + + void sendTriState(char* Code); + void send(unsigned long Code, unsigned int length); + void send(char* Code); + + #if not defined( RCSwitchDisableReceiving ) + void enableReceive(int interrupt); + void enableReceive(); + void disableReceive(); + bool available(); + void resetAvailable(); + + unsigned long getReceivedValue(); + unsigned int getReceivedBitlength(); + unsigned int getReceivedDelay(); + unsigned int getReceivedProtocol(); + unsigned int* getReceivedRawdata(); + #endif + + void enableTransmit(int nTransmitterPin); + void disableTransmit(); + void setPulseLength(int nPulseLength); + void setRepeatTransmit(int nRepeatTransmit); + #if not defined( RCSwitchDisableReceiving ) + void setReceiveTolerance(int nPercent); + #endif + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + + private: + char* getCodeWordB(int nGroupNumber, int nSwitchNumber, boolean bStatus); + char* getCodeWordA(char* sGroup, int nSwitchNumber, boolean bStatus); + char* getCodeWordA(char* sGroup, char* sDevice, boolean bStatus); + char* getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus); + char* getCodeWordD(char group, int nDevice, boolean bStatus); + void sendT0(); + void sendT1(); + void sendTF(); + void send0(); + void send1(); + void sendSync(); + void transmit(int nHighPulses, int nLowPulses); + + static char* dec2binWzerofill(unsigned long dec, unsigned int length); + static char* dec2binWcharfill(unsigned long dec, unsigned int length, char fill); + + #if not defined( RCSwitchDisableReceiving ) + static void handleInterrupt(); + static bool receiveProtocol1(unsigned int changeCount); + static bool receiveProtocol2(unsigned int changeCount); + static bool receiveProtocol3(unsigned int changeCount); + int nReceiverInterrupt; + #endif + int nTransmitterPin; + int nPulseLength; + int nRepeatTransmit; + char nProtocol; + + #if not defined( RCSwitchDisableReceiving ) + static int nReceiveTolerance; + static unsigned long nReceivedValue; + static unsigned int nReceivedBitlength; + static unsigned int nReceivedDelay; + static unsigned int nReceivedProtocol; + #endif + /* + * timings[0] contains sync timing, followed by a number of bits + */ + static unsigned int timings[RCSWITCH_MAX_CHANGES]; + + +}; + +#endif diff --git a/libraries/rc-switch-2.52/README.md b/libraries/rc-switch-2.52/README.md new file mode 100644 index 0000000..562a482 --- /dev/null +++ b/libraries/rc-switch-2.52/README.md @@ -0,0 +1,15 @@ +# rc-switch +Use your Arduino to operate remote radio controlled devices + +##Info +Send RC codes + +Use your Arduino to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets. + +All you need is a Arduino, a 315/433MHz AM transmitter and one or more devices with a SC5262 / SC5272, HX2262 / HX2272, PT2262 / PT2272, EV1527, RT1527, FP1527 or HS1527 chipset. Also supports Intertechno outlets. + +##Receive and decode RC codes + +Find out what codes your remote is sending. Use your remote to control your Arduino. + +All you need is a Arduino, a 315/433MHz AM receiver (altough there is no instruction yet, yes it is possible to hack an existing device) and a remote hand set. diff --git a/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde b/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde new file mode 100644 index 0000000..89cbbc9 --- /dev/null +++ b/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde @@ -0,0 +1,24 @@ +/* + Example for receiving + + http://code.google.com/p/rc-switch/ + + If you want to visualize a telegram copy the raw data and + paste it into http://test.sui.li/oszi/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on inerrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); + mySwitch.resetAvailable(); + } +} diff --git a/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/helperfunctions.ino b/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/helperfunctions.ino new file mode 100644 index 0000000..56f3c0c --- /dev/null +++ b/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/helperfunctions.ino @@ -0,0 +1,20 @@ +static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength){ + static char bin[64]; + unsigned int i=0; + + while (Dec > 0) { + bin[32+i++] = (Dec & 1 > 0) ? '1' : '0'; + Dec = Dec >> 1; + } + + for (unsigned int j = 0; j< bitLength; j++) { + if (j >= bitLength - i) { + bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; + }else { + bin[j] = '0'; + } + } + bin[bitLength] = '\0'; + + return bin; +} diff --git a/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/output.ino b/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/output.ino new file mode 100644 index 0000000..b8b8cf8 --- /dev/null +++ b/libraries/rc-switch-2.52/examples/ReceiveDemo_Advanced/output.ino @@ -0,0 +1,52 @@ +void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) { + + if (decimal == 0) { + Serial.print("Unknown encoding."); + } else { + char* b = dec2binWzerofill(decimal, length); + Serial.print("Decimal: "); + Serial.print(decimal); + Serial.print(" ("); + Serial.print( length ); + Serial.print("Bit) Binary: "); + Serial.print( b ); + Serial.print(" Tri-State: "); + Serial.print( bin2tristate( b) ); + Serial.print(" PulseLength: "); + Serial.print(delay); + Serial.print(" microseconds"); + Serial.print(" Protocol: "); + Serial.println(protocol); + } + + Serial.print("Raw data: "); + for (int i=0; i<= length*2; i++) { + Serial.print(raw[i]); + Serial.print(","); + } + Serial.println(); + Serial.println(); +} + + +static char* bin2tristate(char* bin) { + char returnValue[50]; + int pos = 0; + int pos2 = 0; + while (bin[pos]!='\0' && bin[pos+1]!='\0') { + if (bin[pos]=='0' && bin[pos+1]=='0') { + returnValue[pos2] = '0'; + } else if (bin[pos]=='1' && bin[pos+1]=='1') { + returnValue[pos2] = '1'; + } else if (bin[pos]=='0' && bin[pos+1]=='1') { + returnValue[pos2] = 'F'; + } else { + return "not applicable"; + } + pos = pos+2; + pos2++; + } + returnValue[pos2] = '\0'; + return returnValue; +} + diff --git a/libraries/rc-switch-2.52/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde b/libraries/rc-switch-2.52/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde new file mode 100644 index 0000000..b55e5d7 --- /dev/null +++ b/libraries/rc-switch-2.52/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde @@ -0,0 +1,35 @@ +/* + Simple example for receiving + + http://code.google.com/p/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on inerrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + + int value = mySwitch.getReceivedValue(); + + if (value == 0) { + Serial.print("Unknown encoding"); + } else { + Serial.print("Received "); + Serial.print( mySwitch.getReceivedValue() ); + Serial.print(" / "); + Serial.print( mySwitch.getReceivedBitlength() ); + Serial.print("bit "); + Serial.print("Protocol: "); + Serial.println( mySwitch.getReceivedProtocol() ); + } + + mySwitch.resetAvailable(); + } +} diff --git a/libraries/rc-switch-2.52/examples/SendDemo/SendDemo.pde b/libraries/rc-switch-2.52/examples/SendDemo/SendDemo.pde new file mode 100644 index 0000000..9ee54ce --- /dev/null +++ b/libraries/rc-switch-2.52/examples/SendDemo/SendDemo.pde @@ -0,0 +1,57 @@ +/* + Example for different sending methods + + http://code.google.com/p/rc-switch/ + +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + Serial.begin(9600); + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + + // Optional set protocol (default is 1, will work for most outlets) + // mySwitch.setProtocol(2); + + // Optional set number of transmission repetitions. + // mySwitch.setRepeatTransmit(15); + +} + +void loop() { + + /* See Example: TypeA_WithDIPSwitches */ + mySwitch.switchOn("11111", "00010"); + delay(1000); + mySwitch.switchOn("11111", "00010"); + delay(1000); + + /* Same switch as above, but using decimal code */ + mySwitch.send(5393, 24); + delay(1000); + mySwitch.send(5396, 24); + delay(1000); + + /* Same switch as above, but using binary code */ + mySwitch.send("000000000001010100010001"); + delay(1000); + mySwitch.send("000000000001010100010100"); + delay(1000); + + /* Same switch as above, but tri-state code */ + mySwitch.sendTriState("00000FFF0F0F"); + delay(1000); + mySwitch.sendTriState("00000FFF0FF0"); + delay(1000); + + delay(20000); +} diff --git a/libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde b/libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde new file mode 100644 index 0000000..b362151 --- /dev/null +++ b/libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with a 10 pole DIP switch. + + http://code.google.com/p/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first 5 DIP switches. + // In this example it's ON-ON-OFF-OFF-ON. + // + // The second parameter represents the setting of the last 5 DIP switches. + // In this example the last 5 DIP switches are OFF-ON-OFF-ON-OFF. + mySwitch.switchOn("11001", "01010"); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff("11001", "01010"); + + // Wait another second + delay(1000); + +} diff --git a/libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino new file mode 100644 index 0000000..5796624 --- /dev/null +++ b/libraries/rc-switch-2.52/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino @@ -0,0 +1,43 @@ +/* + This is a minimal sketch without using the library at all but only works for + the 10 pole dip switch sockets. It saves a lot of memory and thus might be + very useful to use with ATTinys :) + + http://code.google.com/p/rc-switch/ +*/ + +int RCLpin = 7; + +void setup() { + pinMode(RCLpin, OUTPUT); +} + +void loop() { + RCLswitch(0b010001000001); // DIPs an Steckdose: 0100010000 An:01 + delay(2000); + + RCLswitch(0b010001000010); // DIPs an Steckdose: 0100010000 Aus:10 + delay(2000); +} + +void RCLswitch(uint16_t code) { + for (int nRepeat=0; nRepeat<6; nRepeat++) { + for (int i=4; i<16; i++) { + RCLtransmit(1,3); + if (((code << (i-4)) & 2048) > 0) { + RCLtransmit(1,3); + } else { + RCLtransmit(3,1); + } + } + RCLtransmit(1,31); + } +} + +void RCLtransmit(int nHighPulses, int nLowPulses) { + digitalWrite(RCLpin, HIGH); + delayMicroseconds( 350 * nHighPulses); + digitalWrite(RCLpin, LOW); + delayMicroseconds( 350 * nLowPulses); +} + diff --git a/libraries/rc-switch-2.52/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde b/libraries/rc-switch-2.52/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde new file mode 100644 index 0000000..61e0d76 --- /dev/null +++ b/libraries/rc-switch-2.52/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with two rotary/sliding switches. + + http://code.google.com/p/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first rotary switch. + // In this example it's switched to "1" or "A" or "I". + // + // The second parameter represents the setting of the second rotary switch. + // In this example it's switched to "4" or "D" or "IV". + mySwitch.switchOn(1, 4); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff(1, 4); + + // Wait another second + delay(1000); + +} diff --git a/libraries/rc-switch-2.52/examples/TypeC_Intertechno/TypeC_Intertechno.pde b/libraries/rc-switch-2.52/examples/TypeC_Intertechno/TypeC_Intertechno.pde new file mode 100644 index 0000000..012a93a --- /dev/null +++ b/libraries/rc-switch-2.52/examples/TypeC_Intertechno/TypeC_Intertechno.pde @@ -0,0 +1,40 @@ +/* + Example for Intertechno outlets + + http://code.google.com/p/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the familycode (a, b, c, ... f) + // The second parameter represents the group number + // The third parameter represents the device number + // + // In this example it's family 'b', group #3, device #2 + mySwitch.switchOn('b', 3, 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('b', 3, 2); + + // Wait another second + delay(1000); + +} \ No newline at end of file diff --git a/libraries/rc-switch-2.52/examples/TypeD_REV/TypeD_REV.ino b/libraries/rc-switch-2.52/examples/TypeD_REV/TypeD_REV.ino new file mode 100644 index 0000000..446bc8a --- /dev/null +++ b/libraries/rc-switch-2.52/examples/TypeD_REV/TypeD_REV.ino @@ -0,0 +1,41 @@ +/* + Example for REV outlets (e.g. 8342L) + + http://code.google.com/p/rc-switch/ + + Need help? http://forum.ardumote.com +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // set pulse length. + mySwitch.setPulseLength(360); + +} + +void loop() { + + // Switch on: + // The first parameter represents the channel (a, b, c, d) + // The second parameter represents the device number + // + // In this example it's family 'd', device #2 + mySwitch.switchOn('d', 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('d', 2); + + // Wait another second + delay(1000); + +} diff --git a/libraries/rc-switch-2.52/examples/Webserver/Webserver.pde b/libraries/rc-switch-2.52/examples/Webserver/Webserver.pde new file mode 100644 index 0000000..ee2c74a --- /dev/null +++ b/libraries/rc-switch-2.52/examples/Webserver/Webserver.pde @@ -0,0 +1,154 @@ +/* + A simple RCSwitch/Ethernet/Webserver demo + + http://code.google.com/p/rc-switch/ +*/ + +#include +#include +#include + +// Ethernet configuration +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC Address +byte ip[] = { 192,168,0, 2 }; // IP Address +EthernetServer server(80); // Server Port 80 + +// RCSwitch configuration +RCSwitch mySwitch = RCSwitch(); +int RCTransmissionPin = 7; + +// More to do... +// You should also modify the processCommand() and +// httpResponseHome() functions to fit your needs. + + + +/** + * Setup + */ +void setup() { + Ethernet.begin(mac, ip); + server.begin(); + mySwitch.enableTransmit( RCTransmissionPin ); +} + +/** + * Loop + */ +void loop() { + char* command = httpServer(); +} + +/** + * Command dispatcher + */ +void processCommand(char* command) { + if (strcmp(command, "1-on") == 0) { + mySwitch.switchOn(1,1); + } else if (strcmp(command, "1-off") == 0) { + mySwitch.switchOff(1,1); + } else if (strcmp(command, "2-on") == 0) { + mySwitch.switchOn(1,2); + } else if (strcmp(command, "2-off") == 0) { + mySwitch.switchOff(1,2); + } +} + +/** + * HTTP Response with homepage + */ +void httpResponseHome(EthernetClient c) { + c.println("HTTP/1.1 200 OK"); + c.println("Content-Type: text/html"); + c.println(); + c.println(""); + c.println(""); + c.println( "RCSwitch Webserver Demo"); + c.println( ""); + c.println(""); + c.println(""); + c.println( "

RCSwitch Webserver Demo

"); + c.println( "
"); + c.println( ""); + c.println( "
"); + c.println( "http://code.google.com/p/rc-switch/"); + c.println(""); + c.println(""); +} + +/** + * HTTP Redirect to homepage + */ +void httpResponseRedirect(EthernetClient c) { + c.println("HTTP/1.1 301 Found"); + c.println("Location: /"); + c.println(); +} + +/** + * HTTP Response 414 error + * Command must not be longer than 30 characters + **/ +void httpResponse414(EthernetClient c) { + c.println("HTTP/1.1 414 Request URI too long"); + c.println("Content-Type: text/plain"); + c.println(); + c.println("414 Request URI too long"); +} + +/** + * Process HTTP requests, parse first request header line and + * call processCommand with GET query string (everything after + * the ? question mark in the URL). + */ +char* httpServer() { + EthernetClient client = server.available(); + if (client) { + char sReturnCommand[32]; + int nCommandPos=-1; + sReturnCommand[0] = '\0'; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + if ((c == '\n') || (c == ' ' && nCommandPos>-1)) { + sReturnCommand[nCommandPos] = '\0'; + if (strcmp(sReturnCommand, "\0") == 0) { + httpResponseHome(client); + } else { + processCommand(sReturnCommand); + httpResponseRedirect(client); + } + break; + } + if (nCommandPos>-1) { + sReturnCommand[nCommandPos++] = c; + } + if (c == '?' && nCommandPos == -1) { + nCommandPos = 0; + } + } + if (nCommandPos > 30) { + httpResponse414(client); + sReturnCommand[0] = '\0'; + break; + } + } + if (nCommandPos!=-1) { + sReturnCommand[nCommandPos] = '\0'; + } + // give the web browser time to receive the data + delay(1); + client.stop(); + + return sReturnCommand; + } + return '\0'; +} \ No newline at end of file diff --git a/libraries/rc-switch-2.52/keywords.txt b/libraries/rc-switch-2.52/keywords.txt new file mode 100644 index 0000000..2474367 --- /dev/null +++ b/libraries/rc-switch-2.52/keywords.txt @@ -0,0 +1,57 @@ +####################################### +# Syntax Coloring Map For RCSwitch +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +RCSwitch KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +########## +#SENDS Begin +########## +switchOn KEYWORD2 +switchOff KEYWORD2 +sendTriState KEYWORD2 +send KEYWORD2 +########## +#SENDS End +########## + +########## +#RECEIVE Begin +########## +enableReceive KEYWORD2 +disableReceive KEYWORD2 +available KEYWORD2 +resetAvailable KEYWORD2 +setReceiveTolerance KEYWORD2 +getReceivedValue KEYWORD2 +getReceivedBitlength KEYWORD2 +getReceivedDelay KEYWORD2 +getReceivedProtocol KEYWORD2 +getReceivedRawdata KEYWORD2 +########## +#RECEIVE End +########## + +########## +#OTHERS Begin +########## +enableTransmit KEYWORD2 +disableTransmit KEYWORD2 +setPulseLength KEYWORD2 +setProtocol KEYWORD2 +setRepeatTransmit KEYWORD2 +########## +#OTHERS End +########## + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/readme.txt b/libraries/readme.txt new file mode 100644 index 0000000..96ce674 --- /dev/null +++ b/libraries/readme.txt @@ -0,0 +1 @@ +For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries diff --git a/test_Code/modified_Examples/receiver/receiver.ino b/test_Code/modified_Examples/receiver/receiver.ino new file mode 100644 index 0000000..1d8c104 --- /dev/null +++ b/test_Code/modified_Examples/receiver/receiver.ino @@ -0,0 +1,53 @@ +// receiver.pde +// +// Simple example of how to use VirtualWire to receive messages +// Implements a simplex (one-way) receiver with an Rx-B1 module +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@airspayce.com) +// Copyright (C) 2008 Mike McCauley +// $Id: receiver.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $ + +#include + +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + pinMode(11, INPUT_PULLUP); + pinMode('D12', OUTPUT); + vw_set_rx_pin(11); + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + + vw_rx_start(); // Start the receiver PLL running +} + +void loop() { + Serial.println(digitalRead(11)); +} + +void oldloop() +{ + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + + digitalWrite(13, true); // Flash a light to show received good message + // Message with a good checksum received, dump it. + Serial.print("Got: "); + + for (i = 0; i < buflen; i++) + { + Serial.print(buf[i], HEX); + Serial.print(" "); + } + Serial.println(""); + digitalWrite(13, false); + } +} diff --git a/test_Code/modified_Examples/transmitter/transmitter.ino b/test_Code/modified_Examples/transmitter/transmitter.ino new file mode 100644 index 0000000..0447f7f --- /dev/null +++ b/test_Code/modified_Examples/transmitter/transmitter.ino @@ -0,0 +1,35 @@ +// transmitter.pde +// +// Simple example of how to use VirtualWire to transmit messages +// Implements a simplex (one-way) transmitter with an TX-C1 module +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@airspayce.com) +// Copyright (C) 2008 Mike McCauley +// $Id: transmitter.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $ + +#include + +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + // Initialise the IO and ISR + pinMode(12, OUTPUT); + vw_set_tx_pin(12); + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec +} + +void loop() +{ + const char *msg = "hello"; + + digitalWrite(13, true); // Flash a light to show transmitting + vw_send((uint8_t *)msg, strlen(msg)); + vw_wait_tx(); // Wait until the whole message is gone + Serial.println("Transmitted!"); + digitalWrite(13, false); + delay(2000); +} diff --git a/test_Code/pinState/pinState.ino b/test_Code/pinState/pinState.ino new file mode 100644 index 0000000..12f8bd2 --- /dev/null +++ b/test_Code/pinState/pinState.ino @@ -0,0 +1,7 @@ +void setup() { + Serial.begin(9600); + pinMode(11, INPUT_PULLUP); +} +void loop() { + Serial.println(digitalRead(11)); +} diff --git a/test_Code/receive-test/receive-test.ino b/test_Code/receive-test/receive-test.ino new file mode 100644 index 0000000..4557231 --- /dev/null +++ b/test_Code/receive-test/receive-test.ino @@ -0,0 +1,25 @@ +#define rfReceivePin A0 //RF Receiver pin = Analog pin 0 + + unsigned int data = 0; // variable used to store received data + const unsigned int upperThreshold = 50; //upper threshold value + const unsigned int lowerThreshold = 30; //lower threshold value + + void setup(){ + pinMode(13, OUTPUT); + Serial.begin(9600); + } + + void loop(){ + data=analogRead(rfReceivePin); //listen for data on Analog pin 0 + + if(data>upperThreshold){ + Serial.println("low"); + Serial.println(data); + } + + if(data +void setup() +{ + vw_set_ptt_inverted(true); // Required for DR3100 + vw_set_rx_pin(12); + vw_setup(4000); // Bits per sec + pinMode(13, OUTPUT); + + vw_rx_start(); // Start the receiver PLL running +} + void loop() +{ + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + if (vw_get_message(buf, &buflen)) // Non-blocking + { + if(buf[0]=='1'){ + + + digitalWrite(13,1); + } + if(buf[0]=='0'){ + digitalWrite(13,0); + } + +} +} diff --git a/test_Code/transmit-test/transmit-test.ino b/test_Code/transmit-test/transmit-test.ino new file mode 100644 index 0000000..954ab2f --- /dev/null +++ b/test_Code/transmit-test/transmit-test.ino @@ -0,0 +1,18 @@ +#define rfTransmitPin 4 //RF Transmitter pin = digital pin 4 + + void setup(){ + pinMode(rfTransmitPin, OUTPUT); + pinMode(13, OUTPUT); + } + + void loop(){ + for(int i=4000; i>5; i=i-(i/3)){ + digitalWrite(rfTransmitPin, HIGH); //Transmit a HIGH signal + Serial.println("HIGH"); + delay(2000); //Wait for 1 second + +// digitalWrite(rfTransmitPin,LOW); //Transmit a LOW signal +// Serial.println("low"); +// delay(i); //Variable delay + } + } diff --git a/test_Code/transmit/transmit.ino b/test_Code/transmit/transmit.ino new file mode 100644 index 0000000..0cdcf7b --- /dev/null +++ b/test_Code/transmit/transmit.ino @@ -0,0 +1,241 @@ +/********************************************************** + Bosch Pressure Sensor BMP085 / BMP180 readout routine + for the Arduino platform. + + Compiled by Leo Nutz + www.ALTDuino.de +**********************************************************/ + +#include "DHT.h" // Adafruit DHTxx lib +#include // Wire lib for I2C +#include + +#define TXPIN 12 +#define BMPPIN 0x77 // Sensor address +#define DHTPIN 2 // Digital pin the DHT22 is connected to +#define DHTTYPE DHT22 // Sensor type (DHT11, DHT22 etc) +DHT dht(DHTPIN, DHTTYPE); // Create DHT sensor object + +int RF_TX_PIN = 12; + +int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; // Store sensor PROM values from BMP180 +uint16_t ac4, ac5, ac6; // Store sensor PROM values from BMP180 +// Ultra Low Power OSS = 0, OSD = 5ms +// Standard OSS = 1, OSD = 8ms +// High OSS = 2, OSD = 14ms +// Ultra High Resolution OSS = 3, OSD = 26ms +const uint8_t oss = 3; // Set oversampling setting +const uint8_t osd = 26; // with corresponding oversampling delay + +float T, P; // Set global variables for temperature and pressure + +void setup() +{ + Wire.begin(); // Activate I2C + Serial.begin(9600); // Set up serial port + init_SENSOR(); // Initialize baro sensor variables + // Setup transmit pin + vw_set_tx_pin(RF_TX_PIN); + vw_setup(2000); // + delay(100); + +} + +void loop() +{ + int32_t b5; + + float h = dht.readHumidity(); // Read humidity + float t = dht.readTemperature(); // Read temperatre in celcius + float f = dht.readTemperature(true); // Read temperature in farenheit + + // Check if any reads failed and exit early (to try again). + if (isnan(h) || isnan(t) || isnan(f)) { + Serial.println("Failed to read from DHT sensor!"); + return; + } + // Compute heat index in Celsius (isFahreheit = false) + float hic = dht.computeHeatIndex(t, h, false); + + // Print everything + Serial.print("Humidity: "); + Serial.print(h); + Serial.println("%"); + + b5 = temperature(); // Read and calculate temperature (T) + + Serial.print("Temperature: "); + Serial.print(T, 2); + Serial.print(" C, "); + Serial.print(1.8 * T + 32.0, 2); + Serial.println(" F"); + + P = pressure(b5); // Read and calculate pressure (P) + + Serial.print("Pressure: "); + Serial.print(P, 2); + Serial.print(" mbar, "); + Serial.print(P * 0.0295299830714, 2); + Serial.println(" inHg"); + Serial.println(""); + + SendData("testing"); + delay(2000); // Delay between each readout + +} + + +void SendData(String Data) +{ + //Debug + Serial.println("-->"+ Data + "<-- "); + + //Making char Array of String + const char* rawdata = Data.c_str(); + + digitalWrite(13, true); // Flash a light to show transmitting + vw_send((uint8_t *)rawdata, strlen(rawdata)); //Send Data + vw_wait_tx(); // Wait until the whole message is gone + digitalWrite(13, false); + Serial.println("Data sent"); +} + +/********************************************** + Initialize sensor variables +**********************************************/ +void init_SENSOR() +{ + ac1 = read_2_bytes(0xAA); + ac2 = read_2_bytes(0xAC); + ac3 = read_2_bytes(0xAE); + ac4 = read_2_bytes(0xB0); + ac5 = read_2_bytes(0xB2); + ac6 = read_2_bytes(0xB4); + b1 = read_2_bytes(0xB6); + b2 = read_2_bytes(0xB8); + mb = read_2_bytes(0xBA); + mc = read_2_bytes(0xBC); + md = read_2_bytes(0xBE); + + Serial.println(""); + Serial.println("Sensor calibration data:"); + Serial.print(F("AC1 = ")); Serial.println(ac1); + Serial.print(F("AC2 = ")); Serial.println(ac2); + Serial.print(F("AC3 = ")); Serial.println(ac3); + Serial.print(F("AC4 = ")); Serial.println(ac4); + Serial.print(F("AC5 = ")); Serial.println(ac5); + Serial.print(F("AC6 = ")); Serial.println(ac6); + Serial.print(F("B1 = ")); Serial.println(b1); + Serial.print(F("B2 = ")); Serial.println(b2); + Serial.print(F("MB = ")); Serial.println(mb); + Serial.print(F("MC = ")); Serial.println(mc); + Serial.print(F("MD = ")); Serial.println(md); + Serial.println(""); +} + +/********************************************** + Calcualte pressure readings +**********************************************/ +float pressure(int32_t b5) +{ + int32_t x1, x2, x3, b3, b6, p, UP; + uint32_t b4, b7; + + UP = read_pressure(); // Read raw pressure + + b6 = b5 - 4000; + x1 = (b2 * (b6 * b6 >> 12)) >> 11; + x2 = ac2 * b6 >> 11; + x3 = x1 + x2; + b3 = (((ac1 * 4 + x3) << oss) + 2) >> 2; + x1 = ac3 * b6 >> 13; + x2 = (b1 * (b6 * b6 >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + b4 = (ac4 * (uint32_t)(x3 + 32768)) >> 15; + b7 = ((uint32_t)UP - b3) * (50000 >> oss); + if(b7 < 0x80000000) { p = (b7 << 1) / b4; } else { p = (b7 / b4) << 1; } // or p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2; + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + return (p + ((x1 + x2 + 3791) >> 4)) / 100.0f; // Return pressure in mbar +} + +/********************************************** + Read uncompensated temperature +**********************************************/ +int32_t temperature() +{ + int32_t x1, x2, b5, UT; + + Wire.beginTransmission(BMPPIN); // Start transmission to device + Wire.write(0xf4); // Sends register address + Wire.write(0x2e); // Write data + Wire.endTransmission(); // End transmission + delay(5); // Datasheet suggests 4.5 ms + + UT = read_2_bytes(0xf6); // Read uncompensated TEMPERATURE value + + // Calculate true temperature + x1 = (UT - (int32_t)ac6) * (int32_t)ac5 >> 15; + x2 = ((int32_t)mc << 11) / (x1 + (int32_t)md); + b5 = x1 + x2; + T = (b5 + 8) >> 4; + T = T / 10.0; // Temperature in celsius + return b5; +} + +/********************************************** + Read uncompensated pressure value +**********************************************/ +int32_t read_pressure() +{ + int32_t value; + Wire.beginTransmission(BMPPIN); // Start transmission to device + Wire.write(0xf4); // Sends register address to read from + Wire.write(0x34 + (oss << 6)); // Write data + Wire.endTransmission(); // SEd transmission + delay(osd); // Oversampling setting delay + Wire.beginTransmission(BMPPIN); + Wire.write(0xf6); // Register to read + Wire.endTransmission(); + Wire.requestFrom(BMPPIN, 3); // Request three bytes + if(Wire.available() >= 3) + { + value = (((int32_t)Wire.read() << 16) | ((int32_t)Wire.read() << 8) | ((int32_t)Wire.read())) >> (8 - oss); + } + return value; // Return value +} + +/********************************************** + Read 1 byte from the BMP sensor +**********************************************/ +uint8_t read_1_byte(uint8_t code) +{ + uint8_t value; + Wire.beginTransmission(BMPPIN); // Start transmission to device + Wire.write(code); // Sends register address to read from + Wire.endTransmission(); // End transmission + Wire.requestFrom(BMPPIN, 1); // Request data for 1 byte to be read + if(Wire.available() >= 1) + { + value = Wire.read(); // Get 1 byte of data + } + return value; // Return value +} + +/********************************************** + Read 2 bytes from the BMP sensor +**********************************************/ +uint16_t read_2_bytes(uint8_t code) +{ + uint16_t value; + Wire.beginTransmission(BMPPIN); // Start transmission to device + Wire.write(code); // Sends register address to read from + Wire.endTransmission(); // End transmission + Wire.requestFrom(BMPPIN, 2); // Request 2 bytes from device + if(Wire.available() >= 2) + { + value = (Wire.read() << 8) | Wire.read(); // Get 2 bytes of data + } + return value; // Return value +} diff --git a/test_Code/weather_Reciver/weather_Reciver.ino b/test_Code/weather_Reciver/weather_Reciver.ino new file mode 100644 index 0000000..bca2f97 --- /dev/null +++ b/test_Code/weather_Reciver/weather_Reciver.ino @@ -0,0 +1,174 @@ +// receiver.pde +// +// Simple example of how to use VirtualWire to receive messages +// Implements a simplex (one-way) receiver with an Rx-B1 module +// +// See VirtualWire.h for detailed API docs +// Author: Mike McCauley (mikem@airspayce.com) +// Copyright (C) 2008 Mike McCauley +// $Id: receiver.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $ +#include +#include +#include +#include + +double Temp; + +LiquidCrystal lcd(12, 10, 5, 4, 3, 2); //LCD Pins +int LCDpin =9; //LCD backlight Pin +int Humid; // Value +#define pir A0 //Pin for the PIR input + +//Varaible to store the recoverd values +String TempC; //Temp in C +String Vocht; //humidity +String Druk; //pressure + +void setup() +{ + Serial.begin(9600); // Debugging only + Serial.println("setup"); + + + ////Setting pins for backlight + pinMode(pir, INPUT); + pinMode(LCDpin, OUTPUT); + + //LCD + lcd.begin(20, 4); //Setting rows an colums + + lcd.setCursor(0, 0); //Set Cursor at begining + lcd.print("####################"); //Drawing + + lcd.setCursor(0, 1); //Set cursor at next line + lcd.print("# Bram's #"); //Drawim + + lcd.setCursor(0, 2); //Set cursor at next line + lcd.print("# Weather station #"); //Drawim + + lcd.setCursor(0, 3); //Set cursor at next line + lcd.print("#######-V1.0-#######"); //Drawim + + //Show on Screen, if this isnt called, screen would be empty + lcd.display(); + + //Set back color to full brightness + digitalWrite(LCDpin,255); + + //Wait a seccond + delay(1000); + + //For Receiving Data + // Initialise the IO and ISR + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + vw_rx_start(); // Start the receiver PLL running +} + + + +void loop() +{ + //IF PIR sensor if HIGH, LCD backlight is on + //The Sensitivity and duration is adjusted ON the PIR + digitalWrite(LCDpin, digitalRead(pir)); + + ////Receiving DATA + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + if (vw_get_message(buf, &buflen)) // Non-blocking + { + int i; + digitalWrite(13, true); //onboard LED ON + char Chars[buflen]; + for (i = 0; i < buflen; i++) + { + Chars[i] = char(buf[i]); //from buffer to Char Arry + } + + Serial.println(Chars); //Debug only + Decode(Chars); //Send to deconder + digitalWrite(13, false); //onboard LED OFF + } +} + +void Decode(char* Raw) +{ + + String Code = (String)Raw; //From Char Array to string + if (Code.startsWith("#C")) //Looks if Code starts With #C + { + TempC = Code.substring(2,7); //get 2 to 7 char and put in int TempC string + } + + if (Code.startsWith("#H")) //Looks if Code starts With #H + { + Vocht = Code.substring(2,4);//get 2 to 4 char and put in int Vocht string + } + + if (Code.startsWith("#P")) //Looks if Code starts With #P + { + Druk = Code.substring(2,8);//get 2 to 8 char and put in int Druk string + } + + SetScreen(); //Call Funtion +} + +//Herbouw scherm +void SetScreen() +{ + + lcd.clear(); //Cleas LCD + lcd.begin(20, 4); //set screen res + + if (TempC != "") + { + lcd.setCursor(0, 0); //Set Cursos + lcd.print(((String)" Temp = " + TempC + " oC")); //Writes text with received value + } + + if (Vocht != "") + { + lcd.setCursor(0, 1); //Set Cursos + lcd.print(((String)" Vocht = " + Vocht + "%")); //Writes text with received value + } + + if (Druk != "") + { + lcd.setCursor(0, 2); //Set Cursos + lcd.print(((String)" Druk = " + Druk + " HPA"));//Writes text with received value + } + lcd.display(); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test_Code/weather_Transmitter/weather_Transmitter.ino b/test_Code/weather_Transmitter/weather_Transmitter.ino new file mode 100644 index 0000000..762b736 --- /dev/null +++ b/test_Code/weather_Transmitter/weather_Transmitter.ino @@ -0,0 +1,135 @@ +#include + +/* + * Arduino Weather Station + * Transmitter Unit + * + * Code by Andrew Lorimer, 2016 + */ + + + +// Libraries +#include // Used for BMP180 +#include // Used for BMP180 (I2C communication) +#include // Used for 433 MHz transmitter +#include "DHT.h" // Adafruit DHTxx lib + +// Set up DHT22 +#define dhtpin 2 // Digital connection to DHT22 +DHT dht(dhtpin, DHT22); // Create DHT22 object + + +// Set up BMP180 +#define bmppin 0x77 // I2C address of BMP180 +const unsigned char OSS = 0; // Oversampling Setting +int ac1; // Calibration values +int ac2; +int ac3; +unsigned int ac4; +unsigned int ac5; +unsigned int ac6; +int b1; +int b2; +int mb; +int mc; +int md; +long b5; // + +// Set up 433 MHz transmitter +#define INTEGER_MAX (pow(2,31)-1) +#define E_MAX (pow(10, 7)) +#define E_MIN (pow(10, -6)) +#define EPSILON 0.000000119209 +OneWire oneWire(10); +int RF_TX_PIN = 12; + + + + + +void setup() +{ + Serial.begin(9600); + Serial.println("Entering setup routine..."); + + // DHT22 (humidity & temp) + dht.begin(); + Serial.println("> Successfully started DHT22"); + + //Pressure sensor + Wire.begin(); + CalibratePressure(); + Serial.println("> Successfully started BMP180"); + + // Setup transmit pin + vw_set_tx_pin(RF_TX_PIN); + vw_setup(2000); // + Serial.println("> Successfully started 433 MHz transmitter"); + + //For Debug + Serial.println("Finished setup routine.\n"); +} + + + + + + + +void loop() { + + // Humidity (DHT22) + float humidity = dht.readHumidity(); // Read humidity + if (isnan(humidity)) {Serial.println("ERROR: Failed to read humidity from DHT22.");} + SendData("#H"+ ((String)humidity)); // Send humidity data + + // Temperature (BMP180) + float temperature = readTemperature(); // Read temperature + if (isnan(temperature)) {Serial.println("ERROR: Failed to read temperature from BMP180.");} + SendData("#C"+(String(temperature,2))); // Send temperature data + + // Barometric pressure (BMP180) + float pressure = readPressure(); // Read pressure + if (isnan(pressure)) {Serial.println("ERROR: Failed to read pressure from BMP180.");} + SendData("#P"+(String(pressure/100,2))); + + delay(5000); //Wait for next loop + +} + + + + + + + +void SendData(String data) { + + Serial.println("Sending " + data); + + const char* rawdata = data.c_str(); // Conver input string to char array + digitalWrite(13, true); // Flash onboard TX light + vw_send((uint8_t *)rawdata, strlen(rawdata)); //Send Data + vw_wait_tx(); // Wait until the whole message is gone + digitalWrite(13, false); + +} + + + + + + + + + + + + + + + + + + diff --git a/weather_Receiver/weather_Receiver.ino b/weather_Receiver/weather_Receiver.ino new file mode 100644 index 0000000..d840083 --- /dev/null +++ b/weather_Receiver/weather_Receiver.ino @@ -0,0 +1,215 @@ +/* + * Arduino Weather Station - Receiver Unit + * Code by Andrew Lorimer (http://lorimer.id.au) + * Credit to @bram2202 (Instructables) and Mike McCauley (mikem@airspayce.com) + */ + + +// Libraries +#include // Communicates with 433 MHz receiver +#include // Displays text on LCD + +// Objects and pins +LiquidCrystal lcd(7, 8, 5, 4, 3, 2); //LCD Pins +#define pir A0 // Pin for PIR input +#define backpin A1 // Pin for backlight output + +// Data received ([0] = current; [1] = min; [2] = max) +String TempC[3]; // Temp (deg C) +String Humidity[3]; // Humidity (%) +String Pressure[3]; // Pressure (Pa) + + + + + + +void setup() { + + Serial.begin(9600); + Serial.println("Starting setup routine..."); + + // Motion sensor + pinMode(pir, INPUT); + Serial.println("> Successfully started motion sensor"); + + // LCD Display + pinMode(backpin, OUTPUT); // Set backlight pin + lcd.begin(20, 4); // Set resolution + + // Show splash + lcd.setCursor(0, 1); // Set cursor at first line + lcd.print(" arduino "); // Print splash + lcd.setCursor(0, 2); // Set cursor at second line + lcd.print(" weather "); // Print splash + lcd.display(); + Serial.println("> Successfully started LCD display"); + + // Wireless receiver + pinMode(11, INPUT); + vw_set_rx_pin(11); + vw_set_ptt_inverted(true); // Required for DR3100 + vw_setup(2000); // Bits per sec + vw_rx_start(); // Start the receiver PLL running + Serial.println("> Successfully started 433 MHz receiver"); + Serial.println("Finished setup routine.\n"); + + // Buttons + pinMode(A2, INPUT); + pinMode(A3, INPUT); + + delay(1500); +} + + + + +void loop() { + + analogWrite(backpin, analogRead(pir)); // If PIR is high, LCD backlight goes on. Duration & sensitivity adjusted on sensor. + Serial.println(analogRead(pir)); + // Receive data + uint8_t buf[VW_MAX_MESSAGE_LEN]; + uint8_t buflen = VW_MAX_MESSAGE_LEN; + + if (vw_get_message(buf, &buflen)) { + digitalWrite(13, true); // Flash onboard LED + char Chars[buflen]; + for (int i = 0; i < buflen; i++) {Chars[i] = char(buf[i]);} // From buffer to char array + Decode(Chars); // Send to deconder + digitalWrite(13, false); // Turn off onboard LED + } + + if (analogRead(A2) > 1020) { + DisplayMin(); + delay(7000); + DisplayCurrent(); + } + if (analogRead(A3) > 1020) { + DisplayMax(); + delay(7000); + DisplayCurrent(); + } +} + + + + +void Decode(char* Raw) { // Filter wireless signals and put data into strings + + String Code = (String)Raw; // From char array to string + + if (Code.startsWith("#C")) { + TempC[0] = Code.substring(2,7); // Get chars 2-7 + if (TempC[1] == "") {TempC[1] = TempC[0]; TempC[2] = TempC[0];} + if (TempC[0] < TempC[1]) {TempC[1] = TempC[0];} + if (TempC[0] > TempC[2]) {TempC[2] = TempC[0];} + Serial.println("Current Temp: " + TempC[0]); + Serial.println("Min Temp: " + TempC[1]); + Serial.println("Max Temp: " + TempC[2] + "\n"); + } + + if (Code.startsWith("#H")) { + Humidity[0] = Code.substring(2,4); // Get chars 2-4 + if (Humidity[1] == "") {Humidity[1] = Humidity[0]; Humidity[2] = Humidity[0];} + if (Humidity[0] < Humidity[1]) {Humidity[1] = Humidity[0];} + if (Humidity[0] > Humidity[2]) {Humidity[2] = Humidity[0];} + Serial.println("Current Humidity: " + Humidity[0]); + Serial.println("Min Humidity: " + Humidity[1]); + Serial.println("Max Humidity: " + Humidity[2] + "\n"); + } + + if (Code.startsWith("#P")) { + Pressure[0] = Code.substring(2,8); // Get chars 2-8 + if (Pressure[1] == "") {Pressure[1] = Pressure[0]; Pressure[2] = Pressure[0];} + if (Pressure[0] < Pressure[1]) {Pressure[1] = Pressure[0];} + if (Pressure[0] > Pressure[2]) {Pressure[2] = Pressure[0];} + Serial.println("Current Pressure: " + Pressure[0]); + Serial.println("Min Pressure: " + Pressure[1]); + Serial.println("Max Pressure: " + Pressure[2] + "\n"); + } + + DisplayCurrent(); + +} + + + + +void DisplayCurrent() { // Show text on screen + + lcd.clear(); // Clear LCD + lcd.begin(20, 4); // Set resolution + + if (TempC[0] != "") { + lcd.setCursor(0, 0); // Set cursor position to origin + lcd.print(((String)" Temp. " + TempC[0] + " oC")); // Print received data + } + + if (Humidity[0] != "") { + lcd.setCursor(0, 1); // Set cursor position to second line + lcd.print(((String)"Humid. " + Humidity[0] + " %")); // Print received data + } + + if (Pressure[0] != "") { + lcd.setCursor(0, 2); // Set cursor position to third line + lcd.print(((String)"Press. " + Pressure[0] + " hPa")); // Print received data + } + + lcd.display(); // Display data in buffer + +} + + + + +void DisplayMin() { // Show text on screen + + lcd.clear(); // Clear LCD + lcd.begin(20, 4); // Set resolution + + if (TempC[1] != "") { + lcd.setCursor(0, 0); // Set cursor position to origin + lcd.print(((String)" Temp. " + TempC[1] + " oC")); // Print received data + } + + if (Humidity[1] != "") { + lcd.setCursor(0, 1); // Set cursor position to second line + lcd.print(((String)"Humid. " + Humidity[1] + " %")); // Print received data + } + + if (Pressure[1] != "") { + lcd.setCursor(0, 2); // Set cursor position to third line + lcd.print(((String)"Press. " + Pressure[1] + " hPa")); // Print received data + } + + lcd.display(); // Display data in buffer + +} + + + + +void DisplayMax() { // Show text on screen + + lcd.clear(); // Clear LCD + lcd.begin(20, 4); // Set resolution + + if (TempC[2] != "") { + lcd.setCursor(0, 0); // Set cursor position to origin + lcd.print(((String)" Temp. " + TempC[2] + " oC")); // Print received data + } + + if (Humidity[2] != "") { + lcd.setCursor(0, 1); // Set cursor position to second line + lcd.print(((String)"Humid. " + Humidity[2] + " %")); // Print received data + } + + if (Pressure[2] != "") { + lcd.setCursor(0, 2); // Set cursor position to third line + lcd.print(((String)"Press. " + Pressure[2] + " hPa")); // Print received data + } + + lcd.display(); // Display data in buffer + +} diff --git a/weather_Transmitter/weather_Transmitter.ino b/weather_Transmitter/weather_Transmitter.ino new file mode 100644 index 0000000..a2497be --- /dev/null +++ b/weather_Transmitter/weather_Transmitter.ino @@ -0,0 +1,229 @@ +/* + * Arduino Weather Station - Transmitter Unit + * Code by Andrew Lorimer (http://lorimer.id.au) + * Credit to @bram2202 (Instructables) and Leo Nutz (http://altduino.de) + */ + + +// Libraries +#include // Used for BMP180 +#include // Used for 433 MHz transmitter +#include "DHT.h" // Adafruit DHTxx lib + + +// Sensor setup + +DHT dht(2, DHT22); // Set up DHT22 object on digital pin 2 +#define bmppin 0x77 // I2C address of BMP180 +const unsigned char OSS = 0; // Oversampling Setting for BMP180 + +// Calibration values for BMP180 +int ac1, ac2, ac3, b1, b2, mb, mc, md; +unsigned int ac4, ac5, ac6; +long b5; + +// Transmitter setup +#define INTEGER_MAX (powx(2,31)-1) +#define E_MAX (pow(10, 7)) +#define E_MIN (pow(10, -6)) +#define EPSILON 0.000000119209 +int txpin = 12; // Transmit pin of 433 MHz transmitter +int linenumber = 0; // Tracks how many lines of data sent (0-3) + + + +void setup() +{ + Serial.begin(9600); + Serial.println("Entering setup routine..."); + + // DHT22 (humidity & temp) + dht.begin(); + Serial.println("> Successfully started DHT22"); + + //Pressure sensor + Wire.begin(); + CalibratePressure(); + Serial.println("> Successfully started BMP180"); + + // Setup transmitter + pinMode('D12', OUTPUT); + vw_set_tx_pin(txpin); + vw_setup(2000); // + Serial.println("> Successfully started 433 MHz transmitter"); + + Serial.println("Finished setup routine.\n"); +} + + + + +void loop() { + + // Humidity (DHT22) + float humidity = dht.readHumidity(); // Read humidity + if (isnan(humidity)) {Serial.println("ERROR: Failed to read humidity from DHT22.");} + SendData("#H"+ ((String)humidity)); // Send humidity data + Serial.println(" Humidity: " + String(humidity) + " % (sent)"); + + // Temperature (BMP180) + float temperature = GetTemp(); // Read temperature + if (isnan(temperature)) {Serial.println("ERROR: Failed to read temperature from BMP180.");} + SendData("#C"+(String(temperature,2))); // Send temperature data + Serial.println("Temperature: " + String(temperature) + " " + char(176) + "C (sent)"); + + // Barometric pressure (BMP180) + float pressure = GetPressure(); // Read pressure + if (isnan(pressure)) {Serial.println("ERROR: Failed to read pressure from BMP180.");} + SendData("#P"+(String(pressure/100,2))); + Serial.println(" Pressure: " + String(temperature) + " hPa (sent)"); + + Serial.println(); + + delay(5000); //Wait for next loop + +} + + + + +void SendData(String data) { // Transmit data over 433 MHz + const char* rawdata = data.c_str(); // Convert input string to char array + digitalWrite(13, true); // Flash onboard TX light + vw_send((uint8_t *)rawdata, strlen(rawdata)); //Send Data + vw_wait_tx(); // Wait until the whole message is gone + digitalWrite(13, false); +} + + + + +void CalibratePressure() { + ac1 = BMP180ReadInt(0xAA); + ac2 = BMP180ReadInt(0xAC); + ac3 = BMP180ReadInt(0xAE); + ac4 = BMP180ReadInt(0xB0); + ac5 = BMP180ReadInt(0xB2); + ac6 = BMP180ReadInt(0xB4); + b1 = BMP180ReadInt(0xB6); + b2 = BMP180ReadInt(0xB8); + mb = BMP180ReadInt(0xBA); + mc = BMP180ReadInt(0xBC); + md = BMP180ReadInt(0xBE); +} + + + + +float GetTemp(){ // Calculate temperature (deg C) based on calibration data + + unsigned int ut; + + // Write 0x2E into Register 0xF4 + // This requests a temperature reading + Wire.beginTransmission(bmppin); + Wire.write(0xF4); + Wire.write(0x2E); + Wire.endTransmission(); + + delay(5); // Must be >4.5 ms + + ut = BMP180ReadInt(0xF6); // Read two bytes from registers 0xF6 and 0xF7 + + long x1, x2; + x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; + x2 = ((long)mc << 11)/(x1 + md); + b5 = x1 + x2; + float temp = ((b5 + 8)>>4); + temp = temp /10; + + return temp; +} + + + + +long GetPressure(){ // Calculate pressure based on calibration data +unsigned char msb, lsb, xlsb; + unsigned long up = 0; + + // Write 0x34+(OSS<<6) into register 0xF4 + // Request a pressure reading w/ oversampling setting + Wire.beginTransmission(bmppin); + Wire.write(0xF4); + Wire.write(0x34 + (OSS<<6)); + Wire.endTransmission(); + + // Wait for conversion, delay time dependent on OSS + delay(2 + (3<> (8-OSS); + + + long x1, x2, x3, b3, b6, p; + unsigned long b4, b7; + + b6 = b5 - 4000; + // Calculate B3 + x1 = (b2 * (b6 * b6)>>12)>>11; + x2 = (ac2 * b6)>>11; + x3 = x1 + x2; + b3 = (((((long)ac1)*4 + x3)<>2; + + // Calculate B4 + x1 = (ac3 * b6)>>13; + x2 = (b1 * ((b6 * b6)>>12))>>16; + x3 = ((x1 + x2) + 2)>>2; + b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; + + b7 = ((unsigned long)(up - b3) * (50000>>OSS)); + if (b7 < 0x80000000) + p = (b7<<1)/b4; + else + p = (b7/b4)<<1; + + x1 = (p>>8) * (p>>8); + x1 = (x1 * 3038)>>16; + x2 = (-7357 * p)>>16; + p += (x1 + x2 + 3791)>>4; + + long temp = p; + return temp; +} + + + + +char BMP180Read(unsigned char address) { // Read 1 byte + unsigned char data; + + Wire.beginTransmission(bmppin); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(bmppin, 1); + while(!Wire.available()); + + return Wire.read(); +} + +int BMP180ReadInt(unsigned char address) { // Read 2 bytes - first from 'address', second from 'address' + 1 + unsigned char msb, lsb; + + Wire.beginTransmission(bmppin); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(bmppin, 2); + while(Wire.available()<2) + ; + msb = Wire.read(); + lsb = Wire.read(); + + return (int) msb<<8 | lsb; +} -- 2.43.2