From 9d398154c75911f306f9e434a3b3f536fd94fa65 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Sun, 20 Sep 2015 22:59:27 +0200 Subject: [PATCH] Add pubsub client --- .../MySensors/drivers/pubsubclient/.gitignore | 1 + .../drivers/pubsubclient/.travis.yml | 7 + .../drivers/pubsubclient/CHANGES.txt | 63 + .../drivers/pubsubclient/LICENSE.txt | 20 + .../MySensors/drivers/pubsubclient/README.md | 47 + .../examples/mqtt_auth/mqtt_auth.ino | 43 + .../examples/mqtt_basic/mqtt_basic.ino | 77 + .../examples/mqtt_esp8266/mqtt_esp8266.ino | 126 ++ .../mqtt_publish_in_callback.ino | 60 + .../mqtt_reconnect_nonblocking.ino | 67 + .../examples/mqtt_stream/mqtt_stream.ino | 57 + .../drivers/pubsubclient/keywords.txt | 30 + .../drivers/pubsubclient/library.properties | 9 + .../drivers/pubsubclient/src/PubSubClient.cpp | 571 +++++ .../drivers/pubsubclient/src/PubSubClient.h | 127 ++ .../drivers/pubsubclient/tests/.gitignore | 4 + .../drivers/pubsubclient/tests/Makefile | 25 + .../drivers/pubsubclient/tests/README.md | 93 + .../pubsubclient/tests/src/connect_spec.cpp | 256 +++ .../pubsubclient/tests/src/keepalive_spec.cpp | 185 ++ .../pubsubclient/tests/src/lib/Arduino.h | 23 + .../pubsubclient/tests/src/lib/BDDTest.cpp | 50 + .../pubsubclient/tests/src/lib/BDDTest.h | 23 + .../pubsubclient/tests/src/lib/Buffer.cpp | 30 + .../pubsubclient/tests/src/lib/Buffer.h | 23 + .../pubsubclient/tests/src/lib/Client.h | 21 + .../pubsubclient/tests/src/lib/IPAddress.cpp | 44 + .../pubsubclient/tests/src/lib/IPAddress.h | 72 + .../pubsubclient/tests/src/lib/ShimClient.cpp | 153 ++ .../pubsubclient/tests/src/lib/ShimClient.h | 51 + .../pubsubclient/tests/src/lib/Stream.cpp | 39 + .../pubsubclient/tests/src/lib/Stream.h | 22 + .../pubsubclient/tests/src/lib/trace.h | 10 + .../pubsubclient/tests/src/publish_spec.cpp | 190 ++ .../pubsubclient/tests/src/receive_spec.cpp | 249 +++ .../pubsubclient/tests/src/subscribe_spec.cpp | 177 ++ .../pubsubclient/tests/testcases/__init__.py | 0 .../tests/testcases/mqtt_basic.py | 43 + .../testcases/mqtt_publish_in_callback.py | 64 + .../pubsubclient/tests/testcases/settings.py | 2 + .../drivers/pubsubclient/tests/testsuite.py | 179 ++ .../AirQualitySensor/AirQualitySensor.ino | 216 ++ .../BatteryPoweredSensor.ino | 89 + .../BinarySwitchSensor/BinarySwitchSensor.ino | 80 + .../BinarySwitchSleepSensor.ino | 118 + .../examples/CO2Sensor/CO2Sensor.ino | 102 + .../ClearEepromConfig/ClearEepromConfig.ino | 43 + .../DallasTemperatureSensor.ino | 103 + .../DimmableLEDActuator.ino | 126 ++ .../examples/DimmableLight/DimmableLight.ino | 162 ++ .../DimmableLightWithRotaryEncoderButton.ino | 240 +++ .../DistanceSensor/DistanceSensor.ino | 75 + .../examples/DustSensor/DustSensor.ino | 103 + .../examples/DustSensorDSM/DustSensorDSM.ino | 146 ++ .../EnergyMeterPulseSensor.ino | 151 ++ .../Esp8266Gateway/Esp8266Gateway.ino | 265 +++ .../examples/Esp8266Gateway/GatewayUtil.h | 136 ++ .../EthernetGateway/EthernetGateway.ino | 125 ++ .../HumiditySensor/HumiditySensor.ino | 97 + .../MySensors/examples/IrSensor/IrSensor.ino | 148 ++ .../IrrigationController.ino | 876 ++++++++ .../LightLuxSensor/LightLuxSensor.ino | 85 + .../examples/LightSensor/LightSensor.ino | 67 + .../LightningSensor/LightningSensor.ino | 123 ++ .../MAX6875TemperatureSensor.ino | 87 + .../MQTTClientGateway/MQTTClientGateway.ino | 614 ++++++ .../examples/MQTTClientGateway/MyMQTTClient.h | 129 ++ .../examples/MQTTGateway/MQTTGateway.ino | 474 ++++ .../MySensors/examples/MQTTGateway/MyMQTT.h | 138 ++ .../examples/MockMySensors/MockMySensors.ino | 1465 +++++++++++++ .../examples/MockMySensors/README.md | 40 + .../examples/MotionSensor/MotionSensor.ino | 70 + .../examples/ParkingSensor/ParkingSensor.ino | 178 ++ .../examples/PingPongSensor/MYSLog.h | 44 + .../PingPongSensor/PingPongSensor.ino | 97 + .../PressureSensor/PressureSensor.ino | 302 +++ .../RF433MhzSensor/RF433MhzSensor.ino | 139 ++ .../RFIDLockSensor/RFIDLockSensor.ino | 184 ++ .../MySensors/examples/RGB-3D/RGB-3D.ino | 304 +++ .../examples/RainGauge/RainGauge.ino | 599 ++++++ .../RealTimeClockDisplaySensor.ino | 142 ++ .../examples/RelayActuator/RelayActuator.ino | 86 + .../RelayWithButtonActuator.ino | 121 ++ .../examples/RepeaterNode/RepeaterNode.ino | 52 + .../SecretKnockSensor/SecretKnockSensor.ino | 379 ++++ .../SecureActuator/SecureActuator.ino | 102 + .../SensebenderBlink/SensebenderBlink.ino | 50 + .../SensebenderMicro/SensebenderMicro.ino | 422 ++++ .../examples/SerialGateway/SerialGateway.ino | 82 + .../examples/ServoActuator/ServoActuator.ino | 106 + .../Sha204Personalizer/Sha204Personalizer.ino | 1007 +++++++++ .../SoilMoistSensor/SoilMoistSensor.ino | 186 ++ .../TimeAwareSensor/TimeAwareSensor.ino | 95 + .../ArialNumFontPlus.c | 22 + .../TouchDisplaySceneControllerSensor.ino | 198 ++ .../Ubuntu.c | 110 + .../arial_bold.c | 111 + .../TouchDisplaySceneControllerSensor/logo.c | 235 ++ .../MySensors/examples/UVSensor/UVSensor.ino | 109 + .../VibrationSensor/VibrationSensor.ino | 96 + .../WaterMeterPulseSensor.ino | 189 ++ libraries/MySensors/keywords.txt | 84 + libraries/NewPing/NewPing.cpp | 231 ++ libraries/NewPing/NewPing.h | 162 ++ .../NewPing15Sensors/NewPing15Sensors.pde | 74 + .../NewPingEventTimer/NewPingEventTimer.pde | 46 + .../NewPingExample/NewPingExample.ino | 23 + .../examples/TimerExample/TimerExample.pde | 25 + libraries/NewPing/keywords.txt | 29 + .../NewRemoteSwitch/NewRemoteReceiver.cpp | 318 +++ libraries/NewRemoteSwitch/NewRemoteReceiver.h | 107 + .../NewRemoteSwitch/NewRemoteTransmitter.cpp | 134 ++ .../NewRemoteSwitch/NewRemoteTransmitter.h | 103 + libraries/NewRemoteSwitch/README.TXT | 48 + .../NewRemoteSwitch/docs/hardware setup.jpg | Bin 0 -> 132303 bytes .../docs/new kaku protocol.txt | 23 + .../examples/LearnCode/LearnCode.ino | 64 + .../examples/LightShow/LightShow.ino | 55 + .../examples/Retransmitter/Retransmitter.ino | 53 + .../ShowReceivedCode/ShowReceivedCode.ino | 65 + libraries/NewRemoteSwitch/keywords.txt | 11 + libraries/NewRemoteSwitch/license.txt | 674 ++++++ libraries/OneWire/OneWire.cpp | 557 +++++ libraries/OneWire/OneWire.h | 229 ++ .../DS18x20_Temperature.pde | 112 + .../examples/DS2408_Switch/DS2408_Switch.pde | 77 + .../examples/DS250x_PROM/DS250x_PROM.pde | 90 + libraries/OneWire/keywords.txt | 38 + libraries/PN532/PN532.cpp | 811 +++++++ libraries/PN532/PN532.h | 190 ++ libraries/PN532/PN532Interface.h | 56 + libraries/PN532/PN532_debug.h | 18 + libraries/PN532/README.md | 29 + .../examples/iso14443a_uid/iso14443a_uid.ino | 92 + .../mifareclassic_formatndef.ino | 180 ++ .../mifareclassic_memdump.ino | 168 ++ .../mifareclassic_ndeftoclassic.ino | 186 ++ .../mifareclassic_updatendef.ino | 158 ++ libraries/PN532/examples/p2p_raw/p2p_raw.ino | 51 + .../p2p_with_ndef_library.ino | 56 + .../PN532/examples/readMifare/readMifare.ino | 161 ++ libraries/PN532/license.txt | 27 + libraries/PN532/llcp.cpp | 282 +++ libraries/PN532/llcp.h | 72 + libraries/PN532/mac_link.cpp | 20 + libraries/PN532/mac_link.h | 51 + libraries/PN532/snep.cpp | 102 + libraries/PN532/snep.h | 49 + libraries/PN532_I2C/PN532_I2C.cpp | 180 ++ libraries/PN532_I2C/PN532_I2C.h | 40 + .../PWF_Lightning_Sensor.txt | 10 + .../PWFusion_AS3935.cpp | 414 ++++ .../PWFusion_AS3935.h | 96 + .../Examples/ByteBuffer/ByteBuffer.cpp | 272 +++ .../Examples/ByteBuffer/ByteBuffer.h | 104 + .../PinChangeInt/Examples/GetPSTR/GetPSTR.h | 21 + .../PinChangeIntExample.pde | 77 + .../PinChangeIntSpeedTest.pde | 265 +++ .../PinChangeIntTest/PinChangeIntTest.pde | 344 +++ .../PinChangeIntTest2/PinChangeIntTest2.ino | 275 +++ libraries/PinChangeInt/PinChangeInt.h | 624 ++++++ libraries/PinChangeInt/RELEASE_NOTES | 332 +++ libraries/PinChangeInt/gpl.txt | 674 ++++++ libraries/PinChangeInt/keywords.txt | 10 + libraries/PubSubClient/CHANGES.txt | 47 + libraries/PubSubClient/LICENSE.txt | 20 + libraries/PubSubClient/PubSubClient.cpp | 427 ++++ libraries/PubSubClient/PubSubClient.h | 81 + .../examples/mqtt_auth/mqtt_auth.ino | 39 + .../examples/mqtt_basic/mqtt_basic.ino | 38 + .../mqtt_publish_in_callback.ino | 61 + .../examples/mqtt_stream/mqtt_stream.ino | 58 + libraries/PubSubClient/keywords.txt | 25 + libraries/RemoteSensor/README.TXT | 62 + libraries/RemoteSensor/SensorReceiver.cpp | 221 ++ libraries/RemoteSensor/SensorReceiver.h | 107 + libraries/RemoteSensor/SensorTransmitter.cpp | 166 ++ libraries/RemoteSensor/SensorTransmitter.h | 111 + .../docs/Cresta weather station wx580m.jpg | Bin 0 -> 21472 bytes .../RemoteSensor/docs/CrestaProtocol.pdf | Bin 0 -> 164256 bytes .../RemoteSensor/docs/hardware setup.jpg | Bin 0 -> 132303 bytes .../examples/Repeater/Repeater.ino | 54 + .../ThermoHygroReceiver.ino | 54 + .../ThermoHygroTransmitter.ino | 28 + libraries/RemoteSensor/keywords.txt | 9 + libraries/RemoteSensor/license.txt | 674 ++++++ libraries/RemoteSwitch/README.TXT | 81 + libraries/RemoteSwitch/RemoteReceiver.cpp | 193 ++ libraries/RemoteSwitch/RemoteReceiver.h | 88 + libraries/RemoteSwitch/RemoteTransmitter.cpp | 306 +++ libraries/RemoteSwitch/RemoteTransmitter.h | 249 +++ ...sheet PT2262 (encoder for transmitter).pdf | Bin 0 -> 602722 bytes .../RemoteSwitch/docs/hardware setup.jpg | Bin 0 -> 132303 bytes .../examples/LightShow/LightShow.ino | 63 + .../RemoteTranslator/RemoteTranslator.ino | 58 + .../examples/Retransmitter/Retransmitter.ino | 40 + .../ShowReceivedCode/ShowReceivedCode.ino | 38 + libraries/RemoteSwitch/keywords.txt | 15 + libraries/RemoteSwitch/license.txt | 674 ++++++ libraries/RunningAverage/RunningAverage.cpp | 101 + libraries/RunningAverage/RunningAverage.h | 56 + .../examples/fillValue/fillValue.ino | 38 + .../examples/ra_MinMaxTest/ra_MinMaxTest.ino | 46 + .../examples/ra_hour/ra_hour.ino | 40 + .../examples/ra_test/ra_test.ino | 40 + libraries/RunningAverage/keywords.txt | 32 + libraries/SFE_BMP180/SFE_BMP180.cpp | 387 ++++ libraries/SFE_BMP180/SFE_BMP180.h | 121 ++ .../BMP180_altitude_example.ino | 168 ++ .../SFE_BMP180_example/SFE_BMP180_example.ino | 200 ++ libraries/SFE_BMP180/keywords.txt | 27 + libraries/SI7021/LICENSE | 339 +++ libraries/SI7021/README.md | 4 + libraries/SI7021/SI7021.cpp | 135 ++ libraries/SI7021/SI7021.h | 51 + .../SI7021/examples/readsensor/readsensor.ino | 80 + libraries/SPIFlash/README.md | 24 + libraries/SPIFlash/SPIFlash.cpp | 274 +++ libraries/SPIFlash/SPIFlash.h | 108 + .../SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino | 116 + libraries/SPIFlash/keywords.txt | 18 + libraries/SPIFlash/library.json | 12 + libraries/SimpleTimer/README.markdown | 34 + libraries/SimpleTimer/SimpleTimer.cpp | 224 ++ libraries/SimpleTimer/SimpleTimer.h | 124 ++ libraries/SimpleTimer/keywords.txt | 32 + libraries/Time/DateStrings.cpp | 80 + .../SyncArduinoClock/SyncArduinoClock.pde | 70 + .../Processing/SyncArduinoClock/readme.txt | 9 + libraries/Time/Examples/TimeGPS/TimeGPS.pde | 82 + libraries/Time/Examples/TimeNTP/TimeNTP.pde | 120 ++ libraries/Time/Examples/TimeRTC/TimeRTC.pde | 47 + .../Time/Examples/TimeRTCLog/TimeRTCLog.pde | 106 + .../Time/Examples/TimeRTCSet/TimeRTCSet.pde | 82 + .../Time/Examples/TimeSerial/TimeSerial.pde | 82 + .../TimeSerialDateStrings.pde | 80 + libraries/Time/Readme.txt | 131 ++ libraries/Time/Time.cpp | 307 +++ libraries/Time/Time.h | 126 ++ libraries/Time/keywords.txt | 33 + libraries/UIPEthernet/Dhcp.cpp | 478 +++++ libraries/UIPEthernet/Dhcp.h | 178 ++ libraries/UIPEthernet/Dns.cpp | 422 ++++ libraries/UIPEthernet/Dns.h | 41 + libraries/UIPEthernet/README | 227 ++ libraries/UIPEthernet/UIPClient.cpp | 583 +++++ libraries/UIPEthernet/UIPClient.h | 112 + libraries/UIPEthernet/UIPEthernet.cpp | 485 +++++ libraries/UIPEthernet/UIPEthernet.h | 127 ++ libraries/UIPEthernet/UIPServer.cpp | 63 + libraries/UIPEthernet/UIPServer.h | 40 + libraries/UIPEthernet/UIPUdp.cpp | 383 ++++ libraries/UIPEthernet/UIPUdp.h | 126 ++ libraries/UIPEthernet/ethernet_comp.h | 9 + .../AdvancedChatServer/AdvancedChatServer.ino | 104 + .../examples/EchoServer/EchoServer.ino | 58 + .../examples/TcpClient/TcpClient.ino | 76 + .../examples/TcpServer/TcpServer.ino | 53 + .../examples/UdpClient/UdpClient.ino | 93 + .../examples/UdpServer/UdpServer.ino | 88 + libraries/UIPEthernet/keywords.txt | 58 + libraries/UIPEthernet/library.properties | 10 + libraries/UIPEthernet/tests/perl/tcpclient.pl | 34 + libraries/UIPEthernet/tests/perl/tcpserver.pl | 53 + libraries/UIPEthernet/tests/perl/udpclient.pl | 26 + libraries/UIPEthernet/tests/perl/udpserver.pl | 40 + .../UIPEthernet/utility/Enc28J60Network.cpp | 612 ++++++ .../UIPEthernet/utility/Enc28J60Network.h | 91 + libraries/UIPEthernet/utility/clock-arch.c | 28 + libraries/UIPEthernet/utility/clock-arch.h | 27 + libraries/UIPEthernet/utility/enc28j60.h | 257 +++ libraries/UIPEthernet/utility/mempool.cpp | 168 ++ libraries/UIPEthernet/utility/mempool.h | 54 + libraries/UIPEthernet/utility/mempool_conf.h | 34 + libraries/UIPEthernet/utility/uip-conf.h | 185 ++ libraries/UIPEthernet/utility/uip.c | 1897 +++++++++++++++++ libraries/UIPEthernet/utility/uip.h | 1601 ++++++++++++++ libraries/UIPEthernet/utility/uip_arch.h | 138 ++ libraries/UIPEthernet/utility/uip_arp.c | 423 ++++ libraries/UIPEthernet/utility/uip_arp.h | 144 ++ libraries/UIPEthernet/utility/uip_clock.h | 88 + libraries/UIPEthernet/utility/uip_debug.cpp | 170 ++ libraries/UIPEthernet/utility/uip_debug.h | 18 + libraries/UIPEthernet/utility/uip_timer.c | 127 ++ libraries/UIPEthernet/utility/uip_timer.h | 86 + .../UIPEthernet/utility/uipethernet-conf.h | 29 + libraries/UIPEthernet/utility/uipopt.h | 543 +++++ libraries/UIPEthernet/utility/util.h | 13 + libraries/UTFT/DefaultFonts.c | 246 +++ .../License - CC BY-NC-SA 3.0 - Legal.pdf | Bin 0 -> 150761 bytes .../License - CC BY-NC-SA 3.0 - Summary.pdf | Bin 0 -> 109586 bytes libraries/UTFT/Tools/ImageConverter565.exe | Bin 0 -> 212480 bytes libraries/UTFT/Tools/ImgConv.exe | Bin 0 -> 25600 bytes .../Online-tool - ImageConverter 565.url | 7 + libraries/UTFT/UTFT.cpp | 1335 ++++++++++++ libraries/UTFT/UTFT.h | 275 +++ .../UTFT_Bitmap/UTFT_Bitmap.ino | 66 + .../Arduino (ARM) + Teensy/UTFT_Bitmap/icon.c | 71 + .../Arduino (ARM) + Teensy/UTFT_Bitmap/info.c | 71 + .../Arduino (ARM) + Teensy/UTFT_Bitmap/tux.c | 71 + .../UTFT_Bitmap_128x128.ino | 49 + .../UTFT_Bitmap_128x128/icon1.c | 72 + .../UTFT_Bitmap_128x128/icon2.c | 72 + .../UTFT_Bitmap_128x128/tux.c | 264 +++ .../UTFT_CPLD_PageSwitching.ino | 93 + .../UTFT_Demo_128x128_Serial.ino | 335 +++ .../UTFT_Demo_160x128_Serial.ino | 328 +++ .../UTFT_Demo_220x176/UTFT_Demo_220x176.ino | 330 +++ .../UTFT_Demo_220x176_Serial.ino | 323 +++ .../UTFT_Demo_320x240/UTFT_Demo_320x240.ino | 329 +++ .../UTFT_Demo_320x240_Serial.ino | 343 +++ .../UTFT_Demo_400x240/UTFT_Demo_400x240.ino | 331 +++ .../UTFT_Demo_480x272/UTFT_Demo_480x272.ino | 328 +++ .../UTFT_Demo_480x320/UTFT_Demo_480x320.ino | 329 +++ .../UTFT_Demo_800x480/UTFT_Demo_800x480.ino | 288 +++ .../UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino | 37 + .../UTFT_Rotate_Bitmap/biohazard.c | 264 +++ .../UTFT_Textrotation_Demo.ino | 52 + .../UTFT_ViewFont/UTFT_ViewFont.ino | 59 + .../Arduino (AVR)/UTFT_Bitmap/UTFT_Bitmap.ino | 71 + .../examples/Arduino (AVR)/UTFT_Bitmap/icon.c | 73 + .../examples/Arduino (AVR)/UTFT_Bitmap/info.c | 73 + .../examples/Arduino (AVR)/UTFT_Bitmap/tux.c | 73 + .../UTFT_Bitmap_128x128.ino | 50 + .../Arduino (AVR)/UTFT_Bitmap_128x128/icon1.c | 74 + .../Arduino (AVR)/UTFT_Bitmap_128x128/icon2.c | 74 + .../Arduino (AVR)/UTFT_Bitmap_128x128/tux.c | 266 +++ .../UTFT_CPLD_PageSwitching.ino | 93 + .../UTFT_Demo_128x128_Serial.ino | 335 +++ .../UTFT_Demo_160x128_Serial.ino | 328 +++ .../UTFT_Demo_220x176/UTFT_Demo_220x176.ino | 335 +++ .../UTFT_Demo_220x176_Serial.ino | 322 +++ .../UTFT_Demo_320x240/UTFT_Demo_320x240.ino | 334 +++ .../UTFT_Demo_320x240_Serial.ino | 354 +++ .../UTFT_Demo_400x240/UTFT_Demo_400x240.ino | 336 +++ .../UTFT_Demo_480x272/UTFT_Demo_480x272.ino | 333 +++ .../UTFT_Demo_480x320/UTFT_Demo_480x320.ino | 334 +++ .../UTFT_Demo_800x480/UTFT_Demo_800x480.ino | 293 +++ .../UTFT_Leonardo_Demo_320x240.ino | 252 +++ .../UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino | 43 + .../Arduino (AVR)/UTFT_Rotate_Bitmap/tux.c | 73 + .../UTFT_Textrotation_Demo.ino | 57 + .../UTFT_ViewFont/UTFT_ViewFont.ino | 64 + .../chipKit/UTFT_Bitmap/UTFT_Bitmap.pde | 65 + .../UTFT/examples/chipKit/UTFT_Bitmap/icon.c | 71 + .../UTFT/examples/chipKit/UTFT_Bitmap/info.c | 71 + .../UTFT/examples/chipKit/UTFT_Bitmap/tux.c | 71 + .../UTFT_Bitmap_128x128.pde | 49 + .../chipKit/UTFT_Bitmap_128x128/icon1.c | 72 + .../chipKit/UTFT_Bitmap_128x128/icon2.c | 72 + .../chipKit/UTFT_Bitmap_128x128/tux.c | 264 +++ .../UTFT_Demo_128x128_Serial.pde | 335 +++ .../UTFT_Demo_160x128_Serial.pde | 328 +++ .../UTFT_Demo_220x176/UTFT_Demo_220x176.pde | 329 +++ .../UTFT_Demo_220x176_Serial.pde | 322 +++ .../UTFT_Demo_320x240/UTFT_Demo_320x240.pde | 328 +++ .../UTFT_Demo_320x240_Serial.pde | 323 +++ .../UTFT_Demo_400x240/UTFT_Demo_400x240.pde | 330 +++ .../UTFT_Demo_480x272/UTFT_Demo_480x272.pde | 327 +++ .../UTFT_Demo_480x320/UTFT_Demo_480x320.pde | 328 +++ .../UTFT_Demo_800x480/UTFT_Demo_800x480.pde | 287 +++ .../UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.pde | 36 + .../chipKit/UTFT_Rotate_Bitmap/biohazard.c | 264 +++ .../UTFT_Textrotation_Demo.pde | 51 + .../chipKit/UTFT_ViewFont/UTFT_ViewFont.pde | 58 + libraries/UTFT/hardware/arm/HW_ARM.h | 7 + libraries/UTFT/hardware/arm/HW_ARM_defines.h | 40 + libraries/UTFT/hardware/arm/HW_MX20DX256.h | 188 ++ libraries/UTFT/hardware/arm/HW_SAM3X8E.h | 242 +++ libraries/UTFT/hardware/avr/HW_ATmega1280.h | 239 +++ libraries/UTFT/hardware/avr/HW_ATmega1284P.h | 190 ++ libraries/UTFT/hardware/avr/HW_ATmega328P.h | 171 ++ libraries/UTFT/hardware/avr/HW_ATmega32U4.h | 222 ++ libraries/UTFT/hardware/avr/HW_AVR.h | 4 + libraries/UTFT/hardware/avr/HW_AVR_defines.h | 25 + libraries/UTFT/hardware/pic32/HW_PIC32.h | 7 + .../UTFT/hardware/pic32/HW_PIC32MX320F128H.h | 174 ++ .../UTFT/hardware/pic32/HW_PIC32MX340F512H.h | 174 ++ .../UTFT/hardware/pic32/HW_PIC32MX795F512L.h | 188 ++ .../UTFT/hardware/pic32/HW_PIC32_defines.h | 26 + libraries/UTFT/keywords.txt | 148 ++ libraries/UTFT/memorysaver.h | 45 + libraries/UTFT/tft_drivers/cpld/initlcd.h | 10 + libraries/UTFT/tft_drivers/cpld/setxy.h | 7 + .../UTFT/tft_drivers/hx8340b/8/initlcd.h | 80 + libraries/UTFT/tft_drivers/hx8340b/8/setxy.h | 11 + .../UTFT/tft_drivers/hx8340b/s/initlcd.h | 71 + libraries/UTFT/tft_drivers/hx8340b/s/setxy.h | 13 + libraries/UTFT/tft_drivers/hx8347a/initlcd.h | 88 + libraries/UTFT/tft_drivers/hx8347a/setxy.h | 11 + libraries/UTFT/tft_drivers/hx8352a/initlcd.h | 131 ++ libraries/UTFT/tft_drivers/hx8352a/setxy.h | 11 + libraries/UTFT/tft_drivers/hx8353c/initlcd.h | 69 + libraries/UTFT/tft_drivers/hx8353c/setxy.h | 13 + libraries/UTFT/tft_drivers/ili9320/initlcd.h | 67 + libraries/UTFT/tft_drivers/ili9320/setxy.h | 10 + libraries/UTFT/tft_drivers/ili9325c/initlcd.h | 61 + libraries/UTFT/tft_drivers/ili9325c/setxy.h | 9 + .../UTFT/tft_drivers/ili9325d/alt/initlcd.h | 61 + .../UTFT/tft_drivers/ili9325d/alt/setxy.h | 9 + .../tft_drivers/ili9325d/default/initlcd.h | 62 + .../UTFT/tft_drivers/ili9325d/default/setxy.h | 10 + libraries/UTFT/tft_drivers/ili9327/initlcd.h | 63 + libraries/UTFT/tft_drivers/ili9327/setxy.h | 13 + .../UTFT/tft_drivers/ili9341/s4p/initlcd.h | 58 + .../UTFT/tft_drivers/ili9341/s4p/setxy.h | 13 + .../UTFT/tft_drivers/ili9341/s5p/initlcd.h | 105 + .../UTFT/tft_drivers/ili9341/s5p/setxy.h | 13 + libraries/UTFT/tft_drivers/ili9481/initlcd.h | 62 + libraries/UTFT/tft_drivers/ili9481/setxy.h | 13 + libraries/UTFT/tft_drivers/ili9486/initlcd.h | 105 + libraries/UTFT/tft_drivers/ili9486/setxy.h | 13 + libraries/UTFT/tft_drivers/pcf8833/initlcd.h | 30 + libraries/UTFT/tft_drivers/pcf8833/setxy.h | 9 + libraries/UTFT/tft_drivers/r61581/initlcd.h | 110 + libraries/UTFT/tft_drivers/r61581/setxy.h | 13 + libraries/UTFT/tft_drivers/s1d19122/initlcd.h | 183 ++ libraries/UTFT/tft_drivers/s1d19122/setxy.h | 13 + libraries/UTFT/tft_drivers/s6d0164/initlcd.h | 44 + libraries/UTFT/tft_drivers/s6d0164/setxy.h | 9 + libraries/UTFT/tft_drivers/s6d1121/initlcd.h | 47 + libraries/UTFT/tft_drivers/s6d1121/setxy.h | 9 + libraries/UTFT/tft_drivers/ssd1289/initlcd.h | 46 + libraries/UTFT/tft_drivers/ssd1289/setxy.h | 10 + .../UTFT/tft_drivers/ssd1963/480/initlcd.h | 78 + .../UTFT/tft_drivers/ssd1963/480/setxy.h | 15 + .../UTFT/tft_drivers/ssd1963/800/initlcd.h | 78 + .../UTFT/tft_drivers/ssd1963/800/setxy.h | 15 + .../UTFT/tft_drivers/ssd1963/800alt/initlcd.h | 78 + .../UTFT/tft_drivers/ssd1963/800alt/setxy.h | 15 + libraries/UTFT/tft_drivers/st7735/initlcd.h | 104 + libraries/UTFT/tft_drivers/st7735/setxy.h | 13 + libraries/UTFT/tft_drivers/st7735s/initlcd.h | 98 + libraries/UTFT/tft_drivers/st7735s/setxy.h | 13 + libraries/UTFT/version.txt | 65 + .../License - CC BY-NC-SA 3.0 - Legal.pdf | Bin 0 -> 150761 bytes .../License - CC BY-NC-SA 3.0 - Summary.pdf | Bin 0 -> 109586 bytes libraries/UTFT_Buttons/UTFT_Buttons.cpp | 269 +++ libraries/UTFT_Buttons/UTFT_Buttons.h | 84 + .../UTFT_Buttons_Bitmap_Demo.ino | 130 ++ .../examples/UTFT_Buttons_Bitmap_Demo/bird.c | 314 +++ .../examples/UTFT_Buttons_Bitmap_Demo/cat.c | 314 +++ .../examples/UTFT_Buttons_Bitmap_Demo/dog.c | 314 +++ .../UTFT_Buttons_Bitmap_Demo/monkey.c | 314 +++ .../UTFT_Buttons_Demo_320x240.ino | 125 ++ libraries/UTFT_Buttons/fonts.c | 117 + .../hardware/arm/HW_ARM_defines.h | 1 + .../hardware/avr/HW_AVR_defines.h | 1 + .../hardware/pic32/HW_PIC32_defines.h | 2 + libraries/UTFT_Buttons/keywords.txt | 22 + libraries/UTFT_Buttons/version.txt | 3 + .../License - CC BY-NC-SA 3.0 - Legal.pdf | Bin 0 -> 150761 bytes .../License - CC BY-NC-SA 3.0 - Summary.pdf | Bin 0 -> 109586 bytes libraries/UTouch/UTouch.cpp | 262 +++ libraries/UTouch/UTouch.h | 80 + libraries/UTouch/UTouchCD.h | 21 + .../UTouch_ButtonTest/UTouch_ButtonTest.ino | 253 +++ .../UTouch_Calibration/UTouch_Calibration.ino | 382 ++++ .../UTouch_QuickDraw/UTouch_QuickDraw.ino | 65 + .../UTouch_QuickPaint/UTouch_QuickPaint.ino | 172 ++ .../UTouch_ButtonTest/UTouch_ButtonTest.pde | 236 ++ .../UTouch_Calibration/UTouch_Calibration.pde | 364 ++++ .../UTouch_QuickDraw/UTouch_QuickDraw.pde | 46 + .../UTouch_QuickPaint/UTouch_QuickPaint.pde | 155 ++ libraries/UTouch/hardware/arm/HW_ARM.inc | 36 + .../UTouch/hardware/arm/HW_ARM_defines.h | 17 + libraries/UTouch/hardware/avr/HW_AVR.inc | 34 + .../UTouch/hardware/avr/HW_AVR_defines.h | 12 + libraries/UTouch/hardware/pic32/HW_PIC32.inc | 36 + .../UTouch/hardware/pic32/HW_PIC32_defines.h | 12 + libraries/UTouch/keywords.txt | 17 + libraries/UTouch/version.txt | 18 + libraries/readme.txt | 1 + libraries/sha204/sha204_lib_return_codes.h | 48 + libraries/sha204/sha204_library.cpp | 832 ++++++++ libraries/sha204/sha204_library.h | 321 +++ 476 files changed, 69941 insertions(+) create mode 100644 libraries/MySensors/drivers/pubsubclient/.gitignore create mode 100644 libraries/MySensors/drivers/pubsubclient/.travis.yml create mode 100644 libraries/MySensors/drivers/pubsubclient/CHANGES.txt create mode 100644 libraries/MySensors/drivers/pubsubclient/LICENSE.txt create mode 100644 libraries/MySensors/drivers/pubsubclient/README.md create mode 100644 libraries/MySensors/drivers/pubsubclient/examples/mqtt_auth/mqtt_auth.ino create mode 100644 libraries/MySensors/drivers/pubsubclient/examples/mqtt_basic/mqtt_basic.ino create mode 100644 libraries/MySensors/drivers/pubsubclient/examples/mqtt_esp8266/mqtt_esp8266.ino create mode 100644 libraries/MySensors/drivers/pubsubclient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino create mode 100644 libraries/MySensors/drivers/pubsubclient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino create mode 100644 libraries/MySensors/drivers/pubsubclient/examples/mqtt_stream/mqtt_stream.ino create mode 100644 libraries/MySensors/drivers/pubsubclient/keywords.txt create mode 100644 libraries/MySensors/drivers/pubsubclient/library.properties create mode 100644 libraries/MySensors/drivers/pubsubclient/src/PubSubClient.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/src/PubSubClient.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/.gitignore create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/Makefile create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/README.md create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/connect_spec.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/keepalive_spec.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/Arduino.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/Client.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/lib/trace.h create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/publish_spec.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/receive_spec.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/src/subscribe_spec.cpp create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/testcases/__init__.py create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_basic.py create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_publish_in_callback.py create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/testcases/settings.py create mode 100644 libraries/MySensors/drivers/pubsubclient/tests/testsuite.py create mode 100644 libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino create mode 100644 libraries/MySensors/examples/BatteryPoweredSensor/BatteryPoweredSensor.ino create mode 100644 libraries/MySensors/examples/BinarySwitchSensor/BinarySwitchSensor.ino create mode 100644 libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino create mode 100644 libraries/MySensors/examples/CO2Sensor/CO2Sensor.ino create mode 100644 libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino create mode 100644 libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino create mode 100644 libraries/MySensors/examples/DimmableLEDActuator/DimmableLEDActuator.ino create mode 100644 libraries/MySensors/examples/DimmableLight/DimmableLight.ino create mode 100644 libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino create mode 100644 libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino create mode 100644 libraries/MySensors/examples/DustSensor/DustSensor.ino create mode 100644 libraries/MySensors/examples/DustSensorDSM/DustSensorDSM.ino create mode 100644 libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino create mode 100644 libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino create mode 100644 libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h create mode 100644 libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino create mode 100644 libraries/MySensors/examples/HumiditySensor/HumiditySensor.ino create mode 100644 libraries/MySensors/examples/IrSensor/IrSensor.ino create mode 100644 libraries/MySensors/examples/IrrigationController/IrrigationController.ino create mode 100644 libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino create mode 100644 libraries/MySensors/examples/LightSensor/LightSensor.ino create mode 100644 libraries/MySensors/examples/LightningSensor/LightningSensor.ino create mode 100644 libraries/MySensors/examples/MAX6875TemperatureSensor/MAX6875TemperatureSensor.ino create mode 100644 libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino create mode 100644 libraries/MySensors/examples/MQTTClientGateway/MyMQTTClient.h create mode 100644 libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino create mode 100644 libraries/MySensors/examples/MQTTGateway/MyMQTT.h create mode 100644 libraries/MySensors/examples/MockMySensors/MockMySensors.ino create mode 100644 libraries/MySensors/examples/MockMySensors/README.md create mode 100644 libraries/MySensors/examples/MotionSensor/MotionSensor.ino create mode 100644 libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino create mode 100644 libraries/MySensors/examples/PingPongSensor/MYSLog.h create mode 100644 libraries/MySensors/examples/PingPongSensor/PingPongSensor.ino create mode 100644 libraries/MySensors/examples/PressureSensor/PressureSensor.ino create mode 100644 libraries/MySensors/examples/RF433MhzSensor/RF433MhzSensor.ino create mode 100644 libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino create mode 100644 libraries/MySensors/examples/RGB-3D/RGB-3D.ino create mode 100644 libraries/MySensors/examples/RainGauge/RainGauge.ino create mode 100644 libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino create mode 100644 libraries/MySensors/examples/RelayActuator/RelayActuator.ino create mode 100644 libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino create mode 100644 libraries/MySensors/examples/RepeaterNode/RepeaterNode.ino create mode 100644 libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino create mode 100644 libraries/MySensors/examples/SecureActuator/SecureActuator.ino create mode 100644 libraries/MySensors/examples/SensebenderBlink/SensebenderBlink.ino create mode 100644 libraries/MySensors/examples/SensebenderMicro/SensebenderMicro.ino create mode 100644 libraries/MySensors/examples/SerialGateway/SerialGateway.ino create mode 100644 libraries/MySensors/examples/ServoActuator/ServoActuator.ino create mode 100644 libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino create mode 100644 libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino create mode 100644 libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino create mode 100644 libraries/MySensors/examples/TouchDisplaySceneControllerSensor/ArialNumFontPlus.c create mode 100644 libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino create mode 100644 libraries/MySensors/examples/TouchDisplaySceneControllerSensor/Ubuntu.c create mode 100644 libraries/MySensors/examples/TouchDisplaySceneControllerSensor/arial_bold.c create mode 100644 libraries/MySensors/examples/TouchDisplaySceneControllerSensor/logo.c create mode 100644 libraries/MySensors/examples/UVSensor/UVSensor.ino create mode 100644 libraries/MySensors/examples/VibrationSensor/VibrationSensor.ino create mode 100644 libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino create mode 100644 libraries/MySensors/keywords.txt create mode 100644 libraries/NewPing/NewPing.cpp create mode 100644 libraries/NewPing/NewPing.h create mode 100644 libraries/NewPing/examples/NewPing15Sensors/NewPing15Sensors.pde create mode 100644 libraries/NewPing/examples/NewPingEventTimer/NewPingEventTimer.pde create mode 100644 libraries/NewPing/examples/NewPingExample/NewPingExample.ino create mode 100644 libraries/NewPing/examples/TimerExample/TimerExample.pde create mode 100644 libraries/NewPing/keywords.txt create mode 100644 libraries/NewRemoteSwitch/NewRemoteReceiver.cpp create mode 100644 libraries/NewRemoteSwitch/NewRemoteReceiver.h create mode 100644 libraries/NewRemoteSwitch/NewRemoteTransmitter.cpp create mode 100644 libraries/NewRemoteSwitch/NewRemoteTransmitter.h create mode 100644 libraries/NewRemoteSwitch/README.TXT create mode 100644 libraries/NewRemoteSwitch/docs/hardware setup.jpg create mode 100644 libraries/NewRemoteSwitch/docs/new kaku protocol.txt create mode 100644 libraries/NewRemoteSwitch/examples/LearnCode/LearnCode.ino create mode 100644 libraries/NewRemoteSwitch/examples/LightShow/LightShow.ino create mode 100644 libraries/NewRemoteSwitch/examples/Retransmitter/Retransmitter.ino create mode 100644 libraries/NewRemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino create mode 100644 libraries/NewRemoteSwitch/keywords.txt create mode 100644 libraries/NewRemoteSwitch/license.txt 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/PN532/PN532.cpp create mode 100644 libraries/PN532/PN532.h create mode 100644 libraries/PN532/PN532Interface.h create mode 100644 libraries/PN532/PN532_debug.h create mode 100644 libraries/PN532/README.md create mode 100644 libraries/PN532/examples/iso14443a_uid/iso14443a_uid.ino create mode 100644 libraries/PN532/examples/mifareclassic_formatndef/mifareclassic_formatndef.ino create mode 100644 libraries/PN532/examples/mifareclassic_memdump/mifareclassic_memdump.ino create mode 100644 libraries/PN532/examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.ino create mode 100644 libraries/PN532/examples/mifareclassic_updatendef/mifareclassic_updatendef.ino create mode 100644 libraries/PN532/examples/p2p_raw/p2p_raw.ino create mode 100644 libraries/PN532/examples/p2p_with_ndef_library/p2p_with_ndef_library.ino create mode 100644 libraries/PN532/examples/readMifare/readMifare.ino create mode 100644 libraries/PN532/license.txt create mode 100644 libraries/PN532/llcp.cpp create mode 100644 libraries/PN532/llcp.h create mode 100644 libraries/PN532/mac_link.cpp create mode 100644 libraries/PN532/mac_link.h create mode 100644 libraries/PN532/snep.cpp create mode 100644 libraries/PN532/snep.h create mode 100644 libraries/PN532_I2C/PN532_I2C.cpp create mode 100644 libraries/PN532_I2C/PN532_I2C.h create mode 100644 libraries/PWF_AS3935_Lightning_Sensor/PWF_Lightning_Sensor.txt create mode 100644 libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp create mode 100644 libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.h create mode 100644 libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.cpp create mode 100644 libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.h create mode 100644 libraries/PinChangeInt/Examples/GetPSTR/GetPSTR.h create mode 100644 libraries/PinChangeInt/Examples/PinChangeIntExample/PinChangeIntExample.pde create mode 100644 libraries/PinChangeInt/Examples/PinChangeIntSpeedTest/PinChangeIntSpeedTest.pde create mode 100644 libraries/PinChangeInt/Examples/PinChangeIntTest/PinChangeIntTest.pde create mode 100644 libraries/PinChangeInt/Examples/PinChangeIntTest2/PinChangeIntTest2.ino create mode 100644 libraries/PinChangeInt/PinChangeInt.h create mode 100644 libraries/PinChangeInt/RELEASE_NOTES create mode 100644 libraries/PinChangeInt/gpl.txt create mode 100644 libraries/PinChangeInt/keywords.txt create mode 100755 libraries/PubSubClient/CHANGES.txt create mode 100755 libraries/PubSubClient/LICENSE.txt create mode 100755 libraries/PubSubClient/PubSubClient.cpp create mode 100755 libraries/PubSubClient/PubSubClient.h create mode 100755 libraries/PubSubClient/examples/mqtt_auth/mqtt_auth.ino create mode 100755 libraries/PubSubClient/examples/mqtt_basic/mqtt_basic.ino create mode 100755 libraries/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino create mode 100755 libraries/PubSubClient/examples/mqtt_stream/mqtt_stream.ino create mode 100755 libraries/PubSubClient/keywords.txt create mode 100644 libraries/RemoteSensor/README.TXT create mode 100644 libraries/RemoteSensor/SensorReceiver.cpp create mode 100644 libraries/RemoteSensor/SensorReceiver.h create mode 100644 libraries/RemoteSensor/SensorTransmitter.cpp create mode 100644 libraries/RemoteSensor/SensorTransmitter.h create mode 100644 libraries/RemoteSensor/docs/Cresta weather station wx580m.jpg create mode 100644 libraries/RemoteSensor/docs/CrestaProtocol.pdf create mode 100644 libraries/RemoteSensor/docs/hardware setup.jpg create mode 100644 libraries/RemoteSensor/examples/Repeater/Repeater.ino create mode 100644 libraries/RemoteSensor/examples/ThermoHygroReceiver/ThermoHygroReceiver.ino create mode 100644 libraries/RemoteSensor/examples/ThermoHygroTransmitter/ThermoHygroTransmitter.ino create mode 100644 libraries/RemoteSensor/keywords.txt create mode 100644 libraries/RemoteSensor/license.txt create mode 100644 libraries/RemoteSwitch/README.TXT create mode 100644 libraries/RemoteSwitch/RemoteReceiver.cpp create mode 100644 libraries/RemoteSwitch/RemoteReceiver.h create mode 100644 libraries/RemoteSwitch/RemoteTransmitter.cpp create mode 100644 libraries/RemoteSwitch/RemoteTransmitter.h create mode 100644 libraries/RemoteSwitch/docs/Datasheet PT2262 (encoder for transmitter).pdf create mode 100644 libraries/RemoteSwitch/docs/hardware setup.jpg create mode 100644 libraries/RemoteSwitch/examples/LightShow/LightShow.ino create mode 100644 libraries/RemoteSwitch/examples/RemoteTranslator/RemoteTranslator.ino create mode 100644 libraries/RemoteSwitch/examples/Retransmitter/Retransmitter.ino create mode 100644 libraries/RemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino create mode 100644 libraries/RemoteSwitch/keywords.txt create mode 100644 libraries/RemoteSwitch/license.txt create mode 100644 libraries/RunningAverage/RunningAverage.cpp create mode 100644 libraries/RunningAverage/RunningAverage.h create mode 100644 libraries/RunningAverage/examples/fillValue/fillValue.ino create mode 100644 libraries/RunningAverage/examples/ra_MinMaxTest/ra_MinMaxTest.ino create mode 100644 libraries/RunningAverage/examples/ra_hour/ra_hour.ino create mode 100644 libraries/RunningAverage/examples/ra_test/ra_test.ino create mode 100644 libraries/RunningAverage/keywords.txt create mode 100644 libraries/SFE_BMP180/SFE_BMP180.cpp create mode 100644 libraries/SFE_BMP180/SFE_BMP180.h create mode 100644 libraries/SFE_BMP180/examples/BMP180_altitude_example/BMP180_altitude_example.ino create mode 100644 libraries/SFE_BMP180/examples/SFE_BMP180_example/SFE_BMP180_example.ino create mode 100644 libraries/SFE_BMP180/keywords.txt create mode 100644 libraries/SI7021/LICENSE create mode 100644 libraries/SI7021/README.md create mode 100644 libraries/SI7021/SI7021.cpp create mode 100644 libraries/SI7021/SI7021.h create mode 100644 libraries/SI7021/examples/readsensor/readsensor.ino create mode 100644 libraries/SPIFlash/README.md create mode 100644 libraries/SPIFlash/SPIFlash.cpp create mode 100644 libraries/SPIFlash/SPIFlash.h create mode 100644 libraries/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino create mode 100644 libraries/SPIFlash/keywords.txt create mode 100644 libraries/SPIFlash/library.json create mode 100644 libraries/SimpleTimer/README.markdown create mode 100644 libraries/SimpleTimer/SimpleTimer.cpp create mode 100644 libraries/SimpleTimer/SimpleTimer.h create mode 100644 libraries/SimpleTimer/keywords.txt create mode 100644 libraries/Time/DateStrings.cpp create mode 100644 libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde create mode 100644 libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt create mode 100644 libraries/Time/Examples/TimeGPS/TimeGPS.pde create mode 100644 libraries/Time/Examples/TimeNTP/TimeNTP.pde create mode 100644 libraries/Time/Examples/TimeRTC/TimeRTC.pde create mode 100644 libraries/Time/Examples/TimeRTCLog/TimeRTCLog.pde create mode 100644 libraries/Time/Examples/TimeRTCSet/TimeRTCSet.pde create mode 100644 libraries/Time/Examples/TimeSerial/TimeSerial.pde create mode 100644 libraries/Time/Examples/TimeSerialDateStrings/TimeSerialDateStrings.pde create mode 100644 libraries/Time/Readme.txt create mode 100644 libraries/Time/Time.cpp create mode 100644 libraries/Time/Time.h create mode 100644 libraries/Time/keywords.txt create mode 100644 libraries/UIPEthernet/Dhcp.cpp create mode 100644 libraries/UIPEthernet/Dhcp.h create mode 100644 libraries/UIPEthernet/Dns.cpp create mode 100644 libraries/UIPEthernet/Dns.h create mode 100644 libraries/UIPEthernet/README create mode 100644 libraries/UIPEthernet/UIPClient.cpp create mode 100644 libraries/UIPEthernet/UIPClient.h create mode 100644 libraries/UIPEthernet/UIPEthernet.cpp create mode 100644 libraries/UIPEthernet/UIPEthernet.h create mode 100644 libraries/UIPEthernet/UIPServer.cpp create mode 100644 libraries/UIPEthernet/UIPServer.h create mode 100644 libraries/UIPEthernet/UIPUdp.cpp create mode 100644 libraries/UIPEthernet/UIPUdp.h create mode 100644 libraries/UIPEthernet/ethernet_comp.h create mode 100644 libraries/UIPEthernet/examples/AdvancedChatServer/AdvancedChatServer.ino create mode 100644 libraries/UIPEthernet/examples/EchoServer/EchoServer.ino create mode 100644 libraries/UIPEthernet/examples/TcpClient/TcpClient.ino create mode 100644 libraries/UIPEthernet/examples/TcpServer/TcpServer.ino create mode 100644 libraries/UIPEthernet/examples/UdpClient/UdpClient.ino create mode 100644 libraries/UIPEthernet/examples/UdpServer/UdpServer.ino create mode 100644 libraries/UIPEthernet/keywords.txt create mode 100644 libraries/UIPEthernet/library.properties create mode 100644 libraries/UIPEthernet/tests/perl/tcpclient.pl create mode 100644 libraries/UIPEthernet/tests/perl/tcpserver.pl create mode 100644 libraries/UIPEthernet/tests/perl/udpclient.pl create mode 100644 libraries/UIPEthernet/tests/perl/udpserver.pl create mode 100644 libraries/UIPEthernet/utility/Enc28J60Network.cpp create mode 100644 libraries/UIPEthernet/utility/Enc28J60Network.h create mode 100644 libraries/UIPEthernet/utility/clock-arch.c create mode 100644 libraries/UIPEthernet/utility/clock-arch.h create mode 100644 libraries/UIPEthernet/utility/enc28j60.h create mode 100644 libraries/UIPEthernet/utility/mempool.cpp create mode 100644 libraries/UIPEthernet/utility/mempool.h create mode 100644 libraries/UIPEthernet/utility/mempool_conf.h create mode 100644 libraries/UIPEthernet/utility/uip-conf.h create mode 100644 libraries/UIPEthernet/utility/uip.c create mode 100644 libraries/UIPEthernet/utility/uip.h create mode 100644 libraries/UIPEthernet/utility/uip_arch.h create mode 100644 libraries/UIPEthernet/utility/uip_arp.c create mode 100644 libraries/UIPEthernet/utility/uip_arp.h create mode 100644 libraries/UIPEthernet/utility/uip_clock.h create mode 100644 libraries/UIPEthernet/utility/uip_debug.cpp create mode 100644 libraries/UIPEthernet/utility/uip_debug.h create mode 100644 libraries/UIPEthernet/utility/uip_timer.c create mode 100644 libraries/UIPEthernet/utility/uip_timer.h create mode 100644 libraries/UIPEthernet/utility/uipethernet-conf.h create mode 100644 libraries/UIPEthernet/utility/uipopt.h create mode 100644 libraries/UIPEthernet/utility/util.h create mode 100644 libraries/UTFT/DefaultFonts.c create mode 100644 libraries/UTFT/License - CC BY-NC-SA 3.0 - Legal.pdf create mode 100644 libraries/UTFT/License - CC BY-NC-SA 3.0 - Summary.pdf create mode 100644 libraries/UTFT/Tools/ImageConverter565.exe create mode 100644 libraries/UTFT/Tools/ImgConv.exe create mode 100644 libraries/UTFT/Tools/Online-tool - ImageConverter 565.url create mode 100644 libraries/UTFT/UTFT.cpp create mode 100644 libraries/UTFT/UTFT.h create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/UTFT_Bitmap.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/icon.c create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/info.c create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/tux.c create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon1.c create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon2.c create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/tux.c create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176/UTFT_Demo_220x176.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240/UTFT_Demo_320x240.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_400x240/UTFT_Demo_400x240.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x272/UTFT_Demo_480x272.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x320/UTFT_Demo_480x320.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_800x480/UTFT_Demo_800x480.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/biohazard.c create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino create mode 100644 libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_ViewFont/UTFT_ViewFont.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/UTFT_Bitmap.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/icon.c create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/info.c create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/tux.c create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon1.c create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon2.c create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/tux.c create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176/UTFT_Demo_220x176.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240/UTFT_Demo_320x240.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_400x240/UTFT_Demo_400x240.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x272/UTFT_Demo_480x272.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x320/UTFT_Demo_480x320.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_800x480/UTFT_Demo_800x480.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Leonardo_Demo_320x240/UTFT_Leonardo_Demo_320x240.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/tux.c create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino create mode 100644 libraries/UTFT/examples/Arduino (AVR)/UTFT_ViewFont/UTFT_ViewFont.ino create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap/UTFT_Bitmap.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap/icon.c create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap/info.c create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap/tux.c create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon1.c create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon2.c create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/tux.c create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_220x176/UTFT_Demo_220x176.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_320x240/UTFT_Demo_320x240.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_400x240/UTFT_Demo_400x240.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_480x272/UTFT_Demo_480x272.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_480x320/UTFT_Demo_480x320.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Demo_800x480/UTFT_Demo_800x480.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/biohazard.c create mode 100644 libraries/UTFT/examples/chipKit/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.pde create mode 100644 libraries/UTFT/examples/chipKit/UTFT_ViewFont/UTFT_ViewFont.pde create mode 100644 libraries/UTFT/hardware/arm/HW_ARM.h create mode 100644 libraries/UTFT/hardware/arm/HW_ARM_defines.h create mode 100644 libraries/UTFT/hardware/arm/HW_MX20DX256.h create mode 100644 libraries/UTFT/hardware/arm/HW_SAM3X8E.h create mode 100644 libraries/UTFT/hardware/avr/HW_ATmega1280.h create mode 100644 libraries/UTFT/hardware/avr/HW_ATmega1284P.h create mode 100644 libraries/UTFT/hardware/avr/HW_ATmega328P.h create mode 100644 libraries/UTFT/hardware/avr/HW_ATmega32U4.h create mode 100644 libraries/UTFT/hardware/avr/HW_AVR.h create mode 100644 libraries/UTFT/hardware/avr/HW_AVR_defines.h create mode 100644 libraries/UTFT/hardware/pic32/HW_PIC32.h create mode 100644 libraries/UTFT/hardware/pic32/HW_PIC32MX320F128H.h create mode 100644 libraries/UTFT/hardware/pic32/HW_PIC32MX340F512H.h create mode 100644 libraries/UTFT/hardware/pic32/HW_PIC32MX795F512L.h create mode 100644 libraries/UTFT/hardware/pic32/HW_PIC32_defines.h create mode 100644 libraries/UTFT/keywords.txt create mode 100644 libraries/UTFT/memorysaver.h create mode 100644 libraries/UTFT/tft_drivers/cpld/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/cpld/setxy.h create mode 100644 libraries/UTFT/tft_drivers/hx8340b/8/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/hx8340b/8/setxy.h create mode 100644 libraries/UTFT/tft_drivers/hx8340b/s/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/hx8340b/s/setxy.h create mode 100644 libraries/UTFT/tft_drivers/hx8347a/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/hx8347a/setxy.h create mode 100644 libraries/UTFT/tft_drivers/hx8352a/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/hx8352a/setxy.h create mode 100644 libraries/UTFT/tft_drivers/hx8353c/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/hx8353c/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9320/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9320/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9325c/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9325c/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9325d/alt/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9325d/alt/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9325d/default/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9325d/default/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9327/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9327/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9341/s4p/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9341/s4p/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9341/s5p/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9341/s5p/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9481/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9481/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ili9486/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ili9486/setxy.h create mode 100644 libraries/UTFT/tft_drivers/pcf8833/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/pcf8833/setxy.h create mode 100644 libraries/UTFT/tft_drivers/r61581/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/r61581/setxy.h create mode 100644 libraries/UTFT/tft_drivers/s1d19122/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/s1d19122/setxy.h create mode 100644 libraries/UTFT/tft_drivers/s6d0164/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/s6d0164/setxy.h create mode 100644 libraries/UTFT/tft_drivers/s6d1121/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/s6d1121/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ssd1289/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ssd1289/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ssd1963/480/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ssd1963/480/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ssd1963/800/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ssd1963/800/setxy.h create mode 100644 libraries/UTFT/tft_drivers/ssd1963/800alt/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/ssd1963/800alt/setxy.h create mode 100644 libraries/UTFT/tft_drivers/st7735/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/st7735/setxy.h create mode 100644 libraries/UTFT/tft_drivers/st7735s/initlcd.h create mode 100644 libraries/UTFT/tft_drivers/st7735s/setxy.h create mode 100644 libraries/UTFT/version.txt create mode 100644 libraries/UTFT_Buttons/License - CC BY-NC-SA 3.0 - Legal.pdf create mode 100644 libraries/UTFT_Buttons/License - CC BY-NC-SA 3.0 - Summary.pdf create mode 100644 libraries/UTFT_Buttons/UTFT_Buttons.cpp create mode 100644 libraries/UTFT_Buttons/UTFT_Buttons.h create mode 100644 libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/UTFT_Buttons_Bitmap_Demo.ino create mode 100644 libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/bird.c create mode 100644 libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/cat.c create mode 100644 libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/dog.c create mode 100644 libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/monkey.c create mode 100644 libraries/UTFT_Buttons/examples/UTFT_Buttons_Demo_320x240/UTFT_Buttons_Demo_320x240.ino create mode 100644 libraries/UTFT_Buttons/fonts.c create mode 100644 libraries/UTFT_Buttons/hardware/arm/HW_ARM_defines.h create mode 100644 libraries/UTFT_Buttons/hardware/avr/HW_AVR_defines.h create mode 100644 libraries/UTFT_Buttons/hardware/pic32/HW_PIC32_defines.h create mode 100644 libraries/UTFT_Buttons/keywords.txt create mode 100644 libraries/UTFT_Buttons/version.txt create mode 100644 libraries/UTouch/License - CC BY-NC-SA 3.0 - Legal.pdf create mode 100644 libraries/UTouch/License - CC BY-NC-SA 3.0 - Summary.pdf create mode 100644 libraries/UTouch/UTouch.cpp create mode 100644 libraries/UTouch/UTouch.h create mode 100644 libraries/UTouch/UTouchCD.h create mode 100644 libraries/UTouch/examples/Arduino/UTouch_ButtonTest/UTouch_ButtonTest.ino create mode 100644 libraries/UTouch/examples/Arduino/UTouch_Calibration/UTouch_Calibration.ino create mode 100644 libraries/UTouch/examples/Arduino/UTouch_QuickDraw/UTouch_QuickDraw.ino create mode 100644 libraries/UTouch/examples/Arduino/UTouch_QuickPaint/UTouch_QuickPaint.ino create mode 100644 libraries/UTouch/examples/chipKit/UTouch_ButtonTest/UTouch_ButtonTest.pde create mode 100644 libraries/UTouch/examples/chipKit/UTouch_Calibration/UTouch_Calibration.pde create mode 100644 libraries/UTouch/examples/chipKit/UTouch_QuickDraw/UTouch_QuickDraw.pde create mode 100644 libraries/UTouch/examples/chipKit/UTouch_QuickPaint/UTouch_QuickPaint.pde create mode 100644 libraries/UTouch/hardware/arm/HW_ARM.inc create mode 100644 libraries/UTouch/hardware/arm/HW_ARM_defines.h create mode 100644 libraries/UTouch/hardware/avr/HW_AVR.inc create mode 100644 libraries/UTouch/hardware/avr/HW_AVR_defines.h create mode 100644 libraries/UTouch/hardware/pic32/HW_PIC32.inc create mode 100644 libraries/UTouch/hardware/pic32/HW_PIC32_defines.h create mode 100644 libraries/UTouch/keywords.txt create mode 100644 libraries/UTouch/version.txt create mode 100644 libraries/readme.txt create mode 100644 libraries/sha204/sha204_lib_return_codes.h create mode 100644 libraries/sha204/sha204_library.cpp create mode 100644 libraries/sha204/sha204_library.h diff --git a/libraries/MySensors/drivers/pubsubclient/.gitignore b/libraries/MySensors/drivers/pubsubclient/.gitignore new file mode 100644 index 0000000..1c3ba18 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/.gitignore @@ -0,0 +1 @@ +tests/bin diff --git a/libraries/MySensors/drivers/pubsubclient/.travis.yml b/libraries/MySensors/drivers/pubsubclient/.travis.yml new file mode 100644 index 0000000..e7b28cb --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/.travis.yml @@ -0,0 +1,7 @@ +sudo: false +language: cpp +compiler: + - g++ +script: cd tests && make && make test +os: + - linux diff --git a/libraries/MySensors/drivers/pubsubclient/CHANGES.txt b/libraries/MySensors/drivers/pubsubclient/CHANGES.txt new file mode 100644 index 0000000..5202dda --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/CHANGES.txt @@ -0,0 +1,63 @@ +2.3 + * Add publish(topic,payload,retained) function + +2.2 + * Change code layout to match Arduino Library reqs + +2.1 + * Add MAX_TRANSFER_SIZE def to chunk messages if needed + * Reject topic/payloads that exceed MQTT_MAX_PACKET_SIZE + +2.0 + * Add (and default to) MQTT 3.1.1 support + * Fix PROGMEM handling for Intel Galileo/ESP8266 + * Add overloaded constructors for convenience + * Add chainable setters for server/callback/client/stream + * Add state function to return connack return code + +1.9 + * Do not split MQTT packets over multiple calls to _client->write() + * API change: All constructors now require an instance of Client + to be passed in. + * Fixed example to match 1.8 api changes - dpslwk + * Added username/password support - WilHall + * Added publish_P - publishes messages from PROGMEM - jobytaffey + +1.8 + * KeepAlive interval is configurable in PubSubClient.h + * Maximum packet size is configurable in PubSubClient.h + * API change: Return boolean rather than int from various functions + * API change: Length parameter in message callback changed + from int to unsigned int + * Various internal tidy-ups around types +1.7 + * Improved keepalive handling + * Updated to the Arduino-1.0 API +1.6 + * Added the ability to publish a retained message + +1.5 + * Added default constructor + * Fixed compile error when used with arduino-0021 or later + +1.4 + * Fixed connection lost handling + +1.3 + * Fixed packet reading bug in PubSubClient.readPacket + +1.2 + * Fixed compile error when used with arduino-0016 or later + + +1.1 + * Reduced size of library + * Added support for Will messages + * Clarified licensing - see LICENSE.txt + + +1.0 + * Only Quality of Service (QOS) 0 messaging is supported + * The maximum message size, including header, is 128 bytes + * The keepalive interval is set to 30 seconds + * No support for Will messages diff --git a/libraries/MySensors/drivers/pubsubclient/LICENSE.txt b/libraries/MySensors/drivers/pubsubclient/LICENSE.txt new file mode 100644 index 0000000..217df35 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2015 Nicholas O'Leary + +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. diff --git a/libraries/MySensors/drivers/pubsubclient/README.md b/libraries/MySensors/drivers/pubsubclient/README.md new file mode 100644 index 0000000..8317691 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/README.md @@ -0,0 +1,47 @@ +# Arduino Client for MQTT + +This library provides a client for doing simple publish/subscribe messaging with +a server that supports MQTT. + +## Examples + +The library comes with a number of example sketches. See File > Examples > PubSubClient +within the Arduino application. + +Full API documentation is available here: http://pubsubclient.knolleary.net + +## Limitations + + - It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1. + - The maximum message size, including header, is **128 bytes** by default. This + is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h`. + - The keepalive interval is set to 15 seconds by default. This is configurable + via `MQTT_KEEPALIVE` in `PubSubClient.h`. + - The client uses MQTT 3.1.1 by default. It can be changed to use MQTT 3.1 by + changing value of `MQTT_VERSION` in `PubSubClient.h`. + + +## Compatible Hardware + +The library uses the Arduino Ethernet Client api for interacting with the +underlying network hardware. This means it Just Works with a growing number of +boards and shields, including: + + - Arduino Ethernet + - Arduino Ethernet Shield + - Arduino YUN – use the included `YunClient` in place of `EthernetClient`, and + be sure to do a `Bridge.begin()` first + - Arduino WiFi Shield - if you want to send packets > 90 bytes with this shield, + enable the `MQTT_MAX_TRANSFER_SIZE` define in `PubSubClient.h`. + - Sparkfun WiFly Shield – [library](https://github.com/dpslwk/WiFly) + - TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library) + - Intel Galileo/Edison + - ESP8266 + +The library cannot currently be used with hardware based on the ENC28J60 chip – +such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an +[alternative library](https://github.com/njh/NanodeMQTT) available. + +## License + +This code is released under the MIT License. diff --git a/libraries/MySensors/drivers/pubsubclient/examples/mqtt_auth/mqtt_auth.ino b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_auth/mqtt_auth.ino new file mode 100644 index 0000000..e9f7b18 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_auth/mqtt_auth.ino @@ -0,0 +1,43 @@ +/* + Basic MQTT example with Authentication + + - connects to an MQTT server, providing username + and password + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +void setup() +{ + Ethernet.begin(mac, ip); + // Note - the default maximum packet size is 128 bytes. If the + // combined length of clientId, username and password exceed this, + // you will need to increase the value of MQTT_MAX_PACKET_SIZE in + // PubSubClient.h + + if (client.connect("arduinoClient", "testuser", "testpass")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} diff --git a/libraries/MySensors/drivers/pubsubclient/examples/mqtt_basic/mqtt_basic.ino b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_basic/mqtt_basic.ino new file mode 100644 index 0000000..f545ade --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_basic/mqtt_basic.ino @@ -0,0 +1,77 @@ +/* + Basic MQTT example + + This sketch demonstrates the basic capabilities of the library. + It connects to an MQTT server then: + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic", printing out any messages + it receives. NB - it assumes the received payloads are strings not binary + + It will reconnect to the server if the connection is lost using a blocking + reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to + achieve the same result without blocking the main loop. + +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (int i=0;i Preferences -> Additional Boards Manager URLs": + http://arduino.esp8266.com/stable/package_esp8266com_index.json + - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" + - Select your ESP8266 in "Tools -> Board" + +*/ + +#include +#include + +// Update these with values suitable for your network. + +const char* ssid = "........"; +const char* password = "........"; +const char* mqtt_server = "broker.mqtt-dashboard.com"; + +WiFiClient espClient; +PubSubClient client(espClient); +long lastMsg = 0; +char msg[50]; +int value = 0; + +void setup() { + pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(mqtt_server, 1883); + client.setCallback(callback); +} + +void setup_wifi() { + + delay(10); + // We start by connecting to a WiFi network + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); + + // Switch on the LED if an 1 was received as first character + if ((char)payload[0] == '1') { + digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level + // but actually the LED is on; this is because + // it is acive low on the ESP-01) + } else { + digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH + } + +} + +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + if (client.connect("ESP8266Client")) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.publish("outTopic", "hello world"); + // ... and resubscribe + client.subscribe("inTopic"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} +void loop() { + + if (!client.connected()) { + reconnect(); + } + client.loop(); + + long now = millis(); + if (now - lastMsg > 2000) { + lastMsg = now; + ++value; + snprintf (msg, 75, "hello world #%ld", value); + Serial.print("Publish message: "); + Serial.println(msg); + client.publish("outTopic", msg); + } +} diff --git a/libraries/MySensors/drivers/pubsubclient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino new file mode 100644 index 0000000..42afb2a --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino @@ -0,0 +1,60 @@ +/* + Publishing in the callback + + - connects to an MQTT server + - subscribes to the topic "inTopic" + - when a message is received, republishes it to "outTopic" + + This example shows how to publish messages within the + callback function. The callback function header needs to + be declared before the PubSubClient constructor and the + actual callback defined afterwards. + This ensures the client reference in the callback function + is valid. + +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +// Callback function header +void callback(char* topic, byte* payload, unsigned int length); + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +// Callback function +void callback(char* topic, byte* payload, unsigned int length) { + // In order to republish this payload, a copy must be made + // as the orignal payload buffer will be overwritten whilst + // constructing the PUBLISH packet. + + // Allocate the correct amount of memory for the payload copy + byte* p = (byte*)malloc(length); + // Copy the payload to the new buffer + memcpy(p,payload,length); + client.publish("outTopic", p, length); + // Free the memory + free(p); +} + +void setup() +{ + + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} diff --git a/libraries/MySensors/drivers/pubsubclient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino new file mode 100644 index 0000000..080b739 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino @@ -0,0 +1,67 @@ +/* + Reconnecting MQTT example - non-blocking + + This sketch demonstrates how to keep the client connected + using a non-blocking reconnect function. If the client loses + its connection, it attempts to reconnect every 5 seconds + without blocking the main loop. + +*/ + +#include +#include +#include + +// Update these with values suitable for your hardware/network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(ethClient); + +long lastReconnectAttempt = 0; + +boolean reconnect() { + if (client.connect("arduinoClient")) { + // Once connected, publish an announcement... + client.publish("outTopic","hello world"); + // ... and resubscribe + client.subscribe("inTopic"); + } + return client.connected(); +} + +void setup() +{ + client.setServer(server, 1883); + client.setCallback(callback); + + Ethernet.begin(mac, ip); + delay(1500); + lastReconnectAttempt = 0; +} + + +void loop() +{ + if (!client.connected()) { + long now = millis(); + if (now - lastReconnectAttempt > 5000) { + lastReconnectAttempt = now; + // Attempt to reconnect + if (reconnect()) { + lastReconnectAttempt = 0; + } + } + } else { + // Client connected + + client.loop(); + } + +} diff --git a/libraries/MySensors/drivers/pubsubclient/examples/mqtt_stream/mqtt_stream.ino b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_stream/mqtt_stream.ino new file mode 100644 index 0000000..67c2287 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/examples/mqtt_stream/mqtt_stream.ino @@ -0,0 +1,57 @@ +/* + Example of using a Stream object to store the message payload + + Uses SRAM library: https://github.com/ennui2342/arduino-sram + but could use any Stream based class such as SD + + - connects to an MQTT server + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +SRAM sram(4, SRAM_1024); + +void callback(char* topic, byte* payload, unsigned int length) { + sram.seek(1); + + // do something with the message + for(uint8_t i=0; i +maintainer=Nick O'Leary +sentence=A client library for MQTT messaging. +paragraph=MQTT is a lightweight messaging protocol ideal for small devices. This library allows you to send and receive MQTT messages. It supports the latest MQTT 3.1.1 protocol and can be configured to use the older MQTT 3.1 if needed. It supports all Arduino Ethernet Client compatible hardware, including the Intel Galileo/Edison, ESP8266 and TI CC3000. +category=Communication +url=http://pubsubclient.knolleary.net +architectures=* diff --git a/libraries/MySensors/drivers/pubsubclient/src/PubSubClient.cpp b/libraries/MySensors/drivers/pubsubclient/src/PubSubClient.cpp new file mode 100644 index 0000000..1a50236 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/src/PubSubClient.cpp @@ -0,0 +1,571 @@ +/* + PubSubClient.cpp - A simple client for MQTT. + Nick O'Leary + http://knolleary.net +*/ + +#include "PubSubClient.h" +#include "Arduino.h" + +PubSubClient::PubSubClient() { + this->_state = MQTT_DISCONNECTED; + this->_client = NULL; + this->stream = NULL; + setCallback(NULL); +} + +PubSubClient::PubSubClient(Client& client) { + this->_state = MQTT_DISCONNECTED; + setClient(client); + this->stream = NULL; +} + +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(addr, port); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(addr,port); + setClient(client); + setStream(stream); +} +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(addr, port); + setCallback(callback); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(addr,port); + setCallback(callback); + setClient(client); + setStream(stream); +} + +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(ip, port); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(ip,port); + setClient(client); + setStream(stream); +} +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(ip, port); + setCallback(callback); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(ip,port); + setCallback(callback); + setClient(client); + setStream(stream); +} + +PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setClient(client); + setStream(stream); +} +PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setCallback(callback); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setCallback(callback); + setClient(client); + setStream(stream); +} + +boolean PubSubClient::connect(const char *id) { + return connect(id,NULL,NULL,0,0,0,0); +} + +boolean PubSubClient::connect(const char *id, const char *user, const char *pass) { + return connect(id,user,pass,0,0,0,0); +} + +boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { + return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); +} + +boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { + if (!connected()) { + int result = 0; + + if (domain != NULL) { + result = _client->connect(this->domain, this->port); + } else { + result = _client->connect(this->ip, this->port); + } + if (result) { + nextMsgId = 1; + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + unsigned int j; + +#if MQTT_VERSION == MQTT_VERSION_3_1 + uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION}; +#define MQTT_HEADER_VERSION_LENGTH 9 +#elif MQTT_VERSION == MQTT_VERSION_3_1_1 + uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION}; +#define MQTT_HEADER_VERSION_LENGTH 7 +#endif + for (j = 0;j>1); + } + } + + buffer[length++] = v; + + buffer[length++] = ((MQTT_KEEPALIVE) >> 8); + buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); + length = writeString(id,buffer,length); + if (willTopic) { + length = writeString(willTopic,buffer,length); + length = writeString(willMessage,buffer,length); + } + + if(user != NULL) { + length = writeString(user,buffer,length); + if(pass != NULL) { + length = writeString(pass,buffer,length); + } + } + + write(MQTTCONNECT,buffer,length-5); + + lastInActivity = lastOutActivity = millis(); + + while (!_client->available()) { + unsigned long t = millis(); + if (t-lastInActivity > MQTT_KEEPALIVE*1000UL) { + _state = MQTT_CONNECTION_TIMEOUT; + _client->stop(); + return false; + } + } + uint8_t llen; + uint16_t len = readPacket(&llen); + + if (len == 4) { + if (buffer[3] == 0) { + lastInActivity = millis(); + pingOutstanding = false; + _state = MQTT_CONNECTED; + return true; + } else { + _state = buffer[3]; + } + } + _client->stop(); + } else { + _state = MQTT_CONNECT_FAILED; + } + return false; + } + return true; +} + +uint8_t PubSubClient::readByte() { + while(!_client->available()) {} + return _client->read(); +} + +uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { + uint16_t len = 0; + buffer[len++] = readByte(); + bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; + uint32_t multiplier = 1; + uint16_t length = 0; + uint8_t digit = 0; + uint16_t skip = 0; + uint8_t start = 0; + + do { + digit = readByte(); + buffer[len++] = digit; + length += (digit & 127) * multiplier; + multiplier *= 128; + } while ((digit & 128) != 0); + *lengthLength = len-1; + + if (isPublish) { + // Read in topic length to calculate bytes to skip over for Stream writing + buffer[len++] = readByte(); + buffer[len++] = readByte(); + skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; + start = 2; + if (buffer[0]&MQTTQOS1) { + // skip message id + skip += 2; + } + } + + for (uint16_t i = start;istream) { + if (isPublish && len-*lengthLength-2>skip) { + this->stream->write(digit); + } + } + if (len < MQTT_MAX_PACKET_SIZE) { + buffer[len] = digit; + } + len++; + } + + if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { + len = 0; // This will cause the packet to be ignored. + } + + return len; +} + +boolean PubSubClient::loop() { + if (connected()) { + unsigned long t = millis(); + if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { + if (pingOutstanding) { + this->_state = MQTT_CONNECTION_TIMEOUT; + _client->stop(); + return false; + } else { + buffer[0] = MQTTPINGREQ; + buffer[1] = 0; + _client->write(buffer,2); + lastOutActivity = t; + lastInActivity = t; + pingOutstanding = true; + } + } + if (_client->available()) { + uint8_t llen; + uint16_t len = readPacket(&llen); + uint16_t msgId = 0; + uint8_t *payload; + if (len > 0) { + lastInActivity = t; + uint8_t type = buffer[0]&0xF0; + if (type == MQTTPUBLISH) { + if (callback) { + uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; + char topic[tl+1]; + for (uint16_t i=0;i0 + if ((buffer[0]&0x06) == MQTTQOS1) { + msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; + payload = buffer+llen+3+tl+2; + callback(topic,payload,len-llen-3-tl-2); + + buffer[0] = MQTTPUBACK; + buffer[1] = 2; + buffer[2] = (msgId >> 8); + buffer[3] = (msgId & 0xFF); + _client->write(buffer,4); + lastOutActivity = t; + + } else { + payload = buffer+llen+3+tl; + callback(topic,payload,len-llen-3-tl); + } + } + } else if (type == MQTTPINGREQ) { + buffer[0] = MQTTPINGRESP; + buffer[1] = 0; + _client->write(buffer,2); + } else if (type == MQTTPINGRESP) { + pingOutstanding = false; + } + } + } + return true; + } + return false; +} + +boolean PubSubClient::publish(const char* topic, const char* payload) { + return publish(topic,(const uint8_t*)payload,strlen(payload),false); +} + +boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) { + return publish(topic,(const uint8_t*)payload,strlen(payload),retained); +} + +boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) { + return publish(topic, payload, plength, false); +} + +boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { + if (connected()) { + if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) { + // Too long + return false; + } + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + length = writeString(topic,buffer,length); + uint16_t i; + for (i=0;i 0) { + digit |= 0x80; + } + buffer[pos++] = digit; + llen++; + } while(len>0); + + pos = writeString(topic,buffer,pos); + + rc += _client->write(buffer,pos); + + for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); + } + + lastOutActivity = millis(); + + return rc == tlen + 4 + plength; +} + +boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { + uint8_t lenBuf[4]; + uint8_t llen = 0; + uint8_t digit; + uint8_t pos = 0; + uint8_t rc; + uint16_t len = length; + do { + digit = len % 128; + len = len / 128; + if (len > 0) { + digit |= 0x80; + } + lenBuf[pos++] = digit; + llen++; + } while(len>0); + + buf[4-llen] = header; + for (int i=0;i 0) && result) { + bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining; + rc = _client->write(writeBuf,bytesToWrite); + result = (rc == bytesToWrite); + bytesRemaining -= rc; + writeBuf += rc; + } + return result; +#else + rc = _client->write(buf+(4-llen),length+1+llen); + lastOutActivity = millis(); + return (rc == 1+llen+length); +#endif +} + +boolean PubSubClient::subscribe(const char* topic) { + return subscribe(topic, 0); +} + +boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { + if (qos < 0 || qos > 1) { + return false; + } + if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + // Too long + return false; + } + if (connected()) { + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString((char*)topic, buffer,length); + buffer[length++] = qos; + return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +boolean PubSubClient::unsubscribe(const char* topic) { + if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + // Too long + return false; + } + if (connected()) { + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, buffer,length); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +void PubSubClient::disconnect() { + buffer[0] = MQTTDISCONNECT; + buffer[1] = 0; + _client->write(buffer,2); + _state = MQTT_DISCONNECTED; + _client->stop(); + lastInActivity = lastOutActivity = millis(); +} + +uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) { + const char* idp = string; + uint16_t i = 0; + pos += 2; + while (*idp) { + buf[pos++] = *idp++; + i++; + } + buf[pos-i-2] = (i >> 8); + buf[pos-i-1] = (i & 0xFF); + return pos; +} + + +boolean PubSubClient::connected() { + boolean rc; + if (_client == NULL ) { + rc = false; + } else { + rc = (int)_client->connected(); + if (!rc) { + if (this->_state == MQTT_CONNECTED) { + this->_state = MQTT_CONNECTION_LOST; + _client->flush(); + _client->stop(); + } + } + } + return rc; +} + +PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { + IPAddress addr(ip[0],ip[1],ip[2],ip[3]); + return setServer(addr,port); +} + +PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) { + this->ip = ip; + this->port = port; + this->domain = NULL; + return *this; +} + +PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) { + this->domain = domain; + this->port = port; + return *this; +} + +PubSubClient& PubSubClient::setCallback(void(*callback)(char*,uint8_t*,unsigned int)){ + this->callback = callback; + return *this; +} + +PubSubClient& PubSubClient::setClient(Client& client){ + this->_client = &client; + return *this; +} + +PubSubClient& PubSubClient::setStream(Stream& stream){ + this->stream = &stream; + return *this; +} + +int PubSubClient::state() { + return this->_state; +} diff --git a/libraries/MySensors/drivers/pubsubclient/src/PubSubClient.h b/libraries/MySensors/drivers/pubsubclient/src/PubSubClient.h new file mode 100644 index 0000000..ece2d4b --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/src/PubSubClient.h @@ -0,0 +1,127 @@ +/* + PubSubClient.h - A simple client for MQTT. + Nick O'Leary + http://knolleary.net +*/ + +#ifndef PubSubClient_h +#define PubSubClient_h + +#include +#include "IPAddress.h" +#include "Client.h" +#include "Stream.h" + +#define MQTT_VERSION_3_1 3 +#define MQTT_VERSION_3_1_1 4 + +// MQTT_VERSION : Pick the version +//#define MQTT_VERSION MQTT_VERSION_3_1 +#define MQTT_VERSION MQTT_VERSION_3_1_1 + +// MQTT_MAX_PACKET_SIZE : Maximum packet size +#define MQTT_MAX_PACKET_SIZE 128 + +// MQTT_KEEPALIVE : keepAlive interval in Seconds +#define MQTT_KEEPALIVE 15 + +// MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client +// in each write call. Needed for the Arduino Wifi Shield. Leave undefined to +// pass the entire MQTT packet in each write call. +//#define MQTT_MAX_TRANSFER_SIZE 80 + +// Possible values for client.state() +#define MQTT_CONNECTION_TIMEOUT -4 +#define MQTT_CONNECTION_LOST -3 +#define MQTT_CONNECT_FAILED -2 +#define MQTT_DISCONNECTED -1 +#define MQTT_CONNECTED 0 +#define MQTT_CONNECT_BAD_PROTOCOL 1 +#define MQTT_CONNECT_BAD_CLIENT_ID 2 +#define MQTT_CONNECT_UNAVAILABLE 3 +#define MQTT_CONNECT_BAD_CREDENTIALS 4 +#define MQTT_CONNECT_UNAUTHORIZED 5 + +#define MQTTCONNECT 1 << 4 // Client request to connect to Server +#define MQTTCONNACK 2 << 4 // Connect Acknowledgment +#define MQTTPUBLISH 3 << 4 // Publish message +#define MQTTPUBACK 4 << 4 // Publish Acknowledgment +#define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1) +#define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2) +#define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3) +#define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request +#define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment +#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request +#define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment +#define MQTTPINGREQ 12 << 4 // PING Request +#define MQTTPINGRESP 13 << 4 // PING Response +#define MQTTDISCONNECT 14 << 4 // Client is Disconnecting +#define MQTTReserved 15 << 4 // Reserved + +#define MQTTQOS0 (0 << 1) +#define MQTTQOS1 (1 << 1) +#define MQTTQOS2 (2 << 1) + +#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*,uint8_t*,unsigned int) + +class PubSubClient { +private: + Client* _client; + uint8_t buffer[MQTT_MAX_PACKET_SIZE]; + uint16_t nextMsgId; + unsigned long lastOutActivity; + unsigned long lastInActivity; + bool pingOutstanding; + MQTT_CALLBACK_SIGNATURE; + uint16_t readPacket(uint8_t*); + uint8_t readByte(); + boolean write(uint8_t header, uint8_t* buf, uint16_t length); + uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); + IPAddress ip; + const char* domain; + uint16_t port; + Stream* stream; + int _state; +public: + PubSubClient(); + PubSubClient(Client& client); + PubSubClient(IPAddress, uint16_t, Client& client); + PubSubClient(IPAddress, uint16_t, Client& client, Stream&); + PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); + PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + PubSubClient(uint8_t *, uint16_t, Client& client); + PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); + PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); + PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + PubSubClient(const char*, uint16_t, Client& client); + PubSubClient(const char*, uint16_t, Client& client, Stream&); + PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); + PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + + PubSubClient& setServer(IPAddress ip, uint16_t port); + PubSubClient& setServer(uint8_t * ip, uint16_t port); + PubSubClient& setServer(const char * domain, uint16_t port); + PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); + PubSubClient& setClient(Client& client); + PubSubClient& setStream(Stream& stream); + + boolean connect(const char* id); + boolean connect(const char* id, const char* user, const char* pass); + boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); + boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); + void disconnect(); + boolean publish(const char* topic, const char* payload); + boolean publish(const char* topic, const char* payload, boolean retained); + boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); + boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + boolean subscribe(const char* topic); + boolean subscribe(const char* topic, uint8_t qos); + boolean unsubscribe(const char* topic); + boolean loop(); + boolean connected(); + int state(); +}; + + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/.gitignore b/libraries/MySensors/drivers/pubsubclient/tests/.gitignore new file mode 100644 index 0000000..215de78 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/.gitignore @@ -0,0 +1,4 @@ +.build +tmpbin +logs +*.pyc diff --git a/libraries/MySensors/drivers/pubsubclient/tests/Makefile b/libraries/MySensors/drivers/pubsubclient/tests/Makefile new file mode 100644 index 0000000..1f71636 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/Makefile @@ -0,0 +1,25 @@ +SRC_PATH=./src +OUT_PATH=./bin +TEST_SRC=$(wildcard ${SRC_PATH}/*_spec.cpp) +TEST_BIN= $(TEST_SRC:${SRC_PATH}/%.cpp=${OUT_PATH}/%) +VPATH=${SRC_PATH} +SHIM_FILES=${SRC_PATH}/lib/*.cpp +PSC_FILE=../src/PubSubClient.cpp +CC=g++ +CFLAGS=-I${SRC_PATH}/lib -I../src + +all: $(TEST_BIN) + +${OUT_PATH}/%: ${SRC_PATH}/%.cpp ${PSC_FILE} ${SHIM_FILES} + mkdir -p ${OUT_PATH} + ${CC} ${CFLAGS} $^ -o $@ + +clean: + @rm -rf ${OUT_PATH} + +test: + @bin/connect_spec + @bin/publish_spec + @bin/receive_spec + @bin/subscribe_spec + @bin/keepalive_spec diff --git a/libraries/MySensors/drivers/pubsubclient/tests/README.md b/libraries/MySensors/drivers/pubsubclient/tests/README.md new file mode 100644 index 0000000..e5700a6 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/README.md @@ -0,0 +1,93 @@ +# Arduino Client for MQTT Test Suite + +This is a regression test suite for the `PubSubClient` library. + +There are two parts: + + - Tests that can be compiled and run on any machine + - Tests that build the example sketches using the Arduino IDE + + +It is a work-in-progress and is subject to complete refactoring as the whim takes +me. + + +## Local tests + +These are a set of executables that can be run to test specific areas of functionality. +They do not require a real Arduino to be attached, nor the use of the Arduino IDE. + +The tests include a set of mock files to stub out the parts of the Arduino environment the library +depends on. + +### Dependencies + + - g++ + +### Running + +Build the tests using the provided `Makefile`: + + $ make + +This will create a set of executables in `./bin/`. Run each of these executables to test the corresponding functionality. + +*Note:* the `connect_spec` and `keepalive_spec` tests involve testing keepalive timers so naturally take a few minutes to run through. + +## Arduino tests + +*Note:* INO Tool doesn't currently play nicely with Arduino 1.5. This has broken this test suite. + +Without a suitable arduino plugged in, the test suite will only check the +example sketches compile cleanly against the library. + +With an arduino plugged in, each sketch that has a corresponding python +test case is built, uploaded and then the tests run. + +### Dependencies + + - Python 2.7+ + - [INO Tool](http://inotool.org/) - this provides command-line build/upload of Arduino sketches + +### Running + +The test suite _does not_ run an MQTT server - it is assumed to be running already. + + $ python testsuite.py + +A summary of activity is printed to the console. More comprehensive logs are written +to the `logs` directory. + +### What it does + +For each sketch in the library's `examples` directory, e.g. `mqtt_basic.ino`, the suite looks for a matching test case +`testcases/mqtt_basic.py`. + +The test case must follow these conventions: + - sub-class `unittest.TestCase` + - provide the class methods `setUpClass` and `tearDownClass` (TODO: make this optional) + - all test method names begin with `test_` + +The suite will call the `setUpClass` method _before_ uploading the sketch. This +allows any test setup to be performed before the sketch runs - such as connecting +a client and subscribing to topics. + + +### Settings + +The file `testcases/settings.py` is used to config the test environment. + + - `server_ip` - the IP address of the broker the client should connect to (the broker port is assumed to be 1883). + - `arduino_ip` - the IP address the arduino should use (when not testing DHCP). + +Before each sketch is compiled, these values are automatically substituted in. To +do this, the suite looks for lines that _start_ with the following: + + byte server[] = { + byte ip[] = { + +and replaces them with the appropriate values. + + + + diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/connect_spec.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/connect_spec.cpp new file mode 100644 index 0000000..69f1864 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/connect_spec.cpp @@ -0,0 +1,256 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + + +int test_connect_fails_no_network() { + IT("fails to connect if underlying client doesn't connect"); + ShimClient shimClient; + shimClient.setAllowConnect(false); + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_FALSE(rc); + int state = client.state(); + IS_TRUE(state == MQTT_CONNECT_FAILED); + END_IT +} + +int test_connect_fails_on_no_response() { + IT("fails to connect if no response received after 15 seconds"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_FALSE(rc); + int state = client.state(); + IS_TRUE(state == MQTT_CONNECTION_TIMEOUT); + END_IT +} + +int test_connect_properly_formatted() { + IT("sends a properly formatted connect packet and succeeds"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + byte expectServer[] = { 172, 16, 0, 2 }; + shimClient.expectConnect(expectServer,1883); + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + END_IT +} + +int test_connect_properly_formatted_hostname() { + IT("accepts a hostname"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + shimClient.expectConnect((char* const)"localhost",1883); + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client((char* const)"localhost", 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_connect_fails_on_bad_rc() { + IT("fails to connect if a bad return code is received"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + byte connack[] = { 0x20, 0x02, 0x00, 0x01 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_FALSE(rc); + + int state = client.state(); + IS_TRUE(state == 0x01); + + END_IT +} + +int test_connect_accepts_username_password() { + IT("accepts a username and password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = { 0x10,0x24,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x4,0x70,0x61,0x73,0x73}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_accepts_username_no_password() { + IT("accepts a username but no password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = { 0x10,0x1e,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x82,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x20); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",0); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_ignores_password_no_username() { + IT("ignores a password but no username"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",0,(char*)"pass"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_with_will() { + IT("accepts a will"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = {0x10,0x30,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xe,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x9,0x77,0x69,0x6c,0x6c,0x54,0x6f,0x70,0x69,0x63,0x0,0xb,0x77,0x69,0x6c,0x6c,0x4d,0x65,0x73,0x73,0x61,0x67,0x65}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x32); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"willTopic",1,0,(char*)"willMessage"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_with_will_username_password() { + IT("accepts a will, username and password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = {0x10,0x40,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xce,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x9,0x77,0x69,0x6c,0x6c,0x54,0x6f,0x70,0x69,0x63,0x0,0xb,0x77,0x69,0x6c,0x6c,0x4d,0x65,0x73,0x73,0x61,0x67,0x65,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x8,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x42); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"password",(char*)"willTopic",1,0,(char*)"willMessage"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_disconnect_connect() { + IT("connects, disconnects and connects again"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + byte expectServer[] = { 172, 16, 0, 2 }; + shimClient.expectConnect(expectServer,1883); + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + + int state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + byte disconnect[] = {0xE0,0x00}; + shimClient.expect(disconnect,2); + + client.disconnect(); + + IS_FALSE(client.connected()); + IS_FALSE(shimClient.connected()); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + shimClient.expect(connect,28); + shimClient.respond(connack,4); + rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + END_IT +} + +int main() +{ + SUITE("Connect"); + test_connect_fails_no_network(); + test_connect_fails_on_no_response(); + + test_connect_properly_formatted(); + test_connect_accepts_username_password(); + test_connect_fails_on_bad_rc(); + test_connect_properly_formatted_hostname(); + + test_connect_accepts_username_no_password(); + test_connect_ignores_password_no_username(); + test_connect_with_will(); + test_connect_with_will_username_password(); + test_connect_disconnect_connect(); + FINISH +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/keepalive_spec.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/keepalive_spec.cpp new file mode 100644 index 0000000..ea643cf --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/keepalive_spec.cpp @@ -0,0 +1,185 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" +#include + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + + +int test_keepalive_pings_idle() { + IT("keeps an idle connection alive (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + byte pingresp[] = { 0xD0,0x0 }; + shimClient.respond(pingresp,2); + + for (int i = 0; i < 50; i++) { + sleep(1); + if ( i == 15 || i == 31 || i == 47) { + shimClient.expect(pingreq,2); + shimClient.respond(pingresp,2); + } + rc = client.loop(); + IS_TRUE(rc); + } + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_keepalive_pings_with_outbound_qos0() { + IT("keeps a connection alive that only sends qos0 (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + + for (int i = 0; i < 50; i++) { + TRACE(i<<":"); + shimClient.expect(publish,16); + rc = client.publish((char*)"topic",(char*)"payload"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + sleep(1); + if ( i == 15 || i == 31 || i == 47) { + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + byte pingresp[] = { 0xD0,0x0 }; + shimClient.respond(pingresp,2); + } + rc = client.loop(); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + } + + END_IT +} + +int test_keepalive_pings_with_inbound_qos0() { + IT("keeps a connection alive that only receives qos0 (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + + for (int i = 0; i < 50; i++) { + TRACE(i<<":"); + sleep(1); + if ( i == 15 || i == 31 || i == 47) { + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + byte pingresp[] = { 0xD0,0x0 }; + shimClient.respond(pingresp,2); + } + shimClient.respond(publish,16); + rc = client.loop(); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + } + + END_IT +} + +int test_keepalive_no_pings_inbound_qos1() { + IT("does not send pings for connections with inbound qos1 (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + byte puback[] = {0x40,0x2,0x12,0x34}; + + for (int i = 0; i < 50; i++) { + shimClient.respond(publish,18); + shimClient.expect(puback,4); + sleep(1); + rc = client.loop(); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + } + + END_IT +} + +int test_keepalive_disconnects_hung() { + IT("disconnects a hung connection (takes 30 seconds)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + + for (int i = 0; i < 32; i++) { + sleep(1); + rc = client.loop(); + } + IS_FALSE(rc); + + int state = client.state(); + IS_TRUE(state == MQTT_CONNECTION_TIMEOUT); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int main() +{ + SUITE("Keep-alive"); + test_keepalive_pings_idle(); + test_keepalive_pings_with_outbound_qos0(); + test_keepalive_pings_with_inbound_qos0(); + test_keepalive_no_pings_inbound_qos1(); + test_keepalive_disconnects_hung(); + + FINISH +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Arduino.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Arduino.h new file mode 100644 index 0000000..c675280 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Arduino.h @@ -0,0 +1,23 @@ +#ifndef Arduino_h +#define Arduino_h + +#include +#include +#include +#include + + +extern "C"{ + typedef uint8_t byte ; + typedef uint8_t boolean ; + + /* sketch */ + extern void setup( void ) ; + extern void loop( void ) ; + uint32_t millis( void ); +} + +#define PROGMEM +#define pgm_read_byte_near(x) *(x) + +#endif // Arduino_h diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.cpp new file mode 100644 index 0000000..a72bf65 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.cpp @@ -0,0 +1,50 @@ +#include "BDDTest.h" +#include "trace.h" +#include +#include +#include +#include + +int testCount = 0; +int testPasses = 0; +const char* testDescription; + +std::list failureList; + +void bddtest_suite(const char* name) { + LOG(name << "\n"); +} + +int bddtest_test(const char* file, int line, const char* assertion, int result) { + if (!result) { + LOG("✗\n"); + std::ostringstream os; + os << " ! "<::iterator it = failureList.begin(); it != failureList.end(); it++) { + LOG("\n"); + LOG(*it); + LOG("\n"); + } + + LOG(std::dec << testPasses << "/" << testCount << " tests passed\n\n"); + if (testPasses == testCount) { + return 0; + } + return 1; +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.h new file mode 100644 index 0000000..1197fdd --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/BDDTest.h @@ -0,0 +1,23 @@ +#ifndef bddtest_h +#define bddtest_h + +void bddtest_suite(const char* name); +int bddtest_test(const char*, int, const char*, int); +void bddtest_start(const char*); +void bddtest_end(); +int bddtest_summary(); + +#define SUITE(x) { bddtest_suite(x); } +#define TEST(x) { if (!bddtest_test(__FILE__, __LINE__, #x, (x))) return false; } + +#define IT(x) { bddtest_start(x); } +#define END_IT { bddtest_end();return true;} + +#define FINISH { return bddtest_summary(); } + +#define IS_TRUE(x) TEST(x) +#define IS_FALSE(x) TEST(!(x)) +#define IS_EQUAL(x,y) TEST(x==y) +#define IS_NOT_EQUAL(x,y) TEST(x!=y) + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.cpp new file mode 100644 index 0000000..59a2fbb --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.cpp @@ -0,0 +1,30 @@ +#include "Buffer.h" +#include "Arduino.h" + +Buffer::Buffer() { +} + +Buffer::Buffer(uint8_t* buf, size_t size) { + this->add(buf,size); +} +bool Buffer::available() { + return this->pos < this->length; +} + +uint8_t Buffer::next() { + if (this->available()) { + return this->buffer[this->pos++]; + } + return 0; +} + +void Buffer::reset() { + this->pos = 0; +} + +void Buffer::add(uint8_t* buf, size_t size) { + uint16_t i = 0; + for (;ibuffer[this->length++] = buf[i]; + } +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.h new file mode 100644 index 0000000..f448cad --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Buffer.h @@ -0,0 +1,23 @@ +#ifndef buffer_h +#define buffer_h + +#include "Arduino.h" + +class Buffer { +private: + uint8_t buffer[1024]; + uint16_t pos; + uint16_t length; + +public: + Buffer(); + Buffer(uint8_t* buf, size_t size); + + virtual bool available(); + virtual uint8_t next(); + virtual void reset(); + + virtual void add(uint8_t* buf, size_t size); +}; + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Client.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Client.h new file mode 100644 index 0000000..9e18c07 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Client.h @@ -0,0 +1,21 @@ +#ifndef client_h +#define client_h +#include "IPAddress.h" + +class Client { +public: + virtual int connect(IPAddress ip, uint16_t port) =0; + virtual int connect(const char *host, uint16_t port) =0; + virtual size_t write(uint8_t) =0; + virtual size_t write(const uint8_t *buf, size_t size) =0; + virtual int available() = 0; + virtual int read() = 0; + virtual int read(uint8_t *buf, size_t size) = 0; + virtual int peek() = 0; + virtual void flush() = 0; + virtual void stop() = 0; + virtual uint8_t connected() = 0; + virtual operator bool() = 0; +}; + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.cpp new file mode 100644 index 0000000..610ff4c --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.cpp @@ -0,0 +1,44 @@ + +#include +#include + +IPAddress::IPAddress() +{ + memset(_address, 0, sizeof(_address)); +} + +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +{ + _address[0] = first_octet; + _address[1] = second_octet; + _address[2] = third_octet; + _address[3] = fourth_octet; +} + +IPAddress::IPAddress(uint32_t address) +{ + memcpy(_address, &address, sizeof(_address)); +} + +IPAddress::IPAddress(const uint8_t *address) +{ + memcpy(_address, address, sizeof(_address)); +} + +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + memcpy(_address, address, sizeof(_address)); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + memcpy(_address, (const uint8_t *)&address, sizeof(_address)); + return *this; +} + +bool IPAddress::operator==(const uint8_t* addr) +{ + return memcmp(addr, _address, sizeof(_address)) == 0; +} + diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.h new file mode 100644 index 0000000..e75a8fe --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/IPAddress.h @@ -0,0 +1,72 @@ +/* + * + * MIT License: + * Copyright (c) 2011 Adrian McEwen + * 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. + * + * adrianm@mcqn.com 1/1/2011 + */ + +#ifndef IPAddress_h +#define IPAddress_h + + +// A class to make it easier to handle and pass around IP addresses + +class IPAddress { +private: + uint8_t _address[4]; // IPv4 address + // Access the raw byte array containing the address. Because this returns a pointer + // to the internal structure rather than a copy of the address this function should only + // be used when you know that the usage of the returned uint8_t* will be transient and not + // stored. + uint8_t* raw_address() { return _address; }; + +public: + // Constructors + IPAddress(); + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + IPAddress(uint32_t address); + IPAddress(const uint8_t *address); + + // Overloaded cast operator to allow IPAddress objects to be used where a pointer + // to a four-byte uint8_t array is expected + operator uint32_t() { return *((uint32_t*)_address); }; + bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); }; + bool operator==(const uint8_t* addr); + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const { return _address[index]; }; + uint8_t& operator[](int index) { return _address[index]; }; + + // Overloaded copy operators to allow initialisation of IPAddress objects from other types + IPAddress& operator=(const uint8_t *address); + IPAddress& operator=(uint32_t address); + + + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; +}; + + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.cpp new file mode 100644 index 0000000..f70115f --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.cpp @@ -0,0 +1,153 @@ +#include "ShimClient.h" +#include "trace.h" +#include +#include +#include + +extern "C" { + uint32_t millis(void) { + return time(0)*1000; + } +} + +ShimClient::ShimClient() { + this->responseBuffer = new Buffer(); + this->expectBuffer = new Buffer(); + this->_allowConnect = true; + this->_connected = false; + this->_error = false; + this->expectAnything = true; + this->_received = 0; + this->_expectedPort = 0; +} + +int ShimClient::connect(IPAddress ip, uint16_t port) { + if (this->_allowConnect) { + this->_connected = true; + } + if (this->_expectedPort !=0) { + // if (memcmp(ip,this->_expectedIP,4) != 0) { + // TRACE( "ip mismatch\n"); + // this->_error = true; + // } + if (port != this->_expectedPort) { + TRACE( "port mismatch\n"); + this->_error = true; + } + } + return this->_connected; +} +int ShimClient::connect(const char *host, uint16_t port) { + if (this->_allowConnect) { + this->_connected = true; + } + if (this->_expectedPort !=0) { + if (strcmp(host,this->_expectedHost) != 0) { + TRACE( "host mismatch\n"); + this->_error = true; + } + if (port != this->_expectedPort) { + TRACE( "port mismatch\n"); + this->_error = true; + } + + } + return this->_connected; +} +size_t ShimClient::write(uint8_t b) { + this->_received += 1; + TRACE(std::hex << (unsigned int)b); + if (!this->expectAnything) { + if (this->expectBuffer->available()) { + uint8_t expected = this->expectBuffer->next(); + if (expected != b) { + this->_error = true; + TRACE("!=" << (unsigned int)expected); + } + } else { + this->_error = true; + } + } + TRACE("\n"<< std::dec); + return 1; +} +size_t ShimClient::write(const uint8_t *buf, size_t size) { + this->_received += size; + TRACE( "[" << std::dec << (unsigned int)(size) << "] "); + uint16_t i=0; + for (;i0) { + TRACE(":"); + } + TRACE(std::hex << (unsigned int)(buf[i])); + + if (!this->expectAnything) { + if (this->expectBuffer->available()) { + uint8_t expected = this->expectBuffer->next(); + if (expected != buf[i]) { + this->_error = true; + TRACE("!=" << (unsigned int)expected); + } + } else { + this->_error = true; + } + } + } + TRACE("\n"<responseBuffer->available(); +} +int ShimClient::read() { return this->responseBuffer->next(); } +int ShimClient::read(uint8_t *buf, size_t size) { + uint16_t i = 0; + for (;iread(); + } + return size; +} +int ShimClient::peek() { return 0; } +void ShimClient::flush() {} +void ShimClient::stop() { + this->setConnected(false); +} +uint8_t ShimClient::connected() { return this->_connected; } +ShimClient::operator bool() { return true; } + + +ShimClient* ShimClient::respond(uint8_t *buf, size_t size) { + this->responseBuffer->add(buf,size); + return this; +} + +ShimClient* ShimClient::expect(uint8_t *buf, size_t size) { + this->expectAnything = false; + this->expectBuffer->add(buf,size); + return this; +} + +void ShimClient::setConnected(bool b) { + this->_connected = b; +} +void ShimClient::setAllowConnect(bool b) { + this->_allowConnect = b; +} + +bool ShimClient::error() { + return this->_error; +} + +uint16_t ShimClient::received() { + return this->_received; +} + +void ShimClient::expectConnect(IPAddress ip, uint16_t port) { + this->_expectedIP = ip; + this->_expectedPort = port; +} + +void ShimClient::expectConnect(const char *host, uint16_t port) { + this->_expectedHost = host; + this->_expectedPort = port; +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.h new file mode 100644 index 0000000..2e3f874 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/ShimClient.h @@ -0,0 +1,51 @@ +#ifndef shimclient_h +#define shimclient_h + +#include "Arduino.h" +#include "Client.h" +#include "IPAddress.h" +#include "Buffer.h" + + +class ShimClient : public Client { +private: + Buffer* responseBuffer; + Buffer* expectBuffer; + bool _allowConnect; + bool _connected; + bool expectAnything; + bool _error; + uint16_t _received; + IPAddress _expectedIP; + uint16_t _expectedPort; + const char* _expectedHost; + +public: + ShimClient(); + virtual int connect(IPAddress ip, uint16_t port); + virtual int connect(const char *host, uint16_t port); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int available(); + virtual int read(); + virtual int read(uint8_t *buf, size_t size); + virtual int peek(); + virtual void flush(); + virtual void stop(); + virtual uint8_t connected(); + virtual operator bool(); + + virtual ShimClient* respond(uint8_t *buf, size_t size); + virtual ShimClient* expect(uint8_t *buf, size_t size); + + virtual void expectConnect(IPAddress ip, uint16_t port); + virtual void expectConnect(const char *host, uint16_t port); + + virtual uint16_t received(); + virtual bool error(); + + virtual void setAllowConnect(bool b); + virtual void setConnected(bool b); +}; + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.cpp new file mode 100644 index 0000000..b0ecbb4 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.cpp @@ -0,0 +1,39 @@ +#include "Stream.h" +#include "trace.h" +#include +#include + +Stream::Stream() { + this->expectBuffer = new Buffer(); + this->_error = false; + this->_written = 0; +} + +size_t Stream::write(uint8_t b) { + this->_written++; + TRACE(std::hex << (unsigned int)b); + if (this->expectBuffer->available()) { + uint8_t expected = this->expectBuffer->next(); + if (expected != b) { + this->_error = true; + TRACE("!=" << (unsigned int)expected); + } + } else { + this->_error = true; + } + TRACE("\n"<< std::dec); + return 1; +} + + +bool Stream::error() { + return this->_error; +} + +void Stream::expect(uint8_t *buf, size_t size) { + this->expectBuffer->add(buf,size); +} + +uint16_t Stream::length() { + return this->_written; +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.h new file mode 100644 index 0000000..4e41f86 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/Stream.h @@ -0,0 +1,22 @@ +#ifndef Stream_h +#define Stream_h + +#include "Arduino.h" +#include "Buffer.h" + +class Stream { +private: + Buffer* expectBuffer; + bool _error; + uint16_t _written; + +public: + Stream(); + virtual size_t write(uint8_t); + + virtual bool error(); + virtual void expect(uint8_t *buf, size_t size); + virtual uint16_t length(); +}; + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/lib/trace.h b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/trace.h new file mode 100644 index 0000000..42eb991 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/lib/trace.h @@ -0,0 +1,10 @@ +#ifndef trace_h +#define trace_h +#include + +#include + +#define LOG(x) {std::cout << x << std::flush; } +#define TRACE(x) {if (getenv("TRACE")) { std::cout << x << std::flush; }} + +#endif diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/publish_spec.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/publish_spec.cpp new file mode 100644 index 0000000..232df0d --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/publish_spec.cpp @@ -0,0 +1,190 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +int test_publish() { + IT("publishes a null-terminated string"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.expect(publish,16); + + rc = client.publish((char*)"topic",(char*)"payload"); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_publish_bytes() { + IT("publishes a byte array"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; + int length = 5; + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; + shimClient.expect(publish,14); + + rc = client.publish((char*)"topic",payload,length); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_publish_retained() { + IT("publishes retained - 1"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; + int length = 5; + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; + shimClient.expect(publish,14); + + rc = client.publish((char*)"topic",payload,length,true); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_retained_2() { + IT("publishes retained - 2"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,'A','B','C','D','E'}; + shimClient.expect(publish,14); + + rc = client.publish((char*)"topic",(char*)"ABCDE",true); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_not_connected() { + IT("publish fails when not connected"); + ShimClient shimClient; + + PubSubClient client(server, 1883, callback, shimClient); + + int rc = client.publish((char*)"topic",(char*)"payload"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_too_long() { + IT("publish fails when topic/payload are too long"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + // 0 1 2 3 4 5 6 7 8 9 0 1 2 + rc = client.publish((char*)"topic",(char*)"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_P() { + IT("publishes using PROGMEM"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; + int length = 5; + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; + shimClient.expect(publish,14); + + rc = client.publish_P((char*)"topic",payload,length,true); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + + + +int main() +{ + SUITE("Publish"); + test_publish(); + test_publish_bytes(); + test_publish_retained(); + test_publish_retained_2(); + test_publish_not_connected(); + test_publish_too_long(); + test_publish_P(); + + FINISH +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/receive_spec.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/receive_spec.cpp new file mode 100644 index 0000000..54a62ee --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/receive_spec.cpp @@ -0,0 +1,249 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +bool callback_called = false; +char lastTopic[1024]; +char lastPayload[1024]; +unsigned int lastLength; + +void reset_callback() { + callback_called = false; + lastTopic[0] = '\0'; + lastPayload[0] = '\0'; + lastLength = 0; +} + +void callback(char* topic, byte* payload, unsigned int length) { + callback_called = true; + strcpy(lastTopic,topic); + memcpy(lastPayload,payload,length); + lastLength = length; +} + +int test_receive_callback() { + IT("receives a callback message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.respond(publish,16); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(memcmp(lastPayload,"payload",7)==0); + IS_TRUE(lastLength == 7); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_stream() { + IT("receives a streamed callback message"); + reset_callback(); + + Stream stream; + stream.expect((uint8_t*)"payload",7); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient, stream); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.respond(publish,16); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(lastLength == 7); + + IS_FALSE(stream.error()); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_max_sized_message() { + IT("receives an max-sized message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + int length = MQTT_MAX_PACKET_SIZE; + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + byte bigPublish[length]; + memset(bigPublish,'A',length); + bigPublish[length] = 'B'; + memcpy(bigPublish,publish,16); + shimClient.respond(bigPublish,length); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(lastLength == length-9); + IS_TRUE(memcmp(lastPayload,bigPublish+9,lastLength)==0); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_oversized_message() { + IT("drops an oversized message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + int length = MQTT_MAX_PACKET_SIZE+1; + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + byte bigPublish[length]; + memset(bigPublish,'A',length); + bigPublish[length] = 'B'; + memcpy(bigPublish,publish,16); + shimClient.respond(bigPublish,length); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_FALSE(callback_called); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_oversized_stream_message() { + IT("drops an oversized message"); + reset_callback(); + + Stream stream; + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient, stream); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + int length = MQTT_MAX_PACKET_SIZE+1; + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + + byte bigPublish[length]; + memset(bigPublish,'A',length); + bigPublish[length] = 'B'; + memcpy(bigPublish,publish,16); + + shimClient.respond(bigPublish,length); + stream.expect(bigPublish+9,length-9); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(lastLength == length-9); + + IS_FALSE(stream.error()); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_qos1() { + IT("receives a qos1 message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.respond(publish,18); + + byte puback[] = {0x40,0x2,0x12,0x34}; + shimClient.expect(puback,4); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(memcmp(lastPayload,"payload",7)==0); + IS_TRUE(lastLength == 7); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int main() +{ + SUITE("Receive"); + test_receive_callback(); + test_receive_stream(); + test_receive_max_sized_message(); + test_receive_oversized_message(); + test_receive_oversized_stream_message(); + test_receive_qos1(); + + FINISH +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/src/subscribe_spec.cpp b/libraries/MySensors/drivers/pubsubclient/tests/src/subscribe_spec.cpp new file mode 100644 index 0000000..a419823 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/src/subscribe_spec.cpp @@ -0,0 +1,177 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +int test_subscribe_no_qos() { + IT("subscribe without qos defaults to 0"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x0 }; + shimClient.expect(subscribe,12); + byte suback[] = { 0x90,0x3,0x0,0x2,0x0 }; + shimClient.respond(suback,5); + + rc = client.subscribe((char*)"topic"); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_qos_1() { + IT("subscribes qos 1"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1 }; + shimClient.expect(subscribe,12); + byte suback[] = { 0x90,0x3,0x0,0x2,0x1 }; + shimClient.respond(suback,5); + + rc = client.subscribe((char*)"topic",1); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_not_connected() { + IT("subscribe fails when not connected"); + ShimClient shimClient; + + PubSubClient client(server, 1883, callback, shimClient); + + int rc = client.subscribe((char*)"topic"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_invalid_qos() { + IT("subscribe fails with invalid qos values"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + rc = client.subscribe((char*)"topic",2); + IS_FALSE(rc); + rc = client.subscribe((char*)"topic",254); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_too_long() { + IT("subscribe fails with too long topic"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + // max length should be allowed + // 0 1 2 3 4 5 6 7 8 9 0 1 2 + rc = client.subscribe((char*)"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"); + IS_TRUE(rc); + + // 0 1 2 3 4 5 6 7 8 9 0 1 2 + rc = client.subscribe((char*)"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_unsubscribe() { + IT("unsubscribes"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte unsubscribe[] = { 0xA2,0x9,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63 }; + shimClient.expect(unsubscribe,12); + byte unsuback[] = { 0xB0,0x2,0x0,0x2 }; + shimClient.respond(unsuback,4); + + rc = client.unsubscribe((char*)"topic"); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_unsubscribe_not_connected() { + IT("unsubscribe fails when not connected"); + ShimClient shimClient; + + PubSubClient client(server, 1883, callback, shimClient); + + int rc = client.unsubscribe((char*)"topic"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int main() +{ + SUITE("Subscribe"); + test_subscribe_no_qos(); + test_subscribe_qos_1(); + test_subscribe_not_connected(); + test_subscribe_invalid_qos(); + test_subscribe_too_long(); + test_unsubscribe(); + test_unsubscribe_not_connected(); + FINISH +} diff --git a/libraries/MySensors/drivers/pubsubclient/tests/testcases/__init__.py b/libraries/MySensors/drivers/pubsubclient/tests/testcases/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_basic.py b/libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_basic.py new file mode 100644 index 0000000..1b0cc65 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_basic.py @@ -0,0 +1,43 @@ +import unittest +import settings + +import time +import mosquitto + +import serial + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + +class mqtt_basic(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic",0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_one(self): + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue[0] + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,"hello world") + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + diff --git a/libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_publish_in_callback.py b/libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_publish_in_callback.py new file mode 100644 index 0000000..7989f7f --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/testcases/mqtt_publish_in_callback.py @@ -0,0 +1,64 @@ +import unittest +import settings + +import time +import mosquitto + +import serial + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + +class mqtt_publish_in_callback(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic",0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_connect(self): + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,"hello world") + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + def test_publish(self): + self.assertEqual(len(self.message_queue), 0, "message queue not empty") + payload = "abcdefghij" + self.client.publish("inTopic",payload) + + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,payload) + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + diff --git a/libraries/MySensors/drivers/pubsubclient/tests/testcases/settings.py b/libraries/MySensors/drivers/pubsubclient/tests/testcases/settings.py new file mode 100644 index 0000000..4ad8719 --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/testcases/settings.py @@ -0,0 +1,2 @@ +server_ip = "172.16.0.2" +arduino_ip = "172.16.0.100" diff --git a/libraries/MySensors/drivers/pubsubclient/tests/testsuite.py b/libraries/MySensors/drivers/pubsubclient/tests/testsuite.py new file mode 100644 index 0000000..0a8e70d --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient/tests/testsuite.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +import os +import os.path +import sys +import shutil +from subprocess import call +import importlib +import unittest +import re + +from testcases import settings + +class Workspace(object): + + def __init__(self): + self.root_dir = os.getcwd() + self.build_dir = os.path.join(self.root_dir,"tmpbin"); + self.log_dir = os.path.join(self.root_dir,"logs"); + self.tests_dir = os.path.join(self.root_dir,"testcases"); + self.examples_dir = os.path.join(self.root_dir,"../PubSubClient/examples") + self.examples = [] + self.tests = [] + if not os.path.isdir("../PubSubClient"): + raise Exception("Cannot find PubSubClient library") + try: + import ino + except: + raise Exception("ino tool not installed") + + def init(self): + if os.path.isdir(self.build_dir): + shutil.rmtree(self.build_dir) + os.mkdir(self.build_dir) + if os.path.isdir(self.log_dir): + shutil.rmtree(self.log_dir) + os.mkdir(self.log_dir) + + os.chdir(self.build_dir) + call(["ino","init"]) + + shutil.copytree("../../PubSubClient","lib/PubSubClient") + + filenames = [] + for root, dirs, files in os.walk(self.examples_dir): + filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.examples.append(Sketch(self,e)) + + filenames = [] + for root, dirs, files in os.walk(self.tests_dir): + filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.tests.append(Sketch(self,e)) + + def clean(self): + shutil.rmtree(self.build_dir) + +class Sketch(object): + def __init__(self,wksp,fn): + self.w = wksp + self.filename = fn + self.basename = os.path.basename(self.filename) + self.build_log = os.path.join(self.w.log_dir,"%s.log"%(os.path.basename(self.filename),)) + self.build_err_log = os.path.join(self.w.log_dir,"%s.err.log"%(os.path.basename(self.filename),)) + self.build_upload_log = os.path.join(self.w.log_dir,"%s.upload.log"%(os.path.basename(self.filename),)) + + def build(self): + sys.stdout.write(" Build: ") + sys.stdout.flush() + + # Copy sketch over, replacing IP addresses as necessary + fin = open(self.filename,"r") + lines = fin.readlines() + fin.close() + fout = open(os.path.join(self.w.build_dir,"src","sketch.ino"),"w") + for l in lines: + if re.match(r"^byte server\[\] = {",l): + fout.write("byte server[] = { %s };\n"%(settings.server_ip.replace(".",", "),)) + elif re.match(r"^byte ip\[\] = {",l): + fout.write("byte ip[] = { %s };\n"%(settings.arduino_ip.replace(".",", "),)) + else: + fout.write(l) + fout.flush() + fout.close() + + # Run build + fout = open(self.build_log, "w") + ferr = open(self.build_err_log, "w") + rc = call(["ino","build"],stdout=fout,stderr=ferr) + fout.close() + ferr.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_err_log) as f: + for line in f: + print " ",line, + return False + + def upload(self): + sys.stdout.write(" Upload: ") + sys.stdout.flush() + fout = open(self.build_upload_log, "w") + rc = call(["ino","upload"],stdout=fout,stderr=fout) + fout.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_upload_log) as f: + for line in f: + print " ",line, + return False + + + def test(self): + # import the matching test case, if it exists + try: + basename = os.path.basename(self.filename)[:-4] + i = importlib.import_module("testcases."+basename) + except: + sys.stdout.write(" Test: no tests found") + sys.stdout.write("\n") + return + c = getattr(i,basename) + + testmethods = [m for m in dir(c) if m.startswith("test_")] + testmethods.sort() + tests = [] + for m in testmethods: + tests.append(c(m)) + + result = unittest.TestResult() + c.setUpClass() + if self.upload(): + sys.stdout.write(" Test: ") + sys.stdout.flush() + for t in tests: + t.run(result) + print "%d/%d"%(result.testsRun-len(result.failures)-len(result.errors),result.testsRun) + if not result.wasSuccessful(): + if len(result.failures) > 0: + for f in result.failures: + print "-- %s"%(str(f[0]),) + print f[1] + if len(result.errors) > 0: + print " Errors:" + for f in result.errors: + print "-- %s"%(str(f[0]),) + print f[1] + c.tearDownClass() + +if __name__ == '__main__': + run_tests = True + + w = Workspace() + w.init() + + for e in w.examples: + print "--------------------------------------" + print "[%s]"%(e.basename,) + if e.build() and run_tests: + e.test() + for e in w.tests: + print "--------------------------------------" + print "[%s]"%(e.basename,) + if e.build() and run_tests: + e.test() + + w.clean() diff --git a/libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino b/libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino new file mode 100644 index 0000000..310295c --- /dev/null +++ b/libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino @@ -0,0 +1,216 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * Connect the MQ2 sensor as follows : + * + * A H A >>> 5V + * B >>> A0 + * H >>> GND + * B >>> 10K ohm >>> GND + * + * Contribution: epierre + * Based on http://sandboxelectronics.com/?p=165 + * License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) + * Modified by HEK to work in 1.4 + * + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define CHILD_ID_MQ 0 +/************************Hardware Related Macros************************************/ +#define MQ_SENSOR_ANALOG_PIN (0) //define which analog input channel you are going to use +#define RL_VALUE (5) //define the load resistance on the board, in kilo ohms +#define RO_CLEAN_AIR_FACTOR (9.83) //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO, + //which is derived from the chart in datasheet +/***********************Software Related Macros************************************/ +#define CALIBARAION_SAMPLE_TIMES (50) //define how many samples you are going to take in the calibration phase +#define CALIBRATION_SAMPLE_INTERVAL (500) //define the time interal(in milisecond) between each samples in the + //cablibration phase +#define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation +#define READ_SAMPLE_TIMES (5) //define the time interal(in milisecond) between each samples in + //normal operation +/**********************Application Related Macros**********************************/ +#define GAS_LPG (0) +#define GAS_CO (1) +#define GAS_SMOKE (2) +/*****************************Globals***********************************************/ +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) +//VARIABLES +float Ro = 10000.0; // this has to be tuned 10K Ohm +int val = 0; // variable to store the value coming from the sensor +float valMQ =0.0; +float lastMQ =0.0; +float LPGCurve[3] = {2.3,0.21,-0.47}; //two points are taken from the curve. + //with these two points, a line is formed which is "approximately equivalent" + //to the original curve. + //data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59) +float COCurve[3] = {2.3,0.72,-0.34}; //two points are taken from the curve. + //with these two points, a line is formed which is "approximately equivalent" + //to the original curve. + //data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15) +float SmokeCurve[3] ={2.3,0.53,-0.44}; //two points are taken from the curve. + //with these two points, a line is formed which is "approximately equivalent" + //to the original curve. + //data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22) + + +MyMessage msg(CHILD_ID_MQ, V_LEVEL); + + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Air Quality Sensor", "1.0"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_MQ, S_AIR_QUALITY); + + Ro = MQCalibration(MQ_SENSOR_ANALOG_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air + //when you perform the calibration +} + +void loop() +{ + uint16_t valMQ = MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO); + Serial.println(val); + + Serial.print("LPG:"); + Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_LPG) ); + Serial.print( "ppm" ); + Serial.print(" "); + Serial.print("CO:"); + Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO) ); + Serial.print( "ppm" ); + Serial.print(" "); + Serial.print("SMOKE:"); + Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_SMOKE) ); + Serial.print( "ppm" ); + Serial.print("\n"); + + if (valMQ != lastMQ) { + send(msg.set((int)ceil(valMQ))); + lastMQ = ceil(valMQ); + } + + sleep(SLEEP_TIME); //sleep for: sleepTime +} + +/****************** MQResistanceCalculation **************************************** +Input: raw_adc - raw value read from adc, which represents the voltage +Output: the calculated sensor resistance +Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage + across the load resistor and its resistance, the resistance of the sensor + could be derived. +************************************************************************************/ +float MQResistanceCalculation(int raw_adc) +{ + return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc)); +} + +/***************************** MQCalibration **************************************** +Input: mq_pin - analog channel +Output: Ro of the sensor +Remarks: This function assumes that the sensor is in clean air. It use + MQResistanceCalculation to calculates the sensor resistance in clean air + and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about + 10, which differs slightly between different sensors. +************************************************************************************/ +float MQCalibration(int mq_pin) +{ + int i; + float val=0; + + for (i=0;i + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * This is an example that demonstrates how to report the battery level for a sensor + * Instructions for measuring battery capacity on A0 are available here: + * http://www.mysensors.org/build/battery + * + */ + + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point + +unsigned long SLEEP_TIME = 900000; // sleep time between reads (seconds * 1000 milliseconds) +int oldBatteryPcnt = 0; + +void setup() +{ + // use the 1.1 V internal reference +#if defined(__AVR_ATmega2560__) + analogReference(INTERNAL1V1); +#else + analogReference(INTERNAL); +#endif + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Battery Meter", "1.0"); +} + +void loop() +{ + // get the battery Voltage + int sensorValue = analogRead(BATTERY_SENSE_PIN); + #ifdef DEBUG + Serial.println(sensorValue); + #endif + + // 1M, 470K divider across battery and using internal ADC ref of 1.1V + // Sense point is bypassed with 0.1 uF cap to reduce noise at that point + // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts + // 3.44/1023 = Volts per bit = 0.003363075 + float batteryV = sensorValue * 0.003363075; + int batteryPcnt = sensorValue / 10; + + #ifdef DEBUG + Serial.print("Battery Voltage: "); + Serial.print(batteryV); + Serial.println(" V"); + + Serial.print("Battery percent: "); + Serial.print(batteryPcnt); + Serial.println(" %"); + #endif + + if (oldBatteryPcnt != batteryPcnt) { + // Power up radio after sleep + sendBatteryLevel(batteryPcnt); + oldBatteryPcnt = batteryPcnt; + } + sleep(SLEEP_TIME); +} diff --git a/libraries/MySensors/examples/BinarySwitchSensor/BinarySwitchSensor.ino b/libraries/MySensors/examples/BinarySwitchSensor/BinarySwitchSensor.ino new file mode 100644 index 0000000..b7a96a3 --- /dev/null +++ b/libraries/MySensors/examples/BinarySwitchSensor/BinarySwitchSensor.ino @@ -0,0 +1,80 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * Simple binary switch example + * Connect button or door/window reed switch between + * digitial I/O pin 3 (BUTTON_PIN below) and GND. + * http://www.mysensors.org/build/binary + */ + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +#define CHILD_ID 3 +#define BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch + +Bounce debouncer = Bounce(); +int oldValue=-1; + +// Change to V_LIGHT if you use S_LIGHT in presentation below +MyMessage msg(CHILD_ID,V_TRIPPED); + +void setup() +{ + // Setup the button + pinMode(BUTTON_PIN,INPUT); + // Activate internal pull-up + digitalWrite(BUTTON_PIN,HIGH); + + // After setting up the button, setup debouncer + debouncer.attach(BUTTON_PIN); + debouncer.interval(5); + + // Register binary input sensor to gw (they will be created as child devices) + // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. + // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. + present(CHILD_ID, S_DOOR); +} + + +// Check if digital input has changed and send in new value +void loop() +{ + debouncer.update(); + // Get the update value + int value = debouncer.read(); + + if (value != oldValue) { + // Send in the new value + send(msg.set(value==HIGH ? 1 : 0)); + oldValue = value; + } +} + diff --git a/libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino b/libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino new file mode 100644 index 0000000..7a88465 --- /dev/null +++ b/libraries/MySensors/examples/BinarySwitchSleepSensor/BinarySwitchSleepSensor.ino @@ -0,0 +1,118 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * Interrupt driven binary switch example with dual interrupts + * Author: Patrick 'Anticimex' Fallberg + * Connect one button or door/window reed switch between + * digitial I/O pin 3 (BUTTON_PIN below) and GND and the other + * one in similar fashion on digital I/O pin 2. + * This example is designed to fit Arduino Nano/Pro Mini + * + */ + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define SKETCH_NAME "Binary Sensor" +#define SKETCH_MAJOR_VER "1" +#define SKETCH_MINOR_VER "0" + +#define PRIMARY_CHILD_ID 3 +#define SECONDARY_CHILD_ID 4 + +#define PRIMARY_BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch +#define SECONDARY_BUTTON_PIN 3 // Arduino Digital I/O pin for button/reed switch + +#if (PRIMARY_BUTTON_PIN < 2 || PRIMARY_BUTTON_PIN > 3) +#error PRIMARY_BUTTON_PIN must be either 2 or 3 for interrupts to work +#endif +#if (SECONDARY_BUTTON_PIN < 2 || SECONDARY_BUTTON_PIN > 3) +#error SECONDARY_BUTTON_PIN must be either 2 or 3 for interrupts to work +#endif +#if (PRIMARY_BUTTON_PIN == SECONDARY_BUTTON_PIN) +#error PRIMARY_BUTTON_PIN and BUTTON_PIN2 cannot be the same +#endif +#if (PRIMARY_CHILD_ID == SECONDARY_CHILD_ID) +#error PRIMARY_CHILD_ID and SECONDARY_CHILD_ID cannot be the same +#endif + + +// Change to V_LIGHT if you use S_LIGHT in presentation below +MyMessage msg(PRIMARY_CHILD_ID, V_TRIPPED); +MyMessage msg2(SECONDARY_CHILD_ID, V_TRIPPED); + +void setup() +{ + // Setup the buttons + pinMode(PRIMARY_BUTTON_PIN, INPUT); + pinMode(SECONDARY_BUTTON_PIN, INPUT); + + // Activate internal pull-ups + digitalWrite(PRIMARY_BUTTON_PIN, HIGH); + digitalWrite(SECONDARY_BUTTON_PIN, HIGH); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER); + + // Register binary input sensor to sensor_node (they will be created as child devices) + // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. + // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. + present(PRIMARY_CHILD_ID, S_DOOR); + present(SECONDARY_CHILD_ID, S_DOOR); +} + +// Loop will iterate on changes on the BUTTON_PINs +void loop() +{ + uint8_t value; + static uint8_t sentValue=2; + static uint8_t sentValue2=2; + + // Short delay to allow buttons to properly settle + sleep(5); + + value = digitalRead(PRIMARY_BUTTON_PIN); + + if (value != sentValue) { + // Value has changed from last transmission, send the updated value + send(msg.set(value==HIGH ? 1 : 0)); + sentValue = value; + } + + value = digitalRead(SECONDARY_BUTTON_PIN); + + if (value != sentValue2) { + // Value has changed from last transmission, send the updated value + send(msg2.set(value==HIGH ? 1 : 0)); + sentValue2 = value; + } + + // Sleep until something happens with the sensor + sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, 0); +} diff --git a/libraries/MySensors/examples/CO2Sensor/CO2Sensor.ino b/libraries/MySensors/examples/CO2Sensor/CO2Sensor.ino new file mode 100644 index 0000000..09d7645 --- /dev/null +++ b/libraries/MySensors/examples/CO2Sensor/CO2Sensor.ino @@ -0,0 +1,102 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * MH-Z14 CO2 sensor + * + * Wiring: + * Pad 1, Pad 5: Vin (Voltage input 4.5V-6V) + * Pad 2, Pad 3, Pad 12: GND + * Pad 6: PWM output ==> pin 6 + * + * From: http://davidegironi.blogspot.fr/2014/01/co2-meter-using-ndir-infrared-mh-z14.html + * MH-Z14 has a PWM output, with a sensitivity range of 0ppm to 2000ppm CO2, an accurancy of ±200ppm. + * The cycle is 1004ms±5%, given the duty cicle Th (pulse high), Tl is 1004-Th, we can convert it to CO2 value using the formula: + * CO2ppm = 2000 * (Th - 2ms) /(Th + Tl - 4ms) + * From: http://airqualityegg.wikispaces.com/Sensor+Tests + * - response time is less than 30 s + * - 3 minute warm up time + * datasheet: http://www.futurlec.com/Datasheet/Sensor/MH-Z14.pdf +* Contributor: epierre +**/ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define CHILD_ID_AIQ 0 +#define AIQ_SENSOR_ANALOG_PIN 6 + +unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) + +float valAIQ =0.0; +float lastAIQ =0.0; + +MyMessage msg(CHILD_ID_AIQ, V_LEVEL); +MyMessage msg2(CHILD_ID_AIQ, V_UNIT_PREFIX); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("AIQ Sensor CO2 MH-Z14", "1.0"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_AIQ, S_AIR_QUALITY); + send(msg2.set("ppm")); + + sleep(SLEEP_TIME); + + pinMode(AIQ_SENSOR_ANALOG_PIN, INPUT); + +} + +void loop() { + + //unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); + while(digitalRead(AIQ_SENSOR_ANALOG_PIN) == HIGH) {;} + //wait for the pin to go HIGH and measure HIGH time + unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); + + //Serial.print(duration/1000); Serial.println(" ms "); + //from datasheet + //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms) + // given Tl + Th = 1004 + // Tl = 1004 - Th + // = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms) + // = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms) + long co2ppm = 2 * ((duration/1000) - 2); + //Serial.print(co2ppm); + if ((co2ppm != lastAIQ)&&(abs(co2ppm-lastAIQ)>=10)) { + send(msg.set((long)ceil(co2ppm))); + lastAIQ = ceil(co2ppm); + } + + //Serial.println(); + + // Power down the radio. Note that the radio will get powered back up + // on the next write() call. + sleep(SLEEP_TIME); //sleep for: sleepTime +} diff --git a/libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino b/libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino new file mode 100644 index 0000000..dc55dff --- /dev/null +++ b/libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino @@ -0,0 +1,43 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * This sketch clears radioId, relayId and other routing information in EEPROM back to factory default + * + */ + +#include +#include + +void setup() +{ + Serial.begin(MY_BAUD_RATE); + Serial.println("Started clearing. Please wait..."); + for (int i=0;i<512;i++) { + EEPROM.write(i, 0xff); + } + Serial.println("Clering done. You're ready to go!"); +} + +void loop() +{ + // Nothing to do here... +} diff --git a/libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino b/libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino new file mode 100644 index 0000000..9232249 --- /dev/null +++ b/libraries/MySensors/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino @@ -0,0 +1,103 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * Example sketch showing how to send in DS1820B OneWire temperature readings back to the controller + * http://www.mysensors.org/build/temp + */ + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include + +#define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No + +#define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected +#define MAX_ATTACHED_DS18B20 16 +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) +OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) +DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. +float lastTemperature[MAX_ATTACHED_DS18B20]; +int numSensors=0; +boolean receivedConfig = false; +boolean metric = true; +// Initialize temperature message +MyMessage msg(0,V_TEMP); + +void setup() +{ + // Startup up the OneWire library + sensors.begin(); + // requestTemperatures() will not block current thread + sensors.setWaitForConversion(false); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Temperature Sensor", "1.1"); + + // Fetch the number of attached temperature sensors + numSensors = sensors.getDeviceCount(); + + // Present all sensors to controller + for (int i=0; i(static_cast((getConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.; + + // Only send data if temperature has changed and no error + #if COMPARE_TEMP == 1 + if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) { + #else + if (temperature != -127.00 && temperature != 85.00) { + #endif + + // Send in the new temperature + send(msg.setSensor(i).set(temperature,1)); + // Save new temperatures for next compare + lastTemperature[i]=temperature; + } + } + sleep(SLEEP_TIME); +} diff --git a/libraries/MySensors/examples/DimmableLEDActuator/DimmableLEDActuator.ino b/libraries/MySensors/examples/DimmableLEDActuator/DimmableLEDActuator.ino new file mode 100644 index 0000000..51582d3 --- /dev/null +++ b/libraries/MySensors/examples/DimmableLEDActuator/DimmableLEDActuator.ino @@ -0,0 +1,126 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - February 15, 2014 - Bruce Lacey + * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek) + * + * DESCRIPTION + * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad + * Vera Arduino Sensor project. + * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches. + * + * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip. + * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected + * to the LED negative terminal and the MOSFET Source pin is connected to ground. + * + * This sketch is extensible to support more than one MOSFET/PWM dimmer per circuit. + * http://www.mysensors.org/build/dimmer + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define SN "DimmableLED" +#define SV "1.1" + +#define LED_PIN 3 // Arduino pin attached to MOSFET Gate pin +#define FADE_DELAY 10 // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim) + +static int currentLevel = 0; // Current dim level... +MyMessage dimmerMsg(0, V_DIMMER); +MyMessage lightMsg(0, V_LIGHT); + + +/*** + * Dimmable LED initialization method + */ +void setup() +{ + // Initialize library and add callback for incoming messages (signing is required) + setIncomingCallback(incomingMessage); + + // Register the LED Dimmable Light with the gateway + present( 0, S_DIMMER ); + + sendSketchInfo(SN, SV); + // Pull the gateway's current dim level - restore light level upon sendor node power-up + request( 0, V_DIMMER ); +} + +/*** + * Dimmable LED main processing loop + */ +void loop() +{ +} + + + +void incomingMessage(const MyMessage &message) { + if (message.type == V_LIGHT || message.type == V_DIMMER) { + + // Retrieve the power or dim level from the incoming request message + int requestedLevel = atoi( message.data ); + + // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on] + requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 ); + + // Clip incoming level to valid range of 0 to 100 + requestedLevel = requestedLevel > 100 ? 100 : requestedLevel; + requestedLevel = requestedLevel < 0 ? 0 : requestedLevel; + + Serial.print( "Changing level to " ); + Serial.print( requestedLevel ); + Serial.print( ", from " ); + Serial.println( currentLevel ); + + fadeToLevel( requestedLevel ); + + // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value... + send(lightMsg.set(currentLevel > 0 ? 1 : 0)); + + // hek comment: Is this really nessesary? + send( dimmerMsg.set(currentLevel) ); + + + } +} + +/*** + * This method provides a graceful fade up/down effect + */ +void fadeToLevel( int toLevel ) { + + int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1; + + while ( currentLevel != toLevel ) { + currentLevel += delta; + analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) ); + delay( FADE_DELAY ); + } +} + diff --git a/libraries/MySensors/examples/DimmableLight/DimmableLight.ino b/libraries/MySensors/examples/DimmableLight/DimmableLight.ino new file mode 100644 index 0000000..ea939a0 --- /dev/null +++ b/libraries/MySensors/examples/DimmableLight/DimmableLight.ino @@ -0,0 +1,162 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - January 30, 2015 - Developed by GizMoCuz (Domoticz) + * + * DESCRIPTION + * This sketch provides an example how to implement a Dimmable Light + * It is pure virtual and it logs messages to the serial output + * It can be used as a base sketch for actual hardware. + * Stores the last light state and level in eeprom. + * + */ + +// Enable debug prints +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define CHILD_ID_LIGHT 1 + +#define EPROM_LIGHT_STATE 1 +#define EPROM_DIMMER_LEVEL 2 + +#define LIGHT_OFF 0 +#define LIGHT_ON 1 + +#define SN "Dimable Light" +#define SV "1.0" + +int LastLightState=LIGHT_OFF; +int LastDimValue=100; + +MyMessage lightMsg(CHILD_ID_LIGHT, V_LIGHT); +MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER); + +void setup() +{ + // Initialize library and add callback for incoming messages (signing is required) + setIncomingCallback(incomingMessage); + + // Send the Sketch Version Information to the Gateway + sendSketchInfo(SN, SV); + + present(CHILD_ID_LIGHT, S_DIMMER ); + + //Retreive our last light state from the eprom + int LightState=loadState(EPROM_LIGHT_STATE); + if (LightState<=1) { + LastLightState=LightState; + int DimValue=loadState(EPROM_DIMMER_LEVEL); + if ((DimValue>0)&&(DimValue<=100)) { + //There should be no Dim value of 0, this would mean LIGHT_OFF + LastDimValue=DimValue; + } + } + + //Here you actualy switch on/off the light with the last known dim level + SetCurrentState2Hardware(); + + Serial.println( "Node ready to receive messages..." ); +} + +void loop() +{ +} + +void incomingMessage(const MyMessage &message) +{ + if (message.type == V_LIGHT) { + Serial.println( "V_LIGHT command received..." ); + + int lstate= atoi( message.data ); + if ((lstate<0)||(lstate>1)) { + Serial.println( "V_LIGHT data invalid (should be 0/1)" ); + return; + } + LastLightState=lstate; + saveState(EPROM_LIGHT_STATE, LastLightState); + + if ((LastLightState==LIGHT_ON)&&(LastDimValue==0)) { + //In the case that the Light State = On, but the dimmer value is zero, + //then something (probably the controller) did something wrong, + //for the Dim value to 100% + LastDimValue=100; + saveState(EPROM_DIMMER_LEVEL, LastDimValue); + } + + //When receiving a V_LIGHT command we switch the light between OFF and the last received dimmer value + //This means if you previously set the lights dimmer value to 50%, and turn the light ON + //it will do so at 50% + } + else if (message.type == V_DIMMER) { + Serial.println( "V_DIMMER command received..." ); + int dimvalue= atoi( message.data ); + if ((dimvalue<0)||(dimvalue>100)) { + Serial.println( "V_DIMMER data invalid (should be 0..100)" ); + return; + } + if (dimvalue==0) { + LastLightState=LIGHT_OFF; + } + else { + LastLightState=LIGHT_ON; + LastDimValue=dimvalue; + saveState(EPROM_DIMMER_LEVEL, LastDimValue); + } + } + else { + Serial.println( "Invalid command received..." ); + return; + } + + //Here you set the actual light state/level + SetCurrentState2Hardware(); +} + +void SetCurrentState2Hardware() +{ + if (LastLightState==LIGHT_OFF) { + Serial.println( "Light state: OFF" ); + } + else { + Serial.print( "Light state: ON, Level: " ); + Serial.println( LastDimValue ); + } + + //Send current state to the controller + SendCurrentState2Controller(); +} + +void SendCurrentState2Controller() +{ + if ((LastLightState==LIGHT_OFF)||(LastDimValue==0)) { + send(dimmerMsg.set(0)); + } + else { + send(dimmerMsg.set(LastDimValue)); + } +} + diff --git a/libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino b/libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino new file mode 100644 index 0000000..2764e20 --- /dev/null +++ b/libraries/MySensors/examples/DimmableLightWithRotaryEncoderButton/DimmableLightWithRotaryEncoderButton.ino @@ -0,0 +1,240 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz) + * Version 1.1 - Modified by hek to incorporate a rotary encode to adjust + * light level locally at node + * + * DESCRIPTION + * This sketch provides an example how to implement a dimmable led light node with a rotary + * encoder connected for adjusting light level. + * The encoder has a click button which turns on/off the light (and remembers last dim-level) + * The sketch fades the light (non-blocking) to the desired level. + * + * Default MOSFET pin is 3 + * + * Arduino Encoder module + * --------------------------- + * 5V 5V (+) + * GND GND (-) + * 4 CLK (or putput 1) + * 5 DT (or output 1) + * 6 SW (Switch/Click) + */ + + +// Enable debug prints +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include + +#define LED_PIN 3 // Arduino pin attached to MOSFET Gate pin +#define KNOB_ENC_PIN_1 4 // Rotary encoder input pin 1 +#define KNOB_ENC_PIN_2 5 // Rotary encoder input pin 2 +#define KNOB_BUTTON_PIN 6 // Rotary encoder button pin +#define FADE_DELAY 10 // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim) +#define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob +#define SN "DimmableLED /w button" +#define SV "1.2" + +#define CHILD_ID_LIGHT 1 + +#define EEPROM_DIM_LEVEL_LAST 1 +#define EEPROM_DIM_LEVEL_SAVE 2 + +#define LIGHT_OFF 0 +#define LIGHT_ON 1 + +int dimValue; +int fadeTo; +int fadeDelta; +byte oldButtonVal; +bool changedByKnob=false; +bool sendDimValue=false; +unsigned long lastFadeStep; +unsigned long sendDimTimeout; +char convBuffer[10]; + +MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER); +Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2); +Bounce debouncer = Bounce(); + +void setup() +{ + // Initialize library and add callback for incoming messages (signing is required) + setIncomingCallback(incomingMessage); + + // Set knob button pin as input (with debounce) + pinMode(KNOB_BUTTON_PIN, INPUT); + digitalWrite(KNOB_BUTTON_PIN, HIGH); + debouncer.attach(KNOB_BUTTON_PIN); + debouncer.interval(5); + oldButtonVal = debouncer.read(); + + // Set analog led pin to off + analogWrite( LED_PIN, 0); + + // Send the Sketch Version Information to the Gateway + present(CHILD_ID_LIGHT, S_DIMMER); + sendSketchInfo(SN, SV); + + // Retreive our last dim levels from the eprom + fadeTo = dimValue = 0; + byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST); + Serial.print("Sending in last known light level to controller: "); + Serial.println(oldLevel); + send(dimmerMsg.set(oldLevel), true); + + Serial.println("Ready to receive messages..."); +} + +void loop() +{ + // Check if someone turned the rotary encode + checkRotaryEncoder(); + + // Check if someone has pressed the knob button + checkButtonClick(); + + // Fade light to new dim value + fadeStep(); +} + +void incomingMessage(const MyMessage &message) +{ + if (message.type == V_LIGHT) { + // Incoming on/off command sent from controller ("1" or "0") + int lightState = message.getString()[0] == '1'; + int newLevel = 0; + if (lightState==LIGHT_ON) { + // Pick up last saved dimmer level from the eeprom + newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE); + } + // Send dimmer level back to controller with ack enabled + send(dimmerMsg.set(newLevel), true); + // We do not change any levels here until ack comes back from gateway + return; + } else if (message.type == V_DIMMER) { + // Incoming dim-level command sent from controller (or ack message) + fadeTo = atoi(message.getString(convBuffer)); + // Save received dim value to eeprom (unless turned off). Will be + // retreived when a on command comes in + if (fadeTo != 0) + saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo); + } + saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo); + + Serial.print("New light level received: "); + Serial.println(fadeTo); + + if (!changedByKnob) + knob.write(fadeTo); + + // Cancel send if user turns knob while message comes in + changedByKnob = false; + sendDimValue = false; + + // Stard fading to new light level + startFade(); +} + + + +void checkRotaryEncoder() { + long encoderValue = knob.read(); + + if (encoderValue > 100) { + encoderValue = 100; + knob.write(100); + } else if (encoderValue < 0) { + encoderValue = 0; + knob.write(0); + } + + if (encoderValue != fadeTo) { + fadeTo = encoderValue; + changedByKnob = true; + startFade(); + } +} + +void checkButtonClick() { + debouncer.update(); + byte buttonVal = debouncer.read(); + byte newLevel = 0; + if (buttonVal != oldButtonVal && buttonVal == LOW) { + if (dimValue==0) { + // Turn on light. Set the level to last saved dim value + int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE); + newLevel = saved > 0 ? saved : 100; + } + send(dimmerMsg.set(newLevel),true); + } + oldButtonVal = buttonVal; +} + +void startFade() { + fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1; + lastFadeStep = millis(); +} + +// This method provides a graceful none-blocking fade up/down effect +void fadeStep() { + unsigned long currentTime = millis(); + if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) { + dimValue += fadeDelta; + analogWrite( LED_PIN, (int)(dimValue / 100. * 255) ); + lastFadeStep = currentTime; + + Serial.print("Fading level: "); + Serial.println(dimValue); + + if (fadeTo == dimValue && changedByKnob) { + sendDimValue = true; + sendDimTimeout = currentTime; + } + } + // Wait a few millisecs before sending in new value (if user still turns the knob) + if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY) { + // We're done fading.. send in new dim-value to controller. + // Send in new dim value with ack (will be picked up in incomingMessage) + send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back + sendDimValue = false; + } +} + +// Make sure only to store/fetch values in the range 0-100 from eeprom +int loadLevelState(byte pos) { + return min(max(loadState(pos),0),100); +} +void saveLevelState(byte pos, byte data) { + saveState(pos,min(max(data,0),100)); +} + + + + diff --git a/libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino b/libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino new file mode 100644 index 0000000..5d3e157 --- /dev/null +++ b/libraries/MySensors/examples/DistanceSensor/DistanceSensor.ino @@ -0,0 +1,75 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * + * DESCRIPTION + * This sketch provides an example how to implement a distance sensor using HC-SR04 + * http://www.mysensors.org/build/distance + */ + +// Enable debug prints +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +#define CHILD_ID 1 +#define TRIGGER_PIN 6 // Arduino pin tied to trigger pin on the ultrasonic sensor. +#define ECHO_PIN 5 // Arduino pin tied to echo pin on the ultrasonic sensor. +#define MAX_DISTANCE 300 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. +unsigned long SLEEP_TIME = 5000; // Sleep time between reads (in milliseconds) + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. +MyMessage msg(CHILD_ID, V_DISTANCE); +int lastDist; +boolean metric = true; + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Distance Sensor", "1.0"); + + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID, S_DISTANCE); + metric = getConfig().isMetric; +} + +void loop() +{ + int dist = metric?sonar.ping_cm():sonar.ping_in(); + Serial.print("Ping: "); + Serial.print(dist); // Convert ping time to distance in cm and print result (0 = outside set distance range) + Serial.println(metric?" cm":" in"); + + if (dist != lastDist) { + send(msg.set(dist)); + lastDist = dist; + } + + sleep(SLEEP_TIME); +} + + diff --git a/libraries/MySensors/examples/DustSensor/DustSensor.ino b/libraries/MySensors/examples/DustSensor/DustSensor.ino new file mode 100644 index 0000000..03eb3e6 --- /dev/null +++ b/libraries/MySensors/examples/DustSensor/DustSensor.ino @@ -0,0 +1,103 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - epierre + * Converted to 1.4 by Henrik Ekblad + * + * DESCRIPTION + * Arduino Dust Sensort + * + * connect the sensor as follows : + * + * VCC >>> 5V + * A >>> A0 + * GND >>> GND + * + * Based on: http://www.dfrobot.com/wiki/index.php/Sharp_GP2Y1010AU + * Authors: Cyrille Médard de Chardon (serialC), Christophe Trefois (Trefex) + * + * http://www.mysensors.org/build/dust + * + */ + +// Enable debug prints +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define CHILD_ID_DUST 0 +#define DUST_SENSOR_ANALOG_PIN 1 + +unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) +//VARIABLES +int val = 0; // variable to store the value coming from the sensor +float valDUST =0.0; +float lastDUST =0.0; +int samplingTime = 280; +int deltaTime = 40; +int sleepTime = 9680; +float voMeasured = 0; +float calcVoltage = 0; +float dustDensity = 0; + +MyMessage dustMsg(CHILD_ID_DUST, V_LEVEL); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Dust Sensor", "1.1"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_DUST, S_DUST); +} + +void loop() +{ + uint16_t voMeasured = analogRead(DUST_SENSOR_ANALOG_PIN);// Get DUST value + + // 0 - 5V mapped to 0 - 1023 integer values + // recover voltage + calcVoltage = voMeasured * (5.0 / 1024.0); + + // linear eqaution taken from http://www.howmuchsnow.com/arduino/airquality/ + // Chris Nafis (c) 2012 + dustDensity = (0.17 * calcVoltage - 0.1)*1000; + + Serial.print("Raw Signal Value (0-1023): "); + Serial.print(voMeasured); + + Serial.print(" - Voltage: "); + Serial.print(calcVoltage); + + Serial.print(" - Dust Density: "); + Serial.println(dustDensity); // unit: ug/m3 + + if (ceil(dustDensity) != lastDUST) { + send(dustMsg.set((int)ceil(dustDensity))); + lastDUST = ceil(dustDensity); + } + + sleep(SLEEP_TIME); +} diff --git a/libraries/MySensors/examples/DustSensorDSM/DustSensorDSM.ino b/libraries/MySensors/examples/DustSensorDSM/DustSensorDSM.ino new file mode 100644 index 0000000..0e4d724 --- /dev/null +++ b/libraries/MySensors/examples/DustSensorDSM/DustSensorDSM.ino @@ -0,0 +1,146 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * Dust Sensor for SamYoung DSM501 + * connect the sensor as follows : + * Pin 2 of dust sensor PM1 -> Digital 3 (PMW) + * Pin 3 of dust sensor -> +5V + * Pin 4 of dust sensor PM2.5 -> Digital 6 (PWM) + * Pin 5 of dust sensor -> Ground + * Datasheet: http://www.samyoungsnc.com/products/3-1%20Specification%20DSM501.pdf +* Contributor: epierre +**/ + +// Enable debug prints +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define CHILD_ID_DUST_PM10 0 +#define CHILD_ID_DUST_PM25 1 +#define DUST_SENSOR_DIGITAL_PIN_PM10 6 +#define DUST_SENSOR_DIGITAL_PIN_PM25 3 + +unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) +//VARIABLES +int val = 0; // variable to store the value coming from the sensor +float valDUSTPM25 =0.0; +float lastDUSTPM25 =0.0; +float valDUSTPM10 =0.0; +float lastDUSTPM10 =0.0; +unsigned long duration; +unsigned long starttime; +unsigned long endtime; +unsigned long sampletime_ms = 30000; +unsigned long lowpulseoccupancy = 0; +float ratio = 0; +long concentrationPM25 = 0; +long concentrationPM10 = 0; + +MyMessage dustMsgPM10(CHILD_ID_DUST_PM10, V_LEVEL); +MyMessage msgPM10(CHILD_ID_DUST_PM10, V_UNIT_PREFIX); +MyMessage dustMsgPM25(CHILD_ID_DUST_PM25, V_LEVEL); +MyMessage msgPM25(CHILD_ID_DUST_PM25, V_UNIT_PREFIX); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Dust Sensor DSM501", "1.4"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_DUST_PM10, S_DUST); + send(msgPM10.set("ppm")); + present(CHILD_ID_DUST_PM25, S_DUST); + send(msgPM25.set("ppm")); + + pinMode(DUST_SENSOR_DIGITAL_PIN_PM10,INPUT); + pinMode(DUST_SENSOR_DIGITAL_PIN_PM25,INPUT); +} + +void loop() +{ + + //get PM 2.5 density of particles over 2.5 μm. + concentrationPM25=(long)getPM(DUST_SENSOR_DIGITAL_PIN_PM25); + Serial.print("PM25: "); + Serial.println(concentrationPM25); + Serial.print("\n"); + + if ((concentrationPM25 != lastDUSTPM25)&&(concentrationPM25>0)) { + send(dustMsgPM25.set((long)ceil(concentrationPM25))); + lastDUSTPM25 = ceil(concentrationPM25); + } + + //get PM 1.0 - density of particles over 1 μm. + concentrationPM10=getPM(DUST_SENSOR_DIGITAL_PIN_PM10); + Serial.print("PM10: "); + Serial.println(concentrationPM10); + Serial.print("\n"); + //ppmv=mg/m3 * (0.08205*Tmp)/Molecular_mass + //0.08205 = Universal gas constant in atm·m3/(kmol·K) + int temp=20; //external temperature, if you can replace this with a DHT11 or better + long ppmv=(concentrationPM10*0.0283168/100/1000) * (0.08205*temp)/0.01; + + if ((ceil(concentrationPM10) != lastDUSTPM10)&&((long)concentrationPM10>0)) { + send(dustMsgPM10.set((long)ppmv)); + lastDUSTPM10 = ceil(concentrationPM10); + } + + //sleep to save on radio + sleep(SLEEP_TIME); + +} + + +long getPM(int DUST_SENSOR_DIGITAL_PIN) { + + starttime = millis(); + + while (1) { + + duration = pulseIn(DUST_SENSOR_DIGITAL_PIN, LOW); + lowpulseoccupancy += duration; + endtime = millis(); + + if ((endtime-starttime) > sampletime_ms) + { + ratio = (lowpulseoccupancy-endtime+starttime)/(sampletime_ms*10.0); // Integer percentage 0=>100 + long concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve + //Serial.print("lowpulseoccupancy:"); + //Serial.print(lowpulseoccupancy); + //Serial.print("\n"); + //Serial.print("ratio:"); + //Serial.print(ratio); + //Serial.print("\n"); + //Serial.print("DSM501A:"); + //Serial.println(concentration); + //Serial.print("\n"); + + lowpulseoccupancy = 0; + return(concentration); + } + } +} diff --git a/libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino b/libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino new file mode 100644 index 0000000..1ddcdd0 --- /dev/null +++ b/libraries/MySensors/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino @@ -0,0 +1,151 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * + * DESCRIPTION + * This sketch provides an example how to implement a distance sensor using HC-SR04 + * Use this sensor to measure KWH and Watt of your house meeter + * You need to set the correct pulsefactor of your meeter (blinks per KWH). + * The sensor starts by fetching current KWH value from gateway. + * Reports both KWH and Watt back to gateway. + * + * Unfortunately millis() won't increment when the Arduino is in + * sleepmode. So we cannot make this sensor sleep if we also want + * to calculate/report watt-number. + * http://www.mysensors.org/build/pulse_power + */ + +// Enable debug prints +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) +#define PULSE_FACTOR 1000 // Nummber of blinks per KWH of your meeter +#define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false. +#define MAX_WATT 10000 // Max watt value to report. This filetrs outliers. +#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) +#define CHILD_ID 1 // Id of the sensor child + +unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. +double ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour +boolean pcReceived = false; +volatile unsigned long pulseCount = 0; +volatile unsigned long lastBlink = 0; +volatile unsigned long watt = 0; +unsigned long oldPulseCount = 0; +unsigned long oldWatt = 0; +double oldKwh; +unsigned long lastSend; +MyMessage wattMsg(CHILD_ID,V_WATT); +MyMessage kwhMsg(CHILD_ID,V_KWH); +MyMessage pcMsg(CHILD_ID,V_VAR1); + + +void setup() +{ + // Initialize library and add callback for incoming messages (signing is required) + setIncomingCallback(incomingMessage); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Energy Meter", "1.0"); + + // Register this device as power sensor + present(CHILD_ID, S_POWER); + + // Fetch last known pulse count value from gw + request(CHILD_ID, V_VAR1); + + attachInterrupt(INTERRUPT, onPulse, RISING); + lastSend=millis(); +} + + +void loop() +{ + unsigned long now = millis(); + // Only send values at a maximum frequency or woken up from sleep + bool sendTime = now - lastSend > SEND_FREQUENCY; + if (pcReceived && (SLEEP_MODE || sendTime)) { + // New watt value has been calculated + if (!SLEEP_MODE && watt != oldWatt) { + // Check that we dont get unresonable large watt value. + // could hapen when long wraps or false interrupt triggered + if (watt<((unsigned long)MAX_WATT)) { + send(wattMsg.set(watt)); // Send watt value to gw + } + Serial.print("Watt:"); + Serial.println(watt); + oldWatt = watt; + } + + // Pulse cout has changed + if (pulseCount != oldPulseCount) { + send(pcMsg.set(pulseCount)); // Send pulse count value to gw + double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); + oldPulseCount = pulseCount; + if (kwh != oldKwh) { + send(kwhMsg.set(kwh, 4)); // Send kwh value to gw + oldKwh = kwh; + } + } + lastSend = now; + } else if (sendTime && !pcReceived) { + // No count received. Try requesting it again + request(CHILD_ID, V_VAR1); + lastSend=now; + } + + if (SLEEP_MODE) { + sleep(SEND_FREQUENCY); + } +} + +void incomingMessage(const MyMessage &message) { + if (message.type==V_VAR1) { + pulseCount = oldPulseCount = message.getLong(); + Serial.print("Received last pulse count from gw:"); + Serial.println(pulseCount); + pcReceived = true; + } +} + +void onPulse() +{ + if (!SLEEP_MODE) { + unsigned long newBlink = micros(); + unsigned long interval = newBlink-lastBlink; + if (interval<10000L) { // Sometimes we get interrupt on RISING + return; + } + watt = (3600000000.0 /interval) / ppwh; + lastBlink = newBlink; + } + pulseCount++; +} + + + diff --git a/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino b/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino new file mode 100644 index 0000000..ee828b5 --- /dev/null +++ b/libraries/MySensors/examples/Esp8266Gateway/Esp8266Gateway.ino @@ -0,0 +1,265 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * Contribution by a-lurker and Anticimex, + * Contribution by Norbert Truchsess + * Contribution by Ivo Pullens (ESP8266 support) + * + * DESCRIPTION + * The EthernetGateway sends data received from sensors to the WiFi link. + * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. + * + * VERA CONFIGURATION: + * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. + * E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003 + * + * LED purposes: + * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h + * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved + * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly + * - ERR (red) - fast blink on error during transmission error or recieve crc error + * + * See http://www.mysensors.org/build/ethernet_gateway for wiring instructions. + * The ESP8266 however requires different wiring: + * nRF24L01+ ESP8266 + * VCC VCC + * CE GPIO4 + * CSN/CS GPIO15 + * SCK GPIO14 + * MISO GPIO12 + * MOSI GPIO13 + * + * Not all ESP8266 modules have all pins available on their external interface. + * This code has been tested on an ESP-12 module. + * The ESP8266 requires a certain pin configuration to download code, and another one to run code: + * - Connect REST (reset) via 10K pullup resistor to VCC, and via switch to GND ('reset switch') + * - Connect GPIO15 via 10K pulldown resistor to GND + * - Connect CH_PD via 10K resistor to VCC + * - Connect GPIO2 via 10K resistor to VCC + * - Connect GPIO0 via 10K resistor to VCC, and via switch to GND ('bootload switch') + * + * Inclusion mode button: + * - Connect GPIO5 via switch to GND ('inclusion switch') + * + * Hardware SHA204 signing is currently not supported! + * + * Make sure to fill in your ssid and WiFi password below for ssid & pass. + */ +#define NO_PORTB_PINCHANGES + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "GatewayUtil.h" + +const char *ssid = "MySSID"; // cannot be longer than 32 characters! +const char *pass = "MyVerySecretPassword"; // + +#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled +#define INCLUSION_MODE_PIN 5 // Digital pin used for inclusion mode button + +#define RADIO_CE_PIN 4 // radio chip enable +#define RADIO_SPI_SS_PIN 15 // radio SPI serial select + +#ifdef WITH_LEDS_BLINKING +#define RADIO_ERROR_LED_PIN 7 // Error led pin +#define RADIO_RX_LED_PIN 8 // Receive led pin +#define RADIO_TX_LED_PIN 9 // the PCB, on board LED +#endif + + +// NRFRF24L01 radio driver (set low transmit power by default) +MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW); +//MyTransportRFM69 transport; + + +// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +#ifdef MY_SIGNING_FEATURE +MySigningNone signer; +//MySigningAtsha204Soft signer; +#endif + +// Hardware profile +MyHwESP8266 hw; + +// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h +MySensor gw(transport, hw +#ifdef MY_SIGNING_FEATURE + , signer +#endif +#ifdef WITH_LEDS_BLINKING + , RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN +#endif + ); + + +#define IP_PORT 5003 // The port you want to open +#define MAX_SRV_CLIENTS 5 // how many clients should be able to telnet to this ESP8266 + +// a R/W server on the port +static WiFiServer server(IP_PORT); +static WiFiClient clients[MAX_SRV_CLIENTS]; +static bool clientsConnected[MAX_SRV_CLIENTS]; +static inputBuffer inputString[MAX_SRV_CLIENTS]; + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + + +void output(const char *fmt, ... ) +{ + char serialBuffer[MAX_SEND_LENGTH]; + va_list args; + va_start (args, fmt ); + vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args); + va_end (args); + Serial.print(serialBuffer); + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) + { + if (clients[i] && clients[i].connected()) + { +// Serial.print("Client "); Serial.print(i); Serial.println(" write"); + clients[i].write((uint8_t*)serialBuffer, strlen(serialBuffer)); + } + } +} + +void setup() +{ + // Setup console + hw_init(); + + Serial.println(); Serial.println(); + Serial.println("ESP8266 MySensors Gateway"); + Serial.print("Connecting to "); Serial.println(ssid); + + (void)WiFi.begin(ssid, pass); + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print("."); + } + Serial.println("Connected!"); + Serial.print("IP: "); Serial.println(WiFi.localIP()); + Serial.flush(); + + setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output); + + // Initialize gateway at maximum PA level, channel 70 and callback for write operations + gw.begin(incomingMessage, 0, true, 0); + + // start listening for clients + server.begin(); + server.setNoDelay(true); +} + + +void loop() { + gw.process(); + + checkButtonTriggeredInclusion(); + checkInclusionFinished(); + + // Go over list of clients and stop any that are no longer connected. + // If the server has a new client connection it will be assigned to a free slot. + bool allSlotsOccupied = true; + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) + { + if (!clients[i].connected()) + { + if (clientsConnected[i]) + { + Serial.print("Client "); Serial.print(i); Serial.println(" disconnected"); + clients[i].stop(); + } + //check if there are any new clients + if (server.hasClient()) + { + clients[i] = server.available(); + inputString[i].idx = 0; + Serial.print("Client "); Serial.print(i); Serial.println(" connected"); + output(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY); + } + } + bool connected = clients[i].connected(); + clientsConnected[i] = connected; + allSlotsOccupied &= connected; + } + if (allSlotsOccupied && server.hasClient()) + { + //no free/disconnected spot so reject + Serial.println("No free slot available"); + WiFiClient c = server.available(); + c.stop(); + } + + // Loop over clients connect and read available data + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) + { + while(clients[i].connected() && clients[i].available()) + { + char inChar = clients[i].read(); + if ( inputString[i].idx < MAX_RECEIVE_LENGTH - 1 ) + { + // if newline then command is complete + if (inChar == '\n') + { + // a command was issued by the client + // we will now try to send it to the actuator + inputString[i].string[inputString[i].idx] = 0; + + // echo the string to the serial port + Serial.print("Client "); Serial.print(i); Serial.print(": "); Serial.println(inputString[i].string); + + parseAndSend(gw, inputString[i].string); + + // clear the string: + inputString[i].idx = 0; + // Finished with this client's message. Next loop() we'll see if there's more to read. + break; + } else { + // add it to the inputString: + inputString[i].string[inputString[i].idx++] = inChar; + } + } else { + // Incoming message too long. Throw away + Serial.print("Client "); Serial.print(i); Serial.println(": Message too long"); + inputString[i].idx = 0; + // Finished with this client's message. Next loop() we'll see if there's more to read. + break; + } + } + } +} + + + diff --git a/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h b/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h new file mode 100644 index 0000000..fa814b3 --- /dev/null +++ b/libraries/MySensors/examples/Esp8266Gateway/GatewayUtil.h @@ -0,0 +1,136 @@ +#ifndef __GATEWAYUTIL_H__ +#define __GATEWAYUTIL_H__ + +#ifdef ARDUINO + +static uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled +static uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode + +#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller +#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller + + +typedef struct +{ + char string[MAX_RECEIVE_LENGTH]; + uint8_t idx; +} inputBuffer; + +static volatile boolean buttonTriggeredInclusion; +static boolean inclusionMode; // Keeps track on inclusion mode +bool inclusionButtonSupported = false; +void (*serial)(const char *fmt, ... ); + +MyParserSerial parser; + +void setInclusionMode(boolean newMode); + +char convBuf[MAX_PAYLOAD*2+1]; +unsigned long inclusionStartTime; + + +void startInclusionInterrupt() { + buttonTriggeredInclusion = true; +} + +void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) { + inclusionMode = 0; + buttonTriggeredInclusion = false; + serial = _serial; + + inclusionTime = _incTime; + inclusionButtonSupported = (_inc != 255); + if (inclusionButtonSupported) + { + pinInclusion = _inc; + + // Setup digital in that triggers inclusion mode + pinMode(pinInclusion, INPUT_PULLUP); + + // Add interrupt for inclusion button to pin + attachInterrupt(pinInclusion, startInclusionInterrupt, FALLING); + } +} + +void incomingMessage(const MyMessage &message) { +// if (mGetCommand(message) == C_PRESENTATION && inclusionMode) { +// gw.rxBlink(3); +// } else { +// gw.rxBlink(1); +// } + // Pass along the message from sensors to serial line + serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf)); +} + + + +void checkButtonTriggeredInclusion() { + if (inclusionButtonSupported) + { + if (buttonTriggeredInclusion) { + // Ok, someone pressed the inclusion button on the gateway + // start inclusion mode for 1 munute. + #ifdef DEBUG + serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE); + #endif + buttonTriggeredInclusion = false; + setInclusionMode(true); + } + } +} + +void checkInclusionFinished() { + if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) { + // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode + setInclusionMode(false); + } +} + +void parseAndSend(MySensor &gw, char *commandBuffer) { + boolean ok; + MyMessage &msg = gw.getLastMessage(); + + if (parser.parse(msg, commandBuffer)) { + uint8_t command = mGetCommand(msg); + + if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { + // Handle messages directed to gateway + if (msg.type == I_VERSION) { + // Request for version + serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); + } else if (msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + setInclusionMode(atoi(msg.data) == 1); + } + } else { + #ifdef WITH_LEDS_BLINKING + gw.txBlink(1); + #endif + ok = gw.sendRoute(msg); + if (!ok) { + #ifdef WITH_LEDS_BLINKING + gw.errBlink(1); + #endif + } + } + } +} + +void setInclusionMode(boolean newMode) { + if (newMode != inclusionMode) { + inclusionMode = newMode; + // Send back mode change on serial line to ack command + serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0); + + if (inclusionMode) { + inclusionStartTime = millis(); + } + } +} + + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino new file mode 100644 index 0000000..9fd07aa --- /dev/null +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -0,0 +1,125 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * Contribution by a-lurker and Anticimex, + * Contribution by Norbert Truchsess + * Contribution by Tomas Hozza + * + * + * DESCRIPTION + * The EthernetGateway sends data received from sensors to the ethernet link. + * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. + * + * The GW code is designed for Arduino 328p / 16MHz. ATmega168 does not have enough memory to run this program. + * + * + * COMPILING WIZNET (W5100) ETHERNET MODULE + * > Edit MyConfig.h in (libraries\MySensors\) to enable softspi (remove // before "#define SOFTSPI"). + * + * COMPILING ENC28J60 ETHERNET MODULE + * > Use Arduino IDE 1.5.7 (or later) + * > Disable DEBUG in Sensor.h before compiling this sketch. Othervise the sketch will probably not fit in program space when downloading. + * > Remove Ethernet.h include below and include UIPEthernet.h + * > Remove DigitalIO include + * Note that I had to disable UDP and DHCP support in uipethernet-conf.h to reduce space. (which means you have to choose a static IP for that module) + * + * VERA CONFIGURATION: + * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. + * E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003 + * + * LED purposes: + * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h + * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved + * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly + * - ERR (red) - fast blink on error during transmission error or recieve crc error + * + * See http://www.mysensors.org/build/ethernet_gateway for wiring instructions. + * + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +// Enable gateway transportation type +#define MY_GATEWAY_W5100 +//#define MY_GATEWAY_ENC28J60 + +// Enable Soft SPI for radio (note different radio wiring required) +// Useful for W5100 which sometimes have hard time co-operate with radio on the same spi bus. +//#define MY_SOFTSPI +//#define MY_SOFT_SPI_SCK_PIN 14 +//#define MY_SOFT_SPI_MISO_PIN 16 +//#define MY_SOFT_SPI_MOSI_PIN 15 + + +// Enable to use UDP +#define MY_USE_UDP + +#define MY_IP_ADDRESS 192,168,178,66 // If this is disabled, DHCP is used to retrieve address +// Renewal period if using DHCP +//#define MY_IP_RENEWAL_INTERVAL 60000 +// The port to keep open on node server mode / or port to contact in client mode +#define MY_PORT 5003 + +// Controller ip address (enables client mode). Undefine this to act as sever. +#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 + +// The MAC address can be anything you want but should be unique on your network. +// Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. +// Note that most of the Ardunio examples use "DEAD BEEF FEED" for the MAC address. +#define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED + +// Flash leds on rx/tx/err +#define MY_LEDS_BLINKING_FEATURE +// Set blinking period +#define MY_DEFAULT_LED_BLINK_PERIOD 300 + +// Enable inclusion mode +#define MY_INCLUSION_MODE_FEATURE +// Enable Inclusion mode button on gateway +#define MY_INCLUSION_BUTTON_FEATURE +// Set inclusion mode duration (in seconds) +#define MY_INCLUSION_MODE_DURATION 60 +// Digital pin used for inclusion mode button +#define MY_INCLUSION_MODE_BUTTON_PIN 3 + +#define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin +#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin +#define MY_DEFAULT_TX_LED_PIN 9 // the PCB, on board LED + +#define MY_RADIO_CE_PIN 5 // radio chip enable +#define MY_RADIO_SPI_SS_PIN 6 // radio SPI serial select + +#include + + +void setup() +{ +} + +void loop() { +} + diff --git a/libraries/MySensors/examples/HumiditySensor/HumiditySensor.ino b/libraries/MySensors/examples/HumiditySensor/HumiditySensor.ino new file mode 100644 index 0000000..fee90ea --- /dev/null +++ b/libraries/MySensors/examples/HumiditySensor/HumiditySensor.ino @@ -0,0 +1,97 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * + * DESCRIPTION + * This sketch provides an example how to implement a humidity/temperature + * sensor using DHT11/DHT-22 + * http://www.mysensors.org/build/humidity + */ + +// Enable debug prints +//#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +#define CHILD_ID_HUM 0 +#define CHILD_ID_TEMP 1 +#define HUMIDITY_SENSOR_DIGITAL_PIN 3 +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) + +DHT dht; +float lastTemp; +float lastHum; +boolean metric = true; +MyMessage msgHum(CHILD_ID_HUM, V_HUM); +MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); + + +void setup() +{ + dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); + + // Send the Sketch Version Information to the Gateway + sendSketchInfo("Humidity", "1.0"); + + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID_HUM, S_HUM); + present(CHILD_ID_TEMP, S_TEMP); + + metric = getConfig().isMetric; +} + +void loop() +{ + delay(dht.getMinimumSamplingPeriod()); + + float temperature = dht.getTemperature(); + if (isnan(temperature)) { + Serial.println("Failed reading temperature from DHT"); + } else if (temperature != lastTemp) { + lastTemp = temperature; + if (!metric) { + temperature = dht.toFahrenheit(temperature); + } + send(msgTemp.set(temperature, 1)); + Serial.print("T: "); + Serial.println(temperature); + } + + float humidity = dht.getHumidity(); + if (isnan(humidity)) { + Serial.println("Failed reading humidity from DHT"); + } else if (humidity != lastHum) { + lastHum = humidity; + send(msgHum.set(humidity, 1)); + Serial.print("H: "); + Serial.println(humidity); + } + + sleep(SLEEP_TIME); //sleep a bit +} + + diff --git a/libraries/MySensors/examples/IrSensor/IrSensor.ino b/libraries/MySensors/examples/IrSensor/IrSensor.ino new file mode 100644 index 0000000..95afd5a --- /dev/null +++ b/libraries/MySensors/examples/IrSensor/IrSensor.ino @@ -0,0 +1,148 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * + * DESCRIPTION + * Example sketch showing how to control ir devices + * An IR LED must be connected to Arduino PWM pin 3. + * An optional ir receiver can be connected to PWM pin 8. + * All receied ir signals will be sent to gateway device stored in VAR_1. + * When binary light on is clicked - sketch will send volume up ir command + * When binary light off is clicked - sketch will send volume down ir command + * http://www.mysensors.org/build/ir + */ + +// Enable debug prints +//#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +int RECV_PIN = 8; + +#define CHILD_1 3 // childId + +IRsend irsend; +IRrecv irrecv(RECV_PIN); +IRdecode decoder; +//decode_results results; +unsigned int Buffer[RAWBUF]; +MyMessage msg(CHILD_1, V_VAR1); + +void setup() +{ + irrecv.enableIRIn(); // Start the ir receiver + decoder.UseExtnBuf(Buffer); + setIncomingCallback(incomingMessage); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("IR Sensor", "1.0"); + + // Register a sensors to Use binary light for test purposes. + present(CHILD_1, S_LIGHT); +} + + +void loop() +{ + if (irrecv.GetResults(&decoder)) { + irrecv.resume(); + decoder.decode(); + decoder.DumpResults(); + + char buffer[10]; + sprintf(buffer, "%08lx", decoder.value); + // Send ir result to gw + send(msg.set(buffer)); + } +} + + + +void incomingMessage(const MyMessage &message) { + // We only expect one type of message from controller. But we better check anyway. + if (message.type==V_LIGHT) { + int incomingRelayStatus = message.getInt(); + if (incomingRelayStatus == 1) { + irsend.send(NEC, 0x1EE17887, 32); // Vol up yamaha ysp-900 + } else { + irsend.send(NEC, 0x1EE1F807, 32); // Vol down yamaha ysp-900 + } + // Start receiving ir again... + irrecv.enableIRIn(); + } +} + +// Dumps out the decode_results structure. +// Call this after IRrecv::decode() +// void * to work around compiler issue +//void dump(void *v) { +// decode_results *results = (decode_results *)v +/*void dump(decode_results *results) { + int count = results->rawlen; + if (results->decode_type == UNKNOWN) { + Serial.print("Unknown encoding: "); + } + else if (results->decode_type == NEC) { + Serial.print("Decoded NEC: "); + } + else if (results->decode_type == SONY) { + Serial.print("Decoded SONY: "); + } + else if (results->decode_type == RC5) { + Serial.print("Decoded RC5: "); + } + else if (results->decode_type == RC6) { + Serial.print("Decoded RC6: "); + } + else if (results->decode_type == PANASONIC) { + Serial.print("Decoded PANASONIC - Address: "); + Serial.print(results->panasonicAddress,HEX); + Serial.print(" Value: "); + } + else if (results->decode_type == JVC) { + Serial.print("Decoded JVC: "); + } + Serial.print(results->value, HEX); + Serial.print(" ("); + Serial.print(results->bits, DEC); + Serial.println(" bits)"); + Serial.print("Raw ("); + Serial.print(count, DEC); + Serial.print("): "); + + for (int i = 0; i < count; i++) { + if ((i % 2) == 1) { + Serial.print(results->rawbuf[i]*USECPERTICK, DEC); + } + else { + Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); + } + Serial.print(" "); + } + Serial.println(""); +} +*/ diff --git a/libraries/MySensors/examples/IrrigationController/IrrigationController.ino b/libraries/MySensors/examples/IrrigationController/IrrigationController.ino new file mode 100644 index 0000000..7689cb1 --- /dev/null +++ b/libraries/MySensors/examples/IrrigationController/IrrigationController.ino @@ -0,0 +1,876 @@ +/* +MySprinkler for MySensors + +Arduino Multi-Zone Sprinkler Control + +May 31, 2015 + +*** Version 2.0 + +*** Upgraded to http://MySensors.org version 1.4.1 +*** Expanded for up to 16 Valves +*** Setup for active low relay board or comment out #define ACTIVE_LOW to switch to active high +*** Switch to bitshift method vs byte arrays +*** Changed RUN_ALL_ZONES Vera device to 0 (was highest valve) +*** Added optional LCD display featuring remaining time, date last ran & current time +*** Features 'raindrop' and 'clock' icons which indicate sensor is updating valve data and clock respectively +*** Added single pushbutton menu to manually select which program to run (All Zones or a Single Zone) +*** Added option of naming your Zones programmatically or with Vera (V_VAR3 used to store names) + +Utilizing your Vera home automation controller and the MySensors.org gateway you can +control up to a sixteen zone irrigation system with only three digital pins. This sketch +will create NUMBER_OF_VALVES + 1 devices on your Vera controller + +This sketch features the following: + +* Allows you to cycle through All zones (RUN_ALL_ZONES) or individual zone (RUN_SINGLE_ZONE) control. +* Use the 0th controller to activate RUN_ALL_ZONES (each zone in numeric sequence 1 to n) + using Variable1 as the "ON" time in minutes in each of the vera devices created. +* Use the individual zone controller to activate a single zone. This feature uses + Variable2 as the "ON" time for each individual device/zone. +* Connect according to pinout below and uses Shift Registers as to allow the MySensors + standard radio configuration and still leave available digital pins +* Turning on any zone will stop the current process and begin that particular process. +* Turning off any zone will stop the current process and turn off all zones. +* To push your new time intervals for your zones, simply change the variable on your Vera and + your arduino will call to Vera once a minute and update accordingly. Variables will also be + requested when the device is first powered on. +* Pushbutton activation to RUN_ALL_ZONES, RUN_SINGLE_ZONE or halt the current program +* LED status indicator + +PARTS LIST: +Available from the MySensors store - http://www.mysensors.org/store/ +* Relays (8 channel) +* Female Pin Header Connector Strip +* Prototype Universal Printed Circuit Boards (PCB) +* NRF24L01 Radio +* Arduino (I used a Pro Mini) +* FTDI USB to TTL Serial Adapter +* Capacitors (10uf and .1uf) +* 3.3v voltage regulator +* Resistors (270 & 10K) +* Female Dupont Cables +* 1602 LCD (with I2C Interface) +* LED +* Push button +* Shift Register (SN74HC595) +* 2 Pole 5mm Pitch PCB Mount Screw Terminal Block +* 3 Pole 5mm Pitch PCB Mount Screw Terminal Block +* 22-24 gauge wire or similar (I used Cat5/Cat6 cable) +* 18 gauge wire (for relay) +* Irrigation Power Supply (24-Volt/750 mA Transformer) + + +INSTRUCTIONS: + +* A step-by-step setup video is available here: http://youtu.be/l4GPRTsuHkI +* After assembling your arduino, radio, decoupling capacitors, shift register(s), status LED, pushbutton LCD (I2C connected to + A4 and A5) and relays, and load the sketch. +* Following the instructions at https://MySensors.org include the device to your MySensors Gateway. +* Verify that each new device has a Variable1, Variable2 and Variable3. Populate data accordingly with whole minutes for + the RUN_ALL_ZONES routine (Variable1) and the RUN_SINGLE_ZONE routines (Variable 2). The values entered for times may be zero and + you may use the defaulet zone names by leaving Variable3 blank. +* Once you have entered values for each zone and each variable, save the settings by pressing the red save button on your Vera. +* Restart your arduino; verify the settings are loaded into your arduino with the serial monitor; the array will be printed + on the serial monitor. +* Your arduino should slow-flash, indicating that it is in ready mode. +* There are multiple debug serial prints that can be monitored to assure that it is operating properly. +* ***THIS SHOULD NO LONGER BE NEEDED*** The standard MySensors library now works. https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads for the I2C library, or use yours + +Contributed by Jim (BulldogLowell@gmail.com) with much contribution from Pete (pete.will@mysensors.org) and is released to the public domain +*/ +// + +// Enable debug prints +//#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +//#define MY_NODE_ID 1 // Set this to fix your Radio ID or use Auto + +#include +#include +#include +#include +#include + + +#define NUMBER_OF_VALVES 8 // Change this to set your valve count up to 16. +#define VALVE_RESET_TIME 7500UL // Change this (in milliseconds) for the time you need your valves to hydraulically reset and change state + +#define SKETCH_NAME "MySprinkler" +#define SKETCH_VERSION "2.0" +// +#define CHILD_ID_SPRINKLER 0 +// +#define ACTIVE_LOW // comment out this line if your relays are active high +// +#define DEBUG_ON // comment out to supress serial monitor output +// +#ifdef ACTIVE_LOW +#define BITSHIFT_VALVE_NUMBER ~(1U << (valveNumber-1)) +#define ALL_VALVES_OFF 0xFFFF +#else +#define BITSHIFT_VALVE_NUMBER (1U << (valveNumber-1)) +#define ALL_VALVES_OFF 0U +#endif +// +#ifdef DEBUG_ON +#define DEBUG_PRINT(x) Serial.print(x) +#define DEBUG_PRINTLN(x) Serial.println(x) +#else +#define DEBUG_PRINT(x) +#define DEBUG_PRINTLN(x) +#define SERIAL_START(x) +#endif +// +typedef enum { + STAND_BY_ALL_OFF, RUN_SINGLE_ZONE, RUN_ALL_ZONES, CYCLE_COMPLETE, ZONE_SELECT_MENU +} +SprinklerStates; +// +SprinklerStates state = STAND_BY_ALL_OFF; +SprinklerStates lastState; +byte menuState = 0; +unsigned long menuTimer; +byte countDownTime = 10; +// +int allZoneTime [NUMBER_OF_VALVES + 1]; +int valveSoloTime [NUMBER_OF_VALVES + 1]; +int valveNumber; +int lastValve; +unsigned long startMillis; +const int ledPin = 5; +const int waterButtonPin = 3; +boolean buttonPushed = false; +boolean showTime = true; +boolean clockUpdating = false; +boolean recentUpdate = true; +const char *dayOfWeek[] = { + "Null", "Sunday ", "Monday ", "Tuesday ", "Wednesday ", "Thursday ", "Friday ", "Saturday " +}; +// Name your Zones here or use Vera to edit them by adding a name in Variable3... +String valveNickName[17] = { + "All Zones", "Zone 1", "Zone 2", "Zone 3", "Zone 4", "Zone 5", "Zone 6", "Zone 7", "Zone 8", "Zone 9", "Zone 10", "Zone 11", "Zone 12", "Zone 13", "Zone 14", "Zone 15", "Zone 16" +}; +// +time_t lastTimeRun = 0; +//Setup Shift Register... +const int latchPin = 8; +const int clockPin = 4; +const int dataPin = 7; +// +byte clock[8] = {0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0}; // fetching time indicator +byte raindrop[8] = {0x4, 0x4, 0xA, 0xA, 0x11, 0xE, 0x0,}; // fetching Valve Data indicator +// Set the pins on the I2C chip used for LCD connections: +// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol +LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address to 0x27 +// +MyMessage msg1valve(CHILD_ID_SPRINKLER, V_LIGHT); +MyMessage var1valve(CHILD_ID_SPRINKLER, V_VAR1); +MyMessage var2valve(CHILD_ID_SPRINKLER, V_VAR2); + +bool receivedInitialValue = false; +// +void setup() +{ + DEBUG_PRINTLN(F("Initialising...")); + pinMode(latchPin, OUTPUT); + pinMode(clockPin, OUTPUT); + pinMode(dataPin, OUTPUT); + pinMode(ledPin, OUTPUT); + pinMode(waterButtonPin, INPUT_PULLUP); + //pinMode(waterButtonPin, INPUT); + attachInterrupt(1, PushButton, RISING); //May need to change for your Arduino model + digitalWrite (ledPin, HIGH); + DEBUG_PRINTLN(F("Turning All Valves Off...")); + updateRelays(ALL_VALVES_OFF); + //delay(5000); + lcd.begin(16, 2); //(16 characters and 2 line display) + lcd.clear(); + lcd.backlight(); + lcd.createChar(0, clock); + lcd.createChar(1, raindrop); + // + //check for saved date in EEPROM + DEBUG_PRINTLN(F("Checking EEPROM for stored date:")); + delay(500); + if (loadState(0) == 0xFF) // EEPROM flag + { + DEBUG_PRINTLN(F("Retreiving last run time from EEPROM...")); + for (int i = 0; i < 4 ; i++) + { + lastTimeRun = lastTimeRun << 8; + lastTimeRun = lastTimeRun | loadState(i + 1); // assemble 4 bytes into an ussigned long epoch timestamp + } + } + setIncomingCallback(getVariables); + sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + present(i, S_LIGHT); + } + DEBUG_PRINTLN(F("Sensor Presentation Complete")); + // + digitalWrite (ledPin, LOW); + DEBUG_PRINTLN(F("Ready...")); + // + lcd.setCursor(0, 0); + lcd.print(F(" Syncing Time ")); + lcd.setCursor(15, 0); + lcd.write(byte(0)); + lcd.setCursor(0, 1); + int clockCounter = 0; + while (timeStatus() == timeNotSet && clockCounter < 21) + { + requestTime(receiveTime); + DEBUG_PRINTLN(F("Requesting time from Gateway:")); + wait(1000); + lcd.print("."); + clockCounter++; + if (clockCounter > 16) + { + DEBUG_PRINTLN(F("Failed initial clock synchronization!")); + lcd.clear(); + lcd.print(F(" Failed Clock ")); + lcd.setCursor(0, 1); + lcd.print(F(" Syncronization ")); + wait(2000); + break; + } + } + // + lcd.clear(); + //Update valve data when first powered on + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + lcd.print(F(" Updating ")); + lcd.setCursor(0, 1); + lcd.print(F(" Valve Data: ")); + lcd.print(i); + boolean flashIcon = false; + DEBUG_PRINT(F("Calling for Valve ")); + DEBUG_PRINT(i); + DEBUG_PRINTLN(F(" Data...")); + while (!receivedInitialValue) + { + lcd.setCursor(15, 0); + flashIcon = !flashIcon; + flashIcon ? lcd.write(byte(1)) : lcd.print(F(" ")); + request(i, V_VAR1); + wait(500); + } + receivedInitialValue = false; + while (!receivedInitialValue) + { + lcd.setCursor(15, 0); + flashIcon = !flashIcon; + flashIcon ? lcd.write(byte(1)) : lcd.print(F(" ")); + request(i, V_VAR2); + wait(500); + } + receivedInitialValue = false; + while (!receivedInitialValue) + { + lcd.setCursor(15, 0); + flashIcon = !flashIcon; + flashIcon ? lcd.write(byte(1)) : lcd.print(F(" ")); + request(i, V_VAR3); + wait(500); + } + } + lcd.clear(); +} +// +void loop() +{ + updateClock(); + updateDisplay(); + goGetValveTimes(); + // + if (buttonPushed) + { + menuTimer = millis(); + DEBUG_PRINTLN(F("Button Pressed")); + if (state == STAND_BY_ALL_OFF) + { + state = ZONE_SELECT_MENU; + menuState = 0; + } + else if (state == ZONE_SELECT_MENU) + { + menuState++; + if (menuState > NUMBER_OF_VALVES) + { + menuState = 0; + } + } + else + { + state = STAND_BY_ALL_OFF; + } + buttonPushed = false; + } + if (state == STAND_BY_ALL_OFF) + { + slowToggleLED (); + if (state != lastState) + { + updateRelays(ALL_VALVES_OFF); + DEBUG_PRINTLN(F("State Changed... all Zones off")); + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + wait(50); + send(msg1valve.setSensor(i).set(false), false); + } + lcd.clear(); + lcd.setCursor(0,0); + lcd.print(F("** Irrigation **")); + lcd.setCursor(0,1); + lcd.print(F("** Halted **")); + wait(2000); + lastValve = -1; + } + } + // + else if (state == RUN_ALL_ZONES) + { + if (lastValve != valveNumber) + { + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + if (i == 0 || i == valveNumber) + { + send(msg1valve.setSensor(i).set(true), false); + } + else + { + send(msg1valve.setSensor(i).set(false), false); + } + } + } + lastValve = valveNumber; + fastToggleLed(); + if (state != lastState) + { + valveNumber = 1; + updateRelays(ALL_VALVES_OFF); + DEBUG_PRINTLN(F("State Changed, Running All Zones...")); + } + unsigned long nowMillis = millis(); + if (nowMillis - startMillis < VALVE_RESET_TIME) + { + updateRelays(ALL_VALVES_OFF); + } + else if (nowMillis - startMillis < (allZoneTime[valveNumber] * 60000UL)) + { + updateRelays(BITSHIFT_VALVE_NUMBER); + } + else + { + DEBUG_PRINTLN(F("Changing Valves...")); + updateRelays(ALL_VALVES_OFF); + startMillis = millis(); + valveNumber++; + if (valveNumber > NUMBER_OF_VALVES) + { + state = CYCLE_COMPLETE; + startMillis = millis(); + lastValve = -1; + lastTimeRun = now(); + saveDateToEEPROM(lastTimeRun); + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + send(msg1valve.setSensor(i).set(false), false); + } + DEBUG_PRINT(F("State = ")); + DEBUG_PRINTLN(state); + } + } + } + // + else if (state == RUN_SINGLE_ZONE) + { + fastToggleLed(); + if (state != lastState) + { + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + if (i == 0 || i == valveNumber) + { + send(msg1valve.setSensor(i).set(true), false); + } + else + { + send(msg1valve.setSensor(i).set(false), false); + } + } + DEBUG_PRINTLN(F("State Changed, Single Zone Running...")); + DEBUG_PRINT(F("Zone: ")); + DEBUG_PRINTLN(valveNumber); + } + unsigned long nowMillis = millis(); + if (nowMillis - startMillis < VALVE_RESET_TIME) + { + updateRelays(ALL_VALVES_OFF); + } + else if (nowMillis - startMillis < (valveSoloTime [valveNumber] * 60000UL)) + { + updateRelays(BITSHIFT_VALVE_NUMBER); + } + else + { + updateRelays(ALL_VALVES_OFF); + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + send(msg1valve.setSensor(i).set(false), false); + } + state = CYCLE_COMPLETE; + startMillis = millis(); + DEBUG_PRINT(F("State = ")); + DEBUG_PRINTLN(state); + } + lastTimeRun = now(); + } + else if (state == CYCLE_COMPLETE) + { + if (millis() - startMillis < 30000UL) + { + fastToggleLed(); + } + else + { + state = STAND_BY_ALL_OFF; + } + } + else if (state == ZONE_SELECT_MENU) + { + displayMenu(); + } + lastState = state; +} +// +void displayMenu(void) +{ + static byte lastMenuState = -1; + static int lastSecond; + if (menuState != lastMenuState) + { + lcd.clear(); + lcd.setCursor(0, 0); + lcd.print(valveNickName[menuState]); + lcd.setCursor(0, 1); + lcd.print(F("Starting")); + DEBUG_PRINT(valveNickName[menuState]); + Serial.print(F(" Starting Shortly")); + } + int thisSecond = (millis() - menuTimer) / 1000UL; + if (thisSecond != lastSecond && thisSecond < 8) + { + lcd.print(F(".")); + Serial.print("."); + } + lastSecond = thisSecond; + if (millis() - menuTimer > 10000UL) + { + startMillis = millis(); + if (menuState == 0) + { + valveNumber = 1; + state = RUN_ALL_ZONES; + } + else + { + valveNumber = menuState; + state = RUN_SINGLE_ZONE; + } + } + else + { + + } + lastMenuState = menuState; +} +// +void updateRelays(int value) +{ + digitalWrite(latchPin, LOW); + shiftOut(dataPin, clockPin, MSBFIRST, highByte(value)); + shiftOut(dataPin, clockPin, MSBFIRST, lowByte(value)); + digitalWrite(latchPin, HIGH); +} +// +void PushButton() //interrupt with debounce +{ + static unsigned long last_interrupt_time = 0; + unsigned long interrupt_time = millis(); + if (interrupt_time - last_interrupt_time > 200) + { + buttonPushed = true; + } + last_interrupt_time = interrupt_time; +} +// +void fastToggleLed() +{ + static unsigned long fastLedTimer; + if (millis() - fastLedTimer >= 100UL) + { + digitalWrite(ledPin, !digitalRead(ledPin)); + fastLedTimer = millis (); + } +} +// +void slowToggleLED () +{ + static unsigned long slowLedTimer; + if (millis() - slowLedTimer >= 1250UL) + { + digitalWrite(ledPin, !digitalRead(ledPin)); + slowLedTimer = millis (); + } +} +// +void getVariables(const MyMessage &message) +{ + boolean zoneTimeUpdate = false; + if (message.isAck()) + { + DEBUG_PRINTLN(F("This is an ack from gateway")); + } + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + if (message.sensor == i) + { + if (message.type == V_LIGHT) + { + int switchState = atoi(message.data); + if (switchState == 0) + { + state = STAND_BY_ALL_OFF; + DEBUG_PRINTLN(F("Recieved Instruction to Cancel...")); + } + else + { + if (i == 0) + { + state = RUN_ALL_ZONES; + valveNumber = 1; + DEBUG_PRINTLN(F("Recieved Instruction to Run All Zones...")); + } + else + { + state = RUN_SINGLE_ZONE; + valveNumber = i; + DEBUG_PRINT(F("Recieved Instruction to Activate Zone: ")); + DEBUG_PRINTLN(i); + } + } + startMillis = millis(); + } + else if (message.type == V_VAR1) + { + int variable1 = atoi(message.data);// RUN_ALL_ZONES time + DEBUG_PRINT(F("Recieved variable1 valve:")); + DEBUG_PRINT(i); + DEBUG_PRINT(F(" = ")); + DEBUG_PRINTLN(variable1); + if (variable1 != allZoneTime[i]) + { + allZoneTime[i] = variable1; + + zoneTimeUpdate = true; + } + receivedInitialValue = true; + } + else if (message.type == V_VAR2) + { + int variable2 = atoi(message.data);// RUN_SINGLE_ZONE time + DEBUG_PRINT(F("Recieved variable2 valve:")); + DEBUG_PRINT(i); + DEBUG_PRINT(F(" = ")); + DEBUG_PRINTLN(variable2); + if (variable2 != valveSoloTime[i]) + { + valveSoloTime[i] = variable2; + zoneTimeUpdate = true; + } + receivedInitialValue = true; + } + else if (message.type == V_VAR3) + { + String newMessage = String(message.data); + if (newMessage.length() == 0) + { + DEBUG_PRINT(F("No Name Recieved for zone ")); + DEBUG_PRINTLN(i); + break; + } + if (newMessage.length() > 16) + { + newMessage.substring(0, 16); + } + valveNickName[i] = ""; + valveNickName[i] += newMessage; + DEBUG_PRINT(F("Recieved new name for zone ")); + DEBUG_PRINT(i); + DEBUG_PRINT(F(" and it is now called: ")); + DEBUG_PRINTLN(valveNickName[i]); + } + receivedInitialValue = true; + } + } + if (zoneTimeUpdate) + { + // + DEBUG_PRINTLN(F("New Zone Times Recieved...")); + for (byte i = 0; i <= NUMBER_OF_VALVES; i++) + { + if (i != 0) + { + DEBUG_PRINT(F("Zone ")); + DEBUG_PRINT(i); + DEBUG_PRINT(F(" individual time: ")); + DEBUG_PRINT(valveSoloTime[i]); + DEBUG_PRINT(F(" group time: ")); + DEBUG_PRINTLN(allZoneTime[i]); + recentUpdate = true; + } + } + } + else + { + recentUpdate = false; + } +} +// +void updateDisplay() +{ + static unsigned long lastUpdateTime; + static boolean displayToggle = false; + //static byte toggleCounter = 0; + static SprinklerStates lastDisplayState; + if (state != lastDisplayState || millis() - lastUpdateTime >= 3000UL) + { + displayToggle = !displayToggle; + switch (state) { + case STAND_BY_ALL_OFF: + // + fastClear(); + lcd.setCursor(0, 0); + if (displayToggle) + { + lcd.print(F(" System Ready ")); + if (clockUpdating) + { + lcd.setCursor(15, 0); + lcd.write(byte(0)); + } + lcd.setCursor(0, 1); + lcd.print(hourFormat12() < 10 ? F(" ") : F("")); + lcd.print(hourFormat12()); + lcd.print(minute() < 10 ? F(":0") : F(":")); + lcd.print(minute()); + lcd.print(isAM() ? F("am") : F("pm")); + lcd.print(month() < 10 ? F(" 0") : F(" ")); + lcd.print(month()); + lcd.print(day() < 10 ? F("/0") : F("/")); + lcd.print(day()); + lcd.print(F("/")); + lcd.print(year() % 100); + } + else + { + lcd.print(F(" Last Watered ")); + if (clockUpdating) + { + lcd.setCursor(15, 0); + lcd.write(byte(0)); + } + lcd.setCursor(0, 1); + lcd.print(dayOfWeek[weekday(lastTimeRun)]); + lcd.setCursor(11, 1); + lcd.print(month(lastTimeRun) < 10 ? F(" ") : F("")); + lcd.print(month(lastTimeRun)); + lcd.print(day(lastTimeRun) < 10 ? F("/0") : F("/")); + lcd.print(day(lastTimeRun)); + } + break; + case RUN_SINGLE_ZONE: + // + fastClear(); + lcd.setCursor(0, 0); + if (displayToggle) + { + lcd.print(F("Single Zone Mode")); + lcd.setCursor(0, 1); + lcd.print(F(" Zone:")); + if (valveNumber < 10) lcd.print(F("0")); + lcd.print(valveNumber); + lcd.print(F(" Active")); + } + else + { + lcd.print(F(" Time Remaining ")); + lcd.setCursor(0, 1); + if (valveSoloTime[valveNumber] == 0) + { + lcd.print(F(" No Valve Time ")); + } + else + { + unsigned long timeRemaining = (valveSoloTime[valveNumber] * 60) - ((millis() - startMillis) / 1000); + lcd.print(timeRemaining / 60 < 10 ? " 0" : " "); + lcd.print(timeRemaining / 60); + lcd.print("min"); + lcd.print(timeRemaining % 60 < 10 ? " 0" : " "); + lcd.print(timeRemaining % 60); + lcd.print("sec "); + } + } + break; + case RUN_ALL_ZONES: + // + fastClear(); + lcd.setCursor(0, 0); + if (displayToggle) + { + lcd.print(F(" All-Zone Mode ")); + lcd.setCursor(0, 1); + lcd.print(F(" Zone:")); + if (valveNumber < 10) lcd.print(F("0")); + lcd.print(valveNumber); + lcd.print(F(" Active ")); + } + else + { + lcd.print(F(" Time Remaining ")); + lcd.setCursor(0, 1); + int timeRemaining = (allZoneTime[valveNumber] * 60) - ((millis() - startMillis) / 1000); + lcd.print((timeRemaining / 60) < 10 ? " 0" : " "); + lcd.print(timeRemaining / 60); + lcd.print("min"); + lcd.print(timeRemaining % 60 < 10 ? " 0" : " "); + lcd.print(timeRemaining % 60); + lcd.print("sec "); + } + break; + case CYCLE_COMPLETE: + // + if (displayToggle) + { + lcd.setCursor(0, 0); + lcd.print(F(" Watering Cycle ")); + lcd.setCursor(0, 1); + lcd.print(F(" Complete ")); + } + else + { + int totalTimeRan = 0; + for (int i = 1; i < NUMBER_OF_VALVES + 1; i++) + { + totalTimeRan += allZoneTime[i]; + } + lcd.setCursor(0, 0); + lcd.print(F(" Total Time Run ")); + lcd.setCursor(0, 1); + lcd.print(totalTimeRan < 10 ? " 0" : " "); + lcd.print(totalTimeRan); + lcd.print(" Minutes "); + } + default: + // what of ZONE_SELECT_MENU? + break; + } + lastUpdateTime = millis(); + } + lastDisplayState = state; +} +void receiveTime(time_t newTime) +{ + DEBUG_PRINTLN(F("Time value received and updated...")); + int lastSecond = second(); + int lastMinute = minute(); + int lastHour = hour(); + setTime(newTime); + if (((second() != lastSecond) || (minute() != lastMinute) || (hour() != lastHour)) || showTime) + { + DEBUG_PRINTLN(F("Clock updated....")); + DEBUG_PRINT(F("Sensor's time currently set to:")); + DEBUG_PRINT(hourFormat12() < 10 ? F(" 0") : F(" ")); + DEBUG_PRINT(hourFormat12()); + DEBUG_PRINT(minute() < 10 ? F(":0") : F(":")); + DEBUG_PRINT(minute()); + DEBUG_PRINTLN(isAM() ? F("am") : F("pm")); + DEBUG_PRINT(month()); + DEBUG_PRINT(F("/")); + DEBUG_PRINT(day()); + DEBUG_PRINT(F("/")); + DEBUG_PRINTLN(year()); + DEBUG_PRINTLN(dayOfWeek[weekday()]); + showTime = false; + } + else + { + DEBUG_PRINTLN(F("Sensor's time did NOT need adjustment greater than 1 second.")); + } + clockUpdating = false; +} +void fastClear() +{ + lcd.setCursor(0, 0); + lcd.print(F(" ")); + lcd.setCursor(0, 1); + lcd.print(F(" ")); +} +// +void updateClock() +{ + static unsigned long lastVeraGetTime; + if (millis() - lastVeraGetTime >= 3600000UL) // updates clock time and gets zone times from vera once every hour + { + DEBUG_PRINTLN(F("Requesting time and valve data from Gateway...")); + lcd.setCursor(15, 0); + lcd.write(byte(0)); + clockUpdating = true; + requestTime(receiveTime); + lastVeraGetTime = millis(); + } +} +// +void saveDateToEEPROM(unsigned long theDate) +{ + DEBUG_PRINTLN(F("Saving Last Run date")); + if (loadState(0) != 0xFF) + { + saveState(0, 0xFF); // EEPROM flag for last date saved stored in EEPROM (location zero) + } + // + for (int i = 1; i < 5; i++) + { + saveState(5 - i, byte(theDate >> 8 * (i - 1))); // store epoch datestamp in 4 bytes of EEPROM starting in location one + } +} +// +void goGetValveTimes() +{ + static unsigned long valveUpdateTime; + static byte valveIndex = 1; + if (millis() - valveUpdateTime >= 300000UL / NUMBER_OF_VALVES)// update each valve once every 5 mins (distributes the traffic) + { + DEBUG_PRINTLN(F("Calling for Valve Data...")); + lcd.setCursor(15, 0); + lcd.write(byte(1)); //lcd.write(1); + request(valveIndex, V_VAR1); + request(valveIndex, V_VAR2); + request(valveIndex, V_VAR3); + valveUpdateTime = millis(); + valveIndex++; + if (valveIndex > NUMBER_OF_VALVES + 1) + { + valveIndex = 1; + } + } +} diff --git a/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino b/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino new file mode 100644 index 0000000..665568c --- /dev/null +++ b/libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino @@ -0,0 +1,85 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - idefix + * + * DESCRIPTION + * Arduino BH1750FVI Light sensor + * communicate using I2C Protocol + * this library enable 2 slave device addresses + * Main address 0x23 + * secondary address 0x5C + * connect the sensor as follows : + * + * VCC >>> 5V + * Gnd >>> Gnd + * ADDR >>> NC or GND + * SCL >>> A5 + * SDA >>> A4 + * http://www.mysensors.org/build/light + */ + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include + +#define CHILD_ID_LIGHT 0 +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) + +BH1750 lightSensor; + +// V_LIGHT_LEVEL should only be used for uncalibrated light level 0-100%. +// If your controller supports the new V_LEVEL variable, use this instead for +// transmitting LUX light level. +MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); +// MyMessage msg(CHILD_ID_LIGHT, V_LEVEL); +uint16_t lastlux; + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Light Lux Sensor", "1.0"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); + + lightSensor.begin(); +} + +void loop() +{ + uint16_t lux = lightSensor.readLightLevel();// Get Lux value + Serial.println(lux); + if (lux != lastlux) { + send(msg.set(lux)); + lastlux = lux; + } + + sleep(SLEEP_TIME); +} diff --git a/libraries/MySensors/examples/LightSensor/LightSensor.ino b/libraries/MySensors/examples/LightSensor/LightSensor.ino new file mode 100644 index 0000000..8c27775 --- /dev/null +++ b/libraries/MySensors/examples/LightSensor/LightSensor.ino @@ -0,0 +1,67 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik EKblad + * + * DESCRIPTION + * Example sketch showing how to measue light level using a LM393 photo-resistor + * http://www.mysensors.org/build/light + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define CHILD_ID_LIGHT 0 +#define LIGHT_SENSOR_ANALOG_PIN 0 + +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) + +MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); +int lastLightLevel; + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Light Sensor", "1.0"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); +} + +void loop() +{ + int lightLevel = (1023-analogRead(LIGHT_SENSOR_ANALOG_PIN))/10.23; + Serial.println(lightLevel); + if (lightLevel != lastLightLevel) { + send(msg.set(lightLevel)); + lastLightLevel = lightLevel; + } + sleep(SLEEP_TIME); +} + + + diff --git a/libraries/MySensors/examples/LightningSensor/LightningSensor.ino b/libraries/MySensors/examples/LightningSensor/LightningSensor.ino new file mode 100644 index 0000000..5b85acf --- /dev/null +++ b/libraries/MySensors/examples/LightningSensor/LightningSensor.ino @@ -0,0 +1,123 @@ +// This sketch is to integrate the Playing With Fusion AXS3935 Lightning Sensor Breakout Board +// with the MySensors environment and is based on a sketch provided by Playing With Fusion +// http://playingwithfusion.com/productview.php?pdid=22&catid=1001 +// + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include "MySensor.h" +// include Playing With Fusion AXS3935 libraries +#include "PWFusion_AS3935.h" + +// setup CS pins used for the connection with the lightning sensor +// other connections are controlled by the SPI library) +int8_t CS_PIN = 8; +int8_t SI_PIN = 7; +int8_t IRQ_PIN = 3; +volatile int8_t AS3935_ISR_Trig = 0; + +// #defines +#define AS3935_INDOORS 1 +#define AS3935_OUTDOORS 0 +#define AS3935_DIST_DIS 0 +#define AS3935_DIST_EN 1 +#define AS3935_CAPACITANCE 96 // <-- SET THIS VALUE TO THE NUMBER LISTED ON YOUR BOARD +// prototypes +void AS3935_ISR(); + +PWF_AS3935 lightning0(CS_PIN, IRQ_PIN, SI_PIN); + +#define CHILD_ID_DISTANCE 1 +#define CHILD_ID_INTENSITY 2 +MyMessage msgDist(CHILD_ID_DISTANCE, V_DISTANCE); +MyMessage msgInt(CHILD_ID_INTENSITY, V_VAR1); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Lightning Sensor", "1.1"); + + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID_DISTANCE, S_DISTANCE); + present(CHILD_ID_INTENSITY, S_CUSTOM); + + Serial.begin(115200); + Serial.println("Playing With Fusion: AS3935 Lightning Sensor, SEN-39001"); + Serial.println("beginning boot procedure...."); + + // setup for the the SPI library: + SPI.begin(); // begin SPI + SPI.setClockDivider(SPI_CLOCK_DIV4); // SPI speed to SPI_CLOCK_DIV16/1MHz (max 2MHz, NEVER 500kHz!) + SPI.setDataMode(SPI_MODE1); // MAX31855 is a Mode 1 device + // --> clock starts low, read on rising edge + SPI.setBitOrder(MSBFIRST); // data sent to chip MSb first + + lightning0.AS3935_DefInit(); // set registers to default + // now update sensor cal for your application and power up chip + lightning0.AS3935_ManualCal(AS3935_CAPACITANCE, AS3935_OUTDOORS, AS3935_DIST_EN); + // AS3935_ManualCal Parameters: + // --> capacitance, in pF (marked on package) + // --> indoors/outdoors (AS3935_INDOORS:0 / AS3935_OUTDOORS:1) + // --> disturbers (AS3935_DIST_EN:1 / AS3935_DIST_DIS:2) + // function also powers up the chip + + // enable interrupt (hook IRQ pin to Arduino Uno/Mega interrupt input: 1 -> pin 3 ) + attachInterrupt(1, AS3935_ISR, RISING); + // dump the registry data to the serial port for troubleshooting purposes + lightning0.AS3935_PrintAllRegs(); + + // delay execution to allow chip to stabilize. + delay(1000); + +} + +void loop() +{ + + // This program only handles an AS3935 lightning sensor. It does nothing until + // an interrupt is detected on the IRQ pin. + while(0 == AS3935_ISR_Trig){} + + // reset interrupt flag + AS3935_ISR_Trig = 0; + + // now get interrupt source + uint8_t int_src = lightning0.AS3935_GetInterruptSrc(); + if(0 == int_src) + { + Serial.println("Unknown interrupt source"); + } + else if(1 == int_src) + { + uint8_t lightning_dist_km = lightning0.AS3935_GetLightningDistKm(); + uint32_t lightning_intensity = lightning0.AS3935_GetStrikeEnergyRaw(); + + Serial.print("Lightning detected! Distance to strike: "); + Serial.print(lightning_dist_km); + Serial.println(" kilometers"); + Serial.print("Lightning detected! Lightning Intensity: "); + Serial.println(lightning_intensity); + send(msgDist.set(lightning_dist_km)); + send(msgInt.set(lightning_intensity)); + } + else if(2 == int_src) + { + Serial.println("Disturber detected"); + } + else if(3 == int_src) + { + Serial.println("Noise level too high"); + } +} + +// this is irq handler for AS3935 interrupts, has to return void and take no arguments +// always make code in interrupt handlers fast and short +void AS3935_ISR() +{ + AS3935_ISR_Trig = 1; +} diff --git a/libraries/MySensors/examples/MAX6875TemperatureSensor/MAX6875TemperatureSensor.ino b/libraries/MySensors/examples/MAX6875TemperatureSensor/MAX6875TemperatureSensor.ino new file mode 100644 index 0000000..fa98f90 --- /dev/null +++ b/libraries/MySensors/examples/MAX6875TemperatureSensor/MAX6875TemperatureSensor.ino @@ -0,0 +1,87 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - MrLynx + * + * DESCRIPTION + * MAX6875 High temperature sensor with range: -200 degC - +1300 degC + * http://forum.mysensors.org/topic/641/max6675 + * + * Connect MAX6675 - Arduino + * CS0 - 4 + * SO - 3 + * SCLK - 5 + * VCC - 5V + * GND - GND + * + */ + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +uint8_t CS0 = 4; // CS pin on MAX6675 +uint8_t SO = 3; // SO pin of MAX6675 +uint8_t SCLK = 5; // SCK pin of MAX6675 +uint8_t units = 1; // Units to readout temp (0 = ˚F, 1 = ˚C) +float temperature = 0.0; // Temperature output variable +float lastTemperature; +unsigned long SLEEP_TIME = 30000; +boolean metric = true; + +MyMessage msg(0, V_TEMP); + +// Initialize the MAX6675 Library for our chip + +MAX6675 temp0(CS0, SO, SCLK, units); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Max6675 Temp Sensor", "1.0"); + + // Present all sensors to controller + present(0, S_TEMP); +} + +void loop() +{ + temperature = temp0.read_temp(); // Read the temp + + if (temperature < 0) { // If there is an error with the TC, temperature will be < 0 + Serial.println("Thermocouple Error!!"); // There is a thermocouple error + } else { + Serial.print("Current Temperature: "); + Serial.println( temperature ); // Print the temperature to Serial + if (temperature != lastTemperature) + send(msg.setSensor(0).set(temperature, 1)); + lastTemperature = temperature; + } + + sleep(SLEEP_TIME); +} diff --git a/libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino b/libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino new file mode 100644 index 0000000..9c5b60b --- /dev/null +++ b/libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino @@ -0,0 +1,614 @@ +/* MyMQTT Client Gateway 0.1b + Created by Norbert Truchsess + Based on MyMQTT-broker gateway created by Daniel Wiegert + Based on MySensors Ethernet Gateway by Henrik Ekblad + http://www.mysensors.org + + Changes by Thomas Krebs + - Add signing support from MySensors 1.5 and update for MySensors 1.5; + - Restructured code back to a C like implementation following the existing MQTTGateway + Requires MySensors lib 1.5 + + * Change below; TCP_IP, TCP_PORT, TCP_MAC + This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also. + *1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges. + *2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change + the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details. + http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5 + * Don't forget to look at the definitions in libraries\MySensors\MyMQTT.h! + define TCPDUMP and connect serial interface if you have problems, please write on + http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to + turn on DEBUG in libraries\MySensors\MyConfig.h also. + MQTT_FIRST_SENSORID is for 'DHCP' server in MyMQTT. You may limit the ID's with FIRST and LAST definition. + If you want your manually configured below 20 set MQTT_FIRST_SENSORID to 20. + To disable: set MQTT_FIRST_SENSORID to 255. + MQTT_BROKER_PREFIX is the leading prefix for your nodes. This can be only one char if like. + MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes. + This can be useful if you want to send latest state back to the MQTT client. Just check if incoming + message has any length or not. + Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things. + * Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/V_[SensorType][/set | /get] + NodeID and SensorID is uint8 (0-255) number. + Segment after SensorID is translation of the sensor type, look inside MyMQTT.cpp for the definitions. + User can change this to their needs. We have also left some space for custom types. + Special: (sensor 255 reserved for special commands) + + The last seqment is a command to to be send down to the sensor. The gateway is subscribed to topics which have + a command present! This is to avoid that a publish by the gateway will end up in the gateway via it subsription. + You can receive a node sketch name with MyMQTT/20/255/V_Sketch_name (or version with _version) + + So far tested in openhab and MyMQTT for Android (Not my creation) + - http://www.openhab.org/ + * How to set-up Openhab and MQTTGateway: + http://forum.mysensors.org/topic/303/mqtt-broker-gateway + + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MyMQTTClient.h" + +#ifdef MY_SIGNING_FEATURE +#include +#include +#include +#endif + +//#define DSRTC +#ifdef DSRTC +#include +#include // a basic DS1307 library that returns time as a time_t +#endif + +/* + * To configure MQTTClientGateway.ino to use an ENC28J60 based board include + * 'UIPEthernet.h' (SPI.h required for MySensors anyway). The UIPEthernet-library can be downloaded + * from: https://github.com/ntruchsess/arduino_uip + */ + +//#include +/* + * To execute MQTTClientGateway.ino on Yun uncomment Bridge.h and YunClient.h. + * Do not include Ethernet.h or SPI.h in this case. + * On Yun there's no need to configure local_ip and mac in the sketch + * as this is configured on the linux-side of Yun. + */ + +//#include +//#include +// * Use this for IBOARD modded to use standard MISO/MOSI/SCK, see note *1 above! +/* + #define RADIO_CE_PIN 3 // radio chip enable + #define RADIO_SPI_SS_PIN 8 // radio SPI serial select + #define RADIO_ERROR_LED_PIN A2 // Error led pin + #define RADIO_RX_LED_PIN A1 // Receive led pin + #define RADIO_TX_LED_PIN A0 // the PCB, on board LED*/ + +// * Use this for default configured pro mini / nano etc : +// + +//#define RADIO_CE_PIN 5 // radio chip enable +//#define RADIO_SPI_SS_PIN 6 // radio SPI serial select +//#define RADIO_ERROR_LED_PIN 7 // Error led pin +//#define RADIO_RX_LED_PIN 8 // Receive led pin +//#define RADIO_TX_LED_PIN 9 // the PCB, on board LED*/ + +// CE_PIN and SPI_SS_PIN for Mega +#define RADIO_CE_PIN 48 // radio chip enable +#define RADIO_SPI_SS_PIN 49 // radio SPI serial select +#define RADIO_ERROR_LED_PIN A2 // Error led pin +#define RADIO_RX_LED_PIN A1 // Receive led pin +#define RADIO_TX_LED_PIN A0 // the PCB, on board LED*/ + +//replace with ip of server you want to connect to, comment out if using 'remote_host' +uint8_t remote_ip[] = { 192, 168, 178, 74 }; // Mosquitto broker + +//replace with hostname of server you want to connect to, comment out if using 'remote_ip' +//char* remote_ip = "server.local"; +//replace with the port that your server is listening on +#define remote_port 1883 +//replace with arduinos ip-address. Comment out if Ethernet-startup should use dhcp. Is ignored on Yun +uint8_t local_ip[] = {192, 168, 178, 11}; +//replace with ethernet shield mac. It's mandatory every device is assigned a unique mac. Is ignored on Yun +uint8_t mac[] = { 0xA2, 0xAE, 0xAD, 0xA0, 0xA0, 0xA2 }; + +#if defined remote_ip && defined remote_host +#error "cannot define both remote_ip and remote_host at the same time!" +#endif + +#ifdef _YUN_CLIENT_H_ +YunClient ethClient; +#else +EthernetClient ethClient; +#endif + +//////////////////////////////////////////////////////////////// +// NRFRF24L01 radio driver (set low transmit power by default) +MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW); +//MyTransportRFM69 transport; + +// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +//MySigningNone signer; +//MySigningAtsha204Soft signer(true); +//MySigningAtsha204 signer; + +// Hardware profile +MyHwATMega328 hw; + +MyMessage msg; +char convBuf[MAX_PAYLOAD * 2 + 1]; +uint8_t buffsize; +char buffer[MQTT_MAX_PACKET_SIZE]; +char user[sizeof(MQTT_USER)]; // introduced the bufs to get rid of compiler warnings +char pwd[sizeof(MQTT_PWD)]; // see above +char connID[sizeof(MQTT_CONN_ID)]; // see above +char mqttTopicMask[sizeof(MQTT_TOPIC_MASK)]; // see above + +//////////////////////////////////////////////////////////////// + +volatile uint8_t countRx; +volatile uint8_t countTx; +volatile uint8_t countErr; + + +//////////////////////////////////////////////////////////////// + +void processMQTTMessages(char* topic, byte* payload, unsigned int length); +PubSubClient client(remote_ip, remote_port, processMQTTMessages, ethClient); + +//////////////////////////////////////////////////////////////// + + +// Declare and initialize MySensor instance +// Construct MyMQTTClient (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h, if signing +// feature not to be used, uncomment) +// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h +MySensor gw(transport, hw +#ifdef MY_SIGNING_FEATURE + , signer +#endif +#ifdef WITH_LEDS_BLINKING + , RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN +#endif + ); + +/* + * setup + */ +void setup() +{ + strcpy(connID,MQTT_CONN_ID); + strcpy(mqttTopicMask,MQTT_TOPIC_MASK); + + countRx = 0; + countTx = 0; + countErr = 0; + + Ethernet.begin(mac, local_ip); + //Bridge.begin(); + delay(1000); // Wait for Ethernet to get configured. + + begin(); +} + +/* + * loop + */ +void loop() +{ + if (!client.connected()) + { + boolean ret; +#ifdef MQTT_AUTH_REQUIRED + strcpy(user, MQTT_USER); + strcpy(pwd, MQTT_PWD); + ret = client.connect(connID, user,pwd); +#else + ret = client.connect(connID); +#endif + if (ret) { + Serial.println("Connected to MQTT broker"); + } else { + Serial.println("Connection to MQTT broker failed"); + } + client.subscribe(mqttTopicMask); + } + client.loop(); + gw.process(); +} + +/* + * processRadioMessage + * + * Receives radio message, parses it and forwards it to the MQTT broker + */ +void processRadioMessage(const MyMessage &message) +{ + rxBlink(1); + sendMQTT(message); +} + +/* + * sendMQTT + * Handles processing of radio messages and eventually publishes it to the MQTT broker + */ +void sendMQTT(const MyMessage &inMsg) +{ + MyMessage msg = inMsg; + buffsize = 0; + if (!client.connected()) + return; //We have no connections - return + if (msg.isAck()) + { +#ifdef DEBUG + Serial.println("msg is ack!"); +#endif + if (msg.sender == 255 && mGetCommand(msg) == C_INTERNAL + && msg.type == I_ID_REQUEST) + { + // TODO: sending ACK request on id_response fucks node up. doesn't work. + // The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS. + } + } + else + { + // we have to check every message if its a newly assigned id or not. + // Ack on I_ID_RESPONSE does not work, and checking on C_PRESENTATION isn't reliable. + uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS) + 1; + if (newNodeID <= MQTT_FIRST_SENSORID) + newNodeID = MQTT_FIRST_SENSORID; + if (msg.sender == newNodeID) + { + gw.saveState(EEPROM_LATEST_NODE_ADDRESS, newNodeID); + } + if (mGetCommand(msg) == C_INTERNAL) + { + if (msg.type == I_CONFIG) + { + txBlink(1); + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, + I_CONFIG, 0).set("M"))) + errBlink(1); + } + else if (msg.type == I_TIME) + { +#ifdef DEBUG + Serial.println("I_TIME requested!"); +#endif + txBlink(1); + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, + I_TIME, 0).set(now()))) + errBlink(1); + } + else if (msg.type == I_ID_REQUEST && msg.sender == 255) + { + uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS) + 1; + if (newNodeID <= MQTT_FIRST_SENSORID) + newNodeID = MQTT_FIRST_SENSORID; + if (newNodeID >= MQTT_LAST_SENSORID) + return; // Sorry no more id's left :( + txBlink(1); + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, + I_ID_RESPONSE, 0).set(newNodeID))) + errBlink(1); + } + else if (msg.type == I_BATTERY_LEVEL) + { + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/255/BATTERY_LEVEL", msg.sender ); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + else if (msg.type == I_SKETCH_NAME) + { + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/255/SKETCH_NAME", msg.sender ); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + else if (msg.type == I_SKETCH_VERSION) + { + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/255/SKETCH_VERSION", msg.sender ); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + + } + else if (mGetCommand(msg) != 0) + { + if (mGetCommand(msg) == 3) + msg.type = msg.type + (S_FIRSTCUSTOM - 10); //Special message + + if (msg.type > VAR_TOTAL) + msg.type = VAR_TOTAL; // If type > defined types set to unknown. + strcpy_P(buffer, mqtt_prefix); + buffsize += strlen_P(mqtt_prefix); + buffsize += sprintf(&buffer[buffsize], "/%i/%i/V_%s", msg.sender, + msg.sensor, getType(convBuf, &VAR_Type[msg.type])); + msg.getString(convBuf); +#ifdef DEBUG + Serial.print("publish: "); + Serial.print((char*) buffer); + Serial.print(" "); + Serial.println((char*) convBuf); +#endif + client.publish(buffer, convBuf); + } + } +} + +/* + * build + * Constructs a radio message + */ +inline MyMessage& build(MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, + uint8_t command, uint8_t type, bool enableAck) +{ + msg.destination = destination; + msg.sender = sender; + msg.sensor = sensor; + msg.type = type; + mSetCommand(msg, command); + mSetRequestAck(msg, enableAck); + mSetAck(msg, false); + return msg; +} + +/* + * getType + */ +char *getType(char *b, const char **index) +{ + char *q = b; + char *p = (char *) pgm_read_word(index); + while (*q++ = pgm_read_byte(p++)) + ; + *q = 0; + return b; +} + +/* + * begin + * wraps MySensors begin method; setup of RTC and led timers interrupt + */ +void begin() +{ +#ifdef DEBUG + Serial.begin(BAUD_RATE); +#endif +#ifdef DSRTC + // Attach RTC + setSyncProvider(RTC.get); // the function to get the time from the RTC + setSyncInterval(60); +#endif + + gw.begin(processRadioMessage, 0, true, 0); + + MsTimer2::set(200, ledTimersInterrupt); + MsTimer2::start(); + +#ifdef DEBUG + Serial.print(getType(convBuf, &VAR_Type[S_FIRSTCUSTOM])); +#endif +} + +/* + * processMQTTMessages + * message handler for the PubSubClient + */ +void processMQTTMessages(char* topic, byte* payload, unsigned int length) +{ + processMQTTMessage(topic, payload, length); +} + +/* + * processMQTTMessage + * processes MQTT messages, parses the topic, extracts radio address out of topic and sends them + * to the respective radio + */ +void processMQTTMessage(char* topic, byte* payload, + unsigned int length) +{ + char *str, *p; + uint8_t i = 0; + buffer[0] = 0; + buffsize = 0; + int8_t cmd = -1; + + for (str = strtok_r(topic, "/", &p); str && i < 5; + str = strtok_r(NULL, "/", &p)) + { + switch (i) + { + case 0: + { + if (strcmp_P(str, mqtt_prefix) != 0) + { //look for MQTT_PREFIX + return; //Message not for us or malformatted! + } + break; + } + case 1: + { + msg.destination = atoi(str); //NodeID + break; + } + case 2: + { + msg.sensor = atoi(str); //SensorID + break; + } + case 3: + { + char match = 0; //SensorType + //strcpy(str,(char*)&str[2]); //Strip VAR_ + + for (uint8_t j = 0; + strcpy_P(convBuf, (char*) pgm_read_word(&(VAR_Type[j]))); j++) + { + if (strcmp((char*) &str[2], convBuf) == 0) + { //Strip VAR_ and compare + match = j; + break; + } + if (j >= VAR_TOTAL) + { // No match found! + match = VAR_TOTAL; // last item. + break; + } + } + msg.type = match; + break; + } + case 4: + { + // support the command get and set; get will be mapped to a C_REQ and set to C_SET + if (strcmp(str,MQTT_CMD_SET) == 0) + { + cmd = C_SET; + } + else if (strcmp(str,MQTT_CMD_GET) == 0) { + cmd = C_REQ; + } + else { +#ifdef DEBUG + Serial.print("Received unsupported command - ignore: "); + Serial.println(str); +#endif + } + } + } + i++; + } //Check if packge has payload + + if (cmd != -1) { + char* ca; + ca = (char *)payload; + ca += length; + *ca = '\0'; + + msg.set((const char*)payload); //Payload + + txBlink(1); + // inject time + if ((msg.destination == 0) && (msg.sensor == 199)) { + unsigned long epoch = atol((char*)payload); + if (epoch > 10000) { +#ifdef DSRTC + RTC.set(epoch); // this sets the RTC to the time from controller - which we do want periodically +#endif + setTime(epoch); + } +#ifdef DEBUG + Serial.print("Time received "); + Serial.println(epoch); +#endif + } + // + if (!gw.sendRoute( + build(msg, GATEWAY_ADDRESS, msg.destination, msg.sensor, C_SET, msg.type, + 0))) + errBlink(1); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Led handling +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * ledTimersIntterupt + */ +void ledTimersInterrupt() { + if (countRx && countRx != 255) { + // switch led on + digitalWrite(RADIO_RX_LED_PIN, LOW); + } else if (!countRx) { + // switching off + digitalWrite(RADIO_RX_LED_PIN, HIGH); + } + if (countRx != 255) { + countRx--; + } + + if (countTx && countTx != 255) { + // switch led on + digitalWrite(RADIO_TX_LED_PIN, LOW); + } else if (!countTx) { + // switching off + digitalWrite(RADIO_TX_LED_PIN, HIGH); + } + if (countTx != 255) { + countTx--; + } + + if (countErr && countErr != 255) { + // switch led on + digitalWrite(RADIO_ERROR_LED_PIN, LOW); + } else if (!countErr) { + // switching off + digitalWrite(RADIO_ERROR_LED_PIN, HIGH); + } + if (countErr != 255) { + countErr--; + } +} + + +void rxBlink(uint8_t cnt) +{ + if (countRx == 255) + { + countRx = cnt; + } +} + +void txBlink(uint8_t cnt) +{ + if (countTx == 255) + { + countTx = cnt; + } +} + +void errBlink(uint8_t cnt) +{ + if (countErr == 255) + { + countErr = cnt; + } +} + + diff --git a/libraries/MySensors/examples/MQTTClientGateway/MyMQTTClient.h b/libraries/MySensors/examples/MQTTClientGateway/MyMQTTClient.h new file mode 100644 index 0000000..d347825 --- /dev/null +++ b/libraries/MySensors/examples/MQTTClientGateway/MyMQTTClient.h @@ -0,0 +1,129 @@ +/* +The MySensors library adds a new layer on top of the RF24 library. +It handles radio network routing, relaying and ids. +Created by Henrik Ekblad +Modified by Daniel Wiegert +Modified by Norbert Truchsess +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. +*/ + + +#ifndef MyMQTTClient_h +#define MyMQTTClient_h + +////////////////////////////////////////////////////////////////// + +#ifdef DEBUG +#define TCPDUMP // Dump TCP packages. +#endif +#define MQTT_FIRST_SENSORID 20 // If you want manually configured nodes below this value. 255 = Disable +#define MQTT_LAST_SENSORID 254 // 254 is max! 255 reserved. +#define MQTT_PREFIX "MyMQTT" // First prefix in MQTT tree, keep short! +#define MQTT_TOPIC_MASK "MyMQTT/+/+/+/+" // Topic mask the client will subscribe to. This ensures that it will not receive any sensor data send by sensors + // the following topic structure is assumed: MyMQTT//// +#define MQTT_SEND_SUBSCRIPTION 1 // Send empty payload (request) to node upon MQTT client subscribe request. +#define MQTT_CMD_SET "set" // command (see MQTT_TOPIC_MASK); mapped to C_SET command type of sensor network +#define MQTT_CMD_GET "get" // command (see MQTT_TOPIC_MASK); mapped to C_REQ command type of sensor network + + +#define MQTT_AUTH_REQUIRED // if your broker has anonymous access uncomment +#define MQTT_USER "user" // username on MQTT broker +#define MQTT_PWD "pwd" // password for MQTT username above +#define MQTT_CONN_ID "MySensors" // passed as id to the MQTT broker + + +// NOTE above : Beware to check if there is any length on payload in your incommingMessage code: +// Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things. + +////////////////////////////////////////////////////////////////// + + +char VAR_0[] PROGMEM = "TEMP"; //V_TEMP +char VAR_1[] PROGMEM = "HUM"; //V_HUM +char VAR_2[] PROGMEM = "LIGHT"; //V_LIGHT +char VAR_3[] PROGMEM = "DIMMER"; //V_DIMMER +char VAR_4[] PROGMEM = "PRESSURE"; //V_PRESSURE +char VAR_5[] PROGMEM = "FORECAST"; //V_FORECAST +char VAR_6[] PROGMEM = "RAIN"; //V_RAIN +char VAR_7[] PROGMEM = "RAINRATE"; //V_RAINRATE +char VAR_8[] PROGMEM = "WIND"; //V_WIND +char VAR_9[] PROGMEM = "GUST"; //V_GUST +char VAR_10[] PROGMEM = "DIRECTON"; //V_DIRECTON +char VAR_11[] PROGMEM = "UV"; //V_UV +char VAR_12[] PROGMEM = "WEIGHT"; //V_WEIGHT +char VAR_13[] PROGMEM = "DISTANCE"; //V_DISTANCE +char VAR_14[] PROGMEM = "IMPEDANCE"; //V_IMPEDANCE +char VAR_15[] PROGMEM = "ARMED"; //V_ARMED +char VAR_16[] PROGMEM = "TRIPPED"; //V_TRIPPED +char VAR_17[] PROGMEM = "WATT"; //V_WATT +char VAR_18[] PROGMEM = "KWH"; //V_KWH +char VAR_19[] PROGMEM = "SCENE_ON"; //V_SCENE_ON +char VAR_20[] PROGMEM = "SCENE_OFF"; //V_SCENE_OFF +char VAR_21[] PROGMEM = "HEATER"; //V_HEATER +char VAR_22[] PROGMEM = "HEATER_SW"; //V_HEATER_SW +char VAR_23[] PROGMEM = "LIGHT_LEVEL"; //V_LIGHT_LEVEL +char VAR_24[] PROGMEM = "VAR1"; //V_VAR1 +char VAR_25[] PROGMEM = "VAR2"; //V_VAR2 +char VAR_26[] PROGMEM = "VAR3"; //V_VAR3 +char VAR_27[] PROGMEM = "VAR4"; //V_VAR4 +char VAR_28[] PROGMEM = "VAR5"; //V_VAR5 +char VAR_29[] PROGMEM = "UP"; //V_UP +char VAR_30[] PROGMEM = "DOWN"; //V_DOWN +char VAR_31[] PROGMEM = "STOP"; //V_STOP +char VAR_32[] PROGMEM = "IR_SEND"; //V_IR_SEND +char VAR_33[] PROGMEM = "IR_RECEIVE"; //V_IR_RECEIVE +char VAR_34[] PROGMEM = "FLOW"; //V_FLOW +char VAR_35[] PROGMEM = "VOLUME"; //V_VOLUME +char VAR_36[] PROGMEM = "LOCK_STATUS"; //V_LOCK_STATUS +char VAR_37[] PROGMEM = "LEVEL"; // S_DUST, S_LIGHT_LEVEL, ... +char VAR_38[] PROGMEM = "VOLTAGE"; //V_VOLTAGE +char VAR_39[] PROGMEM = "CURRENT"; //V_CURRENT +char VAR_40[] PROGMEM = "RGB"; //V_RGB +char VAR_41[] PROGMEM = ""; // +char VAR_42[] PROGMEM = ""; // +char VAR_43[] PROGMEM = ""; // +char VAR_44[] PROGMEM = ""; // +char VAR_45[] PROGMEM = ""; // +char VAR_46[] PROGMEM = ""; // +char VAR_47[] PROGMEM = ""; // +char VAR_48[] PROGMEM = ""; // +char VAR_49[] PROGMEM = ""; // +char VAR_50[] PROGMEM = ""; // +char VAR_51[] PROGMEM = ""; // +char VAR_52[] PROGMEM = ""; // +char VAR_53[] PROGMEM = ""; // +char VAR_54[] PROGMEM = ""; // +char VAR_55[] PROGMEM = ""; // +char VAR_56[] PROGMEM = ""; // +char VAR_57[] PROGMEM = ""; // +char VAR_58[] PROGMEM = ""; // +char VAR_59[] PROGMEM = ""; // +char VAR_60[] PROGMEM = "Started!\n"; //Custom for MQTTGateway +char VAR_61[] PROGMEM = "SKETCH_NAME"; //Custom for MQTTGateway +char VAR_62[] PROGMEM = "SKETCH_VERSION"; //Custom for MQTTGateway +char VAR_63[] PROGMEM = "UNKNOWN"; //Custom for MQTTGateway + +////////////////////////////////////////////////////////////////// + +PROGMEM const char *VAR_Type[] = +{ VAR_0, VAR_1, VAR_2, VAR_3, VAR_4, VAR_5, VAR_6, VAR_7, VAR_8, VAR_9, VAR_10, VAR_11, VAR_12, VAR_13, + VAR_14, VAR_15, VAR_16, VAR_17, VAR_18, VAR_19, VAR_20, VAR_21, VAR_22, VAR_23, VAR_24, VAR_25, + VAR_26, VAR_27, VAR_28, VAR_29, VAR_30, VAR_31, VAR_32, VAR_33, VAR_34, VAR_35, VAR_36, VAR_37, + VAR_38, VAR_39, VAR_40, VAR_41, VAR_42, VAR_43, VAR_44, VAR_45, VAR_46, VAR_47, VAR_48, VAR_49, + VAR_50, VAR_51, VAR_52, VAR_53, VAR_54, VAR_55, VAR_56, VAR_57, VAR_58, VAR_59, VAR_60, VAR_61, + VAR_62, VAR_63 +}; + +char mqtt_prefix[] PROGMEM = MQTT_PREFIX; + +#define S_FIRSTCUSTOM 60 +#define TYPEMAXLEN 20 +#define VAR_TOTAL (sizeof(VAR_Type)/sizeof(char *))-1 + + +#define EEPROM_LATEST_NODE_ADDRESS ((uint8_t)EEPROM_LOCAL_CONFIG_ADDRESS) + +//#define DSRTC // RTC Dallas support -> disable debug and use isp programmer to free memory +#endif diff --git a/libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino b/libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino new file mode 100644 index 0000000..34d3fff --- /dev/null +++ b/libraries/MySensors/examples/MQTTGateway/MQTTGateway.ino @@ -0,0 +1,474 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Created by Daniel Wiegert + * + * DESCRIPTION + * MyMQTT Broker Gateway 0.1b + * Latest instructions found here: + * http://www.mysensors.org/build/mqtt_gateway + * http://www.mysensors.org/build/ethernet_gateway + * + * Change below; TCP_IP, TCP_PORT, TCP_MAC + * This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also. + * 1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges. + * 2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change + * the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details. + * http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5 + * + * Don't forget to look at the definitions in MyMQTT.h! + * + * define TCPDUMP and connect serial interface if you have problems, please write on + * http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to + * turn on DEBUG in libraries\MySensors\MyConfig.h also. + * + * MQTT_FIRST_SENSORID is for 'DHCP' server in MyMQTT. You may limit the ID's with FIRST and LAST definition. + * If you want your manually configured below 20 set MQTT_FIRST_SENSORID to 20. + * To disable: set MQTT_FIRST_SENSORID to 255. + * + * MQTT_BROKER_PREFIX is the leading prefix for your nodes. This can be only one char if like. + * + * MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes. + * This can be useful if you want to send latest state back to the MQTT client. Just check if incoming + * message has any length or not. + * Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things. + * + * (*) Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/V_[SensorType] + * NodeID and SensorID is uint8 (0-255) number. + * Last segment is translation of the sensor type, look inside MyMQTT.cpp for the definitions. + * User can change this to their needs. We have also left some space for custom types. + * + * Special: (sensor 255 reserved for special commands) + * You can receive a node sketch name with MyMQTT/20/255/V_Sketch_name (or version with _version) + * + * To-do: + * Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself. + * Be able to send ACK so client returns the data being sent. + * ... Please come with ideas! + * What to do with publish messages. + * + * Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation) + * - http://www.openhab.org/ + * - https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en + * ... Please notify me if you use this broker with other software. + * + * How to set-up Openhab and MQTTGateway: + * http://forum.mysensors.org/topic/303/mqtt-broker-gateway + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "MyMQTT.h" + + +#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled +#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button + +// * Use this for IBOARD modded to use standard MISO/MOSI/SCK, see note *1 above! +/* +#define RADIO_CE_PIN 3 // radio chip enable +#define RADIO_SPI_SS_PIN 8 // radio SPI serial select +#define RADIO_ERROR_LED_PIN A2 // Error led pin +#define RADIO_RX_LED_PIN A1 // Receive led pin +#define RADIO_TX_LED_PIN A0 // the PCB, on board LED +*/ + +// * Use this for default configured pro mini / nano etc : +///* + +#define RADIO_CE_PIN 5 // radio chip enable +#define RADIO_SPI_SS_PIN 6 // radio SPI serial select +#define RADIO_ERROR_LED_PIN 7 // Error led pin +#define RADIO_RX_LED_PIN 8 // Receive led pin +#define RADIO_TX_LED_PIN 9 // the PCB, on board LED*/ + +#define TCP_PORT 1883 // Set your MQTT Broker Listening port. +IPAddress TCP_IP ( 192, 168, 0, 234 ); // Configure your static ip-address here +byte TCP_MAC[] = { 0x02, 0xDE, 0xAD, 0x00, 0x00, 0x42 }; // Mac-address - You should change this! see note *2 above! + +////////////////////////////////////////////////////////////////// + +// NRFRF24L01 radio driver (set low transmit power by default) +MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW); +//MyTransportRFM69 transport; + +// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +//MySigningNone signer; +//MySigningAtsha204Soft signer; +//MySigningAtsha204 signer; + +// Hardware profile +MyHwATMega328 hw; + +// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +MySensor gw(transport, hw /*, signer*/); + + +EthernetServer server = EthernetServer(TCP_PORT); +EthernetClient *currentClient = NULL; +MyMessage msg; +char convBuf[MAX_PAYLOAD*2+1]; +char broker[] PROGMEM = MQTT_BROKER_PREFIX; +bool MQTTClientConnected = false; +uint8_t buffsize; +char buffer[MQTT_MAX_PACKET_SIZE]; +volatile uint8_t countRx; +volatile uint8_t countTx; +volatile uint8_t countErr; + + +void writeEthernet(const char *writeBuffer, uint8_t *writeSize) { +#ifdef TCPDUMP + Serial.print(">>"); + char buf[4]; + for (uint8_t a=0; a<*writeSize; a++) { sprintf(buf,"%02X ",(uint8_t)writeBuffer[a]); Serial.print(buf); } Serial.println(""); +#endif + server.write((const uint8_t *)writeBuffer, *writeSize); +} + + +void processEthernetMessages() { + char inputString[MQTT_MAX_PACKET_SIZE] = ""; + byte inputSize = 0; + byte readCnt = 0; + byte length = 0; + + EthernetClient client = server.available(); + if (client) { + while (client.available()) { + // Save the current client we are talking with + currentClient = &client; + byte inByte = client.read(); + readCnt++; + + if (inputSize < MQTT_MAX_PACKET_SIZE) { + inputString[inputSize] = (char)inByte; + inputSize++; + } + + if (readCnt == 2) { + length = (inByte & 127) * 1; + } + if (readCnt == (length+2)) { + break; + } + } +#ifdef TCPDUMP + Serial.print("<<"); + char buf[4]; + for (byte a=0; a> 4 == MQTTCONNECT) { + buffer[buffsize++] = MQTTCONNACK << 4; + buffer[buffsize++] = 0x02; // Remaining length + buffer[buffsize++] = 0x00; // Connection accepted + buffer[buffsize++] = 0x00; // Reserved + MQTTClientConnected=true; // We have connection! + } + if ((uint8_t)inputString[0] >> 4 == MQTTPINGREQ) { + buffer[buffsize++] = MQTTPINGRESP << 4; + buffer[buffsize++] = 0x00; + } + if ((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE) { + buffer[buffsize++] = MQTTSUBACK << 4; // Just ack everything, we actually dont really care! + buffer[buffsize++] = 0x03; // Remaining length + buffer[buffsize++] = (uint8_t)inputString[2]; // Message ID MSB + buffer[buffsize++] = (uint8_t)inputString[3]; // Message ID LSB + buffer[buffsize++] = MQTTQOS0; // QOS level + } + if ((uint8_t)inputString[0] >> 4 == MQTTUNSUBSCRIBE) { + buffer[buffsize++] = MQTTUNSUBACK << 4; + buffer[buffsize++] = 0x02; // Remaining length + buffer[buffsize++] = (uint8_t)inputString[2]; // Message ID MSB + buffer[buffsize++] = (uint8_t)inputString[3]; // Message ID LSB + } + if ((uint8_t)inputString[0] >> 4 == MQTTDISCONNECT) { + MQTTClientConnected=false; // We lost connection! + } + if (buffsize > 0) { + writeEthernet(buffer,&buffsize); + } + + // We publish everything we get, we dont care if its subscribed or not! + if ((uint8_t)inputString[0] >> 4 == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && (uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE)) { + buffer[0]= 0; + buffsize = 0; + // Cut out address and payload depending on message type. + if ((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE) { + strncat(buffer,inputString+6,inputString[5]); + } else { + strncat(buffer,inputString+4,inputString[3]); + } + +#ifdef DEBUG + Serial.println(buffer); +#endif + // TODO: Check if we should send ack or not. + for (str = strtok_r(buffer,"/",&p) ; str && i<4 ; str = strtok_r(NULL,"/",&p)) { + if (i == 0) { + if (strcmp_P(str,broker)!=0) { //look for MQTT_BROKER_PREFIX + return; //Message not for us or malformatted! + } + } else if (i==1) { + msg.destination = atoi(str); //NodeID + } else if (i==2) { + msg.sensor = atoi(str); //SensorID + } else if (i==3) { + unsigned char match=255; //SensorType +#ifdef MQTT_TRANSLATE_TYPES + + for (uint8_t j=0; strcpy_P(convBuf, (char*)pgm_read_word(&(vType[j]))) ; j++) { + if (strcmp((char*)&str[2],convBuf)==0) { //Strip V_ and compare + match=j; + break; + } + if (j >= V_TOTAL) break; + } + +#endif + if ( atoi(str)!=0 || (str[0]=='0' && str[1] =='\0') ) { + match=atoi(str); + } + + if (match==255) { + match=V_UNKNOWN; + } + msg.type = match; + } + i++; + } //Check if packge has payload + if ((uint8_t)inputString[1] > (uint8_t)(inputString[3]+2) && !((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE)) { + strcpy(convBuf,inputString+(inputString[3]+4)); + msg.set(convBuf); //Payload + } else { + msg.set(""); //No payload + } + txBlink(1); + if (!gw.sendRoute(build(msg, msg.destination, msg.sensor, C_SET, msg.type, 0))) errBlink(1); + + } +} + +void sendMQTT(const MyMessage &inMsg) { + MyMessage msg = inMsg; + buffsize = 0; + if (!MQTTClientConnected) return; //We have no connections - return + if (msg.isAck()) { +// if (msg.sender==255 && mGetCommand(msg)==C_INTERNAL && msg.type==I_ID_REQUEST) { +// TODO: sending ACK request on id_response fucks node up. doesn't work. +// The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS. +// } + } else { + // we have to check every message if its a newly assigned id or not. + // Ack on I_ID_RESPONSE does not work, and checking on C_PRESENTATION isn't reliable. + uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS)+1; + if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID; + if (msg.sender==newNodeID) { + gw.saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID); + } + if (mGetCommand(msg)==C_INTERNAL) { + if (msg.type==I_CONFIG) { + txBlink(1); + if (!gw.sendRoute(build(msg, msg.sender, 255, C_INTERNAL, I_CONFIG, 0).set(MQTT_UNIT))) errBlink(1); + return; + } else if (msg.type==I_ID_REQUEST && msg.sender==255) { + uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS)+1; + if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID; + if (newNodeID >= MQTT_LAST_SENSORID) return; // Sorry no more id's left :( + txBlink(1); + if (!gw.sendRoute(build(msg, msg.sender, 255, C_INTERNAL, I_ID_RESPONSE, 0).set(newNodeID))) errBlink(1); + return; + } + } + if (mGetCommand(msg)!=C_PRESENTATION) { + if (mGetCommand(msg)==C_INTERNAL) msg.type=msg.type+(S_FIRSTCUSTOM-10); //Special message + buffer[buffsize++] = MQTTPUBLISH << 4; // 0: + buffer[buffsize++] = 0x09; // 1: Remaining length with no payload, we'll set this later to correct value, buffsize -2 + buffer[buffsize++] = 0x00; // 2: Length MSB (Remaing length can never exceed ff,so MSB must be 0!) + buffer[buffsize++] = 0x08; // 3: Length LSB (ADDR), We'll set this later + strcpy_P(buffer+4, broker); + buffsize+=strlen_P(broker); +#ifdef MQTT_TRANSLATE_TYPES + if (msg.type > V_TOTAL) msg.type=V_UNKNOWN;// If type > defined types set to unknown. + buffsize+=sprintf(&buffer[buffsize],"/%i/%i/V_%s",msg.sender,msg.sensor,getType(convBuf, &vType[msg.type])); +#else + buffsize+=sprintf(&buffer[buffsize],"/%i/%i/%i",msg.sender,msg.sensor,msg.type); +#endif + buffer[3]=buffsize-4; // Set correct address length on byte 4. +#ifdef DEBUG + Serial.println((char*)&buffer[4]); +#endif + msg.getString(convBuf); + for (uint8_t a=0; a +Modified by Daniel Wiegert +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. +*/ + +#ifdef DEBUG +#define TCPDUMP // Dump TCP packages +#endif + +#define MQTT_FIRST_SENSORID 20 // If you want manually configured nodes below this value. 255 = Disable +#define MQTT_LAST_SENSORID 254 // 254 is max! 255 reserved. +#define MQTT_BROKER_PREFIX "MyMQTT" // First prefix in MQTT tree, keep short! +#define MQTT_SEND_SUBSCRIPTION 1 // Send empty payload (request) to node upon MQTT client subscribe request. +// NOTE above : Beware to check if there is any length on payload in your incommingMessage code: +// Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things. +#define MQTT_UNIT "M" // Select M for metric or I for imperial. +#define MQTT_TRANSLATE_TYPES // V_TYPE in address, Comment if you want all numbers (MyMQTT/01/01/01) + +////////////////////////////////////////////////////////////////// + +#define EEPROM_LATEST_NODE_ADDRESS ((uint8_t)EEPROM_LOCAL_CONFIG_ADDRESS) +#define MQTT_MAX_PACKET_SIZE 100 + +#define MQTTPROTOCOLVERSION 3 +#define MQTTCONNECT 1 // Client request to connect to Server +#define MQTTCONNACK 2 // Connect Acknowledgment +#define MQTTPUBLISH 3 // Publish message +#define MQTTPUBACK 4 // Publish Acknowledgment +#define MQTTPUBREC 5 // Publish Received (assured delivery part 1) +#define MQTTPUBREL 6 // Publish Release (assured delivery part 2) +#define MQTTPUBCOMP 7 // Publish Complete (assured delivery part 3) +#define MQTTSUBSCRIBE 8 // Client Subscribe request +#define MQTTSUBACK 9 // Subscribe Acknowledgment +#define MQTTUNSUBSCRIBE 10 // Client Unsubscribe request +#define MQTTUNSUBACK 11 // Unsubscribe Acknowledgment +#define MQTTPINGREQ 12 // PING Request +#define MQTTPINGRESP 13 // PING Response +#define MQTTDISCONNECT 14 // Client is Disconnecting +#define MQTTReserved 15 // Reserved + +#define MQTTQOS0 (0 << 1) +#define MQTTQOS1 (1 << 1) +#define MQTTQOS2 (2 << 1) + +#ifdef MQTT_TRANSLATE_TYPES + +char V_0[] PROGMEM = "TEMP"; //V_TEMP +char V_1[] PROGMEM = "HUM"; //V_HUM +char V_2[] PROGMEM = "LIGHT"; //V_LIGHT +char V_3[] PROGMEM = "DIMMER"; //V_DIMMER +char V_4[] PROGMEM = "PRESSURE"; //V_PRESSURE +char V_5[] PROGMEM = "FORECAST"; //V_FORECAST +char V_6[] PROGMEM = "RAIN"; //V_RAIN +char V_7[] PROGMEM = "RAINRATE"; //V_RAINRATE +char V_8[] PROGMEM = "WIND"; //V_WIND +char V_9[] PROGMEM = "GUST"; //V_GUST +char V_10[] PROGMEM = "DIRECTON"; //V_DIRECTON +char V_11[] PROGMEM = "UV"; //V_UV +char V_12[] PROGMEM = "WEIGHT"; //V_WEIGHT +char V_13[] PROGMEM = "DISTANCE"; //V_DISTANCE +char V_14[] PROGMEM = "IMPEDANCE"; //V_IMPEDANCE +char V_15[] PROGMEM = "ARMED"; //V_ARMED +char V_16[] PROGMEM = "TRIPPED"; //V_TRIPPED +char V_17[] PROGMEM = "WATT"; //V_WATT +char V_18[] PROGMEM = "KWH"; //V_KWH +char V_19[] PROGMEM = "SCENE_ON"; //V_SCENE_ON +char V_20[] PROGMEM = "SCENE_OFF"; //V_SCENE_OFF +char V_21[] PROGMEM = "HEATER"; //V_HEATER +char V_22[] PROGMEM = "HEATER_SW"; //V_HEATER_SW +char V_23[] PROGMEM = "LIGHT_LEVEL"; //V_LIGHT_LEVEL +char V_24[] PROGMEM = "VAR1"; //V_VAR1 +char V_25[] PROGMEM = "VAR2"; //V_VAR2 +char V_26[] PROGMEM = "VAR3"; //V_VAR3 +char V_27[] PROGMEM = "VAR4"; //V_VAR4 +char V_28[] PROGMEM = "VAR5"; //V_VAR5 +char V_29[] PROGMEM = "UP"; //V_UP +char V_30[] PROGMEM = "DOWN"; //V_DOWN +char V_31[] PROGMEM = "STOP"; //V_STOP +char V_32[] PROGMEM = "IR_SEND"; //V_IR_SEND +char V_33[] PROGMEM = "IR_RECEIVE"; //V_IR_RECEIVE +char V_34[] PROGMEM = "FLOW"; //V_FLOW +char V_35[] PROGMEM = "VOLUME"; //V_VOLUME +char V_36[] PROGMEM = "LOCK_STATUS"; //V_LOCK_STATUS +char V_37[] PROGMEM = "DUST_LEVEL"; //V_DUST_LEVEL +char V_38[] PROGMEM = "VOLTAGE"; //V_VOLTAGE +char V_39[] PROGMEM = "CURRENT"; //V_CURRENT +char V_40[] PROGMEM = ""; // +char V_41[] PROGMEM = ""; // +char V_42[] PROGMEM = ""; // +char V_43[] PROGMEM = ""; // +char V_44[] PROGMEM = ""; // +char V_45[] PROGMEM = ""; // +char V_46[] PROGMEM = ""; // +char V_47[] PROGMEM = ""; // +char V_48[] PROGMEM = ""; // +char V_49[] PROGMEM = ""; // +char V_50[] PROGMEM = ""; // +char V_51[] PROGMEM = ""; // +char V_52[] PROGMEM = ""; // +char V_53[] PROGMEM = ""; // +char V_54[] PROGMEM = ""; // +char V_55[] PROGMEM = ""; // +char V_56[] PROGMEM = ""; // +char V_57[] PROGMEM = ""; // +char V_58[] PROGMEM = ""; // +char V_59[] PROGMEM = ""; // +char V_60[] PROGMEM = "DEFAULT"; //Custom for MQTTGateway +char V_61[] PROGMEM = "SKETCH_NAME"; //Custom for MQTTGateway +char V_62[] PROGMEM = "SKETCH_VERSION"; //Custom for MQTTGateway +char V_63[] PROGMEM = "UNKNOWN"; //Custom for MQTTGateway + +////////////////////////////////////////////////////////////////// + +PROGMEM const char *vType[] = { + V_0, V_1, V_2, V_3, V_4, V_5, V_6, V_7, V_8, V_9, V_10, + V_11, V_12, V_13, V_14, V_15, V_16, V_17, V_18, V_19, V_20, + V_21, V_22, V_23, V_24, V_25, V_26, V_27, V_28, V_29, V_30, + V_31, V_32, V_33, V_34, V_35, V_36, V_37, V_38, V_39, V_40, + V_41, V_42, V_43, V_44, V_45, V_46, V_47, V_48, V_49, V_50, + V_51, V_52, V_53, V_54, V_55, V_56, V_57, V_58, V_59, V_60, + V_61, V_62, V_63 +}; + + + +#define S_FIRSTCUSTOM 60 +#define V_TOTAL (sizeof(vType)/sizeof(char *))-1 + +#endif + +#define S_FIRSTCUSTOM 60 +#define V_UNKNOWN 63 diff --git a/libraries/MySensors/examples/MockMySensors/MockMySensors.ino b/libraries/MySensors/examples/MockMySensors/MockMySensors.ino new file mode 100644 index 0000000..4b2f6b5 --- /dev/null +++ b/libraries/MySensors/examples/MockMySensors/MockMySensors.ino @@ -0,0 +1,1465 @@ +/* +* MockMySensors +* +* This skecth is intended to crate fake sensors which register and respond to the controller +* *** +* Barduino 2015, GizMoCuz 2015 +*/ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#define MY_NODE_ID 254 + +#include + +#define RADIO_ERROR_LED_PIN 4 // Error led pin +#define RADIO_RX_LED_PIN 6 // Receive led pin +#define RADIO_TX_LED_PIN 5 // the PCB, on board LED + +// Wait times +#define LONG_WAIT 500 +#define SHORT_WAIT 50 + +#define SKETCH_NAME "MockMySensors " +#define SKETCH_VERSION "v0.5" + +// Define Sensors ids +/* S_DOOR, S_MOTION, S_SMOKE, S_LIGHT, S_DIMMER, S_COVER, S_TEMP, S_HUM, S_BARO, S_WIND, + S_RAIN, S_UV, S_WEIGHT, S_POWER, S_HEATER, S_DISTANCE, S_LIGHT_LEVEL, S_ARDUINO_NODE, + S_ARDUINO_REPEATER_NODE, S_LOCK, S_IR, S_WATER, S_AIR_QUALITY, S_CUSTOM, S_DUST, + S_SCENE_CONTROLLER +*/ + +////#define ID_S_ARDUINO_NODE //auto defined in initialization +////#define ID_S_ARDUINO_REPEATER_NODE //auto defined in initialization + + +// Some of these ID's have not been updated for v1.5. Uncommenting too many of them +// will make the sketch too large for a pro mini's memory so it's probably best to try +// one at a time. + +#define ID_S_ARMED 0 // dummy to controll armed stated for several sensors +#define ID_S_DOOR 1 +//#define ID_S_MOTION 2 +//#define ID_S_SMOKE 3 +//#define ID_S_LIGHT 4 +//#define ID_S_DIMMER 5 +//#define ID_S_COVER 6 +//#define ID_S_TEMP 7 +//#define ID_S_HUM 8 +//#define ID_S_BARO 9 +//#define ID_S_WIND 10 +//#define ID_S_RAIN 11 +//#define ID_S_UV 12 +//#define ID_S_WEIGHT 13 +//#define ID_S_POWER 14 +//#define ID_S_HEATER 15 +//#define ID_S_DISTANCE 16 +//#define ID_S_LIGHT_LEVEL 17 +//#define ID_S_LOCK 18 +//#define ID_S_IR 19 +//#define ID_S_WATER 20 +//#define ID_S_AIR_QUALITY 21 +//#define ID_S_DUST 22 +//#define ID_S_SCENE_CONTROLLER 23 +//// Lib 1.5 sensors +//#define ID_S_RGB_LIGHT 24 +//#define ID_S_RGBW_LIGHT 25 +//#define ID_S_COLOR_SENSOR 26 +//#define ID_S_HVAC 27 +//#define ID_S_MULTIMETER 28 +//#define ID_S_SPRINKLER 29 +//#define ID_S_WATER_LEAK 30 +//#define ID_S_SOUND 31 +//#define ID_S_VIBRATION 32 +//#define ID_S_MOISTURE 33 +// +//#define ID_S_CUSTOM 99 + + + +// Global Vars +unsigned long SLEEP_TIME = 900000; // Sleep time between reads (in milliseconds) +boolean metric = true; +long randNumber; + + +//Instanciate Messages objects + +#ifdef ID_S_ARMED + bool isArmed; +#endif + +#ifdef ID_S_DOOR // V_TRIPPED, V_ARMED + MyMessage msg_S_DOOR_T(ID_S_DOOR,V_TRIPPED); + MyMessage msg_S_DOOR_A(ID_S_DOOR,V_ARMED); +#endif + +#ifdef ID_S_MOTION // V_TRIPPED, V_ARMED + MyMessage msg_S_MOTION_A(ID_S_MOTION,V_ARMED); + MyMessage msg_S_MOTION_T(ID_S_MOTION,V_TRIPPED); +#endif + +#ifdef ID_S_SMOKE // V_TRIPPED, V_ARMED + MyMessage msg_S_SMOKE_T(ID_S_SMOKE,V_TRIPPED); + MyMessage msg_S_SMOKE_A(ID_S_SMOKE,V_ARMED); +#endif + +#ifdef ID_S_LIGHT + MyMessage msg_S_LIGHT(ID_S_LIGHT,V_LIGHT); + bool isLightOn=0; +#endif + +#ifdef ID_S_DIMMER + MyMessage msg_S_DIMMER(ID_S_DIMMER,V_DIMMER); + int dimmerVal=100; +#endif + +#ifdef ID_S_COVER + MyMessage msg_S_COVER_U(ID_S_COVER,V_UP); + MyMessage msg_S_COVER_D(ID_S_COVER,V_DOWN); + MyMessage msg_S_COVER_S(ID_S_COVER,V_STOP); + MyMessage msg_S_COVER_V(ID_S_COVER,V_VAR1); + int coverState=0; //0=Stop; 1=up; -1=down +#endif + +#ifdef ID_S_TEMP + MyMessage msg_S_TEMP(ID_S_TEMP,V_TEMP); +#endif + +#ifdef ID_S_HUM + MyMessage msg_S_HUM(ID_S_HUM,V_HUM); +#endif + +#ifdef ID_S_BARO + MyMessage msg_S_BARO_P(ID_S_BARO,V_PRESSURE); + MyMessage msg_S_BARO_F(ID_S_BARO,V_FORECAST); +#endif + +#ifdef ID_S_WIND + MyMessage msg_S_WIND_S(ID_S_WIND,V_WIND); + MyMessage msg_S_WIND_G(ID_S_WIND,V_GUST); + MyMessage msg_S_WIND_D(ID_S_WIND,V_DIRECTION); +#endif + +#ifdef ID_S_RAIN + MyMessage msg_S_RAIN_A(ID_S_RAIN,V_RAIN); + MyMessage msg_S_RAIN_R(ID_S_RAIN,V_RAINRATE); +#endif + +#ifdef ID_S_UV + MyMessage msg_S_UV(ID_S_UV,V_UV); +#endif + +#ifdef ID_S_WEIGHT + MyMessage msg_S_WEIGHT(ID_S_WEIGHT,V_WEIGHT); +#endif + +#ifdef ID_S_POWER + MyMessage msg_S_POWER_W(ID_S_POWER,V_WATT); + MyMessage msg_S_POWER_K(ID_S_POWER,V_KWH); +#endif + + +#ifdef ID_S_HEATER + + //////// REVIEW IMPLEMENTATION //////////// + + MyMessage msg_S_HEATER_SET_POINT(ID_S_HEATER,V_HVAC_SETPOINT_HEAT); // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC + MyMessage msg_S_HEATER_FLOW_STATE(ID_S_HEATER,V_HVAC_FLOW_STATE); // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" // S_HVAC, S_HEATER + + //MyMessage msg_S_HEATER_STATUS(ID_S_HEATER,V_STATUS); + //MyMessage msg_S_HEATER_TEMP(ID_S_HEATER,V_TEMP); + + float heater_setpoint=21.5; + String heater_flow_state="Off"; + +// float heater_temp=23.5; +// bool heater_status=false; + + + // V_TEMP // Temperature + // V_STATUS // Binary status. 0=off 1=on + // V_HVAC_FLOW_STATE // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" + // V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") + // V_HVAC_SETPOINT_HEAT // HVAC/Heater setpoint +#endif + +#ifdef ID_S_DISTANCE + MyMessage msg_S_DISTANCE(ID_S_DISTANCE,V_DISTANCE); +#endif + +#ifdef ID_S_LIGHT_LEVEL + MyMessage msg_S_LIGHT_LEVEL(ID_S_LIGHT_LEVEL,V_LIGHT_LEVEL); +#endif + +#ifdef ID_S_LOCK + MyMessage msg_S_LOCK(ID_S_LOCK,V_LOCK_STATUS); + bool isLocked = 0; +#endif + +#ifdef ID_S_IR + MyMessage msg_S_IR_S(ID_S_IR,V_IR_SEND); + MyMessage msg_S_IR_R(ID_S_IR,V_IR_RECEIVE); + long irVal = 0; +#endif + +#ifdef ID_S_WATER + MyMessage msg_S_WATER_F(ID_S_WATER,V_FLOW); + MyMessage msg_S_WATER_V(ID_S_WATER,V_VOLUME); +#endif + +#ifdef ID_S_AIR_QUALITY + MyMessage msg_S_AIR_QUALITY(ID_S_AIR_QUALITY,V_LEVEL); +#endif + +#ifdef ID_S_DUST + MyMessage msg_S_DUST(ID_S_DUST,V_LEVEL); +#endif + +#ifdef ID_S_SCENE_CONTROLLER + MyMessage msg_S_SCENE_CONTROLLER_ON(ID_S_SCENE_CONTROLLER,V_SCENE_ON); + MyMessage msg_S_SCENE_CONTROLLER_OF(ID_S_SCENE_CONTROLLER,V_SCENE_OFF); + // not sure if scene controller sends int or chars + // betting on ints as Touch Display Scen by Hek // compiler warnings + char *scenes[] = { + (char *)"Good Morning", + (char *)"Clean Up!", + (char *)"All Lights Off", + (char *)"Music On/Off" + }; + + int sceneVal=0; + int sceneValPrevious=0; + +#endif + +#ifdef ID_S_RGB_LIGHT + MyMessage msg_S_RGB_LIGHT_V_RGB(ID_S_RGB_LIGHT,V_RGB); + MyMessage msg_S_RGB_LIGHT_V_WATT(ID_S_RGB_LIGHT,V_WATT); + String rgbState="000000"; + //RGB light V_RGB, V_WATT + //RGB value transmitted as ASCII hex string (I.e "ff0000" for red) +#endif + +#ifdef ID_S_RGBW_LIGHT + MyMessage msg_S_RGBW_LIGHT_V_RGBW(ID_S_RGBW_LIGHT,V_RGBW); + MyMessage msg_S_RGBW_LIGHT_V_WATT(ID_S_RGBW_LIGHT,V_WATT); + String rgbwState="00000000"; + //RGBW light (with separate white component) V_RGBW, V_WATT + //RGBW value transmitted as ASCII hex string (I.e "ff0000ff" for red + full white) S_RGBW_LIGHT +#endif + +#ifdef ID_S_COLOR_SENSOR + MyMessage msg_S_COLOR_SENSOR_V_RGB(ID_S_COLOR_SENSOR,V_RGB); + //Color sensor V_RGB + //RGB value transmitted as ASCII hex string (I.e "ff0000" for red) S_RGB_LIGHT, S_COLOR_SENSOR +#endif + +#ifdef ID_S_HVAC + MyMessage msg_S_HVAC_V_HVAC_SETPOINT_HEAT(ID_S_HVAC,V_HVAC_SETPOINT_HEAT); + MyMessage msg_S_HVAC_V_HVAC_SETPOINT_COOL(ID_S_HVAC,V_HVAC_SETPOINT_COOL); + MyMessage msg_S_HVAC_V_HVAC_FLOW_STATET(ID_S_HVAC,V_HVAC_FLOW_STATE); + MyMessage msg_S_HVAC_V_HVAC_FLOW_MODE(ID_S_HVAC,V_HVAC_FLOW_MODE); + MyMessage msg_S_HVAC_V_HVAC_SPEED(ID_S_HVAC,V_HVAC_SPEED); + + float hvac_SetPointHeat = 16.5; + float hvac_SetPointCool = 25.5; + String hvac_FlowState = "AutoChangeOver"; + String hvac_FlowMode = "Auto"; + String hvac_Speed = "Normal"; + + //Thermostat/HVAC device + //V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint + //V_HVAC_SETPOINT_COOL, // HVAC cold setpoint + //V_HVAC_FLOW_STATE, // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" + //V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn") + //V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") + + // NOT IMPLEMENTED YET + //V_TEMP // Temperature + //V_STATUS // Binary status. 0=off 1=on +#endif + +#ifdef ID_S_MULTIMETER + MyMessage msg_S_MULTIMETER_V_IMPEDANCE(ID_S_MULTIMETER,V_IMPEDANCE); + MyMessage msg_S_MULTIMETER_V_VOLTAGE(ID_S_MULTIMETER,V_VOLTAGE); + MyMessage msg_S_MULTIMETER_V_CURRENT(ID_S_MULTIMETER,V_CURRENT); + + // Multimeter device V_VOLTAGE, V_CURRENT, V_IMPEDANCE + // V_IMPEDANCE 14 Impedance value + // V_VOLTAGE 38 Voltage level + // V_CURRENT 39 Current level +#endif + +#ifdef ID_S_SPRINKLER + // S_SPRINKLER 31 Sprinkler device V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) + // V_STATUS 2 Binary status. 0=off 1=on + // V_ARMED 15 Armed status of a security sensor. 1=Armed, 0=Bypassed + // V_TRIPPED 16 Tripped status of a security sensor. 1=Tripped, 0=Untripped +#endif + +#ifdef ID_S_WATER_LEAK +#endif +#ifdef ID_S_SOUND +#endif +#ifdef ID_S_VIBRATION +#endif +#ifdef ID_S_MOISTURE +#endif + +#ifdef ID_S_MOISTURE + MyMessage msg_S_MOISTURE(ID_S_MOISTURE,V_LEVEL); +#endif + +#ifdef ID_S_CUSTOM + MyMessage msg_S_CUSTOM_1(ID_S_CUSTOM,V_VAR1); + MyMessage msg_S_CUSTOM_2(ID_S_CUSTOM,V_VAR2); + MyMessage msg_S_CUSTOM_3(ID_S_CUSTOM,V_VAR3); + MyMessage msg_S_CUSTOM_4(ID_S_CUSTOM,V_VAR4); + MyMessage msg_S_CUSTOM_5(ID_S_CUSTOM,V_VAR5); +#endif + + + + +void setup() +{ + // Random SEED + randomSeed(analogRead(0)); + + // Start the gateway + setIncomingCallback(incomingMessage); + wait(LONG_WAIT); + Serial.println("GW Started"); + + // Send the Sketch Version Information to the Gateway + Serial.print("Send Sketch Info: "); + sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); + Serial.print(SKETCH_NAME); + Serial.println(SKETCH_VERSION); + wait(LONG_WAIT); + + // Get controller configuration + Serial.print("Get Config: "); + metric = getConfig().isMetric; + Serial.println(metric ? "Metric":"Imperial"); + wait(LONG_WAIT); + + // Init Armed + #ifdef ID_S_ARMED + isArmed = true; + #endif + + // Register all sensors to gw (they will be created as child devices) + Serial.println("Presenting Nodes"); + Serial.println("________________"); + + #ifdef ID_S_DOOR + Serial.println(" S_DOOR"); + present(ID_S_DOOR,S_DOOR,"Outside Door"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_MOTION + Serial.println(" S_MOTION"); + present(ID_S_MOTION,S_MOTION,"Outside Motion"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_SMOKE + Serial.println(" S_SMOKE"); + present(ID_S_SMOKE,S_SMOKE,"Kitchen Smoke"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_LIGHT + Serial.println(" S_LIGHT"); + present(ID_S_LIGHT,S_LIGHT,"Hall Light"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_DIMMER + Serial.println(" S_DIMMER"); + present(ID_S_DIMMER,S_DIMMER,"Living room dimmer"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_COVER + Serial.println(" S_COVER"); + present(ID_S_COVER,S_COVER,"Window cover"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_TEMP + Serial.println(" S_TEMP"); + present(ID_S_TEMP,S_TEMP,"House Temperarue"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_HUM + Serial.println(" S_HUM"); + present(ID_S_HUM,S_HUM,"Current Humidity"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_BARO + Serial.println(" S_BARO"); + present(ID_S_BARO,S_BARO," Air pressure"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_WIND + Serial.println(" S_WIND"); + present(ID_S_WIND,S_WIND,"Wind Station"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_RAIN + Serial.println(" S_RAIN"); + present(ID_S_RAIN,S_RAIN,"Rain Station"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_UV + Serial.println(" S_UV"); + present(ID_S_UV,S_UV,"Ultra Violet"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_WEIGHT + Serial.println(" S_WEIGHT"); + present(ID_S_WEIGHT,S_WEIGHT,"Outdoor Scale"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_POWER + Serial.println(" S_POWER"); + present(ID_S_POWER,S_POWER,"Power Metric"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_HEATER + Serial.println(" S_HEATER"); + present(ID_S_HEATER,S_HEATER,"Garage Heater"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_DISTANCE + Serial.println(" S_DISTANCE"); + present(ID_S_DISTANCE,S_DISTANCE,"Distance Measure"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_LIGHT_LEVEL + Serial.println(" S_LIGHT_LEVEL"); + present(ID_S_LIGHT_LEVEL,S_LIGHT_LEVEL,"Outside Light Level"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_LOCK + Serial.println(" S_LOCK"); + present(ID_S_LOCK,S_LOCK,"Front Door Lock"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_IR + Serial.println(" S_IR"); + present(ID_S_IR,S_IR,"Univeral Command"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_WATER + Serial.println(" S_WATER"); + present(ID_S_WATER,S_WATER,"Water Level"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_AIR_QUALITY + Serial.println(" S_AIR_QUALITY"); + present(ID_S_AIR_QUALITY,S_AIR_QUALITY,"Air Station"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_DUST + Serial.println(" S_DUST"); + present(ID_S_DUST,S_DUST,"Dust Level"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_SCENE_CONTROLLER + Serial.println(" S_SCENE_CONTROLLER"); + present(ID_S_SCENE_CONTROLLER,S_SCENE_CONTROLLER,"Scene Controller"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_RGB_LIGHT + Serial.println(" RGB_LIGHT"); + present(ID_S_RGB_LIGHT,S_RGB_LIGHT,"Mood Light"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_RGBW_LIGHT + Serial.println(" RGBW_LIGHT"); + present(ID_S_RGBW_LIGHT,S_RGBW_LIGHT,"Mood Light 2"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_COLOR_SENSOR + Serial.println(" COLOR_SENSOR"); + present(ID_S_COLOR_SENSOR,S_COLOR_SENSOR,"Hall Painting"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_HVAC + Serial.println(" HVAC"); + present(ID_S_HVAC,S_HVAC,"HVAC"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_MULTIMETER + Serial.println(" MULTIMETER"); + present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Staion"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_SPRINKLER + #endif + #ifdef ID_S_WATER_LEAK + #endif + #ifdef ID_S_SOUND + #endif + #ifdef ID_S_VIBRATION + #endif + #ifdef ID_S_MOISTURE + #endif + + #ifdef ID_S_MOISTURE + Serial.println(" S_MOISTURE"); + present(ID_S_MOISTURE,S_MOISTURE,"Basement Sensor"); + wait(SHORT_WAIT); + #endif + + #ifdef ID_S_CUSTOM + Serial.println(" S_CUSTOM"); + present(ID_S_CUSTOM,S_CUSTOM,"Other Stuff"); + wait(SHORT_WAIT); + #endif + + + +Serial.println("________________"); + +} + +void loop() +{ + Serial.println(""); + Serial.println(""); + Serial.println(""); + Serial.println("#########################"); + randNumber=random(0,101); + + Serial.print("RandomNumber:"); + Serial.println(randNumber); + // Send fake battery level + Serial.println("Send Battery Level"); + sendBatteryLevel(randNumber); + wait(LONG_WAIT); + + // Request time + Serial.println("Request Time"); + requestTime(receiveTime); + wait(LONG_WAIT); + + //Read Sensors + #ifdef ID_S_DOOR + door(); + #endif + + #ifdef ID_S_MOTION + motion(); + #endif + + #ifdef ID_S_SMOKE + smoke(); + #endif + + #ifdef ID_S_LIGHT + light(); + #endif + + #ifdef ID_S_DIMMER + dimmer(); + #endif + + #ifdef ID_S_COVER + cover(); + #endif + + #ifdef ID_S_TEMP + temp(); + #endif + + #ifdef ID_S_HUM + hum(); + #endif + + #ifdef ID_S_BARO + baro(); + #endif + + #ifdef ID_S_WIND + wind(); + #endif + + #ifdef ID_S_RAIN + rain(); + #endif + + #ifdef ID_S_UV + uv(); + #endif + + #ifdef ID_S_WEIGHT + weight(); + #endif + + #ifdef ID_S_POWER + power(); + #endif + + #ifdef ID_S_HEATER + heater(); + #endif + + #ifdef ID_S_DISTANCE + distance(); + #endif + + #ifdef ID_S_LIGHT_LEVEL + light_level(); + #endif + + #ifdef ID_S_LOCK + lock(); + #endif + + #ifdef ID_S_IR + ir(); + #endif + + #ifdef ID_S_WATER + water(); + #endif + + #ifdef ID_S_AIR_QUALITY + air(); + #endif + + #ifdef ID_S_DUST + dust(); + #endif + + #ifdef ID_S_SCENE_CONTROLLER + scene(); + #endif + + #ifdef ID_S_RGB_LIGHT + rgbLight(); + #endif + + #ifdef ID_S_RGBW_LIGHT + rgbwLight(); + #endif + + #ifdef ID_S_COLOR_SENSOR + color(); + #endif + + #ifdef ID_S_HVAC + hvac(); + #endif + + #ifdef ID_S_MULTIMETER + multimeter(); + #endif + + #ifdef ID_S_SPRINKLER + #endif + #ifdef ID_S_WATER_LEAK + #endif + #ifdef ID_S_SOUND + #endif + #ifdef ID_S_VIBRATION + #endif + #ifdef ID_S_MOISTURE + #endif + + #ifdef ID_S_MOISTURE + moisture(); + #endif + + #ifdef ID_S_CUSTOM + custom(); + #endif + + sendBatteryLevel(randNumber); + wait(SHORT_WAIT); + Serial.println("#########################"); + wait(SLEEP_TIME); //sleep a bit +} + +// This is called when a new time value was received +void receiveTime(unsigned long controllerTime) { + + Serial.print("Time value received: "); + Serial.println(controllerTime); + +} + +//void door(){} + +#ifdef ID_S_DOOR +void door(){ + + Serial.print("Door is: " ); + + if (randNumber <= 50) { + Serial.println("Open"); + send(msg_S_DOOR_T.set(1)); + } else { + Serial.println("Closed"); + send(msg_S_DOOR_T.set(0)); + } + #ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + send(msg_S_DOOR_A.set(isArmed)); + #endif +} +#endif + +#ifdef ID_S_MOTION +void motion(){ + + Serial.print("Motion is: " ); + + if (randNumber <= 50) { + Serial.println("Active"); + send(msg_S_MOTION_T.set(1)); + } else { + Serial.println("Quiet"); + send(msg_S_MOTION_T.set(0)); + } + + #ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + send(msg_S_MOTION_A.set(isArmed)); + #endif +} +#endif + +#ifdef ID_S_SMOKE +void smoke(){ + + Serial.print("Smoke is: " ); + + if (randNumber <= 50) { + Serial.println("Active"); + send(msg_S_SMOKE_T.set(1)); + } else { + Serial.println("Quiet"); + send(msg_S_SMOKE_T.set(0)); + } + + #ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + send(msg_S_SMOKE_A.set(isArmed)); + #endif + +} +#endif + +#ifdef ID_S_LIGHT +void light(){ + + Serial.print("Light is: " ); + Serial.println((isLightOn ? "On":"Off")); + + send(msg_S_LIGHT.set(isLightOn)); + +} +#endif + +#ifdef ID_S_DIMMER +void dimmer(){ + + Serial.print("Dimmer is set to: " ); + Serial.println(dimmerVal); + + send(msg_S_DIMMER.set(dimmerVal)); + +} +#endif + +#ifdef ID_S_COVER +void cover(){ + + Serial.print("Cover is : " ); + + if (coverState == 1){ + Serial.println("Opening"); + send(msg_S_COVER_U.set(1)); + }else if (coverState == -1){ + Serial.println("Closing"); + send(msg_S_COVER_D.set(0)); + }else{ + Serial.println("Idle"); + send(msg_S_COVER_S.set(-1)); + } + send(msg_S_COVER_V.set(coverState)); +} +#endif + +#ifdef ID_S_TEMP +void temp(){ + + Serial.print("Temperature is: " ); + Serial.println(map(randNumber,1,100,0,45)); + + send(msg_S_TEMP.set(map(randNumber,1,100,0,45))); + +} +#endif + +#ifdef ID_S_HUM +void hum(){ + + Serial.print("Humitidty is: " ); + Serial.println(randNumber); + + send(msg_S_HUM.set(randNumber)); + +} +#endif + +#ifdef ID_S_BARO +void baro(){ + + const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"}; + long pressure = map(randNumber,1,100,870,1086);// hPa? + int forecast = map(randNumber,1,100,0,5); + + Serial.print("Atmosferic Pressure is: " ); + Serial.println(pressure); + send(msg_S_BARO_P.set(pressure)); + + Serial.print("Weather forecast: " ); + Serial.println(weather[forecast]); + send(msg_S_BARO_F.set(weather[forecast])); + +} +#endif + +#ifdef ID_S_WIND +void wind(){ + + Serial.print("Wind Speed is: " ); + Serial.println(randNumber); + send(msg_S_WIND_S.set(randNumber)); + + Serial.print("Wind Gust is: " ); + Serial.println(randNumber+10); + send(msg_S_WIND_G.set(randNumber+10)); + + Serial.print("Wind Direction is: " ); + Serial.println(map(randNumber,1,100,0,360)); + send(msg_S_WIND_D.set(map(randNumber,1,100,0,360))); + +} +#endif + +#ifdef ID_S_RAIN +void rain(){ + + Serial.print("Rain ammount is: " ); + Serial.println(randNumber); + + send(msg_S_RAIN_A.set(randNumber)); + + Serial.print("Rain rate is: " ); + Serial.println(randNumber/60); + + send(msg_S_RAIN_R.set(randNumber/60,1)); + +} +#endif + +#ifdef ID_S_UV +void uv(){ + + Serial.print("Ultra Violet level is: " ); + Serial.println(map(randNumber,1,100,0,15)); + + send(msg_S_UV.set(map(randNumber,1,100,0,15))); + +} +#endif + +#ifdef ID_S_WEIGHT +void weight(){ + + Serial.print("Weight is: " ); + Serial.println(map(randNumber,1,100,0,150)); + + send(msg_S_WEIGHT.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_POWER +void power(){ + + Serial.print("Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_POWER_W.set(map(randNumber,1,100,0,150))); + + Serial.print("KWH is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_POWER_K.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_HEATER +void heater(){ +// float heater_setpoint=21.5; +// float heater_temp=23.5; +// bool heater_status=false; +// String heatState="Off"; + + Serial.print("Heater flow state is: " ); + Serial.println(heater_flow_state); + send(msg_S_HEATER_FLOW_STATE.set(heater_flow_state.c_str())); + +// Serial.print("Heater on/off is: " ); +// Serial.println((heater_status==true)?"On":"Off"); +// send(msg_S_HEATER_STATUS.set(heater_status)); + +// Serial.print("Heater Temperature is: " ); +// Serial.println(heater_temp,1); +// send(msg_S_HEATER_TEMP.set(heater_temp,1)); + + Serial.print("Heater Setpoint: " ); + Serial.println(heater_setpoint,1); + send(msg_S_HEATER_SET_POINT.set(heater_setpoint,1)); +} +#endif + +#ifdef ID_S_DISTANCE +void distance(){ + + Serial.print("Distance is: " ); + Serial.println(map(randNumber,1,100,0,150)); + + send(msg_S_DISTANCE.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_LIGHT_LEVEL +void light_level(){ + + Serial.print("Light is: " ); + Serial.println(map(randNumber,1,100,0,150)); + + send(msg_S_LIGHT_LEVEL.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_LOCK +void lock(){ + + Serial.print("Lock is: " ); + Serial.println((isLocked ? "Locked":"Unlocked")); + send(msg_S_LOCK.set(isLocked)); + +} +#endif + +#ifdef ID_S_IR +void ir(){ + + Serial.print("Infrared is: " ); + Serial.println(irVal); + + send(msg_S_IR_S.set(irVal)); + send(msg_S_IR_R.set(irVal)); + +} +#endif + +#ifdef ID_S_WATER +void water(){ + + Serial.print("Water flow is: " ); + Serial.println(map(randNumber,1,100,0,150)); + + send(msg_S_WATER_F.set(map(randNumber,1,100,0,150))); + + Serial.print("Water volume is: " ); + Serial.println(map(randNumber,1,100,0,150)); + + send(msg_S_WATER_V.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_AIR_QUALITY +void air(){ + + Serial.print("Air Quality is: " ); + Serial.println(randNumber); + + send(msg_S_AIR_QUALITY.set(randNumber)); + +} +#endif + +#ifdef ID_S_DUST +void dust(){ + + Serial.print("Dust level is: " ); + Serial.println(randNumber); + + send(msg_S_DUST.set(randNumber)); + +} +#endif + +#ifdef ID_S_SCENE_CONTROLLER +void scene(){ + + Serial.print("Scene is: " ); + Serial.println(scenes[sceneVal]); + + if(sceneValPrevious != sceneVal){ + send(msg_S_SCENE_CONTROLLER_OF.set(sceneValPrevious)); + send(msg_S_SCENE_CONTROLLER_ON.set(sceneVal)); + sceneValPrevious=sceneVal; + } + +} +#endif + +#ifdef ID_S_RGB_LIGHT +void rgbLight(){ + + Serial.print("RGB Light state is: " ); + Serial.println(rgbState); + send(msg_S_RGB_LIGHT_V_RGB.set(rgbState.c_str())); + + Serial.print("RGB Light Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_RGB_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_RGBW_LIGHT +void rgbwLight(){ + + Serial.print("RGBW Light state is: " ); + Serial.println(rgbwState); + send(msg_S_RGBW_LIGHT_V_RGBW.set(rgbwState.c_str())); + + Serial.print("RGBW Light Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_RGBW_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); + +} +#endif + +#ifdef ID_S_COLOR_SENSOR +void color(){ + String colorState; + + String red = String(random(0,256),HEX); + String green = String(random(0,256),HEX); + String blue = String(random(0,256),HEX); + + colorState=String(red + green + blue); + + Serial.print("Color state is: " ); + Serial.println(colorState); + send(msg_S_COLOR_SENSOR_V_RGB.set(colorState.c_str())); + +} +#endif + +#ifdef ID_S_HVAC +void hvac(){ + +// float hvac_SetPointHeat = 16.5; +// float hvac_SetPointCool = 25.5; +// String hvac_FlowState = "AutoChangeOver"; +// String hvac_FlowMode = "Auto"; +// String hvac_Speed = "Normal"; + + Serial.print("HVAC Set Point Heat is: " ); + Serial.println(hvac_SetPointHeat); + send(msg_S_HVAC_V_HVAC_SETPOINT_HEAT.set(hvac_SetPointHeat,1)); + + Serial.print("HVAC Set Point Cool is: " ); + Serial.println(hvac_SetPointCool); + send(msg_S_HVAC_V_HVAC_SETPOINT_COOL.set(hvac_SetPointCool,1)); + + Serial.print("HVAC Flow State is: " ); + Serial.println(hvac_FlowState); + send(msg_S_HVAC_V_HVAC_FLOW_STATET.set(hvac_FlowState.c_str())); + + Serial.print("HVAC Flow Mode is: " ); + Serial.println(hvac_FlowMode); + send(msg_S_HVAC_V_HVAC_FLOW_MODE.set(hvac_FlowMode.c_str())); + + Serial.print("HVAC Speed is: " ); + Serial.println(hvac_Speed); + send(msg_S_HVAC_V_HVAC_SPEED.set(hvac_Speed.c_str())); + +} +#endif + +#ifdef ID_S_MULTIMETER +void multimeter(){ + int impedance=map(randNumber,1,100,0,15000); + int volt=map(randNumber,1,100,0,380); + int amps=map(randNumber,1,100,0,16); + + Serial.print("Impedance is: " ); + Serial.println(impedance); + send(msg_S_MULTIMETER_V_IMPEDANCE.set(impedance)); + + Serial.print("Voltage is: " ); + Serial.println(volt); + send(msg_S_MULTIMETER_V_VOLTAGE.set(volt)); + + Serial.print("Current is: " ); + Serial.println(amps); + send(msg_S_MULTIMETER_V_CURRENT.set(amps)); + +} +#endif + +#ifdef ID_S_SPRINKLER +#endif +#ifdef ID_S_WATER_LEAK +#endif +#ifdef ID_S_SOUND +#endif +#ifdef ID_S_VIBRATION +#endif +#ifdef ID_S_MOISTURE +#endif + +#ifdef ID_S_MOISTURE +void moisture(){ + + Serial.print("Moisture level is: " ); + Serial.println(randNumber); + + send(msg_S_MOISTURE.set(randNumber)); +} +#endif + +#ifdef ID_S_CUSTOM +void custom(){ + + Serial.print("Custom value is: " ); + Serial.println(randNumber); + + send(msg_S_CUSTOM_1.set(randNumber)); + send(msg_S_CUSTOM_2.set(randNumber)); + send(msg_S_CUSTOM_3.set(randNumber)); + send(msg_S_CUSTOM_4.set(randNumber)); + send(msg_S_CUSTOM_5.set(randNumber)); + +} +#endif + + +void incomingMessage(const MyMessage &message) { + switch (message.type) { + #ifdef ID_S_ARMED + case V_ARMED: + isArmed = message.getBool(); + Serial.print("Incoming change for ID_S_ARMED:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println((isArmed ? "Armed":"Disarmed" )); + #ifdef ID_S_DOOR + door();//temp ack for door + #endif + #ifdef ID_S_MOTION + motion();//temp ack + #endif + #ifdef ID_S_SMOKE + smoke();//temp ack + #endif + break; + #endif + + + case V_STATUS: // V_LIGHT: + #ifdef ID_S_LIGHT + if(message.sensor==ID_S_LIGHT){ + isLightOn = message.getBool(); + Serial.print("Incoming change for ID_S_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println((isLightOn ? "On":"Off")); + light(); // temp ack + } + #endif +// #ifdef ID_S_HEATER +// if(message.sensor == ID_S_HEATER){ +// heater_status = message.getBool(); +// Serial.print("Incoming change for ID_S_HEATER:"); +// Serial.print(message.sensor); +// Serial.print(", New status: "); +// Serial.println(heater_status); +// heater();//temp ack +// } +// #endif + break; + + + #ifdef ID_S_DIMMER + case V_DIMMER: + if ((message.getInt()<0)||(message.getInt()>100)) { + Serial.println( "V_DIMMER data invalid (should be 0..100)" ); + break; + } + dimmerVal= message.getInt(); + Serial.print("Incoming change for ID_S_DIMMER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getInt()); + dimmer();// temp ack + break; + #endif + + #ifdef ID_S_COVER + case V_UP: + coverState=1; + Serial.print("Incoming change for ID_S_COVER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println("V_UP"); + cover(); // temp ack + break; + + case V_DOWN: + coverState=-1; + Serial.print("Incoming change for ID_S_COVER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println("V_DOWN"); + cover(); //temp ack + break; + + case V_STOP: + coverState=0; + Serial.print("Incoming change for ID_S_COVER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println("V_STOP"); + cover(); //temp ack + break; + #endif + + + case V_HVAC_SETPOINT_HEAT: + + #ifdef ID_S_HEATER + if(message.sensor == ID_S_HEATER){ + heater_setpoint=message.getFloat(); + + Serial.print("Incoming set point for ID_S_HEATER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(heater_setpoint,1); + heater();//temp ack + } + #endif + + #ifdef ID_S_HVAC + if(message.sensor == ID_S_HVAC){ + hvac_SetPointHeat=message.getFloat(); + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_SetPointHeat,1); + hvac();//temp ack + } + #endif + break; + + case V_HVAC_FLOW_STATE: + #ifdef ID_S_HEATER + if(message.sensor == ID_S_HEATER){ + heater_flow_state=message.getString(); + Serial.print("Incoming flow state change for ID_S_HEATER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(heater_flow_state); + heater();//temp ack + } + #endif + + #ifdef ID_S_HVAC + if(message.sensor == ID_S_HVAC){ + hvac_FlowState=message.getString(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_FlowState); + hvac();//temp ack + } + #endif + break; + + #ifdef ID_S_LOCK + case V_LOCK_STATUS: + isLocked = message.getBool(); + Serial.print("Incoming change for ID_S_LOCK:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getBool()?"Locked":"Unlocked"); + lock(); //temp ack + break; + #endif + + #ifdef ID_S_IR + case V_IR_SEND: + irVal = message.getLong(); + Serial.print("Incoming change for ID_S_IR:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(irVal); + ir(); // temp ack + break; + case V_IR_RECEIVE: + irVal = message.getLong(); + Serial.print("Incoming change for ID_S_IR:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(irVal); + ir(); // temp ack + break; + #endif + + #ifdef ID_S_SCENE_CONTROLLER + case V_SCENE_ON: + sceneVal = message.getInt(); + Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.print(scenes[sceneVal]); + Serial.println(" On"); + scene();// temp ack + break; + case V_SCENE_OFF: + sceneVal = message.getInt(); + Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.print(scenes[sceneVal]); + Serial.println(" Off"); + scene();// temp ack + break; + #endif + + #ifdef ID_S_RGB_LIGHT + case V_RGB: + rgbState=message.getString(); + Serial.print("Incoming flow state change for ID_S_RGB_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(rgbState); + rgbLight(); // temp ack + + break; + #endif + + #ifdef ID_S_RGBW_LIGHT + case V_RGBW: + rgbwState=message.getString(); + Serial.print("Incoming flow state change for ID_S_RGBW_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(rgbwState); + rgbwLight(); + break; + #endif + + #ifdef ID_S_HVAC + // hvac_SetPointHeat + // hvac_SetPointCool + // hvac_FlowState + // hvac_FlowMode + // hvac_Speed + + case V_HVAC_SETPOINT_COOL: + hvac_SetPointCool=message.getFloat(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_SetPointCool,1); + hvac();//temp ack + break; + + case V_HVAC_FLOW_MODE: + hvac_Speed=message.getString(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_Speed); + hvac();//temp ack + break; + + case V_HVAC_SPEED: + hvac_FlowMode=message.getString(); + + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_FlowMode); + hvac();//temp ack + break; + #endif + + default: + Serial.print("Unknown/UnImplemented message type: "); + Serial.println(message.type); + } + +} + + + + + + + diff --git a/libraries/MySensors/examples/MockMySensors/README.md b/libraries/MySensors/examples/MockMySensors/README.md new file mode 100644 index 0000000..ef2062e --- /dev/null +++ b/libraries/MySensors/examples/MockMySensors/README.md @@ -0,0 +1,40 @@ +# MockMySensors +Arduino sketch to fake sensor for the MySensors Library + +This skecth is intended to crate fake sensors which register and respond to the controller + +Barduino, GizMoCuz 2015 +----------------- + +Comment/Uncomment the sensors you would like to test + +Arduino Uno R3 can support about 12 sensors before it runs out of memory. +(turning off the MySensors debug helps if you are memory limited) + +With a Mega you can have them all + + +Changes Log +----------------- + +2015-09-07 +Five more sensors + S_RGB_LIGHT + S_RGBW_LIGHT + S_COLOR_SENSOR + S_HVAC + S_MULTIMETER +Consolidated HVAC and HEATER incoming message + +2015-09-06 + +Merge with Gizmocuz (implementation of S_HEATER & S_MOISTURE +Implementation of S_COVER, S_IR, S_SCENE_CONTROLLER + + +2015-08-19 + +Removed the load/save to eeprom +Touched the heater sensor +Created a pseudo sensor to handle the V_ARMED message. +All sensors which support V_ARMED will arm/disarm at the same time diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino new file mode 100644 index 0000000..8d64c21 --- /dev/null +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -0,0 +1,70 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * Motion Sensor example using HC-SR501 + * http://www.mysensors.org/build/motion + * + */ + +// Enable debug prints +//#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds) +#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) +#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) +#define CHILD_ID 1 // Id of the sensor child + +// Initialize motion message +MyMessage msg(CHILD_ID, V_TRIPPED); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Motion Sensor", "1.0"); + + pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID, S_MOTION); + +} + +void loop() +{ + // Read digital motion value + boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; + + Serial.println(tripped); + send(msg.set(tripped?"1":"0")); // Send tripped value to gw + + // Sleep until interrupt comes in on motion sensor. Send update every two minute. + sleep(INTERRUPT,CHANGE, SLEEP_TIME); +} + + diff --git a/libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino b/libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino new file mode 100644 index 0000000..d7a786b --- /dev/null +++ b/libraries/MySensors/examples/ParkingSensor/ParkingSensor.ino @@ -0,0 +1,178 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Created by Henrik Ekblad + * + * DESCRIPTION + * Parking sensor using a neopixel led ring and distance sensor (HC-SR04). + * Configure the digital pins used for distance sensor and neopixels below. + * NOTE! Remeber to feed leds and distance sensor serparatly from your Arduino. + * It will probably not survive feeding more than a couple of LEDs. You + * can also adjust intesity below to reduce the power requirements. + * + * Sends parking status to the controller as a DOOR sensor if SEND_STATUS_TO_CONTROLLER + * is defined below. You can also use this _standalone_ without any radio by + * removing the SEND_STATUS_TO_CONTROLLER define. + */ + +#define SEND_STATUS_TO_CONTROLLER // Put a comment on this line for standalone mode + +#include +#include + +#ifdef SEND_STATUS_TO_CONTROLLER +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#endif + +#define NEO_PIN 4 // NeoPixels input pin + +#define TRIGGER_PIN 6 // Arduino pin tied to trigger pin on the ultrasonic sensor. +#define ECHO_PIN 5 // Arduino pin tied to echo pin on the ultrasonic sensor. + +#define NUMPIXELS 24 // Number of nexpixels in ring/strip +#define MAX_INTESITY 20 // Intesity of leds (in percentage). Remeber more intesity requires more power. + +// The maximum rated measuring range for the HC-SR04 is about 400-500cm. +#define MAX_DISTANCE 100 // Max distance we want to start indicating green (in cm) +#define PANIC_DISTANCE 5 // Mix distance we red warning indication should be active (in cm) +#define PARKED_DISTANCE 20 // Distance when "parked signal" should be sent to controller (in cm) + +#define PARK_OFF_TIMEOUT 20000 // Number of milliseconds until turning off light when parked. + +// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest +// example for more information on possible values. + +Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, NEO_PIN, NEO_GRB + NEO_KHZ400); + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +#ifdef SEND_STATUS_TO_CONTROLLER +#define CHILD_ID 1 +MyMessage msg(CHILD_ID,V_TRIPPED); +#endif +unsigned long sendInterval = 5000; // Send park status at maximum every 5 second. +unsigned long lastSend; + +int oldParkedStatus=-1; + +unsigned long blinkInterval = 100; // blink interval (milliseconds) +unsigned long lastBlinkPeriod; +bool blinkColor = true; + +// To make a fading motion on the led ring/tape we only move one pixel/distDebounce time +unsigned long distDebounce = 30; +unsigned long lastDebouncePeriod; +int numLightPixels=0; +int skipZero=0; + +void setup() { + Serial.begin(115200); + Serial.println("Starting distance sensor"); + pixels.begin(); // This initializes the NeoPixel library. + Serial.println("Neopixels initialized"); +#ifdef SEND_STATUS_TO_CONTROLLER + sendSketchInfo("Parking Sensor", "1.0"); + present(CHILD_ID, S_DOOR, "Parking Status"); +#endif +} + +void loop() { + unsigned long now = millis(); + + unsigned int fullDist = (sonar.ping_median() / US_ROUNDTRIP_CM); +// Serial.println(fullDist); + int displayDist = min(fullDist, MAX_DISTANCE); + if (displayDist == 0 && skipZero<10) { + // Try to filter zero readings + skipZero++; + return; + } + // Check if it is time to alter the leds + if (now-lastDebouncePeriod > distDebounce) { + lastDebouncePeriod = now; + + // Update parked status + int parked = displayDist != 0 && displayDist sendInterval) { + if (parked) + Serial.println("Car Parked"); + else + Serial.println("Car Gone"); +#ifdef SEND_STATUS_TO_CONTROLLER + send(msg.set(parked)); +#endif + oldParkedStatus = parked; + lastSend = now; + } + + if (parked && now-lastSend > PARK_OFF_TIMEOUT) { + // We've been parked for a while now. Turn off all pixels + for(int i=0;inumLightPixels) { + // Fast raise + numLightPixels += max((newLightPixels - numLightPixels) / 2, 1); + } else if (newLightPixels=NUMPIXELS) { + // Do some intense red blinking + if (now-lastBlinkPeriod > blinkInterval) { + blinkColor = !blinkColor; + lastBlinkPeriod = now; + } + for(int i=0;i +#include "MYSLog.h" + +#define VSN "v1.0" + +// Define two generic nodes with a single child +#define YING 200 +#define YANG 201 +#define CHILD 1 + +MyMessage mPing(CHILD, V_VAR1); //Ping message +MyMessage mPong(CHILD, V_VAR2); //Pong message + +void setup() { + setIncomingCallback(incomingMessage); + + present(CHILD, S_CUSTOM); // + + sendSketchInfo( nodeTypeAsCharRepresentation( getNodeId() ), VSN ); + LOG(F("\n%sReady.\n"), nodeTypeAsCharRepresentation(getNodeId())); +} + +void loop() { + + // Interactive command and control + // Entering a number from 0 or 1 will write the node 200 (YING) or 201 (YANG) to EEPROM + // Entering T on either node will initiatve a ping-pong test. + if (Serial.available()) { + byte inChar = Serial.read(); + uint8_t node = getNodeId(); + + // Manual Test Mode + if (inChar == 'T' || inChar == 't') { + LOG(F("T received - starting test...\n")); + MyMessage msg = mPong; + msg.sender = (node == YING ? YANG : YING); + sendPingOrPongResponse( msg ); + } + else if (inChar == '0' or inChar == '1') { + byte nodeID = 200 + (inChar - '0'); + setNodeId(nodeID); + } + else { + LOG("Invalid input\n"); + } + } +} + +void incomingMessage(const MyMessage &message) { + + LOG(F("Received %s from %s\n"), msgTypeAsCharRepresentation((mysensor_data)message.type), nodeTypeAsCharRepresentation(message.sender)); + + delay(250); + sendPingOrPongResponse( message ); +} + +void sendPingOrPongResponse( MyMessage msg ) { + + MyMessage response = (msg.type == V_VAR1 ? mPong : mPing); + + LOG(F("Sending %s to %s\n"), msgTypeAsCharRepresentation( (mysensor_data)response.type ), nodeTypeAsCharRepresentation(msg.sender)); + + // Set payload to current time in millis to ensure each message is unique + response.set( millis() ); + response.setDestination(msg.sender); + send(response); +} + +void setNodeId(byte nodeID) { + LOG(F("Setting node id to: %i.\n***Please restart the node for changes to take effect.\n"), nodeID); + eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, (byte)nodeID); +} + +const char * msgTypeAsCharRepresentation( mysensor_data mType ) { + return mType == V_VAR1 ? "Ping" : "Pong"; +} + +const char * nodeTypeAsCharRepresentation( uint8_t node ) { + return node == YING ? "Ying Node" : "Yang Node"; +} diff --git a/libraries/MySensors/examples/PressureSensor/PressureSensor.ino b/libraries/MySensors/examples/PressureSensor/PressureSensor.ino new file mode 100644 index 0000000..c7658ea --- /dev/null +++ b/libraries/MySensors/examples/PressureSensor/PressureSensor.ino @@ -0,0 +1,302 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * Pressure sensor example using BMP085 module + * http://www.mysensors.org/build/pressure + * + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include + +#define BARO_CHILD 0 +#define TEMP_CHILD 1 + +const float ALTITUDE = 688; // <-- adapt this value to your own location's altitude. + +// Sleep time between reads (in seconds). Do not change this value as the forecast algorithm needs a sample every minute. +const unsigned long SLEEP_TIME = 60000; + +const char *weather[] = { "stable", "sunny", "cloudy", "unstable", "thunderstorm", "unknown" }; +enum FORECAST +{ + STABLE = 0, // "Stable Weather Pattern" + SUNNY = 1, // "Slowly rising Good Weather", "Clear/Sunny " + CLOUDY = 2, // "Slowly falling L-Pressure ", "Cloudy/Rain " + UNSTABLE = 3, // "Quickly rising H-Press", "Not Stable" + THUNDERSTORM = 4, // "Quickly falling L-Press", "Thunderstorm" + UNKNOWN = 5 // "Unknown (More Time needed) +}; + +Adafruit_BMP085 bmp = Adafruit_BMP085(); // Digital Pressure Sensor + +float lastPressure = -1; +float lastTemp = -1; +int lastForecast = -1; + +const int LAST_SAMPLES_COUNT = 5; +float lastPressureSamples[LAST_SAMPLES_COUNT]; + +// this CONVERSION_FACTOR is used to convert from Pa to kPa in forecast algorithm +// get kPa/h be dividing hPa by 10 +#define CONVERSION_FACTOR (1.0/10.0) + +int minuteCount = 0; +bool firstRound = true; +// average value is used in forecast algorithm. +float pressureAvg; +// average after 2 hours is used as reference value for the next iteration. +float pressureAvg2; + +float dP_dt; +boolean metric; +MyMessage tempMsg(TEMP_CHILD, V_TEMP); +MyMessage pressureMsg(BARO_CHILD, V_PRESSURE); +MyMessage forecastMsg(BARO_CHILD, V_FORECAST); + + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Pressure Sensor", "1.1"); + + if (!bmp.begin()) + { + Serial.println("Could not find a valid BMP085 sensor, check wiring!"); + while (1) {} + } + + // Register sensors to gw (they will be created as child devices) + present(BARO_CHILD, S_BARO); + present(TEMP_CHILD, S_TEMP); + metric = getConfig().isMetric; +} + +void loop() +{ + float pressure = bmp.readSealevelPressure(ALTITUDE) / 100.0; + float temperature = bmp.readTemperature(); + + if (!metric) + { + // Convert to fahrenheit + temperature = temperature * 9.0 / 5.0 + 32.0; + } + + int forecast = sample(pressure); + + Serial.print("Temperature = "); + Serial.print(temperature); + Serial.println(metric ? " *C" : " *F"); + Serial.print("Pressure = "); + Serial.print(pressure); + Serial.println(" hPa"); + Serial.print("Forecast = "); + Serial.println(weather[forecast]); + + + if (temperature != lastTemp) + { + send(tempMsg.set(temperature, 1)); + lastTemp = temperature; + } + + if (pressure != lastPressure) + { + send(pressureMsg.set(pressure, 0)); + lastPressure = pressure; + } + + if (forecast != lastForecast) + { + send(forecastMsg.set(weather[forecast])); + lastForecast = forecast; + } + + sleep(SLEEP_TIME); +} + +float getLastPressureSamplesAverage() +{ + float lastPressureSamplesAverage = 0; + for (int i = 0; i < LAST_SAMPLES_COUNT; i++) + { + lastPressureSamplesAverage += lastPressureSamples[i]; + } + lastPressureSamplesAverage /= LAST_SAMPLES_COUNT; + + return lastPressureSamplesAverage; +} + + + +// Algorithm found here +// http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf +// Pressure in hPa --> forecast done by calculating kPa/h +int sample(float pressure) +{ + // Calculate the average of the last n minutes. + int index = minuteCount % LAST_SAMPLES_COUNT; + lastPressureSamples[index] = pressure; + + minuteCount++; + if (minuteCount > 185) + { + minuteCount = 6; + } + + if (minuteCount == 5) + { + pressureAvg = getLastPressureSamplesAverage(); + } + else if (minuteCount == 35) + { + float lastPressureAvg = getLastPressureSamplesAverage(); + float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; + if (firstRound) // first time initial 3 hour + { + dP_dt = change * 2; // note this is for t = 0.5hour + } + else + { + dP_dt = change / 1.5; // divide by 1.5 as this is the difference in time from 0 value. + } + } + else if (minuteCount == 65) + { + float lastPressureAvg = getLastPressureSamplesAverage(); + float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; + if (firstRound) //first time initial 3 hour + { + dP_dt = change; //note this is for t = 1 hour + } + else + { + dP_dt = change / 2; //divide by 2 as this is the difference in time from 0 value + } + } + else if (minuteCount == 95) + { + float lastPressureAvg = getLastPressureSamplesAverage(); + float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; + if (firstRound) // first time initial 3 hour + { + dP_dt = change / 1.5; // note this is for t = 1.5 hour + } + else + { + dP_dt = change / 2.5; // divide by 2.5 as this is the difference in time from 0 value + } + } + else if (minuteCount == 125) + { + float lastPressureAvg = getLastPressureSamplesAverage(); + pressureAvg2 = lastPressureAvg; // store for later use. + float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; + if (firstRound) // first time initial 3 hour + { + dP_dt = change / 2; // note this is for t = 2 hour + } + else + { + dP_dt = change / 3; // divide by 3 as this is the difference in time from 0 value + } + } + else if (minuteCount == 155) + { + float lastPressureAvg = getLastPressureSamplesAverage(); + float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; + if (firstRound) // first time initial 3 hour + { + dP_dt = change / 2.5; // note this is for t = 2.5 hour + } + else + { + dP_dt = change / 3.5; // divide by 3.5 as this is the difference in time from 0 value + } + } + else if (minuteCount == 185) + { + float lastPressureAvg = getLastPressureSamplesAverage(); + float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR; + if (firstRound) // first time initial 3 hour + { + dP_dt = change / 3; // note this is for t = 3 hour + } + else + { + dP_dt = change / 4; // divide by 4 as this is the difference in time from 0 value + } + pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past. + firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop. + } + + int forecast = UNKNOWN; + if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval. + { + forecast = UNKNOWN; + } + else if (dP_dt < (-0.25)) + { + forecast = THUNDERSTORM; + } + else if (dP_dt > 0.25) + { + forecast = UNSTABLE; + } + else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05))) + { + forecast = CLOUDY; + } + else if ((dP_dt > 0.05) && (dP_dt < 0.25)) + { + forecast = SUNNY; + } + else if ((dP_dt >(-0.05)) && (dP_dt < 0.05)) + { + forecast = STABLE; + } + else + { + forecast = UNKNOWN; + } + + // uncomment when debugging + //Serial.print(F("Forecast at minute ")); + //Serial.print(minuteCount); + //Serial.print(F(" dP/dt = ")); + //Serial.print(dP_dt); + //Serial.print(F("kPa/h --> ")); + //Serial.println(weather[forecast]); + + return forecast; +} diff --git a/libraries/MySensors/examples/RF433MhzSensor/RF433MhzSensor.ino b/libraries/MySensors/examples/RF433MhzSensor/RF433MhzSensor.ino new file mode 100644 index 0000000..ec21834 --- /dev/null +++ b/libraries/MySensors/examples/RF433MhzSensor/RF433MhzSensor.ino @@ -0,0 +1,139 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * This sketch demonstrates how to use InterruptChain to receive and + * decode remote switches (old and new) and remote sensors. + * + * Basically, this sketch combines the features of the ShowReceivedCode + * and ShowReceivedCodeNewKaku examples of RemoteSwitch and the + * ThermoHygroReceiver of RemoteSensor all at the same time! + * + * After uploading, enable the serial monitor at 115200 baud. + * When you press buttons on a 433MHz remote control, as supported by + * RemoteSwitch or NewRemoteSwitch, the code will be echoed. + * At the same time, if data of a remote thermo/hygro-sensor is + * received, as supported by RemoteSensor, it will be echoed as well. + * + * Setup: + * - connect a 433MHz receiver on digital pin 2. + * + * MySensor note: This example has not yet been adopted but can be used as an example + * of receiving 433Mhz stuff. + * + * One idea could be to echo received 433 codes back to gateway to be able to pick up and + * handle data over there. + * + */ + +#include +#include +#include +#include + +void setup() { + Serial.begin(115200); + + // Interrupt -1 to indicate you will call the interrupt handler with InterruptChain + RemoteReceiver::init(-1, 2, showOldCode); + + // Again, interrupt -1 to indicate you will call the interrupt handler with InterruptChain + NewRemoteReceiver::init(-1, 2, showNewCode); + + // And once more, interrupt -1 to indicate you will call the interrupt handler with InterruptChain + SensorReceiver::init(-1, showTempHumi); + + // On interrupt, call the interrupt handlers of remote and sensor receivers + InterruptChain::addInterruptCallback(0, RemoteReceiver::interruptHandler); + InterruptChain::addInterruptCallback(0, NewRemoteReceiver::interruptHandler); + InterruptChain::addInterruptCallback(0, SensorReceiver::interruptHandler); +} + +void loop() { + // You can do other stuff here! +} + +// shows the received code sent from an old-style remote switch +void showOldCode(unsigned long receivedCode, unsigned int period) { + // Print the received code. + Serial.print("Code: "); + Serial.print(receivedCode); + Serial.print(", period: "); + Serial.print(period); + Serial.println("us."); +} + +// Shows the received code sent from an new-style remote switch +void showNewCode(NewRemoteCode receivedCode) { + // Print the received code. + Serial.print("Addr "); + Serial.print(receivedCode.address); + + if (receivedCode.groupBit) { + Serial.print(" group"); + } else { + Serial.print(" unit "); + Serial.print(receivedCode.unit); + } + + switch (receivedCode.switchType) { + case NewRemoteCode::off: + Serial.print(" off"); + break; + case NewRemoteCode::on: + Serial.print(" on"); + break; + case NewRemoteCode::dim: + Serial.print(" dim level "); + Serial.print(receivedCode.dimLevel); + break; + case NewRemoteCode::on_with_dim: + Serial.print(" on with dim level "); + Serial.print(receivedCode.dimLevel); + break; + } + + Serial.print(", period: "); + Serial.print(receivedCode.period); + Serial.println("us."); +} + +// Shows the received sensor data +void showTempHumi(byte *data) { + // is data a ThermoHygro-device? + if ((data[3] & 0x1f) == 0x1e) { + // Yes! + byte channel, randomId; + int temp; + byte humidity; + + // Decode the data + SensorReceiver::decodeThermoHygro(data, channel, randomId, temp, humidity); + + // Print temperature. Note: temp is 10x the actual temperature! + Serial.print("Temperature: "); + Serial.print(temp / 10); // units + Serial.print('.'); + Serial.println(temp % 10); // decimal + } +} diff --git a/libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino b/libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino new file mode 100644 index 0000000..891d47e --- /dev/null +++ b/libraries/MySensors/examples/RFIDLockSensor/RFIDLockSensor.ino @@ -0,0 +1,184 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * RFID Lock sensor/actuator + * + * Use RFID tag to lock/unlock a door or trigger a scene on your controller. + * This example sketch allows you to add an optional relay or solenoid + * which can be activated/opened by RFID or controller. + * + * Use the I2C wiring option for your RFID module and connect to the following Arduino pins. + * + * RFID Arduino + * ----- ------- + * GND -> GND + * VCC -> +5V + * SCL -> A5 + * SDA -> A4 + * + * Use normal wiring for NRF24L01 radio + * + * Attach a optional relay or solonoid lock to pin 4 + * http://www.mysensors.org/build/rfid + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include +#include + + +// Add your valid rfid keys here. To find you your key just run sketch; hold your new RFID tag in fron ot the reader; +// and copy the key from serial output of this sketch. +const uint8_t maxKeyLength = 7; +uint8_t validKeys[][maxKeyLength] = { + { 0xB3, 0xC6, 0xD9, 0x80, 0x00, 0x00, 0x00 }, + { 0, 0, 0, 0, 0, 0, 0 }, // ADD YOUR KEYS HERE! + { 0, 0, 0, 0, 0, 0, 0 }}; +int keyCount = sizeof validKeys / maxKeyLength; + + +#define CHILD_ID 99 // Id of the sensor child + +// Pin definition +const int lockPin = 4; // (Digital 4) The pin that activates the relay/solenoid lock. +bool lockStatus; +MyMessage lockMsg(CHILD_ID, V_LOCK_STATUS); +PN532_I2C pn532i2c(Wire); +PN532 nfc(pn532i2c); + +void setup() { + + pinMode(lockPin, OUTPUT); + + nfc.begin(); + uint32_t versiondata = nfc.getFirmwareVersion(); + if (! versiondata) { + Serial.print("Couldn't find PN53x board"); + while (1); // halt + } + Serial.print("Found NFC chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); + // Set the max number of retry attempts to read from a card + // This prevents us from waiting forever for a card, which is + // the default behaviour of the PN532. + nfc.setPassiveActivationRetries(0x3); + + // configure board to read RFID tags + nfc.SAMConfig(); + + // Add callback for incoming messages + setIncomingCallback(incomingMessage); + + sendSketchInfo("RFID Lock", "1.0"); + present(CHILD_ID, S_LOCK); + + lockStatus = loadState(0); // Read last lock status from eeprom + setLockState(lockStatus, true); // Now set the last known state and send it to controller +} + +void loop() { + boolean success; + uint8_t key[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + uint8_t currentKeyLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) + + + // Wait for an ISO14443A type cards (Mifare, etc.). When one is found + // 'uid' will be populated with the UID, and uidLength will indicate + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &key[0], ¤tKeyLength); + + if (success) { + Serial.print("Found tag id: "); + for (uint8_t i=0; i < currentKeyLength; i++) + { + if (i>0) Serial.print(","); + Serial.print("0x");Serial.print(key[i], HEX); + } + for (uint8_t i=currentKeyLength; i < maxKeyLength; i++) + { + Serial.print(",0x00"); + } + + + Serial.println(""); + + boolean valid = false; + // Compare this key to the valid once registered here in sketch + for (int i=0;i + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Created by vil1driver + * + * DESCRIPTION + * RGB led strip controled with three dimmers + one On/Off for run/stop rgb color cycle :p + * + */ + +#define SN "RGB Led strip 3D" +#define SV "v1" + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +// Arduino pin attached to MOSFET Gate pin +#define RED_PIN 3 +#define GREEN_PIN 5 +#define BLUE_PIN 6 + +// Define message name and type to send sensor info +MyMessage RedStatus(RED_PIN, V_DIMMER); +MyMessage GreenStatus(GREEN_PIN, V_DIMMER); +MyMessage BlueStatus(BLUE_PIN, V_DIMMER); +MyMessage Status(1, V_DIMMER); +MyMessage rgbShowState(0, V_LIGHT); + +// Serial.print translate sensor id to sensor name +char color[][6] = {"","","","RED","","GREEN","BLUE"}; + +// Vars for rgbShow function +int redval = 0; +int greenval = 0; +int blueval = 0; +long time=0; +int isShow; + +void setup() +{ + // Add callback for incoming messages + setIncomingCallback(incomingMessage); + + // Present sketch (name, version) + sendSketchInfo(SN, SV); + + // Register sensors (id, type, description, ack back) + present(RED_PIN, S_DIMMER, "present RED light", false); + present(GREEN_PIN, S_DIMMER, "present GREEN light", false); + present(BLUE_PIN, S_DIMMER, "present BLUE light", false); + present(0, S_LIGHT, "present Show button", false); + + // Define pin mode (pin number, type) + pinMode(RED_PIN, OUTPUT); + pinMode(GREEN_PIN, OUTPUT); + pinMode(BLUE_PIN, OUTPUT); + + // Correct saved RGB value for first start + saveState(RED_PIN, constrain((int8_t)loadState(RED_PIN), 0, 100)); + saveState(GREEN_PIN, constrain((int8_t)loadState(GREEN_PIN), 0, 100)); + saveState(BLUE_PIN, constrain((int8_t)loadState(BLUE_PIN), 0, 100)); + + // Get value from eeprom and write to output + analogWrite(RED_PIN, 255 * loadState(RED_PIN) / 100); + analogWrite(GREEN_PIN, 255 * loadState(GREEN_PIN) / 100); + analogWrite(BLUE_PIN, 255 * loadState(BLUE_PIN) / 100); + + // Write some debug info + Serial.print("Load from eeprom RED: "); + Serial.print(loadState(RED_PIN)); + Serial.println("%"); + Serial.print("Load from eeprom GREEN: "); + Serial.print(loadState(GREEN_PIN)); + Serial.println("%"); + Serial.print("Load from eeprom BLUE: "); + Serial.print(loadState(BLUE_PIN)); + Serial.println("%"); + + // Send RGB value to controler (request ack back: true/false) + Serial.println("Send eeprom value to controler"); + send( RedStatus.set(loadState(RED_PIN)), false ); + send( GreenStatus.set(loadState(GREEN_PIN)), false ); + send( BlueStatus.set(loadState(BLUE_PIN)), false ); + + // Correct RGB show state for first start and load it (set to 'On' at first start) + saveState(0, constrain((int8_t)loadState(0), 0, 1)); + isShow=loadState(0); + + // Send RGB show state to controler (request ack back: true/false) + send( rgbShowState.set(isShow), false); + + if (isShow==1){Serial.println("RGB show running..."); } + Serial.println("Ready to receive messages..."); +} + +void loop() +{ + // Run RGB show if is set + if (isShow==1) + { + rgbShow(); + analogWrite(RED_PIN, redval); + analogWrite(GREEN_PIN, greenval); + analogWrite(BLUE_PIN, blueval); + } +} + + +void incomingMessage(const MyMessage &message) +{ + if (message.isAck()) + { + Serial.println("Got ack from gateway"); + } + if (message.type == V_LIGHT) + { + // Incoming on/off command sent from controller ("1" or "0") + int lightState = message.getString()[0] == '1'; + + // if receive RGB Show On commands, start the show + if (message.sensor==0 && lightState==1){ rgbShowOn(); } + // if receive RGB Show Off commands, stop the show + else if (message.sensor==0 && lightState==0){ rgbShowOff(); } + + // if receive RGB switch On command + else if (lightState==1) + { + // Write some debug info + Serial.print("Incoming change for "); + Serial.print(color[message.sensor]); + Serial.println(": On"); + Serial.print("Load from eeprom: "); + + if ( loadState(message.sensor) == 0) + { + // Pick up last saved dimmer level from the eeprom + analogWrite(message.sensor, 255 * loadState(10*message.sensor) / 100); + // Save loaded value to current + saveState(message.sensor, loadState(10*message.sensor)); + Serial.print(loadState(10*message.sensor)); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + send(Status.setSensor(message.sensor).set(loadState(10*message.sensor)),false); + } + else + { + // Pick up last saved dimmer level from the eeprom + analogWrite(message.sensor, 255 * loadState(message.sensor) / 100); + Serial.print(loadState(message.sensor)); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + send(Status.setSensor(message.sensor).set(loadState(message.sensor)),false); + } + // Stop the show if it's running + if (isShow==1){ rgbShowStop(message.sensor); } + } + // if recieve switch Off command + else if (lightState==0) + { + // Write output to 0 (Off) + analogWrite(message.sensor, 0); + // Save old value to eeprom if it'was not zero + if ( loadState(message.sensor) != 0 ) + { + saveState(10*message.sensor, constrain((int8_t)loadState(message.sensor), 0, 100)); + } + // Save new value to eeprom + saveState(message.sensor, 0); + // Write some debug info + Serial.print("Incoming change for "); + Serial.print(color[message.sensor]); + Serial.print(": "); + Serial.println("Off"); + Serial.print("Store old value: "); + Serial.print(loadState(10*message.sensor)); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + send(Status.setSensor(message.sensor).set(loadState(message.sensor)),false); + // Stop the show if it's running + if (isShow==1){ rgbShowStop(message.sensor); } + } + } + else if (message.type == V_DIMMER) + { + uint8_t incomingDimmerStatus = message.getByte(); + // limits range of sensor values to between 0 and 100 + incomingDimmerStatus = constrain((int8_t)incomingDimmerStatus, 0, 100); + // Change Dimmer level + analogWrite(message.sensor, 255 * incomingDimmerStatus / 100); + //Save value to eeprom + saveState(message.sensor, incomingDimmerStatus); + // Write some debug info + Serial.print("Incoming change for "); + Serial.print(color[message.sensor]); + Serial.print(": "); + Serial.print(incomingDimmerStatus); + Serial.println("%"); + // Send value to controler + Serial.println("Send value to controler"); + send(Status.setSensor(message.sensor).set(loadState(message.sensor)),false); + // Stop the show if it's running + if (isShow==1){ rgbShowStop(message.sensor); } + } +} + +void rgbShow() +{ + time = millis(); + redval = 128+250*cos(2*PI/300000*time); + greenval = 128+250*cos(2*PI/300000*time-222); + blueval = 128+250*cos(2*PI/300000*time-111); + // limits range of sensor values to between 0 and 255 + redval = constrain(redval, 0, 255); + greenval = constrain(greenval, 0, 255); + blueval = constrain(blueval, 0, 255); +} + +void rgbShowOn() +{ + // define show On + isShow=1; + // Save state + saveState(0, 1); + // Write some debug info + Serial.println("Show must go on"); +} + +void rgbShowOff() +{ + // define show Off + isShow=0; + // Save state + saveState(0, 0); + // Save RGB value to eeprom + saveState(RED_PIN, 100 * redval / 255); + saveState(GREEN_PIN, 100 * greenval / 255); + saveState(BLUE_PIN, 100 * blueval / 255); + // Write some debug info + Serial.println("Stop the show"); + // Send actual RGB value and state to controler and request ack back (true/false) + Serial.println("Send eeprom value to controler"); + send( RedStatus.set(loadState(RED_PIN)), false ); + send( GreenStatus.set(loadState(GREEN_PIN)), false ); + send( BlueStatus.set(loadState(BLUE_PIN)), false ); + send( rgbShowState.set(0), false); +} + +void rgbShowStop(int sensor) +{ + // define show Off + isShow=0; + // Save state + saveState(0, 0); + // Write some debug info + Serial.println("Stop the show"); + // Send actual RGB value and state to controler and request ack back (true/false) + Serial.println("Send eeprom value to controler"); + if (sensor != RED_PIN) + { + saveState(RED_PIN, 100 * redval / 255); + send( RedStatus.set(loadState(RED_PIN)), false ); + } + if (sensor != GREEN_PIN) + { + saveState(GREEN_PIN, 100 * greenval / 255); + send( GreenStatus.set(loadState(GREEN_PIN)), false ); + } + if (sensor != BLUE_PIN) + { + saveState(BLUE_PIN, 100 * blueval / 255); + send( BlueStatus.set(loadState(BLUE_PIN)), false ); + } + send( rgbShowState.set(0), false); +} + + + diff --git a/libraries/MySensors/examples/RainGauge/RainGauge.ino b/libraries/MySensors/examples/RainGauge/RainGauge.ino new file mode 100644 index 0000000..8c11f78 --- /dev/null +++ b/libraries/MySensors/examples/RainGauge/RainGauge.ino @@ -0,0 +1,599 @@ +/* + Arduino Tipping Bucket Rain Gauge + + April 26, 2015 + + Version 1.4.1 alpha + + Arduino Tipping Bucket Rain Gauge + + Utilizing a tipping bucket sensor, your Vera home automation controller and the MySensors.org + gateway you can measure and sense local rain. This sketch will create two devices on your + Vera controller. One will display your total precipitation for the last 5 days. The other, + a sensor that changes state if there is recent rain (up to last 120 hours) above a threshold. + Both these settings are user definable. + + There is a build overview video here: https://youtu.be/1eMfKQaLROo + + This sketch features the following: + + * Allows you to set the rain threshold in mm + * Allows you to determine the tripped indicator window up to 120 hours. + * Displays the last 5 days of rain in Variable1 through Variable5 + of the Rain Sensor device + * Configuration changes to Sensor device updated every hour + * Should run on any Arduino + * Will retain Tripped/Not Tripped status and data in a power interruption, saving small amount + of data to EEPROM (Circular Buffer to maximize life of EEPROM) + * LED status indicator + * Optional Temp/Humidity (DHT-22 or DHT-11) and Light LUX (BH1750) sensors. To use, uncomment + #define DHT_ON and/or #define LUX_ON + * Optionally send total accumulation of each day's rainfall or send only individual days rainfall totals. + Comment out #define USE_DAILY to display individual daily rainfall. + + by @BulldogLowell and @PeteWill for free public use + + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +//#define MY_NODE_ID 7 + +#include +#include +#include + +#define SKETCH_NAME "Rain Gauge" +#define SKETCH_VERSION "1.4.1a" + +#define DWELL_TIME 125 // this allows for radio to come back to power after a transmission, ideally 0 + +//#define DEBUG_ON // comment out this line to disable serial debug +#define DHT_ON // uncomment out this line to enable DHT sensor +#define LUX_ON // uncomment out this line to enable BH1750 sensor +//#define USE_DAILY // displays each time segment as an accumulation of prior periods inclusive. Comment out to display individual daily rainfall totals in the variables sent to your controller. + +#define CALIBRATE_FACTOR 60 // amount of rain per rain bucket tip e.g. 5 is .05mm +#define DHT_LUX_DELAY 300000 //Delay in milliseconds that the DHT and LUX sensors will wait before sending data + +#define CHILD_ID_RAIN_LOG 3 // Keeps track of accumulated rainfall +#define CHILD_ID_TRIPPED_INDICATOR 4 // Indicates Tripped when rain detected +#define EEPROM_BUFFER_LOCATION 0 // location of the EEPROM circular buffer +#define E_BUFFER_LENGTH 240 +#define RAIN_BUCKET_SIZE 120 + +#ifdef DEBUG_ON + #define DEBUG_PRINT(x) Serial.print(x) + #define DEBUG_PRINTLN(x) Serial.println(x) + #define SERIAL_START(x) Serial.begin(x) + #else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTLN(x) + #define SERIAL_START(x) +#endif +// +MyMessage msgRainRate(CHILD_ID_RAIN_LOG, V_RAINRATE); +MyMessage msgRain(CHILD_ID_RAIN_LOG, V_RAIN); +// +MyMessage msgRainVAR1(CHILD_ID_RAIN_LOG, V_VAR1); +MyMessage msgRainVAR2(CHILD_ID_RAIN_LOG, V_VAR2); +MyMessage msgRainVAR3(CHILD_ID_RAIN_LOG, V_VAR3); +MyMessage msgRainVAR4(CHILD_ID_RAIN_LOG, V_VAR4); +MyMessage msgRainVAR5(CHILD_ID_RAIN_LOG, V_VAR5); +// +MyMessage msgTripped(CHILD_ID_TRIPPED_INDICATOR, V_TRIPPED); +MyMessage msgTrippedVar1(CHILD_ID_TRIPPED_INDICATOR, V_VAR1); +MyMessage msgTrippedVar2(CHILD_ID_TRIPPED_INDICATOR, V_VAR2); +// +#ifdef DHT_ON + #include + #define CHILD_ID_HUM 0 + #define CHILD_ID_TEMP 1 + #define HUMIDITY_SENSOR_DIGITAL_PIN 8 + DHT dht; + float lastTemp; + float lastHum; + boolean metric = true; + MyMessage msgHum(CHILD_ID_HUM, V_HUM); + MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); +#endif +// +#ifdef LUX_ON + //BH1750 is connected to SCL (analog input A5) and SDA (analog input A4) + #include + #include + #define CHILD_ID_LIGHT 2 + BH1750 lightSensor; + MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); + unsigned int lastlux; + byte heartbeat = 10; //Used to send the light lux to gateway as soon as the device is restarted and after the DHT_LUX_DELAY has happened 10 times +#endif +unsigned long sensorPreviousMillis; +int eepromIndex; +int tipSensorPin = 3; // Pin the tipping bucket is connected to. Must be interrupt capable pin +int ledPin = 5; // Pin the LED is connected to. PWM capable pin required +unsigned long dataMillis; +unsigned long serialInterval = 600000UL; +const unsigned long oneHour = 3600000UL; +unsigned long lastTipTime; +unsigned long lastRainTime; //Used for rainRate calculation +unsigned int rainBucket [RAIN_BUCKET_SIZE] ; /* 24 hours x 5 Days = 120 hours */ +unsigned int rainRate = 0; +byte rainWindow = 72; //default rain window in hours. Will be overwritten with msgTrippedVar1. +volatile int wasTippedBuffer = 0; +int rainSensorThreshold = 50; //default rain sensor sensitivity in hundredths. Will be overwritten with msgTrippedVar2. +byte state = 0; +byte oldState = -1; +unsigned int lastRainRate = 0; +int lastMeasure = 0; +boolean gotTime = false; +byte lastHour; +byte currentHour; +// +void setup() +{ + SERIAL_START(115200); + // + // Set up the IO + pinMode(tipSensorPin, INPUT_PULLUP); + attachInterrupt (1, sensorTipped, FALLING); // depending on location of the hall effect sensor may need CHANGE + pinMode(ledPin, OUTPUT); + digitalWrite(ledPin, HIGH); + // + //Let's get the controller talking to the Arduino + setIncomingCallback(getVariables); + + sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); + wait(DWELL_TIME); + present(CHILD_ID_RAIN_LOG, S_RAIN); + wait(DWELL_TIME); + present(CHILD_ID_TRIPPED_INDICATOR, S_MOTION); + wait(DWELL_TIME); + DEBUG_PRINTLN(F("Sensor Presentation Complete")); + // + //Sync time with the server, this will be called hourly in order to keep time from creeping with the crystal + // + unsigned long functionTimeout = millis(); + while (timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL) + { + requestTime(receiveTime); + DEBUG_PRINTLN(F("Getting Time")); + wait(1000); // call once per second + DEBUG_PRINTLN(F(".")); + } + currentHour = hour(); + lastHour = hour(); + // + //retrieve from EEPROM stored values on a power cycle. + // + boolean isDataOnEeprom = false; + for (int i = 0; i < E_BUFFER_LENGTH; i++) + { + byte locator = loadState(EEPROM_BUFFER_LOCATION + i); + if (locator == 0xFE) // found the EEPROM circular buffer index + { + eepromIndex = EEPROM_BUFFER_LOCATION + i; + DEBUG_PRINT(F("EEPROM Index ")); + DEBUG_PRINTLN(eepromIndex); + //Now that we have the buffer index let's populate the rainBucket[] with data from eeprom + loadRainArray(eepromIndex); + isDataOnEeprom = true; + break; + } + } + // + if (!isDataOnEeprom) // Added for the first time it is run on a new Arduino + { + DEBUG_PRINTLN(F("I didn't find valid EEPROM Index, so I'm writing one to location 0")); + eepromIndex = EEPROM_BUFFER_LOCATION; + saveState(eepromIndex, 0xFE); + saveState(eepromIndex + 1, 0xFE); + //then I will clear out any bad data + for (int i = 2; i <= E_BUFFER_LENGTH; i++) + { + saveState(i, 0x00); + } + } + dataMillis = millis(); + lastTipTime = millis() - oneHour; //why is this -oneHour?? Doesn't millis() start at 0 when first powered on? + // + request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1); + wait(DWELL_TIME); + request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2); + wait(DWELL_TIME); + // +#ifdef DHT_ON + dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID_HUM, S_HUM); + wait(DWELL_TIME); + present(CHILD_ID_TEMP, S_TEMP); + wait(DWELL_TIME); + metric = getConfig().isMetric; + wait(DWELL_TIME); +#endif + // +#ifdef LUX_ON + present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); + wait(DWELL_TIME); + lightSensor.begin(); +#endif + // + DEBUG_PRINTLN(F("Radio Setup Complete!")); + transmitRainData(); +} + +void loop() +{ + if (state) + { + prettyFade(); // breathe if tripped + } + else + { + slowFlash(); // blink if not tripped + } +#ifdef DEBUG_ON // Serial Debug Block + if ( (millis() - dataMillis) >= serialInterval) + { + for (int i = 24; i <= 120; i = i + 24) + { + updateSerialData(i); + } + dataMillis = millis(); + } +#endif + // + // let's constantly check to see if the rain in the past rainWindow hours is greater than rainSensorThreshold + // + int measure = 0; // Check to see if we need to show sensor tripped in this block + for (int i = 0; i < rainWindow; i++) + { + measure += rainBucket [i]; + if (measure != lastMeasure) + { + // DEBUG_PRINT(F("measure value (total rainBucket within rainWindow): ")); + // DEBUG_PRINTLN(measure); + lastMeasure = measure; + } + } + // + state = (measure >= (rainSensorThreshold * 100)); + if (state != oldState) + { + send(msgTripped.set(state)); + wait(DWELL_TIME); + DEBUG_PRINT(F("New Sensor State... Sensor: ")); + DEBUG_PRINTLN(state ? "Tripped" : "Not Tripped"); + oldState = state; + } + // + unsigned long tipDelay = millis() - lastRainTime; + if (wasTippedBuffer) // if was tipped, then update the 24hour total and transmit to Vera + { + DEBUG_PRINTLN(F("Sensor Tipped")); + DEBUG_PRINT(F("rainBucket [0] value: ")); + DEBUG_PRINTLN(rainBucket [0]); + send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); //Calculate the total rain for the day + wait(DWELL_TIME); + wasTippedBuffer--; + rainRate = ((oneHour) / tipDelay); + if (rainRate != lastRainRate) + { + send(msgRainRate.set(rainRate, 1)); + wait(DWELL_TIME); + DEBUG_PRINT(F("RainRate= ")); + DEBUG_PRINTLN(rainRate); + lastRainRate = rainRate; + } + lastRainTime = lastTipTime; + } + // + currentHour = hour(); + if (currentHour != lastHour) + { + DEBUG_PRINTLN(F("One hour elapsed.")); + send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); // send today's rainfall + wait(DWELL_TIME); + saveState(eepromIndex, highByte(rainBucket[0])); + saveState(eepromIndex + 1, lowByte(rainBucket[0])); + DEBUG_PRINT(F("Saving rainBucket[0] to eeprom. rainBucket[0] = ")); + DEBUG_PRINTLN(rainBucket[0]); + for (int i = RAIN_BUCKET_SIZE - 1; i >= 0; i--)//cascade an hour of values back into the array + { + rainBucket [i + 1] = rainBucket [i]; + } + request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1); + wait(DWELL_TIME); + request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2); + wait(DWELL_TIME); + rainBucket[0] = 0; + eepromIndex = eepromIndex + 2; + if (eepromIndex > EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH) + { + eepromIndex = EEPROM_BUFFER_LOCATION; + } + DEBUG_PRINT(F("Writing to EEPROM. Index: ")); + DEBUG_PRINTLN(eepromIndex); + saveState(eepromIndex, 0xFE); + saveState(eepromIndex + 1, 0xFE); + requestTime(receiveTime); // sync the time every hour + wait(DWELL_TIME); + transmitRainData(); + rainRate = 0; + send(msgRainRate.set(rainRate, 1)); + wait(DWELL_TIME); + DEBUG_PRINTLN(F("Sending rainRate is 0 to controller")); + lastHour = currentHour; + } + if (millis() - sensorPreviousMillis > DHT_LUX_DELAY) + { + #ifdef DHT_ON //DHT Code + doDHT(); + #endif + #ifdef LUX_ON + doLUX(); + #endif + sensorPreviousMillis = millis(); + } +} +// +#ifdef DHT_ON +void doDHT(void) +{ + float temperature = dht.getTemperature(); + if (isnan(temperature)) + { + DEBUG_PRINTLN(F("Failed reading temperature from DHT")); + } else if (temperature != lastTemp) + { + lastTemp = temperature; + if (!metric) + { + temperature = dht.toFahrenheit(temperature); + } + send(msgTemp.set(temperature, 1)); + wait(DWELL_TIME); + DEBUG_PRINT(F("Temperature is: ")); + DEBUG_PRINTLN(temperature); + } + float humidity = dht.getHumidity();; + if (isnan(humidity)) + { + DEBUG_PRINTLN(F("Failed reading humidity from DHT")); + } else if (humidity != lastHum) + { + lastHum = humidity; + send(msgHum.set(humidity, 1)); + wait(DWELL_TIME); + DEBUG_PRINT(F("Humidity is: ")); + DEBUG_PRINTLN(humidity); + } +} +#endif +// +#ifdef LUX_ON +void doLUX(void) +{ + unsigned int lux = lightSensor.readLightLevel();// Get Lux value + DEBUG_PRINT(F("Current LUX Level: ")); + DEBUG_PRINTLN(lux); + heartbeat++; + if (lux != lastlux || heartbeat > 10) + { + send(msg.set(lux)); + lastlux = lux; + } + if (heartbeat > 10) + { + heartbeat = 0; + } +} +#endif +// +void sensorTipped() +{ + unsigned long thisTipTime = millis(); + if (thisTipTime - lastTipTime > 100UL) + { + rainBucket[0] += CALIBRATE_FACTOR; // adds CALIBRATE_FACTOR hundredths of unit each tip + wasTippedBuffer++; + } + lastTipTime = thisTipTime; +} +// +int rainTotal(int hours) +{ + int total = 0; + for ( int i = 0; i <= hours; i++) + { + total += rainBucket [i]; + } + return total; +} + +void updateSerialData(int x) +{ + DEBUG_PRINT(F("Rain last ")); + DEBUG_PRINT(x); + DEBUG_PRINTLN(F(" hours: ")); + float tipCount = 0; + for (int i = 0; i < x; i++) + { + tipCount = tipCount + rainBucket [i]; + } + tipCount = tipCount / 100; + DEBUG_PRINTLN(tipCount); +} + +void loadRainArray(int value) // retrieve stored rain array from EEPROM on powerup +{ + for (int i = 0; i < RAIN_BUCKET_SIZE; i++) + { + value = value - 2; + if (value < EEPROM_BUFFER_LOCATION) + { + value = EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH; + } + DEBUG_PRINT(F("EEPROM location: ")); + DEBUG_PRINTLN(value); + byte rainValueHigh = loadState(value); + byte rainValueLow = loadState(value + 1); + unsigned int rainValue = rainValueHigh << 8; + rainValue |= rainValueLow; + rainBucket[i + 1] = rainValue; + // + DEBUG_PRINT(F("rainBucket[ value: ")); + DEBUG_PRINT(i + 1); + DEBUG_PRINT(F("] value: ")); + DEBUG_PRINTLN(rainBucket[i + 1]); + } +} + +void transmitRainData(void) +{ + DEBUG_PRINT(F("In transmitRainData. currentHour = ")); + DEBUG_PRINTLN(currentHour); + int rainUpdateTotal = 0; + for (int i = currentHour; i >= 0; i--) + { + rainUpdateTotal += rainBucket[i]; + DEBUG_PRINT(F("Adding rainBucket[")); + DEBUG_PRINT(i); + DEBUG_PRINTLN(F("] to rainUpdateTotal.")); + } + DEBUG_PRINT(F("TX Day 1: rainUpdateTotal = ")); + DEBUG_PRINTLN((float)rainUpdateTotal / 100.0); + send(msgRainVAR1.set((float)rainUpdateTotal / 100.0, 1)); //Send current day rain totals (resets at midnight) + wait(DWELL_TIME); +#ifdef USE_DAILY + rainUpdateTotal = 0; +#endif + for (int i = currentHour + 24; i > currentHour; i--) + { + rainUpdateTotal += rainBucket[i]; + DEBUG_PRINT(F("Adding rainBucket[")); + DEBUG_PRINT(i); + DEBUG_PRINTLN(F("] to rainUpdateTotal.")); + } + DEBUG_PRINT(F("TX Day 2: rainUpdateTotal = ")); + DEBUG_PRINTLN((float)rainUpdateTotal / 100.0); + send(msgRainVAR2.set((float)rainUpdateTotal / 100.0, 1)); + wait(DWELL_TIME); +#ifdef USE_DAILY + rainUpdateTotal = 0; +#endif + for (int i = currentHour + 48; i > currentHour + 24; i--) + { + rainUpdateTotal += rainBucket[i]; + DEBUG_PRINT(F("Adding rainBucket[")); + DEBUG_PRINT(i); + DEBUG_PRINTLN(F("] to rainUpdateTotal.")); + } + DEBUG_PRINT(F("TX Day 3: rainUpdateTotal = ")); + DEBUG_PRINTLN((float)rainUpdateTotal / 100.0); + send(msgRainVAR3.set((float)rainUpdateTotal / 100.0, 1)); + wait(DWELL_TIME); +#ifdef USE_DAILY + rainUpdateTotal = 0; +#endif + for (int i = currentHour + 72; i > currentHour + 48; i--) + { + rainUpdateTotal += rainBucket[i]; + DEBUG_PRINT(F("Adding rainBucket[")); + DEBUG_PRINT(i); + DEBUG_PRINTLN(F("] to rainUpdateTotal.")); + } + DEBUG_PRINT(F("TX Day 4: rainUpdateTotal = ")); + DEBUG_PRINTLN((float)rainUpdateTotal / 100.0); + send(msgRainVAR4.set((float)rainUpdateTotal / 100.0, 1)); + wait(DWELL_TIME); +#ifdef USE_DAILY + rainUpdateTotal = 0; +#endif + for (int i = currentHour + 96; i > currentHour + 72; i--) + { + rainUpdateTotal += rainBucket[i]; + DEBUG_PRINT(F("Adding rainBucket[")); + DEBUG_PRINT(i); + DEBUG_PRINTLN(F("] to rainUpdateTotal.")); + } + DEBUG_PRINT(F("TX Day 5: rainUpdateTotal = ")); + DEBUG_PRINTLN((float)rainUpdateTotal / 100.0); + send(msgRainVAR5.set((float)rainUpdateTotal / 100.0, 1)); + wait(DWELL_TIME); +} + +void getVariables(const MyMessage &message) +{ + if (message.sensor == CHILD_ID_RAIN_LOG) + { + // nothing to do here + } + else if (message.sensor == CHILD_ID_TRIPPED_INDICATOR) + { + if (message.type == V_VAR1) + { + rainWindow = atoi(message.data); + if (rainWindow > 120) + { + rainWindow = 120; + } + else if (rainWindow < 1) + { + rainWindow = 1; + } + if (rainWindow != atoi(message.data)) // if I changed the value back inside the boundries, push that number back to Vera + { + send(msgTrippedVar1.set(rainWindow)); + } + } + else if (message.type == V_VAR2) + { + rainSensorThreshold = atoi(message.data); + if (rainSensorThreshold > 10000) + { + rainSensorThreshold = 10000; + } + else if (rainSensorThreshold < 1) + { + rainSensorThreshold = 1; + } + if (rainSensorThreshold != atoi(message.data)) // if I changed the value back inside the boundries, push that number back to Vera + { + send(msgTrippedVar2.set(rainSensorThreshold)); + } + } + } +} + +void prettyFade(void) +{ + float val = (exp(sin(millis() / 2000.0 * PI)) - 0.36787944) * 108.0; + analogWrite(ledPin, val); +} + +void slowFlash(void) +{ + static boolean ledState = true; + static unsigned long pulseStart = millis(); + if (millis() - pulseStart < 100UL) + { + digitalWrite(ledPin, !ledState); + pulseStart = millis(); + } +} + +void receiveTime(unsigned long time) +{ + DEBUG_PRINTLN(F("Time received...")); + setTime(time); + char theTime[6]; + sprintf(theTime, "%d:%2d", hour(), minute()); + DEBUG_PRINTLN(theTime); +} diff --git a/libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino b/libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino new file mode 100644 index 0000000..d33296c --- /dev/null +++ b/libraries/MySensors/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino @@ -0,0 +1,142 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * Example sketch showing how to request time from controller which is stored in RTC module + * The time and temperature (DS3231/DS3232) is shown on an attached Crystal LCD display + * + * + * Wiring (radio wiring on www.mysensors.org) + * ------------------------------------ + * Arduino RTC-Module I2C Display + * ------------------------------------ + * GND GND GND + * +5V VCC VCC + * A4 SDA SDA + * A5 SCL SCL + * + * http://www.mysensors.org/build/display + * + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include // A DS3231/DS3232 library +#include +#include + +boolean timeReceived = false; +unsigned long lastUpdate=0, lastRequest=0; + +// Initialize display. Google the correct settings for your display. +// The follwoing setting should work for the recommended display in the MySensors "shop". +LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("RTC Clock", "1.0"); + + // the function to get the time from the RTC + setSyncProvider(RTC.get); + + // Request latest time from controller at startup + requestTime(receiveTime); + + // initialize the lcd for 16 chars 2 lines and turn on backlight + lcd.begin(16,2); +} + +// This is called when a new time value was received +void receiveTime(unsigned long controllerTime) { + // Ok, set incoming time + Serial.print("Time value received: "); + Serial.println(controllerTime); + RTC.set(controllerTime); // this sets the RTC to the time from controller - which we do want periodically + timeReceived = true; +} + +void loop() +{ + unsigned long now = millis(); + + // If no time has been received yet, request it every 10 second from controller + // When time has been received, request update every hour + if ((!timeReceived && (now-lastRequest) > (10UL*1000UL)) + || (timeReceived && (now-lastRequest) > (60UL*1000UL*60UL))) { + // Request time from controller. + Serial.println("requesting time"); + requestTime(receiveTime); + lastRequest = now; + } + + // Update display every second + if (now-lastUpdate > 1000) { + updateDisplay(); + lastUpdate = now; + } +} + + +void updateDisplay(){ + tmElements_t tm; + RTC.read(tm); + + // Print date and time + lcd.home(); + lcd.print(tm.Day); + lcd.print("/"); + lcd.print(tm.Month); +// lcd.print(" "); +// lcd.print(tmYearToCalendar(tm.Year)-2000); + + lcd.print(" "); + printDigits(tm.Hour); + lcd.print(":"); + printDigits(tm.Minute); + lcd.print(":"); + printDigits(tm.Second); + + // Go to next line and print temperature + lcd.setCursor ( 0, 1 ); + lcd.print("Temp: "); + lcd.print(RTC.temperature()/4); + lcd.write(223); // Degree-sign + lcd.print("C"); +} + + +void printDigits(int digits){ + if(digits < 10) + lcd.print('0'); + lcd.print(digits); +} + + diff --git a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino new file mode 100644 index 0000000..c652166 --- /dev/null +++ b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino @@ -0,0 +1,86 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * Example sketch showing how to control physical relays. + * This example will remember relay state after power failure. + * http://www.mysensors.org/build/relay + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +// Enable repeater functionality for this node +#define MY_REPEATER_FEATURE + +#include + +#define RELAY_1 3 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) +#define NUMBER_OF_RELAYS 1 // Total number of attached relays +#define RELAY_ON 1 // GPIO value to write to turn on attached relay +#define RELAY_OFF 0 // GPIO value to write to turn off attached relay + +void setup() +{ + // Initialize library and add callback for incoming messages + setIncomingCallback(incomingMessage); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Relay", "1.0"); + + // Fetch relay status + for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) { + // Register all sensors to gw (they will be created as child devices) + present(sensor, S_LIGHT); + // Then set relay pins in output mode + pinMode(pin, OUTPUT); + // Set relay to last known state (using eeprom storage) + digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); + } +} + + +void loop() +{ + +} + +void incomingMessage(const MyMessage &message) { + // We only expect one type of message from controller. But we better check anyway. + if (message.type==V_LIGHT) { + // Change relay state + digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); + // Store state in eeprom + saveState(message.sensor, message.getBool()); + // Write some debug info + Serial.print("Incoming change for sensor:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getBool()); + } +} + diff --git a/libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino b/libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino new file mode 100644 index 0000000..8df9c80 --- /dev/null +++ b/libraries/MySensors/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino @@ -0,0 +1,121 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * Example sketch for a "light switch" where you can control light or something + * else from both HA controller and a local physical button + * (connected between digital pin 3 and GND). + * This node also works as a repeader for other nodes + * http://www.mysensors.org/build/relay + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +// Enabled repeater feature for this node +#define MY_REPEATER_FEATURE + +#include +#include + +#define RELAY_PIN 4 // Arduino Digital I/O pin number for relay +#define BUTTON_PIN 3 // Arduino Digital I/O pin number for button +#define CHILD_ID 1 // Id of the sensor child +#define RELAY_ON 1 +#define RELAY_OFF 0 + +Bounce debouncer = Bounce(); +int oldValue=0; +bool state; + +MyMessage msg(CHILD_ID,V_LIGHT); + +void setup() +{ + setIncomingCallback(incomingMessage); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Relay & Button", "1.0"); + + // Setup the button + pinMode(BUTTON_PIN,INPUT); + // Activate internal pull-up + digitalWrite(BUTTON_PIN,HIGH); + + // After setting up the button, setup debouncer + debouncer.attach(BUTTON_PIN); + debouncer.interval(5); + + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID, S_LIGHT); + + // Make sure relays are off when starting up + digitalWrite(RELAY_PIN, RELAY_OFF); + // Then set relay pins in output mode + pinMode(RELAY_PIN, OUTPUT); + + // Set relay to last known state (using eeprom storage) + state = loadState(CHILD_ID); + digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF); +} + + +/* +* Example on how to asynchronously check for new messages from gw +*/ +void loop() +{ + debouncer.update(); + // Get the update value + int value = debouncer.read(); + if (value != oldValue && value==0) { + send(msg.set(state?false:true), true); // Send new state and request ack back + } + oldValue = value; +} + +void incomingMessage(const MyMessage &message) { + // We only expect one type of message from controller. But we better check anyway. + if (message.isAck()) { + Serial.println("This is an ack from gateway"); + } + + if (message.type == V_LIGHT) { + // Change relay state + state = message.getBool(); + digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF); + // Store state in eeprom + saveState(CHILD_ID, state); + + // Write some debug info + Serial.print("Incoming change for sensor:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getBool()); + } +} + diff --git a/libraries/MySensors/examples/RepeaterNode/RepeaterNode.ino b/libraries/MySensors/examples/RepeaterNode/RepeaterNode.ino new file mode 100644 index 0000000..ace19da --- /dev/null +++ b/libraries/MySensors/examples/RepeaterNode/RepeaterNode.ino @@ -0,0 +1,52 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * Example sketch showing how to create a node thay repeates messages + * from nodes far from gateway back to gateway. + * It is important that nodes that has enabled repeater mode calls + * process() frequently. Repeaters should never sleep. + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +// Enabled repeater feature for this node +#define MY_REPEATER_FEATURE + +#include + +void setup() +{ + //Send the sensor node sketch version information to the gateway + sendSketchInfo("Repeater Node", "1.0"); +} + +void loop() +{ +} + diff --git a/libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino b/libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino new file mode 100644 index 0000000..2619c33 --- /dev/null +++ b/libraries/MySensors/examples/SecretKnockSensor/SecretKnockSensor.ino @@ -0,0 +1,379 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * + * Secret Knock Sensor + * http://www.mysensors.org/build/knock + * + * See original instructions here (note: The MySensors adopted code might differ in wiring. The instructions below is correct): + * https://learn.adafruit.com/secret-knock-activated-drawer-lock/ + * Version 13.10.31 Built with Arduino IDE 1.0.5 + * + * By Steve Hoefer http://grathio.com + * Adapted to MySensors by Henrik Ekblad + * + * Licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0 + * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ + * (In short: Do what you want, as long as you credit me, don't relicense it, and don't sell it or use it in anything you sell without contacting me.) + * + * ------Wiring------ + * Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND) + * Pin 1: Optional: Connect LED here (remember resisor in series) + * Pin 2: Optional: Piezo element (for beeps). + * Pin 5: A sound sensor (digital output) for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg + * Pin 4: Connects to either 1. Relay which open door or lock or + * 2. transistor that opens a solenoid lock when HIGH (see adafruit guide for this option). + * + * + * Connect radio according as usual(you can skip IRQ pin) + * http://www.mysensors.org/build/connect_radio + */ + + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + + +#define CHILD_ID 99 // Id of the sensor child + +const byte eepromValid = 121; // If the first byte in eeprom is this then the data is valid. + +/*Pin definitions*/ +const int programButton = 0; // (Digital 0) Record A New Knock button. +const int ledPin = 1; // (Digital 1) The LED pin (if any) +const int knockSensor = 5; // (Digital 5) for using the microphone digital output (tune knob to register knock) +const int audioOut = 2; // (Digital 2) for using the peizo as an output device. (Thing that goes beep.) +const int lockPin = 4; // (Digital 4) The pin that activates the relay/solenoid lock. + +/*Tuning constants. Changing the values below changes the behavior of the device.*/ +int threshold = 3; // Minimum signal from the piezo to register as a knock. Higher = less sensitive. Typical values 1 - 10 +const int rejectValue = 25; // If an individual knock is off by this percentage of a knock we don't unlock. Typical values 10-30 +const int averageRejectValue = 15; // If the average timing of all the knocks is off by this percent we don't unlock. Typical values 5-20 +const int knockFadeTime = 150; // Milliseconds we allow a knock to fade before we listen for another one. (Debounce timer.) +const int lockOperateTime = 2500; // Milliseconds that we operate the lock solenoid latch before releasing it. +const int maximumKnocks = 20; // Maximum number of knocks to listen for. +const int knockComplete = 1200; // Longest time to wait for a knock before we assume that it's finished. (milliseconds) + +byte secretCode[maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initial setup: "Shave and a Hair Cut, two bits." +int knockReadings[maximumKnocks]; // When someone knocks this array fills with the delays between knocks. +int knockSensorValue = 0; // Last reading of the knock sensor. +boolean programModeActive = false; // True if we're trying to program a new knock. + +bool lockStatus; + +MyMessage lockMsg(CHILD_ID, V_LOCK_STATUS); + +void setup() { + + pinMode(ledPin, OUTPUT); + pinMode(knockSensor, INPUT); + pinMode(lockPin, OUTPUT); + pinMode(programButton, INPUT); + digitalWrite(programButton, HIGH); // Enable internal pull up + + setIncomingCallback(incomingMessage); + + sendSketchInfo("Secret Knock", "1.0"); + present(CHILD_ID, S_LOCK); + + readSecretKnock(); // Load the secret knock (if any) from EEPROM. + + digitalWrite(lockPin, HIGH); // Unlock the door for a bit when we power up. For system check and to allow a way in if the key is forgotten + delay(500); // Wait a short time + + lockStatus = loadState(0); // Read last lock status from eeprom + setLockState(lockStatus, true); // Now set the last known state and send it to controller + + delay(500); // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock. +} + +void loop() { + // Listen for any knock at all. + knockSensorValue = digitalRead(knockSensor); + if (digitalRead(programButton) == LOW){ // is the program button pressed? + delay(100); // Cheap debounce. + if (digitalRead(programButton) == LOW){ + if (programModeActive == false){ // If we're not in programming mode, turn it on. + programModeActive = true; // Remember we're in programming mode. + digitalWrite(ledPin, HIGH); // Turn on the red light too so the user knows we're programming. + chirp(500, 1500); // And play a tone in case the user can't see the LED. + chirp(500, 1000); + } else { // If we are in programing mode, turn it off. + programModeActive = false; + digitalWrite(ledPin, LOW); + chirp(500, 1000); // Turn off the programming LED and play a sad note. + chirp(500, 1500); + delay(500); + } + while (digitalRead(programButton) == LOW){ + delay(10); // Hang around until the button is released. + } + } + delay(250); // Another cheap debounce. Longer because releasing the button can sometimes be sensed as a knock. + } + + + if (knockSensorValue == 0) { + if (programModeActive == true){ // Blink the LED when we sense a knock. + digitalWrite(ledPin, LOW); + } else { + digitalWrite(ledPin, HIGH); + } + knockDelay(); + if (programModeActive == true){ // Un-blink the LED. + digitalWrite(ledPin, HIGH); + } else { + digitalWrite(ledPin, LOW); + } + listenToSecretKnock(); // We have our first knock. Go and see what other knocks are in store... + } + +} + +// Records the timing of knocks. +void listenToSecretKnock(){ + int i = 0; + // First reset the listening array. + for (i=0; i < maximumKnocks; i++){ + knockReadings[i] = 0; + } + + int currentKnockNumber = 0; // Position counter for the array. + int startTime = millis(); // Reference for when this knock started. + int now = millis(); + + do { // Listen for the next knock or wait for it to timeout. + knockSensorValue = digitalRead(knockSensor); + + if (knockSensorValue == 0){ // Here's another knock. Save the time between knocks. + Serial.println("knock"); + + now=millis(); + knockReadings[currentKnockNumber] = now - startTime; + currentKnockNumber ++; + startTime = now; + + if (programModeActive==true){ // Blink the LED when we sense a knock. + digitalWrite(ledPin, LOW); + } else { + digitalWrite(ledPin, HIGH); + } + knockDelay(); + if (programModeActive == true){ // Un-blink the LED. + digitalWrite(ledPin, HIGH); + } else { + digitalWrite(ledPin, LOW); + } + } + + now = millis(); + + // Stop listening if there are too many knocks or there is too much time between knocks. + } while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks)); + Serial.println("end"); + + //we've got our knock recorded, lets see if it's valid + if (programModeActive == false){ // Only do this if we're not recording a new knock. + if (validateKnock() == true){ + // Lock/unlock door + chirp(500, 1500); // And play a tone in case the user can't see the LED. + chirp(500, 1000); + setLockState(!lockStatus, true); + } else { + Serial.println("fail unlock"); + + // knock is invalid. Blink the LED as a warning to others. + for (i=0; i < 4; i++){ + digitalWrite(ledPin, HIGH); + delay(50); + digitalWrite(ledPin, LOW); + delay(50); + } + } + } else { // If we're in programming mode we still validate the lock because it makes some numbers we need, we just don't do anything with the return. + validateKnock(); + } +} + + +// Unlocks the door. +void setLockState(bool state, bool doSend){ + if (state) + Serial.println("open lock"); + else + Serial.println("close lock"); + if (doSend) + send(lockMsg.set(state)); + + digitalWrite(ledPin, state); + digitalWrite(lockPin, state); + saveState(0,state); + lockStatus = state; + delay(500); // This delay is here because releasing the latch can cause a vibration that will be sensed as a knock. +} + +// Checks to see if our knock matches the secret. +// Returns true if it's a good knock, false if it's not. +boolean validateKnock(){ + int i = 0; + + int currentKnockCount = 0; + int secretKnockCount = 0; + int maxKnockInterval = 0; // We use this later to normalize the times. + + for (i=0;i 0){ + currentKnockCount++; + } + if (secretCode[i] > 0){ + secretKnockCount++; + } + + if (knockReadings[i] > maxKnockInterval){ // Collect normalization data while we're looping. + maxKnockInterval = knockReadings[i]; + } + } + + // If we're recording a new knock, save the info and get out of here. + if (programModeActive == true){ + for (i=0; i < maximumKnocks; i++){ // Normalize the time between knocks. (the longest time = 100) + secretCode[i] = map(knockReadings[i], 0, maxKnockInterval, 0, 100); + } + saveSecretKnock(); // save the result to EEPROM + programModeActive = false; + playbackKnock(maxKnockInterval); + return false; + } + + if (currentKnockCount != secretKnockCount){ // Easiest check first. If the number of knocks is wrong, don't unlock. + return false; + } + + /* Now we compare the relative intervals of our knocks, not the absolute time between them. + (ie: if you do the same pattern slow or fast it should still open the door.) + This makes it less picky, which while making it less secure can also make it + less of a pain to use if you're tempo is a little slow or fast. + */ + int totaltimeDifferences = 0; + int timeDiff = 0; + for (i=0; i < maximumKnocks; i++){ // Normalize the times + knockReadings[i]= map(knockReadings[i], 0, maxKnockInterval, 0, 100); + timeDiff = abs(knockReadings[i] - secretCode[i]); + if (timeDiff > rejectValue){ // Individual value too far out of whack. No access for this knock! + return false; + } + totaltimeDifferences += timeDiff; + } + // It can also fail if the whole thing is too inaccurate. + if (totaltimeDifferences / secretKnockCount > averageRejectValue){ + return false; + } + + return true; +} + + +// reads the secret knock from EEPROM. (if any.) +void readSecretKnock(){ + byte reading; + reading = loadState(1); + if (reading == eepromValid){ // only read EEPROM if the signature byte is correct. + for (int i=0; i < maximumKnocks ;i++){ + secretCode[i] = loadState(i+2); + } + } +} + + +//saves a new pattern too eeprom +void saveSecretKnock(){ + saveState(1, 0); // clear out the signature. That way we know if we didn't finish the write successfully. + for (int i=0; i < maximumKnocks; i++){ + saveState(i+2, secretCode[i]); + } + saveState(1, eepromValid); // all good. Write the signature so we'll know it's all good. +} + +// Plays back the pattern of the knock in blinks and beeps +void playbackKnock(int maxKnockInterval){ + digitalWrite(ledPin, LOW); + delay(1000); + digitalWrite(ledPin, HIGH); + chirp(200, 1800); + for (int i = 0; i < maximumKnocks ; i++){ + digitalWrite(ledPin, LOW); + // only turn it on if there's a delay + if (secretCode[i] > 0){ + delay(map(secretCode[i], 0, 100, 0, maxKnockInterval)); // Expand the time back out to what it was. Roughly. + digitalWrite(ledPin, HIGH); + chirp(200, 1800); + } + } + digitalWrite(ledPin, LOW); +} + +// Deals with the knock delay thingy. +void knockDelay(){ + int itterations = (knockFadeTime / 20); // Wait for the peak to dissipate before listening to next one. + for (int i=0; i < itterations; i++){ + delay(10); + analogRead(knockSensor); // This is done in an attempt to defuse the analog sensor's capacitor that will give false readings on high impedance sensors. + delay(10); + } +} + +// Plays a non-musical tone on the piezo. +// playTime = milliseconds to play the tone +// delayTime = time in microseconds between ticks. (smaller=higher pitch tone.) +void chirp(int playTime, int delayTime){ + long loopTime = (playTime * 1000L) / delayTime; + pinMode(audioOut, OUTPUT); + for(int i=0; i < loopTime; i++){ + digitalWrite(audioOut, HIGH); + delayMicroseconds(delayTime); + digitalWrite(audioOut, LOW); + } + pinMode(audioOut, INPUT); +} + + + +void incomingMessage(const MyMessage &message) { + // We only expect one type of message from controller. But we better check anyway. + if (message.type==V_LOCK_STATUS) { + // Change relay state + setLockState(message.getBool(), false); + + // Write some debug info + Serial.print("Incoming lock status:"); + Serial.println(message.getBool()); + } +} + diff --git a/libraries/MySensors/examples/SecureActuator/SecureActuator.ino b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino new file mode 100644 index 0000000..a3c0b15 --- /dev/null +++ b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino @@ -0,0 +1,102 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Patrick "Anticimex" Fallberg + * + * DESCRIPTION + * Example sketch showing how to securely control locks. + * This example will remember lock state even after power failure. + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +// Select soft/hardware signing method +#define MY_SIGNING_SOFT // Software signing enabled +//#define MY_SIGNING_ATSHA204 // Hardware signing using ATSHA204A + +// Enable node whitelisting +//#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} +// Enable this if you want destination node to sign all messages sent to this node. Default is not to require signing. +//#define MY_SIGNING_REQUEST_SIGNATURES + + +// SETTINGS FOR MY_SIGNING_SOFT +// Set the soft_serial value to an arbitrary value for proper security (9 bytes) +#define MY_SIGNING_SOFT_SERIAL 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09 +// Key to use for HMAC calculation in soft signing (32 bytes) +#define MY_SIGNING_SOFT_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + +#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 + +// SETTINGS FOR MY_SIGNING_ATSHA204 +#define MY_SIGNING_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached + +#include + + +#define LOCK_1 3 // Arduino Digital I/O pin number for first lock (second on pin+1 etc) +#define NOF_LOCKS 1 // Total number of attached locks +#define LOCK_LOCK 1 // GPIO value to write to lock attached lock +#define LOCK_UNLOCK 0 // GPIO value to write to unlock attached lock + + +void setup() +{ + // Add callback for incoming messages (signing is required) + setIncomingCallback(incomingMessage); + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Secure Lock", "1.0"); + + // Fetch lock status + for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS;lock++, pin++) { + // Register all locks to gw (they will be created as child devices) + present(lock, S_LOCK, "SecureActuator", false); + // Then set lock pins in output mode + pinMode(pin, OUTPUT); + // Set lock to last known state (using eeprom storage) + digitalWrite(pin, loadState(lock)?LOCK_LOCK:LOCK_UNLOCK); + } +} + +void loop() +{ +} + +void incomingMessage(const MyMessage &message) { + // We only expect one type of message from controller. But we better check anyway. + if (message.type==V_LOCK_STATUS && message.sensor<=NOF_LOCKS) { + // Change relay state + digitalWrite(message.sensor-1+LOCK_1, message.getBool()?LOCK_LOCK:LOCK_UNLOCK); + // Store state in eeprom + saveState(message.sensor, message.getBool()); + // Write some debug info + Serial.print("Incoming change for lock:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getBool()); + } +} + diff --git a/libraries/MySensors/examples/SensebenderBlink/SensebenderBlink.ino b/libraries/MySensors/examples/SensebenderBlink/SensebenderBlink.ino new file mode 100644 index 0000000..d84be05 --- /dev/null +++ b/libraries/MySensors/examples/SensebenderBlink/SensebenderBlink.ino @@ -0,0 +1,50 @@ +// Sensebender Micro board +// Simple blinking FW to test OTA updates + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable repeater feature +#define MY_REPEATER_FEATURE + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define SketchName "Sensebender Blink" +#define SketchVersion "20150721" +#define NODE_ID AUTO +#define CHILD_ID_COUNTER 0 + +#define LED_PIN A2 +#define BLINK_INTERVAL 500 +#define REPORT_TIME 5000L + +unsigned long lastUpdate = 0; +boolean LED_STATUS = false; + +MyMessage msgCounter(CHILD_ID_COUNTER, V_VAR1); + +void setup() { + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, LED_STATUS); + + sendSketchInfo(SketchName, SketchVersion); + + present(CHILD_ID_COUNTER, S_CUSTOM,"Millis()"); +} + +void loop() { + wait(BLINK_INTERVAL); + LED_STATUS ^= true; + digitalWrite(LED_PIN, LED_STATUS); + + if (millis()-lastUpdate > REPORT_TIME) { + send(msgCounter.set( millis() )); + lastUpdate = millis(); + } +} + + diff --git a/libraries/MySensors/examples/SensebenderMicro/SensebenderMicro.ino b/libraries/MySensors/examples/SensebenderMicro/SensebenderMicro.ino new file mode 100644 index 0000000..b66bdbd --- /dev/null +++ b/libraries/MySensors/examples/SensebenderMicro/SensebenderMicro.ino @@ -0,0 +1,422 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Thomas Bowman Mørch + * + * DESCRIPTION + * Default sensor sketch for Sensebender Micro module + * Act as a temperature / humidity sensor by default. + * + * If A0 is held low while powering on, it will enter testmode, which verifies all on-board peripherals + * + * Battery voltage is as battery percentage (Internal message), and optionally as a sensor value (See defines below) + * + * + * Version 1.3 - Thomas Bowman Mørch + * Improved transmission logic, eliminating spurious transmissions (when temperatuere / humidity fluctuates 1 up and down between measurements) + * + * Added OTA boot mode, need to hold A1 low while applying power. (uses slightly more power as it's waiting for bootloader messages) + * + */ + +// Enable debug prints to serial monitor +//#define MY_DEBUG + +// Define a static node address, remove if you want auto address assignment +//#deine MY_NODE_ID 3 + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include +#include "drivers/SPIFlash/SPIFlash.cpp" +#include +#include +#include +#include +//#include + +// Uncomment the line below, to transmit battery voltage as a normal sensor value +//#define BATT_SENSOR 199 + +#define RELEASE "1.3" + +#define AVERAGES 2 + +// Child sensor ID's +#define CHILD_ID_TEMP 1 +#define CHILD_ID_HUM 2 + +// How many milli seconds between each measurement +#define MEASURE_INTERVAL 60000 + +// How many milli seconds should we wait for OTA? +#define OTA_WAIT_PERIOD 300 + +// FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller +#define FORCE_TRANSMIT_INTERVAL 30 + +// When MEASURE_INTERVAL is 60000 and FORCE_TRANSMIT_INTERVAL is 30, we force a transmission every 30 minutes. +// Between the forced transmissions a tranmission will only occur if the measured value differs from the previous measurement + +// HUMI_TRANSMIT_THRESHOLD tells how much the humidity should have changed since last time it was transmitted. Likewise with +// TEMP_TRANSMIT_THRESHOLD for temperature threshold. +#define HUMI_TRANSMIT_THRESHOLD 0.5 +#define TEMP_TRANSMIT_THRESHOLD 0.5 + +// Pin definitions +#define TEST_PIN A0 +#define OTA_ENABLE A1 +#define LED_PIN A2 +#define ATSHA204_PIN 17 // A3 + +const int sha204Pin = ATSHA204_PIN; +atsha204Class sha204(sha204Pin); + +SI7021 humiditySensor; +SPIFlash flash(8, 0x1F65); + +// Sensor messages +MyMessage msgHum(CHILD_ID_HUM, V_HUM); +MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); + +#ifdef BATT_SENSOR +MyMessage msgBatt(BATT_SENSOR, V_VOLTAGE); +#endif + +// Global settings +int measureCount = 0; +int sendBattery = 0; +boolean isMetric = true; +boolean highfreq = true; +boolean ota_enabled = false; +boolean transmission_occured = false; + +// Storage of old measurements +float lastTemperature = -100; +int lastHumidity = -100; +long lastBattery = -100; + +RunningAverage raHum(AVERAGES); + +/**************************************************** + * + * Setup code + * + ****************************************************/ +void setup() { + + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, LOW); + + Serial.begin(115200); + Serial.print(F("Sensebender Micro FW ")); + Serial.print(RELEASE); + Serial.flush(); + + // First check if we should boot into test mode + + pinMode(TEST_PIN,INPUT); + digitalWrite(TEST_PIN, HIGH); // Enable pullup + if (!digitalRead(TEST_PIN)) testMode(); + + pinMode(OTA_ENABLE, INPUT); + digitalWrite(OTA_ENABLE, HIGH); + if (!digitalRead(OTA_ENABLE)) { + ota_enabled = true; + } + + // Make sure that ATSHA204 is not floating + pinMode(ATSHA204_PIN, INPUT); + digitalWrite(ATSHA204_PIN, HIGH); + + digitalWrite(TEST_PIN,LOW); + digitalWrite(OTA_ENABLE, LOW); // remove pullup, save some power. + + digitalWrite(LED_PIN, HIGH); + + humiditySensor.begin(); + + digitalWrite(LED_PIN, LOW); + + Serial.flush(); + Serial.println(F(" - Online!")); + sendSketchInfo("Sensebender Micro", RELEASE); + + present(CHILD_ID_TEMP,S_TEMP); + present(CHILD_ID_HUM,S_HUM); + +#ifdef BATT_SENSOR + present(BATT_SENSOR, S_POWER); +#endif + + + isMetric = getConfig().isMetric; + Serial.print(F("isMetric: ")); Serial.println(isMetric); + raHum.clear(); + sendTempHumidityMeasurements(false); + sendBattLevel(false); + if (ota_enabled) Serial.println("OTA FW update enabled"); + +} + + +/*********************************************** + * + * Main loop function + * + ***********************************************/ +void loop() { + + measureCount ++; + sendBattery ++; + bool forceTransmit = false; + transmission_occured = false; + if ((measureCount == 5) && highfreq) + { + if (!ota_enabled) clock_prescale_set(clock_div_8); // Switch to 1Mhz for the reminder of the sketch, save power. + highfreq = false; + } + + if (measureCount > FORCE_TRANSMIT_INTERVAL) { // force a transmission + forceTransmit = true; + measureCount = 0; + } + + sendTempHumidityMeasurements(forceTransmit); + if (sendBattery > 60) + { + sendBattLevel(forceTransmit); // Not needed to send battery info that often + sendBattery = 0; + } + + if (ota_enabled & transmission_occured) { + wait(OTA_WAIT_PERIOD); + } + + sleep(MEASURE_INTERVAL); +} + + +/********************************************* + * + * Sends temperature and humidity from Si7021 sensor + * + * Parameters + * - force : Forces transmission of a value (even if it's the same as previous measurement) + * + *********************************************/ +void sendTempHumidityMeasurements(bool force) +{ + bool tx = force; + + si7021_env data = humiditySensor.getHumidityAndTemperature(); + + raHum.addValue(data.humidityPercent); + + float diffTemp = abs(lastTemperature - (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths)/100); + float diffHum = abs(lastHumidity - raHum.getAverage()); + + Serial.print(F("TempDiff :"));Serial.println(diffTemp); + Serial.print(F("HumDiff :"));Serial.println(diffHum); + + if (isnan(diffHum)) tx = true; + if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true; + if (diffHum > HUMI_TRANSMIT_THRESHOLD) tx = true; + + if (tx) { + measureCount = 0; + float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0; + + int humidity = data.humidityPercent; + Serial.print("T: ");Serial.println(temperature); + Serial.print("H: ");Serial.println(humidity); + + send(msgTemp.set(temperature,1)); + send(msgHum.set(humidity)); + lastTemperature = temperature; + lastHumidity = humidity; + transmission_occured = true; + } +} + +/******************************************** + * + * Sends battery information (battery percentage) + * + * Parameters + * - force : Forces transmission of a value + * + *******************************************/ +void sendBattLevel(bool force) +{ + if (force) lastBattery = -1; + long vcc = readVcc(); + if (vcc != lastBattery) { + lastBattery = vcc; + +#ifdef BATT_SENSOR + send(msgBatt.set(vcc)); +#endif + + // Calculate percentage + + vcc = vcc - 1900; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at + + long percent = vcc / 14.0; + sendBatteryLevel(percent); + transmission_occured = true; + } +} + +/******************************************* + * + * Internal battery ADC measuring + * + *******************************************/ +long readVcc() { + // Read 1.1V reference against AVcc + // set the reference to Vcc and the measurement to the internal 1.1V reference + #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); + #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) + ADMUX = _BV(MUX5) | _BV(MUX0); + #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) + ADcdMUX = _BV(MUX3) | _BV(MUX2); + #else + ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); + #endif + + delay(2); // Wait for Vref to settle + ADCSRA |= _BV(ADSC); // Start conversion + while (bit_is_set(ADCSRA,ADSC)); // measuring + + uint8_t low = ADCL; // must read ADCL first - it then locks ADCH + uint8_t high = ADCH; // unlocks both + + long result = (high<<8) | low; + + result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 + return result; // Vcc in millivolts + +} + +/**************************************************** + * + * Verify all peripherals, and signal via the LED if any problems. + * + ****************************************************/ +void testMode() +{ + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + byte tests = 0; + + digitalWrite(LED_PIN, HIGH); // Turn on LED. + Serial.println(F(" - TestMode")); + Serial.println(F("Testing peripherals!")); + Serial.flush(); + Serial.print(F("-> SI7021 : ")); + Serial.flush(); + + if (humiditySensor.begin()) + { + Serial.println(F("ok!")); + tests ++; + } + else + { + Serial.println(F("failed!")); + } + Serial.flush(); + + Serial.print(F("-> Flash : ")); + Serial.flush(); + if (flash.initialize()) + { + Serial.println(F("ok!")); + tests ++; + } + else + { + Serial.println(F("failed!")); + } + Serial.flush(); + + + Serial.print(F("-> SHA204 : ")); + ret_code = sha204.sha204c_wakeup(rx_buffer); + Serial.flush(); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX); + } + Serial.flush(); + if (ret_code == SHA204_SUCCESS) + { + ret_code = sha204.getSerialNumber(rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX); + } + else + { + Serial.print(F("Ok (serial : ")); + for (int i=0; i<9; i++) + { + if (rx_buffer[i] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[i], HEX); + } + Serial.println(")"); + tests ++; + } + + } + Serial.flush(); + + Serial.println(F("Test finished")); + + if (tests == 3) + { + Serial.println(F("Selftest ok!")); + while (1) // Blink OK pattern! + { + digitalWrite(LED_PIN, HIGH); + delay(200); + digitalWrite(LED_PIN, LOW); + delay(200); + } + } + else + { + Serial.println(F("----> Selftest failed!")); + while (1) // Blink FAILED pattern! Rappidly blinking.. + { + } + } +} + diff --git a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino new file mode 100644 index 0000000..6e94b95 --- /dev/null +++ b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino @@ -0,0 +1,82 @@ + /** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * The ArduinoGateway prints data received from sensors on the serial link. + * The gateway accepts input on seral which will be sent out on radio network. + * + * The GW code is designed for Arduino Nano 328p / 16MHz + * + * Wire connections (OPTIONAL): + * - Inclusion button should be connected between digital pin 3 and GND + * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series + * + * LEDs (OPTIONAL): + * - To use the feature, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h + * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved + * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly + * - ERR (red) - fast blink on error during transmission error or recieve crc error + * + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +// Enable serial gateway +#define MY_GATEWAY_SERIAL + +// Flash leds on rx/tx/err +#define MY_LEDS_BLINKING_FEATURE +// Set blinking period +#define MY_DEFAULT_LED_BLINK_PERIOD 300 + +// Enable inclusion mode +#define MY_INCLUSION_MODE_FEATURE +// Enable Inclusion mode button on gateway +#define MY_INCLUSION_BUTTON_FEATURE +// Set inclusion mode duration (in seconds) +#define MY_INCLUSION_MODE_DURATION 60 +// Digital pin used for inclusion mode button +#define MY_INCLUSION_MODE_BUTTON_PIN 3 + +#define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin +#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin +#define MY_DEFAULT_TX_LED_PIN 9 // the PCB, on board LED + +#include + +void setup() +{ + // Nothing to do here +} + +void loop() +{ + // Nothing to do here +} + + + + + diff --git a/libraries/MySensors/examples/ServoActuator/ServoActuator.ino b/libraries/MySensors/examples/ServoActuator/ServoActuator.ino new file mode 100644 index 0000000..48a2aa4 --- /dev/null +++ b/libraries/MySensors/examples/ServoActuator/ServoActuator.ino @@ -0,0 +1,106 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * Contribution by: Derek Macias + * + * DESCRIPTION + * Example showing how to create an atuator for a servo. + * Connect red to +5V, Black or brown to GND and the last cable to Digital pin 3. + * The servo consumes much power and should probably have its own powersource.' + * The arduino might spontanally restart if too much power is used (happend + * to me when servo tried to pass the extreme positions = full load). + * http://www.mysensors.org/build/servo + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +#define SERVO_DIGITAL_OUT_PIN 3 +#define SERVO_MIN 0 // Fine tune your servos min. 0-180 +#define SERVO_MAX 180 // Fine tune your servos max. 0-180 +#define DETACH_DELAY 900 // Tune this to let your movement finish before detaching the servo +#define CHILD_ID 10 // Id of the sensor child + +MyMessage msg(CHILD_ID, V_DIMMER); +Servo myservo; // create servo object to control a servo + // a maximum of eight servo objects can be created Sensor gw(9,10); +unsigned long timeOfLastChange = 0; +bool attachedServo = false; + +void setup() +{ + // Attach method for incoming messages + setIncomingCallback(incomingMessage); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Servo", "1.0"); + + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID, S_COVER); + + // Request last servo state at startup + request(CHILD_ID, V_DIMMER); +} + +void loop() +{ + if (attachedServo && millis() - timeOfLastChange > DETACH_DELAY) { + myservo.detach(); + attachedServo = false; + } +} + +void incomingMessage(const MyMessage &message) { + myservo.attach(SERVO_DIGITAL_OUT_PIN); + attachedServo = true; + if (message.type==V_DIMMER) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE + int val = message.getInt(); + myservo.write(SERVO_MAX + (SERVO_MIN-SERVO_MAX)/100 * val); // sets the servo position 0-180 + // Write some debug info + Serial.print("Servo changed. new state: "); + Serial.println(val); + } else if (message.type==V_UP) { + Serial.println("Servo UP command"); + myservo.write(SERVO_MIN); + send(msg.set(100)); + } else if (message.type==V_DOWN) { + Serial.println("Servo DOWN command"); + myservo.write(SERVO_MAX); + send(msg.set(0)); + } else if (message.type==V_STOP) { + Serial.println("Servo STOP command"); + myservo.detach(); + attachedServo = false; + + } + timeOfLastChange = millis(); +} + + + diff --git a/libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino b/libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino new file mode 100644 index 0000000..4c542df --- /dev/null +++ b/libraries/MySensors/examples/Sha204Personalizer/Sha204Personalizer.ino @@ -0,0 +1,1007 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Patrick Fallberg, January 10, 2015 + * + * DESCRIPTION + * SHA204 personalization sketch + * + * This sketch will write factory default settings to the configuration zone + * and then lock it. + * It will then either + * a. Generate a random value to use as a key which will be stored in + * slot 0. The key is printed on UART (115200) in clear text for the user to be + * able to use it as a user-supplied key in other personalization executions + * where the same key is needed. + * b. Use a user-supplied value to use as a key which will be stored in + * slot 0. + * Finally it will lock the data zone. + * + * By default, no locking is performed. User have to manually enable the flags that + * turn on the locking. Furthermore, user have to send a SPACE character on serial + * console when prompted to do any locking. On boards that does not provide UART + * input it is possible to configure the sketch to skip this confirmation. + * Default settings use ATSHA204 on pin 17 (A3). + */ + +#include +#include + +// The pin the ATSHA204 is connected on +#define ATSHA204_PIN 17 // A3 + +// Uncomment this to enable locking the configuration zone. +// *** BE AWARE THAT THIS PREVENTS ANY FUTURE CONFIGURATION CHANGE TO THE CHIP *** +// It is still possible to change the key, and this also enable random key generation +//#define LOCK_CONFIGURATION + +// Uncomment this to enable locking the data zone. +// *** BE AWARE THAT THIS PREVENTS THE KEY TO BE CHANGED *** +// It is not required to lock data, key cannot be retrieved anyway, but by locking +// data, it can be guaranteed that nobody even with physical access to the chip, +// will be able to change the key. +//#define LOCK_DATA + +// Uncomment this to skip key storage (typically once key has been written once) +//#define SKIP_KEY_STORAGE + +// Uncomment this to skip key data storage (once configuration is locked, key +// will aways randomize) +// Uncomment this to skip key generation and use 'user_key_data' as key instead. +//#define USER_KEY_DATA + +// Uncomment this for boards that lack UART +// IMPORTANT: No confirmation will be required for locking any zones with this +// configuration! +// Also, key generation is not permitted in this mode as there is no way of +// presenting the generated key. +//#define SKIP_UART_CONFIRMATION + +#if defined(SKIP_UART_CONFIRMATION) && !defined(USER_KEY_DATA) +#error You have to define USER_KEY_DATA for boards that does not have UART +#endif + +#ifdef USER_KEY_DATA +#define MY_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +const uint8_t user_key_data[32] = {MY_HMAC_KEY}; +#endif + +const int sha204Pin = ATSHA204_PIN; +atsha204Class sha204(sha204Pin); + +void halt() +{ + Serial.println(F("Halting!")); + while(1); +} + +uint16_t write_config_and_get_crc() +{ + uint16_t crc = 0; + uint8_t config_word[4]; + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + bool do_write; + + // We will set default settings from datasheet on all slots. This means that we can use slot 0 for the key + // as that slot will not be readable (key will therefore be secure) and slot 8 for the payload digest + // calculationon as that slot can be written in clear text even when the datazone is locked. + // Other settings which are not relevant are kept as is. + + for (int i=0; i < 88; i += 4) + { + do_write = true; + if (i == 20) + { + config_word[0] = 0x8F; + config_word[1] = 0x80; + config_word[2] = 0x80; + config_word[3] = 0xA1; + } + else if (i == 24) + { + config_word[0] = 0x82; + config_word[1] = 0xE0; + config_word[2] = 0xA3; + config_word[3] = 0x60; + } + else if (i == 28) + { + config_word[0] = 0x94; + config_word[1] = 0x40; + config_word[2] = 0xA0; + config_word[3] = 0x85; + } + else if (i == 32) + { + config_word[0] = 0x86; + config_word[1] = 0x40; + config_word[2] = 0x87; + config_word[3] = 0x07; + } + else if (i == 36) + { + config_word[0] = 0x0F; + config_word[1] = 0x00; + config_word[2] = 0x89; + config_word[3] = 0xF2; + } + else if (i == 40) + { + config_word[0] = 0x8A; + config_word[1] = 0x7A; + config_word[2] = 0x0B; + config_word[3] = 0x8B; + } + else if (i == 44) + { + config_word[0] = 0x0C; + config_word[1] = 0x4C; + config_word[2] = 0xDD; + config_word[3] = 0x4D; + } + else if (i == 48) + { + config_word[0] = 0xC2; + config_word[1] = 0x42; + config_word[2] = 0xAF; + config_word[3] = 0x8F; + } + else if (i == 52 || i == 56 || i == 60 || i == 64) + { + config_word[0] = 0xFF; + config_word[1] = 0x00; + config_word[2] = 0xFF; + config_word[3] = 0x00; + } + else if (i == 68 || i == 72 || i == 76 || i == 80) + { + config_word[0] = 0xFF; + config_word[1] = 0xFF; + config_word[2] = 0xFF; + config_word[3] = 0xFF; + } + else + { + // All other configs are untouched + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to read config. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + // Set config_word to the read data + config_word[0] = rx_buffer[SHA204_BUFFER_POS_DATA+0]; + config_word[1] = rx_buffer[SHA204_BUFFER_POS_DATA+1]; + config_word[2] = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + config_word[3] = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + do_write = false; + } + + // Update crc with CRC for the current word + crc = sha204.calculateAndUpdateCrc(4, config_word, crc); + + // Write config word + if (do_write) + { + ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_CONFIG, + i >> 2, 4, config_word, 0, NULL, 0, NULL, + WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to write config word at address ")); Serial.print(i); + Serial.print(F(". Response: ")); Serial.println(ret_code, HEX); + halt(); + } + } + } + return crc; +} + +void write_key(uint8_t* key) +{ + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + + // Write key to slot 0 + ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, + 0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL, + WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to write key to slot 0. Response: ")); Serial.println(ret_code, HEX); + halt(); + } +} + +void dump_configuration() +{ + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + + for (int i=0; i < 88; i += 4) + { + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to read config. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + if (i == 0x00) + { + Serial.print(F(" SN[0:1] | SN[2:3] | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x04) + { + Serial.print(F(" Revnum | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } + else if (i == 0x08) + { + Serial.print(F(" SN[4:7] | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } + else if (i == 0x0C) + { + Serial.print(F(" SN[8] | Reserved13 | I2CEnable | Reserved15 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x10) + { + Serial.print(F(" I2CAddress | TempOffset | OTPmode | SelectorMode | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x14) + { + Serial.print(F(" SlotConfig00 | SlotConfig01 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x18) + { + Serial.print(F(" SlotConfig02 | SlotConfig03 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x1C) + { + Serial.print(F(" SlotConfig04 | SlotConfig05 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x20) + { + Serial.print(F(" SlotConfig06 | SlotConfig07 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x24) + { + Serial.print(F(" SlotConfig08 | SlotConfig09 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x28) + { + Serial.print(F(" SlotConfig0A | SlotConfig0B | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x2C) + { + Serial.print(F(" SlotConfig0C | SlotConfig0D | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x30) + { + Serial.print(F(" SlotConfig0E | SlotConfig0F | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x34) + { + Serial.print(F(" UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x38) + { + Serial.print(F(" UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x3C) + { + Serial.print(F(" UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x40) + { + Serial.print(F(" UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + else if (i == 0x44) + { + Serial.print(F(" LastKeyUse[0:3] | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } + else if (i == 0x48) + { + Serial.print(F(" LastKeyUse[4:7] | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } + else if (i == 0x4C) + { + Serial.print(F(" LastKeyUse[8:B] | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } + else if (i == 0x50) + { + Serial.print(F(" LastKeyUse[C:F] | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } + else if (i == 0x54) + { + Serial.print(F(" UserExtra | Selector | LockValue | LockConfig | ")); + for (int j=0; j<4; j++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) + { + Serial.print(F(" | ")); + } + else + { + Serial.print(F(" ")); + } + } + Serial.println(); + } + } +} + +void setup() +{ + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t key[32]; + uint8_t ret_code; + uint8_t lockConfig = 0; + uint8_t lockValue = 0; + uint16_t crc; + (void)crc; + + Serial.begin(115200); + + Serial.println(F("ATSHA204 personalization sketch for MySensors usage.")); + Serial.println(F("----------------------------------------------------")); + + // Wake device before starting operations + ret_code = sha204.sha204c_wakeup(rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + + // Output device revision on console + ret_code = sha204.sha204m_dev_rev(tx_buffer, rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to determine device revision. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + Serial.print(F("Device revision: ")); + for (int i=0; i<4; i++) + { + if (rx_buffer[SHA204_BUFFER_POS_DATA+i] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+i], HEX); + } + Serial.println(); + } + + // Output serial number on console + ret_code = sha204.getSerialNumber(rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + Serial.print(F("Device serial: ")); + Serial.print('{'); + for (int i=0; i<9; i++) + { + Serial.print(F("0x")); + if (rx_buffer[i] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[i], HEX); + if (i < 8) Serial.print(','); + } + Serial.print('}'); + Serial.println(); + for (int i=0; i<9; i++) + { + if (rx_buffer[i] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[i], HEX); + } + Serial.println(); + } + + // Read out lock config bits to determine if locking is possible + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + } + + if (lockConfig != 0x00) + { + // Write config and get CRC for the updated config + crc = write_config_and_get_crc(); + + // List current configuration before attempting to lock + Serial.println(F("Chip configuration:")); + dump_configuration(); + +#ifdef LOCK_CONFIGURATION + // Purge serial input buffer +#ifndef SKIP_UART_CONFIRMATION + while (Serial.available()) + { + Serial.read(); + } + Serial.println(F("Send SPACE character now to lock the configuration...")); + + while (Serial.available() == 0); + if (Serial.read() == ' ') +#endif //not SKIP_UART_CONFIRMATION + { + Serial.println(F("Locking configuration...")); + + // Correct sequence, resync chip + ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer); + if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) + { + Serial.print(F("Resync failed. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + + // Lock configuration zone + ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_CONFIG, + crc, 0, NULL, 0, NULL, 0, NULL, + LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Configuration lock failed. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + Serial.println(F("Configuration locked.")); + + // Update lock flags after locking + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + } + } + } +#ifndef SKIP_UART_CONFIRMATION + else + { + Serial.println(F("Unexpected answer. Skipping lock.")); + } +#endif //not SKIP_UART_CONFIRMATION +#else //LOCK_CONFIGURATION + Serial.println(F("Configuration not locked. Define LOCK_CONFIGURATION to lock for real.")); +#endif + } + else + { + Serial.println(F("Skipping configuration write and lock (configuration already locked).")); + Serial.println(F("Chip configuration:")); + dump_configuration(); + } + +#ifdef SKIP_KEY_STORAGE + Serial.println(F("Disable SKIP_KEY_STORAGE to store key.")); +#else +#ifdef USER_KEY_DATA + memcpy(key, user_key_data, 32); + Serial.println(F("Using this user supplied key:")); +#else + // Retrieve random value to use as key + ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Random key generation failed. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32); + } + if (lockConfig == 0x00) + { + Serial.println(F("Take note of this key, it will never be the shown again:")); + } + else + { + Serial.println(F("Key is not randomized (configuration not locked):")); + } +#endif + Serial.print("#define MY_HMAC_KEY "); + for (int i=0; i<32; i++) + { + Serial.print("0x"); + if (key[i] < 0x10) + { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(key[i], HEX); + if (i < 31) Serial.print(','); + if (i+1 == 16) Serial.print("\\\n "); + } + Serial.println(); + + // It will not be possible to write the key if the configuration zone is unlocked + if (lockConfig == 0x00) + { + // Write the key to the appropriate slot in the data zone + Serial.println(F("Writing key to slot 0...")); + write_key(key); + } + else + { + Serial.println(F("Skipping key storage (configuration not locked).")); + Serial.println(F("The configuration must be locked to be able to write a key.")); + } +#endif + + if (lockValue != 0x00) + { +#ifdef LOCK_DATA +#ifndef SKIP_UART_CONFIRMATION + while (Serial.available()) + { + Serial.read(); + } + Serial.println(F("Send SPACE character to lock data...")); + while (Serial.available() == 0); + if (Serial.read() == ' ') +#endif //not SKIP_UART_CONFIRMATION + { + // Correct sequence, resync chip + ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer); + if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) + { + Serial.print(F("Resync failed. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + + // If configuration is unlocked, key is not updated. Locking data in this case will cause + // slot 0 to contain an unknown (or factory default) key, and this is in practically any + // usecase not the desired behaviour, so ask for additional confirmation in this case. + if (lockConfig != 0x00) + { + while (Serial.available()) + { + Serial.read(); + } + Serial.println(F("*** ATTENTION ***")); + Serial.println(F("Configuration is not locked. Are you ABSULOUTELY SURE you want to lock data?")); + Serial.println(F("Locking data at this stage will cause slot 0 to contain a factory default key")); + Serial.println(F("which cannot be change after locking is done. This is in practically any usecase")); + Serial.println(F("NOT the desired behavour. Send SPACE character now to lock data anyway...")); + while (Serial.available() == 0); + if (Serial.read() != ' ') + { + Serial.println(F("Unexpected answer. Skipping lock.")); + halt(); + } + } + + // Lock data zone + ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_DATA | LOCK_ZONE_NO_CRC, + 0x0000, 0, NULL, 0, NULL, 0, NULL, + LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Data lock failed. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + Serial.println(F("Data locked.")); + + // Update lock flags after locking + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); + if (ret_code != SHA204_SUCCESS) + { + Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX); + halt(); + } + else + { + lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + } + } + } +#ifndef SKIP_UART_CONFIRMATION + else + { + Serial.println(F("Unexpected answer. Skipping lock.")); + } +#endif //not SKIP_UART_CONFIRMATION +#else //LOCK_DATA + Serial.println(F("Data not locked. Define LOCK_DATA to lock for real.")); +#endif + } + else + { + Serial.println(F("Skipping OTP/data zone lock (zone already locked).")); + } + + Serial.println(F("--------------------------------")); + Serial.println(F("Personalization is now complete.")); + Serial.print(F("Configuration is ")); + if (lockConfig == 0x00) + { + Serial.println("LOCKED"); + } + else + { + Serial.println("UNLOCKED"); + } + Serial.print(F("Data is ")); + if (lockValue == 0x00) + { + Serial.println("LOCKED"); + } + else + { + Serial.println("UNLOCKED"); + } +} + +void loop() +{ +} diff --git a/libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino b/libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino new file mode 100644 index 0000000..8c39a79 --- /dev/null +++ b/libraries/MySensors/examples/SoilMoistSensor/SoilMoistSensor.ino @@ -0,0 +1,186 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * Arduino soil moisture based on gypsum sensor/resistive sensor to avoid electric catalyse in soil + * Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148 + * + * Gypsum sensor and calibration: + * DIY: See http://vanderleevineyard.com/1/category/vinduino/1.html + * Built: Davis / Watermark 200SS + * http://www.cooking-hacks.com/watermark-soil-moisture-sensor?_bksrc=item2item&_bkloc=product + * http://www.irrometer.com/pdf/supportmaterial/sensors/voltage-WM-chart.pdf + * cb (centibar) http://www.irrometer.com/basics.html + * 0-10 Saturated Soil. Occurs for a day or two after irrigation + * 10-20 Soil is adequately wet (except coarse sands which are drying out at this range) + * 30-60 Usual range to irrigate or water (except heavy clay soils). + * 60-100 Usual range to irrigate heavy clay soils + * 100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution. + * + * Connection: + * D6, D7: alternative powering to avoid sensor degradation + * A0, A1: alternative resistance mesuring + * + * Based on: + * "Vinduino" portable soil moisture sensor code V3.00 + * Date December 31, 2012 + * Reinier van der Lee and Theodore Kaskalis + * www.vanderleevineyard.com + * Contributor: epierre +**/ + +// Copyright (C) 2015, Reinier van der Lee +// www.vanderleevineyard.com + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. + +// This program 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 General Public License for more details. + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include // Conversion equation from resistance to % +#include + +// Setting up format for reading 3 soil sensors +#define NUM_READS 10 // Number of sensor reads for filtering +#define CHILD_ID 0 + +MyMessage msg(CHILD_ID, V_LEVEL); +unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) + +long buffer[NUM_READS]; +int index; + +typedef struct { // Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs) + int moisture; + long resistance; +} values; + +const long knownResistor = 4700; // Constant value of known resistor in Ohms + +int supplyVoltage; // Measured supply voltage +int sensorVoltage; // Measured sensor voltage + +values valueOf[NUM_READS]; // Calculated moisture percentages and resistances to be sorted and filtered + +int i; // Simple index variable + +void setup() { + + sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0"); + present(CHILD_ID, S_HUM); + // initialize the digital pins as an output. + // Pin 6,7 is for sensor 1 + // initialize the digital pin as an output. + // Pin 6 is sense resistor voltage supply 1 + pinMode(6, OUTPUT); + + // initialize the digital pin as an output. + // Pin 7 is sense resistor voltage supply 2 + pinMode(7, OUTPUT); +} + +void loop() { + + measure(6,7,1); + Serial.print ("\t"); + Serial.println (average()); + long read1 = average(); + + measure(7,6,0); + Serial.print ("\t"); + Serial.println (average()); + long read2= average(); + + long sensor1 = (read1 + read2)/2; + + Serial.print ("resistance bias =" ); + Serial.println (read1-read2); + Serial.print ("sensor bias compensated value = "); + Serial.println (sensor1); + Serial.println (); + + //send back the values + send(msg.set((long int)ceil(sensor1))); + // delay until next measurement (msec) + sleep(SLEEP_TIME); +} + +void measure (int phase_b, int phase_a, int analog_input) +{ + // read sensor, filter, and calculate resistance value + // Noise filter: median filter + + for (i=0; i= NUM_READS) index = 0; +} + +long average(){ + long sum = 0; + for (int i = 0; i < NUM_READS; i++){ + sum += buffer[i]; + } + return (long)(sum / NUM_READS); +} diff --git a/libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino b/libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino new file mode 100644 index 0000000..f73a44c --- /dev/null +++ b/libraries/MySensors/examples/TimeAwareSensor/TimeAwareSensor.ino @@ -0,0 +1,95 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * Example sketch showing how to request time from controller. + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +boolean timeReceived = false; +unsigned long lastUpdate=0, lastRequest=0; + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Clock", "1.0"); + + // Request time from controller. + requestTime(receiveTime); +} + +// This is called when a new time value was received +void receiveTime(unsigned long time) { + // Ok, set incoming time + setTime(time); + timeReceived = true; +} + +void loop() +{ + unsigned long now = millis(); + + // If no time has been received yet, request it every 10 second from controller + // When time has been received, request update every hour + if ((!timeReceived && (now-lastRequest) > (10UL*1000UL)) + || (timeReceived && (now-lastRequest) > (60UL*1000UL*60UL))) { + // Request time from controller. + Serial.println("requesting time"); + requestTime(receiveTime); + lastRequest = now; + } + + // Print time every second + if (timeReceived && now-lastUpdate > 1000) { + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); + lastUpdate = now; + } +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + + diff --git a/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/ArialNumFontPlus.c b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/ArialNumFontPlus.c new file mode 100644 index 0000000..bbe7fd1 --- /dev/null +++ b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/ArialNumFontPlus.c @@ -0,0 +1,22 @@ +// SevenSegNumFontPlus.c +// Font type : Special (SubSet) +// Font size : 32x50 pixels +// Memory usage : 2204 bytes + +#include + +const uint8_t ArialNumFontPlus[2204] PROGMEM={ +0x20,0x32,0x30,0x0B, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xF8,0x00,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x00,0x03,0xF8,0x1F,0x80,0x03,0xF0,0x0F,0xC0,0x07,0xE0,0x07,0xC0,0x07,0xC0,0x03,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0xFC,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3F,0x00,0x00,0x7C,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xF0,0x0F,0xC0,0x01,0xF8,0x1F,0x80,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x7F,0xFC,0x00,0x00,0x1F,0xF8,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x7F,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x03,0xFD,0xF0,0x00,0x0F,0xF1,0xF0,0x00,0x0F,0xE1,0xF0,0x00,0x0F,0x81,0xF0,0x00,0x0F,0x01,0xF0,0x00,0x0C,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //1 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x7F,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xE0,0x07,0xE0,0x0F,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x3E,0x00,0x00,0xF8,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0x80,0x00,0x00,0x7F,0x00,0x00,0x00,0xFE,0x00,0x00,0x01,0xFC,0x00,0x00,0x03,0xF8,0x00,0x00,0x07,0xF0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0x80,0x00,0x00,0x7F,0x00,0x00,0x00,0xFE,0x00,0x00,0x01,0xFC,0x00,0x00,0x03,0xF8,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x3F,0xFC,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x03,0xE0,0x1F,0xC0,0x07,0xC0,0x0F,0xC0,0x07,0x80,0x07,0xE0,0x0F,0x80,0x03,0xE0,0x0F,0x00,0x03,0xE0,0x0F,0x00,0x03,0xF0,0x0F,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0x80,0x00,0x07,0xFF,0x00,0x00,0x07,0xFF,0x00,0x00,0x07,0xFF,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x1F,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x07,0xF0,0x07,0xE0,0x0F,0xE0,0x03,0xFC,0x3F,0xC0,0x01,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0xFF,0x00,0x00,0x01,0xFF,0x00,0x00,0x01,0xFF,0x00,0x00,0x03,0xFF,0x00,0x00,0x07,0xDF,0x00,0x00,0x07,0xDF,0x00,0x00,0x0F,0x9F,0x00,0x00,0x0F,0x9F,0x00,0x00,0x1F,0x1F,0x00,0x00,0x3E,0x1F,0x00,0x00,0x7E,0x1F,0x00,0x00,0x7C,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x07,0xC0,0x1F,0x00,0x07,0xC0,0x1F,0x00,0x0F,0x80,0x1F,0x00,0x1F,0x80,0x1F,0x00,0x1F,0x00,0x1F,0x00,0x3E,0x00,0x1F,0x00,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00, //4 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xF0,0x01,0xFF,0xFF,0xF0,0x01,0xFF,0xFF,0xF0,0x01,0xFF,0xFF,0xF0,0x01,0xFF,0xFF,0xF0,0x03,0xE0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0xF0,0x00,0x0F,0x8F,0xFE,0x00,0x0F,0xBF,0xFF,0x80,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xE0,0x1F,0xFF,0x07,0xF0,0x1F,0xE0,0x03,0xF0,0x1F,0xC0,0x01,0xF8,0x1F,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x3F,0x00,0x00,0xF8,0x3F,0x00,0x00,0xF8,0x3F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x80,0x03,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xE0,0x1F,0xC0,0x03,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0x00,0x01,0xFF,0xFE,0x00,0x00,0x7F,0xF8,0x00,0x00,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 5 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x3F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xC0,0x03,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xF8,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x03,0xF0,0x00,0x3F,0x1F,0xFC,0x00,0x3F,0x7F,0xFE,0x00,0x3F,0xFF,0xFF,0x80,0x3F,0xFF,0xFF,0xC0,0x3F,0xF8,0x0F,0xE0,0x3F,0xE0,0x03,0xF0,0x3F,0xE0,0x03,0xF0,0x3F,0xC0,0x01,0xF8,0x3F,0x80,0x00,0xF8,0x3F,0x80,0x00,0xF8,0x3F,0x00,0x00,0x7C,0x3F,0x00,0x00,0x7C,0x3F,0x00,0x00,0x7C,0x3F,0x00,0x00,0x7C,0x3F,0x00,0x00,0x7C,0x3F,0x00,0x00,0x7C,0x1F,0x00,0x00,0x7C,0x1F,0x80,0x00,0x78,0x1F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0xC0,0x01,0xF0,0x07,0xF0,0x03,0xF0,0x03,0xF8,0x0F,0xE0,0x01,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0x00,0x00,0x1F,0xFC,0x00,0x00,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x03,0xF8,0x1F,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xC0,0x03,0xE0,0x0F,0xC0,0x03,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x03,0xE0,0x07,0xC0,0x01,0xF0,0x07,0x80,0x00,0xFC,0x3F,0x00,0x00,0x7F,0xFF,0x00,0x00,0x3F,0xFC,0x00,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xC0,0x07,0xF0,0x0F,0xE0,0x0F,0xC0,0x03,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x03,0xF0,0x07,0xC0,0x07,0xE0,0x03,0xF0,0x0F,0xC0,0x01,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x00,0x00,0x3F,0xFC,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x3F,0xFC,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xC0,0x03,0xF8,0x1F,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0xC0,0x03,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x80,0x01,0xFC,0x1F,0x80,0x01,0xFC,0x0F,0xC0,0x03,0xFC,0x0F,0xC0,0x03,0xFC,0x07,0xE0,0x07,0xFC,0x07,0xE0,0x07,0xFC,0x03,0xF8,0x1F,0xFC,0x01,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFC,0x00,0xFF,0xFE,0xFC,0x00,0x7F,0xF8,0xFC,0x00,0x1F,0xE0,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF0,0x1F,0x00,0x03,0xF0,0x1F,0x80,0x07,0xE0,0x0F,0xC0,0x0F,0xE0,0x0F,0xE0,0x3F,0xC0,0x07,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0x00,0x01,0xFF,0xFE,0x00,0x00,0xFF,0xF8,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 neu +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : +}; diff --git a/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino new file mode 100644 index 0000000..b22f318 --- /dev/null +++ b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino @@ -0,0 +1,198 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * + * DESCRIPTION + * http://www.mysensors.org/build/scene_controller + * Touch Display Scene Controller build using a touch enabled tft display + * attached to a ATMega 2560. This example fetches time from controller and sends + * in scene commands to the controller. + * Short press sends V_SCENE_ON and long press (>0.5sec) sends V_SCENE_OFF. + * + * Henrik Ekblad + * + * This example uses: + * UTFT library: http://www.henningkarlsen.com/electronics/library.php?id=51 + * Convert your own images here: http://www.henningkarlsen.com/electronics/t_imageconverter565.php + * + * The 3v3 output on the ATMega2560 is especially bad. I had to use a step down + * on the 5V output to get solid transmissions. + * + * + * Connect radio + * ---------------------------------- + * Radio Arduino Pin + * ---------------------------------- + * GND GND + * 5V -> Step down -> 3V3 (see buying guide for help finding step-down) + * SCK 14 + * MOSI 15 + * MISO 16 + * CE 17 + * CSN 18 + * + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable soft spi as radio has a hard time sharing spi +#define MY_SOFTSPI + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include +#include +#include +#include +#include +#include +#include "arial_bold.c" +#include "ArialNumFontPlus.c" +#include "logo.c" + +#define CHILD_ID 1 + +int LONG_PRESS = 500; // Number of millisecons to trinnger scene off for button push +int RESEND_DEBOUNCE = 2000; // Number of millisecons interval between sending of same + // scene number again. + // This is used to avoid unwanted re-trigger when using + // a sensetive touch diplay. + +// Add your buttons here. Max is 5 if you still want time at the top. +char *buttons[] = { + (char *)"Good Morning", + (char *)"Clean Up!", + (char *)"All Lights Off", + (char *)"Music On/Off" + }; + +const int buttonCount = sizeof(buttons)/sizeof(char *); +const int padding = 10; +const int topBarHeight = 60; + +MyMessage on(CHILD_ID, V_SCENE_ON); +MyMessage off(CHILD_ID, V_SCENE_OFF); + +UTFT myGLCD(ITDB32S,38,39,40,41); +UTouch myTouch( 6, 5, 4, 3, 2); +UTFT_Buttons myButtons(&myGLCD, &myTouch); +boolean timeReceived = false; +unsigned long lastTimeUpdate=0, lastRequest=0; +char timeBuf[20]; + + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont((uint8_t*)ArialNumFontPlus); + myGLCD.setColor(100, 255, 100); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawBitmap (0, 0, 60, 60, (unsigned int*)logo); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_MEDIUM); + + myButtons.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_BLUE); + myButtons.setTextFont((uint8_t*)arial_bold); + int height = (myGLCD.getDisplayYSize()-topBarHeight-(padding*(buttonCount+2)))/buttonCount; + + // Add buttons + for (int i=0; i=0) { + bool longPress = millis()-now>(unsigned long)LONG_PRESS; + + if (pressedButton != lastPressedButton || now-lastPressedButtonTime > (unsigned long)RESEND_DEBOUNCE) { + if (longPress) { + send(off.set(pressedButton)); + Serial.print("Long pressed: "); + } else { + send(on.set(pressedButton)); + Serial.print("Pressed: "); + } + Serial.println(pressedButton); + lastPressedButton = pressedButton; + lastPressedButtonTime=now; + } + } + } + + // If no time has been received yet, request it every 10 second from controller + // When time has been received, request update every hour + if ((!timeReceived && now-lastRequest > (unsigned long)10*1000) + || (timeReceived && now-lastRequest > (unsigned long)60*1000*60)) { + // Request time from controller. + Serial.println("requesting time"); + requestTime(receiveTime); + lastRequest = now; + } + + // Update time every second + if (timeReceived && now-lastTimeUpdate > 1000) { + printTime(); + lastTimeUpdate = now; + } +} + + + +// This is called when a new time value was received +void receiveTime(unsigned long time) { + // Ok, set incoming time + setTime(time); + timeReceived = true; +} + +void printTime() { + sprintf(timeBuf, "%02d:%02d:%02d", hour(), minute(), second()); + myGLCD.print(timeBuf, 60,7); +} + + diff --git a/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/Ubuntu.c b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/Ubuntu.c new file mode 100644 index 0000000..4d7ce1c --- /dev/null +++ b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/Ubuntu.c @@ -0,0 +1,110 @@ +// Ubuntu.c +// Font type : Full (95 characters) +// Font size : 24x32 pixels +// Memory usage : 9124 bytes + +#include + +const uint8_t Ubuntu[9124] PROGMEM={ +0x18,0x20,0x20,0x5F, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // +0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ! +0x00,0x00,0x00,0x01,0xC0,0xE0,0x03,0xE1,0xF0,0x03,0xE1,0xF0,0x03,0xE1,0xF0,0x01,0xE0,0xF0,0x00,0xE0,0x70,0x01,0xC0,0xE0,0x03,0xC1,0xE0,0x0F,0x87,0xC0,0x0E,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x00,0x38,0x70,0x00,0x70,0xE0,0x00,0x70,0xE0,0x00,0x70,0xE0,0x00,0x70,0xE0,0x0F,0xFF,0xF8,0x0F,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0xE1,0xC0,0x00,0xE1,0xC0,0x00,0xE1,0xC0,0x01,0xC3,0x80,0x01,0xC3,0x80,0x01,0xC3,0x80,0x0F,0xFF,0xF8,0x0F,0xFF,0xF8,0x0F,0xFF,0xF8,0x03,0x87,0x00,0x03,0x87,0x00,0x03,0x87,0x00,0x03,0x87,0x00,0x07,0x0E,0x00,0x07,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // # +0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xC0,0x07,0x80,0x80,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x03,0xF8,0x00,0x01,0xFE,0x00,0x00,0x7F,0x80,0x00,0x0F,0xC0,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x02,0x01,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0x80,0x01,0xFE,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x00,0x00, // $ +0x00,0x00,0x00,0x07,0x80,0x70,0x0F,0xC0,0xE0,0x0C,0xC0,0xE0,0x18,0x61,0xC0,0x18,0x63,0x80,0x18,0x63,0x80,0x18,0x67,0x00,0x18,0x67,0x00,0x18,0x6E,0x00,0x0C,0xDC,0x00,0x0F,0xDC,0x00,0x07,0xB8,0x00,0x00,0x3B,0xC0,0x00,0x77,0xE0,0x00,0x76,0x60,0x00,0xEC,0x30,0x01,0xCC,0x30,0x01,0xCC,0x30,0x03,0x8C,0x30,0x03,0x8C,0x30,0x07,0x0C,0x30,0x0E,0x06,0x60,0x0E,0x07,0xE0,0x1C,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // % +0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0xFF,0x00,0x01,0xFF,0x00,0x03,0xC7,0x80,0x03,0x83,0x80,0x03,0x83,0x80,0x03,0x83,0x80,0x03,0x87,0x00,0x01,0xCF,0x00,0x01,0xFE,0x00,0x00,0xFC,0x00,0x01,0xF0,0x70,0x03,0xF8,0x70,0x03,0xBC,0x70,0x07,0x1E,0x60,0x0E,0x0F,0xE0,0x0E,0x07,0xE0,0x0E,0x03,0xC0,0x0E,0x01,0xC0,0x0F,0x03,0xE0,0x07,0x8F,0xE0,0x07,0xFF,0x70,0x03,0xFE,0x70,0x00,0xF8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // & +0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' +0x00,0x07,0x00,0x00,0x0F,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0x00,0x00,0x01,0x00, // ( +0x00,0x60,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x00,0x60,0x00,0x00,0x40,0x00, // ) +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x02,0x1C,0x20,0x03,0xC9,0xE0,0x07,0xFF,0xF0,0x01,0xFF,0xC0,0x00,0x1C,0x00,0x00,0x36,0x00,0x00,0x77,0x00,0x00,0xF3,0x80,0x01,0xE3,0xC0,0x00,0xE3,0x80,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // * +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00,0x0F,0x00,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x78,0x00,0x00,0x70,0x00,0x00,0x00,0x00, // , +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . +0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x07,0x00,0x00, // / + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x01,0xFF,0x00,0x03,0xFF,0x80,0x03,0xC7,0x80,0x07,0x83,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x30,0xE0,0x0E,0x78,0xE0,0x0E,0x78,0xE0,0x0E,0x78,0xE0,0x0E,0x30,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x83,0xC0,0x03,0xC7,0x80,0x03,0xFF,0x80,0x01,0xFF,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x7C,0x00,0x00,0xFC,0x00,0x03,0xFC,0x00,0x07,0x9C,0x00,0x02,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x03,0xFF,0xC0,0x03,0xFF,0xC0,0x03,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x03,0xFF,0x00,0x07,0xFF,0x80,0x07,0x87,0xC0,0x02,0x03,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2 +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFC,0x00,0x0F,0xFF,0x00,0x0F,0xFF,0x80,0x06,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x80,0x00,0x07,0xC0,0x00,0x01,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x01,0xE0,0x04,0x03,0xC0,0x0F,0xFF,0x80,0x0F,0xFF,0x00,0x03,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x0F,0x80,0x00,0x1F,0x80,0x00,0x3F,0x80,0x00,0x3B,0x80,0x00,0x73,0x80,0x00,0xF3,0x80,0x01,0xE3,0x80,0x01,0xC3,0x80,0x03,0x83,0x80,0x03,0x83,0x80,0x07,0x03,0x80,0x0F,0x03,0x80,0x0E,0x03,0x80,0x1E,0x03,0x80,0x1F,0xFF,0xF0,0x1F,0xFF,0xF0,0x1F,0xFF,0xF0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4 +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0x80,0x03,0xFF,0x80,0x03,0xFF,0x80,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xF0,0x00,0x07,0xFE,0x00,0x07,0xFF,0x00,0x00,0x1F,0x80,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x0C,0x07,0x80,0x0F,0xFF,0x00,0x0F,0xFE,0x00,0x03,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 5 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x1F,0xC0,0x00,0x7F,0xC0,0x00,0xFC,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x06,0x7E,0x00,0x0F,0xFF,0x80,0x0F,0xFF,0xC0,0x0F,0x03,0xC0,0x0E,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x07,0x00,0xE0,0x07,0x01,0xC0,0x07,0xC3,0xC0,0x03,0xFF,0x80,0x01,0xFF,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6 +0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x01,0xFF,0x00,0x03,0xFF,0x80,0x03,0xC7,0xC0,0x07,0x03,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x81,0xC0,0x03,0xC3,0x80,0x03,0xF7,0x00,0x01,0xFE,0x00,0x01,0xFF,0x80,0x03,0xCF,0xC0,0x07,0x03,0xC0,0x06,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x01,0xE0,0x07,0x83,0xC0,0x07,0xFF,0xC0,0x03,0xFF,0x80,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x01,0xFF,0x00,0x03,0xFF,0x80,0x07,0x87,0xC0,0x07,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x00,0xE0,0x07,0x81,0xE0,0x07,0xFF,0xE0,0x03,0xFF,0xE0,0x00,0xFE,0xE0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x7E,0x00,0x07,0xFC,0x00,0x07,0xF8,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x3C,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x01,0xE0,0x00,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ; +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x01,0xE0,0x00,0x0F,0xE0,0x00,0x3F,0xC0,0x00,0xFE,0x00,0x03,0xF8,0x00,0x0F,0xC0,0x00,0x0F,0x00,0x00,0x0F,0xC0,0x00,0x07,0xF8,0x00,0x00,0xFE,0x00,0x00,0x3F,0xC0,0x00,0x0F,0xE0,0x00,0x01,0xE0,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // < +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x0F,0x00,0x00,0x0F,0xE0,0x00,0x07,0xF8,0x00,0x00,0xFE,0x00,0x00,0x3F,0x80,0x00,0x07,0xE0,0x00,0x01,0xE0,0x00,0x07,0xE0,0x00,0x3F,0xC0,0x00,0xFE,0x00,0x07,0xF8,0x00,0x0F,0xE0,0x00,0x0F,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // > +0x00,0x00,0x00,0x00,0xFE,0x00,0x03,0xFF,0x80,0x03,0xFF,0xC0,0x01,0x03,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x3C,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? + +0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0xFF,0x80,0x01,0xFF,0xC0,0x01,0xE1,0xE0,0x03,0x80,0xE0,0x03,0x80,0x70,0x07,0x00,0x70,0x07,0x00,0x70,0x07,0x07,0xF0,0x0E,0x1F,0xF0,0x0E,0x3F,0xF0,0x0E,0x3C,0x70,0x0E,0x78,0x70,0x0E,0x70,0x70,0x0E,0x70,0x70,0x0E,0x70,0x70,0x0E,0x70,0x70,0x0E,0x78,0x70,0x0E,0x38,0x70,0x07,0x3F,0xF0,0x07,0x1F,0xF0,0x07,0x07,0xE0,0x07,0x80,0x00,0x03,0xC0,0x00,0x03,0xC0,0x00,0x01,0xF0,0x00,0x00,0xFF,0xC0,0x00,0x7F,0xC0,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // @ +0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0xFF,0x00,0x00,0xF7,0x00,0x00,0xE7,0x00,0x00,0xE7,0x00,0x01,0xE7,0x80,0x01,0xC3,0x80,0x01,0xC3,0x80,0x03,0xC3,0xC0,0x03,0xC1,0xC0,0x03,0x81,0xC0,0x03,0x81,0xC0,0x07,0x81,0xE0,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x0F,0x00,0xF0,0x0E,0x00,0x70,0x0E,0x00,0x70,0x0E,0x00,0x70,0x1E,0x00,0x78,0x1C,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // A +0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFC,0x00,0x0F,0xFF,0x00,0x0F,0xFF,0x80,0x0E,0x07,0xC0,0x0E,0x03,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x03,0x80,0x0E,0x07,0x80,0x0F,0xFF,0x00,0x0F,0xFF,0x00,0x0F,0xFF,0x80,0x0E,0x03,0xC0,0x0E,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x01,0xE0,0x0E,0x07,0xC0,0x0F,0xFF,0xC0,0x0F,0xFF,0x00,0x0F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // B +0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x7F,0xE0,0x01,0xFF,0xE0,0x03,0xE0,0x40,0x03,0xC0,0x00,0x07,0x80,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0F,0x00,0x00,0x07,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x03,0xE0,0x40,0x01,0xFF,0xE0,0x00,0xFF,0xE0,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // C +0x00,0x00,0x00,0x0F,0xF0,0x00,0x0F,0xFE,0x00,0x0F,0xFF,0x00,0x0E,0x0F,0x80,0x0E,0x03,0x80,0x0E,0x03,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x01,0xE0,0x0E,0x01,0xC0,0x0E,0x03,0xC0,0x0E,0x03,0x80,0x0E,0x0F,0x80,0x0F,0xFF,0x00,0x0F,0xFE,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // D +0x00,0x00,0x00,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xFF,0x80,0x07,0xFF,0x80,0x07,0xFF,0x80,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // E +0x00,0x00,0x00,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // F +0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0xFF,0xC0,0x01,0xFF,0xE0,0x03,0xE0,0xC0,0x03,0xC0,0x40,0x07,0x80,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x00,0xE0,0x07,0x00,0xE0,0x07,0x80,0xE0,0x03,0xC0,0xE0,0x03,0xE0,0xE0,0x01,0xFF,0xE0,0x00,0xFF,0xE0,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // G +0x00,0x00,0x00,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // H +0x00,0x00,0x00,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // I +0x00,0x00,0x00,0x01,0xFF,0xC0,0x01,0xFF,0xC0,0x01,0xFF,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x04,0x03,0xC0,0x07,0x07,0x80,0x0F,0xFF,0x00,0x07,0xFE,0x00,0x01,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // J +0x00,0x00,0x00,0x0E,0x01,0xE0,0x0E,0x03,0xC0,0x0E,0x03,0x80,0x0E,0x07,0x80,0x0E,0x0F,0x00,0x0E,0x0E,0x00,0x0E,0x1C,0x00,0x0E,0x3C,0x00,0x0E,0x78,0x00,0x0E,0xF0,0x00,0x0F,0xE0,0x00,0x0F,0xE0,0x00,0x0F,0xF0,0x00,0x0E,0xF8,0x00,0x0E,0x7C,0x00,0x0E,0x3E,0x00,0x0E,0x1E,0x00,0x0E,0x0F,0x00,0x0E,0x07,0x80,0x0E,0x03,0xC0,0x0E,0x03,0xC0,0x0E,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // K +0x00,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // L +0x00,0x00,0x00,0x03,0x00,0x60,0x03,0x80,0xF0,0x07,0x80,0xF0,0x07,0x80,0xF0,0x06,0xC1,0xB0,0x06,0xC1,0xB0,0x06,0xE3,0xB0,0x06,0x63,0x30,0x06,0x63,0x30,0x06,0x77,0x30,0x06,0x36,0x30,0x06,0x36,0x30,0x06,0x3E,0x30,0x06,0x1C,0x38,0x0E,0x1C,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x0E,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // M +0x00,0x00,0x00,0x07,0x80,0x70,0x07,0xC0,0x70,0x07,0xC0,0x70,0x07,0xE0,0x70,0x07,0xE0,0x70,0x07,0xF0,0x70,0x07,0x70,0x70,0x07,0x70,0x70,0x07,0x38,0x70,0x07,0x38,0x70,0x07,0x1C,0x70,0x07,0x1C,0x70,0x07,0x0E,0x70,0x07,0x0E,0x70,0x07,0x06,0x70,0x07,0x07,0x70,0x07,0x07,0x70,0x07,0x03,0xF0,0x07,0x03,0xF0,0x07,0x01,0xF0,0x07,0x01,0xF0,0x07,0x00,0xF0,0x07,0x00,0xF0,0x07,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // N +0x00,0x00,0x00,0x00,0x7C,0x00,0x01,0xFF,0x00,0x03,0xFF,0x80,0x07,0x83,0xC0,0x0F,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x1C,0x00,0xF0,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0xF0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x01,0xE0,0x07,0x83,0xC0,0x03,0xFF,0x80,0x01,0xFF,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // O + +0x00,0x00,0x00,0x07,0xFC,0x00,0x07,0xFF,0x00,0x07,0xFF,0x80,0x07,0x03,0xC0,0x07,0x01,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x01,0xE0,0x07,0x03,0xC0,0x07,0xFF,0x80,0x07,0xFF,0x00,0x07,0xFC,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P +0x00,0x00,0x00,0x00,0x7C,0x00,0x01,0xFF,0x00,0x03,0xFF,0x80,0x07,0x83,0xC0,0x0F,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x1C,0x00,0xF0,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0xF0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x01,0xE0,0x07,0x83,0xC0,0x03,0xFF,0x80,0x01,0xFF,0x00,0x00,0xFE,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0x1F,0x00,0x00,0x0F,0xE0,0x00,0x07,0xE0,0x00,0x00,0xC0,0x00,0x00,0x00, // Q +0x00,0x00,0x00,0x0F,0xF8,0x00,0x0F,0xFE,0x00,0x0F,0xFF,0x00,0x0E,0x07,0x80,0x0E,0x03,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x03,0x80,0x0E,0x07,0x80,0x0F,0xFF,0x00,0x0F,0xFE,0x00,0x0F,0xFC,0x00,0x0E,0x1E,0x00,0x0E,0x0E,0x00,0x0E,0x07,0x00,0x0E,0x07,0x00,0x0E,0x03,0x80,0x0E,0x03,0x80,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // R +0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xC0,0x03,0xC0,0x80,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x80,0x00,0x03,0xE0,0x00,0x01,0xF8,0x00,0x00,0xFE,0x00,0x00,0x3F,0x80,0x00,0x0F,0xC0,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x04,0x01,0xE0,0x0F,0x03,0xC0,0x0F,0xFF,0xC0,0x07,0xFF,0x80,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // S +0x00,0x00,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // T +0x00,0x00,0x00,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x01,0xE0,0x07,0x01,0xC0,0x07,0x83,0xC0,0x03,0xFF,0x80,0x01,0xFF,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // U +0x00,0x00,0x00,0x1C,0x00,0x70,0x1C,0x00,0x70,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x03,0x83,0x80,0x03,0x83,0x80,0x03,0x83,0x80,0x03,0x87,0x80,0x01,0xC7,0x00,0x01,0xC7,0x00,0x01,0xC7,0x00,0x00,0xEE,0x00,0x00,0xEE,0x00,0x00,0xEE,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // V +0x00,0x00,0x00,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x38,0xE0,0x0E,0x38,0xE0,0x0E,0x38,0xE0,0x0E,0x6C,0xE0,0x0E,0x6C,0xE0,0x0E,0x6C,0xE0,0x0E,0xC6,0xE0,0x0E,0xC6,0xE0,0x0E,0xC6,0xE0,0x0F,0x83,0xE0,0x0F,0x83,0xE0,0x0F,0x83,0xE0,0x0F,0x01,0xE0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // W +0x00,0x00,0x00,0x1E,0x00,0xF0,0x0E,0x00,0xE0,0x0F,0x01,0xE0,0x07,0x01,0xC0,0x03,0x83,0x80,0x03,0x83,0x80,0x01,0xC7,0x00,0x01,0xEF,0x00,0x00,0xEE,0x00,0x00,0xFE,0x00,0x00,0x7C,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0xFE,0x00,0x00,0xEE,0x00,0x01,0xC7,0x00,0x03,0xC7,0x80,0x03,0x83,0x80,0x07,0x83,0xC0,0x07,0x01,0xC0,0x0F,0x01,0xE0,0x0E,0x00,0xE0,0x1E,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // X +0x00,0x00,0x00,0x1C,0x00,0x70,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x01,0xE0,0x07,0x01,0xC0,0x07,0x83,0xC0,0x03,0x83,0x80,0x03,0xC3,0x80,0x01,0xC7,0x00,0x01,0xEF,0x00,0x00,0xEE,0x00,0x00,0xFE,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Y +0x00,0x00,0x00,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x07,0xFF,0xE0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0F,0x00,0x00,0x0E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x38,0x00,0x00,0x78,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xE0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x00,0x03,0x80,0x00,0x07,0x80,0x00,0x07,0x00,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Z +0x01,0xFF,0x00,0x01,0xFF,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xFF,0x00,0x01,0xFF,0x00, // [ +0x03,0x80,0x00,0x03,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0xE0, // +0x00,0xFF,0x80,0x00,0xFF,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0xFF,0x80,0x00,0xFF,0x80, // ] +0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0xEE,0x00,0x00,0xEE,0x00,0x01,0xC7,0x00,0x01,0xC7,0x00,0x03,0xC7,0x80,0x03,0x83,0x80,0x07,0x83,0xC0,0x07,0x01,0xC0,0x0F,0x01,0xE0,0x02,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF8,0x3F,0xFF,0xF8,0x3F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // _ + +0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0xFE,0x00,0x01,0xC7,0x00,0x01,0x83,0x00,0x01,0x83,0x00,0x01,0x83,0x00,0x01,0xC7,0x00,0x00,0xFE,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x01,0xFF,0x80,0x01,0xFF,0xC0,0x01,0x83,0xE0,0x00,0x01,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x7F,0xE0,0x01,0xFF,0xE0,0x03,0xFF,0xE0,0x07,0xC0,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x80,0xE0,0x03,0xFF,0xE0,0x01,0xFF,0xE0,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x7E,0x00,0x07,0xFF,0x00,0x07,0xFF,0x80,0x07,0x83,0xC0,0x07,0x01,0xC0,0x07,0x01,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x01,0xE0,0x07,0x01,0xC0,0x07,0x07,0xC0,0x07,0xFF,0x80,0x07,0xFF,0x00,0x03,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // b +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xE0,0x40,0x07,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x07,0x80,0x00,0x03,0xE0,0x60,0x03,0xFF,0xE0,0x00,0xFF,0xE0,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c +0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x7E,0xE0,0x00,0xFF,0xE0,0x01,0xFF,0xE0,0x03,0xC1,0xE0,0x03,0x80,0xE0,0x07,0x80,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x80,0xE0,0x03,0x80,0xE0,0x03,0xE0,0xE0,0x01,0xFF,0xE0,0x00,0xFF,0xE0,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x01,0xFF,0x00,0x03,0xFF,0x80,0x07,0xC3,0xC0,0x07,0x01,0xC0,0x07,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0E,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xC0,0xC0,0x03,0xFF,0xC0,0x01,0xFF,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e +0x00,0x0F,0xC0,0x00,0x3F,0xF0,0x00,0x7F,0xF0,0x00,0x78,0x30,0x00,0xF0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x0F,0xFF,0xC0,0x0F,0xFF,0xC0,0x0F,0xFF,0xC0,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xC0,0x07,0x81,0xC0,0x07,0x01,0xC0,0x0F,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x0E,0x01,0xC0,0x07,0x01,0xC0,0x07,0x83,0xC0,0x03,0xFF,0xC0,0x01,0xFF,0xC0,0x00,0xFD,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x06,0x07,0x80,0x07,0xFF,0x80,0x07,0xFF,0x00,0x03,0xFC,0x00,0x00,0x00,0x00, // g +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xFC,0x00,0x07,0xFF,0x00,0x07,0xFF,0x80,0x07,0x07,0x80,0x07,0x03,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // h +0x00,0x00,0x00,0x00,0x60,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x0F,0xF0,0x00,0x0F,0xF0,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x78,0x20,0x00,0x3F,0xE0,0x00,0x3F,0xE0,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // i +0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x0F,0x00,0x00,0x0F,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0x80,0x03,0xFF,0x80,0x03,0xFF,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x06,0x0F,0x00,0x0F,0xFF,0x00,0x0F,0xFE,0x00,0x03,0xF8,0x00, // j +0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x01,0xE0,0x07,0x03,0xC0,0x07,0x07,0x80,0x07,0x0F,0x00,0x07,0x1E,0x00,0x07,0x3C,0x00,0x07,0x78,0x00,0x07,0xF0,0x00,0x07,0xE0,0x00,0x07,0xF0,0x00,0x07,0x78,0x00,0x07,0x1C,0x00,0x07,0x0F,0x00,0x07,0x07,0x00,0x07,0x03,0x80,0x07,0x03,0xC0,0x07,0x01,0xE0,0x07,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // k +0x07,0xF8,0x00,0x07,0xF8,0x00,0x07,0xF8,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x3C,0x10,0x00,0x1F,0xF0,0x00,0x1F,0xF0,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // l +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE3,0xC0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0E,0x3C,0xF0,0x0E,0x1C,0x70,0x0E,0x1C,0x70,0x0E,0x1C,0x70,0x0E,0x1C,0x70,0x0E,0x1C,0x70,0x0E,0x1C,0x70,0x0E,0x1C,0x70,0x0E,0x00,0x70,0x0E,0x00,0x70,0x0E,0x00,0x70,0x0E,0x00,0x70,0x0E,0x00,0x70,0x0E,0x00,0x70,0x0E,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // m +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x03,0xFF,0x80,0x03,0xFF,0xC0,0x03,0x83,0xC0,0x03,0x81,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // n +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x01,0xFF,0x00,0x03,0xFF,0x80,0x07,0x83,0xC0,0x07,0x01,0xC0,0x0F,0x01,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x07,0x01,0xE0,0x07,0x01,0xC0,0x07,0x83,0xC0,0x03,0xFF,0x80,0x01,0xFF,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // o + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFC,0x00,0x07,0xFF,0x00,0x07,0xFF,0x80,0x07,0x07,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x01,0xE0,0x07,0x01,0xC0,0x07,0x83,0xC0,0x07,0xFF,0x80,0x07,0xFF,0x00,0x07,0x7C,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00, // p +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0xFF,0xE0,0x01,0xFF,0xE0,0x03,0xE0,0xE0,0x03,0x80,0xE0,0x03,0x80,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x80,0xE0,0x03,0x80,0xE0,0x03,0xC1,0xE0,0x01,0xFF,0xE0,0x00,0xFF,0xE0,0x00,0x3E,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0, // q +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0x80,0x80,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // r +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x01,0xFF,0x80,0x03,0xFF,0x80,0x07,0x81,0x80,0x07,0x00,0x00,0x07,0x00,0x00,0x07,0xC0,0x00,0x03,0xF0,0x00,0x01,0xFE,0x00,0x00,0x7F,0x00,0x00,0x1F,0x80,0x00,0x03,0xC0,0x00,0x01,0xC0,0x00,0x01,0xC0,0x06,0x03,0xC0,0x07,0xFF,0x80,0x07,0xFF,0x80,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // s +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xF0,0x20,0x00,0x7F,0xE0,0x00,0x7F,0xE0,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // t +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x81,0xC0,0x03,0xC1,0xC0,0x03,0xFF,0xC0,0x01,0xFF,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // u +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x70,0x1E,0x00,0xF0,0x0E,0x00,0xE0,0x0E,0x00,0xE0,0x0F,0x01,0xE0,0x07,0x01,0xC0,0x07,0x01,0xC0,0x07,0x83,0xC0,0x03,0x83,0x80,0x03,0x83,0x80,0x03,0xC7,0x00,0x01,0xC7,0x00,0x01,0xEF,0x00,0x00,0xEE,0x00,0x00,0xFE,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // v +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x10,0x70,0x0C,0x38,0xE0,0x0E,0x38,0xE0,0x0E,0x38,0xE0,0x0E,0x28,0xE0,0x0E,0x6C,0xE0,0x0E,0x6C,0xE0,0x06,0x44,0xC0,0x06,0xC6,0xC0,0x06,0xC7,0xC0,0x07,0x87,0xC0,0x07,0x83,0xC0,0x07,0x83,0x80,0x03,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // w +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x01,0xE0,0x0F,0x03,0xC0,0x07,0x03,0x80,0x03,0x87,0x80,0x03,0xCF,0x00,0x01,0xEE,0x00,0x00,0xFC,0x00,0x00,0x7C,0x00,0x00,0x78,0x00,0x00,0x7C,0x00,0x00,0xFE,0x00,0x01,0xEE,0x00,0x01,0xC7,0x00,0x03,0xC3,0x80,0x07,0x83,0xC0,0x0F,0x01,0xC0,0x0E,0x01,0xE0,0x1E,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // x +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x70,0x0F,0x00,0xF0,0x07,0x00,0xE0,0x07,0x00,0xE0,0x07,0x80,0xE0,0x03,0x81,0xE0,0x03,0x81,0xC0,0x03,0xC1,0xC0,0x01,0xC3,0xC0,0x01,0xC3,0x80,0x01,0xE3,0x80,0x00,0xE7,0x80,0x00,0xF7,0x80,0x00,0x77,0x00,0x00,0x7F,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x0F,0xF0,0x00,0x0F,0xF0,0x00,0x0F,0xC0,0x00, // y +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x00,0x03,0x80,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x00,0xE0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x03,0x80,0x00,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x07,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // z +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x0F,0x80,0x00,0x0F,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x7F,0x80,0x00,0x1F,0x80, // { +0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00, // | +0x00,0xFC,0x00,0x00,0xFF,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0xFF,0x00,0x00,0xFC,0x00, // } +0x00,0x00,0x00,0x01,0xE0,0x20,0x03,0xF0,0x30,0x07,0xFC,0x70,0x0E,0x3F,0xE0,0x0C,0x0F,0xC0,0x04,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ +}; diff --git a/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/arial_bold.c b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/arial_bold.c new file mode 100644 index 0000000..e8107e9 --- /dev/null +++ b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/arial_bold.c @@ -0,0 +1,111 @@ +// arial_bold.c +// Font type : Full (95 characters) +// Font size : 16x16 pixels +// Memory usage : 3044 bytes +// Submitted by : MBWK + +#include + +const uint8_t arial_bold[3044] PROGMEM={ +0x10,0x10,0x20,0x5F, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // +0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00, // ! +0x00,0x00,0x00,0x00,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " +0x00,0x00,0x00,0x00,0x03,0x60,0x03,0x60,0x06,0xC0,0x3F,0xF0,0x3F,0xF0,0x06,0xC0,0x0D,0x80,0x3F,0xF0,0x3F,0xF0,0x0D,0x80,0x1B,0x00,0x1B,0x00,0x00,0x00,0x00,0x00, // # +0x00,0x00,0x01,0x00,0x03,0x80,0x07,0xC0,0x0D,0x60,0x0D,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x0D,0x60,0x0D,0x60,0x07,0xC0,0x03,0x80,0x01,0x00,0x00,0x00, // $ +0x00,0x00,0x00,0x00,0x3C,0x18,0x66,0x30,0x66,0x30,0x66,0x60,0x66,0xC0,0x3C,0xC0,0x01,0x9E,0x01,0xB3,0x03,0x33,0x03,0x33,0x06,0x33,0x0C,0x1E,0x00,0x00,0x00,0x00, // % +0x00,0x00,0x00,0x00,0x07,0xC0,0x0F,0xE0,0x0C,0x60,0x0C,0x60,0x07,0xC0,0x07,0x80,0x0D,0x90,0x19,0xD8,0x18,0xF0,0x18,0x78,0x0F,0xFC,0x07,0x88,0x00,0x00,0x00,0x00, // & +0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' +0x00,0x00,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x00,0x00,0x00,0x00, // ( +0x00,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x00,0x00,0x00,0x00, // ) +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x33,0x98,0x3F,0xF8,0x07,0xC0,0x07,0xC0,0x0E,0xE0,0x1C,0x70,0x04,0x40,0x00,0x00,0x00,0x00,0x00,0x00, // * +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x07,0xF8,0x07,0xF8,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x00,0x00, // , +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x03,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . +0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00, // / + +0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0E,0x70,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0E,0x70,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00, // 0 +0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x80,0x07,0x80,0x0D,0x80,0x09,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00, // 1 +0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0E,0x30,0x0C,0x30,0x00,0x30,0x00,0x60,0x00,0xE0,0x01,0xC0,0x03,0x80,0x06,0x00,0x0F,0xF0,0x0F,0xF0,0x00,0x00,0x00,0x00, // 2 +0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0xF0,0x0E,0x30,0x00,0x30,0x01,0xE0,0x01,0xE0,0x00,0x70,0x00,0x30,0x0C,0x30,0x0E,0x70,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00, // 3 +0x00,0x00,0x00,0x00,0x00,0x60,0x00,0xE0,0x00,0xE0,0x01,0xE0,0x03,0x60,0x03,0x60,0x06,0x60,0x0C,0x60,0x0F,0xF0,0x0F,0xF0,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00, // 4 +0x00,0x00,0x00,0x00,0x07,0xE0,0x07,0xE0,0x06,0x00,0x0C,0x00,0x0F,0xC0,0x0F,0xE0,0x0C,0x70,0x00,0x30,0x0C,0x30,0x0E,0x70,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00, // 5 +0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0xF0,0x06,0x30,0x0C,0x00,0x0D,0xC0,0x0F,0xE0,0x0E,0x70,0x0C,0x30,0x0C,0x30,0x06,0x30,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00, // 6 +0x00,0x00,0x00,0x00,0x0F,0xF0,0x0F,0xF0,0x00,0x60,0x00,0xC0,0x00,0xC0,0x01,0x80,0x01,0x80,0x01,0x80,0x03,0x80,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00, // 7 +0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x07,0xE0,0x07,0xE0,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00, // 8 +0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0C,0x60,0x0C,0x30,0x0C,0x30,0x0E,0x70,0x07,0xF0,0x03,0xB0,0x00,0x30,0x0C,0x60,0x0F,0xE0,0x07,0xC0,0x00,0x00,0x00,0x00, // 9 +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x80,0x00,0x80,0x01,0x00,0x00,0x00, // ; +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xE0,0x03,0xC0,0x0F,0x00,0x1C,0x00,0x0F,0x00,0x03,0xC0,0x00,0xE0,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00, // < +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF0,0x1F,0xF0,0x00,0x00,0x00,0x00,0x1F,0xF0,0x1F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x80,0x01,0xE0,0x00,0x70,0x01,0xE0,0x07,0x80,0x0E,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // > +0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0E,0x30,0x0C,0x30,0x00,0x70,0x00,0xE0,0x01,0xC0,0x01,0x80,0x01,0x80,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00, // ? + +0x00,0x00,0x07,0xC0,0x0C,0x30,0x13,0x78,0x17,0xE8,0x2C,0xC8,0x2C,0xC8,0x2C,0xC8,0x2F,0xD0,0x26,0xE0,0x10,0x08,0x08,0x10,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, // @ +0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x06,0xC0,0x06,0xC0,0x06,0xC0,0x0C,0x60,0x0C,0x60,0x0F,0xE0,0x1F,0xF0,0x18,0x30,0x18,0x30,0x30,0x18,0x00,0x00,0x00,0x00, // A +0x00,0x00,0x00,0x00,0x1F,0xE0,0x1F,0xF0,0x18,0x30,0x18,0x30,0x18,0x30,0x1F,0xE0,0x1F,0xF0,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0xF0,0x1F,0xE0,0x00,0x00,0x00,0x00, // B +0x00,0x00,0x00,0x00,0x03,0xE0,0x0F,0xF0,0x0C,0x38,0x1C,0x10,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x1C,0x10,0x0C,0x38,0x0F,0xF0,0x03,0xE0,0x00,0x00,0x00,0x00, // C +0x00,0x00,0x00,0x00,0x1F,0xC0,0x1F,0xF0,0x18,0x30,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x30,0x1F,0xF0,0x1F,0xC0,0x00,0x00,0x00,0x00, // D +0x00,0x00,0x00,0x00,0x0F,0xF8,0x0F,0xF8,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0F,0xF8,0x0F,0xF8,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0F,0xF8,0x0F,0xF8,0x00,0x00,0x00,0x00, // E +0x00,0x00,0x00,0x00,0x0F,0xF0,0x0F,0xF0,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0F,0xE0,0x0F,0xE0,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00, // F +0x00,0x00,0x00,0x00,0x07,0xE0,0x1F,0xF0,0x18,0x38,0x38,0x10,0x30,0x00,0x30,0x00,0x30,0xF8,0x30,0xF8,0x38,0x18,0x18,0x38,0x1F,0xF8,0x07,0xE0,0x00,0x00,0x00,0x00, // G +0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0xF8,0x1F,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // H +0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00, // I +0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x0C,0x30,0x0E,0x70,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00, // J +0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x18,0x60,0x18,0xC0,0x19,0x80,0x1B,0xC0,0x1E,0xC0,0x1C,0x60,0x18,0x70,0x18,0x30,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // K +0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0F,0xF0,0x0F,0xF0,0x00,0x00,0x00,0x00, // L +0x00,0x00,0x00,0x00,0x38,0x38,0x38,0x38,0x3C,0x78,0x3C,0x78,0x34,0x58,0x36,0xD8,0x36,0xD8,0x36,0xD8,0x33,0x98,0x33,0x98,0x33,0x98,0x31,0x18,0x00,0x00,0x00,0x00, // M +0x00,0x00,0x00,0x00,0x18,0x18,0x1C,0x18,0x1E,0x18,0x1E,0x18,0x1B,0x18,0x19,0x98,0x19,0x98,0x18,0xD8,0x18,0x78,0x18,0x78,0x18,0x38,0x18,0x18,0x00,0x00,0x00,0x00, // N +0x00,0x00,0x00,0x00,0x07,0xC0,0x1F,0xF0,0x18,0x30,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x18,0x30,0x1F,0xF0,0x07,0xC0,0x00,0x00,0x00,0x00, // O + +0x00,0x00,0x00,0x00,0x0F,0xE0,0x0F,0xF0,0x0C,0x38,0x0C,0x18,0x0C,0x38,0x0F,0xF0,0x0F,0xE0,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00, // P +0x00,0x00,0x00,0x00,0x07,0xC0,0x1F,0xF0,0x18,0x30,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x31,0xB8,0x18,0xF0,0x1F,0xF0,0x07,0xB0,0x00,0x18,0x00,0x00, // Q +0x00,0x00,0x00,0x00,0x1F,0xE0,0x1F,0xF0,0x18,0x38,0x18,0x18,0x18,0x38,0x1F,0xF0,0x1F,0xC0,0x18,0xE0,0x18,0x70,0x18,0x30,0x18,0x38,0x18,0x1C,0x00,0x00,0x00,0x00, // R +0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0xF0,0x0E,0x38,0x0C,0x18,0x0F,0x00,0x07,0xE0,0x01,0xF0,0x00,0x38,0x0C,0x18,0x0E,0x38,0x07,0xF0,0x03,0xE0,0x00,0x00,0x00,0x00, // S +0x00,0x00,0x00,0x00,0x1F,0xF8,0x1F,0xF8,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00, // T +0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x38,0x0F,0xF0,0x07,0xE0,0x00,0x00,0x00,0x00, // U +0x00,0x00,0x00,0x00,0x30,0x18,0x18,0x30,0x18,0x30,0x18,0x30,0x0C,0x60,0x0C,0x60,0x0E,0xE0,0x06,0xC0,0x06,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00, // V +0x00,0x00,0x00,0x00,0x31,0xC6,0x31,0xC6,0x31,0xC6,0x1B,0x6C,0x1B,0x6C,0x1B,0x6C,0x1B,0x6C,0x1B,0x6C,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x00,0x00,0x00,0x00, // W +0x00,0x00,0x00,0x00,0x18,0x30,0x1C,0x70,0x0C,0x60,0x06,0xC0,0x07,0xC0,0x03,0x80,0x03,0x80,0x07,0xC0,0x06,0xC0,0x0C,0x60,0x1C,0x70,0x18,0x30,0x00,0x00,0x00,0x00, // X +0x00,0x00,0x00,0x00,0x18,0x18,0x1C,0x38,0x0C,0x30,0x06,0x60,0x06,0x60,0x03,0xC0,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00, // Y +0x00,0x00,0x00,0x00,0x07,0xF8,0x07,0xF8,0x00,0x30,0x00,0x60,0x00,0xE0,0x00,0xC0,0x01,0x80,0x03,0x80,0x03,0x00,0x06,0x00,0x0F,0xF8,0x0F,0xF8,0x00,0x00,0x00,0x00, // Z +0x00,0x00,0x03,0xC0,0x03,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0xC0,0x03,0xC0,0x00,0x00, // [ +0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00, // +0x00,0x00,0x03,0xC0,0x03,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x03,0xC0,0x03,0xC0,0x00,0x00, // ] +0x00,0x00,0x01,0x80,0x03,0xC0,0x03,0xC0,0x06,0x60,0x06,0x60,0x06,0x60,0x0C,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00, // _ + +0x00,0x00,0x00,0x00,0x01,0x80,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x0F,0xE0,0x0C,0x60,0x01,0xE0,0x07,0xE0,0x0E,0x60,0x0C,0x60,0x0F,0xE0,0x07,0xB0,0x00,0x00,0x00,0x00,0x00,0x00, // a +0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0D,0xC0,0x0F,0xE0,0x0E,0x70,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0E,0x70,0x0F,0xE0,0x0D,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // b +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0E,0x60,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0E,0x60,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // c +0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x03,0xB0,0x07,0xF0,0x0E,0x70,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0E,0x70,0x07,0xF0,0x03,0xB0,0x00,0x00,0x00,0x00,0x00,0x00, // d +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x07,0xC0,0x0C,0x60,0x0F,0xE0,0x0F,0xE0,0x0C,0x00,0x0E,0x60,0x07,0xC0,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // e +0x00,0x00,0x03,0xC0,0x07,0xC0,0x06,0x00,0x0F,0x80,0x0F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f +0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x60,0x0F,0xE0,0x1C,0xE0,0x18,0x60,0x18,0x60,0x18,0x60,0x1C,0xE0,0x0F,0xE0,0x07,0x60,0x18,0x60,0x1F,0xE0,0x0F,0xC0,0x00,0x00, // g +0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0D,0xE0,0x0F,0xF0,0x0E,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // h +0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // i +0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x07,0x80,0x07,0x00, // j +0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x60,0x0C,0xC0,0x0D,0x80,0x0F,0x80,0x0F,0xC0,0x0E,0xC0,0x0C,0xC0,0x0C,0x60,0x0C,0x60,0x00,0x00,0x00,0x00,0x00,0x00, // k +0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // l +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x38,0x3F,0xFC,0x39,0xCC,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x00,0x00,0x00,0x00,0x00,0x00, // m +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0xE0,0x0F,0xF0,0x0E,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // n +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0E,0x70,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0E,0x70,0x07,0xE0,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // o + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0xC0,0x0F,0xE0,0x0E,0x70,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0E,0x70,0x0F,0xE0,0x0D,0xC0,0x0C,0x00,0x0C,0x00,0x0C,0x00, // p +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xB0,0x07,0xF0,0x0E,0x70,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0E,0x70,0x07,0xF0,0x03,0xB0,0x00,0x30,0x00,0x30,0x00,0x30, // q +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x70,0x03,0xF0,0x03,0x80,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // r +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x0F,0xE0,0x0C,0x60,0x0F,0x00,0x07,0xC0,0x00,0xE0,0x0C,0x60,0x0F,0xE0,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // s +0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x07,0xC0,0x07,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // t +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x70,0x0F,0xF0,0x07,0xB0,0x00,0x00,0x00,0x00,0x00,0x00, // u +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x30,0x06,0x30,0x06,0x30,0x03,0x60,0x03,0x60,0x03,0x60,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // v +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0xC6,0x31,0xC6,0x19,0xCC,0x1B,0x6C,0x1B,0x6C,0x1B,0x6C,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x00,0x00,0x00,0x00,0x00,0x00, // w +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x30,0x07,0x70,0x03,0x60,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x03,0x60,0x07,0x70,0x06,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // x +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x18,0x0C,0x18,0x06,0x30,0x06,0x30,0x03,0x60,0x03,0x60,0x03,0xE0,0x01,0xC0,0x01,0xC0,0x01,0x80,0x07,0x80,0x07,0x00, // y +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF8,0x03,0xF8,0x00,0x30,0x00,0x70,0x00,0xE0,0x01,0xC0,0x01,0x80,0x03,0xF8,0x03,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, // z +0x01,0xC0,0x03,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x0E,0x00,0x0E,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0xC0,0x01,0xC0,0x00,0x00, // { +0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80, // | +0x03,0x80,0x03,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x70,0x00,0x70,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x03,0xC0,0x03,0x80,0x00,0x00, // } +0x00,0x00,0x00,0x00,0x07,0x88,0x0F,0xF8,0x08,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ +}; diff --git a/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/logo.c b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/logo.c new file mode 100644 index 0000000..116321b --- /dev/null +++ b/libraries/MySensors/examples/TouchDisplaySceneControllerSensor/logo.c @@ -0,0 +1,235 @@ +// Generated by : ImageConverter 565 Online +// Generated from : top.png +// Time generated : Tue, 30 Sep 14 23:16:51 +0200 (Server timezone: CET) +// Image Size : 60x60 pixels +// Memory usage : 7200 bytes + +#include + +const unsigned short logo[3600] PROGMEM={ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0010 (16) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0020 (32) pixels +0x08E4, 0x28A3, 0x89A7, 0x71C7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0030 (48) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0040 (64) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0050 (80) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xAD55, 0x18C3, 0x0082, 0x4944, 0x5A08, 0x8147, 0xBB0D, 0x5A69, // 0x0060 (96) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0070 (112) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0080 (128) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52A0, 0x3180, 0x0000, 0x52AA, 0x2945, // 0x0090 (144) pixels +0x2965, 0x0000, 0x0000, 0x0000, 0x18E3, 0x0021, 0x4144, 0x69C6, 0x6924, 0xAA49, 0xB3AD, 0x00E2, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00A0 (160) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00B0 (176) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00C0 (192) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, 0x0861, 0x2924, 0x0000, 0x0000, 0x00C2, // 0x00D0 (208) pixels +0x1862, 0x4924, 0x4924, 0x9965, 0xCB4A, 0xE48D, 0x9329, 0x0004, 0x6A69, 0x51A5, 0x2125, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, // 0x00E0 (224) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00F0 (240) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0100 (256) pixels +0x0000, 0x1002, 0x1924, 0x41A4, 0x3124, 0x0000, 0x0000, 0x4A69, 0x2924, 0x0000, 0x0000, 0x4125, 0x38E4, 0x5983, 0x9A46, 0xE40A, // 0x0110 (272) pixels +0xFCCD, 0xF4CE, 0x50E5, 0x6226, 0xBBAC, 0xAAEB, 0x4904, 0x0000, 0x4104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0120 (288) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0130 (304) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2124, 0x10C3, 0x0000, 0x0000, 0x2800, 0x41A5, 0x9309, // 0x0140 (320) pixels +0x8288, 0x00E5, 0x4A49, 0x73AE, 0x31A6, 0x1800, 0x59C7, 0x71E7, 0x2100, 0x8266, 0xE40B, 0xFCAC, 0xFC8C, 0xDC8F, 0x5187, 0xA387, // 0x0150 (336) pixels +0xABA9, 0x9249, 0x58C0, 0x0000, 0x0000, 0x8410, 0x2104, 0x10A2, 0x2965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0160 (352) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0170 (368) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0944, 0x2062, 0x5165, 0x5903, 0x00A4, 0x0165, 0x8A67, 0xAB28, 0x7267, 0x29E8, 0x7B0C, // 0x0180 (384) pixels +0x6185, 0x8207, 0xC3AC, 0x6A04, 0x0140, 0xC36A, 0xFDEC, 0xF5AC, 0xFD30, 0xCC51, 0x70C5, 0xC469, 0xEC8D, 0x89E9, 0x0000, 0x5269, // 0x0190 (400) pixels +0x20C3, 0x0861, 0x0841, 0x18A2, 0x39E7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01A0 (416) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01B0 (432) pixels +0x5000, 0x0000, 0x71A5, 0x9A88, 0xAAA8, 0xC2C9, 0xA248, 0x9A26, 0xCA87, 0xCAC8, 0x58C0, 0x69C5, 0xC30B, 0xD3AC, 0xDC4A, 0x51A2, // 0x01C0 (448) pixels +0x5A65, 0xEC6B, 0xFDCB, 0xFE0E, 0xFD0F, 0xEBF1, 0xB3EB, 0xED6E, 0xEC10, 0x61C7, 0x0123, 0x0021, 0x0082, 0x10C3, 0x3186, 0x0000, // 0x01D0 (464) pixels +0x0000, 0x6180, 0x5000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01E0 (480) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF800, 0x0000, 0xFFF0, 0x5943, // 0x01F0 (496) pixels +0xA226, 0xD369, 0xEB4A, 0xE289, 0xE26A, 0xEB0E, 0x9AAA, 0x5042, 0xDBAC, 0xEC8C, 0xDC29, 0x7A45, 0xCC4A, 0xFB4C, 0xFD8D, 0xFDF0, // 0x0200 (512) pixels +0xF510, 0xFD8F, 0xF5CF, 0xFE31, 0xCC31, 0x0000, 0x3801, 0x4143, 0x59A6, 0x4165, 0x0082, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0210 (528) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0220 (544) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0041, 0x9986, 0xC2E8, 0xDB88, 0xF44A, // 0x0230 (560) pixels +0xDBCB, 0xEBCD, 0xD44D, 0x41C5, 0xB308, 0xEC0B, 0xF46C, 0xE40D, 0xD38A, 0xEC2D, 0xFEAE, 0xFEF2, 0xFDD2, 0xFE51, 0xFD52, 0xFCB1, // 0x0240 (576) pixels +0xEC50, 0xCBEE, 0xB42A, 0xA2C6, 0x8985, 0x79A6, 0x89A6, 0xB1E6, 0xA1C6, 0x5924, 0x4986, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0250 (592) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0260 (608) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0040, 0x6125, 0xE3A9, 0xF4EB, 0xF5AC, 0xDD49, 0xE5CB, 0xFE6E, 0xC44E, // 0x0270 (624) pixels +0x9B8A, 0xE4CD, 0xFD70, 0xFDB1, 0xCCCE, 0xF62E, 0xFE8D, 0xFE50, 0xFE56, 0xFD97, 0xF4B6, 0xF3F0, 0xFD2F, 0xFE50, 0xF5D1, 0xDC10, // 0x0280 (640) pixels +0xB289, 0xC269, 0xCA68, 0xEB6C, 0xDC2F, 0xA2C9, 0x2062, 0x1945, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0290 (656) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x02A0 (672) pixels +0x0000, 0x0000, 0x0000, 0x00E3, 0x3904, 0xB1C6, 0xE34C, 0xEC2C, 0xE4AB, 0xCD2B, 0xF64C, 0xFE70, 0xFE4F, 0xEE4E, 0xFED2, 0xFED2, // 0x02B0 (688) pixels +0xFEB2, 0xFE33, 0xFDD3, 0xFE74, 0xF535, 0xCB11, 0xEB32, 0xFCF2, 0xFDF1, 0xF574, 0xFE13, 0xFE52, 0xBC4B, 0x8226, 0x6945, 0x6A28, // 0x02C0 (704) pixels +0x3228, 0x2124, 0x1904, 0x51C7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x02D0 (720) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x10A2, // 0x02E0 (736) pixels +0x0861, 0x91C5, 0xDA4A, 0xEAAB, 0xF3D1, 0xED12, 0xD591, 0xC50D, 0xA3E9, 0xB50C, 0xEE92, 0xB4EE, 0x7329, 0x82E8, 0xC572, 0xEDF3, // 0x02F0 (752) pixels +0xB3ED, 0x3800, 0xA3CF, 0xFEF6, 0xFED0, 0xFEB4, 0xFEF3, 0xF6CF, 0xEEAE, 0xBD2A, 0x0120, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0300 (768) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0310 (784) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1001, 0x39C7, 0x8227, 0xE2AA, 0xDB0C, // 0x0320 (800) pixels +0xE4B3, 0xCD11, 0x83EA, 0x5286, 0x52AA, 0x7BEF, 0x2940, 0x3A2A, 0x5AEB, 0x73CF, 0x52AA, 0x3945, 0x1184, 0x6B2B, 0xACF1, 0xB54F, // 0x0330 (816) pixels +0xF733, 0xFF51, 0xFF32, 0xFF55, 0xFF33, 0xF696, 0xCC93, 0x624A, 0x0120, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0340 (832) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0350 (848) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6248, 0x9249, 0xCB2A, 0xABEC, 0x8C2B, 0x5AE6, 0x10C3, 0x5269, // 0x0360 (864) pixels +0xA4F3, 0xD637, 0x9C90, 0xAD33, 0xAD12, 0xE6FA, 0xC5B5, 0x6AC9, 0x83CE, 0xBD53, 0xCDD5, 0x9450, 0x6B47, 0xCD91, 0xFEB4, 0xEED4, // 0x0370 (880) pixels +0x9490, 0x736E, 0xCCD5, 0xCC94, 0x7B2D, 0x0000, 0xFC10, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0380 (896) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0390 (912) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x6A8A, 0x8B0A, 0x9C2B, 0x7BCA, 0x3163, 0x526B, 0x1904, 0x736C, 0xE698, 0xD658, 0xD658, 0xD616, // 0x03A0 (928) pixels +0xF719, 0xFF5B, 0xF71A, 0xEED8, 0xD5F5, 0xEEFA, 0xE6B8, 0xA4F3, 0x29A8, 0x0000, 0xAC31, 0xEE36, 0x9C2E, 0x0000, 0x4145, 0xAB70, // 0x03B0 (944) pixels +0xC4B4, 0x93F0, 0x0000, 0x0000, 0x4008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x03C0 (960) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x03D0 (976) pixels +0x8B6B, 0x7B6A, 0x1124, 0x0000, 0x0000, 0x41E6, 0x0002, 0xB512, 0xFF7B, 0xFF9C, 0xFF9C, 0xFFDD, 0xFF9C, 0xFFBD, 0xFFFF, 0xFF9C, // 0x03E0 (992) pixels +0xFF5B, 0xFFBD, 0xFF9C, 0xF71A, 0x9CB1, 0x0000, 0x0000, 0xACB2, 0xE6B6, 0x4A68, 0x0000, 0x0144, 0x738E, 0x6B4D, 0x0000, 0x0000, // 0x03F0 (1008) pixels +0x500A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0400 (1024) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2145, 0x3144, 0x0002, 0x0000, 0x0000, // 0x0410 (1040) pixels +0x0000, 0x39C7, 0x0083, 0xC594, 0xEED9, 0xEEB8, 0xEEFA, 0xC5F7, 0xEEFA, 0xFFDD, 0xDEFB, 0xA4F2, 0xEE97, 0xF6D8, 0xEEF9, 0xFF7B, // 0x0420 (1056) pixels +0xDE56, 0x41C6, 0x0000, 0x0000, 0x9491, 0x7BCE, 0x0000, 0x6209, 0x0000, 0x0000, 0x6A49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0430 (1072) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0440 (1088) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2965, 0x0000, 0xAD12, // 0x0450 (1104) pixels +0xCE17, 0x534E, 0x02B0, 0x7472, 0xF73A, 0xFF7B, 0xF71A, 0xA4F2, 0x02AE, 0x4B6F, 0x9C91, 0xFF5B, 0xF6D9, 0x838C, 0x0000, 0x0000, // 0x0460 (1120) pixels +0x0000, 0x0001, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0470 (1136) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0480 (1152) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x8400, 0x5000, 0x8410, 0x0000, 0xB4D3, 0x2965, 0x3985, 0xA4D1, 0xFFDF, 0xCEDC, 0x4413, 0xDEFA, // 0x0490 (1168) pixels +0xFF9C, 0xEED9, 0xFF5A, 0xFF5A, 0x8D36, 0xBE59, 0xFFDE, 0xFF7B, 0xFF19, 0x8BEE, 0x0000, 0x0000, 0x0000, 0x632C, 0x0005, 0x0000, // 0x04A0 (1184) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x04B0 (1200) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x04C0 (1216) pixels +0x0000, 0x0000, 0x8410, 0x0000, 0x7BCF, 0x2966, 0x5247, 0xBD95, 0xFFDE, 0xFF9C, 0xF73A, 0xFF7B, 0xF719, 0xCE17, 0xF75C, 0xFFDE, // 0x04D0 (1232) pixels +0xFF7C, 0xFF5A, 0xFFDE, 0xFF3A, 0xFF5A, 0xACF1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x04E0 (1248) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x04F0 (1264) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0x0000, // 0x0500 (1280) pixels +0x8C51, 0x2966, 0x62A9, 0x9CB2, 0xE6B9, 0xEEB8, 0xFF5B, 0xFF9C, 0xEEB8, 0xD637, 0xFF9C, 0xFFBD, 0xFF7B, 0xFF5B, 0xFF5B, 0xFF19, // 0x0510 (1296) pixels +0xFF5A, 0xC574, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0520 (1312) pixels +0x0000, 0x0000, 0x5000, 0x52AA, 0x8000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0530 (1328) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0x0000, 0xACF3, 0x3186, 0x5AA9, 0x940E, // 0x0540 (1344) pixels +0x9C90, 0xD616, 0xEEF9, 0xFF7B, 0xDE78, 0xB533, 0xE697, 0xFF39, 0xFF5A, 0xFF5B, 0xFF3A, 0xFF5B, 0xFF5A, 0xC593, 0x0000, 0x0000, // 0x0550 (1360) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0560 (1376) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0570 (1392) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2125, 0x5248, 0xA490, 0xC5B5, 0xEED9, 0xF73A, 0xF71A, // 0x0580 (1408) pixels +0xACF2, 0xBD74, 0xB533, 0xF71A, 0xFF9C, 0xFF3B, 0xFF7C, 0xFF9C, 0xFF9C, 0xB512, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0590 (1424) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x05A0 (1440) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x05B0 (1456) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2125, 0x41E7, 0xA4B1, 0xBD95, 0xE698, 0xF71A, 0xFF7B, 0xEEB8, 0xFF3A, 0xF6F9, 0xFFBD, // 0x05C0 (1472) pixels +0xEEB9, 0xAC2F, 0xE71B, 0xFFBD, 0xFF9C, 0xB532, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x05D0 (1488) pixels +0x0000, 0x0000, 0x0000, 0x4208, 0x2965, 0x5248, 0xB512, 0xE676, 0xA46F, 0x0000, 0xFFF0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x05E0 (1504) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x05F0 (1520) pixels +0x0000, 0x4208, 0x0000, 0xA490, 0xFF7C, 0xAD54, 0x91E6, 0xFF3B, 0xFFBC, 0xFF5A, 0xFF7B, 0xFFDD, 0xDC90, 0xB450, 0xF75B, 0xFF3A, // 0x0600 (1536) pixels +0xFF9B, 0xA4D1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0610 (1552) pixels +0x4A28, 0xC573, 0xFF7B, 0xFF5A, 0x7B4B, 0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0x0000, 0x0000, // 0x0620 (1568) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4208, 0x0000, 0x52AA, 0x1904, 0x62C9, // 0x0630 (1584) pixels +0xFF5B, 0xE6BA, 0x5800, 0xDC0E, 0xFF1B, 0xFF7B, 0xFFBD, 0xF617, 0xB940, 0xD617, 0xFF5A, 0xFF19, 0xFF7B, 0x7B6C, 0x0000, 0x0000, // 0x0640 (1600) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5000, 0x0000, 0x08C4, 0x6B0A, 0x942F, 0xF6F9, 0xFF7A, 0xC574, // 0x0650 (1616) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0660 (1632) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0x0000, 0x738E, 0x4A49, 0x08A3, 0xCDB4, 0xFF7B, 0x9CB1, 0x9000, // 0x0670 (1648) pixels +0xC267, 0xA3AD, 0xB34C, 0xA8E0, 0xBD14, 0xF71A, 0xFF39, 0xFF9B, 0xE698, 0x0000, 0x0000, 0x52AA, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0680 (1664) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x4200, 0x0000, 0x1904, 0x6AEA, 0x83AC, 0xC573, 0x8BEE, 0x0000, 0x52AA, 0x0000, 0x0000, 0x0000, // 0x0690 (1680) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x4229, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x06A0 (1696) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x4208, 0x0000, 0x5AAA, 0x2146, 0x83CD, 0xFF19, 0xFF19, 0xBD53, 0x9BEE, 0x9BAD, 0xACD3, 0xC658, // 0x06B0 (1712) pixels +0xF73B, 0xFF5A, 0xFF5A, 0xF73A, 0x630C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x06C0 (1728) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00A7, // 0x06D0 (1744) pixels +0x4A28, 0x4A48, 0x428B, 0x0000, 0x4208, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x06E0 (1760) pixels +0x0000, 0x0000, 0x0000, 0x4228, 0x3186, 0xCDF6, 0xFF7B, 0xFF7B, 0xF71A, 0xF73A, 0xFF9C, 0xFF7C, 0xFF3A, 0xFF3A, 0xFF9C, 0x9471, // 0x06F0 (1776) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, // 0x0700 (1792) pixels +0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4208, 0x0000, 0x0000, 0xACD1, 0xE677, 0x836C, 0x0000, // 0x0710 (1808) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0x0000, 0x8C51, // 0x0720 (1824) pixels +0x2945, 0x39C6, 0x9C90, 0xE6B9, 0xFF9C, 0xFF5A, 0xFF19, 0xFF3A, 0xFF7B, 0xFFDD, 0xB5B6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0730 (1840) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x39C7, 0x18C3, 0x3186, 0x0000, 0x0000, 0x0000, // 0x0740 (1856) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFF0, 0x10E4, 0xB512, 0xFF9B, 0xE6B8, 0x0002, 0x0000, 0x8410, 0x0000, 0x0000, // 0x0750 (1872) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0180, 0x0000, 0x52AA, 0x10E3, 0x0000, 0x83AD, // 0x0760 (1888) pixels +0xE698, 0xFF19, 0xFF39, 0xEED8, 0xD658, 0x9492, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0770 (1904) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0x18E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0780 (1920) pixels +0x0000, 0x0000, 0xAD55, 0x2145, 0x9C4F, 0xBD32, 0x9450, 0x31A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0790 (1936) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0x0000, 0x0000, 0x8C31, 0xB576, 0x41E7, 0x5AA9, 0x5A68, 0x8C0F, 0x8C0F, 0x5ACA, // 0x07A0 (1952) pixels +0x4A6A, 0xB532, 0x8BCD, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x07B0 (1968) pixels +0x0000, 0x0000, 0x18C3, 0x2945, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2965, // 0x07C0 (1984) pixels +0x18C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x07D0 (2000) pixels +0x0000, 0x52AA, 0x0000, 0x1003, 0xCE1A, 0xEF1D, 0x62EC, 0x7B8C, 0xA4B1, 0x9C70, 0xB512, 0xB532, 0xD616, 0xF6D8, 0x6B0B, 0x0000, // 0x07E0 (2016) pixels +0x3165, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0x18E3, 0x0000, // 0x07F0 (2032) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xA451, 0x2945, 0x18E3, // 0x0800 (2048) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9E73, 0x0000, // 0x0810 (2064) pixels +0x9493, 0xF77E, 0xCE39, 0x4A48, 0xCDF6, 0xC5B5, 0xEED9, 0xE6B8, 0xFF3A, 0x942F, 0x73AE, 0x8430, 0x39C7, 0x0000, 0x0000, 0x0000, // 0x0820 (2080) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2124, 0x18E3, 0x8410, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0830 (2096) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0x18E3, 0x18E3, 0x4A69, 0x0000, 0x0000, // 0x0840 (2112) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0x0000, 0x4268, 0x5A8C, 0x0003, 0xB557, 0xFFDF, 0xA555, // 0x0850 (2128) pixels +0xA4B1, 0xDE57, 0xEEB8, 0xFFBC, 0xB554, 0xA534, 0xB595, 0xB576, 0x7BD0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0860 (2144) pixels +0x0000, 0x0000, 0x4208, 0x18C3, 0x18E3, 0x31A6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0870 (2160) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0x0000, 0x0000, 0x2124, 0x18C3, 0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0880 (2176) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x4208, 0x0000, 0x4A68, 0x526B, 0x7B50, 0x62AD, 0xDEBC, 0xFFFF, 0x8430, 0xB554, 0xFF7B, 0xE6B9, // 0x0890 (2192) pixels +0x636E, 0xF7BE, 0x8C71, 0xDE9B, 0xCE1A, 0x1063, 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x39E7, 0x18E3, 0x18E3, 0x2104, // 0x08A0 (2208) pixels +0x8410, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x08B0 (2224) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3186, 0x18C3, 0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x08C0 (2240) pixels +0x4208, 0x0000, 0x4A49, 0x4A0A, 0xACF7, 0x7B70, 0xA514, 0xFFFF, 0xF79E, 0x9491, 0xE6B8, 0x83EF, 0xDEDB, 0xE71C, 0x8410, 0xFFFF, // 0x08D0 (2256) pixels +0xF77E, 0xA4D5, 0x0000, 0x0000, 0x0000, 0x0000, 0x3186, 0x2104, 0x18E3, 0x18E3, 0x39C7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x08E0 (2272) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x08F0 (2288) pixels +0x0000, 0x0000, 0x0000, 0x18C3, 0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x31C6, 0x734E, // 0x0900 (2304) pixels +0xB537, 0xACB6, 0x5AAB, 0xE71C, 0xFFFF, 0xCE59, 0x0000, 0x9CD3, 0xFFFF, 0xA535, 0xBDF7, 0xFFFF, 0xF79E, 0xE6DD, 0xC5D8, 0x4228, // 0x0910 (2320) pixels +0x0000, 0x3186, 0x18E3, 0x2104, 0x4208, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0920 (2336) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4A49, // 0x0930 (2352) pixels +0x10A2, 0x18C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3166, 0x9453, 0xBD58, 0xB518, 0x83B1, 0xAD75, // 0x0940 (2368) pixels +0xD6BA, 0x2125, 0x3186, 0x736E, 0xB596, 0x7BF0, 0xE73C, 0xFFFF, 0xF77E, 0xF79E, 0xF79E, 0xC5F8, 0x10A1, 0x1082, 0x8410, 0x0000, // 0x0950 (2384) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0960 (2400) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0x18E3, 0x10A2, 0x18C3, // 0x0970 (2416) pixels +0x18C3, 0x0861, 0x0861, 0x0000, 0x0000, 0x2985, 0x41E8, 0xA4D5, 0xACF7, 0xC5D9, 0xE6DC, 0x6B4D, 0x62ED, 0xA4D4, 0x9452, 0xC5B9, // 0x0980 (2432) pixels +0x522A, 0x8430, 0xFFFF, 0xFFBF, 0xF77E, 0xF7BE, 0xF77E, 0xE6DD, 0x9CD4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0990 (2448) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x09A0 (2464) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, 0x18E3, 0x18E3, 0x18C3, 0x18C3, 0x2945, // 0x09B0 (2480) pixels +0x39C7, 0x3186, 0x62CC, 0x9C54, 0x9C35, 0xD63A, 0xF75E, 0xA534, 0x83D0, 0xC5D8, 0x9CD3, 0xE6DD, 0x7B70, 0xB5B6, 0xFFFF, 0xEF5E, // 0x09C0 (2496) pixels +0xF77E, 0xFFBF, 0xF77E, 0xE6FD, 0xBD98, 0x39A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x09D0 (2512) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x09E0 (2528) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4A49, 0x5AAC, 0x8392, // 0x09F0 (2544) pixels +0xB537, 0xCE1A, 0xE6FC, 0xF7BE, 0xDEDB, 0xD69A, 0x8C71, 0xFFFF, 0xEF7D, 0xEF7D, 0xFFFF, 0xEF5E, 0xF77E, 0xFFDF, 0xF79E, 0xF77E, // 0x0A00 (2560) pixels +0xD65B, 0x7B70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0A10 (2576) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0A20 (2592) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4208, 0x5A4B, 0xA495, 0xD67B, 0xC599, 0xDEBC, 0xFFFF, // 0x0A30 (2608) pixels +0xFFBF, 0xE71C, 0x8C71, 0xE73C, 0xB5B6, 0xEF7D, 0xFFFF, 0xEF5E, 0xF77E, 0xFFFF, 0xFFDF, 0xF79E, 0xEF5E, 0xC5B9, 0x4A49, 0x0000, // 0x0A40 (2624) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0A50 (2640) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0A60 (2656) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x39E7, 0x4A2A, 0xACF6, 0xE6FC, 0xD63A, 0xE71D, 0xFFFF, 0xF79E, 0xEF3D, 0x9CD3, 0xD69A, // 0x0A70 (2672) pixels +0xBDF7, 0xFFDE, 0xFFDF, 0xF77E, 0xF79E, 0xFFDF, 0xFFFF, 0xFFBF, 0xF7BF, 0xEF1D, 0xAD15, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0A80 (2688) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0A90 (2704) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0AA0 (2720) pixels +0x0000, 0x2965, 0x62CC, 0xACD6, 0xEF3D, 0xE6DC, 0xE71D, 0xFFFF, 0xF7BF, 0xF75E, 0x9CF3, 0xDEDB, 0xFFDF, 0xE73C, 0xFFDF, 0xF7BE, // 0x0AB0 (2736) pixels +0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5E, 0xD65A, 0x41E8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0AC0 (2752) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0AD0 (2768) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1922, 0x734F, 0xB4F7, // 0x0AE0 (2784) pixels +0xEF5E, 0xE6FC, 0xEF3D, 0xEF5D, 0xF79E, 0xF79E, 0xB5B6, 0xBDF7, 0xC638, 0xC638, 0xFFFF, 0xFFDF, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0AF0 (2800) pixels +0xFFFF, 0xFFDF, 0xEF1D, 0x9452, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B00 (2816) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B10 (2832) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2144, 0x736F, 0xBD78, 0xEF5E, 0xDEBC, 0xEF3D, 0xE6FC, // 0x0B20 (2848) pixels +0xF7BF, 0xF79E, 0xD69A, 0x9492, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79F, 0xC5D9, // 0x0B30 (2864) pixels +0x2144, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B40 (2880) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B50 (2896) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x31A6, 0x7B8F, 0xB537, 0xE6DC, 0xE71D, 0xF79E, 0xE6FD, 0xFFDF, 0xFFFF, 0xEF7D, 0x9492, // 0x0B60 (2912) pixels +0xE71C, 0x738E, 0xEF7D, 0xFFDF, 0xFFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xD67B, 0x62ED, 0x0000, 0x8410, 0x0000, // 0x0B70 (2928) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B80 (2944) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B90 (2960) pixels +0x0000, 0x39C7, 0x83F0, 0xACF7, 0xD65B, 0xF79E, 0xFFDF, 0xE6FC, 0xFFDF, 0xFFFF, 0xFFDF, 0x8C71, 0xE71C, 0xE71C, 0xFFFF, 0xFFDF, // 0x0BA0 (2976) pixels +0xFFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDE7B, 0x8BD2, 0x0000, 0x630C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0BB0 (2992) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0BC0 (3008) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x39C7, 0x8C31, 0xACD6, // 0x0BD0 (3024) pixels +0xD65B, 0xF79E, 0xFFDF, 0xE6FD, 0xFFDF, 0xEF5E, 0xEF1D, 0x83F0, 0xE73C, 0xFFFF, 0xEF5D, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0BE0 (3040) pixels +0xFFFF, 0xFFFF, 0xDE9C, 0xD65B, 0x8430, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0BF0 (3056) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0C00 (3072) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0x0000, 0x31A6, 0x8C31, 0x9C74, 0xDE9B, 0xFFDF, 0xFFDF, 0xEF1D, // 0x0C10 (3088) pixels +0xF79E, 0xEF5E, 0xE6FD, 0x9493, 0xCE79, 0xD6BA, 0xBDD7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77E, 0xBD78, 0x9472, // 0x0C20 (3104) pixels +0x4A4C, 0x524B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0C30 (3120) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0C40 (3136) pixels +0x0000, 0x0000, 0x0000, 0x4208, 0x0000, 0x3166, 0x73AE, 0x9C74, 0xE6DC, 0xFFDF, 0xF79E, 0xF79E, 0xF79E, 0xF79E, 0xE6DC, 0xC618, // 0x0C50 (3152) pixels +0x9492, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF3D, 0xDE9C, 0xACD6, 0x6ACD, 0x3ACF, 0x9D9A, 0x7C94, 0x0000, 0x0000, // 0x0C60 (3168) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0C70 (3184) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0C80 (3200) pixels +0x0000, 0x2945, 0x4A8B, 0xA4F5, 0xF77E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFBF, 0xFFDF, 0x8C51, 0xBDD8, 0xC5DA, 0xBDB9, // 0x0C90 (3216) pixels +0xCE3A, 0xC5F9, 0x9C74, 0x622D, 0x3806, 0x2106, 0x3BF4, 0x7DBB, 0xAEBE, 0x8578, 0x0000, 0x0000, 0x4208, 0x0000, 0x0000, 0x0000, // 0x0CA0 (3232) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0CB0 (3248) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0x0000, 0x420A, 0x11CB, 0x632F, // 0x0CC0 (3264) pixels +0x9CB5, 0xB597, 0xCE79, 0xD6BA, 0xD6BB, 0xAD77, 0xB5B7, 0xAD96, 0x6B30, 0x0809, 0x300C, 0x280C, 0x3009, 0x0003, 0x0000, 0x00A3, // 0x0CD0 (3280) pixels +0x332F, 0x7D99, 0x8E1C, 0x8E1B, 0x9E7D, 0x95FB, 0x2986, 0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0CE0 (3296) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0CF0 (3312) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x001F, 0x0000, 0x82B5, 0x398D, 0x18CC, 0x0170, 0x00B0, 0x000C, 0x100A, // 0x0D00 (3328) pixels +0x180B, 0x000A, 0x0009, 0x0009, 0x380B, 0x518D, 0x48CC, 0x484B, 0x49AD, 0x3BF5, 0x5CF8, 0x6539, 0x7DDC, 0xBEDD, 0xCF1D, 0x759B, // 0x0D10 (3344) pixels +0x9E7C, 0xA67D, 0x3AAC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0D20 (3360) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0D30 (3376) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x000A, 0x0000, 0x398C, 0x314B, 0x3A32, 0x53B7, 0x53B6, 0x42D4, 0x4314, 0x5375, 0x63B5, 0x6395, // 0x0D40 (3392) pixels +0x4252, 0x496E, 0x4AF2, 0x5436, 0x5CD9, 0x5D5B, 0x8DFC, 0x9E7D, 0xAE9D, 0xBEDD, 0xCEFD, 0x5D5A, 0xA67C, 0xA69D, 0x5390, 0x0000, // 0x0D50 (3408) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0D60 (3424) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0D70 (3440) pixels +0x4208, 0x0000, 0x318A, 0x292A, 0x30ED, 0x52F4, 0x53B7, 0x4BF7, 0x5438, 0x5458, 0x5C17, 0x5376, 0x4B36, 0x6CD9, 0x5D5A, 0x75DB, // 0x0D80 (3456) pixels +0x85FC, 0x963C, 0xA67C, 0xA67C, 0x9E5C, 0xA67C, 0x8DFB, 0x5D5A, 0xA67C, 0xBEFE, 0x74B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0D90 (3472) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0DA0 (3488) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02AA, 0x0000, 0x31C9, 0x292A, // 0x0DB0 (3504) pixels +0x394D, 0x4212, 0x4315, 0x43B6, 0x5CB9, 0x4B96, 0x5BB6, 0x7458, 0x6C58, 0x755A, 0x5D5A, 0x85DB, 0xAE9D, 0x9E5C, 0xBEDD, 0xAE9D, // 0x0DC0 (3520) pixels +0x963C, 0x9E5C, 0x75BB, 0x657B, 0xBEBD, 0xB6DE, 0x74F7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0DD0 (3536) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0DE0 (3552) pixels +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2108, 0x396E, 0x41D0, 0x42D4, 0x3356, // 0x0DF0 (3568) pixels +0x3BF7, 0x43B7, 0x53D7, 0x5C99, 0x5417, 0x651A, 0x5D5A, 0x7DBB, 0x85FB, 0x8E1C, 0x9E5C, 0x8E1C, 0x85FB, 0x963C, 0x961C, 0x7DDB, // 0x0E00 (3584) pixels +0xD73E, 0xAEBD, 0x8517, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0E10 (3600) pixels +}; diff --git a/libraries/MySensors/examples/UVSensor/UVSensor.ino b/libraries/MySensors/examples/UVSensor/UVSensor.ino new file mode 100644 index 0000000..2fb70eb --- /dev/null +++ b/libraries/MySensors/examples/UVSensor/UVSensor.ino @@ -0,0 +1,109 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - epierre + * Contribution: bulldoglowell, gizmocuz + * + * DESCRIPTION + * Arduino UVM-30A + * Index table taken from: http://www.elecrow.com/sensors-c-111/environment-c-111_112/uv-sensor-moduleuvm30a-p-716.html + * Because this table is pretty lineair, we can calculate a UVI with one decimal + * + * Connect sensor: + * + * + >>> 5V + * - >>> GND + * out >>> A0 + * + * License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define UV_SENSOR_ANALOG_PIN 0 + +#define CHILD_ID_UV 0 + +unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds) + +MyMessage uvMsg(CHILD_ID_UV, V_UV); + +unsigned long lastSend =0; +float uvIndex; +float lastUV = -1; +uint16_t uvIndexValue [12] = { 50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170}; + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("UV Sensor", "1.2"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_UV, S_UV); +} + +void loop() +{ + unsigned long currentTime = millis(); + + uint16_t uv = analogRead(UV_SENSOR_ANALOG_PIN);// Get UV value + if (uv>1170) + uv=1170; + + //Serial.print("UV Analog reading: "); + //Serial.println(uv); + + int i; + for (i = 0; i < 12; i++) + { + if (uv <= uvIndexValue[i]) + { + uvIndex = i; + break; + } + } + + //calculate 1 decimal if possible + if (i>0) { + float vRange=uvIndexValue[i]-uvIndexValue[i-1]; + float vCalc=uv-uvIndexValue[i-1]; + uvIndex+=(1.0/vRange)*vCalc-1.0; + } + + //Serial.print("UVI: "); + //Serial.println(uvIndex,2); + + //Send value to gateway if changed, or at least every 5 minutes + if ((uvIndex != lastUV)||(currentTime-lastSend >= 5UL*60UL*1000UL)) { + lastSend=currentTime; + send(uvMsg.set(uvIndex,2)); + lastUV = uvIndex; + } + + sleep(SLEEP_TIME); +} diff --git a/libraries/MySensors/examples/VibrationSensor/VibrationSensor.ino b/libraries/MySensors/examples/VibrationSensor/VibrationSensor.ino new file mode 100644 index 0000000..f32aa5c --- /dev/null +++ b/libraries/MySensors/examples/VibrationSensor/VibrationSensor.ino @@ -0,0 +1,96 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * DESCRIPTION + * + * Vibration Sensor + * + * connect the sensor as follows : + * + * VCC >>> 5V + * S >>> D3 + * GND >>> GND + * + * Based on: http://www.dfrobot.com/wiki/index.php/DFRobot_Digital_Vibration_Sensor_V2_SKU:DFR0027 + * Contributor: epierre +**/ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include +#include + +#define CHILD_ID_VIBRATION 0 +#define VIBRATION_SENSOR_DIGITAL_PIN 3 +#define SensorLED 13 + +unsigned long SLEEP_TIME = 10*1000; // Sleep time between reads (in seconds) + +//VARIABLES +int val = 0; // variable to store the value coming from the sensor +float valVIBRATION =0.0; +float lastVIBRATION =0.0; +unsigned char state = 0; + +MyMessage vibrationMsg(CHILD_ID_VIBRATION, V_LEVEL); + +void setup() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("VIBRATION Sensor", "1.0"); + + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_VIBRATION, S_VIBRATION); + + + pinMode(VIBRATION_SENSOR_DIGITAL_PIN, INPUT); + attachInterrupt(1, blink, FALLING);// Trigger the blink function when the falling edge is detected + pinMode(SensorLED, OUTPUT); +} + +void loop() +{ + + if(state>=40){ // basically below 40 so ignire basic level + send(vibrationMsg.set(int(state))); + state = 0; + digitalWrite(SensorLED,HIGH); + } else { + state = 0; + digitalWrite(SensorLED,LOW); + } + + + // Power down the radio. Note that the radio will get powered back up + // on the next write() call. + delay(1000); //delay to allow serial to fully print before sleep + + sleep(SLEEP_TIME); //sleep for: sleepTime +} + +void blink()//Interrupts function +{ + state++; +} diff --git a/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino b/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino new file mode 100644 index 0000000..e3d1ae1 --- /dev/null +++ b/libraries/MySensors/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino @@ -0,0 +1,189 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + ******************************* + * + * REVISION HISTORY + * Version 1.0 - Henrik Ekblad + * Version 1.1 - GizMoCuz + * + * DESCRIPTION + * Use this sensor to measure volume and flow of your house watermeter. + * You need to set the correct pulsefactor of your meter (pulses per m3). + * The sensor starts by fetching current volume reading from gateway (VAR 1). + * Reports both volume and flow back to gateway. + * + * Unfortunately millis() won't increment when the Arduino is in + * sleepmode. So we cannot make this sensor sleep if we also want + * to calculate/report flow. + * http://www.mysensors.org/build/pulse_water + */ + +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +#include + +#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) +#define SENSOR_INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) + +#define PULSE_FACTOR 1000 // Nummber of blinks per m3 of your meter (One rotation/liter) + +#define SLEEP_MODE false // flowvalue can only be reported when sleep mode is false. + +#define MAX_FLOW 40 // Max flow (l/min) value to report. This filters outliers. + +#define CHILD_ID 1 // Id of the sensor child + +unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. + +MyMessage flowMsg(CHILD_ID,V_FLOW); +MyMessage volumeMsg(CHILD_ID,V_VOLUME); +MyMessage lastCounterMsg(CHILD_ID,V_VAR1); + +double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter + +volatile unsigned long pulseCount = 0; +volatile unsigned long lastBlink = 0; +volatile double flow = 0; +boolean pcReceived = false; +unsigned long oldPulseCount = 0; +unsigned long newBlink = 0; +double oldflow = 0; +double volume =0; +double oldvolume =0; +unsigned long lastSend =0; +unsigned long lastPulse =0; + +void setup() +{ + setIncomingCallback(incomingMessage); + + // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion) + pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); + + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Water Meter", "1.1"); + + // Register this device as Waterflow sensor + present(CHILD_ID, S_WATER); + + pulseCount = oldPulseCount = 0; + + // Fetch last known pulse count value from gw + request(CHILD_ID, V_VAR1); + + lastSend = lastPulse = millis(); + + attachInterrupt(SENSOR_INTERRUPT, onPulse, FALLING); +} + + +void loop() +{ + unsigned long currentTime = millis(); + + // Only send values at a maximum frequency or woken up from sleep + if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY)) + { + lastSend=currentTime; + + if (!pcReceived) { + //Last Pulsecount not yet received from controller, request it again + request(CHILD_ID, V_VAR1); + return; + } + + if (!SLEEP_MODE && flow != oldflow) { + oldflow = flow; + + Serial.print("l/min:"); + Serial.println(flow); + + // Check that we dont get unresonable large flow value. + // could hapen when long wraps or false interrupt triggered + if (flow<((unsigned long)MAX_FLOW)) { + send(flowMsg.set(flow, 2)); // Send flow value to gw + } + } + + // No Pulse count received in 2min + if(currentTime - lastPulse > 120000){ + flow = 0; + } + + // Pulse count has changed + if ((pulseCount != oldPulseCount)||(!SLEEP_MODE)) { + oldPulseCount = pulseCount; + + Serial.print("pulsecount:"); + Serial.println(pulseCount); + + send(lastCounterMsg.set(pulseCount)); // Send pulsecount value to gw in VAR1 + + double volume = ((double)pulseCount/((double)PULSE_FACTOR)); + if ((volume != oldvolume)||(!SLEEP_MODE)) { + oldvolume = volume; + + Serial.print("volume:"); + Serial.println(volume, 3); + + send(volumeMsg.set(volume, 3)); // Send volume value to gw + } + } + } + if (SLEEP_MODE) { + sleep(SEND_FREQUENCY); + } +} + +void incomingMessage(const MyMessage &message) { + if (message.type==V_VAR1) { + unsigned long gwPulseCount=message.getULong(); + pulseCount += gwPulseCount; + flow=oldflow=0; + Serial.print("Received last pulse count from gw:"); + Serial.println(pulseCount); + pcReceived = true; + } +} + +void onPulse() +{ + if (!SLEEP_MODE) + { + unsigned long newBlink = micros(); + unsigned long interval = newBlink-lastBlink; + + if (interval!=0) + { + lastPulse = millis(); + if (interval<500000L) { + // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) + return; + } + flow = (60000000.0 /interval) / ppl; + } + lastBlink = newBlink; + } + pulseCount++; +} diff --git a/libraries/MySensors/keywords.txt b/libraries/MySensors/keywords.txt new file mode 100644 index 0000000..d98cf9a --- /dev/null +++ b/libraries/MySensors/keywords.txt @@ -0,0 +1,84 @@ +####################################### +# Datatypes (KEYWORD1) +####################################### +MyMessage KEYWORD1 +MySensor KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +setIncomingCallback KEYWORD2 +present KEYWORD2 +send KEYWORD2 +sendSketchInfo KEYWORD2 +sendBatteryLevel KEYWORD2 +sendHeartbeat KEYWORD2 +getNodeId KEYWORD2 +request KEYWORD2 +requestTime KEYWORD2 +saveState KEYWORD2 +loadState KEYWORD2 +wait KEYWORD2 + +###################################### +# Constants (LITERAL1) +####################################### +AUTO LITERAL1 +MY_DEBUG LITERAL1 +MY_REPEATER_FEATURE LITERAL1 +MY_RADIO_NRF24 LITERAL1 +MY_RADIO_RFM69 LITERAL1 +MY_BAUD_RATE LITERAL1 +MY_NODE_ID LITERAL1 +MY_PARENT_NODE_ID LITERAL1 +MY_OTA_FIRMWARE_FEATURE LITERAL1 +MY_OTA_FLASH_SS LITERAL1 +MY_OTA_FLASH_JDECID LITERAL1 +MY_LEDS_BLINKING_FEATURE LITERAL1 +WITH_LEDS_BLINKING_INVERSE LITERAL1 +MY_DEFAULT_LED_BLINK_PERIOD LITERAL1 +MY_WITH_LEDS_BLINKING_INVERSE LITERAL1 +MY_DEFAULT_RX_LED_PIN LITERAL1 +MY_DEFAULT_TX_LED_PIN LITERAL1 +MY_DEFAULT_ERR_LED_PIN LITERAL1 +MY_INCLUSION_MODE_FEATURE LITERAL1 +MY_INCLUSION_BUTTON_FEATURE LITERAL1 +MY_INCLUSION_MODE_BUTTON_PIN LITERAL1 +MY_INCLUSION_MODE_DURATION LITERAL1 +MY_SIGNING_ATSHA204 LITERAL1 +MY_SIGNING_SOFT LITERAL1 +MY_VERIFICATION_TIMEOUT_MS LITERAL1 +MY_SIGNING_NODE_WHITELIST LITERAL1 +MY_SIGNING_ATSHA204_PIN LITERAL1 +MY_SIGNING_SOFT_RANDOMSEED_PIN LITERAL1 +MY_SIGNING_SOFT_SERIAL LITERAL1 +MY_SIGNING_SOFT_HMAC_KEY LITERAL1 +MY_RF24_ENABLE_ENCRYPTION LITERAL1 +MY_RF24_ENCRYPTKEY LITERAL1 +MY_RF24_CE_PIN LITERAL1 +MY_RF24_CS_PIN LITERAL1 +MY_RF24_PA_LEVEL LITERAL1 +MY_RF24_CHANNEL LITERAL1 +MY_RF24_DATARATE LITERAL1 +MY_RF24_BASE_RADIO_ID LITERAL1 +MY_SOFTSPI LITERAL1 +MY_SOFT_SPI_SCK_PIN LITERAL1 +MY_SOFT_SPI_MISO_PIN LITERAL1 +MY_SOFT_SPI_MOSI_PIN LITERAL1 +MY_RFM69_FREQUENCY LITERAL1 +MY_RFM69_FREQUENCY LITERAL1 +MY_IS_RFM69HW LITERAL1 +MY_RFM69_NETWORKID LITERAL1 +MY_RF69_IRQ_PIN LITERAL1 +MY_RF69_SPI_CS LITERAL1 +MY_RF69_IRQ_NUM LITERAL1 +MY_RFM69_ENCRYPTKEY LITERAL1 +MY_GATEWAY_W5100 LITERAL1 +MY_GATEWAY_ENC28J60 LITERAL1 +MY_GATEWAY_ESP8266 LITERAL1 +MY_PORT LITERAL1 +MY_IP_ADDRESS LITERAL1 +MY_USE_UDP LITERAL1 +MY_IP_RENEWAL_INTERVAL LITERAL1 +MY_MAC_ADDRESS LITERAL1 +MY_CONTROLLER_IP_ADDRESS LITERAL1 diff --git a/libraries/NewPing/NewPing.cpp b/libraries/NewPing/NewPing.cpp new file mode 100644 index 0000000..b66bd6c --- /dev/null +++ b/libraries/NewPing/NewPing.cpp @@ -0,0 +1,231 @@ +// --------------------------------------------------------------------------- +// Created by Tim Eckel - teckel@leethost.com +// Copyright 2012 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html +// +// See "NewPing.h" for purpose, syntax, version history, links, and more. +// --------------------------------------------------------------------------- + +#include "NewPing.h" + + +// --------------------------------------------------------------------------- +// NewPing constructor +// --------------------------------------------------------------------------- + +NewPing::NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance) { + _triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin. + _echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin. + + _triggerOutput = portOutputRegister(digitalPinToPort(trigger_pin)); // Get the output port register for the trigger pin. + _echoInput = portInputRegister(digitalPinToPort(echo_pin)); // Get the input port register for the echo pin. + + _triggerMode = (uint8_t *) portModeRegister(digitalPinToPort(trigger_pin)); // Get the port mode register for the trigger pin. + + _maxEchoTime = min(max_cm_distance, MAX_SENSOR_DISTANCE) * US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2); // Calculate the maximum distance in uS. + +#if DISABLE_ONE_PIN == true + *_triggerMode |= _triggerBit; // Set trigger pin to output. +#endif +} + + +// --------------------------------------------------------------------------- +// Standard ping methods +// --------------------------------------------------------------------------- + +unsigned int NewPing::ping() { + if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function. + while (*_echoInput & _echoBit) // Wait for the ping echo. + if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. + return (micros() - (_max_time - _maxEchoTime) - 5); // Calculate ping time, 5uS of overhead. +} + + +unsigned int NewPing::ping_in() { + unsigned int echoTime = NewPing::ping(); // Calls the ping method and returns with the ping echo distance in uS. + return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches. +} + + +unsigned int NewPing::ping_cm() { + unsigned int echoTime = NewPing::ping(); // Calls the ping method and returns with the ping echo distance in uS. + return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters. +} + + +unsigned int NewPing::ping_median(uint8_t it) { + unsigned int uS[it], last; + uint8_t j, i = 0; + uS[0] = NO_ECHO; + while (i < it) { + last = ping(); // Send ping. + if (last == NO_ECHO) { // Ping out of range. + it--; // Skip, don't include as part of median. + last = _maxEchoTime; // Adjust "last" variable so delay is correct length. + } else { // Ping in range, include as part of median. + if (i > 0) { // Don't start sort till second ping. + for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop. + uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion. + } else j = 0; // First ping is starting point for sort. + uS[j] = last; // Add last ping to array in sorted position. + i++; // Move to next ping. + } + if (i < it) delay(PING_MEDIAN_DELAY - (last >> 10)); // Millisecond delay between pings. + } + return (uS[it >> 1]); // Return the ping distance median. +} + + +// --------------------------------------------------------------------------- +// Standard ping method support functions (not called directly) +// --------------------------------------------------------------------------- + +boolean NewPing::ping_trigger() { +#if DISABLE_ONE_PIN != true + *_triggerMode |= _triggerBit; // Set trigger pin to output. +#endif + *_triggerOutput &= ~_triggerBit; // Set the trigger pin low, should already be low, but this will make sure it is. + delayMicroseconds(4); // Wait for pin to go low, testing shows it needs 4uS to work every time. + *_triggerOutput |= _triggerBit; // Set trigger pin high, this tells the sensor to send out a ping. + delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. + *_triggerOutput &= ~_triggerBit; // Set trigger pin back to low. +#if DISABLE_ONE_PIN != true + *_triggerMode &= ~_triggerBit; // Set trigger pin to input (when using one Arduino pin this is technically setting the echo pin to input as both are tied to the same Arduino pin). +#endif + + _max_time = micros() + MAX_SENSOR_DELAY; // Set a timeout for the ping to trigger. + while (*_echoInput & _echoBit && micros() <= _max_time) {} // Wait for echo pin to clear. + while (!(*_echoInput & _echoBit)) // Wait for ping to start. + if (micros() > _max_time) return false; // Something went wrong, abort. + + _max_time = micros() + _maxEchoTime; // Ping started, set the timeout. + return true; // Ping started successfully. +} + + +// --------------------------------------------------------------------------- +// Timer interrupt ping methods (won't work with ATmega8 and ATmega128) +// --------------------------------------------------------------------------- + +void NewPing::ping_timer(void (*userFunc)(void)) { + if (!ping_trigger()) return; // Trigger a ping, if it returns false, return without starting the echo timer. + timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS. +} + + +boolean NewPing::check_timer() { + if (micros() > _max_time) { // Outside the timeout limit. + timer_stop(); // Disable timer interrupt + return false; // Cancel ping timer. + } + + if (!(*_echoInput & _echoBit)) { // Ping echo received. + timer_stop(); // Disable timer interrupt + ping_result = (micros() - (_max_time - _maxEchoTime) - 13); // Calculate ping time, 13uS of overhead. + return true; // Return ping echo true. + } + + return false; // Return false because there's no ping echo yet. +} + + +// --------------------------------------------------------------------------- +// Timer2/Timer4 interrupt methods (can be used for non-ultrasonic needs) +// --------------------------------------------------------------------------- + +// Variables used for timer functions +void (*intFunc)(); +void (*intFunc2)(); +unsigned long _ms_cnt_reset; +volatile unsigned long _ms_cnt; + + +void NewPing::timer_us(unsigned int frequency, void (*userFunc)(void)) { + timer_setup(); // Configure the timer interrupt. + intFunc = userFunc; // User's function to call when there's a timer event. + +#if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). + OCR4C = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. + TIMSK4 = (1<>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. + TIMSK2 |= (1<= 100 + #include +#else + #include + #include +#endif + +#include +#include + +// Shoudln't need to changed these values unless you have a specific need to do so. +#define MAX_SENSOR_DISTANCE 500 // Maximum sensor distance can be as high as 500cm, no reason to wait for ping longer than sound takes to travel this distance and back. +#define US_ROUNDTRIP_IN 146 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space. +#define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. +#define DISABLE_ONE_PIN false // Set to "true" to save up to 26 bytes of compiled code space if you're not using one pin sensor connections. + +// Probably shoudln't change these values unless you really know what you're doing. +#define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance. +#define MAX_SENSOR_DELAY 18000 // Maximum uS it takes for sensor to start the ping (SRF06 is the highest measured, just under 18ms). +#define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy). +#define PING_MEDIAN_DELAY 29 // Millisecond delay between pings in the ping_median method. + +// Conversion from uS to distance (round result to nearest cm or inch). +#define NewPingConvert(echoTime, conversionFactor) (max((echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0))) + + +class NewPing { + public: + NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance = MAX_SENSOR_DISTANCE); + unsigned int ping(); + unsigned int ping_in(); + unsigned int ping_cm(); + unsigned int ping_median(uint8_t it = 5); + unsigned int convert_in(unsigned int echoTime); + unsigned int convert_cm(unsigned int echoTime); + void ping_timer(void (*userFunc)(void)); + boolean check_timer(); + unsigned long ping_result; + static void timer_us(unsigned int frequency, void (*userFunc)(void)); + static void timer_ms(unsigned long frequency, void (*userFunc)(void)); + static void timer_stop(); + private: + boolean ping_trigger(); + boolean ping_wait_timer(); + uint8_t _triggerBit; + uint8_t _echoBit; + volatile uint8_t *_triggerOutput; + volatile uint8_t *_triggerMode; + volatile uint8_t *_echoInput; + unsigned int _maxEchoTime; + unsigned long _max_time; + static void timer_setup(); + static void timer_ms_cntdwn(); +}; + + +#endif \ No newline at end of file diff --git a/libraries/NewPing/examples/NewPing15Sensors/NewPing15Sensors.pde b/libraries/NewPing/examples/NewPing15Sensors/NewPing15Sensors.pde new file mode 100644 index 0000000..8354059 --- /dev/null +++ b/libraries/NewPing/examples/NewPing15Sensors/NewPing15Sensors.pde @@ -0,0 +1,74 @@ +// --------------------------------------------------------------------------- +// This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust +// the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the +// "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor +// is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results +// are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project +// would normally process the sensor results in this function (for example, decide if a robot needs to +// turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs +// to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other +// processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind. +// --------------------------------------------------------------------------- +#include + +#define SONAR_NUM 15 // Number or sensors. +#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. +#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). + +unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor. +unsigned int cm[SONAR_NUM]; // Where the ping distances are stored. +uint8_t currentSensor = 0; // Keeps track of which sensor is active. + +NewPing sonar[SONAR_NUM] = { // Sensor object array. + NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. + NewPing(43, 44, MAX_DISTANCE), + NewPing(45, 20, MAX_DISTANCE), + NewPing(21, 22, MAX_DISTANCE), + NewPing(23, 24, MAX_DISTANCE), + NewPing(25, 26, MAX_DISTANCE), + NewPing(27, 28, MAX_DISTANCE), + NewPing(29, 30, MAX_DISTANCE), + NewPing(31, 32, MAX_DISTANCE), + NewPing(34, 33, MAX_DISTANCE), + NewPing(35, 36, MAX_DISTANCE), + NewPing(37, 38, MAX_DISTANCE), + NewPing(39, 40, MAX_DISTANCE), + NewPing(50, 51, MAX_DISTANCE), + NewPing(52, 53, MAX_DISTANCE) +}; + +void setup() { + Serial.begin(115200); + pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting. + for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor. + pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; +} + +void loop() { + for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors. + if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping? + pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged. + if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results. + sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). + currentSensor = i; // Sensor being accessed. + cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor. + sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). + } + } + // The rest of your code would go here. +} + +void echoCheck() { // If ping received, set the sensor distance to array. + if (sonar[currentSensor].check_timer()) + cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM; +} + +void oneSensorCycle() { // Sensor ping cycle complete, do something with the results. + for (uint8_t i = 0; i < SONAR_NUM; i++) { + Serial.print(i); + Serial.print("="); + Serial.print(cm[i]); + Serial.print("cm "); + } + Serial.println(); +} \ No newline at end of file diff --git a/libraries/NewPing/examples/NewPingEventTimer/NewPingEventTimer.pde b/libraries/NewPing/examples/NewPingEventTimer/NewPingEventTimer.pde new file mode 100644 index 0000000..a469c37 --- /dev/null +++ b/libraries/NewPing/examples/NewPingEventTimer/NewPingEventTimer.pde @@ -0,0 +1,46 @@ +// --------------------------------------------------------------------------- +// This example shows how to use NewPing's ping_timer method which uses the Timer2 interrupt to get the +// ping time. The advantage of using this method over the standard ping method is that it permits a more +// event-driven sketch which allows you to appear to do two things at once. An example would be to ping +// an ultrasonic sensor for a possible collision while at the same time navigating. This allows a +// properly developed sketch to multitask. Be aware that because the ping_timer method uses Timer2, +// other features or libraries that also use Timer2 would be effected. For example, the PWM function on +// pins 3 & 11 on Arduino Uno (pins 9 and 11 on Arduino Mega) and the Tone library. Note, only the PWM +// functionality of the pins is lost (as they use Timer2 to do PWM), the pins are still available to use. +// NOTE: For Teensy/Leonardo (ATmega32U4) the library uses Timer4 instead of Timer2. +// --------------------------------------------------------------------------- +#include + +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on ping sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on ping sensor. +#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +unsigned int pingSpeed = 50; // How frequently are we going to send out a ping (in milliseconds). 50ms would be 20 times a second. +unsigned long pingTimer; // Holds the next ping time. + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. + pingTimer = millis(); // Start now. +} + +void loop() { + // Notice how there's no delays in this sketch to allow you to do other processing in-line while doing distance pings. + if (millis() >= pingTimer) { // pingSpeed milliseconds since last ping, do another ping. + pingTimer += pingSpeed; // Set the next ping time. + sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status. + } + // Do other stuff here, really. Think of it as multi-tasking. +} + +void echoCheck() { // Timer2 interrupt calls this function every 24uS where you can check the ping status. + // Don't do anything here! + if (sonar.check_timer()) { // This is how you check to see if the ping was received. + // Here's where you can add code. + Serial.print("Ping: "); + Serial.print(sonar.ping_result / US_ROUNDTRIP_CM); // Ping returned, uS result in ping_result, convert to cm with US_ROUNDTRIP_CM. + Serial.println("cm"); + } + // Don't do anything here! +} \ No newline at end of file diff --git a/libraries/NewPing/examples/NewPingExample/NewPingExample.ino b/libraries/NewPing/examples/NewPingExample/NewPingExample.ino new file mode 100644 index 0000000..a37f5e9 --- /dev/null +++ b/libraries/NewPing/examples/NewPingExample/NewPingExample.ino @@ -0,0 +1,23 @@ +// --------------------------------------------------------------------------- +// Example NewPing library sketch that does a ping about 20 times per second. +// --------------------------------------------------------------------------- + +#include + +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. +#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. +} + +void loop() { + delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. + unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS). + Serial.print("Ping: "); + Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range) + Serial.println("cm"); +} diff --git a/libraries/NewPing/examples/TimerExample/TimerExample.pde b/libraries/NewPing/examples/TimerExample/TimerExample.pde new file mode 100644 index 0000000..35e1db2 --- /dev/null +++ b/libraries/NewPing/examples/TimerExample/TimerExample.pde @@ -0,0 +1,25 @@ +// --------------------------------------------------------------------------- +// While the NewPing library's primary goal is to interface with ultrasonic sensors, interfacing with +// the Timer2 interrupt was a result of creating an interrupt-based ping method. Since these Timer2 +// interrupt methods were built, the library may as well provide the functionality to use these methods +// in your sketches. This shows how simple it is (no ultrasonic sensor required). Keep in mind that +// these methods use Timer2, as does NewPing's ping_timer method for using ultrasonic sensors. You +// can't use ping_timer at the same time you're using timer_ms or timer_us as all use the same timer. +// --------------------------------------------------------------------------- + +#include + +#define LED_PIN 13 // Pin with LED attached. + +void setup() { + pinMode(LED_PIN, OUTPUT); + NewPing::timer_ms(500, toggleLED); // Create a Timer2 interrupt that calls toggleLED in your sketch once every 500 milliseconds. +} + +void loop() { + // Do anything here, the Timer2 interrupt will take care of the flashing LED without your intervention. +} + +void toggleLED() { + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle the LED. +} \ No newline at end of file diff --git a/libraries/NewPing/keywords.txt b/libraries/NewPing/keywords.txt new file mode 100644 index 0000000..ff7805b --- /dev/null +++ b/libraries/NewPing/keywords.txt @@ -0,0 +1,29 @@ +################################### +# Syntax Coloring Map For NewPing +################################### + +################################### +# Datatypes (KEYWORD1) +################################### + +NewPing KEYWORD1 + +################################### +# Methods and Functions (KEYWORD2) +################################### + +ping KEYWORD2 +ping_in KEYWORD2 +ping_cm KEYWORD2 +ping_median KEYWORD2 +ping_timer KEYWORD2 +check_timer KEYWORD2 +timer_us KEYWORD2 +timer_ms KEYWORD2 +timer_stop KEYWORD2 +convert_in KEYWORD2 +convert_cm KEYWORD2 + +################################### +# Constants (LITERAL1) +################################### diff --git a/libraries/NewRemoteSwitch/NewRemoteReceiver.cpp b/libraries/NewRemoteSwitch/NewRemoteReceiver.cpp new file mode 100644 index 0000000..b4e9ce6 --- /dev/null +++ b/libraries/NewRemoteSwitch/NewRemoteReceiver.cpp @@ -0,0 +1,318 @@ +/* + * NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/ + * See NewRemoteReceiver.h for details. + * + * License: GPLv3. See license.txt + */ + +#include "NewRemoteReceiver.h" + + +/************ +* NewRemoteReceiver + +Protocol. (Copied from Wieltje, http://www.circuitsonline.net/forum/view/message/1181410#1181410, +but with slightly different timings, as measured on my device.) + _ _ +'0': | |_| |_____ (T,T,T,5T) + _ _ +'1': | |_____| |_ (T,5T,T,T) + _ _ +dim: | |_| |_ (T,T,T,T) + +T = short period of ~260µs. However, this code tries +to figure out the correct period + +A full frame looks like this: + +- start pulse: 1T high, 10.44T low +- 26 bit: Address +- 1 bit: group bit +- 1 bit: on/off/[dim] +- 4 bit: unit +- [4 bit: dim level. Only present of [dim] is chosen] +- stop pulse: 1T high, 40T low + +************/ + +int8_t NewRemoteReceiver::_interrupt; +volatile short NewRemoteReceiver::_state; +byte NewRemoteReceiver::_minRepeats; +NewRemoteReceiverCallBack NewRemoteReceiver::_callback; +boolean NewRemoteReceiver::_inCallback = false; +boolean NewRemoteReceiver::_enabled = false; + +void NewRemoteReceiver::init(int8_t interrupt, byte minRepeats, NewRemoteReceiverCallBack callback) { + _interrupt = interrupt; + _minRepeats = minRepeats; + _callback = callback; + + enable(); + if (_interrupt >= 0) { + attachInterrupt(_interrupt, interruptHandler, CHANGE); + } +} + +void NewRemoteReceiver::enable() { + _state = -1; + _enabled = true; +} + +void NewRemoteReceiver::disable() { + _enabled = false; +} + +void NewRemoteReceiver::deinit() { + _enabled = false; + if (_interrupt >= 0) { + detachInterrupt(_interrupt); + } +} + +void NewRemoteReceiver::interruptHandler() { + // This method is written as compact code to keep it fast. While breaking up this method into more + // methods would certainly increase the readability, it would also be much slower to execute. + // Making calls to other methods is quite expensive on AVR. As These interrupt handlers are called + // many times a second, calling other methods should be kept to a minimum. + + if (!_enabled) { + return; + } + + static byte receivedBit; // Contains "bit" currently receiving + static NewRemoteCode receivedCode; // Contains received code + static NewRemoteCode previousCode; // Contains previous received code + static byte repeats = 0; // The number of times the an identical code is received in a row. + static unsigned long edgeTimeStamp[3] = {0, }; // Timestamp of edges + static unsigned int min1Period, max1Period, min5Period, max5Period; + static bool skip; + + // Filter out too short pulses. This method works as a low pass filter. + edgeTimeStamp[1] = edgeTimeStamp[2]; + edgeTimeStamp[2] = micros(); + + if (skip) { + skip = false; + return; + } + + if (_state >= 0 && edgeTimeStamp[2]-edgeTimeStamp[1] < min1Period) { + // Last edge was too short. + // Skip this edge, and the next too. + skip = true; + return; + } + + unsigned int duration = edgeTimeStamp[1] - edgeTimeStamp[0]; + edgeTimeStamp[0] = edgeTimeStamp[1]; + + // Note that if state>=0, duration is always >= 1 period. + + if (_state == -1) { + // wait for the long low part of a stop bit. + // Stopbit: 1T high, 40T low + // By default 1T is 260µs, but for maximum compatibility go as low as 120µs + if (duration > 4800) { // =40*120µs, minimal time between two edges before decoding starts. + // Sync signal received.. Preparing for decoding + repeats = 0; + + receivedCode.period = duration / 40; // Measured signal is 40T, so 1T (period) is measured signal / 40. + + // Allow for large error-margin. ElCheapo-hardware :( + min1Period = receivedCode.period * 3 / 10; // Lower limit for 1 period is 0.3 times measured period; high signals can "linger" a bit sometimes, making low signals quite short. + max1Period = receivedCode.period * 3; // Upper limit for 1 period is 3 times measured period + min5Period = receivedCode.period * 3; // Lower limit for 5 periods is 3 times measured period + max5Period = receivedCode.period * 8; // Upper limit for 5 periods is 8 times measured period + } + else { + return; + } + } else if (_state == 0) { // Verify start bit part 1 of 2 + // Duration must be ~1T + if (duration > max1Period) { + _state = -1; + return; + } + // Start-bit passed. Do some clean-up. + receivedCode.address = receivedCode.unit = receivedCode.dimLevel = 0; + } else if (_state == 1) { // Verify start bit part 2 of 2 + // Duration must be ~10.44T + if (duration < 7 * receivedCode.period || duration > 15 * receivedCode.period) { + _state = -1; + return; + } + } else if (_state < 148) { // state 146 is first edge of stop-sequence. All bits before that adhere to default protocol, with exception of dim-bit + receivedBit <<= 1; + + // One bit consists out of 4 bit parts. + // bit part durations can ONLY be 1 or 5 periods. + if (duration <= max1Period) { + receivedBit &= B1110; // Clear LSB of receivedBit + } else if (duration >= min5Period && duration <= max5Period) { + receivedBit |= B1; // Set LSB of receivedBit + } else if ( + // Check if duration matches the second part of stopbit (duration must be ~40T), and ... + (duration >= 20 * receivedCode.period && duration <= 80 * receivedCode.period) && + // if first part op stopbit was a short signal (short signal yielded a 0 as second bit in receivedBit), and ... + ((receivedBit & B10) == B00) && + // we are in a state in which a stopbit is actually valid, only then ... + (_state == 147 || _state == 131) ) { + // If a dim-level was present... + if (_state == 147) { + // ... test if it was an "on" signal ... + if (receivedCode.switchType == NewRemoteCode::on) { + // ... set the appropriate switch type + receivedCode.switchType = NewRemoteCode::on_with_dim; + } else { + // ... otherwise it was wrong (e.g. off-signal with dim) + _state = -1; + return; + } + } + + // a valid signal was found! + if ( + receivedCode.address != previousCode.address || + receivedCode.unit != previousCode.unit || + receivedCode.dimLevel != previousCode.dimLevel || + receivedCode.groupBit != previousCode.groupBit || + receivedCode.switchType != previousCode.switchType + ) { // memcmp isn't deemed safe + repeats=0; + previousCode = receivedCode; + } + + repeats++; + + if (repeats>=_minRepeats) { + if (!_inCallback) { + _inCallback = true; + (_callback)(receivedCode); + _inCallback = false; + } + // Reset after callback. + _state=-1; + return; + } + + // Reset for next round + _state=0; // no need to wait for another sync-bit! + return; + } + else { // Otherwise the entire sequence is invalid + _state = -1; + return; + } + + if (_state % 4 == 1) { // Last bit part? Note: this is the short version of "if ( (_state-2) % 4 == 3 )" + // There are 3 valid options for receivedBit: + // 0, indicated by short short short long == B0001. + // 1, short long shot short == B0100. + // dim, short shot short shot == B0000. + // Everything else: inconsistent data, trash the whole sequence. + + + if (_state < 106) { + // States 2 - 105 are address bit states + + receivedCode.address <<= 1; + + // Decode bit. Only 4 LSB's of receivedBit are used; trim the rest. + switch (receivedBit & B1111) { + case B0001: // Bit "0" received. + // receivedCode.address |= 0; But let's not do that, as it is wasteful. + break; + case B0100: // Bit "1" received. + receivedCode.address |= 1; + break; + default: // Bit was invalid. Abort. + _state = -1; + return; + } + } else if (_state < 110) { + // States 106 - 109 are group bit states. + switch (receivedBit & B1111) { + case B0001: // Bit "0" received. + receivedCode.groupBit = false; + break; + case B0100: // Bit "1" received. + receivedCode.groupBit = true; + break; + default: // Bit was invalid. Abort. + _state = -1; + return; + } + } else if (_state < 114) { + // States 110 - 113 are switch bit states. + switch (receivedBit & B1111) { + case B0001: // Bit "0" received. + receivedCode.switchType = NewRemoteCode::off; + break; + case B0100: // Bit "1" received. Note: this might turn out to be a on_with_dim signal. + receivedCode.switchType = NewRemoteCode::on; + break; + case B0000: // Bit "dim" received. + receivedCode.switchType = NewRemoteCode::dim; + break; + default: // Bit was invalid. Abort. + _state = -1; + return; + } + } else if (_state < 130){ + // States 114 - 129 are unit bit states. + receivedCode.unit <<= 1; + + // Decode bit. + switch (receivedBit & B1111) { + case B0001: // Bit "0" received. + // receivedCode.unit |= 0; But let's not do that, as it is wasteful. + break; + case B0100: // Bit "1" received. + receivedCode.unit |= 1; + break; + default: // Bit was invalid. Abort. + _state = -1; + return; + } + + } else if (_state < 146) { + // States 130 - 145 are dim bit states. + // If switchType == 0 these are never present. + // If switchType == 2 these are always present. + // If switchType == 1 these are or are not present, depending on the revision of the transmitter. + + receivedCode.dimLevel <<= 1; + + // Decode bit. + switch (receivedBit & B1111) { + case B0001: // Bit "0" received. + // receivedCode.dimLevel |= 0; But let's not do that, as it is wasteful. + break; + case B0100: // Bit "1" received. + receivedCode.dimLevel |= 1; + break; + default: // Bit was invalid. Abort. + _state = -1; + return; + } + } + } + } + + _state++; + return; +} + +boolean NewRemoteReceiver::isReceiving(int waitMillis) { + unsigned long startTime=millis(); + + int waited; // Signed int! + do { + if (_state >= 34) { // Abort if a significant part of a code (start pulse + 8 bits) has been received + return true; + } + waited = (millis()-startTime); + } while(waited>=0 && waited <= waitMillis); // Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time. + + return false; +} diff --git a/libraries/NewRemoteSwitch/NewRemoteReceiver.h b/libraries/NewRemoteSwitch/NewRemoteReceiver.h new file mode 100644 index 0000000..eaa5a45 --- /dev/null +++ b/libraries/NewRemoteSwitch/NewRemoteReceiver.h @@ -0,0 +1,107 @@ +/* + * NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/ + * + * License: GPLv3. See license.txt + */ + +#ifndef NewRemoteReceiver_h +#define NewRemoteReceiver_h + +#include + +struct NewRemoteCode { + enum SwitchType { + off = 0, + on = 1, + dim = 2, + on_with_dim = 3 + }; + + unsigned int period; // Detected duration in microseconds of 1T in the received signal + unsigned long address; // Address of received code. [0..2^26-1] + boolean groupBit; // Group bit set or not + SwitchType switchType; // off, on, dim, on_with_dim. + byte unit; // Unit code of received code [0..15] + byte dimLevel; // Dim level [0..15] iff switchType == 2 +}; + +typedef void (*NewRemoteReceiverCallBack)(NewRemoteCode); + +/** +* See RemoteSwitch for introduction. +* +* NewRemoteReceiver decodes the signal received from a 433MHz-receiver, like the "KlikAanKlikUit"-system +* as well as the signal sent by the RemoteSwtich class. When a correct signal is received, +* a user-defined callback function is called. +* +* Note that in the callback function, the interrupts are still disabled. You can enabled them, if needed. +* A call to the callback must be finished before NewRemoteReceiver will call the callback function again, thus +* there is no re-entrant problem. +* +* When sending your own code using NewRemoteSwich, disable() the receiver first. +* +* This is a pure static class, for simplicity and to limit memory-use. +*/ + +class NewRemoteReceiver { + public: + /** + * Initializes the decoder. + * + * If interrupt >= 0, init will register pin to this library. + * If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler() + * yourself whenever the output of the receiver changes, or you can use InterruptChain. + * + * @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details. + If < 0, you must call interruptHandler() yourself. + * @param minRepeats The number of times the same code must be received in a row before the callback is calles + * @param callback Pointer to a callback function, with signature void (*func)(NewRemoteCode) + */ + static void init(int8_t interrupt, byte minRepeats, NewRemoteReceiverCallBack callback); + + /** + * Enable decoding. No need to call enable() after init(). + */ + static void enable(); + + /** + * Disable decoding. You can re-enable decoding by calling enable(); + */ + static void disable(); + + /** + * Deinitializes the decoder. Disables decoding and detaches the interrupt handler. If you want to + * re-enable decoding, call init() again. + */ + static void deinit(); + + /** + * Tells wether a signal is being received. If a compatible signal is detected within the time out, isReceiving returns true. + * Since it makes no sense to transmit while another transmitter is active, it's best to wait for isReceiving() to false. + * By default it waits for 150ms, in which a (relative slow) KaKu signal can be broadcasted three times. + * + * Note: isReceiving() depends on interrupts enabled. Thus, when disabled()'ed, or when interrupts are disabled (as is + * the case in the callback), isReceiving() will not work properly. + * + * @param waitMillis number of milliseconds to monitor for signal. + * @return boolean If after waitMillis no signal was being processed, returns false. If before expiration a signal was being processed, returns true. + */ + static boolean isReceiving(int waitMillis = 150); + + /** + * Called every time the signal level changes (high to low or vice versa). Usually called by interrupt. + */ + static void interruptHandler(); + + private: + + static int8_t _interrupt; // Radio input interrupt + volatile static short _state; // State of decoding process. + static byte _minRepeats; + static NewRemoteReceiverCallBack _callback; + static boolean _inCallback; // When true, the callback function is being executed; prevents re-entrance. + static boolean _enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately. + +}; + +#endif diff --git a/libraries/NewRemoteSwitch/NewRemoteTransmitter.cpp b/libraries/NewRemoteSwitch/NewRemoteTransmitter.cpp new file mode 100644 index 0000000..7220901 --- /dev/null +++ b/libraries/NewRemoteSwitch/NewRemoteTransmitter.cpp @@ -0,0 +1,134 @@ +/* + * NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/ + * See NewRemoteTransmitter.h for details. + * + * License: GPLv3. See license.txt + */ + +#include "NewRemoteTransmitter.h" + + +NewRemoteTransmitter::NewRemoteTransmitter(unsigned long address, byte pin, unsigned int periodusec, byte repeats) { + _address = address; + _pin = pin; + _periodusec = periodusec; + _repeats = (1 << repeats) - 1; // I.e. _repeats = 2^repeats - 1 + + pinMode(_pin, OUTPUT); +} + +void NewRemoteTransmitter::sendGroup(boolean switchOn) { + for (int8_t i = _repeats; i >= 0; i--) { + _sendStartPulse(); + + _sendAddress(); + + // Do send group bit + _sendBit(true); + + // Switch on | off + _sendBit(switchOn); + + // No unit. Is this actually ignored?.. + _sendUnit(0); + + _sendStopPulse(); + } +} + +void NewRemoteTransmitter::sendUnit(byte unit, boolean switchOn) { + for (int8_t i = _repeats; i >= 0; i--) { + _sendStartPulse(); + + _sendAddress(); + + // No group bit + _sendBit(false); + + // Switch on | off + _sendBit(switchOn); + + _sendUnit(unit); + + _sendStopPulse(); + } +} + +void NewRemoteTransmitter::sendDim(byte unit, byte dimLevel) { + for (int8_t i = _repeats; i >= 0; i--) { + _sendStartPulse(); + + _sendAddress(); + + // No group bit + _sendBit(false); + + // Switch type 'dim' + digitalWrite(_pin, HIGH); + delayMicroseconds(_periodusec); + digitalWrite(_pin, LOW); + delayMicroseconds(_periodusec); + digitalWrite(_pin, HIGH); + delayMicroseconds(_periodusec); + digitalWrite(_pin, LOW); + delayMicroseconds(_periodusec); + + _sendUnit(unit); + + for (int8_t j=3; j>=0; j--) { + _sendBit(dimLevel & 1<> 1)); // Actually 10.5T insteat of 10.44T. Close enough. +} + +void NewRemoteTransmitter::_sendAddress() { + for (int8_t i=25; i>=0; i--) { + _sendBit((_address >> i) & 1); + } +} + +void NewRemoteTransmitter::_sendUnit(byte unit) { + for (int8_t i=3; i>=0; i--) { + _sendBit(unit & 1< + +/** +* NewRemoteTransmitter provides a generic class for simulation of common RF remote controls, like the A-series +* 'Klik aan Klik uit'-system (http://www.klikaanklikuit.nl/), used to remotely switch lights etc. +* +* This class is meant for new-style remotes, usually accompanied by receivers with "code learning" +* capabilities. For other remotes, use the RemoteTransmitter class. +* +* Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g. +* http://www.sparkfun.com/products/10534 +* http://www.conrad.nl/goto/?product=130428 +* +* Notes: +* - I measured the period length with an oscilloscope, using a A-series KAKU transmitter. Other devices +* or manufacturers may use other period length. Use the ShowReceivedCodeNewRemote example to find the +* period length for your devices. +* - You can copy the address of your "real" remotes, so you won't have to learn new codes into the receivers. +* In effect this duplicates a remote. But you can also pick a random number in the range 0..2^26-1. +*/ +class NewRemoteTransmitter { + public: + /** + * Constructor. + * + * To obtain the correct period length, use the ShowReceivedCodeNewRemote example, or you + * can use an oscilloscope. + * + * @param address Address of this transmitter [0..2^26-1] Duplicate the address of your hardware, or choose a random number. + * @param pin Output pin on Arduino to which the transmitter is connected + * @param periodusec Duration of one period, in microseconds. One bit takes 8 periods (but only 4 for 'dim' signal). + * @param repeats [0..8] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust, 8 is maximum (and overkill). + */ + NewRemoteTransmitter(unsigned long address, byte pin, unsigned int periodusec = 260, byte repeats = 4); + + /** + * Send on/off command to the address group. + * + * @param switchOn True to send "on" signal, false to send "off" signal. + */ + void sendGroup(boolean switchOn); + + /** + * Send on/off command to an unit on the current address. + * + * @param unit [0..15] target unit. + * @param switchOn True to send "on" signal, false to send "off" signal. + */ + void sendUnit(byte unit, boolean switchOn); + + /** + * Send dim value to an unit on the current address. + * + * @param unit [0..15] target unit. + * @param dimLevel [0..15] Dim level. 0 for off, 15 for brightest level. + */ + void sendDim(byte unit, byte dimLevel); + + protected: + unsigned long _address; // Address of this transmitter. + byte _pin; // Transmitter output pin + unsigned int _periodusec; // Oscillator period in microseconds + byte _repeats; // Number over repetitions of one telegram + + /** + * Transmits start-pulse + */ + void _sendStartPulse(); + + /** + * Transmits address part + */ + void _sendAddress(); + + /** + * Transmits unit part. + * + * @param unit [0-15] target unit. + */ + void _sendUnit(byte unit); + + /** + * Transmits stop pulse. + */ + void _sendStopPulse(); + + /** + * Transmits a single bit. + * + * @param isBitOne True, to send '1', false to send '0'. + */ + void _sendBit(boolean isBitOne); +}; +#endif diff --git a/libraries/NewRemoteSwitch/README.TXT b/libraries/NewRemoteSwitch/README.TXT new file mode 100644 index 0000000..a1b05f4 --- /dev/null +++ b/libraries/NewRemoteSwitch/README.TXT @@ -0,0 +1,48 @@ +NewRemoteSwitch library v1.1.0 (BETA) for Arduino 1.0 +Made by Randy Simons http://randysimons.nl/ + +This library provides an easy class for Arduino, to send and receive signals +used by some common "new style" 433MHz remote control switches. + +There are two styles of remote: + - "old style", which uses switches or a dial to set the house code. Use the + RemoteSwitch library instead. + - "new style", which use a button on the receivers to "learn" a signal. Use + this library. + +License: GPLv3. See ./NewRemoteSwitch/license.txt + +Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino + + +Installation of library: + - Make sure Arduino is closed + - Copy the directory NewRemoteSwitch to the Arduino library directory (usually + /libraries/) + See http://arduino.cc/en/Guide/Libraries for detailed instructions. + +Default installation demo: + - Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo. + (Note: your hardware may have a different pin configuration!) + - Start Arduino, and open the example: File -> Examples -> NewRemoteSwitch -> + ShowReceivedCode or ShowReceivedCodeNewRemote. + - Compile, upload and run + - Open serial monitor in Arduino (115200 baud) + - Press buttons on a 433MHz-remote, and watch the serial monitor + + +Changelog: +NewRemoteSwitch library v1.1.0 (20130601) for Arduino 1.0 + - BUGFIX: in many occasions, when receiving a dim-level, the code was rejected + even if the signal was correct. + - Support decoding A-series transmitters which transmit a dim-level in + combination with an on-signal, instead of a dim-signal. + - Uses NewRemodeCode::on, ::off, ::dim, ::on_with_dim instead of 0, 1, 2 and 3, + for better readability. This change is backwards compatible. + - Updated examples to use the new NewRemodeCode::on, ::off, ::dim and + ::on_with_dim notation. + - Reduced memory usage (Flash, RAM) + +NewRemoteSwitch library v1.0.0 (20121229) for Arduino 1.0 + - Support for receiving A-series Klik-aan-klik-uit remote. (NewRemoteReceiver) + - With examples to test and demonstrate. diff --git a/libraries/NewRemoteSwitch/docs/hardware setup.jpg b/libraries/NewRemoteSwitch/docs/hardware setup.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bea017e4c0bc5bcac747f08726b9ffffbc64b63d GIT binary patch literal 132303 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%0AdUzN1-(er_@4 zoSO*$z{uD)*67_{4sA-vK`2DQo(kC6Q}b`jq8nx$9>#BN?;RdScpKuU7a(Q4T-BAw zAhx`iIDP~2bnao~V+U3%b7B&C=zn~5sz)4eiGyVPQyK2ze0yMrt$SU&7{^0W?u3bp zi^vERh&U01obML(^wggechqx}Dif>P5EG=5aZlrTR!F)PFm~UJ(ph(^PNDZAQ(%yo zJe)7GFp)Khr=={O_*Xb4u|NxsyHJH@5cU%#m`=4hEXx6KIV2G>4F z2nj9@xYfGaJaJdt4OO>Mc~(NSMD7j_sliz44~;>|bzj@dBSBSw|1)jLe&&3j2D8y6S;x})YJL5PPIm_ps@72LZY>q|qm{gC#LPA24QcR;PY&F6? zo0N5ujhO7-CkXE}TOvDyTG&e|$*`wBu~YZvfjgmmDYhTKP*TF|$($DU5PuHADlX!z zGj*Z0c+Xq*p>Y+$MrnDB<6J_<**n^7`qKF$4W*JJKYiUD)hdt-1?3SJXQZKxGPL?x zq{e2Nl@BzgGCsmXiY=lj0$CkL?NOM}vQ$0pdy@Q&9ms5(sT=P{5twX5jMo#$Nl*TB z_p&X?v74x*Sq-Z|F`BU<#>rN2hB;YpKQ|g~DfhrmtIFOdaj9iUr~h3*ss?gXIf$o# zS%@UE5`a-JUqU=fw5%6_JPjyBLwSH-ZG%GNF++r-S}*^OBi?I$%-FQU+F7LEk&M`EL1dbAkD)S(Dvn`* z?Fm+5WPMszOCdl!K#_JMlOzfVXH7M5>}$>bkl)#U?y#mc`glQ3do-mYdX$(<>X0Vf zTSUHQiam@OgGv`CN@8OBV7OE8$4B88*V^Zuc3F1;=~j)P%s0cC+6EjHeAO*fjF!xm zvIEM^y-khn6*?&vWafD0HiF+T*yzq$bE+cDURYSIAywWx!kNKAK}4WX=b5~r z15Qtf6(I;mN3XPPB=Dw+MfIe4Sw=KSj4mk_(lqzVJ3V*Mrm}dVFe@aqnx0sbsfqYQ zc)LE0W;r7YQn_@tX<|KPRME)GaEQoyP{|;*EO4J3N0B9@vEDEHz}=`Ge@PR zjHnNTWf>(mC!-p?@Vt~nh}Mu+q|Cb=cT=~|L7%B?Bu^M6M=SfSYPdEA-+VH26tjmY za9{A9lL~I6r7E5SHU{;Nw{;^Gb#B5@VXKo*18_7X!-6G{ffi(&&L{FW0weOG4CrTe#*z-vTINi`;m1CbGp77p@|}|l?9Z=>9|n0Oqzy@tiVLy zV81TY%QsZaMaR_e*GekUs$aXnB5aJ|cp_H%_R%gi+ zP}Y=AHs@xd?|=g;qp4+gn+QFQ@*a=BYXVRft7b8=w3Qo<@ZLaD2v1VpnZC?DSfvh2 zyrx^^BX32r)GhK9mDNAm6$&`a2+YQR$$AkG4*#)ImdJTN1!tSQQWH)SPNIpJB=!^n z$`pHf@0pecc@w+X`9SdlNT_yIRW9sDKY<(bAC}Xsx9~h zK~}@g>2r4m`YJ1S4!cJUTscc}sTZVCiXl33@{KGo1P@-m3kVbt-hpeypLK{O@wsLh z>k*)&9M`NASQ`xm?#s;Vu;1m9~GGxK=#m76J|KJGOL*Xw<&g&QR) zc%v#G5mJdj4{u*`=5~Ewtb3^yHgdW3v;?V=EGI^B4BNuiQl!6s!bkXuLxqH5&V%6@ z&YR#~0duV)x`;-b*=*PLhn4Ti-!o0Fczl7jL2k}J^>C^6x70Bh=9(D6m}=M+UJ4wR zyNUP++`dUs__&q7nA$Z^&T@MGDU2qIKl~s);L`U~l=e)cEcO7D<7XJO`x7th-AxMp z;DO-Ym)+L7gkm?HRMpLF6Eb8QcRX7mAwidpM7}q3p_=C7F@%)Bv}Ug@W1fR4xq9w7 zqV&nBZ>K3$Jf>-F1ztf~Nz!}T=&nvDHWN078)jy(M4P$o!@0bYrLSIr%nj*6=a1wP zzOUVk&abb#M!^o!kEYVj?Pi)bqy2xheS!7Oj>2zX(gleD_JJZ+?ZsdkX%@dsoG@-i zB!W;Y?Zb9X3{!Y|mw$pC4X9-nAv! zp(6NudbsOno^9@4(MJ4A?p&jf?M*kZy9cvZXyZ0>F^dhU+Q(zXL3FmEgcqt{yeQo*R0igr1Tg0w~LQAzb?S}1r8PqyuZUg%xTPud`y=wOb|%R;t6Yb z8t3Zk?X{SA$3vBc^3ZtQ!n#1HaHomtXzi-oS9+u7cA_oCj;K45aRH>EkEuphh`+DN zxGlt%x5dpwW2t@A!_mXQsBNEnl_rhNSY&aFLEtF;p=Bo06vZcx;2`*QX|38r3Bpe!`4{$|RMa$iG{qh{redBsP2K@wBhN zP+lPS(9vSWE>l5Y3C-I4w+a#Xb^rmno5;t`Jd>ZU-F5}5c{yG=1zPou*(PIlRW$w^ zFPDzfT~agn6Xv<(Xq;uwCEgo12fHRQxdlyM=WJg0C{15|W9iG_(m@`H!~U95a{Gj;md{lJUkPZ>^?bdm>sn||+r^^!`CrSHEDZ>7Z=R%o& zno5i)kIdKe;VBgjRBq;X6BV2Uoya7r-k&61?{QJvwT;sXZ}^kH=i1wEp=M21RSlBk zJE~6@D2nie_JF;=kT-}NVY7^Aso10sL-h2Wpe6Z+>Q8RAhbQ5m#CsYZ5?_y8c8AqK z=|1}t(oFf+kjQ2kq_iio`xr9P(@{wHvk)2Tf`d1k=wRh&V4kHfwN)gnWxP`7hL*aQ z{$0(~wVz@;GU`>ZU_uAsx@Tu%=dcGV%QAqKwVerV@|{d3iOvUn%+&>{B%dB7a=A_kTbZiddcnU7_-rW=$4Lua-hIh= ze?Gq*sAgB*<+b(gh1FAI7J-lvj?#NUlvFD}PRkY&kEf2llzuv&j!(4&da zi5lWv|4hq*WSqP(9sF#-=HVl?;~(8A*WF2MhworIf@APDPodU|EXV305ttf8Bw7FzMdOH!=`hBv0+I- zV#a1TfeIcl;eHfTWzO`;9IumRWaXj4C#ymmk(=}L_xa{g01AZF9Gy)CWgqy>E+^)H z+`$)$=Oit~B=nG%m|$1JclByd18@))WYjage31b; zad#5&I!H`(grqnLrwkpS+Rf!#2d+Ewi`qkOdT995Fp1QmO|ntb+10e>>PaOdK{7u{ z6VBI1D&T9W=URK$?^CE%zi95k63=J4F57FdYEAj94N&9XYczHcr>_hA72XRp6KVyqQLJXJ*K&EobDwir`cv_3B#7(X1go z2evhfU#kc{#vvp^Lk>+sWw?5uR8V^Tv8$l?_;N(#dp?&7tM34d>&LB_8>{**p-~cv zOp3CiBjaWJ2=@dap8paSKkY;gK_fsx)qQTM^nr)O=~KM?(~7tWrTHYS(Sv*g@7{4m ztVw_2u~nF9JA9GiOmBWKYo#HF|MM(nNnsJ<4*{t&?a_z(ZypwZgP-i|h}q?=+!QEH zWK22iK5f8ae#J7I-=i8>wRig78WTj;Ag|m!f4mE2lhS;%(N0n|#bhlTUT6FTV?>Qb z|Dk3R{Tv;Qoy?%*yQ>1RjSXOxk(SukT1)T57lym%N^P`oTMcEu=adYrBm*T_tQEB5 z-r{Z?f&4%8Ca!xFem3CNvx|A9Ea$n5F%P1b^ZM)@i0AZh^HSr*7Dae{aE|^)%J#;A z8n3G9rRK1b)a%!^vl{xtdCp)yRbIYv|H`!8xwIEv`)7XeQ6#w)Xy;T*wuyUZxfe*CpK^-YHzp|^4u9!z1Di6!y%dYJ6Ps=OLKgFcu5aSa&CRXJShbavKAnGA6@#4r z6t6lCM8{e)f`#ng*illi>-hRGMVvyn-Mz<8fB4@7+@-ZRJpTG%te2RD=ZHc#77K+o zg?1CfWCTtv#B)rG$z7*KMXS-{?`VDK`b|vC1l*#T)b`o~KKb286n(hsbkf48K$Qso zwZ8>W7HIa=PwVOQnN!c3>o0||KbkJOD&pWHNxQbU`B70?Q2{?-J$W}y9?+5Htw1J) zt)im7ZYq-ZfTBv9Gdusw+x;(&CvTe5@?r1+ln z9ti#zlCl$4ZBOWt$FOSk9kF==<+8?Htp`iTvX@xxQ0VVu zn$IrMl1w4?-e;feGV(xh_hpHu1=F7|sa;?R-shza#&deRN)Z`mqJeU9ul53ZjE-;D zMqpx28LJ_!pvFpVvd205R-@~QY#*V4G0+kMdkR7iVlzbzRP+u`vNduhT=>4R&eDpI7NbtO!~mrN3>W-TZ0ui;6^|;Fh94Py zMQdZPAvuOm-NZMk0a%JlM|#DY4{ohbu^@?f*8e%1vRLTHeCNe>N%@O_PvS1}A1mDQ z>?m&9?MRiDcf6J%j>-DZqqa=l%C>qu^PM&)8(gzT#B*x4zPNEoPsJIUF|986LABfaCb=F5a{ttFH5GVLea{1vannj&yA!Wpce6Tf}8GL*ZoaKqQ|2$YJY- zBJU-8eg@4`vzo6LLF^e#uRgB_SiuFQUW{1tR=v-?HK>hMRbQEstl)2Ugf7qTojei3 zB+n_*RDcle8VY&sSPT0_qO#|vr7?myi(XYTlA%ELbHEL<8tAqA7$6QVy@t4vT?*4g z9h0ruvw)8$(@$V>6Gt&>ZHyNp>ydA`kmRp69Z@lx-_yM8-h%jUUw9m>@6>on`Q0_#e|6*P#8Xk?;S#u$(6($jik52=@~3g#P%^Otc6!pnKP4F$o4dPT zYzsHN-NjD5gdEMC3#|I;JW@yVwKj#Q28z$aCm>p1s>-xZr=w(alu7JL$WYU0YFsP|zY_xkn} zV!t5uI`si!TfqcZbE0!*di|3)<})Unyw_L_>L~Kf!NqCMBeWx`SO}V{iK?g|nuU%j z5|Z&Mp~ce`6$$?73VzvnEPUE8gTH?SiE`L1CMjbro&Okr6Yf57xS!~2=p_})qC6&j za9%3%GrlPo$C-)^IqhkzSc~a){#3q`eubLQo>XKJzZSiqs%N;nf=cK#gOXowfdVYb zD+g9K=dNgji%UH^y_j(*YwDZVReIjluYXD^a$7IRG*Io>qe%0D?wKxCk~EpKvx~IB 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�Qxg%Uw&-*G}cIx)@OT*fb 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
8JgHbM9E6x_L5&mnPIDiVXVc9)4?=@J;AeO zL2OG%m?Lp0)euXn*{GIuQn)o6%3KnOSR~@zv&I>4P6u1u)F?orD4`I@gNVH#B@so` zN`gEyT@n~nv_P&{AceT13|PVhg{c~K2Ee{!{c;^d@gGrXF$Aa!1|Xy{#6_wzihzh5 zL9D^5Al79nH#4L zY;TE2xCy{ReIUi$LLTFcqu`p$8Xvhp7N_5B+}L zTJ3rZ5YZj5t6IdZC5TDmCS%k*XRP&}vGM&W0m>W9cK!&#j%v4yJWRNrK*PioCrXuz zsfEP&nP%xj%yb+^4@^qy$q+1F-OLMOM#F}iV{EGcm2tAJVCey1P8+Ij6^&=A2Ca4R z5TMP21_*XAg+s{(nPCHi_9#(yv5|A!mkOC+impz<-8nvBA+`iY)%8-&6{t0v%M$J_ zme*x)^)Id^6)pilHQ=CQksPoKP3G_eEMujB*m+JN;XP-p!;jWxmaH29oR>H3&QElOLEGh#eN zhN+ZBciX7IUyTbYB(ov0Qn(Y9cPV5>q-pfc%dn=xHUpqHF}ml>rAx48-r-Q1Rqo#7 zR5;r!%K)HzIX*ncG)2L%JiwJ!tRT-g6s9WgO0~Z{PF4e86P&PAgSF_4EdgMZ%XYzS z>bLeo>h5w6%xi=`gr<`mRdrkd83NVBC2@GbF)g6KZ9@M5D-1ukgKO!*we{eRAK^G@ z@r9qkfa!k^&<)`H%l`n>zj^JA`AYVHaKJZzQ`z-A--v(BKh#eH>NV*uG(}JjmB4?t z1OmDL0OsNtUxXfrX+I2PqWmK$$EXwywF2T97HmWXieZs3F!vhyp$po?$Fd$|PQ(@2 zaHs_dT6>mU%H7l1G_Vd!p3=J!@+Yx9iR?tC$+Z9mmDuqM$j^$suXi=cZ54f%P;OF; z;vJC&8Rv-=bIlPl-Yyfchc$37QC*1KTke)(4#K1J_9Kt3#s;*E?CXQ?30xz-3!o5yTXRvEnuLQoO zIq?RmT>`(>2py}CwRaF4TnBLFYVZ3>s)^ZlOVtqK%KXC)!J`DH7K)hHfN;Bww(mIg z5H^~jpnY>G&8qZ&nTi#-cg>!aH^)_$pP$#UoM$ogMq11sL4q>hFzIhcsOs5gh!fPs zm!+uZKT1F0a7LQ_V&;CldYAkq`}%XY>&03^aDBxZJumkFEzd#x%^?2(r*YvAU)=?0 z8DpS+b0r1-yhDusAJkJHXY`#PSM-Mm&jIxb{y_!)=){lQKim@|f4?z2*nh6#w4Xoj zRsHYo3#Iu-gphFL5N9;eK@u8K%V@#}FwqE4I8jl1pMFx!e&5sqE!sN>NV-Q1!@$jQ z`i>NiX^4?$`h80JKi^R!{hx?){{XwxNBh5Mhx&hL@c#g#)c*iW{ZI7&0MvND*Xm{e z08ip!{{U~|Kkfejh%U?h_?~}v`i+>U+xnb>`F~Jezt-^=pZcC5S3mA}mgnU(1+s@| zedD?M!VG;f-;qDtn6ZQZ08Zm$WOx2aQU3SbZ~p*G?hbSR0H-r10pWjg?S0Sgdar-( zaDG?!JwLbi9VgiS;Z|?={^NE(*7Gp`0IBy9b6@&%Iw#NfLj1%L;fDw5gDw6sV>tST z>|qHSl~*uBWE|J%VH97%aAlf3!Dsm*g;m|7`9ioT&ADcqjvM^PE0I-`_b%1DvQ#F= z90b9xLg~z;y)B`qxt5?}iUZUQkDGG~0AXoE>LEaAG{sW6vnCmtzM{xx(*Uz&Pz}Uu zA#RxNDo)5^w=keVF~juze?+yW!IsT}#`e$dO6RBMVQg)DN)VNzsZEs-q9wM=3^7M6 zN10K#^i(Y=)(BSE9ZSk#8kBVaY%?p_10*TQ5k=?q5{#n*6%cCT&=IyST!5&HnC8P0 z%+FR*w;3o|V`sU6f6=$7Evzvdqj5F5jAvtnmj>C#h~{-f;y~h71@+h*@gH z%)rH~OpFrOWc8V5rX5VPD)agR6v7yS6vIezYB;MRY%w|nJAo~ixJIZ(1(3sW3PQ|T z_<>Kg&$#o%(OZa1I$X*0B%zP-b%~?cQmphusIwI0tHGP%2p29WW_{V+pW6p zxFzinD$>*FnCuJPGyY-0Swhg)seYBL-h9KioTEOW5mCe}_G4U_ec$3#YETd+a+yK1 z%=C|hUYNK9#Gzw*%($Cg{^Pc$5w~mvQ8bZ(4GdF=lxViFK+&TNGhIg63KdQw>N8y? zATu`@DMVFgU!WHLiiJExL5za@$3m()U|f0vHL@(!MQjP?KIL2bD1=aRQQ{%Y?KDg2 z;ZeJ3?r?-3B0j`_5c1QHGbnWUV%sPeH!1=89)=-I0icv28i5xHs1?~L;!-jzDUsa3 z%0xx#TxJE1YEr3!nB1k(MAD;Z#ZwGnF2fNm;sj!1)T&}KvoT^K>4`{@CJdv51Hx&< z6E0EthG%FNT91N432l#yb06qMsWPGfqQgS}020izmnX$U5*vaRpjw_qXdf|T3%cQ8 zJ-;9a_Z%vQ+rJWs*;qs@0jHuqZrcX)?})vs%@m{fog&`;<&$>oG(%DMOi{{XcC z-M>^4zs!G9hc~DFOxaIg;XNn%>Q$xmVdSA+{wNk;e3Gonpu1P0Oz!$$-0UBMQL=zM zQ&hCLKPV;BcbpGl@_=k5f?)e2%mNEgE{)Wugpx*xoHhIYiT;-Tp#1*;>8O25>3qaa z1e_r2d7R_)&+vvH;n`>Pv;BsD#bpit{8N7@!v6s8n7@2~ss8{4{-^wh`iXyA{Xjph z{-uA`{{T_H0rcO*N0-O+M}6P)>SnL@y-fA>e@ye9zpiu-*YwKpXZa#skT_#l;sKJE z4&joDcPTo@7O>M}S<&E0jG?IqnPQTEP7NjX|jPDZ8&LpYK1&KivNS zsEW`$Xz$!cBxP*JA2yq$BxM!IJVP!#f{Ql!js@*(_z6)I9FN$t>o^fl#1<(du#($V=;-GNGMVT#v)tV^#_!lBCrJQTY}0Kt4pfHtUIR3pTv39Lm3Pf>{z z$LKPVMV@>^AuuGPw}s{p9XS{r#(sdPR4M_~1F1<#PN#|=_@MHBmMxRjDcLzJgK|!U zlr-@F8jnkK;r9 z8Vg@qf5T7s>Hh!?KjEkRlo0+DM=&l4nhG=Zr~G990Gyxlpn82u-jAtHkFU|=7y4gm zu36^Kf74l6Sy@?GSy@PlNQjtF($ZP9q5-G|rH<{0w!R>zE1-r|OZEAH0010H%3q(- zpaSqY^>aH%7s-}_BGfhW5fuh3FKk3?xXJj-a+Wu<@d(O>g#{k_k0~-NSLR*ioUlcR zZd#Q=s;0@PObccI0KOv?LkO7i{{T>sz$&XyF~DK9=!4e-hiCT_pB74^(V2slm$`~4 zGXDTniTWpE2Yex-p2U_(+~N3?g2&oJ$G~1-Ig9!u+#8q(2pAvKxpL3_;#8?pph}hc z80K5tx45rt&uq_gJ+nQrdo#?3kqPwB_}hEr8Lu^_3A}FhGQ$UdNwMirKZ>DdY51 zsZ|vPQuDmQHcR0N)Xi^X#z-;!nMx$PIQmK~a*imK6hpMvtVS^V#vNZM0JL$V|)z5~<(8Ei^oh^l_44*GITAELx=5%HNzUIq{=^iTvBF@HcE z!Fhr10pr=xe{{6$Uf+Q3&AgZ<$pDWGoHrviypexe;glJS0}hbYbNRqgMxTvc5>dGRYs zSk^NSbM1On?}+!Tfnt;aa;-1i6~@6@qAkW49k296D;mh)A29<)p|4O#a4e1tKlMao z5YKcnXYMUg`Vr^gL-~(aom&oyW`l{-kJK*%pvGG0Ifcd#bz}{EE@u6&3Yka&a6aH1 zz&V2N^bW|5NDnX{&_7XdWy}2+E@A%wkYR=tC;*P-xH(j~xhO(3Zpn%sa6Q6Itd^4D z7|sW55G6zZ0E;j5S?)ij#r+Ck9K$Ra%^7@7QexY11X1yW#IC180D>3ZGWwW!y}Ym` zO8p=FWmiGUdGjpB0>FUi9!mxJh$4o=rw|(3N>lLzBaTt?5&*Z5<@MA+fl7A`fCbAB zmFLtzpoLH$h`3;?Kfi3N=!0)dF(lmPsnkP5!Mc`Zbz~phsQVX@I6Xv6THCet8Idll zA4DKEd5)v~1SdcE2%Sq%aVjI3oNj4Or{+vWlxwylvX6krTHdTmqJxSVfLYD6^((f{ zdYD2r%*zep+KFXb(|D~7Tse+|0W{d@pTPT!R&OOu=Jduni`=%Ymz#iudwz=dE8GWg zyriDey~_6~+^2G##CH?iPjEYe2D^bYPe?f31>}cYhh(R4fL$;Whx7;acp8CRFb+P* z85i{r{x9hN0Oex@LAGN&;%DfVklM8Je9NLND!+)b2L^%W7=Sg-K65^Mb;h1@ThNY~`yO#YK;f2?=5QfR^BtqNk zFWy|&T}E5|PjPSuyf8J+*ay>8-z>MDCHlu#AIvzYy@2^8sV^2xWFqqN{l=SR`y;O9 zqxukIn91yqWP2jvP^e?re&(z9Mrfu5Ib}te^Ebo`b5;(VTuf9^j0`aCD?(XCQXHu$ z04#fj1%#+E`lf&JQl&(RDV5?QEA%Ib7Zn54p&vBN3IJI-8DOYU9O!NL5EcWWqBK-g zx2KpEaOwh>AgT(rDU|gQjml*`N_zbq*c9maCVa~g`UcoBQI;s0pV}}O5*LFyubj4Y$d>GY%p==3r5-tx_q2OcLd#tq!Q@Py#!led^UF}vV6F4 zWCJj0!agr?1+ef3h;8niYy8SqAg~#WnO+Q6thkFJtT6q&zMyDB8wFtrD6}8S>QtjL zEK%kST{^3;z6omsK`}>H+A9mpzmVuI9l*D+m;wYPy9@T}4jA@h++t9ozs6!LE|IbY zP=-_x_tZ5Uy8i$qseVmAK{A?n-*scn`xv!Beal?>Ym19Qo7 zmCEsHS(X}qaU{zn!S+2DE9SmqNSi@ri~W;<%(84q&{NX6g9`!Wfa)&sEf^@}&1zZf zEkPC|3Ri%R0S5`pP-jV9{LAB87S1;i*_4WS`|ei~!vz~$OHkHTDa1-d#?-2S&?!Uy zpwGn~0{qNXuz~P~_uv(0P{;|UnuiGz`x72FXsf7oCt|ZH3?6Oen5$OHEZVJYcj_!> zh+qe0m4~?Vqq$MFSxU^b)`el$h_DMZJWMQU0#H?8BnavX*a^`@wMz3Tz2Z|Tl*(mZ zM-sftclehu+$y)OW=(Z+`l>z421nf6Nn6Q@fZph&y&FBneK9mO!o)>L+YCYw4dzmf zy#%LVI-5|zhG^Qf3BEk#gV75-pD>YHqR@u`+bK|?!|1?JHI|YZn)nPu9`#~BL@721 z@(6x377sN2CA6{CVpVn1P>Jj9O-A$Ij2#EV8)0Z@@(6YAAT{0s`d}gi0Ojr@ZhV=o z^2NY6m3>S~0@OHSV(l%VisAx5uS_2LhAPh6HF_Zd)u7SS)GFM-Du@8J8Q34(tlkYF zE1a;oGhxbcPg0*_kZk~MK$5@FP^QPRzjQ%tToJd$L-4A@c=tFjRAqaKuF?CF5Ve#l z`iNp|=3g*BDg||)GRrdxwf7Jfd(wPa8;VNb(;i}Ant%}kEN&<-ZbpXvAIw$?k z!DInKvK>lcX__jfV^~<7GUzTHxkxB=ScXPZAE;gv%&P`k$qeaL@XGLU7h7Ew$!0?r zD%YBn)o?0SXHgb8zll^?r42JLXi-vx$}7#>D8ub@0|VR$mQj7pvU_H$qB-3>nScu; z)B>%DaMC<5Hk0Lsi2H+kLAWVZlIkj9mxyG+UM6vNaDx@4*2?f^3Y8X8j|Xu;Lw9SG z#ui_};syhBvQM}aK`xj*%v!7?M{Id0hBL)R&9>FPj}W2N12Hx|EJK6LT9lhD3+9-F z04Ob=o5T-^qPBFgwHVM6z85McLmRc@{KSV&(Dej2GN`9`aLmFbbAli=P4B^R3fZGi zjm?%7p^p}b*o&24?puh?Zx=Mca`W{Q?;Fn$5={^irf!t|6u#vDKZwJCC8r_&z)Yq%5WQt+# zvb*_(oErk|<~uAAUPcN8veAD8$S5;-A#%!WK2shz)Y|!ajtPEG=2EQH2+8W=&!n<= zB6_OWtMEf%gfWD9>JVyL77!)%tYKjcv=Ltts8A<_?Sh2n^R@m6-Q^3Hm#DgwL0XIE zVhHWy+(NViKCUN=u)Fy%aT9}ya#&a}>6lP7JO@xdR4`-WUc!1{d&{inz#h^ausDgc z%t}(lbM1V=ajDPBFc?G9&o69R#T&^JxHQL7h`(&EHNkTQ1XC~Na3w=0&!{#lz?pZL zPz`BSuf5I>CA0XNP@t>6>N~6fYw-YQEQy~Hix;aDdGQ23g8u*sjbKEgoVr*j(YqwZr_ zcse4QElX}Rzm|`QV)d5Wb^Sx#lSJQsqHA$7zllSIEtiQ(DGDTpQz4vsg4Mo%v`u2)0(`;PItwj)#Ndo;Q{tkq zH8Dzk#B4VKeZXy2DdrVD&W5H`msOcw2%%Ki9Qc9JxolbHq6Nu@%zN$?J%HGHQGoF6 zdxC@vyz;(CBsggpEiJ~GKcX3{29=fT%qRj5>waFM8xR$RU#}5#MSL&NM=7^%cJ86+ zgJnP`5YhoDk^Go3h~Z=*b%Etrrj?~F=2K>^t;OkPi`Dv;*q1gpEp?}pDFl?pn%uxP z4oj!R&^E(%1S950u?-B?>IhD4pmO{&_5w2B%Ur~)*G827rsHL`*Tu?4prozKt1G<8sDNFU z?2bgl?kTdkV+|1nE(cS}B{x;c#LF`0vo2^0YBMc)ZH`bCf|?=MDmdk9FnI$?VX2BG z9If1TQkA=oWVtkV#4Tc4uc#^7&F82f??qweJ#Iw65p0E`(D*G4#jupVWhH{JJDj#b zm?(kABx!KU+j_*>qQNzKH+9mrgIh}Yml?)EC?->W;RfDM9-mXqATBwK(-wq zFbK^+6E2A`EJI@EFb#B8ZJ&N&yhYJUCDt>nfl#n$B33Ns@sK_c(L_x z4XCQ4PUbR8QiBm&XDc(MNolCTWcV3RkmZ0Z3r;Nc97~=M!kWP{IxW>h?3IHAw zEXi!a)DH@$V=Q}kfB;hIW1wxz*R};~4huXH1ubDu<`@*sxICAbl}QzmYFk@=L63f5 zBdMU@v(%+kjxm_~QX;?XZL;2liy(shGJqv!R#U?$Zp5+Q+yRhQiTz9?AS|Rj#UMGA zH^Vh7MqJJI8@Razmrz?}vvDY?NXo*Z!tPJ?mk7`UW89!14P$SH9-Zmn9L5y^obv*x z1PwmJsLvKz^~b2hmn&dSUS(?oVQKdX3UaI5$l+dPgqgy-nJPmS{K5bhtp3jvFDSQ& zm3puQNbG>HpVwU3D!ds9d914qzTrfRy-R z5!`4w@|dzZp`U;9E=I}2bxc)v57fv?kxaj zQo$W5+z}3|+(5kbaox7dC8r?gSLP^y>Y0|+t@UxXZ!+Ag7X&SqAka=jxLyOBJV7rC zGc5^<9#@-yTfk_lSt+hX(dJpJ!5IGlh?J%TvZ0h4<_UMz!~;{HpAyxt$jlb%*kQ4L zU|h2%>FyD91`AMn&R@y(4%0-Y*l#(04QZf$RJ(J$q#h1SbvyNB^YQv zr_%{ftA(29b|^eS75C6qS(0qG5AHQ^wY``MK{i$&=1^P>_F(K@BZy`iR@On>B^k8P zFIi%#gbZ0(hd{EnrXv72OYsV{8q4tkJJt;DA`LB(v?`=+Ey>r8rH9O|tC_Gq!|;hf zG^cJ!N1ZdbDPK?otsk4GsK*z>*0}QwY^eN^G3{Iy2QN`dHEo=;vN})%hcq0(y`-_1 zZZ&WjNqdGjG~Mz#I)+8T3o!QuT$XJFS}yFg!=**s(MPd~OKCf;O57__Rw#@qLyk#K zvmKI5iOz8V=fq)Z8hL>+p`i#tmlEmijd;t>4;301om?3%I#jO_IRy z8j;(o*P2OCrJVE#L_XL1ODgc*idhr}Go<)(}L}odban%}#!`mxx z2!dUUZ>e-V%IW+{Z5YsmlwiQev{w#*5B!2asZC`IxB#JNUM1N0IhKgqGQQ!Y$S#3} z8W70jlxhbe%j$1VTTKZNt2QzZaN~<^#HfNXwX(cMtcw(N^$-;*<>{GoOeR(pf*@?yGhh_aV5dbA-wNBjQJ51$jJsyABeE^RkX+0M1Ke=5 zwW^yXYw~G<+bYDGzwk>xvK0uaYRQw_LhM_2iCr>m?U=c&;EEkBo2D*Ghlzrtd};x? zyl`qN9%1S!C%x(MQ@U9H01!%rYZ0TJ%4VJ*PGiI}l0IN>TTm`#|oJ zaBxFZN>SDG5DbR%RqkDY&e~V^6KEJ}1>88*rXrUYb{Eh@Dqgau<|;IF4KUah(`u{P z<{)E313~7<$^>NLPY?oJ4;%Q22bvEaW;QZ`-?loIjj*`8%VE2w3l^C`*l%vcEF zQFtPV(AYVS6!51BTW*CXN#2jKW%uCT4r4;LDsd<7Ka%DtNuWxZ;nM${qgT6~G zM0arjrr=99O48hQ(`vafGQx&l3-K!rZeM#*=s1*V$^rAg)CxSLABS+3BFL}g<(H(6 z$bRrsbTF;PkO3(m?wM936<&8*ixa^b6(At81qSa{T&mnJG27xb*%-OjKN5yxQ}Lr_ zC}6$$f5fV6WU~0Fl7gzRTKCkmh+R0nR>&C0Q)IC5HlsB!b9e3#U_eUw4ddJ-AwgZY z!&f*=27#U$?z2gd+g(f!}YKdeau1uOy%WbcmP1P-Wmz-(wA+ z{oTGIw567)^6LCbG-z8^+O`7=5sO_buQ4i%D-x(P09H6UJj;;;HoubvyMXN9D!~+_ zOR~DN4Bs?p(}MVx0rk7eYA9WF4gAzHj}_C`1W?<^M!>?OS_gt2v(V<|nPOFnI$%B{ z1zZkIAGswpA)p^gVo_KN9|xG3C9zsVnS~c+d4M5|rk*Y;W+9wI<~dlzR*!wb4RWmu z0z^RBQ5xCY)7%j%EVZ8mSH6I+<$)6glKGTxSF_-kz#e;<+8&^kMZ^#?qH@t4sPGpn z6<8MPTqE65n`}m!a&dD9EG0!f&IO(Ym3Xq z2o%Nih8tvHL(Lv)6heU%%q-Qg;w;%OHN--|rqJq~9%C((gm3_Sp9<)+y(yt zDuKwpSjd~7>_aX{Uzd~O8aBnoH#s69aS>r&hs<)|N~RBT@)wbOdY6veTGi*MlZp)5 z%JOp>T}4K1;x@%4rwM8<8(_Ul(V{iC#qL@z*FZW#QjK9%>LN}o7=+B{fhtGw4~Wj2 zm1S?4L>|}}3aN7m?*QhEDy4C zUgDjgS%=K0;$T$xTmU5il;4|}8K5gqSNp?+wdAi5?v&R-+Ef9{Gy=v60Ma+y6$UFt{)k!2t%gaol*-V5h-3&%gEuVXEjmwP zU=3MgaYE71+E$1r?6|GbIwKTPv}oLAO|U5fUN0zk8tNrPD|mxq3xrj`GmXtAGXQC7 zeM$oSh?Ox!%G~!Zxq}5}3be|`ATSnOpvAyhU@BsPW4KXEmn`Ap41~(Sz80nrLNNwV z%B%EIaA>S*&f+(rUGd@{vq_=MYbLZs7bb%e4IpyHDIHH#dFLTE&ybr7(B~6m5g0uH+z@306x;qGQD9ImBBM{z4)!m7MwZ-GL`itqRhLS)xA6!FXr0#X`(Q;k*0SXElu=4+^6OD+q*h$aO+ zKIKZQ(5rZj7Qm6G#B#g?3iB{x-2*Ic-tzf<%Ck__zNTvz<`4q=ms9}=)9w313cspQjl^i8(n`u<{8A!%-#I(ymH|81ow`DPaYlCrKCz27X zN0-FGS+R4UaRUwVdRcP?9tp#i&Cvhnh9T!r0uSZqtmC^mawN zR2dE(ox!(ost6U=K`>J2I*gX-=4e&Ha7ep)WkIZwcPmAd7fftqJFN{_B zk1P}o2b$ccYl4f_{^&l7EPNJo?SzG*$a)i^SXd!f0#M(anW(eq0SzwMI&X$98W$$( z)%Q1E1fsbPn8@Ytx^l6Ii)gJcM58et`hx404lbB<5ZTMhv2`y%E|~Q3D&!0+mKzNU zs{Z9)I_8H26}fgQ#MQtJnP+nf)fGbVp%WrIHe3rtK4+OrgPNtUTo4;nvg6;WdsB37 zr3MR0OFhH`o+Y+aDn@B*ak6f0ZUdotYnens`Fuo(uO%*MDrO?O2$_|;2xtHi-9U_$ zik9dh3Ngtq-k@8E6J7So8WfKs+YwNA(<}Eagubwq@h_mI6-DugUxcsCjrE!?FqKQY z5rzH6+Q7}y{$n%%DZczgJ@X0K2Wu?5s)!`uTli6MhU9bRARz%QR8Tf(3@?W=Vo(6S}3xneT?o`gQjhXlCPMjf;Vs}%*Y0%RV^%GidOL{9r;!^DSjrYa{)7MQj9Kpn6j;eSAz=M z_2vd>mvyD_6eyZFo+?`$UF@(`06QpNZd8;2T!+QxJACxBu#1>nwSo~qF?C{elgCj_ zcT*DUNAi!YmZ4enO#1+dq3WHIkm`dbrxe1}O0V{Yj7{}g9 z`mUfVvvT7|j1NN_3qsct_@JxHXT*H!ySPfqCo;yg_biaQ$KWP47r#9OPvF|i<&;DU zvyb~96r2nf?J0HvzR}wmZCr`~@o|I0kmdITGe|j&;_?lA!T|?FQG{nW+`QB-_mqB! zOou|_q}gCk0)l_xG%+eJN74Juw&_JI<8G`!Hv&X!FnvIX#cj9S+aU6_A@!&4L+lo0CP!Pprgy;QXIz34-n*;0o^lJu3)Jky&^!`tu7rY zeL?F_6)qNuT%$D>|^@#Yc7#51ay9mQ5Th>=L#+f!%1;nv3wjNKI_OWjbM$*7z6+ls0NA(;S zpw?Nq0Sc{rj1rnU6dHY84_K^OS-K`|2W%d4#?1k`?oisGQL*tJSVFoY3COsGC0uZX zR!euqY6Y(Xs0(5@Oc+0upb(;jH}LhcI;Sk^HF$xT;ND79MPJxZo6 z9hpoE+8cPTCtp7r^&eYp*HZ9o$wUBhB3Bp);Wz-?P?p_w3WEf{pb2)x>#1Dbq$ne= zGN)c3Qjq0PKIIZA70DVjVCF3Lbtxe!)AJBMAy-5!&MSF7VqR5%!Z8p*WuxUTv?x_8 zUf@y|IjK)kYXOF{PY{5srNmzm>5^N9(O#e>9qwc3y!Q1{+7)2$sKmljj9-biszXlh z2x2rA)7cV4+J$eXT2qi*dlJ+Wkuy+BL1glIl^{n0x0pGgSas=$>PBTRYn|ma+Xj#v zsFSiJ1A`xvnQFh9WNz>l$|NU+D%nc~F>5Roly-!wp*tl)3@oF<65A;N3Ky=~fD)bD z(auX;p~Td=MdA-D%n;G;JBtsP72TKw2K$I;`KWA(&bJ-YvNH=Kqjgct?W!pxKRA}H z(}Vp*sC}CEP$_NZ;NLWE7REN|ipyvgdwfLaY|JyQ67MVJgMsAUcLqAGt<9R!*!_{5 zlC`vaL_j=+egYdx(Oh;uU|B?=EM8J$6{|Kvt6dI4K9dsxZe8+{7rVrylnOD&9tjT`GkS;BjTX#i#vha53z$P8s=KUsd?&A zpc-=kJR*5W#u1w{Y$U}(u3>hSb*~M=>JNQO0KIvZrG~Y1#6Sk2GXDUOQjjc&7C}%B z2XHNPUJfJ7FQNwn@|6JdRu-b!!ml$q9;6ciyyH+(88F1a@Ie3#Gfp6&iC530q?f~z z#6S{&s)l$3O~W=H<_jor5eY!NvEkbf4~cY7Hv~XbMxaI)m8<*9r2{!D#qkW97LV-2 z(P)CE`k9IfSx7uUtF{!i@Jrb&ruIOnBEnz#m&VEf2T>S|VD3FC!n)6%WsaaSIDTMB zYXZQy+0fi9fD6Jp6oqyfm4tJMhz0pjL(IU5Qcy~YRJ^(F7??de^%U@wkxZ*oukIoD zV~YM}1>m9eU@vlp25thd(jk?5fEsT%1B7l}zr<4US>Am0GNlhJmeUHTR4o20W}j(= z-EJzN%LCXWwdOmid^KgFG%mN|Ty6n(NkZ&;mg2%iw5?_>ZYfE(%tFDB69Z92qM><@ zBB(yvn%jy!9^-|W=2Fbqt%L~A%9@w63&J53Y=ZV^g*t~w2QK42(|OlAvhbG#bs%iLR&dls8}{? z*Ma9gA*$gEkxw4uyQI|r7s=+%17R8SZZ-AkjQD_$w$58f;I9aY->YAm3jDba8z zkVF>M!QuuEE22~hY70!vMx^4tek0q_ZxZjgz_XrEtq-Y#bPRNkphxQVMCPR;ENQr) zSq!@-qGV20fEAgL#puh_9RvqG{KeXohWbL{NYxy~9?;5}jT?CtnNcn5hn&kp7yvz@ z2l%Xo^i59|Y96?Y`m0p4QSyLEMrOj;RFLShSdL?W3}#J{Vm0QglqqL)+#6HP8Gs^6 z6HeApR@EQL2Rqrss1y|? zUUVz!56G!SeIu|#8UZLHXTaUQYpG)NX-pO6iWwVLyhOx?DZj+0X;p>#S;RvMM`TW* z&;Z*UOBTtO;g&!f1yaOz@oWo9;?7TN34+%ZK>q-JcVC&2LI{6i<18E3hwfni01@Zy znV1aKGnMG0(Sa9uY%x)LBxYYbrp*vzG@vn1>@l1b;FHQPTq}N>Ai{WNQdE4=T?sH*21Mcoxpv15CBnMLsde34zyZ5z1E8`OwhKVJqquYz4ye@W)$W2mEt6>P043ZmT5As;Y7Fi9>+EKa?Qz8DVpi zP+?Lr>~U~R+eD75zHu%CX;syFCdDc&v9SC`0^s5uH@F}PHx(}%Y}^u6#8j^kuOmguD%H?i)B>nr%lU&|ZPn-E;l@>cAbPD_ zqMhDm3DH;%dYno&!8=ma?73q>Mzc9O4=B{rqdI_1L5?tS!-6a*ZDT4p9v>3?BISZ1 z4&VVAiVYEGPr#@&g;kvSsK5%ywZHBaNZo%Bf`>yNYUU8B4Uo^=V#Q{V2Z>UOmW7I$ zxL9+kpvr9PxQs$jq<&@t9EAH@hR~aFQ2CZX0`BsAnLpKNk|4sfEday`0@MOn4J2fW zxf@Ir6Jviyp(acff%8znCdZ2P3}Jw8Jxd0*Du-4;?x`I@(g-Nv!%ZV@rOn@(;UN4I z7vU4J+Nw!Oaw!^V^$w(SPAKe@BYM}LX-8!O%H{DkK+Yc(83%0#Q#20%it_XjilrW6 zjqdj>fnkY{yTG69sSWh^8=HA$=i> zNYQMwf{n1q$VzzTX&Sp{Os*O>Rk0!fFs>!YDv{Kn^l0`m3ZU_bwSXCrE2vMYDqd<) zSPi_vSPujR7N-rr5XxxwynBWoR=~VGKxWH5zODk1aW2h8pwI&X0B6dnX4`=IUs35y zit~~oq$Ri>ASMn<3B49XTx#ur;pYwX1jMfL=L@c&x{q8-I}!-l?ir*R*mqpU7T=4q zdkAa+yEo+slAN&JxPgmFr36BJ+Jt;+N^c&1B_4B$ekUYkEqj6ui0g1sc2{@W$aro^ z-pa>NfSiP+zV>T5@?s){(>RXoPXg9~@JD9RMPcgUl-*)4#HTmWc6R}y=+TYLh_$NS z%~ggHy)(^(o4BBZlcalqB1&I>mt7E zQc;C`O?9MxCJWoV%>i=0V`$HSiI-Dm9#~B!tN>{MKH3qU>N;2yN)Nm~$17)vNn3Ag z;ed$gD9PLj>V%fhQq6SaSbagL7l40=MT=ij&B|_7AlM>@v!XpIQvS&ndxSFx;2H&E ziAya7J0KP;tCRafzD@Dw2LWMOd`4+Qw>5rh5aXaU4@?nQInaqIhtT%LFQ#p?(j9gf zD*7d|46ASMQYj^+U7lcvy$gK|s1jRp(~`b_O%#{rHmYeSQ!!TxSCkcGV&n)S9g@xA zxZt3kDwXg?$c^HifXP|ht%`2kP|8EuB!;F-6r zpt|-j=}}DvdPS%ffl|A;GM3dRhNlGA#1|rm1$AS@QS=5Aes9DEr3p~9m}NTw2h7U` z%EV}>T7c5Sruwgx)@m{9PE%2L@hd>0X>o2U1gKs;$3sx1jB*~X4&^Lv9Px>o3ku2I zgU=BL-;5|AIJMx=Vgo`xC&CVH0ZOH^@#+BhXj0zJQ3tNS`XfqGtet41qT|L3tz5fC=1m>)RXrRqCtJQV!%5V0NV zt_s8)1951Y>f2%{4Z9*^0*C>N+2w-FO8)=`0h%>e2Xd-&nTWh8IXUonfX-KnCKY7@ z{*YGLX-(8IcC};-L<}}R5vtT;*|W2WN72A?tfcyaoWHqHE9h-Kz*;l|tWAq_8JQ>+ z4Jn6QQfb0)#Z3h_l(!oF*7!$YskLN|yhKG&v}p=31rf>Rh_aztSBOaTDYw+QQ_dax zA_5(N?poFq(+Ft03u&~!JQC9`QEI(K4if+@LfM+;2n+#mE}kWzq(OkS8BwQwe8z`~@iY13AoqM*)TDd(sHsayxt z-fmDRyQ=0ci#lmE$AO`~w=RB|urGO}n@&k^oS*!vI>4wk@SZJSqlp00N#F zv^$JjoNfUo0^2Ri9xhqgyn3SY$8!K|cQvG4DOcs3l((ptK1C*4RPp27yL}5(SkP=W zUN4AXqM-%(f0<&-D^&2BsEUkX9WFQ@2(Q`9X^)`*ax`3O+hKr+j1lMfwA z7jzUEYVGB?T}s)zG)j?gtg70V$tVJ(y07LAV=7j1Rm#y#)E>)iXog#n8k7K_fS3lmi$`)BgK1fI^D)sfzz8uc;FllH zGQ%KeC2;|GeqYogZ>|~p5y~sgwf4lmU=h=PU^pvD=ju{erC^EX^(_mzOZPo6)qj{Z zK&uUT5DSn_Q40N<1dXy<1U%*8c#}EOe>mx`hO6#5~KyU79;f^zIy@aNiFidF3vm6u+`CE(ZaASArOU$mr|N zHEYB28NeXqz#AUmQmECNM%iW_hda1_8gmkkUwL81r3 z6fhtQT8CC1^DHLoHdj&H?!yer7gj(g!3JdRa6vM%Z5;W;K-A*fhr=iYJOxUVOXkfm z;t5TP;^5iN!JiP6*rYDbr3K~|#pWMO)tcEW00u;|+h8MqTtyt%ab*spg@=QL#C{7@ zj4B<3uwbp3(0_+!z!l%Be67NHwd+5OBi)~!#*9e3O|BKf!sKq)wN z6d}f!h>odS3ct{>X@hJUln-r1O9NL4N~1)s>>3NIly&EeKXBQquUYO}>{ZyjcPPXg zOWD*3-7Y$YhcQ+dfB@!OfdT_QQJ%gFj0;7fF(wucaTG*~Z-|-uN)`!dQm*1Jk+?v< zB~ZcH1Lj-_D6q{+g%CdF{JNlwMCl~i;jzc>5&(c~J6K&L9LGpL8-@U{K-&71P-vlM z*2*&*25aIkaJGqj{?XF6SXlNLBGMj1Fm+JDJS>$xjGFkY2f0o?gGYh3Yj{?b_XaRE zXd{{(u|!*gxHgRnwVoKfai!I9UBM=E0voR|a?;vSa5WUstPEiDGKVc1B@oLqh9?4X z>RmNg&E*rYCE;u8ET_93J|*K6Ej3DztYxwZLE9&tuGsY1x~c_nNXETvz$Wm;<};FlCDcCm;`#s_h^q5PMqZ)3?> z_b`;$n3lK{T+6rAxs+#pK_a%ol^8J7xggLR#3%2}OBW0)PT15G8{% z2BY_FK2I#{Dn(P#Db8#(_?MTB&U~Squ?KPLUu*%LN8$}xQnq81F~X5qam9&-N`<_d zjfEWzBed=-y6nM21CH(#wFP_me<1-dmM|X zoit16gF$5h)Bu2TON1H`6K}Mk0{nsZ8Yo>0Y!v2_4q$U`zNI3PxaUy})=Px`B^*wr1VOMbdH(xw%=?<4HZNck?2tmj;1^*v4-sY zz!mZpadF$W`-($M+ytNj1(lcLA(U*QBhPVE@EKK|VlX}6XUkH8D6qk$64sKSEGv2$ zjkEGNg0*SDafLFm#G-qtm|ssX=Qp&)PF;Wo`g5f^~&0xSq{H=2}_lHx7|T>R=)y`jC>QDjJk0 zI16vYBPwDBQN~lDF1sRehV#J2qlZK8DOgmN)8YatuFGT8Y!}JDF}QKzRBkI-HYkp( zKyh@G!46CSH5>v(<%?^F$58>?Yh>|qkx|K1_XKf+%@9R*67%ea3>BxBn6jXv3d{tA z7zPh;%AuE~mO%kY!d%r^xrtN}bC7}!0-jO1yT>;&jAV*us+~+Q*%7=C2Z$=7$gP(X zKUH!pOh7Po@hq`#0WKQg<}At`Gw7Bl#3@ws1go>gTlX$N(z}lm@WQY@mmY;2(Wp}q zqll9WZPaMvA!Z2S3SIO{woG3&E0IVPYB-{Btwc=$FFi_>RN2kNc~sRE3P76KQ2zii z8hpW@WETy)a`6^|0S4Dng6k*>Lbl4bokSIJ!^BC7rx&SRVM;J{re!zH4`UKq$5{UW zE)PSm2UQ#plyDAeHtdI>?RbeA;i??dFSa#_UGpx!{6m&bM<sdz^RMbMi~8C zV6d^wb7jz>dEBF*F;RaE<006LZMX|=6R~Tfm^eY=IzSFtXe~Bz4wlvfh%{HR(gG-P z0aXCz5{0pb6u!1+6Fdo;h$z6Rg29)6S1OowP=Azujtx>C+m;)>x>ZR*EdUbSD5C?} zneaJ1a~E(qDK5w*Ua!t~GK~Qx#1Li?${oh)F^h>zm2E{ZX*y~>K`5b>UlA`XWefKc zqZ>GDxkYlc5Rn@}xty(FoXccV=yNU|u#H1l7#p=RbG%&E+y3W5K`?gw*Fu(w);#j52_un(H*p}Ll*A!SM;fY_XVefEjX_)n^9o1%wqvddQ7x?TCN+ac{n4bmy>ebjW&!zM*^XMXjUA;D5}yNM&c8ELs?;B zeiM*Fl;^e*N`(Ts5(2nlD6ZH54v=y)c!C1nhDbf4#l}tD$}+-++hXhDI-B4QLJ)vZ zGCcT|opB$H#AJDF&GvJK|~&e!k1AMWo%k&y5?UA!gPEk9V(Wg zxXKv|ZL_%hV9P3$%5RqM+-P*2q3TsSr5K+bu-hpVVZ+paA0Z_VtlLC##b}}{zcT6+ zS)Gfc!8C&DsgF~#C@LOiHKqe&3Taw~NG&yVJ^7Ad2RwHjPewxqy~|caruHzCVQ9Tf zkc`>8xRuF4ZW16n?N`GPnT0&YRS3Fnm}#8A-O7W*oN+gc@3tu?(=#$#sT@QvRrtT`wk`_Ng~>7v`(ofmn_$8!UjRlt>3PR&M%oRg2$QqZ!sQ`XOr86O z#n?Q`iDXgxz<75Y6CR^y5`lC!1rsswAshh0oWLN4J7H<%!OV7%`BYlbYs5l~Br1fp zOSnKRyST`d$;;G6J!u+gZdyT8o9N0ToW-q;DR93iy|*q^#{l}vOjQRv+ByZjG|Z(% z+)%IRfXW6ga3ZtYb9)TEq z#v=*4F_`!^W8{ckD1AzbI0L^-E{;kE1T$3`C73H}4*ijF{seP^riS2Rd#qt_L2{#! z{4P|jR)s^WxD91{Wx^;+ZMIV~jxQGj3!`n+Tv5KRp#_IDHH6-81Y4X+5*Y`Qvfm7=W5xo*2Q>)xF?hC8kp@l-zj2Oefw~|_al^Pg z_zmg;_<%Eh;gToMIYiZ~dWeLp(C5CPp2PAlhzlIq;Na+We7KM5-3xrGFcmJ5~)Gz$yMC=-U}NUIE{by^?_ojjrPH37DEn=uCn zQtdSj00V*`2ndi52zLQ3vcna-BoF`%1Wq7rWyrSaZZrisRhCj$+zxJ7-{Cj4Y75G+ z8zK}l&?suUl)AOb8CDS4nwOYMd0mo`79Lm|zNUm)I`kdzAG| z0HybHBF4aN{-9c}jUY0yg?|W)MI4QwtdWz?%o-A6{{Rq#03k}@@d7L!e_+d;{cT;L zPT`0-_b$K=pP~#MmYtEs!E1KK2{>DEi@Ox01RSI`u_0A4o*|_LSFAr0$M=-0Wi_yd zHJ8F3pxG@bxXALMOiId*7I60q3xbi%1jCY0j!+f3fC|vcO}+&hR46lI&PG>hnJ(Vr zt|o@@4N5NBZJ6|I8K_F4;?7nvZC$IF-~gaN)rSGZ9stF+aX~GWH&TQlA_Aj(0MlBW zEGpp3<4~O9I@-IZEY60`Z*b+1USFA4v;iK4s@9{x1T>;L`X?|8JExzRj6q3aT}xcz zYgEea^fv{l4K_g3#OAZxF8aNLE%g8h=&mA-4ko^HzR`mptRg{ z(F9v|l;BBpN~L?Yq4S*ceqwSapD{p9sA}p^RxnY2aKU8-0n}8PCig3A{6HHDc#0@W z=Q9xCJ2w>~+0AfANwhSvE+LRwAYm61Jo5n>P=g_*E6la~f!bK>a8+Dd#M`K?+bpv5 zfi>_zitM_?yRNhjkx7t|I{cwAg)wHetM8n$V#P-r}c)?kN8<7nZ07KzBcQ-UQ` zcCZ2>2p)GI1RB2L74nMcq+f4PdWDO+hRgVa0f;22b-3CsPJG8Y1y?J9U{b(u6L>Q1 z%@CNQNEz`j06}X(EgH8=a|3V@mCwX)F%`cM80Li-APHZ9W2czCqy0vJylG1iYScH&%76B|32pnQ<(9c=-=FAPXN4V{NulKbDs5yfyL3T}_MQd9)@s^ea0 zxp1Q4z^#cR%{m>$5x7!A#Z`(UoVmkMInWfbT$v^IQ%WlO-75WX~kW{nv zV%;pXCb|U@w!{m)jVxs3h{ky?b;~VHMah0a`b&)ceo>^gM+N%WaC3ca=(4b04x59J zQ61|AZ_%sI`FiGgdEL{xooPea>>sVn$EJFt4UE}da#G$_ggY3c4~2(GX^b>Q1@hwf z)!_@dlAu5*AjTp601v~v!!Y7?gY(2Euf||KS)Y_N zRO&Ag%n-SZ7>M;fu7=im1IK38LV%SrE|u$Kpec(qxB9#w-nSI+vY<#U8L91=$z}aj z2P!Kyb%9w#FNDs(WZtG!WIl4epg`d+S@&yA7pY`dcN4kY8Pvq`dH#8dtc-`ehEuo5 z&>1ay$bUtD6LqI*#NZQ|qMfrmfK&u;9b4L{KN_Vt%womdzmfaNjK0t4g1@;sI}3kQbRr%nhMGMRF% zv7Fu(T*~_*J(&f)NxU`btDw)sAS&G= z81&qrOYrH1`&>vSu0hPhvxr*NH_adThw}<%uLA?q5Q3JchFcLX)1k>qd zr#)C;2{1u|QP{Aa9DA)41np15zUbRp=;8IpdM|F<$tJhb z0=Xq1Z7&HycIaDxH*qe0=9$V{=vt(p=f?g!@1!p>O(I;8+Le@g6nGzU53kUuW{@oI z@7$c&-m4bUstEii1)i4%%`?ng_fB!0@{H4?t8s^DA6ymGwP$aZ|!+E zMzgn)UtFSnf@acReMMdF6SVlO9uEmd7L~>kp9B4>#;nL8wikNUHXWE|v$Qi0o(dJm ztExi<6ehyvMRJeetyV_{W4xr?OYAxGBSB3do!ccVo5tG?x;$4^s=|Q}f7KgBn^He4 zCI0KDqq8mNb5{u#Tqq@*RcH&K3eT<>X3$3SRRdicbKsP80Y(Z~#)o)O>j0X#46(lb zOwB1)o@<>`3Gch~?d7h|)NJ`23&{6Qn9k>aUkRPPu23eH{8V;0&mbP4VX%HePbQ2o zgDvEAq>1hqgWt8BmOl4o7sjOiEans*~U5bA?{kDx^X`AYUj}uP`-j?;e}3 zSEEx8accE%1V&!L#&hd@^FyKCuq=~4Y8S$q-l`JfRT(uhPIKO}+t=ycNTb9$(uUI<*y`E_)3+b7^D$Rjr56*&SA&US>>n6~Q>>q7qmE5uY}lVmf1cz=FwC*jj&Z?tDsw)P{x-E*xi?Xtce1JC|}@UKBUk##8`wQIs94B&^XE3a`005n+h@pAjvo=!o{(T>gDMSG3*Y7ldH256ac6Qm+&4oRtaTgh$DB zWQd)=?%lU`+^af~$N?|EE}GsezG_!uN+OZks;|ETtg*BG0X2Ld$s4hSg)Nr~vp;CK z*Z;Z5o7SBa)m_iHA{S~Iks|@WZ%CSvI7jPj+_$`fxFZrg=$rarAMUfgGcu#UB2z66 z7BSnor{QBrAk4|s(J#;Xby2*Yr_oJyE>+EI{}1DlDEmK6CD5#>CP#)xKFvy4j2iy&1CitKF{eF$q#kQfc$xdpBN-t(utfQKXKP^iNs2{un?*qZ zGSRuCu2}2e@%snCK5_vZiNQ3V#}5O6fuA;N1DGI_AntPjoXq4&$3JZT;ZV`t1ff4npoRB{BjOIkX%Pm z13vL-&owvG0G#Fa_;B8qJLUqAc9XeXb?*ZVXvVA2R^hoWW(}2(Bg!^Shlm~^n5E&8_<<@Y= z#BVsbqtiPqh%K{MHB3?Ga@gA?Y%KpWk9yCfNQ<1a^B>;H1i_jd;O;F zDY)0kPh<+mQ|cpp0WBW(Ytotdu>fp-vxgu~Zv5zRKyl;8~xtZ<#`qr==hH$I>c1EmknM>x9#pUF$@Q_UC%8k z*gMlQloQ_bV6ZOGBI;rS=7T4v=t;jPB;`^4A@Ot4t#7$?EqcTGHovBOJ@v143->Il zGB5WyN4|v^>!&DVUDpl58HyGoh*tON&QjcQ4I0e8`7;nkWXps6`7 zKZh_jXgFm{Pc4WSoSti{mv~X@uJa{Xjd8djt=ENRxhgg+IcWJ({`Fu+Cp^_JVM}Vw zxpNMEfKs;}{pA~K|iT>h;a(}K6W+YdKf<<0j0r8ONivd`Lv$?Lmtej}pFXXEvY zn;N9C7eAJ3f>J-}=jvVHylI~Jqzm?i=}U9Zf3Yg=s_U;r>liir(D%Xgk(OhpbV zSm`F?TyY0xz}vL}3_(X#snqf1sT`AU8IbkQM{)(v?$F;>Lu5mw^zql9Qt?*Bhdkzn zZtC*uSe3bginDQfKb#I6J6@-VI~EjYcqx0#E{u927?PBx5`Vr;lU%t4_~NoR`gr#; zK(L%EOk9vI`a8>`Bcl)h-anWTVKaq~^Ypl08X(^HQ2)VTh~;P;`2AguXPDK0boKcy z2oXm123ODh0qM4F?q0NJ5e^jr=PK1F^jJOuOz(nYbckA!#BJ#f#=CZf5A_iS!sdZa z=)@YIryadu&yr_{{>Q#`Qn0a@iGrc`z3=hfBfD_{)2!@b%jPrcMN;ZQ*PCg(G<5*0 zo-W|zRQ05WBHL-rXCwm|vZ3?41w(>nlOsCY4bvn~Q4gWdk_7k-{4H*0X2BxSl9w@p zrH5N)u|x$htmjQUJg&@D`YrD`l*ffXdk9tMhTE@SJ`g6i+&ZIXmZz*Gi!gc0i&+(} z=xdnrx?t2Y!s5%Kw3ST{k-7 zT1M0xlzR7cCs>7WiSIQQ8vWqtyKpHNUiy%w5w=fVI_wJ0mgpK|j=|iOLaS4WZpq(P zL8IC1$%d`qT3xcO7rWHs z{7gwuMbn7ID34`@R=IbvIPa_}n^;7w#rD+av(T5mv+U`63ug!EsiNj8g!;jA7!g9? zHcwWhD_QhMVbfPG8aVTcO}I9~H<4&{DjZqU)b_NzRJtH1BHs0Mo9+9`s$^!+7ovz7 ztIiuyneFb#Cl)hdSsMG2=ib07uj%(ed0c1U%?dDn&D8?(v5?U^ff9Xh6hjJbAEntc zLOJ>;mSq31tvuu+Qrn^0+d@)gRN%7gf=D8`=wr{ znE9X3pzbq(8WhB;TV*}k-lA5TaTr?HsI_olz>fG)fK+h@$%(Zhs7`o*Ghhz7v-&>G z$^vO~OO(L$a|#JWOW(Z|)XpjFZ~y$s_+ov8_{TwGc@wz!eb|MmoF5uuCz$^Sh-l1P zCNN0Oq=-+T`iKS3=(#2bjWju&;R2s2V{qnbxUS^l&5lQLez zk`;O91$?S9$0Ax{WNWPzsGIKE`l=H7+U4)scSu6&TXsh9w}m3OSIEaSC1Q}Q0n=XR zY5abo-}Y_^fcZ(*t@ZmCBZVYUr>95I%3%z<&n?IIS#v3QfgH!!a~yh_Y_PG5kmCQQdBn6AqSJ?>>KN~S(Z)y+jXh_$bv-14yuiwLTiJ<$B( z*^Uw?z1K+geL#T)?+u*N!e}rFHD(w=yL6{er94w#vhaGhWJ=XWR?n>(5EzdIHMZk?K>21j(J*7CBbg z)2pE~%l^{&3cojXb088v{7}d#+jL*~{x5>F#)PV}ePJDU*I)T#51XSok3a+!%bX(& z(*M1o_t2ChLEcRNh*~Xe8qbo0zWw7gf}w}p;0P9o$!6ZThH*Lx$O z^uAWi)4LGiF9q#vXO5Bo1IsR+TOWLqKau)_b~krGRe~IuVfa$vHd;-1aMO9Qs7Yhx z76mso>*xS~PdMeHXM;(YDE7M4l9uiZ^Ii{R_ytR@#5X#at564Io!1Is9&&$i9F=|a zpY6YeiM+f69Bp{)VWU31!g*69oL5lFG;d0ViT1=$9_UTiwoF{->FKV1APKn)ai zV9=o4;u|3@QP(qTW#WWCpJ1B)(Vlls#g3xk4w?|u;Rof2PPbIIJb)lhy-q{c$rHM} z@#im4O0yo1Mn*_>hL0~x3lB-CwNR2$i@Bz3ZZMVeg2Ix~jws1EVfc4z7O{8l4(WnI z0%_7De6x7pC#9<}?6`a|AG(;=e`s=6GG51D0A!@G|0n4H6zJEQY%_^_LXFsH_uL|D z{Vf!{i0^x5k|EMX$<*shBV#Jm^=`dMCrUI0Fm5-u+cwaDQS(^fjY93uN(kUa3Ysv$M8$t{d?MTctbuLDw)8 z#rz8=5lY5-Df*sv|CVXnH|0K{Zz|Nwe}-qGrtw*}x;s^rp?yVP6nK7fanI{iM@i(F;tSUiL7}#*^qrWYh)olXI>GT9Ue${&*YQ|Z>~7VwizUsFU>jR;^-qGn z3~k0&nLb{KD~q@rzm%aPOd6|-mvb>rdc38CoFCSJ93djF?o;;-cnOoUvz}q zFFDKKkPIBx+95#}uDCio1ss#0#}FX3iFM^vrRa~{P)2Mgb$GOWuT`W_H|_q$;IG0AhgDMT>U zAyCca{eGK&(=XR#UilRqHRg=a%js6u zVQKkJUaHA?ya-(U`PDF1_&<9AUvmqqwOElhngoaB6mpUBJc(ro2sZaJt3G7Wg0kw# zF7A_Q(0O6kX9Y?op6m*(Gv#6l-a!^QPe}$5xP;Ogfu!O;(P9HeV#*GQ>+_jH7?cDN z(^M!}pF7=LPPwSa)-#KI22t`v^XyY=hM$6n_Q00}@vo9f>rcB_ynUXs}V0n~k#qAh=-42tTlDoVojIOf2Xqe{8`CP9R^^{uR$yZ0EhR;`BX==V99 zSHdIZ4)G~PR<#a7jp@Nt(0MH!30NV>lg&HjL9P@i|Al>aPYpockrQV>sU-?^$JJ|& zydV|SS9eZ0)l`#yWS0n?bwU3ik5+N6ipP`Rwy(o%0V_%(0XcX4OZrAaZry^OF&8WOXcA*&oSa zkk|$ANH=H7T@q(NFgZ53)f~^vJ=Y+f>A#FM`|b=17nfTf5sX|w?l;Tu`a6pHTu$IF>uK>)t1|i#zZ8oI^|D)U=nm8>E(U1**u%Tu z47iG3mdk^uDW7H(5enMq9-mbFjAM!NGtPQ>7=xOGI_nm0)bK{Sa z{nl+xW@!Cajgw#P4mL?@H%&x=|4`cI=s2yLCO)$mHnqz?y2}UA!R|vMl;`=yoOA-< zL$p=@A|_#88dAvd-Er736v$0CC3&r^aUXP~sj|pTnRxIJG?h};CT&+#z4!6M>u&e)Ooslg-%T}w&cAo! z#FBR-$PWMYS-lgSA`PjtM1|p!C$%4{-mDD2%EorQn$=@y)W1K$Y(+=Q^Fimdl}MGk?I?PZ@TE;?q{G# zgPu!SV$M2;FEr6EWhOfRPSD@b)?_y%X zE{InWk${fJY#&LSzKPm3>8$pm#pwORlLT#q*FBwdij$BBe*Ea@+~7AF@WXh$A4Vwt zv(>wQ-^9e1#*37$JC&>~rO(HSDOu%<-{U$aaVFQjS)C*5%bF=mZ!%=&-Zd}i2%VXK zNHBhFiUO9Dofz$ryf%3xtpO-$R~czBB1t`Hay}hB{!tH8AhTww^K;f-$qamP40h{h zq;d>^W4iSRHC30_k~lS>xBihQkO6$QKL1M?2AwyVWQ$4lAjDLd$>($yF60}gdUd# zn88&WP)tY-}+I?iT|P? zwgmlR-@lcl5;>(0E6x0lK&op6C9lrh_>DkXCIxWYb9Xhy=JKQ#EluA4?+%?;NT*Yl zUUL@yUGkWn$;DqQ7GTP_!pRxC@)t;r;CRQaJ;6TaTImvSh{9asw93_-0 zoGYyG_JV?jbl?9lC{tt{Uk@f+;1Q46_tvfTfUSEXEpptkDU%y9^v7pQW|@mY zg~GY$J_(0>vT@@l!w6I6NBHj8x13=LpOY0Hr=hGHW=XY=>gJ?8Wtc)gPc2aSUjJP2 zcDLsBZ)WOYv>~}980{iT$>4t!U^v+;+3c74r}7d-k#doEd?wyD14y_kJtAyTzOvr7 z@dGic^YcNQ8{ceSElTv4-Smiallhg%1l`H}pKIO_lh6z}r?~Qx1sVGFVoB~RR!>tR z^`fNObEYvA{G72GhmDF8dPr(Qo)TG#qpUOI-d4(w((jVcI>|oTQXu$ks z*G0hH+Zc&e$&tngh{=@?`{Q_DgQZkC*=Ld-_|5Ag*%V=)e;k1_z~|a;=uSxAg_#S# zBXg=(4e~OBXO2q_Bd~+-Z z_eXR~`mMmS97$R3MZzUDr2OwyZk*AZGPX?}zt- z`8^&IaBkaiWIog-90uVunu<0K(SA^t!FwISoNcTGFm&j?FW^!ccxaYwftRt>RcQQ% zR5uMjGd)b{2ybxWwz*ar+-Fx0p?89d+Om0K30L-H|JEEHvT6%E2yP2uw?zx-4=oA& zoaWs&aJR(0%cBXJO{J&@<%XUhJ^$HmUv#La6aX}V>mMJ?$|s6yizE*eS1v;$PmbmE zopU}XeNN~^Y9l0St6hEwl*aSb&8}t-GMg?bJQ8fJzy229CR|(^tDHI!T{1a*FGaMJ^iH7$m(ad$`#f9c*L$aD6=j zy~9RhWOBI$#};Ks06pUb1&mh3U#h=7U>*Ft>D@{S02ny=y^5({unRN8byZ%n*B2P(s=akn#$A@%IXzMgGcY^80L#~Ql?txS*VEymc^8uEst7jyRFnQ( zKYwEGBE8&)2n|;QjQbg|0q1yEEHQpd$O0+iQL^F%nT_DFcJaK~w*KhJII7BxPndo;Lc69TMz zy51ewM!JKU@xO*qYro36jGj1Vnb6atMM7Hxf0;WzKM$H`n8a+$W5hNM10IGNz-|)(eXHXuW8vG zK^!6ny^=0Td1?t2Jslh0YLRO!o5XCuG-uT3D6~yG{#jQo=BwX)sX%xPr8#T;Fqk$< zYD&z3iUH^EY56JcYrQ^6@5)eB7&=eAY5Net+;Yrj%nMcV{Z2$+63a1(9GdMxRG(?e z%g1*BEO~py)Kq(ZcT!cRVaJ6Q^r1h`fLk=-bQ$cd(y!O1yVNHr&@2MtkOrI_gz(Ms1oZ|jaAJXt*#iK-7GBHK(FjSdPLa^ z4b|}T)e#MLTHkG92~qbI<@nH97a%q1YMjHAzC?d{O;b0Q@VyTZ=9(hYkFwo5j9hM^ zHr%$5M`!q^8B4QIsGX`<#+t|ng4*PtunNw-k)K|q8^8XRqmf-@a!tfHLJ2q!6pLi# z8E2EXPiT^IcI@T8YJ;}S&9dCMCk}k!f~26m5$O5bJX+2<7HlHW!N++G0s zU(*Z>B?$;MvBL*izzI%s0PjTuv@CDpNczbe9HmLFxMNwnGa^(|(d%P{{rdp=_bMYa zPJMNmY@l==A_-)-tB@U^s5X(4B0!x?SEbaMYC#GYj%-5VAat~0-cZt@uBgR1YTEZ+HpH>S})l*hMb9xU#2zR+m$`iZc1_L z0J5q?q%8}wdcze>NU)8WYJYcCMz_~24&%7B|>k;=(zdUo%fG>IB6*pcdEHd>OB;s@Wep10S zTULfHi(~kFj@00?Ojhy#W(mfgzen;`$#exJEw+ptVpwRxJ^CF3$i|R8;8YY(^=tW+4wDP{i$Ck(**8AN9 zwTalN;oy#3%IIH#Dvtksx3%L0u7{~(a`!RsJfb$#ECfeTyxc8|Xo#eQ^Gk(wL40W~2^jjej9{>kj%+CX;F-QeGwHL3@nXHwAl@sb zy6x>1_c6&Hs#cDKpcJFpHDr$_t76u1*k;Nwd)>@3L&{R8-@wW1XG>`2X#UY9!VQxn z2+zZqx}PS;QS=#wP7m{PdAc+OJ*1S^vfGWwtN~jaI!)MDHDx5Q(MjLvzP`PGou zC=n%>%8ZV`n%L|Dwdv5|79h)#lHW!msm(n2)NYAtu!cN2!Sw4nXY?$p=X=eLY5Vb` z+@<7Asca}m2EDGHb7(T7Cj33FM2AHA;Pfu%RKKFMs?TtH3wX=TA%~kqfQ(Pq*En6W z+glxCgO~ZZhDI*nIZ|1FT;}wZ9pH=FsKBPlHv~PzRQ}7#mMM||x-k=&VB;v7v~S+Q z2riU#-9Y}SoD+d|;}hsDjSjRPQjeyLy|g)zBiDqer2~Fqc=` zw6r#mMydN=1?SXpPe-tY%G7k`3R*Djz!%s~?bh%PKP0(|I(rU`JP(wIehZyTIUfD2 z=taugb@Z0wwTT(VD+g8uelHijY=Mubl29)YO@}z^lF?%3@~t4Pd4qQTNnS!h8F;lJ z&8L0R)_)1gv#ez(=Gc`If6Vd&R~l`JRiRAI5;GXSp|08Vc+$D5mJ}RDtZ^@pNG2vs zsn`-wl0exiTn=3FQXTs%5HD;7JW%aE!+7$y%wLahFCX+}1z3)LRWTaXpqo|`7RHD< z8ag6{K$>4{3`IDN<1QT!nmmo5?5xXNuA{#u@g8+`)Dd2SPc`wIG{Dt$Fgg)mrVgct zJ3ieb2B~1nR4Q{FlQo>Ii;FFJ@V!R&0-ee|n|lPg-oTEoZ+$$zBIen0`l2s`2zDq6MXA^7PTfdG4rx%shvkXh2Y?_qR@W{4dqwE@8}BlkJ&&vT zHW@-WUxfs$?VA%kUUa0m6ol|iVl2C%55X&H=d(S~{;5bq$%zBhC!Vzk-W2d$|d5+u8#^DnkH_^*Hudg%jR=p)AEo zt>qc!_8qU6|A-qX((T_Xf*se8-VuP;D+2b5FpAnce~w%oYCcZH>>v8WU|(q!rIIH^ zq+2sDE68(d=`FqZNu}3vD~t1*BAyuqDsiXg)tXwW^pmo;fPStpR!JvFT2N5BR}KTw zQlhPdM*Du0ubz9xSle)@6($5>vRO~P!SFSSV<_a8hn6*ozWRdm_WwfrAt;#ulx;3n z4_a_CFnVWb`dcxFIuNWpG)r(0N8@oa5}%AV<-KS}3bVWD*VmxAFZ>pUl*^MXj)}WT z?EC)zqKkx=xVOve-}NFB6&`cohTeydO4>C_sauqbE6SdWn;3euR%W2{P^Y!Vc1U(X zo(o$18)R0=qLA>RaJ9Cel*aezvmk;77^|rH=Zh=Cv=y3#b&-JlyONmK9LSOoil;B} zN#}>wuXb2V+<(u*-YDmo ztlx3F?D~YQ7!YWd_e>sV+_>0xpo996e@Tcjl!olJ zadbW&iw+`Z%NJGTJMJ8T%C-c+HIzHs3wV$Gw&WKZI!}%dq}DjDB2BKVsLn%8P1=k2 zTAI@8Ze4HZy>jV%+Ji*975A@_lDCcOmBg;ff`112mg{n};A3Q=Z|Yw5Rn=a*6l5He zDjvhqEx7m!7cOq|xOEg&9<74sSQ(1XsUky6UgmK~CYXJYC2@cLiBUSl5t$ef4 z0S`7(h16X7P@`k=nwYCY4V&pKZ2KS6t#wGbWwC^+iI(?{br$*Ob!s|X!42;^NJQTHk|bJo)8QiU>v69 zF+k~KG^woVritrhf$Gq{(#4v9hj;`<6sI zHN`xZuPlpVj)$`4uH{4Pd)2@A8C`#c$@O;kw<*tyep;n$;G}rF5GMaV`qaWYPc2O- z;uB@#w3ZlcH($1wSm$A9FPir!HGit`j=}O4y*B@VKvJ1GB~wV8FqTx}vH;Bf9*1o` zCfh}+Ozz?C&>mEUH%Vm!>nw_2jBAC?&^dk#KRLEnu_DxjWNdz#nrHf z)sH7gCa?ifF(;(Mlclv05ooRuMkol@5&rlf>{wxsHQH-zSG(qV#hKYU2kbg94oRQ` zo@R0F<;8(66*7vpqUUrv6)&lIVxj%yd~5oz8-!&)qc6;bCK-t-z=${d?u9m=XO>ih zy)07+uENyWT2DcqnnkFG{OUV8r#sl_lxKtyGw8HtQ%4qC{sd)oed%7q)V1>>%F>G| zIMLJxVftJ8%UQHayX>uet!8mmvlf4TE#-S{mmov6-{)5%mf5rqK|6FDB32vGbX-fp zOQ+o#FG0a2$A9!>-T5MX?5X(k(6D+-%5LkiW9VmPU`HDG=v0op1E`7!d5E{4?nyJA z+hkptui;8BIm4QU7T!0l`-;`9G0&T+TG5hcqC^5CO@r;Q`d?xTCv=>rkKT1>fQqWa z0!Ls{uFNIDA#Itg8h^g#6kiN;4T1(U_q7U4Y@C{7JUroAVQg=$46$dlct{XW^^J6i zW|VeafmWwAyd|AoSjN~2m6JDM{&@XKHv)$>k4!s6rP-NkMoNYck-`k zwCxYvp4*uL|8U9aEB$wYa-m3k_WLj4sG%{oBD%QEd#E4~?)a~vsl<+K1fAE_3h%-R(2b3Ls@;8<~34w>mRCtK#G%h&&@ehY>a3GxU0$ugn zKAiYfN?a0Apvo^D?q4d~6T^u9msK_V0?@vy_c(NE@|0a&uZB|Lx4fYmXwsq%S#)ic iB#^E=8y;Q)pgczrP8qo8X<8Pk)9R{qZEybH)Bgt=F{XzA literal 0 HcmV?d00001 diff --git a/libraries/NewRemoteSwitch/docs/new kaku protocol.txt b/libraries/NewRemoteSwitch/docs/new kaku protocol.txt new file mode 100644 index 0000000..c84ca8c --- /dev/null +++ b/libraries/NewRemoteSwitch/docs/new kaku protocol.txt @@ -0,0 +1,23 @@ += Protocol of klikaanklikuit A-series devices = + +Copied from Wieltje, http://www.circuitsonline.net/forum/view/message/1181410#1181410, +but with slightly different timings, as measured on my device. + _ _ +'0': | |_| |_____ (T,T,T,5T) + _ _ +'1': | |_____| |_ (T,5T,T,T) + _ _ +'dim': | |_| |_ (T,T,T,T) + +T = short period of ~260µs. Use the ShowReceivedCodeNewRemote example to find the +actual period length for your devices. + +A full frame looks like this: + +- start pulse: 1T high, 10.44T low +- 26 bit: Address +- 1 bit: group bit +- 1 bit: on/off/[dim] +- 4 bit: unit +- [4 bit: dim level. Only present of [dim] is chosen] +- stop pulse: 1T high, 40T low \ No newline at end of file diff --git a/libraries/NewRemoteSwitch/examples/LearnCode/LearnCode.ino b/libraries/NewRemoteSwitch/examples/LearnCode/LearnCode.ino new file mode 100644 index 0000000..9a2c907 --- /dev/null +++ b/libraries/NewRemoteSwitch/examples/LearnCode/LearnCode.ino @@ -0,0 +1,64 @@ +/* + * Demo for RF remote switch receiver. + * This example is for the new KaKu / Home Easy type of remotes! + * + * For details, see NewRemoteReceiver.h! + * + * With this sketch you can control a LED connected to digital pin 13, + * after the sketch learned the code. After start, the LED starts to blink, + * until a valid code has been received. The led stops blinking. Now you + * can control the LED with the remote. + * + * Note: only unit-switches are supported in this sketch, no group or dim. + * + * Set-up: connect the receiver to digital pin 2 and a LED to digital pin 13. + */ + +#include + +boolean codeLearned = false; +unsigned long learnedAddress; +byte learnedUnit; + +void setup() { + // LED-pin as output + pinMode(13, OUTPUT); + + // Init a new receiver on interrupt pin 0, minimal 2 identical repeats, and callback set to processCode. + NewRemoteReceiver::init(0, 2, processCode); +} + +void loop() { + // Blink led until a code has been learned + if (!codeLearned) { + digitalWrite(13, HIGH); + delay(500); + digitalWrite(13, LOW); + delay(500); + } +} + +// Callback function is called only when a valid code is received. +void processCode(NewRemoteCode receivedCode) { + // A code has been received. + // Do we already know the code? + if (!codeLearned) { + // No! Let's learn the received code. + learnedAddress = receivedCode.address; + learnedUnit = receivedCode.unit; + codeLearned = true; + } else { + // Yes! + // Is the received code identical to the learned code? + if (receivedCode.address == learnedAddress && receivedCode.unit == learnedUnit) { + // Yes! + // Switch the LED off if the received code was "off". + // Anything else (on, dim, on_with_dim) will switch the LED on. + if (receivedCode.switchType == NewRemoteCode::off) { + digitalWrite(13, LOW); + } else { + digitalWrite(13, HIGH); + } + } + } +} diff --git a/libraries/NewRemoteSwitch/examples/LightShow/LightShow.ino b/libraries/NewRemoteSwitch/examples/LightShow/LightShow.ino new file mode 100644 index 0000000..14f8639 --- /dev/null +++ b/libraries/NewRemoteSwitch/examples/LightShow/LightShow.ino @@ -0,0 +1,55 @@ +/** + * Demo for RF remote switch receiver. + * For details, see NewRemoteReceiver.h! + * + * Connect the transmitter to digital pin 11. + * + * This sketch demonstrates the use of the NewRemoteTransmitter class. + * + * When run, this sketch switches some pre-defined devices on and off in a loop. + * + * NOTE: the actual receivers have the address and group numbers in this example + * are only for demonstration! If you want to duplicate an existing remote, please + * try the "retransmitter"-example instead. + * + * To use this actual example, you'd need to "learn" the used code in the receivers + * This sketch is unsuited for that. + * + */ + +#include + +// Create a transmitter on address 123, using digital pin 11 to transmit, +// with a period duration of 260ms (default), repeating the transmitted +// code 2^3=8 times. +NewRemoteTransmitter transmitter(123, 11, 260, 3); + +void setup() { +} + +void loop() { + // Switch unit 2 off + transmitter.sendUnit(2, false); + + // Switch all devices in the group off + transmitter.sendGroup(false); + + // Set unit 1 to dim-level 3 (range 0-15) + transmitter.sendDim(1, 3); + + // Wait 5 seconds + delay(5000); + + + // Switch unit 2 on + transmitter.sendUnit(2, true); + + // Switch all devices in the group on + transmitter.sendGroup(true); + + // Set unit 1 to dim-level 15, full brightness. + transmitter.sendDim(1, 15); + + // Wait 5 seconds + delay(5000); +} diff --git a/libraries/NewRemoteSwitch/examples/Retransmitter/Retransmitter.ino b/libraries/NewRemoteSwitch/examples/Retransmitter/Retransmitter.ino new file mode 100644 index 0000000..6266273 --- /dev/null +++ b/libraries/NewRemoteSwitch/examples/Retransmitter/Retransmitter.ino @@ -0,0 +1,53 @@ +/* +* Demo for RF remote switch receiver. + * For details, see NewRemoteReceiver.h! + * + * Connect the transmitter to digital pin 11, and the receiver to digital pin 2. + * + * When run, this sketch waits for a valid code from a new-style the receiver, + * decodes it, and retransmits it after 5 seconds. + */ + +#include +#include + +void setup() { + // See example ShowReceivedCode for info on this + NewRemoteReceiver::init(0, 2, retransmitter); +} + +void loop() { +} + +void retransmitter(NewRemoteCode receivedCode) { + // Disable the receiver; otherwise it might pick up the retransmit as well. + NewRemoteReceiver::disable(); + + // Need interrupts for delay() + interrupts(); + + // Wait 5 seconds before sending. + delay(5000); + + // Create a new transmitter with the received address and period, use digital pin 11 as output pin + + NewRemoteTransmitter transmitter(receivedCode.address, 11, receivedCode.period); + + if (receivedCode.switchType == NewRemoteCode::dim) { + // Dimmer signal received + transmitter.sendDim(receivedCode.unit, receivedCode.dimLevel); + } else { + // On/Off signal received + bool isOn = receivedCode.switchType == NewRemoteCode::on || receivedCode.switchType == NewRemoteCode::on_with_dim; + + if (receivedCode.groupBit) { + // Send to the group + transmitter.sendGroup(isOn); + } else { + // Send to a single unit + transmitter.sendUnit(receivedCode.unit, isOn); + } + } + + NewRemoteReceiver::enable(); +} diff --git a/libraries/NewRemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino b/libraries/NewRemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino new file mode 100644 index 0000000..14d8228 --- /dev/null +++ b/libraries/NewRemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino @@ -0,0 +1,65 @@ +/* +* Demo for RF remote switch receiver. +* This example is for the new KaKu / Home Easy type of remotes! + +* For details, see NewRemoteReceiver.h! +* +* This sketch shows the received signals on the serial port. +* Connect the receiver to digital pin 2. +*/ + +#include + +void setup() { + Serial.begin(115200); + + // Initialize receiver on interrupt 0 (= digital pin 2), calls the callback "showCode" + // after 2 identical codes have been received in a row. (thus, keep the button pressed + // for a moment) + // + // See the interrupt-parameter of attachInterrupt for possible values (and pins) + // to connect the receiver. + NewRemoteReceiver::init(0, 2, showCode); +} + +void loop() { +} + +// Callback function is called only when a valid code is received. +void showCode(NewRemoteCode receivedCode) { + // Note: interrupts are disabled. You can re-enable them if needed. + + // Print the received code. + Serial.print("Addr "); + Serial.print(receivedCode.address); + + if (receivedCode.groupBit) { + Serial.print(" group"); + } else { + Serial.print(" unit "); + Serial.print(receivedCode.unit); + } + + switch (receivedCode.switchType) { + case NewRemoteCode::off: + Serial.print(" off"); + break; + case NewRemoteCode::on: + Serial.print(" on"); + break; + case NewRemoteCode::dim: + Serial.print(" dim level "); + Serial.print(receivedCode.dimLevel); + break; + case NewRemoteCode::on_with_dim: + Serial.print(" on with dim level "); + Serial.print(receivedCode.dimLevel); + break; + } + + Serial.print(", period: "); + Serial.print(receivedCode.period); + Serial.println("us."); +} + + diff --git a/libraries/NewRemoteSwitch/keywords.txt b/libraries/NewRemoteSwitch/keywords.txt new file mode 100644 index 0000000..876ece8 --- /dev/null +++ b/libraries/NewRemoteSwitch/keywords.txt @@ -0,0 +1,11 @@ +NewRemoteReceiver KEYWORD1 +NewRemoteCode KEYWORD1 +isReceiving KEYWORD2 +init KEYWORD2 +enable KEYWORD2 +disable KEYWORD2 +deinit KEYWORD2 +NewRemoteTransmitter KEYWORD1 +sendGroup KEYWORD2 +sendUnit KEYWORD2 +sendDim KEYWORD2 \ No newline at end of file diff --git a/libraries/NewRemoteSwitch/license.txt b/libraries/NewRemoteSwitch/license.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/libraries/NewRemoteSwitch/license.txt @@ -0,0 +1,674 @@ + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/libraries/OneWire/OneWire.cpp b/libraries/OneWire/OneWire.cpp new file mode 100644 index 0000000..631813f --- /dev/null +++ b/libraries/OneWire/OneWire.cpp @@ -0,0 +1,557 @@ +/* +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.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) +{ + 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 + write(0xF0); + + // 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; + } + 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--) { + 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; + } + } + 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) +{ + 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; + } + return crc; +} +#endif + +#endif diff --git a/libraries/OneWire/OneWire.h b/libraries/OneWire/OneWire.h new file mode 100644 index 0000000..916c529 --- /dev/null +++ b/libraries/OneWire/OneWire.h @@ -0,0 +1,229 @@ +#ifndef OneWire_h +#define OneWire_h + +#include + +#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 + +#define FALSE 0 +#define TRUE 1 + +// 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__) +#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(__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 + +#else +#error "Please define I/O register types here" +#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); +#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/PN532/PN532.cpp b/libraries/PN532/PN532.cpp new file mode 100644 index 0000000..a9ab4c6 --- /dev/null +++ b/libraries/PN532/PN532.cpp @@ -0,0 +1,811 @@ +/**************************************************************************/ +/*! + @file PN532.cpp + @author Adafruit Industries & Seeed Studio + @license BSD (see license.txt) + + + @section HISTORY + v1.5 - Modified to work with I2C and SPI + + v1.4 - Added setPassiveActivationRetries() + + v1.3 - Modified to work with I2C + + v1.2 - Added writeGPIO() + - Added readGPIO() + + v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes + - Added the following helper functions for text display + static void PrintHex(const uint8_t * data, const uint32_t numBytes) + static void PrintHexChar(const uint8_t * pbtData, const uint32_t numBytes) + - Added the following Mifare Classic functions: + bool mifareclassic_IsFirstBlock (uint32_t uiBlock) + bool mifareclassic_IsTrailerBlock (uint32_t uiBlock) + uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData) + uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data) + uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data) + - Added the following Mifare Ultalight functions: + uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) +*/ +/**************************************************************************/ + +#include "PN532.h" +#include "PN532_debug.h" + +#define HAL(func) (_interface->func) + +PN532::PN532(PN532Interface &interface) +{ + _interface = &interface; +} + +/**************************************************************************/ +/*! + @brief Setups the HW +*/ +/**************************************************************************/ +void PN532::begin() +{ + HAL(begin)(); + HAL(wakeup)(); +} + +/**************************************************************************/ +/*! + @brief Prints a hexadecimal value in plain characters + + @param data Pointer to the uint8_t data + @param numBytes Data length in bytes +*/ +/**************************************************************************/ +void PN532::PrintHex(const uint8_t *data, const uint32_t numBytes) +{ + (void)data; + for (uint8_t i = 0; i < numBytes; i++) { + DMSG("0x"); + DMSG_HEX(data[i]); + } + DMSG("\n"); +} + +/**************************************************************************/ +/*! + @brief Prints a hexadecimal value in plain characters, along with + the char equivalents in the following format + + 00 00 00 00 00 00 ...... + + @param data Pointer to the data + @param numBytes Data length in bytes +*/ +/**************************************************************************/ +void PN532::PrintHexChar(const uint8_t *data, const uint32_t numBytes) +{ + for (uint8_t i = 0; i < numBytes; i++) { + DMSG_HEX(data[i]); + } + DMSG(" "); + for (uint8_t i = 0; i < numBytes; i++) { + uint8_t c = data[i]; + if (c <= 0x1f || c > 0x7f) { + DMSG('.'); + } else { + DMSG((char)c); + } + } + +} + +/**************************************************************************/ +/*! + @brief Checks the firmware version of the PN5xx chip + + @returns The chip's firmware version and ID +*/ +/**************************************************************************/ +uint32_t PN532::getFirmwareVersion(void) +{ + uint32_t response; + + pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; + + if (HAL(writeCommand)(pn532_packetbuffer, 1)) { + return 0; + } + + // read data packet + int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + if (0 > status) { + return 0; + } + + response = pn532_packetbuffer[0]; + response <<= 8; + response |= pn532_packetbuffer[1]; + response <<= 8; + response |= pn532_packetbuffer[2]; + response <<= 8; + response |= pn532_packetbuffer[3]; + + return response; +} + + +/**************************************************************************/ +/*! + Writes an 8-bit value that sets the state of the PN532's GPIO pins + + @warning This function is provided exclusively for board testing and + is dangerous since it will throw an error if any pin other + than the ones marked "Can be used as GPIO" are modified! All + pins that can not be used as GPIO should ALWAYS be left high + (value = 1) or the system will become unstable and a HW reset + will be required to recover the PN532. + + pinState[0] = P30 Can be used as GPIO + pinState[1] = P31 Can be used as GPIO + pinState[2] = P32 *** RESERVED (Must be 1!) *** + pinState[3] = P33 Can be used as GPIO + pinState[4] = P34 *** RESERVED (Must be 1!) *** + pinState[5] = P35 Can be used as GPIO + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +bool PN532::writeGPIO(uint8_t pinstate) +{ + // Make sure pinstate does not try to toggle P32 or P34 + pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); + + // Fill command buffer + pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; + pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins + pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by I2C) + + DMSG("Writing P3 GPIO: "); + DMSG_HEX(pn532_packetbuffer[1]); + DMSG("\n"); + + // Send the WRITEGPIO command (0x0E) + if (HAL(writeCommand)(pn532_packetbuffer, 3)) + return 0; + + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +/**************************************************************************/ +/*! + Reads the state of the PN532's GPIO pins + + @returns An 8-bit value containing the pin state where: + + pinState[0] = P30 + pinState[1] = P31 + pinState[2] = P32 + pinState[3] = P33 + pinState[4] = P34 + pinState[5] = P35 +*/ +/**************************************************************************/ +uint8_t PN532::readGPIO(void) +{ + pn532_packetbuffer[0] = PN532_COMMAND_READGPIO; + + // Send the READGPIO command (0x0C) + if (HAL(writeCommand)(pn532_packetbuffer, 1)) + return 0x0; + + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + /* READGPIO response without prefix and suffix should be in the following format: + + byte Description + ------------- ------------------------------------------ + b0 P3 GPIO Pins + b1 P7 GPIO Pins (not used ... taken by I2C) + b2 Interface Mode Pins (not used ... bus select pins) + */ + + + DMSG("P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[7]); + DMSG("P7 GPIO: "); DMSG_HEX(pn532_packetbuffer[8]); + DMSG("I0I1 GPIO: "); DMSG_HEX(pn532_packetbuffer[9]); + DMSG("\n"); + + return pn532_packetbuffer[0]; +} + +/**************************************************************************/ +/*! + @brief Configures the SAM (Secure Access Module) +*/ +/**************************************************************************/ +bool PN532::SAMConfig(void) +{ + pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; + pn532_packetbuffer[1] = 0x01; // normal mode; + pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second + pn532_packetbuffer[3] = 0x01; // use IRQ pin! + + DMSG("SAMConfig\n"); + + if (HAL(writeCommand)(pn532_packetbuffer, 4)) + return false; + + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +/**************************************************************************/ +/*! + Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register + + @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout + after mxRetries + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +bool PN532::setPassiveActivationRetries(uint8_t maxRetries) +{ + pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; + pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries) + pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF) + pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) + pn532_packetbuffer[4] = maxRetries; + + if (HAL(writeCommand)(pn532_packetbuffer, 5)) + return 0x0; // no ACK + + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +/***** ISO14443A Commands ******/ + +/**************************************************************************/ +/*! + Waits for an ISO14443A target to enter the field + + @param cardBaudRate Baud rate of the card + @param uid Pointer to the array that will be populated + with the card's UID (up to 7 bytes) + @param uidLength Pointer to the variable that will hold the + length of the card's UID. + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout) +{ + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) + pn532_packetbuffer[2] = cardbaudrate; + + if (HAL(writeCommand)(pn532_packetbuffer, 3)) { + return 0x0; // command failed + } + + // read data packet + if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { + return 0x0; + } + + // check some basic stuff + /* ISO14443A card response should be in the following format: + + byte Description + ------------- ------------------------------------------ + b0 Tags Found + b1 Tag Number (only one used in this example) + b2..3 SENS_RES + b4 SEL_RES + b5 NFCID Length + b6..NFCIDLen NFCID + */ + + if (pn532_packetbuffer[0] != 1) + return 0; + + uint16_t sens_res = pn532_packetbuffer[2]; + sens_res <<= 8; + sens_res |= pn532_packetbuffer[3]; + + DMSG("ATQA: 0x"); DMSG_HEX(sens_res); + DMSG("SAK: 0x"); DMSG_HEX(pn532_packetbuffer[4]); + DMSG("\n"); + + /* Card appears to be Mifare Classic */ + *uidLength = pn532_packetbuffer[5]; + + for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) { + uid[i] = pn532_packetbuffer[6 + i]; + } + + return 1; +} + + +/***** Mifare Classic Functions ******/ + +/**************************************************************************/ +/*! + Indicates whether the specified block number is the first block + in the sector (block 0 relative to the current sector) +*/ +/**************************************************************************/ +bool PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock) +{ + // Test if we are in the small or big sectors + if (uiBlock < 128) + return ((uiBlock) % 4 == 0); + else + return ((uiBlock) % 16 == 0); +} + +/**************************************************************************/ +/*! + Indicates whether the specified block number is the sector trailer +*/ +/**************************************************************************/ +bool PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock) +{ + // Test if we are in the small or big sectors + if (uiBlock < 128) + return ((uiBlock + 1) % 4 == 0); + else + return ((uiBlock + 1) % 16 == 0); +} + +/**************************************************************************/ +/*! + Tries to authenticate a block of memory on a MIFARE card using the + INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual + for more information on sending MIFARE and other commands. + + @param uid Pointer to a byte array containing the card UID + @param uidLen The length (in bytes) of the card's UID (Should + be 4 for MIFARE Classic) + @param blockNumber The block number to authenticate. (0..63 for + 1KB cards, and 0..255 for 4KB cards). + @param keyNumber Which key type to use during authentication + (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B) + @param keyData Pointer to a byte array containing the 6 bytes + key value + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +uint8_t PN532::mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) +{ + uint8_t i; + + // Hang on to the key and uid data + memcpy (_key, keyData, 6); + memcpy (_uid, uid, uidLen); + _uidLen = uidLen; + + // Prepare the authentication command // + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ + pn532_packetbuffer[1] = 1; /* Max card numbers */ + pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; + pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ + memcpy (pn532_packetbuffer + 4, _key, 6); + for (i = 0; i < _uidLen; i++) { + pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */ + } + + if (HAL(writeCommand)(pn532_packetbuffer, 10 + _uidLen)) + return 0; + + // Read the response packet + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + // Check if the response is valid and we are authenticated??? + // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00 + // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good + if (pn532_packetbuffer[0] != 0x00) { + DMSG("Authentification failed\n"); + return 0; + } + + return 1; +} + +/**************************************************************************/ +/*! + Tries to read an entire 16-bytes data block at the specified block + address. + + @param blockNumber The block number to authenticate. (0..63 for + 1KB cards, and 0..255 for 4KB cards). + @param data Pointer to the byte array that will hold the + retrieved data (if any) + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +uint8_t PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) +{ + DMSG("Trying to read 16 bytes from block "); + DMSG_INT(blockNumber); + + /* Prepare the command */ + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; /* Card number */ + pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ + pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ + + /* Send the command */ + if (HAL(writeCommand)(pn532_packetbuffer, 4)) { + return 0; + } + + /* Read the response packet */ + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + /* If byte 8 isn't 0x00 we probably have an error */ + if (pn532_packetbuffer[0] != 0x00) { + return 0; + } + + /* Copy the 16 data bytes to the output buffer */ + /* Block content starts at byte 9 of a valid response */ + memcpy (data, pn532_packetbuffer + 1, 16); + + return 1; +} + +/**************************************************************************/ +/*! + Tries to write an entire 16-bytes data block at the specified block + address. + + @param blockNumber The block number to authenticate. (0..63 for + 1KB cards, and 0..255 for 4KB cards). + @param data The byte array that contains the data to write. + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +uint8_t PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) +{ + /* Prepare the first command */ + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; /* Card number */ + pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */ + pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ + memcpy (pn532_packetbuffer + 4, data, 16); /* Data Payload */ + + /* Send the command */ + if (HAL(writeCommand)(pn532_packetbuffer, 20)) { + return 0; + } + + /* Read the response packet */ + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +/**************************************************************************/ +/*! + Formats a Mifare Classic card to store NDEF Records + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +uint8_t PN532::mifareclassic_FormatNDEF (void) +{ + uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + // Note 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 must be used for key A + // for the MAD sector in NDEF records (sector 0) + + // Write block 1 and 2 to the card + if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1))) + return 0; + if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2))) + return 0; + // Write key A and access rights card + if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3))) + return 0; + + // Seems that everything was OK (?!) + return 1; +} + +/**************************************************************************/ +/*! + Writes an NDEF URI Record to the specified sector (1..15) + + Note that this function assumes that the Mifare Classic card is + already formatted to work as an "NFC Forum Tag" and uses a MAD1 + file system. You can use the NXP TagWriter app on Android to + properly format cards for this. + + @param sectorNumber The sector that the URI record should be written + to (can be 1..15 for a 1K card) + @param uriIdentifier The uri identifier code (0 = none, 0x01 = + "http://www.", etc.) + @param url The uri text to write (max 38 characters). + + @returns 1 if everything executed properly, 0 for an error +*/ +/**************************************************************************/ +uint8_t PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url) +{ + // Figure out how long the string is + uint8_t len = strlen(url); + + // Make sure we're within a 1K limit for the sector number + if ((sectorNumber < 1) || (sectorNumber > 15)) + return 0; + + // Make sure the URI payload is between 1 and 38 chars + if ((len < 1) || (len > 38)) + return 0; + + // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A + // in NDEF records + + // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message) + uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, (uint8_t)(len + 5), 0xD1, 0x01, (uint8_t)(len + 1), 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + if (len <= 6) { + // Unlikely we'll get a url this short, but why not ... + memcpy (sectorbuffer1 + 9, url, len); + sectorbuffer1[len + 9] = 0xFE; + } else if (len == 7) { + // 0xFE needs to be wrapped around to next block + memcpy (sectorbuffer1 + 9, url, len); + sectorbuffer2[0] = 0xFE; + } else if ((len > 7) || (len <= 22)) { + // Url fits in two blocks + memcpy (sectorbuffer1 + 9, url, 7); + memcpy (sectorbuffer2, url + 7, len - 7); + sectorbuffer2[len - 7] = 0xFE; + } else if (len == 23) { + // 0xFE needs to be wrapped around to final block + memcpy (sectorbuffer1 + 9, url, 7); + memcpy (sectorbuffer2, url + 7, len - 7); + sectorbuffer3[0] = 0xFE; + } else { + // Url fits in three blocks + memcpy (sectorbuffer1 + 9, url, 7); + memcpy (sectorbuffer2, url + 7, 16); + memcpy (sectorbuffer3, url + 23, len - 24); + sectorbuffer3[len - 22] = 0xFE; + } + + // Now write all three blocks back to the card + if (!(mifareclassic_WriteDataBlock (sectorNumber * 4, sectorbuffer1))) + return 0; + if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 1, sectorbuffer2))) + return 0; + if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 2, sectorbuffer3))) + return 0; + if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 3, sectorbuffer4))) + return 0; + + // Seems that everything was OK (?!) + return 1; +} + +/***** Mifare Ultralight Functions ******/ + +/**************************************************************************/ +/*! + Tries to read an entire 4-bytes page at the specified address. + + @param page The page number (0..63 in most cases) + @param buffer Pointer to the byte array that will hold the + retrieved data (if any) +*/ +/**************************************************************************/ +uint8_t PN532::mifareultralight_ReadPage (uint8_t page, uint8_t *buffer) +{ + if (page >= 64) { + DMSG("Page value out of range\n"); + return 0; + } + + /* Prepare the command */ + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; /* Card number */ + pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ + pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ + + /* Send the command */ + if (HAL(writeCommand)(pn532_packetbuffer, 4)) { + return 0; + } + + /* Read the response packet */ + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + /* If byte 8 isn't 0x00 we probably have an error */ + if (pn532_packetbuffer[0] == 0x00) { + /* Copy the 4 data bytes to the output buffer */ + /* Block content starts at byte 9 of a valid response */ + /* Note that the command actually reads 16 bytes or 4 */ + /* pages at a time ... we simply discard the last 12 */ + /* bytes */ + memcpy (buffer, pn532_packetbuffer + 1, 4); + } else { + return 0; + } + + // Return OK signal + return 1; +} + +/**************************************************************************/ +/*! + @brief Exchanges an APDU with the currently inlisted peer + + @param send Pointer to data to send + @param sendLength Length of the data to send + @param response Pointer to response data + @param responseLength Pointer to the response data length +*/ +/**************************************************************************/ +bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength) +{ + uint8_t i; + (void)i; + + pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = inListedTag; + + if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) { + return false; + } + + int16_t status = HAL(readResponse)(response, *responseLength, 1000); + if (status < 0) { + return false; + } + + if ((response[0] & 0x3f) != 0) { + DMSG("Status code indicates an error\n"); + return false; + } + + uint8_t length = status; + length -= 1; + + if (length > *responseLength) { + length = *responseLength; // silent truncation... + } + + for (uint8_t i = 0; i < length; i++) { + response[i] = response[i + 1]; + } + *responseLength = length; + + return true; +} + +/**************************************************************************/ +/*! + @brief 'InLists' a passive target. PN532 acting as reader/initiator, + peer acting as card/responder. +*/ +/**************************************************************************/ +bool PN532::inListPassiveTarget() +{ + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = 0; + + DMSG("inList passive target\n"); + + if (HAL(writeCommand)(pn532_packetbuffer, 3)) { + return false; + } + + int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 30000); + if (status < 0) { + return false; + } + + if (pn532_packetbuffer[0] != 1) { + return false; + } + + inListedTag = pn532_packetbuffer[1]; + + return true; +} + +/** + * Peer to Peer + */ +int8_t PN532::tgInitAsTarget(uint16_t timeout) +{ + const uint8_t command[] = { + PN532_COMMAND_TGINITASTARGET, + 0, + 0x00, 0x00, //SENS_RES + 0x00, 0x00, 0x00, //NFCID1 + 0x40, //SEL_RES + + 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, // POL_RES + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, + + 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, //NFCID3t: Change this to desired value + + 0x06, 0x46, 0x66, 0x6D, 0x01, 0x01, 0x10, 0x00// LLCP magic number and version parameter + }; + + int8_t status = HAL(writeCommand)(command, sizeof(command)); + if (status < 0) { + return -1; + } + + status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout); + if (status > 0) { + return 1; + } else if (PN532_TIMEOUT == status) { + return 0; + } else { + return -2; + } +} + +int16_t PN532::tgGetData(uint8_t *buf, uint8_t len) +{ + buf[0] = PN532_COMMAND_TGGETDATA; + + if (HAL(writeCommand)(buf, 1)) { + return -1; + } + + int16_t status = HAL(readResponse)(buf, len, 3000); + if (0 >= status) { + return status; + } + + uint16_t length = status - 1; + + + if (buf[0] != 0) { + DMSG("status is not ok\n"); + return -5; + } + + for (uint8_t i = 0; i < length; i++) { + buf[i] = buf[i + 1]; + } + + return length; +} + +bool PN532::tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) +{ + if (hlen > (sizeof(pn532_packetbuffer) - 1)) { + return false; + } + + for (int8_t i = hlen - 1; i >= 0; i--){ + pn532_packetbuffer[i + 1] = header[i]; + } + pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA; + + if (HAL(writeCommand)(pn532_packetbuffer, hlen + 1, body, blen)) { + return false; + } + + if (0 > HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 3000)) { + return false; + } + + if (0 != pn532_packetbuffer[0]) { + return false; + } + + return true; +} diff --git a/libraries/PN532/PN532.h b/libraries/PN532/PN532.h new file mode 100644 index 0000000..a6e729c --- /dev/null +++ b/libraries/PN532/PN532.h @@ -0,0 +1,190 @@ +/**************************************************************************/ +/*! + @file PN532.h + @author Adafruit Industries & Seeed Studio + @license BSD (see license.txt) + + + @section HISTORY + v1.5 - Modified to work with I2C and SPI + + v1.3 - Modified to work with I2C + + v1.1 - Added full command list + - Added 'verbose' mode flag to constructor to toggle debug output + - Changed readPassiveTargetID() to return variable length values + +*/ +/**************************************************************************/ + +#ifndef PN532_h +#define PN532_h + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#include "PN532Interface.h" + + +// PN532 Commands +#define PN532_COMMAND_DIAGNOSE (0x00) +#define PN532_COMMAND_GETFIRMWAREVERSION (0x02) +#define PN532_COMMAND_GETGENERALSTATUS (0x04) +#define PN532_COMMAND_READREGISTER (0x06) +#define PN532_COMMAND_WRITEREGISTER (0x08) +#define PN532_COMMAND_READGPIO (0x0C) +#define PN532_COMMAND_WRITEGPIO (0x0E) +#define PN532_COMMAND_SETSERIALBAUDRATE (0x10) +#define PN532_COMMAND_SETPARAMETERS (0x12) +#define PN532_COMMAND_SAMCONFIGURATION (0x14) +#define PN532_COMMAND_POWERDOWN (0x16) +#define PN532_COMMAND_RFCONFIGURATION (0x32) +#define PN532_COMMAND_RFREGULATIONTEST (0x58) +#define PN532_COMMAND_INJUMPFORDEP (0x56) +#define PN532_COMMAND_INJUMPFORPSL (0x46) +#define PN532_COMMAND_INLISTPASSIVETARGET (0x4A) +#define PN532_COMMAND_INATR (0x50) +#define PN532_COMMAND_INPSL (0x4E) +#define PN532_COMMAND_INDATAEXCHANGE (0x40) +#define PN532_COMMAND_INCOMMUNICATETHRU (0x42) +#define PN532_COMMAND_INDESELECT (0x44) +#define PN532_COMMAND_INRELEASE (0x52) +#define PN532_COMMAND_INSELECT (0x54) +#define PN532_COMMAND_INAUTOPOLL (0x60) +#define PN532_COMMAND_TGINITASTARGET (0x8C) +#define PN532_COMMAND_TGSETGENERALBYTES (0x92) +#define PN532_COMMAND_TGGETDATA (0x86) +#define PN532_COMMAND_TGSETDATA (0x8E) +#define PN532_COMMAND_TGSETMETADATA (0x94) +#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88) +#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90) +#define PN532_COMMAND_TGGETTARGETSTATUS (0x8A) + +#define PN532_RESPONSE_INDATAEXCHANGE (0x41) +#define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B) + + +#define PN532_MIFARE_ISO14443A (0x00) + +// Mifare Commands +#define MIFARE_CMD_AUTH_A (0x60) +#define MIFARE_CMD_AUTH_B (0x61) +#define MIFARE_CMD_READ (0x30) +#define MIFARE_CMD_WRITE (0xA0) +#define MIFARE_CMD_TRANSFER (0xB0) +#define MIFARE_CMD_DECREMENT (0xC0) +#define MIFARE_CMD_INCREMENT (0xC1) +#define MIFARE_CMD_STORE (0xC2) + +// Prefixes for NDEF Records (to identify record type) +#define NDEF_URIPREFIX_NONE (0x00) +#define NDEF_URIPREFIX_HTTP_WWWDOT (0x01) +#define NDEF_URIPREFIX_HTTPS_WWWDOT (0x02) +#define NDEF_URIPREFIX_HTTP (0x03) +#define NDEF_URIPREFIX_HTTPS (0x04) +#define NDEF_URIPREFIX_TEL (0x05) +#define NDEF_URIPREFIX_MAILTO (0x06) +#define NDEF_URIPREFIX_FTP_ANONAT (0x07) +#define NDEF_URIPREFIX_FTP_FTPDOT (0x08) +#define NDEF_URIPREFIX_FTPS (0x09) +#define NDEF_URIPREFIX_SFTP (0x0A) +#define NDEF_URIPREFIX_SMB (0x0B) +#define NDEF_URIPREFIX_NFS (0x0C) +#define NDEF_URIPREFIX_FTP (0x0D) +#define NDEF_URIPREFIX_DAV (0x0E) +#define NDEF_URIPREFIX_NEWS (0x0F) +#define NDEF_URIPREFIX_TELNET (0x10) +#define NDEF_URIPREFIX_IMAP (0x11) +#define NDEF_URIPREFIX_RTSP (0x12) +#define NDEF_URIPREFIX_URN (0x13) +#define NDEF_URIPREFIX_POP (0x14) +#define NDEF_URIPREFIX_SIP (0x15) +#define NDEF_URIPREFIX_SIPS (0x16) +#define NDEF_URIPREFIX_TFTP (0x17) +#define NDEF_URIPREFIX_BTSPP (0x18) +#define NDEF_URIPREFIX_BTL2CAP (0x19) +#define NDEF_URIPREFIX_BTGOEP (0x1A) +#define NDEF_URIPREFIX_TCPOBEX (0x1B) +#define NDEF_URIPREFIX_IRDAOBEX (0x1C) +#define NDEF_URIPREFIX_FILE (0x1D) +#define NDEF_URIPREFIX_URN_EPC_ID (0x1E) +#define NDEF_URIPREFIX_URN_EPC_TAG (0x1F) +#define NDEF_URIPREFIX_URN_EPC_PAT (0x20) +#define NDEF_URIPREFIX_URN_EPC_RAW (0x21) +#define NDEF_URIPREFIX_URN_EPC (0x22) +#define NDEF_URIPREFIX_URN_NFC (0x23) + +#define PN532_GPIO_VALIDATIONBIT (0x80) +#define PN532_GPIO_P30 (0) +#define PN532_GPIO_P31 (1) +#define PN532_GPIO_P32 (2) +#define PN532_GPIO_P33 (3) +#define PN532_GPIO_P34 (4) +#define PN532_GPIO_P35 (5) + +class PN532 +{ +public: + PN532(PN532Interface &interface); + + void begin(void); + + // Generic PN532 functions + bool SAMConfig(void); + uint32_t getFirmwareVersion(void); + bool writeGPIO(uint8_t pinstate); + uint8_t readGPIO(void); + bool setPassiveActivationRetries(uint8_t maxRetries); + + /** + * @brief Init PN532 as a target + * @param timeout max time to wait, 0 means no timeout + * @return > 0 success + * = 0 timeout + * < 0 failed + */ + int8_t tgInitAsTarget(uint16_t timeout = 0); + int16_t tgGetData(uint8_t *buf, uint8_t len); + bool tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0); + + // ISO14443A functions + bool inListPassiveTarget(); + bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 1000); + bool inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength); + + // Mifare Classic functions + bool mifareclassic_IsFirstBlock (uint32_t uiBlock); + bool mifareclassic_IsTrailerBlock (uint32_t uiBlock); + uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData); + uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data); + uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data); + uint8_t mifareclassic_FormatNDEF (void); + uint8_t mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url); + + // Mifare Ultralight functions + uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t *buffer); + + // Help functions to display formatted text + static void PrintHex(const uint8_t *data, const uint32_t numBytes); + static void PrintHexChar(const uint8_t *pbtData, const uint32_t numBytes); + + uint8_t *getBuffer(uint8_t *len) { + *len = sizeof(pn532_packetbuffer) - 4; + return pn532_packetbuffer; + }; + +private: + uint8_t _uid[7]; // ISO14443A uid + uint8_t _uidLen; // uid len + uint8_t _key[6]; // Mifare Classic key + uint8_t inListedTag; // Tg number of inlisted tag. + + uint8_t pn532_packetbuffer[64]; + + PN532Interface *_interface; +}; + +#endif diff --git a/libraries/PN532/PN532Interface.h b/libraries/PN532/PN532Interface.h new file mode 100644 index 0000000..6b6d399 --- /dev/null +++ b/libraries/PN532/PN532Interface.h @@ -0,0 +1,56 @@ + + +#ifndef __PN532_INTERFACE_H__ +#define __PN532_INTERFACE_H__ + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#define PN532_PREAMBLE (0x00) +#define PN532_STARTCODE1 (0x00) +#define PN532_STARTCODE2 (0xFF) +#define PN532_POSTAMBLE (0x00) + +#define PN532_HOSTTOPN532 (0xD4) +#define PN532_PN532TOHOST (0xD5) + +#define PN532_ACK_WAIT_TIME (10) // ms, timeout of waiting for ACK + +#define PN532_INVALID_ACK (-1) +#define PN532_TIMEOUT (-2) +#define PN532_INVALID_FRAME (-3) +#define PN532_NO_SPACE (-4) + +class PN532Interface +{ +public: + virtual void begin() = 0; + virtual void wakeup() = 0; + + /** + * @brief write a command and check ack + * @param header packet header + * @param hlen length of header + * @param body packet body + * @param blen length of body + * @return 0 success + * not 0 failed + */ + virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) = 0; + + /** + * @brief read the response of a command, strip prefix and suffix + * @param buf to contain the response data + * @param len lenght to read + * @param timeout max time to wait, 0 means no timeout + * @return >=0 length of response without prefix and suffix + * <0 failed to read response + */ + virtual int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 1000) = 0; +}; + +#endif + diff --git a/libraries/PN532/PN532_debug.h b/libraries/PN532/PN532_debug.h new file mode 100644 index 0000000..8daf550 --- /dev/null +++ b/libraries/PN532/PN532_debug.h @@ -0,0 +1,18 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +//#define DEBUG + +#ifdef DEBUG +#define DMSG(args...) Serial.print(args) +#define DMSG_STR(str) Serial.println(str) +#define DMSG_HEX(num) Serial.print(' '); Serial.print(num, HEX) +#define DMSG_INT(num) Serial.print(' '); Serial.print(num) +#else +#define DMSG(args...) +#define DMSG_STR(str) +#define DMSG_HEX(num) +#define DMSG_INT(num) +#endif + +#endif diff --git a/libraries/PN532/README.md b/libraries/PN532/README.md new file mode 100644 index 0000000..a2f5ff9 --- /dev/null +++ b/libraries/PN532/README.md @@ -0,0 +1,29 @@ +## NFC library for Arduino + +This is an Arduino library for PN532 to use NFC technology. It's based on +[Adafruit_NFCShield_I2C](http://goo.gl/pk3FdB) +and improved by [Seeed Studio](http://goo.gl/zh1iQh). +It works with: + ++ [Elechouse NFC Module](http://goo.gl/i0EQgd) ++ [NFC Shield](http://goo.gl/Cac2OH) ++ [Xadow NFC](http://goo.gl/qBZMt0) ++ [PN532 NFC/RFID controller breakout board](http://goo.gl/tby9Sw) + +### Features ++ Support I2C, SPI and HSU of PN532 ++ Read/write Mifare Classic Card ++ Works with [Don's NDEF Library](http://goo.gl/jDjsXl) ++ Support Peer to Peer communication(exchange data with android 4.0+) ++ Support [mbed platform](http://goo.gl/kGPovZ) + +### Getting Started +1. Download [zip file](http://goo.gl/F6beRM) and +extract the 4 folders(PN532, PN532_SPI, PN532_I2C and PN532_HSU) into Arduino's libraries. +2. Downlaod [Don's NDEF library](http://goo.gl/ewxeAe) and extract it intro Arduino's libraries. +3. Follow the examples of the two libraries. + + +### To do ++ Card emulation + diff --git a/libraries/PN532/examples/iso14443a_uid/iso14443a_uid.ino b/libraries/PN532/examples/iso14443a_uid/iso14443a_uid.ino new file mode 100644 index 0000000..abf9ff8 --- /dev/null +++ b/libraries/PN532/examples/iso14443a_uid/iso14443a_uid.ino @@ -0,0 +1,92 @@ +/**************************************************************************/ +/*! + This example will attempt to connect to an ISO14443A + card or tag and retrieve some basic information about it + that can be used to determine what type of card it is. + + Note that you need the baud rate to be 115200 because we need to print + out the data and read from the card at the same time! + + +*/ +/**************************************************************************/ + +// choose to SPI or I2C or HSU +#if 0 + #include + #include + #include "PN532.h" + + PN532_SPI pn532spi(SPI, 10); + PN532 nfc(pn532spi); +#elif 0 + #include + #include + + PN532_HSU pn532hsu(Serial1); + PN532 nfc(pn532hsu); +#else + #include + #include + #include + + PN532_I2C pn532i2c(Wire); + PN532 nfc(pn532i2c); +#endif + +void setup(void) { + Serial.begin(115200); + Serial.println("Hello!"); + + nfc.begin(); + + uint32_t versiondata = nfc.getFirmwareVersion(); + if (! versiondata) { + Serial.print("Didn't find PN53x board"); + while (1); // halt + } + + // Got ok data, print it out! + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); + + // Set the max number of retry attempts to read from a card + // This prevents us from waiting forever for a card, which is + // the default behaviour of the PN532. + nfc.setPassiveActivationRetries(0xFF); + + // configure board to read RFID tags + nfc.SAMConfig(); + + Serial.println("Waiting for an ISO14443A card"); +} + +void loop(void) { + boolean success; + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) + + // Wait for an ISO14443A type cards (Mifare, etc.). When one is found + // 'uid' will be populated with the UID, and uidLength will indicate + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); + + if (success) { + Serial.println("Found a card!"); + Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); + Serial.print("UID Value: "); + for (uint8_t i=0; i < uidLength; i++) + { + Serial.print(" 0x");Serial.print(uid[i], HEX); + } + Serial.println(""); + // Wait 1 second before continuing + delay(1000); + } + else + { + // PN532 probably timed out waiting for a card + Serial.println("Timed out waiting for a card"); + } +} diff --git a/libraries/PN532/examples/mifareclassic_formatndef/mifareclassic_formatndef.ino b/libraries/PN532/examples/mifareclassic_formatndef/mifareclassic_formatndef.ino new file mode 100644 index 0000000..786fa86 --- /dev/null +++ b/libraries/PN532/examples/mifareclassic_formatndef/mifareclassic_formatndef.ino @@ -0,0 +1,180 @@ +/**************************************************************************/ +/*! + This example attempts to format a clean Mifare Classic 1K card as + an NFC Forum tag (to store NDEF messages that can be read by any + NFC enabled Android phone, etc.) + + Note that you need the baud rate to be 115200 because we need to print + out the data and read from the card at the same time! +*/ +/**************************************************************************/ + +// choose to SPI or I2C or HSU +#if 0 + #include + #include + #include "PN532.h" + + PN532SPI pn532spi(SPI, 10); + PN532 nfc(pn532spi); +#elif 0 + #include + #include + + PN532_HSU pn532hsu(Serial1); + PN532 nfc(pn532hsu); +#else + #include + #include + #include + + PN532_I2C pn532i2c(Wire); + PN532 nfc(pn532i2c); +#endif + +/* + We can encode many different kinds of pointers to the card, + from a URL, to an Email address, to a phone number, and many more + check the library header .h file to see the large # of supported + prefixes! +*/ +// For a http://www. url: +const char * url = "elechouse.com"; +uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT; + +// for an email address +//const char * url = "mail@example.com"; +//uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO; + +// for a phone number +//const char * url = "+1 212 555 1212"; +//uint8_t ndefprefix = NDEF_URIPREFIX_TEL; + + +void setup(void) { + Serial.begin(115200); + Serial.println("Looking for PN532..."); + + nfc.begin(); + + uint32_t versiondata = nfc.getFirmwareVersion(); + if (! versiondata) { + Serial.print("Didn't find PN53x board"); + while (1); // halt + } + + // Got ok data, print it out! + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); + + // configure board to read RFID tags + nfc.SAMConfig(); +} + +void loop(void) { + uint8_t success; // Flag to check if there was an error with the PN532 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) + bool authenticated = false; // Flag to indicate if the sector is authenticated + + // Use the default key + uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + Serial.println(""); + Serial.println("PLEASE NOTE: Formatting your card for NDEF records will change the"); + Serial.println("authentication keys. To reformat your NDEF tag as a clean Mifare"); + Serial.println("Classic tag, use the mifareclassic_ndeftoclassic example!"); + Serial.println(""); + Serial.println("Place your Mifare Classic card on the reader to format with NDEF"); + Serial.println("and press any key to continue ..."); + // Wait for user input before proceeding + while (!Serial.available()); + // a key was pressed1 + while (Serial.available()) Serial.read(); + + // Wait for an ISO14443A type card (Mifare, etc.). When one is found + // 'uid' will be populated with the UID, and uidLength will indicate + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); + + if (success) + { + // Display some basic information about the card + Serial.println("Found an ISO14443A card"); + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); + Serial.print(" UID Value: "); + nfc.PrintHex(uid, uidLength); + Serial.println(""); + + // Make sure this is a Mifare Classic card + if (uidLength != 4) + { + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); + return; + } + + // We probably have a Mifare Classic card ... + Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); + + // Try to format the card for NDEF data + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 0, 0, keya); + if (!success) + { + Serial.println("Unable to authenticate block 0 to enable card formatting!"); + return; + } + success = nfc.mifareclassic_FormatNDEF(); + if (!success) + { + Serial.println("Unable to format the card for NDEF"); + return; + } + + Serial.println("Card has been formatted for NDEF data using MAD1"); + + // Try to authenticate block 4 (first block of sector 1) using our key + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keya); + + // Make sure the authentification process didn't fail + if (!success) + { + Serial.println("Authentication failed."); + return; + } + + // Try to write a URL + Serial.println("Writing URI to sector 1 as an NDEF Message"); + + // Authenticated seems to have worked + // Try to write an NDEF record to sector 1 + // Use 0x01 for the URI Identifier Code to prepend "http://www." + // to the url (and save some space). For information on URI ID Codes + // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef + if (strlen(url) > 38) + { + // The length is also checked in the WriteNDEFURI function, but lets + // warn users here just in case they change the value and it's bigger + // than it should be + Serial.println("URI is too long ... must be less than 38 characters long"); + return; + } + + // URI is within size limits ... write it to the card and report success/failure + success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url); + if (success) + { + Serial.println("NDEF URI Record written to sector 1"); + } + else + { + Serial.println("NDEF Record creation failed! :("); + } + } + + // Wait a bit before trying again + Serial.println("\n\nDone!"); + delay(1000); + Serial.flush(); + while(Serial.available()) Serial.read(); +} \ No newline at end of file diff --git a/libraries/PN532/examples/mifareclassic_memdump/mifareclassic_memdump.ino b/libraries/PN532/examples/mifareclassic_memdump/mifareclassic_memdump.ino new file mode 100644 index 0000000..684fa66 --- /dev/null +++ b/libraries/PN532/examples/mifareclassic_memdump/mifareclassic_memdump.ino @@ -0,0 +1,168 @@ +/**************************************************************************/ +/*! + This example attempts to dump the contents of a Mifare Classic 1K card + + Note that you need the baud rate to be 115200 because we need to print + out the data and read from the card at the same time! +*/ +/**************************************************************************/ + +// choose to SPI or I2C or HSU +#if 0 + #include + #include + #include "PN532.h" + + PN532SPI pn532spi(SPI, 10); + PN532 nfc(pn532spi); +#elif 0 + #include + #include + + PN532_HSU pn532hsu(Serial1); + PN532 nfc(pn532hsu); +#else + #include + #include + #include + + PN532_I2C pn532i2c(Wire); + PN532 nfc(pn532i2c); +#endif + +void setup(void) { + // has to be fast to dump the entire memory contents! + Serial.begin(115200); + Serial.println("Looking for PN532..."); + + nfc.begin(); + + uint32_t versiondata = nfc.getFirmwareVersion(); + if (! versiondata) { + Serial.print("Didn't find PN53x board"); + while (1); // halt + } + // Got ok data, print it out! + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); + + // configure board to read RFID tags + nfc.SAMConfig(); + + Serial.println("Waiting for an ISO14443A Card ..."); +} + + +void loop(void) { + uint8_t success; // Flag to check if there was an error with the PN532 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) + uint8_t currentblock; // Counter to keep track of which block we're on + bool authenticated = false; // Flag to indicate if the sector is authenticated + uint8_t data[16]; // Array to store block data during reads + + // Keyb on NDEF and Mifare Classic should be the same + uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + // Wait for an ISO14443A type cards (Mifare, etc.). When one is found + // 'uid' will be populated with the UID, and uidLength will indicate + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); + + if (success) { + // Display some basic information about the card + Serial.println("Found an ISO14443A card"); + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); + Serial.print(" UID Value: "); + nfc.PrintHex(uid, uidLength); + Serial.println(""); + + if (uidLength == 4) + { + // We probably have a Mifare Classic card ... + Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); + + // Now we try to go through all 16 sectors (each having 4 blocks) + // authenticating each sector, and then dumping the blocks + for (currentblock = 0; currentblock < 64; currentblock++) + { + // Check if this is a new block so that we can reauthenticate + if (nfc.mifareclassic_IsFirstBlock(currentblock)) authenticated = false; + + // If the sector hasn't been authenticated, do so first + if (!authenticated) + { + // Starting of a new sector ... try to to authenticate + Serial.print("------------------------Sector ");Serial.print(currentblock/4, DEC);Serial.println("-------------------------"); + if (currentblock == 0) + { + // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!) + // or 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 for NDEF formatted cards using key a, + // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF) + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal); + } + else + { + // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!) + // or 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 for NDEF formatted cards using key a, + // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF) + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal); + } + if (success) + { + authenticated = true; + } + else + { + Serial.println("Authentication error"); + } + } + // If we're still not authenticated just skip the block + if (!authenticated) + { + Serial.print("Block ");Serial.print(currentblock, DEC);Serial.println(" unable to authenticate"); + } + else + { + // Authenticated ... we should be able to read the block now + // Dump the data into the 'data' array + success = nfc.mifareclassic_ReadDataBlock(currentblock, data); + if (success) + { + // Read successful + Serial.print("Block ");Serial.print(currentblock, DEC); + if (currentblock < 10) + { + Serial.print(" "); + } + else + { + Serial.print(" "); + } + // Dump the raw data + nfc.PrintHexChar(data, 16); + } + else + { + // Oops ... something happened + Serial.print("Block ");Serial.print(currentblock, DEC); + Serial.println(" unable to read this block"); + } + } + } + } + else + { + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); + } + } + // Wait a bit before trying again + Serial.println("\n\nSend a character to run the mem dumper again!"); + Serial.flush(); + while (!Serial.available()); + while (Serial.available()) { + Serial.read(); + } + Serial.flush(); +} \ No newline at end of file diff --git a/libraries/PN532/examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.ino b/libraries/PN532/examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.ino new file mode 100644 index 0000000..76f707c --- /dev/null +++ b/libraries/PN532/examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.ino @@ -0,0 +1,186 @@ +/**************************************************************************/ +/*! + This examples attempts to take a Mifare Classic 1K card that has been + formatted for NDEF messages using mifareclassic_formatndef, and resets + the authentication keys back to the Mifare Classic defaults +*/ +/**************************************************************************/ + +// choose to SPI or I2C or HSU +#if 0 + #include + #include + #include "PN532.h" + + PN532SPI pn532spi(SPI, 10); + PN532 nfc(pn532spi); +#elif 0 + #include + #include + + PN532_HSU pn532hsu(Serial1); + PN532 nfc(pn532hsu); +#else + #include + #include + #include + + PN532_I2C pn532i2c(Wire); + PN532 nfc(pn532i2c); +#endif + + +#define NR_SHORTSECTOR (32) // Number of short sectors on Mifare 1K/4K +#define NR_LONGSECTOR (8) // Number of long sectors on Mifare 4K +#define NR_BLOCK_OF_SHORTSECTOR (4) // Number of blocks in a short sector +#define NR_BLOCK_OF_LONGSECTOR (16) // Number of blocks in a long sector + +// Determine the sector trailer block based on sector number +#define BLOCK_NUMBER_OF_SECTOR_TRAILER(sector) (((sector)>24) & 0xFF, HEX); + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); + + // configure board to read RFID tags + nfc.SAMConfig(); +} + +void loop(void) { + uint8_t success; // Flag to check if there was an error with the PN532 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) + bool authenticated = false; // Flag to indicate if the sector is authenticated + uint8_t blockBuffer[16]; // Buffer to store block contents + uint8_t blankAccessBits[3] = { 0xff, 0x07, 0x80 }; + uint8_t idx = 0; + uint8_t numOfSector = 16; // Assume Mifare Classic 1K for now (16 4-block sectors) + + Serial.println("Place your NDEF formatted Mifare Classic 1K card on the reader"); + Serial.println("and press any key to continue ..."); + + // Wait for user input before proceeding + while (!Serial.available()); + while (Serial.available()) Serial.read(); + + // Wait for an ISO14443A type card (Mifare, etc.). When one is found + // 'uid' will be populated with the UID, and uidLength will indicate + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); + + if (success) + { + // We seem to have a tag ... + // Display some basic information about it + Serial.println("Found an ISO14443A card/tag"); + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); + Serial.print(" UID Value: "); + nfc.PrintHex(uid, uidLength); + Serial.println(""); + + // Make sure this is a Mifare Classic card + if (uidLength != 4) + { + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); + return; + } + + Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); + Serial.println(""); + Serial.println("Reformatting card for Mifare Classic (please don't touch it!) ... "); + + // Now run through the card sector by sector + for (idx = 0; idx < numOfSector; idx++) + { + // Step 1: Authenticate the current sector using key B 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, BLOCK_NUMBER_OF_SECTOR_TRAILER(idx), 1, (uint8_t *)KEY_DEFAULT_KEYAB); + if (!success) + { + Serial.print("Authentication failed for sector "); Serial.println(numOfSector); + return; + } + + // Step 2: Write to the other blocks + if (idx == 16) + { + memset(blockBuffer, 0, sizeof(blockBuffer)); + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer))) + { + Serial.print("Unable to write to sector "); Serial.println(numOfSector); + return; + } + } + if ((idx == 0) || (idx == 16)) + { + memset(blockBuffer, 0, sizeof(blockBuffer)); + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer))) + { + Serial.print("Unable to write to sector "); Serial.println(numOfSector); + return; + } + } + else + { + memset(blockBuffer, 0, sizeof(blockBuffer)); + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer))) + { + Serial.print("Unable to write to sector "); Serial.println(numOfSector); + return; + } + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer))) + { + Serial.print("Unable to write to sector "); Serial.println(numOfSector); + return; + } + } + memset(blockBuffer, 0, sizeof(blockBuffer)); + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 1, blockBuffer))) + { + Serial.print("Unable to write to sector "); Serial.println(numOfSector); + return; + } + + // Step 3: Reset both keys to 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF + memcpy(blockBuffer, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB)); + memcpy(blockBuffer + 6, blankAccessBits, sizeof(blankAccessBits)); + blockBuffer[9] = 0x69; + memcpy(blockBuffer + 10, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB)); + + // Step 4: Write the trailer block + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)), blockBuffer))) + { + Serial.print("Unable to write trailer block of sector "); Serial.println(numOfSector); + return; + } + } + } + + // Wait a bit before trying again + Serial.println("\n\nDone!"); + delay(1000); + Serial.flush(); + while(Serial.available()) Serial.read(); +} \ No newline at end of file diff --git a/libraries/PN532/examples/mifareclassic_updatendef/mifareclassic_updatendef.ino b/libraries/PN532/examples/mifareclassic_updatendef/mifareclassic_updatendef.ino new file mode 100644 index 0000000..7589a18 --- /dev/null +++ b/libraries/PN532/examples/mifareclassic_updatendef/mifareclassic_updatendef.ino @@ -0,0 +1,158 @@ +/**************************************************************************/ +/*! + Updates a sector that is already formatted for NDEF (using + mifareclassic_formatndef.pde for example), inserting a new url +*/ +/**************************************************************************/ + +// choose to SPI or I2C or HSU +#if 0 + #include + #include + #include "PN532.h" + + PN532SPI pn532spi(SPI, 10); + PN532 nfc(pn532spi); +#elif 0 + #include + #include + + PN532_HSU pn532hsu(Serial1); + PN532 nfc(pn532hsu); +#else + #include + #include + #include + + PN532_I2C pn532i2c(Wire); + PN532 nfc(pn532i2c); +#endif + + +/* + We can encode many different kinds of pointers to the card, + from a URL, to an Email address, to a phone number, and many more + check the library header .h file to see the large # of supported + prefixes! +*/ +// For a http://www. url: +const char * url = "elechouse.com"; +uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT; + +// for an email address +//const char * url = "sevice@elechouse.com"; +//uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO; + +// for a phone number +//const char * url = "+1 212 555 1212"; +//uint8_t ndefprefix = NDEF_URIPREFIX_TEL; + + +void setup(void) { + Serial.begin(115200); + Serial.println("Looking for PN532..."); + + nfc.begin(); + + uint32_t versiondata = nfc.getFirmwareVersion(); + if (! versiondata) { + Serial.print("Didn't find PN53x board"); + while (1); // halt + } + + // Got ok data, print it out! + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); + + // configure board to read RFID tags + nfc.SAMConfig(); +} + +void loop(void) { + uint8_t success; // Flag to check if there was an error with the PN532 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) + bool authenticated = false; // Flag to indicate if the sector is authenticated + + // Use the default NDEF keys (these would have have set by mifareclassic_formatndef.pde!) + uint8_t keya[6] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }; + uint8_t keyb[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }; + + Serial.println("Place your NDEF formatted Mifare Classic card on the reader to update the"); + Serial.println("NDEF record and press any key to continue ..."); + // Wait for user input before proceeding + while (!Serial.available()); + // a key was pressed1 + while (Serial.available()) Serial.read(); + + // Wait for an ISO14443A type card (Mifare, etc.). When one is found + // 'uid' will be populated with the UID, and uidLength will indicate + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); + + if (success) + { + // Display some basic information about the card + Serial.println("Found an ISO14443A card"); + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); + Serial.print(" UID Value: "); + nfc.PrintHex(uid, uidLength); + Serial.println(""); + + // Make sure this is a Mifare Classic card + if (uidLength != 4) + { + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); + return; + } + + // We probably have a Mifare Classic card ... + Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); + + // Check if this is an NDEF card (using first block of sector 1 from mifareclassic_formatndef.pde) + // Must authenticate on the first key using 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keyb); + if (!success) + { + Serial.println("Unable to authenticate block 4 ... is this card NDEF formatted?"); + return; + } + + Serial.println("Authentication succeeded (seems to be an NDEF/NFC Forum tag) ..."); + + // Authenticated seems to have worked + // Try to write an NDEF record to sector 1 + // Use 0x01 for the URI Identifier Code to prepend "http://www." + // to the url (and save some space). For information on URI ID Codes + // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef + if (strlen(url) > 38) + { + // The length is also checked in the WriteNDEFURI function, but lets + // warn users here just in case they change the value and it's bigger + // than it should be + Serial.println("URI is too long ... must be less than 38 characters!"); + return; + } + + Serial.println("Updating sector 1 with URI as NDEF Message"); + + // URI is within size limits ... write it to the card and report success/failure + success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url); + if (success) + { + Serial.println("NDEF URI Record written to sector 1"); + Serial.println(""); + } + else + { + Serial.println("NDEF Record creation failed! :("); + } + } + + // Wait a bit before trying again + Serial.println("\n\nDone!"); + delay(1000); + Serial.flush(); + while(Serial.available()) Serial.read(); +} diff --git a/libraries/PN532/examples/p2p_raw/p2p_raw.ino b/libraries/PN532/examples/p2p_raw/p2p_raw.ino new file mode 100644 index 0000000..f03b813 --- /dev/null +++ b/libraries/PN532/examples/p2p_raw/p2p_raw.ino @@ -0,0 +1,51 @@ +// snep_test.ino +// send a SNEP message to adnroid and get a message from android + +#include "SPI.h" +#include "PN532_SPI.h" +#include "llcp.h" +#include "snep.h" + +PN532_SPI pn532spi(SPI, 10); +SNEP nfc(pn532spi); + +void setup() +{ + Serial.begin(115200); + Serial.println("-------Peer to Peer--------"); +} + +uint8_t message[] = { +0xD2, 0xA, 0xB, 0x74,0x65, 0x78, 0x74, 0x2F, 0x70, 0x6C, +0x61, 0x69, 0x6E, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, +0x6F, 0x72, 0x6C, 0x64}; + +uint8_t buf[128]; + +void loop() +{ + + nfc.write(message, sizeof(message)); + delay(3000); + + int16_t len = nfc.read(buf, sizeof(buf)); + if (len > 0) { + Serial.println("get a SNEP message:"); + for (uint8_t i = 0; i < len; i++) { + Serial.print(buf[i], HEX); + Serial.print(' '); + } + Serial.print('\n'); + for (uint8_t i = 0; i < len; i++) { + char c = buf[i]; + if (c <= 0x1f || c > 0x7f) { + Serial.print('.'); + } else { + Serial.print(c); + } + } + Serial.print('\n'); + } + delay(3000); +} + diff --git a/libraries/PN532/examples/p2p_with_ndef_library/p2p_with_ndef_library.ino b/libraries/PN532/examples/p2p_with_ndef_library/p2p_with_ndef_library.ino new file mode 100644 index 0000000..f3e9c1f --- /dev/null +++ b/libraries/PN532/examples/p2p_with_ndef_library/p2p_with_ndef_library.ino @@ -0,0 +1,56 @@ +// send a NDEF message to adnroid or get a NDEF message +// +// note: [NDEF library](https://github.com/Don/NDEF) is needed. + +#include "SPI.h" +#include "PN532_SPI.h" +#include "snep.h" +#include "NdefMessage.h" + +PN532_SPI pn532spi(SPI, 10); +SNEP nfc(pn532spi); +uint8_t ndefBuf[128]; + +void setup() +{ + Serial.begin(115200); + Serial.println("-------Peer to Peer--------"); +} + +void loop() +{ +#if 1 + Serial.println("Send a message to Android"); + NdefMessage message = NdefMessage(); + message.addUriRecord("http://www.seeedstudio.com"); + int messageSize = message.getEncodedSize(); + if (messageSize > sizeof(ndefBuf)) { + Serial.println("ndefBuf is too small"); + while (1) { + } + + } + + message.encode(ndefBuf); + if (0 >= nfc.write(ndefBuf, messageSize)) { + Serial.println("Failed"); + } else { + Serial.println("Success"); + } + + delay(3000); +#else + // it seems there are some issues to use NdefMessage to decode the received data from Android + Serial.println("Get a message from Android"); + int msgSize = nfc.read(ndefBuf, sizeof(ndefBuf)); + if (msgSize > 0) { + NdefMessage msg = NdefMessage(ndefBuf, msgSize); + msg.print(); + Serial.println("\nSuccess"); + } else { + Serial.println("failed"); + } + delay(3000); +#endif +} + diff --git a/libraries/PN532/examples/readMifare/readMifare.ino b/libraries/PN532/examples/readMifare/readMifare.ino new file mode 100644 index 0000000..0c9347c --- /dev/null +++ b/libraries/PN532/examples/readMifare/readMifare.ino @@ -0,0 +1,161 @@ +/**************************************************************************/ +/*! + This example will wait for any ISO14443A card or tag, and + depending on the size of the UID will attempt to read from it. + + If the card has a 4-byte UID it is probably a Mifare + Classic card, and the following steps are taken: + + - Authenticate block 4 (the first block of Sector 1) using + the default KEYA of 0XFF 0XFF 0XFF 0XFF 0XFF 0XFF + - If authentication succeeds, we can then read any of the + 4 blocks in that sector (though only block 4 is read here) + + If the card has a 7-byte UID it is probably a Mifare + Ultralight card, and the 4 byte pages can be read directly. + Page 4 is read by default since this is the first 'general- + purpose' page on the tags. + +*/ +/**************************************************************************/ + +// choose to SPI or I2C or HSU +#if 0 + #include + #include + #include "PN532.h" + + PN532SPI pn532spi(SPI, 10); + PN532 nfc(pn532spi); +#elif 0 + #include + #include + + PN532_HSU pn532hsu(Serial1); + PN532 nfc(pn532hsu); +#else + #include + #include + #include + + PN532_I2C pn532i2c(Wire); + PN532 nfc(pn532i2c); +#endif + + +void setup(void) { + Serial.begin(115200); + Serial.println("Hello!"); + + nfc.begin(); + + uint32_t versiondata = nfc.getFirmwareVersion(); + if (! versiondata) { + Serial.print("Didn't find PN53x board"); + while (1); // halt + } + // Got ok data, print it out! + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); + + // configure board to read RFID tags + nfc.SAMConfig(); + + Serial.println("Waiting for an ISO14443A Card ..."); +} + + +void loop(void) { + uint8_t success; + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) + + // Wait for an ISO14443A type cards (Mifare, etc.). When one is found + // 'uid' will be populated with the UID, and uidLength will indicate + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); + + if (success) { + // Display some basic information about the card + Serial.println("Found an ISO14443A card"); + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); + Serial.print(" UID Value: "); + nfc.PrintHex(uid, uidLength); + Serial.println(""); + + if (uidLength == 4) + { + // We probably have a Mifare Classic card ... + Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); + + // Now we need to try to authenticate it for read/write access + // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF + Serial.println("Trying to authenticate block 4 with default KEYA value"); + uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + // Start with block 4 (the first block of sector 1) since sector 0 + // contains the manufacturer data and it's probably better just + // to leave it alone unless you know what you're doing + success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya); + + if (success) + { + Serial.println("Sector 1 (Blocks 4..7) has been authenticated"); + uint8_t data[16]; + + // If you want to write something to block 4 to test with, uncomment + // the following line and this text should be read back in a minute + // data = { 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0}; + // success = nfc.mifareclassic_WriteDataBlock (4, data); + + // Try to read the contents of block 4 + success = nfc.mifareclassic_ReadDataBlock(4, data); + + if (success) + { + // Data seems to have been read ... spit it out + Serial.println("Reading Block 4:"); + nfc.PrintHexChar(data, 16); + Serial.println(""); + + // Wait a bit before reading the card again + delay(1000); + } + else + { + Serial.println("Ooops ... unable to read the requested block. Try another key?"); + } + } + else + { + Serial.println("Ooops ... authentication failed: Try another key?"); + } + } + + if (uidLength == 7) + { + // We probably have a Mifare Ultralight card ... + Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)"); + + // Try to read the first general-purpose user page (#4) + Serial.println("Reading page 4"); + uint8_t data[32]; + success = nfc.mifareultralight_ReadPage (4, data); + if (success) + { + // Data seems to have been read ... spit it out + nfc.PrintHexChar(data, 4); + Serial.println(""); + + // Wait a bit before reading the card again + delay(1000); + } + else + { + Serial.println("Ooops ... unable to read the requested page!?"); + } + } + } +} + diff --git a/libraries/PN532/license.txt b/libraries/PN532/license.txt new file mode 100644 index 0000000..09c45e1 --- /dev/null +++ b/libraries/PN532/license.txt @@ -0,0 +1,27 @@ +Software License Agreement (BSD License) + +Copyright (c) 2012, Adafruit Industries +Copyright (c) 2013, Seeed Technology Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. 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. +3. Neither the name of the copyright holders nor the +names of its 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 ''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 HOLDER 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. diff --git a/libraries/PN532/llcp.cpp b/libraries/PN532/llcp.cpp new file mode 100644 index 0000000..68da733 --- /dev/null +++ b/libraries/PN532/llcp.cpp @@ -0,0 +1,282 @@ + +#include "llcp.h" +#include "PN532_debug.h" + +// LLCP PDU Type Values +#define PDU_SYMM 0x00 +#define PDU_PAX 0x01 +#define PDU_CONNECT 0x04 +#define PDU_DISC 0x05 +#define PDU_CC 0x06 +#define PDU_DM 0x07 +#define PDU_I 0x0c +#define PDU_RR 0x0d + +uint8_t LLCP::SYMM_PDU[2] = {0, 0}; + +inline uint8_t getPType(const uint8_t *buf) +{ + return ((buf[0] & 0x3) << 2) + (buf[1] >> 6); +} + +inline uint8_t getSSAP(const uint8_t *buf) +{ + return buf[1] & 0x3f; +} + +inline uint8_t getDSAP(const uint8_t *buf) +{ + return buf[0] >> 2; +} + +int8_t LLCP::activate(uint16_t timeout) +{ + return link.activateAsTarget(timeout); +} + +int8_t LLCP::waitForConnection(uint16_t timeout) +{ + uint8_t type; + (void)timeout; + + sequence = 0; + + // Get CONNECT PDU + DMSG("wait for a CONNECT PDU\n"); + do { + if (2 > link.read(headerBuf, headerBufLen)) { + return -1; + } + + type = getPType(headerBuf); + if (PDU_CONNECT == type) { + break; + } else if (PDU_SYMM == type) { + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) { + return -2; + } + } else { + return -3; + } + + } while (1); + + // Put CC PDU + DMSG("put a CC(Connection Complete) PDU to response the CONNECT PDU\n"); + ssap = getDSAP(headerBuf); + dsap = getSSAP(headerBuf); + headerBuf[0] = (dsap << 2) + ((PDU_CC >> 2) & 0x3); + headerBuf[1] = ((PDU_CC & 0x3) << 6) + ssap; + if (!link.write(headerBuf, 2)) { + return -2; + } + + return 1; +} + +int8_t LLCP::waitForDisconnection(uint16_t timeout) +{ + uint8_t type; + (void)timeout; + + // Get DISC PDU + DMSG("wait for a DISC PDU\n"); + do { + if (2 > link.read(headerBuf, headerBufLen)) { + return -1; + } + + type = getPType(headerBuf); + if (PDU_DISC == type) { + break; + } else if (PDU_SYMM == type) { + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) { + return -2; + } + } else { + return -3; + } + + } while (1); + + // Put DM PDU + DMSG("put a DM(Disconnect Mode) PDU to response the DISC PDU\n"); + // ssap = getDSAP(headerBuf); + // dsap = getSSAP(headerBuf); + headerBuf[0] = (dsap << 2) + (PDU_DM >> 2); + headerBuf[1] = ((PDU_DM & 0x3) << 6) + ssap; + if (!link.write(headerBuf, 2)) { + return -2; + } + + return 1; +} + +int8_t LLCP::connect(uint16_t timeout) +{ + uint8_t type; + (void)timeout; + + sequence = 0; + + // try to get a SYMM PDU + if (2 > link.read(headerBuf, headerBufLen)) { + return -1; + } + type = getPType(headerBuf); + if (PDU_SYMM != type) { + return -1; + } + + dsap = LLCP_DEFAULT_DSAP; + ssap = LLCP_DEFAULT_SSAP; + + // put a CONNECT PDU + headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_CONNECT >> 2); + headerBuf[1] = ((PDU_CONNECT & 0x03) << 6) + LLCP_DEFAULT_SSAP; + if (!link.write(headerBuf, 2)) { + return -2; + } + + // wait for a CC PDU + DMSG("wait for a CC PDU\n"); + do { + if (2 > link.read(headerBuf, headerBufLen)) { + return -1; + } + + type = getPType(headerBuf); + if (PDU_CC == type) { + break; + } else if (PDU_SYMM == type) { + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) { + return -2; + } + } else { + return -3; + } + + } while (1); + + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) { + return -2; + } + + return 1; +} + +int8_t LLCP::disconnect(uint16_t timeout) +{ + uint8_t type; + (void)timeout; + + // try to get a SYMM PDU + if (2 > link.read(headerBuf, headerBufLen)) { + return -1; + } + type = getPType(headerBuf); + if (PDU_SYMM != type) { + return -1; + } + + // put a DISC PDU + headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_DISC >> 2); + headerBuf[1] = ((PDU_DISC & 0x03) << 6) + LLCP_DEFAULT_SSAP; + if (!link.write(headerBuf, 2)) { + return -2; + } + + // wait for a DM PDU + DMSG("wait for a DM PDU\n"); + do { + if (2 > link.read(headerBuf, headerBufLen)) { + return -1; + } + + type = getPType(headerBuf); + if (PDU_CC == type) { + break; + } else if (PDU_DM == type) { + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) { + return -2; + } + } else { + return -3; + } + + } while (1); + + return 1; +} + +bool LLCP::write(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) +{ + uint8_t buf[3]; + + if (2 != link.read(buf, sizeof(buf))) { + return false; + } + + if (headerBufLen < (hlen + 3)) { + return false; + } + + for (int8_t i = hlen - 1; i >= 0; i--) { + headerBuf[i + 3] = header[i]; + } + + headerBuf[0] = (dsap << 2) + (PDU_I >> 2); + headerBuf[1] = ((PDU_I & 0x3) << 6) + ssap; + headerBuf[2] = sequence; // sequence + if (!link.write(headerBuf, 3 + hlen, body, blen)) { + return false; + } + + sequence++; + + return true; +} + +int16_t LLCP::read(uint8_t *buf, uint8_t length) +{ + uint8_t type; + uint16_t status; + + // Get INFO PDU + do { + status = link.read(buf, length); + if (2 > status) { + return -1; + } + + type = getPType(buf); + if (PDU_I == type) { + break; + } else if (PDU_SYMM == type) { + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) { + return -2; + } + } else { + return -3; + } + + } while (1); + + uint8_t len = status - 3; + ssap = getDSAP(buf); + dsap = getSSAP(buf); + buf[0] = (dsap << 2) + (PDU_RR >> 2); + buf[1] = ((PDU_RR & 0x3) << 6) + ssap; + buf[2] = 0x01; // sequence + if (!link.write(buf, 3)) { + return -2; + } + + for (uint8_t i = 0; i < len; i++) { + buf[i] = buf[i + 3]; + } + + sequence++; + + return len; +} diff --git a/libraries/PN532/llcp.h b/libraries/PN532/llcp.h new file mode 100644 index 0000000..d857ad6 --- /dev/null +++ b/libraries/PN532/llcp.h @@ -0,0 +1,72 @@ + +#ifndef __LLCP_H__ +#define __LLCP_H__ + +#include "mac_link.h" + +#define LLCP_DEFAULT_TIMEOUT 20000 +#define LLCP_DEFAULT_DSAP 0x04 +#define LLCP_DEFAULT_SSAP 0x20 + +class LLCP { +public: + LLCP(PN532Interface &interface) : link(interface) { + headerBuf = link.getHeaderBuffer(&headerBufLen); + sequence = 0; + }; + + /** + * @brief Actiave PN532 as a target + * @param timeout max time to wait, 0 means no timeout + * @return > 0 success + * = 0 timeout + * < 0 failed + */ + int8_t activate(uint16_t timeout = 0); + + int8_t waitForConnection(uint16_t timeout = LLCP_DEFAULT_TIMEOUT); + + int8_t waitForDisconnection(uint16_t timeout = LLCP_DEFAULT_TIMEOUT); + + int8_t connect(uint16_t timeout = LLCP_DEFAULT_TIMEOUT); + + int8_t disconnect(uint16_t timeout = LLCP_DEFAULT_TIMEOUT); + + /** + * @brief write a packet, the packet should be less than (255 - 2) bytes + * @param header packet header + * @param hlen length of header + * @param body packet body + * @param blen length of body + * @return true success + * false failed + */ + bool write(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0); + + /** + * @brief read a packet, the packet will be less than (255 - 2) bytes + * @param buf the buffer to contain the packet + * @param len lenght of the buffer + * @return >=0 length of the packet + * <0 failed + */ + int16_t read(uint8_t *buf, uint8_t len); + + uint8_t *getHeaderBuffer(uint8_t *len) { + uint8_t *buf = link.getHeaderBuffer(len); + len -= 3; // I PDU header has 3 bytes + return buf; + }; + +private: + MACLink link; + uint8_t ssap; + uint8_t dsap; + uint8_t *headerBuf; + uint8_t headerBufLen; + uint8_t sequence; + + static uint8_t SYMM_PDU[2]; +}; + +#endif // __LLCP_H__ diff --git a/libraries/PN532/mac_link.cpp b/libraries/PN532/mac_link.cpp new file mode 100644 index 0000000..75aca8e --- /dev/null +++ b/libraries/PN532/mac_link.cpp @@ -0,0 +1,20 @@ + +#include "mac_link.h" +#include "PN532_debug.h" + +int8_t MACLink::activateAsTarget(uint16_t timeout) +{ + pn532.begin(); + pn532.SAMConfig(); + return pn532.tgInitAsTarget(timeout); +} + +bool MACLink::write(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) +{ + return pn532.tgSetData(header, hlen, body, blen); +} + +int16_t MACLink::read(uint8_t *buf, uint8_t len) +{ + return pn532.tgGetData(buf, len); +} diff --git a/libraries/PN532/mac_link.h b/libraries/PN532/mac_link.h new file mode 100644 index 0000000..1575c04 --- /dev/null +++ b/libraries/PN532/mac_link.h @@ -0,0 +1,51 @@ + + +#ifndef __MAC_LINK_H__ +#define __MAC_LINK_H__ + +#include "PN532.h" + +class MACLink { +public: + MACLink(PN532Interface &interface) : pn532(interface) { + + }; + + /** + * @brief Activate PN532 as a target + * @param timeout max time to wait, 0 means no timeout + * @return > 0 success + * = 0 timeout + * < 0 failed + */ + int8_t activateAsTarget(uint16_t timeout = 0); + + /** + * @brief write a PDU packet, the packet should be less than (255 - 2) bytes + * @param header packet header + * @param hlen length of header + * @param body packet body + * @param blen length of body + * @return true success + * false failed + */ + bool write(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0); + + /** + * @brief read a PDU packet, the packet will be less than (255 - 2) bytes + * @param buf the buffer to contain the PDU packet + * @param len lenght of the buffer + * @return >=0 length of the PDU packet + * <0 failed + */ + int16_t read(uint8_t *buf, uint8_t len); + + uint8_t *getHeaderBuffer(uint8_t *len) { + return pn532.getBuffer(len); + }; + +private: + PN532 pn532; +}; + +#endif // __MAC_LINK_H__ diff --git a/libraries/PN532/snep.cpp b/libraries/PN532/snep.cpp new file mode 100644 index 0000000..f690878 --- /dev/null +++ b/libraries/PN532/snep.cpp @@ -0,0 +1,102 @@ + +#include "snep.h" +#include "PN532_debug.h" + +int8_t SNEP::write(const uint8_t *buf, uint8_t len, uint16_t timeout) +{ + if (0 >= llcp.activate(timeout)) { + DMSG("failed to activate PN532 as a target\n"); + return -1; + } + + if (0 >= llcp.connect(timeout)) { + DMSG("failed to set up a connection\n"); + return -2; + } + + // response a success SNEP message + headerBuf[0] = SNEP_DEFAULT_VERSION; + headerBuf[1] = SNEP_REQUEST_PUT; + headerBuf[2] = 0; + headerBuf[3] = 0; + headerBuf[4] = 0; + headerBuf[5] = len; + if (0 >= llcp.write(headerBuf, 6, buf, len)) { + return -3; + } + + if (6 > llcp.read(headerBuf, headerBufLen)) { + return -4; + } + + // check SNEP version + if (SNEP_DEFAULT_VERSION != headerBuf[0]) { + DMSG("The received SNEP message's major version is different\n"); + // To-do: send Unsupported Version response + return -4; + } + + // expect a put request + if (SNEP_RESPONSE_SUCCESS != headerBuf[1]) { + DMSG("Expect a success response\n"); + return -4; + } + + llcp.disconnect(timeout); + + return 1; +} + +int16_t SNEP::read(uint8_t *buf, uint8_t len, uint16_t timeout) +{ + if (0 >= llcp.activate(timeout)) { + DMSG("failed to activate PN532 as a target\n"); + return -1; + } + + if (0 >= llcp.waitForConnection(timeout)) { + DMSG("failed to set up a connection\n"); + return -2; + } + + uint16_t status = llcp.read(buf, len); + if (6 > status) { + return -3; + } + + + // check SNEP version + if (SNEP_DEFAULT_VERSION != buf[0]) { + DMSG("The received SNEP message's major version is different\n"); + // To-do: send Unsupported Version response + return -4; + } + + // expect a put request + if (SNEP_REQUEST_PUT != buf[1]) { + DMSG("Expect a put request\n"); + return -4; + } + + // check message's length + uint32_t length = ((uint32_t)buf[2] << 24) + ((uint32_t)buf[3] << 16) + (buf[4] << 8) + buf[5]; + // length should not be more than 244 (header + body < 255, header = 6 + 3 + 2) + if (length > (status - 6)) { + DMSG("The SNEP message is too large\n"); + return -4; + } + for (uint8_t i = 0; i < length; i++) { + buf[i] = buf[i + 6]; + } + + // response a success SNEP message + headerBuf[0] = SNEP_DEFAULT_VERSION; + headerBuf[1] = SNEP_RESPONSE_SUCCESS; + headerBuf[2] = 0; + headerBuf[3] = 0; + headerBuf[4] = 0; + headerBuf[5] = 0; + llcp.write(headerBuf, 6); + + return length; +} diff --git a/libraries/PN532/snep.h b/libraries/PN532/snep.h new file mode 100644 index 0000000..1a51696 --- /dev/null +++ b/libraries/PN532/snep.h @@ -0,0 +1,49 @@ + + +#ifndef __SNEP_H__ +#define __SNEP_H__ + +#include "llcp.h" + +#define SNEP_DEFAULT_VERSION 0x10 // Major: 1, Minor: 0 + +#define SNEP_REQUEST_PUT 0x02 +#define SNEP_REQUEST_GET 0x01 + +#define SNEP_RESPONSE_SUCCESS 0x81 +#define SNEP_RESPONSE_REJECT 0xFF + +class SNEP { +public: + SNEP(PN532Interface &interface) : llcp(interface) { + headerBuf = llcp.getHeaderBuffer(&headerBufLen); + }; + + /** + * @brief write a SNEP packet, the packet should be less than (255 - 2 - 3) bytes + * @param buf the buffer to contain the packet + * @param len lenght of the buffer + * @param timeout max time to wait, 0 means no timeout + * @return >0 success + * =0 timeout + * <0 failed + */ + int8_t write(const uint8_t *buf, uint8_t len, uint16_t timeout = 0); + + /** + * @brief read a SNEP packet, the packet will be less than (255 - 2 - 3) bytes + * @param buf the buffer to contain the packet + * @param len lenght of the buffer + * @param timeout max time to wait, 0 means no timeout + * @return >=0 length of the packet + * <0 failed + */ + int16_t read(uint8_t *buf, uint8_t len, uint16_t timeout = 0); + +private: + LLCP llcp; + uint8_t *headerBuf; + uint8_t headerBufLen; +}; + +#endif // __SNEP_H__ diff --git a/libraries/PN532_I2C/PN532_I2C.cpp b/libraries/PN532_I2C/PN532_I2C.cpp new file mode 100644 index 0000000..aca507b --- /dev/null +++ b/libraries/PN532_I2C/PN532_I2C.cpp @@ -0,0 +1,180 @@ + +#include "PN532_I2C.h" +#include "PN532_debug.h" + +#define PN532_I2C_ADDRESS (0x48 >> 1) + + +PN532_I2C::PN532_I2C(TwoWire &wire) +{ + _wire = &wire; + command = 0; +} + +void PN532_I2C::begin() +{ + _wire->begin(); +} + +void PN532_I2C::wakeup() +{ + _wire->beginTransmission(PN532_I2C_ADDRESS); // I2C start + delay(20); + _wire->endTransmission(); // I2C end +} + +int8_t PN532_I2C::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) +{ + command = header[0]; + _wire->beginTransmission(PN532_I2C_ADDRESS); + + write(PN532_PREAMBLE); + write(PN532_STARTCODE1); + write(PN532_STARTCODE2); + + uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA + write(length); + write(~length + 1); // checksum of length + + write(PN532_HOSTTOPN532); + uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA + + DMSG("write: "); + + for (uint8_t i = 0; i < hlen; i++) { + if (write(header[i])) { + sum += header[i]; + + DMSG_HEX(header[i]); + } else { + DMSG("\nToo many data to send, I2C doesn't support such a big packet\n"); // I2C max packet: 32 bytes + return PN532_INVALID_FRAME; + } + } + + for (uint8_t i = 0; i < blen; i++) { + if (write(body[i])) { + sum += body[i]; + + DMSG_HEX(body[i]); + } else { + DMSG("\nToo many data to send, I2C doesn't support such a big packet\n"); // I2C max packet: 32 bytes + return PN532_INVALID_FRAME; + } + } + + uint8_t checksum = ~sum + 1; // checksum of TFI + DATA + write(checksum); + write(PN532_POSTAMBLE); + + _wire->endTransmission(); + + DMSG('\n'); + + return readAckFrame(); +} + +int16_t PN532_I2C::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout) +{ + uint16_t time = 0; + + do { + if (_wire->requestFrom(PN532_I2C_ADDRESS, len + 2)) { + if (read() & 1) { // check first byte --- status + break; // PN532 is ready + } + } + + delay(1); + time++; + if ((0 != timeout) && (time > timeout)) { + return -1; + } + } while (1); + + if (0x00 != read() || // PREAMBLE + 0x00 != read() || // STARTCODE1 + 0xFF != read() // STARTCODE2 + ) { + + return PN532_INVALID_FRAME; + } + + uint8_t length = read(); + if (0 != (uint8_t)(length + read())) { // checksum of length + return PN532_INVALID_FRAME; + } + + uint8_t cmd = command + 1; // response command + if (PN532_PN532TOHOST != read() || (cmd) != read()) { + return PN532_INVALID_FRAME; + } + + length -= 2; + if (length > len) { + return PN532_NO_SPACE; // not enough space + } + + DMSG("read: "); + DMSG_HEX(cmd); + + uint8_t sum = PN532_PN532TOHOST + cmd; + for (uint8_t i = 0; i < length; i++) { + buf[i] = read(); + sum += buf[i]; + + DMSG_HEX(buf[i]); + } + DMSG('\n'); + + uint8_t checksum = read(); + if (0 != (uint8_t)(sum + checksum)) { + DMSG("checksum is not ok\n"); + return PN532_INVALID_FRAME; + } + read(); // POSTAMBLE + + return length; +} + +int8_t PN532_I2C::readAckFrame() +{ + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; + uint8_t ackBuf[sizeof(PN532_ACK)]; + + DMSG("wait for ack at : "); + DMSG(millis()); + DMSG('\n'); + + uint16_t time = 0; + do { + if (_wire->requestFrom(PN532_I2C_ADDRESS, sizeof(PN532_ACK) + 1)) { + if (read() & 1) { // check first byte --- status + break; // PN532 is ready + } + } + + delay(1); + time++; + if (time > PN532_ACK_WAIT_TIME) { + DMSG("Time out when waiting for ACK\n"); + return PN532_TIMEOUT; + } + } while (1); + + DMSG("ready at : "); + DMSG(millis()); + DMSG('\n'); + + + for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) { + ackBuf[i] = read(); + } + + if (memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK))) { + DMSG("Invalid ACK\n"); + return PN532_INVALID_ACK; + } + + return 0; +} diff --git a/libraries/PN532_I2C/PN532_I2C.h b/libraries/PN532_I2C/PN532_I2C.h new file mode 100644 index 0000000..287a8e8 --- /dev/null +++ b/libraries/PN532_I2C/PN532_I2C.h @@ -0,0 +1,40 @@ + +#ifndef __PN532_I2C_H__ +#define __PN532_I2C_H__ + +#include +#include "PN532Interface.h" + +class PN532_I2C : public PN532Interface { +public: + PN532_I2C(TwoWire &wire); + + void begin(); + void wakeup(); + virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0); + int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout); + +private: + TwoWire* _wire; + uint8_t command; + + int8_t readAckFrame(); + + inline uint8_t write(uint8_t data) { + #if ARDUINO >= 100 + return _wire->write(data); + #else + return _wire->send(data); + #endif + } + + inline uint8_t read() { + #if ARDUINO >= 100 + return _wire->read(); + #else + return _wire->receive(); + #endif + } +}; + +#endif diff --git a/libraries/PWF_AS3935_Lightning_Sensor/PWF_Lightning_Sensor.txt b/libraries/PWF_AS3935_Lightning_Sensor/PWF_Lightning_Sensor.txt new file mode 100644 index 0000000..ed26e7e --- /dev/null +++ b/libraries/PWF_AS3935_Lightning_Sensor/PWF_Lightning_Sensor.txt @@ -0,0 +1,10 @@ +Notes from AS3935 datasheet: +Register Map: Page 11, detailed version on Page 12 + +Max clock freq for SPI = 2MHz + +SPI command Structure: Page14 +To activate this SPI, the CS has to be set to low. A SPI command consists of two bytes serial command and the data are sampled on the falling +edge of SCLK (CPHA=1). The next table shows command structure, from the MSB (B15) to LSB (B0). The command stream has to be sent to +the SPI from the MSB (B15) to the LSB (B0). + diff --git a/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp b/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp new file mode 100644 index 0000000..b512121 --- /dev/null +++ b/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.cpp @@ -0,0 +1,414 @@ +/*************************************************************************** +* File Name: PWFusion_AS3935.h +* Processor/Platform: Arduino Uno R3 (tested) +* Development Environment: Arduino 1.0.5 +* +* Designed for use with with Playing With Fusion AS3935 Lightning Sensor +* Breakout: SEN-39001. +* +* SEN-39001 (universal applications) +* ---> http://www.playingwithfusion.com/productview.php?pdid=22 +* +* Copyright © 2014 Playing With Fusion, Inc. +* SOFTWARE LICENSE AGREEMENT: This code is released under the MIT License. +* +* 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. +* ************************************************************************** +* REVISION HISTORY: +* Author Date Comments +* J. Steinlage 2014Aug20 Original version +* +* Playing With Fusion, Inc. invests time and resources developing open-source +* code. Please support Playing With Fusion and continued open-source +* development by buying products from Playing With Fusion! +* +* ************************************************************************** +* ADDITIONAL NOTES: +* This file contains functions to interface with the AS3935 Franklin +* Lightning Sensor manufactured by AMS. Originally designed for application +* on the Arduino Uno platform. +**************************************************************************/ +#include "PWFusion_AS3935.h" + +PWF_AS3935::PWF_AS3935(int8_t CSx, int8_t IRQx, int8_t SIx) +{ + _cs = CSx; + _si = SIx; + _irq = IRQx; + + // initalize the chip select pins + pinMode(_cs, OUTPUT); + pinMode(_si, OUTPUT); + pinMode(_irq, INPUT); + + digitalWrite(_cs, HIGH); // set pin high to initialize/clear SPI bus + digitalWrite(_si, LOW); // set pin low for SPI mode + +} + +uint8_t PWF_AS3935::_sing_reg_read(uint8_t RegAdd) +{ + digitalWrite(_cs, LOW); // set pin low to start talking to IC + // next pack command byte, send AS3935.... structure is shown below + // MODE Register Address/Direct Cmd + // B15-14 B13------------------8 + // 15 is always 0; B14, 0: Write/Direct Command, 1: Read + SPI.transfer((RegAdd & 0x3F) | 0x40); // simple write, nothing to read back + uint8_t RegData = SPI.transfer(0x00); // read register data from IC + digitalWrite(_cs, HIGH); // set pin high to end SPI session + + return RegData; +} + +void PWF_AS3935::_sing_reg_write(uint8_t RegAdd, uint8_t DataMask, uint8_t RegData) +{ + (void)DataMask; + // Configure and write the updated register value + digitalWrite(_cs, LOW); // set pin low to start talking to IC + // next pack command byte, send AS3935.... structure is shown below + // MODE Register Address/Direct Cmd + // B15-14 B13------------------8 + // 15 is always 0; B14, 0: Write/Direct Command, 1: Read + SPI.transfer((RegAdd & 0x3F)); // simple write, nothing to read back + SPI.transfer(RegData); // write register data to IC + digitalWrite(_cs, HIGH); // set pin high to end SPI session +} + +void PWF_AS3935::AS3935_DefInit() +{ + _AS3935_Reset(); // reset registers to default +} + +void PWF_AS3935::_AS3935_Reset() +{ + // run PRESET_DEFAULT Direct Command to set all registers in default state + digitalWrite(_cs, LOW); // begin transfer + SPI.transfer(0x3C); // send first byte (write, PRESET_DEFAULT register) + SPI.transfer(0x96); // send second byte (direct command) + digitalWrite(_cs, HIGH); // end transfer + delay(2); // wait 2ms to complete +} + +void PWF_AS3935::_CalRCO() +{ + // run ALIB_RCO Direct Command to cal internal RCO + digitalWrite(_cs, LOW); // begin transfer + SPI.transfer(0x3D); // send first byte (write, CALIB_RCO register) + SPI.transfer(0x96); // send second byte (direct command) + digitalWrite(_cs, HIGH); // end transfer + delay(3); // wait 3ms to complete +} + +void PWF_AS3935::AS3935_PowerUp(void) +{ + // power-up sequence based on datasheet, pg 23/27 + // register 0x00, PWD bit: 0 (clears PWD) + _sing_reg_write(0x00, 0x01, 0x00); + _CalRCO(); // run RCO cal cmd + _sing_reg_write(0x08, 0x20, 0x20); // set DISP_SRCO to 1 + delay(2); + _sing_reg_write(0x08, 0x20, 0x00); // set DISP_SRCO to 0 + +} + +void PWF_AS3935::AS3935_PowerDown(void) +{ + // register 0x00, PWD bit: 0 (sets PWD) + _sing_reg_write(0x00, 0x01, 0x01); + Serial.println("AS3935 powered down"); +} + +void PWF_AS3935::AS3935_DisturberEn(void) +{ + // register 0x03, PWD bit: 5 (sets MASK_DIST) + _sing_reg_write(0x03, 0x20, 0x00); + Serial.println("disturber detection enabled"); +} + +void PWF_AS3935::AS3935_DisturberDis(void) +{ + // register 0x03, PWD bit: 5 (sets MASK_DIST) + _sing_reg_write(0x03, 0x20, 0x20); +} + +void PWF_AS3935::AS3935_SetIRQ_Output_Source(uint8_t irq_select) +{ + // set interrupt source - what to displlay on IRQ pin + // reg 0x08, bits 5 (TRCO), 6 (SRCO), 7 (LCO) + // only one should be set at once, I think + // 0 = NONE, 1 = TRCO, 2 = SRCO, 3 = LCO + + if(1 == irq_select) + { + _sing_reg_write(0x08, 0xE0, 0x20); // set only TRCO bit + } + else if(2 == irq_select) + { + _sing_reg_write(0x08, 0xE0, 0x40); // set only SRCO bit + } + else if(3 == irq_select) + { + _sing_reg_write(0x08, 0xE0, 0x80); // set only LCO bit + } + else // assume 0 + { + _sing_reg_write(0x08, 0xE0, 0x00); // clear IRQ pin display bits + } + +} + +void PWF_AS3935::AS3935_SetTuningCaps(uint8_t cap_val) +{ + // Assume only numbers divisible by 8 (because that's all the chip supports) + if(120 < cap_val) // cap_value out of range, assume highest capacitance + { + _sing_reg_write(0x08, 0x0F, 0x0F); // set capacitance bits to maximum + } + else + { + _sing_reg_write(0x08, 0x0F, (cap_val>>3)); // set capacitance bits + } + Serial.print("capacitance set to 8x"); + Serial.println((_sing_reg_read(0x08) & 0x0F)); +} + +uint8_t PWF_AS3935::AS3935_GetInterruptSrc(void) +{ + // definition of interrupt data on table 18 of datasheet + // for this function: + // 0 = unknown src, 1 = lightning detected, 2 = disturber, 3 = Noise level too high + delay(10); // wait 10ms before reading (2ms per pg 22 of datasheet) + uint8_t int_src = (_sing_reg_read(0x03) & 0x0F); // read register, get rid of non-interrupt data + if(0x08 == int_src) + { + return 1; // lightning caused interrupt + } + else if(0x04 == int_src) + { + return 2; // disturber detected + } + else if(0x01 == int_src) + { + return 3; // Noise level too high + } + else{return 0;} // interrupt result not expected + +} + +uint8_t PWF_AS3935::AS3935_GetLightningDistKm(void) +{ + uint8_t strike_dist = (_sing_reg_read(0x07) & 0x3F); // read register, get rid of non-distance data + return strike_dist; +} + +uint32_t PWF_AS3935::AS3935_GetStrikeEnergyRaw(void) +{ + uint32_t nrgy_raw = ((_sing_reg_read(0x06) & 0x1F) << 8); // MMSB, shift 8 bits left, make room for MSB + nrgy_raw |= _sing_reg_read(0x05); // read MSB + nrgy_raw <<= 8; // shift 8 bits left, make room for LSB + nrgy_raw |= _sing_reg_read(0x04); // read LSB, add to others + + return nrgy_raw; +} + +uint8_t PWF_AS3935::AS3935_SetMinStrikes(uint8_t min_strk) +{ + // This function sets min strikes to the closest available number, rounding to the floor, + // where necessary, then returns the physical value that was set. Options are 1, 5, 9 or 16 strikes. + // see pg 22 of the datasheet for more info (#strikes in 17 min) + if(5 > min_strk) + { + _sing_reg_write(0x02, 0x30, 0x00); + return 1; + } + else if(9 > min_strk) + { + _sing_reg_write(0x02, 0x30, 0x10); + return 5; + } + else if(16 > min_strk) + { + _sing_reg_write(0x02, 0x30, 0x20); + return 9; + } + else + { + _sing_reg_write(0x02, 0x30, 0x30); + return 16; + } +} + +void PWF_AS3935::AS3935_SetIndoors(void) +{ + // AFE settings addres 0x00, bits 5:1 (10010, based on datasheet, pg 19, table 15) + // this is the default setting at power-up (AS3935 datasheet, table 9) + _sing_reg_write(0x00, 0x3E, 0x24); + Serial.println("set up for indoor operation"); +} + +void PWF_AS3935::AS3935_SetOutdoors(void) +{ + // AFE settings addres 0x00, bits 5:1 (01110, based on datasheet, pg 19, table 15) + _sing_reg_write(0x00, 0x3E, 0x1C); + Serial.println("set up for outdoor operation"); +} + +void PWF_AS3935::AS3935_ClearStatistics(void) +{ + // clear is accomplished by toggling CL_STAT bit 'high-low-high' (then set low to move on) + _sing_reg_write(0x02, 0x40, 0x40); // high + _sing_reg_write(0x02, 0x40, 0x00); // low + _sing_reg_write(0x02, 0x40, 0x40); // high +} + +uint8_t PWF_AS3935::AS3935_GetNoiseFloorLvl(void) +{ + // NF settings addres 0x01, bits 6:4 + // default setting of 010 at startup (datasheet, table 9) + uint8_t reg_raw = _sing_reg_read(0x01); // read register 0x01 + return ((reg_raw & 0x70)>>4); // should return value from 0-7, see table 16 for info +} + +void PWF_AS3935::AS3935_SetNoiseFloorLvl(uint8_t nf_sel) +{ + // NF settings addres 0x01, bits 6:4 + // default setting of 010 at startup (datasheet, table 9) + if(7 >= nf_sel) // nf_sel within expected range + { + _sing_reg_write(0x01, 0x70, ((nf_sel & 0x07)<<4)); + } + else + { // out of range, set to default (power-up value 010) + _sing_reg_write(0x01, 0x70, 0x20); + } +} + +uint8_t PWF_AS3935::AS3935_GetWatchdogThreshold(void) +{ + // This function is used to read WDTH. It is used to increase robustness to disturbers, + // though will make detection less efficient (see page 19, Fig 20 of datasheet) + // WDTH register: add 0x01, bits 3:0 + // default value of 0001 + // values should only be between 0x00 and 0x0F (0 and 7) + uint8_t reg_raw = _sing_reg_read(0x01); + return (reg_raw & 0x0F); +} + +void PWF_AS3935::AS3935_SetWatchdogThreshold(uint8_t wdth) +{ + // This function is used to modify WDTH. It is used to increase robustness to disturbers, + // though will make detection less efficient (see page 19, Fig 20 of datasheet) + // WDTH register: add 0x01, bits 3:0 + // default value of 0001 + // values should only be between 0x00 and 0x0F (0 and 7) + _sing_reg_write(0x01, 0x0F, (wdth & 0x0F)); +} + +uint8_t PWF_AS3935::AS3935_GetSpikeRejection(void) +{ + // This function is used to read SREJ (spike rejection). Similar to the Watchdog threshold, + // it is used to make the system more robust to disturbers, though will make general detection + // less efficient (see page 20-21, especially Fig 21 of datasheet) + // SREJ register: add 0x02, bits 3:0 + // default value of 0010 + // values should only be between 0x00 and 0x0F (0 and 7) + uint8_t reg_raw = _sing_reg_read(0x02); + return (reg_raw & 0x0F); +} + +void PWF_AS3935::AS3935_SetSpikeRejection(uint8_t srej) +{ + // This function is used to modify SREJ (spike rejection). Similar to the Watchdog threshold, + // it is used to make the system more robust to disturbers, though will make general detection + // less efficient (see page 20-21, especially Fig 21 of datasheet) + // WDTH register: add 0x02, bits 3:0 + // default value of 0010 + // values should only be between 0x00 and 0x0F (0 and 7) + _sing_reg_write(0x02, 0x0F, (srej & 0x0F)); +} + +void PWF_AS3935::AS3935_SetLCO_FDIV(uint8_t fdiv) +{ + // This function sets LCO_FDIV register. This is useful in the tuning of the antenna + // LCO_FDIV register: add 0x03, bits 7:6 + // default value: 00 + // set 0, 1, 2 or 3 for ratios of 16, 32, 64 and 128, respectively. + // See pg 23, Table 20 for more info. + _sing_reg_write(0x03, 0xC0, ((fdiv & 0x03) << 5)); +} + +void PWF_AS3935::AS3935_PrintAllRegs(void) +{ + Serial.print("Reg 0x00: "); + Serial.println(_sing_reg_read(0x00)); + Serial.print("Reg 0x01: "); + Serial.println(_sing_reg_read(0x01)); + Serial.print("Reg 0x02: "); + Serial.println(_sing_reg_read(0x02)); + Serial.print("Reg 0x03: "); + Serial.println(_sing_reg_read(0x03)); + Serial.print("Reg 0x04: "); + Serial.println(_sing_reg_read(0x04)); + Serial.print("Reg 0x05: "); + Serial.println(_sing_reg_read(0x05)); + Serial.print("Reg 0x06: "); + Serial.println(_sing_reg_read(0x06)); + Serial.print("Reg 0x07: "); + Serial.println(_sing_reg_read(0x07)); + Serial.print("Reg 0x08: "); + Serial.println(_sing_reg_read(0x08)); + uint32_t nrgy_val = AS3935_GetStrikeEnergyRaw(); + Serial.println(nrgy_val); +} + +void PWF_AS3935::AS3935_ManualCal(uint8_t capacitance, uint8_t location, uint8_t disturber) +{ + // start by powering up + AS3935_PowerUp(); + + // indoors/outdoors next... + if(1 == location) // set outdoors if 1 + { + AS3935_SetOutdoors(); + } + else // set indoors if anything but 1 + { + AS3935_SetIndoors(); + } + + // disturber cal + if(0 == disturber) // disabled if 0 + { + AS3935_DisturberDis(); + } + else // enabled if anything but 0 + { + AS3935_DisturberEn(); + } + + AS3935_SetIRQ_Output_Source(0); + + delay(500); + // capacitance first... directly write value here + AS3935_SetTuningCaps(capacitance); + + Serial.println("AS3935 manual cal complete"); +} +// a nice function would be to read the last 'x' strike data values.... + diff --git a/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.h b/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.h new file mode 100644 index 0000000..2545093 --- /dev/null +++ b/libraries/PWF_AS3935_Lightning_Sensor/PWFusion_AS3935.h @@ -0,0 +1,96 @@ +/*************************************************************************** +* File Name: PWFusion_AS3935.h +* Processor/Platform: Arduino Uno R3 (tested) +* Development Environment: Arduino 1.0.5 +* +* Designed for use with with Playing With Fusion AS3935 Lightning Sensor +* Breakout: SEN-39001. +* +* SEN-39001 (universal applications) +* ---> http://www.playingwithfusion.com/productview.php?pdid=22 +* +* Copyright � 2014 Playing With Fusion, Inc. +* SOFTWARE LICENSE AGREEMENT: This code is released under the MIT License. +* +* 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. +* ************************************************************************** +* REVISION HISTORY: +* Author Date Comments +* J. Steinlage 2014Aug20 Original version +* +* Playing With Fusion, Inc. invests time and resources developing open-source +* code. Please support Playing With Fusion and continued open-source +* development by buying products from Playing With Fusion! +* +* ************************************************************************** +* ADDITIONAL NOTES: +* This file contains functions to interface with the AS3935 Franklin +* Lightning Sensor manufactured by AMS. Originally designed for application +* on the Arduino Uno platform. +**************************************************************************/ +#ifndef PWF_AS3935_h +#define PWF_AS3935_h + +#include "Arduino.h" +#include "avr/pgmspace.h" +#include "util/delay.h" +#include "stdlib.h" +#include "drivers/AVR/SPI/SPI.h" + +class PWF_AS3935 +{ + public: + PWF_AS3935(int8_t CSx, int8_t IRQx, int8_t SIx); + void AS3935_ManualCal(uint8_t capacitance, uint8_t location, uint8_t disturber); + void AS3935_DefInit(void); + void AS3935_PowerUp(void); + void AS3935_PowerDown(void); + void AS3935_DisturberEn(void); + void AS3935_DisturberDis(void); + void AS3935_SetIRQ_Output_Source(uint8_t irq_select); + void AS3935_SetTuningCaps(uint8_t cap_val); + uint8_t AS3935_GetInterruptSrc(void); + uint8_t AS3935_GetLightningDistKm(void); + uint32_t AS3935_GetStrikeEnergyRaw(void); + uint8_t AS3935_SetMinStrikes(uint8_t min_strk); + void AS3935_ClearStatistics(void); + void AS3935_SetIndoors(void); + void AS3935_SetOutdoors(void); + uint8_t AS3935_GetNoiseFloorLvl(void); + void AS3935_SetNoiseFloorLvl(uint8_t nf_sel); + uint8_t AS3935_GetWatchdogThreshold(void); + void AS3935_SetWatchdogThreshold(uint8_t wdth); + uint8_t AS3935_GetSpikeRejection(void); + void AS3935_SetSpikeRejection(uint8_t srej); + void AS3935_SetLCO_FDIV(uint8_t fdiv); + void AS3935_PrintAllRegs(void); + + private: + int8_t _cs, _irq, _si; + uint8_t _sing_reg_read(uint8_t RegAdd); + void _sing_reg_write(uint8_t RegAdd, uint8_t DataMask, uint8_t RegData); + void _AS3935_Reset(void); + void _CalRCO(void); +}; + +#endif + + + + diff --git a/libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.cpp b/libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.cpp new file mode 100644 index 0000000..db49dce --- /dev/null +++ b/libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.cpp @@ -0,0 +1,272 @@ +/* + ByteBuffer.cpp - A circular buffer implementation for Arduino + Created by Sigurdur Orn, July 19, 2010. + siggi@mit.edu + Updated by GreyGnome (aka Mike Schwager) Thu Feb 23 17:25:14 CST 2012 + added the putString() method and the fillError variable. + added the checkError() and resetError() methods. The checkError() method resets the fillError variable + to false as a side effect. + added the ByteBuffer(unsigned int buf_size) constructor. + added the init() method, and had the constructor call it automagically. + Also made the capacity, position, length, and fillError variables volatile, for safe use by interrupts. + */ + +#include "ByteBuffer.h" + +void ByteBuffer::init(){ + ByteBuffer::init(DEFAULTBUFSIZE); +} + +void ByteBuffer::init(unsigned int buf_length){ + data = (byte*)malloc(sizeof(byte)*buf_length); + capacity = buf_length; + position = 0; + length = 0; + fillError=false; +} + +void ByteBuffer::deAllocate(){ + free(data); +} + +void ByteBuffer::clear(){ + position = 0; + length = 0; +} + +void ByteBuffer::resetError(){ + fillError=false; +} + +boolean ByteBuffer::checkError(){ + /* + if (fillError) { + Serial.print("E: checkError: length "); + Serial.println(length, DEC); + } + */ + + boolean result=fillError; + fillError=false; + return(result); +} + +int ByteBuffer::getSize(){ + return length; +} + +int ByteBuffer::getCapacity(){ + return capacity; +} + +byte ByteBuffer::peek(unsigned int index){ + byte b = data[(position+index)%capacity]; + return b; +} + +uint8_t ByteBuffer::put(byte in){ + if(length < capacity){ + // save data byte at end of buffer + data[(position+length) % capacity] = in; + // increment the length + length++; + return 1; + } + // return failure + //Serial.print("E: put: "); + //Serial.println(length, DEC); + fillError=true; + return 0; +} + + +uint8_t ByteBuffer::putString(char *in){ + uint8_t count=0; + char *inString; + + inString=in; + uint8_t oldSREG = SREG; cli(); + while(length <= capacity){ + if (length == capacity) { + fillError=true; + return count; + } + // save data byte at end of buffer + data[(position+length) % capacity] = *inString; + // increment the length + length++; + inString++; + count++; + if (*inString == 0) { + if (count==0) fillError=true; // Serial.println("E: putString"); }; + SREG = oldSREG; // Restore register; reenables interrupts + return count; + } + } + SREG = oldSREG; // Restore register; reenables interrupts + return count; +} + +uint8_t ByteBuffer::putInFront(byte in){ + uint8_t oldSREG = SREG; cli(); + if(length < capacity){ + // save data byte at end of buffer + if( position == 0 ) + position = capacity-1; + else + position = (position-1)%capacity; + data[position] = in; + // increment the length + length++; + SREG = oldSREG; // Restore register; reenables interrupts + return 1; + } + // return failure + //Serial.println("E: putInFront"); + fillError=true; + SREG = oldSREG; // Restore register; reenables interrupts + return 0; +} + +byte ByteBuffer::get(){ + uint8_t oldSREG = SREG; cli(); + byte b = 0; + + if(length > 0){ + b = data[position]; + // move index down and decrement length + position = (position+1)%capacity; + length--; + } + SREG = oldSREG; // Restore register; reenables interrupts + return b; +} + +byte ByteBuffer::getFromBack(){ + byte b = 0; + if(length > 0){ + uint8_t oldSREG = SREG; cli(); + b = data[(position+length-1)%capacity]; + length--; + SREG = oldSREG; // Restore register; reenables interrupts + } + + return b; +} + +// +// Ints +// + +void ByteBuffer::putIntInFront(int in){ + byte *pointer = (byte *)∈ + putInFront(pointer[0]); + putInFront(pointer[1]); +} + +void ByteBuffer::putInt(int in){ + byte *pointer = (byte *)∈ + put(pointer[1]); + put(pointer[0]); +} + + +int ByteBuffer::getInt(){ + int ret; + byte *pointer = (byte *)&ret; + pointer[1] = get(); + pointer[0] = get(); + return ret; +} + +int ByteBuffer::getIntFromBack(){ + int ret; + byte *pointer = (byte *)&ret; + pointer[0] = getFromBack(); + pointer[1] = getFromBack(); + return ret; +} + +// +// Longs +// + +void ByteBuffer::putLongInFront(long in){ + byte *pointer = (byte *)∈ + putInFront(pointer[0]); + putInFront(pointer[1]); + putInFront(pointer[2]); + putInFront(pointer[3]); +} + +void ByteBuffer::putLong(long in){ + byte *pointer = (byte *)∈ + put(pointer[3]); + put(pointer[2]); + put(pointer[1]); + put(pointer[0]); +} + + +long ByteBuffer::getLong(){ + long ret; + byte *pointer = (byte *)&ret; + pointer[3] = get(); + pointer[2] = get(); + pointer[1] = get(); + pointer[0] = get(); + return ret; +} + +long ByteBuffer::getLongFromBack(){ + long ret; + byte *pointer = (byte *)&ret; + pointer[0] = getFromBack(); + pointer[1] = getFromBack(); + pointer[2] = getFromBack(); + pointer[3] = getFromBack(); + return ret; +} + + +// +// Floats +// + +void ByteBuffer::putFloatInFront(float in){ + byte *pointer = (byte *)∈ + putInFront(pointer[0]); + putInFront(pointer[1]); + putInFront(pointer[2]); + putInFront(pointer[3]); +} + +void ByteBuffer::putFloat(float in){ + byte *pointer = (byte *)∈ + put(pointer[3]); + put(pointer[2]); + put(pointer[1]); + put(pointer[0]); +} + +float ByteBuffer::getFloat(){ + float ret; + byte *pointer = (byte *)&ret; + pointer[3] = get(); + pointer[2] = get(); + pointer[1] = get(); + pointer[0] = get(); + return ret; +} + +float ByteBuffer::getFloatFromBack(){ + float ret; + byte *pointer = (byte *)&ret; + pointer[0] = getFromBack(); + pointer[1] = getFromBack(); + pointer[2] = getFromBack(); + pointer[3] = getFromBack(); + return ret; +} + + diff --git a/libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.h b/libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.h new file mode 100644 index 0000000..8916e58 --- /dev/null +++ b/libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.h @@ -0,0 +1,104 @@ +/* + ByteBuffer.h - A circular buffer implementation for Arduino + Created by Sigurdur Orn, July 19, 2010. siggi@mit.edu + Updated by GreyGnome (aka Mike Schwager) Thu Feb 23 17:25:14 CST 2012 + added the putString() method and the fillError variable. + added the checkError() and resetError() methods. The checkError() method resets the fillError variable + to false as a side effect. + added the ByteBuffer(unsigned int buf_size) constructor. + added the init() method, and had the constructor call it automagically. + protected certain sections of the code with cli()/sei() calls, for safe use by interrupts. + Also made the capacity, position, length, and fillError variables volatile, for safe use by interrupts. + */ + +#ifndef ByteBuffer_h +#define ByteBuffer_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include +#else + #include +#endif +//#include + +#define DEFAULTBUFSIZE 32 +class ByteBuffer +{ +public: + ByteBuffer() { + init(); + }; + ByteBuffer(unsigned int buf_size) { + init(buf_size); + }; + + // This method initializes the datastore of the buffer to a certain size. + void init(unsigned int buf_size); + + // This method initializes the datastore of the buffer to the default size. + void init(); + + // This method resets the buffer into an original state (with no data) + void clear(); + + // This method resets the fillError variable to false. + void resetError(); + + // This method tells you if your buffer overflowed at some time since the last + // check. The error state will be reset to false. + boolean checkError(); + + // This releases resources for this buffer, after this has been called the buffer should NOT be used + void deAllocate(); + + // Returns how much space is used in the buffer + int getSize(); + + // Returns the maximum capacity of the buffer + int getCapacity(); + + // This method returns the byte that is located at index in the buffer but doesn't modify the buffer like the get methods (doesn't remove the retured byte from the buffer) + byte peek(unsigned int index); + + // + // Put methods, either a regular put in back or put in front + // + uint8_t putInFront(byte in); + uint8_t put(byte in); + uint8_t putString(char *in); + + void putIntInFront(int in); + void putInt(int in); + + void putLongInFront(long in); + void putLong(long in); + + void putFloatInFront(float in); + void putFloat(float in); + + // + // Get methods, either a regular get from front or from back + // + byte get(); + byte getFromBack(); + + int getInt(); + int getIntFromBack(); + + long getLong(); + long getLongFromBack(); + + float getFloat(); + float getFloatFromBack(); + +private: + byte* data; + + volatile unsigned int capacity; + volatile unsigned int position; + volatile unsigned int length; + volatile boolean fillError; +}; + +#endif + diff --git a/libraries/PinChangeInt/Examples/GetPSTR/GetPSTR.h b/libraries/PinChangeInt/Examples/GetPSTR/GetPSTR.h new file mode 100644 index 0000000..aaab06a --- /dev/null +++ b/libraries/PinChangeInt/Examples/GetPSTR/GetPSTR.h @@ -0,0 +1,21 @@ +#ifndef INCLUDE_GETPSTR +#define INCLUDE_GETPSTR + +#if defined(ARDUINO) && ARDUINO >= 100 + #include +#else + #include "pins_arduino.h" + #include "WProgram.h" + #include "wiring.h" +#endif + +#define getPSTR(s) pgmStrToRAM(PSTR(s)) + +char *_pstr_to_print; +char *pgmStrToRAM(PROGMEM char *theString) { + free(_pstr_to_print); + _pstr_to_print=(char *) malloc(strlen_P(theString)); + strcpy_P(_pstr_to_print, theString); + return (_pstr_to_print); +} +#endif diff --git a/libraries/PinChangeInt/Examples/PinChangeIntExample/PinChangeIntExample.pde b/libraries/PinChangeInt/Examples/PinChangeIntExample/PinChangeIntExample.pde new file mode 100644 index 0000000..2f254d4 --- /dev/null +++ b/libraries/PinChangeInt/Examples/PinChangeIntExample/PinChangeIntExample.pde @@ -0,0 +1,77 @@ +// PinChangeIntExample, version 1.1 Sun Jan 15 06:24:19 CST 2012 +// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information. +//-------- define these in your sketch, if applicable ---------------------------------------------------------- +// You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts +// on any one or two of the three ports. If only a single port remains, the handler will be declared inline +// reducing the size and latency of the handler. +//#define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts +//#define NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts +// #define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts +// if there is only one PCInt vector in use the code can be inlined +// reducing latency and code size +// define DISABLE_PCINT_MULTI_SERVICE below to limit the handler to servicing a single interrupt per invocation. +// #define DISABLE_PCINT_MULTI_SERVICE +//-------- define the above in your sketch, if applicable ------------------------------------------------------ +#include + +// This example demonstrates a configuration of 3 interrupting pins and 2 interrupt functions. +// All interrupts are serviced immediately, but one of the pins (pin 4) will show you immediately +// on the Terminal. The other function connected to 2 pins sets an array member that is queried in loop(). +// You can then query the array at your leisure. +// This makes loop timing non-critical. + +// Add more Pins at your leisure. +// For the Analog Input pins used as digital input pins, and you can use 14, 15, 16, etc. +// or you can use A0, A1, A2, etc. (the Arduino code comes with #define's +// for the Analog Input pins and will properly recognize e.g., pinMode(A0, INPUT); +#define PIN1 2 +#define PIN2 3 +#define PIN3 4 + +uint8_t latest_interrupted_pin; +uint8_t interrupt_count[20]={0}; // 20 possible arduino pins +void quicfunc() { + latest_interrupted_pin=PCintPort::arduinoPin; + interrupt_count[latest_interrupted_pin]++; +}; + +// You can assign any number of functions to any number of pins. +// How cool is that? +void pin3func() { + Serial.print("Pin "); Serial.print(PIN3, DEC); Serial.println("!"); +} + +void setup() { + pinMode(PIN1, INPUT); digitalWrite(PIN1, HIGH); + PCintPort::attachInterrupt(PIN1, &quicfunc, FALLING); // add more attachInterrupt code as required + pinMode(PIN2, INPUT); digitalWrite(PIN2, HIGH); + PCintPort::attachInterrupt(PIN2, &quicfunc, FALLING); + pinMode(PIN3, INPUT); digitalWrite(PIN3, HIGH); + PCintPort::attachInterrupt(PIN3, &pin3func, CHANGE); + Serial.begin(115200); + Serial.println("---------------------------------------"); +} + +uint8_t i; +void loop() { + uint8_t count; + Serial.print("."); + delay(1000); + for (i=0; i < 20; i++) { + if (interrupt_count[i] != 0) { + count=interrupt_count[i]; + interrupt_count[i]=0; + Serial.print("Count for pin "); + if (i < 14) { + Serial.print("D"); + Serial.print(i, DEC); + } else { + Serial.print("A"); + Serial.print(i-14, DEC); + } + Serial.print(" is "); + Serial.println(count, DEC); + } + } +} + diff --git a/libraries/PinChangeInt/Examples/PinChangeIntSpeedTest/PinChangeIntSpeedTest.pde b/libraries/PinChangeInt/Examples/PinChangeIntSpeedTest/PinChangeIntSpeedTest.pde new file mode 100644 index 0000000..f0ac0f2 --- /dev/null +++ b/libraries/PinChangeInt/Examples/PinChangeIntSpeedTest/PinChangeIntSpeedTest.pde @@ -0,0 +1,265 @@ +// PinChangeIntSpeedTest by GreyGnome aka Mike Schwager. Version numbers here refer to this sketch. +// Version 1.0 - initial version +// Version 1.1 - added code to test digitalRead() +// Version 1.2 - added new comments for the #define's for the NO_PORTx_PINCHANGES. +// Version 1.3 - includes cbiface.h with ooPinChangeInt, rather than cb.h +// Version 1.4 - testing version 2.10Beta with robtillaart's optimization +// Also added a #define/#undef INLINE_PCINTFUNC for inlining of the function called by the interrupt. +// Default: #undef for using the function as per usual. Changed PCIVERSION so that +// ooPinChangeInt starts at 1000 instead of 200. Modified the "Start" message to show "Start..", pause +// for 1 second, show "*\n" (where \n is a newline), pause for 1 second, then run the test. +// Version 1.4 - made this compatible with version 1.5 of PinChangeInt +// Version 1.5 - modified it to use #define OOPCIVERSION for ooPinChangeInt + +// This version number is for ooPinChangeInt +//#define OOPCIVERSION 1030 +#ifndef OOPCIVERSION +#define PCIVERSION 217 // 110 if using PinChangeInt-1.1, 120 for version 1.2 + // 1000 for ooPinChangeIntversion 1.00, 1001 for ooPinChangeInt version 1.01, etc. +#endif + +//-------- define these in your sketch, if applicable ---------------------------------------------------------- +// You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts +// on any one or two of the three ports. If only a single port remains, the handler will be declared inline +// reducing the size and latency of the handler. +#undef NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts +#undef NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts +// #define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts +// You can reduce the code size by 20-50 bytes, and you can speed up the interrupt routine +// slightly by declaring that you don't care if the static variables PCintPort::pinState and/or +// PCintPort::arduinoPin are set and made available to your interrupt routine. +// #define NO_PIN_STATE // to indicate that you don't need the pinState +// #define NO_PIN_NUMBER // to indicate that you don't need the arduinoPin +// if there is only one PCInt vector in use the code can be inlined +// reducing latency and code size +// define DISABLE_PCINT_MULTI_SERVICE below to limit the handler to servicing a single interrupt per invocation. +//#define DISABLE_PCINT_MULTI_SERVICE +//-------- define the above in your sketch, if applicable ------------------------------------------------------ +#if defined(OOPCIVERSION) + #define LIBRARYUNDERTEST "ooPinChangeInt" + #include + #if PCIVERSION == 1001 + #include + #else + #include + #endif +#else + #define LIBRARYUNDERTEST "PinChangeInt" + #include +#endif + +#define SERIALSTUFF // undef to take out all serial statements. Default: #define for measuring time. +#undef MEMTEST // undef to take out memory tests. Default: #undef for measuring time. +#undef INLINE_PCINTFUNC // define to inline the function called from the interrupt. This should have no effect, + // because the compiler will store the registers upon calling the interrupt routine, just + // like calling a function. Still, we test all assumptions. +//----------------------- +// NOTE: BECAUSE OF COLLISIONS in these libraries, you CANNOT have both libraries: PinChangeInt +// and ooPinChangeInt in the libraries directory at the same time. That said, under UNIX-y operating +// systems, it's easy to move the library directory to a name such as "PinChangeInt-1.3", which the +// Arduino will not recognize, and then create a symbolic link when you want to use a library. Such as: +// cd ~/Documents/Arduino/libaries +// mv PinChangeInt PinChangeInt-1.30 +// mv ooPinChangeInt ooPinChangeInt-1.00 +// ln -s PinChangeInt-1.30 PinChangeInt + +#undef FLASH // to flash LED on pin 13 during test + +#ifdef MEMTEST +#include +#endif + +#define TEST 6 + +#if TEST == 1 +#define PTEST 2 // pin to trigger interrupt. pins 0 and 1 are used +#define PLOW 2 // by Serial, so steer clear of them! +#define PHIGH 2 // Interrupts are attached to these pins + +#elif TEST == 2 // see the #if TEST == 2 || TEST == 3 code, below +#define PTEST 2 +#define PLOW 2 +#define PHIGH 2 // need to attachInterrupt to 5 in the code + +#elif TEST == 3 // see the #if TEST == 2 || TEST == 3 code, below +#define PTEST 5 +#define PLOW 2 +#define PHIGH 2 // need to attachInterrupt to 5 in the code + +#elif TEST == 4 +#define PTEST 2 +#define PLOW 2 +#define PHIGH 5 + +#elif TEST == 5 +#define PTEST 3 +#define PLOW 2 +#define PHIGH 5 + +#elif TEST == 6 +#define PTEST 4 +#define PLOW 2 +#define PHIGH 5 + +#elif TEST == 7 +#define PTEST 5 +#define PLOW 2 +#define PHIGH 5 +#endif + +uint8_t qf0; + +#ifdef INLINE_PCINTFUNC +#define INLINE_PCINTFUNC inline +#else +#define INLINE_PCINTFUNC +#endif +INLINE_PCINTFUNC void quicfunc(); +void quicfunc() { + qf0=TCNT0; +} + +#if defined(OOPCIVERSION) +class speedy : public CallBackInterface +{ + public: + uint8_t id; + static uint8_t var0; + speedy () { id=0; }; + speedy (uint8_t _i): id(_i) {}; + + void cbmethod() { + speedy::var0=TCNT0; + //Serial.print("Speedy method "); // debugging + //Serial.println(id, DEC); + }; +}; +uint8_t speedy::var0=0; +#endif + +volatile uint8_t *led_port; +volatile uint8_t *pinT_OP; +volatile uint8_t *pinT_IP; +uint8_t led_mask, not_led_mask; +uint8_t pinT_M, not_pinT_M; +volatile uint8_t pintest, pinIntLow, pinIntHigh; +uint8_t totalpins; +#if defined(OOPCIVERSION) +speedy speedster[8]={speedy(0), speedy(1), speedy(2), speedy(3), speedy(4), speedy(5), speedy(6), speedy(7) }; +#endif +#ifdef MEMTEST +int freemem; +#endif + +int i=0; + +#define PINLED 13 +void setup() +{ +#ifdef SERIALSTUFF + Serial.begin(115200); Serial.println("---------------------------------------"); +#endif // SERIALSTUFF + // set up ports for trigger + pinMode(0, OUTPUT); digitalWrite(0, HIGH); + pinMode(1, OUTPUT); digitalWrite(1, HIGH); + pinMode(2, OUTPUT); digitalWrite(2, HIGH); + pinMode(3, OUTPUT); digitalWrite(3, HIGH); + pinMode(4, OUTPUT); digitalWrite(4, HIGH); + pinMode(5, OUTPUT); digitalWrite(5, HIGH); + pinMode(6, OUTPUT); digitalWrite(6, HIGH); + pinMode(7, OUTPUT); digitalWrite(7, HIGH); +#ifdef FLASH + led_port=portOutputRegister(digitalPinToPort(PINLED)); + led_mask=digitalPinToBitMask(PINLED); + not_led_mask=led_mask^0xFF; + pinMode(PINLED, OUTPUT); digitalWrite(PINLED, LOW); +#endif + // ***************************************************************************** + // set up ports for output ************ PIN TO TEST IS GIVEN HERE ************** + // ***************************************************************************** + pintest=PTEST; + pinIntLow=PLOW; pinIntHigh=PHIGH; // Interrupts are attached to these pins + // ***************************************************************************** + // ***************************************************************************** + pinT_OP=portOutputRegister(digitalPinToPort(pintest)); // output port + pinT_IP=portInputRegister(digitalPinToPort(pintest)); // input port + pinT_M=digitalPinToBitMask(pintest); // mask + not_pinT_M=pinT_M^0xFF; // not-mask + *pinT_OP|=pinT_M; + for (i=pinIntLow; i <= pinIntHigh; i++) { +#if defined(OOPCIVERSION) + PCintPort::attachInterrupt(i, &speedster[i], CHANGE); // C++ technique; v1.3 or better +#endif +#if defined(PCIVERSION) + PCintPort::attachInterrupt((uint8_t) i, &quicfunc, CHANGE); // C technique; v1.2 or earlier +#endif + } +#if TEST == 2 || TEST == 3 + i=5; totalpins=2; +#if defined(OOPCIVERSION) + PCintPort::attachInterrupt(i, &speedster[i], CHANGE); // C++ technique; v1.3 or better +#endif +#if defined(PCIVERSION) + PCintPort::attachInterrupt(i, &quicfunc, CHANGE); // C technique; v1.2 or earlier +#endif +#else + totalpins=pinIntHigh - pinIntLow + 1; +#endif + i=0; +} // end setup() + +uint8_t k=0; +unsigned long milliStart, milliEnd, elapsed; +void loop() { + k=0; + *pinT_OP|=pinT_M; // pintest to 1 +#ifdef SERIALSTUFF + Serial.print(LIBRARYUNDERTEST); Serial.print(" "); + Serial.print("TEST: "); Serial.print(TEST, DEC); Serial.print(" "); +#ifndef MEMTEST + Serial.print("test pin mask: "); Serial.print(pinT_M, HEX); + Serial.print(". Total of "); Serial.print(totalpins, DEC); Serial.println(" pins enabled."); +#endif +#ifdef MEMTEST + freemem=freeMemory(); Serial.print("Free memory: "); Serial.println(freemem, DEC); +#endif +#endif + delay(1000); + Serial.print("Start.."); + delay(1000); Serial.print("*"); + #ifdef FLASH + *led_port|=led_mask; + #endif + milliStart=millis(); + while (k < 10) { + i=0; + while (i < 10000) { + *pinT_OP&=not_pinT_M; // pintest to 0 ****************************** 16.8 us + *pinT_OP|=pinT_M; // pintest to 1 ****************************** ...to get here + i++; + } + k++; + } + milliEnd=millis(); + #ifdef FLASH + *led_port&=not_led_mask; + #endif + elapsed=milliEnd-milliStart; + #ifndef MEMTEST + Serial.print(" Elapsed: "); + Serial.println(elapsed, DEC); + #endif + #ifdef SERIALSTUFF + Serial.print("Interrupted pin: "); + #if defined(OOPCIVERSION) + Serial.println(speedster[pintest].id, DEC); + #else + Serial.println(PCintPort::arduinoPin, DEC); + #endif +#ifdef MEMTEST + freemem=freeMemory(); Serial.print("END-Free memory: "); Serial.println(freemem, DEC); +#endif +#endif + delay(500); +} + diff --git a/libraries/PinChangeInt/Examples/PinChangeIntTest/PinChangeIntTest.pde b/libraries/PinChangeInt/Examples/PinChangeIntTest/PinChangeIntTest.pde new file mode 100644 index 0000000..c8df127 --- /dev/null +++ b/libraries/PinChangeInt/Examples/PinChangeIntTest/PinChangeIntTest.pde @@ -0,0 +1,344 @@ +// PinChangeIntTest +// version 1.0 Wed Feb 15 07:25:09 CST 2012 +// Version 1.1 Fri Jun 22 19:10:50 CDT 2012 minor tweaks to eliminate compiler warnings. Also, there were bugfixes in ByteBuffer. +// I had some "cli()" without "sei()" in there. +// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information. +// This sketch requires the ByteBuffer library, which is found in the PinChangeInt zipfile. +//-------- define these in your sketch, if applicable ---------------------------------------------------------- +//-------- This must go ahead of the #include statement -------------------------------------------------------- +// You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts +// on any one or two of the three ports. If only a single port remains, the handler will be declared inline +// reducing the size and latency of the handler. +// #define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts +// #define NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts +// #define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts +// You can reduce the code size by 20-50 bytes, and you can speed up the interrupt routine +// slightly by declaring that you don't care if the static variables PCintPort::pinState and/or +// PCintPort::arduinoPin are set and made available to your interrupt routine. +// #define NO_PIN_STATE // to indicate that you don't need the pinState +// #define NO_PIN_NUMBER // to indicate that you don't need the arduinoPin +// if there is only one PCInt vector in use the code can be inlined +// reducing latency and code size +// define DISABLE_PCINT_MULTI_SERVICE below to limit the handler to servicing a single interrupt per invocation. +// #define DISABLE_PCINT_MULTI_SERVICE +// The following is intended for testing purposes. If defined, then a variable PCintPort::pinMode can be read +// in your interrupt subroutine. It is not defined by default: +// #define PINMODE +//-------- define the above in your sketch, if applicable ------------------------------------------------------ +#define PINMODE +#define FLASH +#include +#include + +// This example demonstrates a configuration of 6 interrupting pins and 3 interrupt functions. +// A variety of interrupting pins have been chosen, so as to test all PORTs on the Arduino. +// The pins are as follows: +#define tPIN1 2 // port D +#define tPIN2 3 +#define tPIN3 11 // Port B +#define tPIN4 12 +#define tPIN5 A3 // Port C, also can be given as "17" +#define tPIN6 A4 // starts and stops the count +// All pins send interrupts. Arduino pins 2 and A4 (tPIN1,6) interrupt on FALLING. +// Arduino pins 3 and 12 (tPIN2,4) interrupt on RISING. +// Arduino pins 11 and A3 (tPIN5) interrupts on CHANGE. +// quicfunc0 is attached to Arduino pins 2, 3, 11, and 12 (tPIN1-4) +// quicfunc1 is attached to Arduino pin A3 (tPIN5) +// quicfunc2 is attached to Arduino pin A4 (tPIN6). +// NOTE: +// For the Analog Input pins used as digital input pins, you can use numbers such as 14, 15, 16, etc. +// or you can use A0, A1, A2, etc. (the Arduino code comes with #define's for the Analog Input pin +// names and will properly recognize e.g., pinMode(A0, INPUT)); + +// HOW IT WORKS +// The interrupt on Arduino pin A4 (tPIN6) will, when triggered, start the counting of interrupts. +// The array interrupt_count0[20] is updated in the interrupts; each cell keeps track of the number +// of interrupts on one of the 20 available interrupt pins on the Arduino. Every second in the main +// loop the array is scanned and registered interrupts are reported for all pins interrupted since +// the previous second. If no interrupts, the output is quiet. + +// tPIN6 is special. Not only does it start the counting of the interrups, but it turns on and off +// interrupts on pins 2, 11, and A3/17 (tPIN1, tPIN3, tPIN5). All pins start by interrupting, but after +// the count is turned on and then turned off, the 3 pins are detached from interrupts. +// Everytime thereafter when the count is turned off the 3 pins are detached. They are reattached +// when turned on. + +// Output is copied to a buffer, because we can't do a Serial.print() statement in an interrupt +// routine. The main loop checks for entries in the buffer and prints them if found. +// Output looks like this: +// -F- - an interrupt triggered by a falling signal occurred. +// +R+ - an interrupt triggered by a rising signal occurred. +// *C* - an interrupt triggered by a change in signal occurred. +// f#p#-P# - f# shows the interrupt subroutine that was called: 0, 1, or 2 +// - p# shows the pin number that triggered the interrupt +// - P# shows the port that this pin number is attached to. 2 is PORTB, 3 is PORTC, 4 is PORTD + +// HOW TO CONNECT +// Each pin gets a momentary contact switch connected to it. One side of the switch should connect +// to ground. The other side of the switch connects to the Arduino pin. For my purposes, I am using +// two rotary encoders. Each encoder contains 3 switches. But 6 regular pushbuttons would work, too. + +/* WHAT TO LOOK FOR + Output is sent to the serial line, so the Arduino IDE's serial terminal should be opened. + Upon startup, press tPINS1-5. You will see output like this: +-F-f0p2-P4 (counting off) +..*C*f0p11-P2 (counting off) ++R+f0p3-P4 (counting off) + This shows that + 1. an interrupt was triggered on a falling signal (*F*). It called (f0) function 0, which is quicfunc0. + The triggering pin was (p2) Arduuino pin 2, which is on (P4) Port 4 (PORTD). Counting of this interrupt is + off, so you will not see any output from the main loop. + 2. Two dots appeared. Dots came from iterations of loop(), so these 2 dots show that the two interrupts happened 2 seconds apart. + 3. an interrupt was triggered on a change in signal (*C*). It called quicfunc0, from Arduino pin 11, on Port 2 (PORTB). + The interrupt was not counted. + 4. an interrupt was triggered on a rising signal (+R+). It called quicfunc0, from Arduino pin 3, on Purt 4 (PORTD). + The pin should have started out at the high level, so likely the signal fell during onother interrupt, and now + the rise has been caught. + + Now press the button attached to tPIN6 (in our case, A4 or D18). You will see something like this: +-F-START! f2p18-P3 +.Count for pin A4 is 1 + This shows that + 1. The counting machanism (START!) was triggered by a folling signal (-F-) on pin 18 (p18) which is in Port 3 (P3) (which == PORTC) and + function f2 was called (f2). + 2. A dot appeared, which came from loop() because a second passed. + 3. The count for p18 or A4 was displayed. + + Now you will see messages for all the pins that you manipulate, for example: +*C*f0p11-P2 ++R+f0p3-P4 +*C*f0p11-P2 ++R+f0p3-P4 +*C*f0p11-P2 +.Count for pin D3 is 6 +Count for pin D11 is 9 +.+R+f0p3-P4 +-F-f0p2-P4 +.Count for pin D2 is 1 +Count for pin D3 is 1 + These codes reflect the interrupts, as described above. This output will take place until you press tPIN6: +-F-f2: STOP! Counting off. +Interrupt OFF on tPIN1 (2) tPIN3 (11) tPIN5 (17) + Then you will see output like this: +.....................+R+f0p12-P2 (counting off) +.+R+f0p12-P2 (counting off) ++R+f0p12-P2 (counting off) ++R+f0p12-P2 (counting off) + and tPIN1, tPIN3, and tPIN5 will not trigger interrupts. +*/ +// NOTES +// Output overwrites: +// It's possible during moderately fast interrupts to see your print output get garbled; eg, +// +R+f0p12-P2 (+R+f0p12-P2 (counting +R+f0p12-P2 (cou+R+f0p12-P+R+f0p12 +// This is because the print of the buffer takes place inside a while loop, and it can +// be interrupted and new data inserted into the buffer at a midpoint of the buffer's text. +// Just by spinning my rotary encoders I can readily generate over 200 interrupts per second +// on a pin, which is easily fast enough to overrun Serial output at 115,200 bps. +// The lesson here? ...Interrupts are tricky, and interrupt service routines should be fast. +// Just sayin'. + +// Pins: +// We want to use pins from each of ports B, C and D. So choose wisely. Ports are shown in +// this diagram of the ATmega328P chip. PD0 means "Port D, pin 0". PC3 means "Port C, Pin 3", +// PB2 means "Port B, pin 2" and so on. The corresponding Arduino pins are in parentheses. +// So PB2 is Arduino pin D 10, for example. +/* + +-\/-+ + PC6 1| |28 PC5 (AI 5) + (D 0) PD0 2| |27 PC4 (AI 4) + (D 1) PD1 3| |26 PC3 (AI 3) + (D 2) PD2 4| |25 PC2 (AI 2) + PWM+ (D 3) PD3 5| |24 PC1 (AI 1) + (D 4) PD4 6| |23 PC0 (AI 0) + VCC 7| |22 GND + GND 8| |21 AREF + PB6 9| |20 AVCC + PB7 10| |19 PB5 (D 13) + PWM+ (D 5) PD5 11| |18 PB4 (D 12) + PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM + (D 7) PD7 13| |16 PB2 (D 10) PWM + (D 8) PB0 14| |15 PB1 (D 9) PWM + +----+ +*/ + +uint8_t pins[6]={ tPIN1, tPIN2, tPIN3, tPIN4, tPIN5, tPIN6 }; +uint8_t ports[6]={ 0, 0, 0, 0, 0, 0 }; + +uint8_t latest_interrupted_pin; +uint8_t interrupt_count[20]={0}; // 20 possible arduino pins +uint8_t port; +uint8_t mode; + +ByteBuffer printBuffer(80); +char charArray[16]; +char numBuffer[4] = { 0, 0, 0, 0 }; +uint8_t printFull=0; + +volatile boolean start=0; +volatile boolean initial=true; +long begintime=0; +long now=0; + +void uint8ToString(char *outString, uint8_t number) { + uint8_t hundreds=0; + uint8_t tens=0; + uint8_t ones=0; + + while (number >= 100 ) { + hundreds++; + number-=100; + } + while (number >= 10 ) { + tens++; + number-=10; + } + ones=number; + ones+=48; + if (hundreds > 0) { hundreds+=48; tens+=48; outString[0]=hundreds; outString[1]=tens; outString[2]=ones; outString[3]=0; } + else if (tens > 0) { tens+=48; outString[0]=tens; outString[1]=ones; outString[2]=0; } + else { outString[0]=ones; outString[1]=0; }; +} + +void showMode() { + switch (mode) { + case FALLING: + printBuffer.putString((char *) "-F-"); + break; + case RISING: + printBuffer.putString((char *) "+R+"); + break; + case CHANGE: + printBuffer.putString((char *) "*C*"); + break; + } +} + +void quicfunc0() { + latest_interrupted_pin=PCintPort::arduinoPin; + mode=PCintPort::pinmode; + showMode(); + if (start==1) { + interrupt_count[latest_interrupted_pin]++; + } + uint8ToString(numBuffer, latest_interrupted_pin); + printBuffer.putString((char *) "f0p"); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P"); + uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin)); + printBuffer.putString(numBuffer); + if (start !=1) printBuffer.putString((char *) " (counting off)"); + printBuffer.putString((char *) "\n"); +}; + +void quicfunc1() { + latest_interrupted_pin=PCintPort::arduinoPin; + mode=PCintPort::pinmode; + showMode(); + if (start==1) { + interrupt_count[latest_interrupted_pin]++; + } + uint8ToString(numBuffer, latest_interrupted_pin); + printBuffer.putString((char *) "f1p"); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P"); + uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin)); + printBuffer.putString(numBuffer); + if (start !=1) printBuffer.putString((char *) " (counting off)"); + printBuffer.putString((char *) "\n"); +}; + +void quicfunc2() { + latest_interrupted_pin=PCintPort::arduinoPin; + mode=PCintPort::pinmode; + showMode(); + if (start == 1) { + printBuffer.putString((char *) "f2: STOP! Counting off.\n"); + printBuffer.putString((char *) "Interrupt OFF on tPIN1 ("); uint8ToString(numBuffer, tPIN1), printBuffer.putString(numBuffer); + printBuffer.putString((char *) ") tPIN3 (");uint8ToString(numBuffer, tPIN3), printBuffer.putString(numBuffer); + printBuffer.putString((char *) ") tPIN5 (");uint8ToString(numBuffer, tPIN5), printBuffer.putString(numBuffer); + printBuffer.putString((char *) ")\n"); + PCintPort::detachInterrupt(tPIN1); PCintPort::detachInterrupt(tPIN3); PCintPort::detachInterrupt(tPIN5); + start=0; + } else { + start=1; + interrupt_count[latest_interrupted_pin]++; + printBuffer.putString((char *) "START! f2p"); + uint8ToString(numBuffer, latest_interrupted_pin); + printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P"); + uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin)); + printBuffer.putString(numBuffer); printBuffer.putString((char *) "\n"); + if (! initial) { + PCintPort::attachInterrupt(tPIN1, &quicfunc0, FALLING); + PCintPort::attachInterrupt(tPIN3, &quicfunc0, CHANGE); + PCintPort::attachInterrupt(tPIN5, &quicfunc1, CHANGE); + } else { + initial=false; + } + } +}; + +uint8_t i; +void setup() { + Serial.begin(115200); + delay(250); + Serial.println("Test"); + delay(500); + for (i=0; i < 7; i++) { + pinMode(pins[i], INPUT); digitalWrite(pins[i], HIGH); + ports[i]=digitalPinToPort(pins[i]); + switch (pins[i]) { + case tPIN1: + PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING); + break; + case tPIN3: + PCintPort::attachInterrupt(pins[i], &quicfunc0, CHANGE); + break; + case tPIN2: + case tPIN4: + PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING); + break; + case tPIN5: + PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE); + break; + case tPIN6: + PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING); + break; + } + } + //Serial.println(printBuffer.getCapacity(), DEC); + //Serial.println("*---------------------------------------*"); + Serial.print("*---*"); + delay(250); + begintime=millis(); +} + +void loop() { + now=millis(); + uint8_t count; + char outChar; + // uint8_t bufsize; + //if (printBuffer.getSize() != 0) { Serial.print("SZ:"); Serial.println (printBuffer.getSize(), DEC); }; + //bufsize=printBuffer.getSize(); + //if (bufsize > 0) { Serial.print("S:"); Serial.println(bufsize); } + while ((outChar=(char)printBuffer.get()) != 0) Serial.print(outChar); + if ((now - begintime) > 1000) { + Serial.print("."); + if (printBuffer.checkError()) { + Serial.println("NOTICE: Some output lost due to filled buffer."); + } + for (i=0; i < 20; i++) { + if (interrupt_count[i] != 0) { + count=interrupt_count[i]; + interrupt_count[i]=0; + Serial.print("Count for pin "); + if (i < 14) { + Serial.print("D"); + Serial.print(i, DEC); + } else { + Serial.print("A"); + Serial.print(i-14, DEC); + } + Serial.print(" is "); + Serial.println(count, DEC); + } + } + begintime=millis(); + } +} + diff --git a/libraries/PinChangeInt/Examples/PinChangeIntTest2/PinChangeIntTest2.ino b/libraries/PinChangeInt/Examples/PinChangeIntTest2/PinChangeIntTest2.ino new file mode 100644 index 0000000..aec34c4 --- /dev/null +++ b/libraries/PinChangeInt/Examples/PinChangeIntTest2/PinChangeIntTest2.ino @@ -0,0 +1,275 @@ +//#define DISABLE_PCINT_MULTI_SERVICE +#define PINMODE +#define FLASH +#include +#include +#include + +// This example demonstrates a configuration of 6 interrupting pins and 3 interrupt functions. +// A variety of interrupting pins have been chosen, so as to test all PORTs on the Arduino. +// The pins are as follows: +#define tPIN1 2 // port D +#define tPIN2 3 +#define tPIN3 11 // Port B +#define tPIN4 12 +#define tPIN5 A3 // Port C, also can be given as "17" +#define tPIN6 A4 // starts and stops the count + +uint8_t pins[6]={ tPIN1, tPIN2, tPIN3, tPIN4, tPIN5, tPIN6 }; +uint8_t ports[6]={ 0, 0, 0, 0, 0, 0 }; + +uint8_t latest_interrupted_pin; +uint8_t interrupt_count[20]={0}; // 20 possible arduino pins +uint8_t port; +uint8_t mode; + +ByteBuffer printBuffer(200); +char charArray[16]; +char numBuffer[5] = { 0, 0, 0, 0, 0 }; +uint8_t printFull=0; + +volatile boolean start=0; +volatile boolean initial=true; +long begintime=0; +long now=0; + +void uint8ToHexString(char *outString, uint8_t theByte) { + outString[0]='0'; outString[1]='x'; + uint8_t hinybble=theByte>>4; + uint8_t lonybble=theByte & 0x0F; + if (hinybble < 0x0a) outString[2]=hinybble+48; + else outString[2]=hinybble+55; + if (lonybble < 0x0a) outString[3]=lonybble+48; + else outString[3]=lonybble+55; + outString[4]=0; +} + +void uint8ToString(char *outString, uint8_t number) { + uint8_t hundreds=0; + uint8_t tens=0; + uint8_t ones=0; + + while (number >= 100 ) { + hundreds++; + number-=100; + } + while (number >= 10 ) { + tens++; + number-=10; + } + ones=number; + ones+=48; + if (hundreds > 0) { hundreds+=48; tens+=48; outString[0]=hundreds; outString[1]=tens; outString[2]=ones; outString[3]=0; } + else if (tens > 0) { tens+=48; outString[0]=tens; outString[1]=ones; outString[2]=0; } + else { outString[0]=ones; outString[1]=0; }; +} + +void showMode() { + switch (mode) { + case FALLING: + printBuffer.putString(getPSTR("-F-")); + break; + case RISING: + printBuffer.putString(getPSTR("+R+")); + break; + case CHANGE: + printBuffer.putString(getPSTR("*C*")); + break; + } +} + +/* +void quicfunc0() { + latest_interrupted_pin=PCintPort::arduinoPin; + mode=PCintPort::pinmode; + showMode(); + if (start==1) { + interrupt_count[latest_interrupted_pin]++; + } + uint8ToString(numBuffer, latest_interrupted_pin); + printBuffer.putString((char *) "f0p"); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P"); + uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin)); + printBuffer.putString(numBuffer); + if (start !=1) printBuffer.putString(getPSTR(" no count")); + printBuffer.putString((char *) "\n"); +}; + +void quicfunc1() { + latest_interrupted_pin=PCintPort::arduinoPin; + mode=PCintPort::pinmode; + showMode(); + if (start==1) { + interrupt_count[latest_interrupted_pin]++; + } + uint8ToString(numBuffer, latest_interrupted_pin); + printBuffer.putString(getPSTR("f1p")); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P"); + uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin)); + printBuffer.putString(numBuffer); + if (start !=1) printBuffer.putString(getPSTR(" (counting off)")); + printBuffer.putString((char *) "\n"); +}; +*/ + +void quicfunc2() { + //*led_port|=led_mask; + //*led_port&=not_led_mask; // 2 micros to here (ie, 2 micros used to push registers and call subroutine) + latest_interrupted_pin=PCintPort::arduinoPin; + mode=PCintPort::pinmode; + showMode(); + *led_port|=led_mask; // 73 micros to get here from above. Used in "Rigol Timing Example" + *led_port&=not_led_mask; + //uint8ToString(numBuffer, PCintPort::s_count); printBuffer.putString(numBuffer); + *led_port|=led_mask; // 73 micros to get here from above. Second pulse in "Rigol Timing Example" + *led_port&=not_led_mask; + printBuffer.putString(getPSTR(" f2: P"));/* + uint8ToHexString(numBuffer, *portInputRegister(3)); printBuffer.putString(numBuffer);// C port + printBuffer.putString(getPSTR(" pin:")); uint8ToString(numBuffer, latest_interrupted_pin); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" c")); uint8ToHexString(numBuffer, PCintPort::curr); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" l")); uint8ToHexString(numBuffer, PCintPort::s_lastPinView); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" r")); uint8ToHexString(numBuffer, PCintPort::s_portRisingPins); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" f")); uint8ToHexString(numBuffer, PCintPort::s_portFallingPins); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" m")); uint8ToHexString(numBuffer, PCintPort::s_pmask); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" P")); printBuffer.put(PCintPort::s_PORT); printBuffer.putString("\r\n"); + printBuffer.putString(getPSTR("cp")); uint8ToHexString(numBuffer, PCintPort::s_changedPins); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" cXORlpv")); uint8ToHexString(numBuffer, PCintPort::s_currXORlastPinView); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" rp_nCurr")); uint8ToHexString(numBuffer, PCintPort::s_portRisingPins_nCurr); printBuffer.putString(numBuffer); + printBuffer.putString(getPSTR(" fp_nNCurr")); uint8ToHexString(numBuffer, PCintPort::s_portFallingPins_nNCurr); printBuffer.putString(numBuffer); + */printBuffer.putString("\r\n"); + if (PCintPort::pcint_multi > 0) { + printBuffer.putString("MULTI!\n"); PCintPort::pcint_multi=0; + } + if (PCintPort::PCIFRbug > 0) { printBuffer.putString("ERROR: BUG- PCIFR should be reset!"); PCintPort::PCIFRbug=0; } + //s_registers, if it existed, could be used to keep a running queue of the latest interrupts that have + //been serviced by the PCint(). But generally I don't think it's necessary for debugging at this point (famous last words?) + /*if (PCintPort::s_count > 2) { + for (uint8_t i=0; i < PCintPort::s_count; i++) { + uint8ToHexString(numBuffer, PCintPort::s_registers[i]); printBuffer.putString(numBuffer); printBuffer.putString(" "); + } + } + PCintPort::s_count=0;*/ + /* + if (start == 1) { + printBuffer.putString(getPSTR("STOP Count off\n")); + printBuffer.putString(getPSTR("Intr OFF: (")); uint8ToString(numBuffer, tPIN1), printBuffer.putString(numBuffer); + printBuffer.putString((char *) " "); uint8ToString(numBuffer, tPIN3), printBuffer.putString(numBuffer); + printBuffer.putString((char *) " "); uint8ToString(numBuffer, tPIN5), printBuffer.putString(numBuffer); + printBuffer.putString((char *) ")\n"); + PCintPort::detachInterrupt(tPIN1); PCintPort::detachInterrupt(tPIN3); PCintPort::detachInterrupt(tPIN5); + start=0; + } else { + start=1; + interrupt_count[latest_interrupted_pin]++; + printBuffer.putString(getPSTR("START! p")); + uint8ToString(numBuffer, latest_interrupted_pin); + printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P"); + // MIKE put the REAL PORT HERE + uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin)); + printBuffer.putString(numBuffer); printBuffer.putString((char *) "\n"); + if (! initial) { + PCintPort::attachInterrupt(tPIN1, &quicfunc0, FALLING); + PCintPort::attachInterrupt(tPIN3, &quicfunc0, CHANGE); + PCintPort::attachInterrupt(tPIN5, &quicfunc1, CHANGE); + } else { + initial=false; + } + }*/ +}; + +uint8_t i; +char hexBuffer[5]; +void setup() { + int8_t returncode=1; + Serial.begin(115200); + Serial.println("Test"); + delay(500); + for (i=5; i < 6; i++) { + pinMode(pins[i], INPUT); digitalWrite(pins[i], HIGH); + ports[i]=digitalPinToPort(pins[i]); + switch (pins[i]) { + /*case tPIN1: + #if PCINT_VERSION > 2100 + returncode=PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING); + #else + PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING); + #endif + Serial.println(getPSTR("FIRST FAILURE OK.")); + break; + case tPIN3: + #if PCINT_VERSION > 2100 + returncode=PCintPort::attachInterrupt(pins[i], &quicfunc0, CHANGE); + #else + PCintPort::attachInterrupt(pins[i], &quicfunc0, CHANGE); + #endif + break; + case tPIN2: + case tPIN4: + #if PCINT_VERSION > 2100 + returncode=PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING); + #else + PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING); + #endif + break; + case tPIN5: + #if PCINT_VERSION > 2100 + returncode=PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE); + #else + PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE); + #endif + break;*/ + case tPIN6: + #if PCINT_VERSION > 2100 + returncode=PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING); + #else + PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING); + #endif + break; + } + #if PCINT_VERSION > 2100 + Serial.print(getPSTR("setup(): Interrupt attach ")); + if (returncode != 1) Serial.print(getPSTR("unsuccessful ")); + else Serial.print(getPSTR("GOOD ")); + Serial.print(pins[i], DEC); + Serial.print(getPSTR(":pin, code: ")); Serial.println(returncode, DEC); + #endif + } + //Serial.println(printBuffer.getCapacity(), DEC); + //Serial.println("*---------------------------------------*"); + Serial.print("*---*"); + delay(250); + begintime=millis(); +} + +void loop() { + now=millis(); + uint8_t count; + char outChar; + // uint8_t bufsize; + //if (printBuffer.getSize() != 0) { Serial.print("SZ:"); Serial.println (printBuffer.getSize(), DEC); }; + //bufsize=printBuffer.getSize(); + //if (bufsize > 0) { Serial.print("S:"); Serial.println(bufsize); } + while ((outChar=(char)printBuffer.get()) != 0) Serial.print(outChar); + if ((now - begintime) > 1000) { + Serial.print("."); + if (printBuffer.checkError()) { + Serial.println(getPSTR("!Some output lost due to full buffer!")); + } + for (i=0; i < 20; i++) { + if (interrupt_count[i] != 0) { + count=interrupt_count[i]; + interrupt_count[i]=0; + Serial.print(getPSTR("Count for pin ")); + if (i < 14) { + Serial.print("D"); + Serial.print(i, DEC); + } else { + Serial.print("A"); + Serial.print(i-14, DEC); + } + Serial.print(" is "); + Serial.println(count, DEC); + } + } + begintime=millis(); + } +} + diff --git a/libraries/PinChangeInt/PinChangeInt.h b/libraries/PinChangeInt/PinChangeInt.h new file mode 100644 index 0000000..6ccd1df --- /dev/null +++ b/libraries/PinChangeInt/PinChangeInt.h @@ -0,0 +1,624 @@ +// We use 4-character tabstops, so IN VIM: :set ts=4 and :set sw=4 +// ...that's: ESCAPE key, colon key, then "s-e-t SPACE key t-s-=-4" +// +/* + * This is the PinChangeInt library for the Arduino. + + See google code project for latest, bugs and info http://code.google.com/p/arduino-pinchangeint/ + For more information Refer to avr-gcc header files, arduino source and atmega datasheet. + + This library was inspired by and derived from "johnboiles" (it seems) + PCInt Arduino Playground example here: http://www.arduino.cc/playground/Main/PcInt + If you are the original author, please let us know at the google code page + + It provides an extension to the interrupt support for arduino by + adding pin change interrupts, giving a way for users to have + interrupts drive off of any pin. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + (the file gpl.txt is included with the library's zip package) +*/ +//-------- define these in your sketch, if applicable ---------------------------------------------------------- +//-------- These must go in your sketch ahead of the #include statement ----------------------- +// You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts +// on any one or two of the three ports. If only a single port remains, the handler will be declared inline +// reducing the size and latency of the handler. +// #define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts +// #define NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts +// #define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts +// --- Mega support --- +// #define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts +// #define NO_PORTJ_PINCHANGES // to indicate that port c will not be used for pin change interrupts +// #define NO_PORTK_PINCHANGES // to indicate that port d will not be used for pin change interrupts +// In the Mega, there is no Port C, no Port D. Instead, you get Port J and Port K. Port B remains. +// Port J, however, is practically useless because there is only 1 pin available for interrupts. Most +// of the Port J pins are not even connected to a header connection. // "Mega Support" notes +// --- Sanguino, Mioduino support --- +// #define NO_PORTA_PINCHANGES // to indicate that port a will not be used for pin change interrupts +// -------------------- +// +// Other preprocessor directives... +// You can reduce the code size by 20-50 bytes, and you can speed up the interrupt routine +// slightly by declaring that you don't care if the static variables PCintPort::pinState and/or +// PCintPort::arduinoPin are set and made available to your interrupt routine. +// #define NO_PIN_STATE // to indicate that you don't need the pinState +// #define NO_PIN_NUMBER // to indicate that you don't need the arduinoPin +// #define DISABLE_PCINT_MULTI_SERVICE // to limit the handler to servicing a single interrupt per invocation. +// #define GET_PCINT_VERSION // to enable the uint16_t getPCIintVersion () function. +// The following is intended for testing purposes. If defined, then a whole host of static variables can be read +// in your interrupt subroutine. It is not defined by default, and you DO NOT want to define this in +// Production code!: +// #define PINMODE +//-------- define the above in your sketch, if applicable ------------------------------------------------------ + +/* + PinChangeInt.h + ---- VERSIONS --- (NOTE TO SELF: Update the PCINT_VERSION define, below) ----------------- +Version 2.19 (beta) Tue Nov 20 07:33:37 CST 2012 +Version 2.17 (beta) Sat Nov 17 09:46:50 CST 2012 +Version 2.11 (beta) Mon Nov 12 09:33:06 CST 2012 + + Version 2.01 (beta) Thu Jun 28 12:35:48 CDT 2012 + + Version 1.72 Wed Mar 14 18:57:55 CDT 2012 + + Version 1.71beta Sat Mar 10 12:57:05 CST 2012 + + Version 1.6beta Fri Feb 10 08:48:35 CST 2012 + + Version 1.51 Sun Feb 5 23:28:02 CST 2012 + + Version 1.5 Thu Feb 2 18:09:49 CST 2012 + + Version 1.4 Tue Jan 10 09:41:14 CST 2012 + + Version 1.3 Sat Dec 3 22:56:20 CST 2011 + + Version 1.2 Sat Dec 3 Sat Dec 3 09:15:52 CST 2011 + + Version 1.1 Sat Dec 3 00:06:03 CST 2011 + */ + +#ifndef PinChangeInt_h +#define PinChangeInt_h + +#define PCINT_VERSION 2190 // This number MUST agree with the version number, above. + +#include "stddef.h" + +// Thanks to Maurice Beelen, nms277, Akesson Karlpetter, and Orly Andico for these fixes. +#if defined(ARDUINO) && ARDUINO >= 100 + #include + #include + #include // cby and sbi defined here +#else + #include + #include + #ifndef LIBCALL_PINCHANGEINT + #include "../cppfix/cppfix.h" + #endif +#endif + + +#undef DEBUG + +/* +* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts. +* The PCINT corresponding to the pin must be enabled and masked, and +* an ISR routine provided. Since PCINTs are per port, not per pin, the ISR +* must use some logic to actually implement a per-pin interrupt service. +*/ + +/* Pin to interrupt map: +* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2 +* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0 +* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1 +*/ + +#undef INLINE_PCINT +#define INLINE_PCINT +// Thanks to cserveny...@gmail.com for MEGA support! +#if defined __AVR_ATmega2560__ || defined __AVR_ATmega1280__ || defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__ || defined __AVR_ATmega640__ + #define __USE_PORT_JK + // Mega does not have PORTA, C or D + #define NO_PORTA_PINCHANGES + #define NO_PORTC_PINCHANGES + #define NO_PORTD_PINCHANGES + #if ((defined(NO_PORTB_PINCHANGES) && defined(NO_PORTJ_PINCHANGES)) || \ + (defined(NO_PORTJ_PINCHANGES) && defined(NO_PORTK_PINCHANGES)) || \ + (defined(NO_PORTK_PINCHANGES) && defined(NO_PORTB_PINCHANGES))) + #define INLINE_PCINT inline + #endif +#else + #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) + #ifndef NO_PORTA_PINCHANGES + #define __USE_PORT_A + #endif + #else + #define NO_PORTA_PINCHANGES + #endif + // if defined only D .OR. only C .OR. only B .OR. only A, then inline it + #if ( (defined(NO_PORTA_PINCHANGES) && defined(NO_PORTB_PINCHANGES) && defined(NO_PORTC_PINCHANGES)) || \ + (defined(NO_PORTA_PINCHANGES) && defined(NO_PORTB_PINCHANGES) && defined(NO_PORTD_PINCHANGES)) || \ + (defined(NO_PORTA_PINCHANGES) && defined(NO_PORTC_PINCHANGES) && defined(NO_PORTD_PINCHANGES)) || \ + (defined(NO_PORTB_PINCHANGES) && defined(NO_PORTC_PINCHANGES) && defined(NO_PORTD_PINCHANGES)) ) + #define INLINE_PCINT inline + #endif +#endif + +// Provide drop in compatibility with johnboiles PCInt project at +// http://www.arduino.cc/playground/Main/PcInt +#define PCdetachInterrupt(pin) PCintPort::detachInterrupt(pin) +#define PCattachInterrupt(pin,userFunc,mode) PCintPort::attachInterrupt(pin, userFunc,mode) +#define PCgetArduinoPin() PCintPort::getArduinoPin() + + +typedef void (*PCIntvoidFuncPtr)(void); + +class PCintPort { +public: + PCintPort(int index,int pcindex, volatile uint8_t& maskReg) : + portInputReg(*portInputRegister(index)), + portPCMask(maskReg), + PCICRbit(1 << pcindex), + portRisingPins(0), + portFallingPins(0), + firstPin(NULL) +#ifdef PINMODE + ,intrCount(0) +#endif + { + #ifdef FLASH + ledsetup(); + #endif + } + volatile uint8_t& portInputReg; + static int8_t attachInterrupt(uint8_t pin, PCIntvoidFuncPtr userFunc, int mode); + static void detachInterrupt(uint8_t pin); + INLINE_PCINT void PCint(); + static volatile uint8_t curr; + #ifndef NO_PIN_NUMBER + static volatile uint8_t arduinoPin; + #endif + #ifndef NO_PIN_STATE + static volatile uint8_t pinState; + #endif + #ifdef PINMODE + static volatile uint8_t pinmode; + static volatile uint8_t s_portRisingPins; + static volatile uint8_t s_portFallingPins; + static volatile uint8_t s_lastPinView; + static volatile uint8_t s_pmask; + static volatile char s_PORT; + static volatile uint8_t s_changedPins; + static volatile uint8_t s_portRisingPins_nCurr; + static volatile uint8_t s_portFallingPins_nNCurr; + static volatile uint8_t s_currXORlastPinView; + volatile uint8_t intrCount; + static volatile uint8_t s_count; + static volatile uint8_t pcint_multi; + static volatile uint8_t PCIFRbug; + #endif + #ifdef FLASH + static void ledsetup(void); + #endif + +protected: + class PCintPin { + public: + PCintPin() : + PCintFunc((PCIntvoidFuncPtr)NULL), + mode(0) {} + PCIntvoidFuncPtr PCintFunc; + uint8_t mode; + uint8_t mask; + uint8_t arduinoPin; + PCintPin* next; + }; + void enable(PCintPin* pin, PCIntvoidFuncPtr userFunc, uint8_t mode); + int8_t addPin(uint8_t arduinoPin,PCIntvoidFuncPtr userFunc, uint8_t mode); + volatile uint8_t& portPCMask; + const uint8_t PCICRbit; + volatile uint8_t portRisingPins; + volatile uint8_t portFallingPins; + volatile uint8_t lastPinView; + PCintPin* firstPin; + PCintPin thePin; +}; + +#ifndef LIBCALL_PINCHANGEINT // LIBCALL_PINCHANGEINT *********************************************** +volatile uint8_t PCintPort::curr=0; +#ifndef NO_PIN_NUMBER +volatile uint8_t PCintPort::arduinoPin=0; +#endif +#ifndef NO_PIN_STATE +volatile uint8_t PCintPort::pinState=0; +#endif +#ifdef PINMODE +volatile uint8_t PCintPort::pinmode=0; +volatile uint8_t PCintPort::s_portRisingPins=0; +volatile uint8_t PCintPort::s_portFallingPins=0; +volatile uint8_t PCintPort::s_lastPinView=0; +volatile uint8_t PCintPort::s_pmask=0; +volatile char PCintPort::s_PORT='x'; +volatile uint8_t PCintPort::s_changedPins=0; +volatile uint8_t PCintPort::s_portRisingPins_nCurr=0; +volatile uint8_t PCintPort::s_portFallingPins_nNCurr=0; +volatile uint8_t PCintPort::s_currXORlastPinView=0; +volatile uint8_t PCintPort::s_count=0; +volatile uint8_t PCintPort::pcint_multi=0; +volatile uint8_t PCintPort::PCIFRbug=0; +#endif + +#ifdef FLASH +#define PINLED 13 +volatile uint8_t *led_port; +uint8_t led_mask; +uint8_t not_led_mask; +boolean ledsetup_run=false; +void PCintPort::ledsetup(void) { + if (! ledsetup_run) { + led_port=portOutputRegister(digitalPinToPort(PINLED)); + led_mask=digitalPinToBitMask(PINLED); + not_led_mask=led_mask^0xFF; + pinMode(PINLED, OUTPUT); digitalWrite(PINLED, LOW); + ledsetup_run=true; + } +}; +#endif + + +// ATMEGA 644 +// +#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) // Sanguino, Mosquino uino bobino bonanafannafofino, me my momino... + +#ifndef NO_PORTA_PINCHANGES +PCintPort portA=PCintPort(1, 0,PCMSK0); // port PB==2 (from Arduino.h, Arduino version 1.0) +#endif +#ifndef NO_PORTB_PINCHANGES +PCintPort portB=PCintPort(2, 1,PCMSK1); // port PB==2 (from Arduino.h, Arduino version 1.0) +#endif +#ifndef NO_PORTC_PINCHANGES +PCintPort portC=PCintPort(3, 2,PCMSK2); // port PC==3 (also in pins_arduino.c, Arduino version 022) +#endif +#ifndef NO_PORTD_PINCHANGES +PCintPort portD=PCintPort(4, 3,PCMSK3); // port PD==4 +#endif + +#else // others + +#ifndef NO_PORTB_PINCHANGES +PCintPort portB=PCintPort(2, 0,PCMSK0); // port PB==2 (from Arduino.h, Arduino version 1.0) +#endif +#ifndef NO_PORTC_PINCHANGES // note: no PORTC on MEGA +PCintPort portC=PCintPort(3, 1,PCMSK1); // port PC==3 (also in pins_arduino.c, Arduino version 022) +#endif +#ifndef NO_PORTD_PINCHANGES // note: no PORTD on MEGA +PCintPort portD=PCintPort(4, 2,PCMSK2); // port PD==4 +#endif + +#endif // defined __AVR_ATmega644__ + +#ifdef __USE_PORT_JK +#ifndef NO_PORTJ_PINCHANGES +PCintPort portJ=PCintPort(10,1,PCMSK1); // port PJ==10 +#endif +#ifndef NO_PORTK_PINCHANGES +PCintPort portK=PCintPort(11,2,PCMSK2); // port PK==11 +#endif +#endif // USE_PORT_JK + +static PCintPort *lookupPortNumToPort( int portNum ) { + PCintPort *port = NULL; + + switch (portNum) { +#ifndef NO_PORTA_PINCHANGES + case 1: + port=&portA; + break; +#endif +#ifndef NO_PORTB_PINCHANGES + case 2: + port=&portB; + break; +#endif +#ifndef NO_PORTC_PINCHANGES + case 3: + port=&portC; + break; +#endif +#ifndef NO_PORTD_PINCHANGES + case 4: + port=&portD; + break; +#endif +#ifdef __USE_PORT_JK + +#ifndef NO_PORTJ_PINCHANGES + case 10: + port=&portJ; + break; +#endif + +#ifndef NO_PORTK_PINCHANGES + case 11: + port=&portK; + break; +#endif + +#endif + } + + return port; +} + + +void PCintPort::enable(PCintPin* p, PCIntvoidFuncPtr userFunc, uint8_t mode) { + // Enable the pin for interrupts by adding to the PCMSKx register. + // ...The final steps; at this point the interrupt is enabled on this pin. + p->mode=mode; + p->PCintFunc=userFunc; + portPCMask |= p->mask; + if ((p->mode == RISING) || (p->mode == CHANGE)) portRisingPins |= p->mask; + if ((p->mode == FALLING) || (p->mode == CHANGE)) portFallingPins |= p->mask; + PCICR |= PCICRbit; +} + +int8_t PCintPort::addPin(uint8_t arduinoPin, PCIntvoidFuncPtr userFunc, uint8_t mode) +{ + PCintPin* tmp; + + // Add to linked list, starting with firstPin. If pin already exists, just enable. + if (firstPin != NULL) { + tmp=firstPin; + do { + if (tmp->arduinoPin == arduinoPin) { enable(tmp, userFunc, mode); return(0); } + if (tmp->next == NULL) break; + tmp=tmp->next; + } while (true); + } + + // Create pin p: fill in the data. NOTE: MySensors only support one pin due to size constraints + // TODO: Figure out a better way to solve this without relying on new/malloc + PCintPin* p = &thePin; //PCintPin* p=new PCintPin; + if (p == NULL) return(-1); + p->arduinoPin=arduinoPin; + p->mode = mode; + p->next=NULL; + p->mask = digitalPinToBitMask(arduinoPin); // the mask + + if (firstPin == NULL) firstPin=p; + else tmp->next=p; + +#ifdef DEBUG + Serial.print("addPin. pin given: "); Serial.print(arduinoPin, DEC); + int addr = (int) p; + Serial.print(" instance addr: "); Serial.println(addr, HEX); + Serial.print("userFunc addr: "); Serial.println((int)p->PCintFunc, HEX); +#endif + + enable(p, userFunc, mode); +#ifdef DEBUG + Serial.print("addPin. pin given: "); Serial.print(arduinoPin, DEC), Serial.print (" pin stored: "); + int addr = (int) p; + Serial.print(" instance addr: "); Serial.println(addr, HEX); +#endif + return(1); +} + +/* + * attach an interrupt to a specific pin using pin change interrupts. + */ +int8_t PCintPort::attachInterrupt(uint8_t arduinoPin, PCIntvoidFuncPtr userFunc, int mode) +{ + PCintPort *port; + uint8_t portNum = digitalPinToPort(arduinoPin); + if ((portNum == NOT_A_PORT) || (userFunc == NULL)) return(-1); + + port=lookupPortNumToPort(portNum); + // Added by GreyGnome... must set the initial value of lastPinView for it to be correct on the 1st interrupt. + // ...but even then, how do you define "correct"? Ultimately, the user must specify (not provisioned for yet). + port->lastPinView=port->portInputReg; + +#ifdef DEBUG + Serial.print("attachInterrupt FUNC: "); Serial.println(arduinoPin, DEC); +#endif + // map pin to PCIR register + return(port->addPin(arduinoPin,userFunc,mode)); +} + +void PCintPort::detachInterrupt(uint8_t arduinoPin) +{ + PCintPort *port; + PCintPin* current; + uint8_t mask; +#ifdef DEBUG + Serial.print("detachInterrupt: "); Serial.println(arduinoPin, DEC); +#endif + uint8_t portNum = digitalPinToPort(arduinoPin); + if (portNum == NOT_A_PORT) return; + port=lookupPortNumToPort(portNum); + mask=digitalPinToBitMask(arduinoPin); + current=port->firstPin; + //PCintPin* prev=NULL; + while (current) { + if (current->mask == mask) { // found the target + uint8_t oldSREG = SREG; + cli(); // disable interrupts + port->portPCMask &= ~mask; // disable the mask entry. + if (port->portPCMask == 0) PCICR &= ~(port->PCICRbit); + port->portRisingPins &= ~current->mask; port->portFallingPins &= ~current->mask; + // Link the previous' next to the found next. Then remove the found. + //if (prev != NULL) prev->next=current->next; // linked list skips over current. + //else firstPin=current->next; // at the first pin; save the new first pin + SREG = oldSREG; // Restore register; reenables interrupts + return; + } + //prev=current; + current=current->next; + } +} + +// common code for isr handler. "port" is the PCINT number. +// there isn't really a good way to back-map ports and masks to pins. +void PCintPort::PCint() { + uint8_t thisChangedPin; //MIKE + (void)thisChangedPin; + + #ifdef FLASH + if (*led_port & led_mask) *led_port&=not_led_mask; + else *led_port|=led_mask; + #endif + #ifndef DISABLE_PCINT_MULTI_SERVICE + uint8_t pcifr; + while (true) { + #endif + // get the pin states for the indicated port. + #ifdef PINMODE + PCintPort::s_lastPinView=lastPinView; + intrCount++; + PCintPort::s_count=intrCount; + #endif + // OLD v. 2.01 technique: Test 1: 3163; Test 7: 3993 + // From robtillaart online: ------------ (starting v. 2.11beta) + // uint8_t changedPins = PCintPort::curr ^ lastPinView; + // lastPinView = PCintPort::curr; + // uint8_t fastMask = changedPins & ((portRisingPins & PCintPort::curr ) | ( portFallingPins & ~PCintPort::curr )); + // NEW v. 2.11 technique: Test 1: 3270 Test 7: 3987 + // ------------------------------------- + // was: uint8_t changedPins = PCintPort::curr ^ lastPinView; + // makes test 6 of the PinChangeIntSpeedTest go from 3867 to 3923. Not good. + uint8_t changedPins = (PCintPort::curr ^ lastPinView) & + ((portRisingPins & PCintPort::curr ) | ( portFallingPins & ~PCintPort::curr )); + + #ifdef PINMODE + PCintPort::s_currXORlastPinView=PCintPort::curr ^ lastPinView; + PCintPort::s_portRisingPins_nCurr=portRisingPins & PCintPort::curr; + PCintPort::s_portFallingPins_nNCurr=portFallingPins & ~PCintPort::curr; + #endif + lastPinView = PCintPort::curr; + + PCintPin* p = firstPin; + while (p) { + // Trigger interrupt if the bit is high and it's set to trigger on mode RISING or CHANGE + // Trigger interrupt if the bit is low and it's set to trigger on mode FALLING or CHANGE + thisChangedPin=p->mask & changedPins; // PinChangeIntSpeedTest makes this 3673... weird. But GOOD!!! + if (p->mask & changedPins) { + #ifndef NO_PIN_STATE + PCintPort::pinState=PCintPort::curr & p->mask ? HIGH : LOW; + #endif + #ifndef NO_PIN_NUMBER + PCintPort::arduinoPin=p->arduinoPin; + #endif + #ifdef PINMODE + PCintPort::pinmode=p->mode; + PCintPort::s_portRisingPins=portRisingPins; + PCintPort::s_portFallingPins=portFallingPins; + PCintPort::s_pmask=p->mask; + PCintPort::s_changedPins=changedPins; + #endif + p->PCintFunc(); + } + p=p->next; + } + #ifndef DISABLE_PCINT_MULTI_SERVICE + pcifr = PCIFR & PCICRbit; + if (pcifr == 0) break; + PCIFR |= PCICRbit; + #ifdef PINMODE + PCintPort::pcint_multi++; + if (PCIFR & PCICRbit) PCintPort::PCIFRbug=1; // PCIFR & PCICRbit should ALWAYS be 0 here! + #endif + PCintPort::curr=portInputReg; + } + #endif +} + +#ifndef NO_PORTA_PINCHANGES +ISR(PCINT0_vect) { + #ifdef PINMODE + PCintPort::s_PORT='A'; + #endif + PCintPort::curr = portA.portInputReg; + portA.PCint(); +} +#define PORTBVECT PCINT1_vect +#define PORTCVECT PCINT2_vect +#define PORTDVECT PCINT3_vect +#else +#define PORTBVECT PCINT0_vect +#define PORTCVECT PCINT1_vect +#define PORTDVECT PCINT2_vect +#endif + +#ifndef NO_PORTB_PINCHANGES +ISR(PORTBVECT) { + #ifdef PINMODE + PCintPort::s_PORT='B'; + #endif + PCintPort::curr = portB.portInputReg; + portB.PCint(); +} +#endif + +#ifndef NO_PORTC_PINCHANGES +ISR(PORTCVECT) { + #ifdef PINMODE + PCintPort::s_PORT='C'; + #endif + PCintPort::curr = portC.portInputReg; + portC.PCint(); +} +#endif + +#ifndef NO_PORTD_PINCHANGES +ISR(PORTDVECT){ + #ifdef PINMODE + PCintPort::s_PORT='D'; + #endif + PCintPort::curr = portD.portInputReg; + portD.PCint(); +} +#endif + +#ifdef __USE_PORT_JK +#ifndef NO_PORTJ_PINCHANGES +ISR(PCINT1_vect) { + #ifdef PINMODE + PCintPort::s_PORT='J'; + #endif + PCintPort::curr = portJ.portInputReg; + portJ.PCint(); +} +#endif + +#ifndef NO_PORTK_PINCHANGES +ISR(PCINT2_vect){ + #ifdef PINMODE + PCintPort::s_PORT='K'; + #endif + PCintPort::curr = portK.portInputReg; + portK.PCint(); +} +#endif + +#endif // __USE_PORT_JK + +#ifdef GET_PCINT_VERSION +uint16_t getPCIntVersion () { + return ((uint16_t) PCINT_VERSION); +} +#endif // GET_PCINT_VERSION +#endif // #ifndef LIBCALL_PINCHANGEINT ************************************************************* +#endif // #ifndef PinChangeInt_h ******************************************************************* diff --git a/libraries/PinChangeInt/RELEASE_NOTES b/libraries/PinChangeInt/RELEASE_NOTES new file mode 100644 index 0000000..635e4f8 --- /dev/null +++ b/libraries/PinChangeInt/RELEASE_NOTES @@ -0,0 +1,332 @@ +****************************************************************************** + + PinChangeInt + ---- RELEASE NOTES --- + +Version 2.19 (beta) Tue Nov 20 07:33:37 CST 2012 +SANGUINO SUPPORT! ...And Mioduino! +...The ATmega644 chip is so cool, how can I not? 4 full ports of Pin Change Interrupt bliss! 32 i/o pins! 64k Flash! 4k RAM! Well I wish I had one. That said, Sanguino users, PLEASE send in your bug or bliss reports! Your interrupt-loving brethren and sistren are depending on you, so I can assure everyone that my changes work on that platform. Thanks. + +Modified the addPin() method to save 12 bytes; thanks again robtilllart! + if (firstPin != NULL) { + tmp=firstPin; + do { + if (tmp->arduinoPin == arduinoPin) { enable(tmp, userFunc, mode); return(0); } + if (tmp->next == NULL) break; + tmp=tmp->next; + } while (true); + } +Also changed the goto in the PCint() loop to be a while/break combination. No change to +code speed, but it looks better and passes the cleanliness "gut check". + +Includes PinChangeIntTest 1.5 sketch. + +...Ooops! Forgot the GetPSTR library, needed for the PinChangeIntTest code! Now it's included. +****************************************************************************** +Version 2.17 (beta) Sat Nov 17 09:46:50 CST 2012 +Another bugfix in the PCINT_MULTI_SERVICE section. I was using sbi(PCIFR, PCICRbit); +I didn't realize that was for I/O ports, and not ATmega registers. +But according to "deprecated.h", +"These macros became obsolete, as reading and writing IO ports can + be done by simply using the IO port name in an expression, and all + bit manipulation (including those on IO ports) can be done using + generic C bit manipulation operators." +So now I do: + PCIFR |= PCICRbit; +****************************************************************************** +Version 2.15 (beta) Sat Nov 17 01:17:44 CST 2012 +Fixed it so that attachInterrupt() will now follow your changes to the user function, +as well as the mode. detachInterrupt() still does not delete the PCintPin object but +at least you can detach and reattach at will, using different modes (RISING, FALLING, +CHANGE) and different functions as you wish. + +****************************************************************************** +Version 2.13 (beta) Mon Nov 12 09:33:06 CST 2012 +SIGNIFICANT BUGFIX release! Significant changes: +1. PCintPort::curr bug. Interrupts that occur rapidly will likely not get serviced properly by PCint(). +2. PCint() interrupt handler optimization. +3. PCIFR port bit set bug fix. +4. Many static variables added for debugging; used only when #define PINMODE is on. +5. detachInterrupt() no longer does a delete(), since that wasn't working anyway. When you detachInterrupt(), the PORT just disables interrupts for that pin; the PCintPin object remains in memory and in the linked list of pins (possibly slowing down your interrupts a couple of micros). You can reenable a detached interrupt- but you must do it within the PinChangeInt library (would anyone ever enable an interrupt on a pin, then disable it, then have need to reenable it but not using the library?). +6. attachInterrupt() now returns a uint8_t value: 1 on successful attach, 0 on successful attach but using an already-enabled pin, and -1 if the new() operator failed to create a PCintPin object. +Also, modified these release notes. + +Details: + +Uncovered a nasty bug, thanks to robtillaart on the Arduino Forums and Andre' Franken who posted to the PinChangeInt groups. This bug was introduced by me when I assigned PCintPort::curr early in the interrupt handler: +ISR(PCINT0_vect) { + PCintPort::curr = portB.portInputReg; + portB.PCint(); +} +Later, in the interrupt handler PCint(), we loop as long as PCIFR indicates a new interrupt wants to be triggered, provided DISABLE_PCINT_MULTI_SERVICE is not defined (it is not by default): +#ifndef DISABLE_PCINT_MULTI_SERVICE + pcifr = PCIFR & PCICRbit; + PCIFR = pcifr; // clear the interrupt if we will process it (no effect if bit is zero) +} while(pcifr); +#endif +...Well. Problem is, if a pin pops up and causes the PCIFR to change, we have to reread the port and look at how it is now! I wasn't doing that before, so if a new interrupt appeared while I was still servicing the old one, odd behavior would take place. For example, an interrupt would register but then the userFunc would not be called upon to service it. The code needs to be: + pcifr = PCIFR & PCICRbit; + PCIFR = pcifr; // clear the interrupt if we will process it (no effect if bit is zero) + PCintPort::curr=portInputReg; // ...Fixed in 2.11beta. +} while(pcifr); + +Also, made the interrupt handler even faster with an optimization from robtillaart to take out the checks for changed pins from the while() loop that steps through the pins: +uint8_t changedPins = (PCintPort::curr ^ lastPinView) & + ((portRisingPins & PCintPort::curr ) | ( portFallingPins & ~PCintPort::curr )); + +...This speedup is offset by more changes in the PCint() handler, which now looks like the following; there are two bug fixes: +---------------------------- +FIX 1: sbi(PCIFR, PCICRbit); +FIX 2: ...the aforementioned PCintPort::curr=portInputReg; +Here's the new code: +---------------------------- + #ifndef DISABLE_PCINT_MULTI_SERVICE + pcifr = PCIFR & PCICRbit; + if (pcifr) { + //if (PCIFR & PCICRbit) { // believe it or not, this adds .6 micros + sbi(PCIFR, PCICRbit); // This was a BUG: PCIFR = pcifr ...And here is the fix. + #ifdef PINMODE + PCintPort::pcint_multi++; + if (PCIFR & PCICRbit) PCintPort::PCIFRbug=1; // PCIFR & PCICRbit should ALWAYS be 0 here! + #endif + PCintPort::curr=portInputReg; // ...Fixed in 2.11beta. + goto loop; // A goto!!! Don't want to look at the portInputReg gratuitously, so the while() will not do. + } + #endif + +Also I added a lot of variables for debugging when PINMODE is defined, for routing out nasty bugs. I may need them in the future... :-( + +Finally, I am not putting newlines in this commentary so I can make it easier to paste online. + +****************************************************************************** +Version 2.11 (beta) Mon Nov 12 09:33:06 CST 2012 +See version 2.13 (beta) above. No change other than tidying up the release notes. +****************************************************************************** + Version 2.01 (beta) Thu Jun 28 12:35:48 CDT 2012 + ...Wow, Version 2! What? Why? + Modified the way that the pin is tested inside the interrupt subroutine (ISR) PCintPort::PCint(), + to make the interrupt quicker and slightly reduce the memory footprint. The interrupt's time is + reduced by 2 microseconds or about 7%. Instead of using the mode variable, two bitmasks are maintained + for each port. One bitmask contains all the pins that are configured to work on RISING signals, the other + on FALLING signals. A pin configured to work on CHANGE signals will appear in both bitmasks of the port. + Then, the test for a change goes like this: + if (thisChangedPin) { + if ((thisChangedPin & portRisingPins & PCintPort::curr ) || + (thisChangedPin & portFallingPins & ~PCintPort::curr )) { + where portRisingPins is the bitmask for the pins configured to interrupt on RISING signals, and + portFallingPins is the bitmask for the pins configured to interrupt on FALLING signals. Each port includes + these two bitmask variables. + + This is a significant change to some core functionality to the library, and it saves an appreciable amount + of time (2 out of 36 or so micros). Hence, the 2.00 designation. + + Tue Jun 26 12:42:20 CDT 2012 + I was officially given permission to use the PCint library: + + Re: PCint library + « Sent to: GreyGnome on: Today at 08:10:33 AM » + « You have forwarded or responded to this message. » + Quote Reply Remove + HI, + Yeah, I wrote the original PCint library. It was a bit of a hack and the new one has better features. + I intended the code to be freely usable. Didn't really think about a license. Feel free to use it in + your code: I hereby grant you permission. + + I'll investigate the MIT license, and see if it is appropriate. + Chris J. Kiick + Robot builder and all around geek. + + Version 1.81 (beta) Tue Jun 19 07:29:08 CDT 2012 + Created the getPCIntVersion function, and its associated GET_PCINT_VERSION preprocessor macro. The version + is a 16-bit int, therefore versions are represented as a 4-digit integer. 1810, then, is the first beta + release of 1.81x series. 1811 would be a bugfix of 1.810. 1820 would be the production release. + + Reversed the order of this list, so the most recent notes come first. + + Made some variables "volatile", because they are changed in the interrupt code. Thanks, Tony Cappellini! + + Added support for the Arduino Mega! Thanks to cserveny...@gmail.com! + NOTE: I don't have a Mega, so I rely on you to give me error (or working) reports! + To sum it up for the Mega: No Port C, no Port D. Instead, you get Port J and Port K. Port B remains. + Port J, however, is practically useless because there is only 1 pin available for interrupts. + Most of the Port J pins are not even connected to a header connector. Caveat Programmer. + + Created a function to report the version of this code. Put this #define ahead of the #include of this file, + in your sketch: + #define GET_PCINT_VERSION + Then you can call + uint16_t getPCIntVersion (); + and it will return a 16-bit integer representation of the version of this library. That is, version 1.73beta + will be reported as "1730". 1.74, then, will return "1740". And so on, for whatever version of the library + this happens to be. The odd number in the 10's position will indicate a beta version, as per usual, and the + number in the 1s place will indicate the beta revision (bugs may necessitate a 1.731, 1.732, etc.). + + Here are some of his notes based on his changes: + Mega and friends are using port B, J and K for interrupts. B is working without any modifications. + + J is mostly useless, because of the hardware UART. I was not able to get pin change notifications from + the TX pin (14), so only 15 left. All other (PORT J) pins are not connected on the Arduino boards. + + K controls Arduino pin A8-A15, working fine. + + 328/168 boards use C and D. So in case the lib is compiled with Mega target, the C and D will be + disabled. Also you cannot see port J/K with other targets. For J and K new flags introduced: + NO_PORTJ_PINCHANGES and NO_PORTK_PINCHANGES. + Maybe we should have PORTJ_PINCHANGES to enable PJ, because they will be most likely unused. + + Enjoy! + + Note: To remain consistent, I have not included PORTJ_PINCHANGES. All ports behave the same, + no matter how trivial those ports may seem... no surprises... + + Version 1.72 Wed Mar 14 18:57:55 CDT 2012 + Release. + + Version 1.71beta Sat Mar 10 12:57:05 CST 2012 + Code reordering: Starting in version 1.3 of this library, I put the code that enables + interrupts for the given pin, and the code that enables Pin Change Interrupts, ahead of actually + setting the user's function for the pin. Thus in the small interval between turning on the + interrupts and actually creating a valid link to an interrupt handler, it is possible to get an + interrupt. At that point the value of the pointer is 0, so this means that the Arduino + will start over again from memory location 0- just as if you'd pressed the reset button. Oops! + + I corrected it so the code now operates in the proper order. + (EDITORIAL NOTE: If you want to really learn something, teach it!) + + Minor code clean-up: All references to PCintPort::curr are now explicit. This changes the compiled + hex code not one whit. I just sleep better at night. + + Numbering: Changed the numbering scheme. Beta versions will end with an odd number in the hundredths + place- because they may be odd- and continue to be marked "beta". I'll just sleep better at night. :-) + + Version 1.70beta Mon Feb 27 07:20:42 CST 2012 + Happy Birthday to me! Happy Birthday tooooo meee! Happy Birthday, Dear Meeeeee-eeeee! + Happy Birthday to me! + + Yes, it is on this auspicious occasion of mine (and Elizabeth Taylor's [R.I.P.]) birthday that I + humbly submit to you, gracious Arduino PinChangeInt user, version 1.70beta of the PinChangeInt + library. I hope you enjoy it. + + New in this release: + The PinChangeIntTest sketch was created, which can be found in the Examples directory. It exercises: + * Two interrupting pins, one on each of the Arduino's PORTs. + * detachInterrupt() (and subsequent attachInterrupt()s). + Hopefully this will help avoid the embarrassing bugs that I have heretofore missed. + + As well, it has come to this author's (GreyGnome) attention that the Serial class in Arduino 1.0 + uses an interrupt that, if you attempt to print from an interrupt (which is what I was doing in my + tests) can easily lock up the Arduino. So I have taken SigurðurOrn's excellent ByteBuffer library + and modified it for my own nefarious purposes. (see http://siggiorn.com/?p=460). The zipfile + comes complete with the ByteBuffer library; see the ByteBuffer/ByteBuffer.h file for a list of + changes, and see the PinChangeIntTest sketch for a usage scenario. Now the (interrupt-less and) + relatively fast operation of filling a circular buffer is used in the interrupt routines. The buffer + is then printed from loop(). + + The library has been modified so it can be used in other libraries, such as my AdaEncoder library + (http://code.google.com/p/adaencoder/). When #include'd by another library you should #define + the LIBCALL_PINCHANGEINT macro. For example: + #ifndef PinChangeInt_h + #define LIBCALL_PINCHANGEINT + #include "../PinChangeInt/PinChangeInt.h" + #endif + This is necessary because the IDE compiles both your sketch and the .cpp file of your library, and + the .h file is included in both places. But since the .h file actually contains the code, any variable + or function definitions would occur twice and cause compilation errors- unless #ifdef'ed out. + + Version 1.6beta Fri Feb 10 08:48:35 CST 2012 + Set the value of the current register settings, first thing in each ISR; e.g., + ISR(PCINT0_vect) { + PCintPort::curr = portB.portInputReg; // version 1.6 + ... + ...instead of at the beginning of the PCintPort::PCint() static method. This means that the port is read + closer to the beginning of the interrupt, and may be slightly more accurate- only by a couple of microseconds, + really, but it's a cheap win. + + Fixed a bug- a BUG!- in the attachInterrupt() and detachInterrupt() methods. I didn't have breaks in my + switch statements! Augh! What am I, a (UNIX) shell programmer? ...Uh, generally, yes... + + Added the PINMODE define and the PCintPort::pinmode variable. + + Version 1.51 Sun Feb 5 23:28:02 CST 2012 + Crap, a bug! Changed line 392 from this: + PCintPort::pinState=curr & changedPins ? HIGH : LOW; + to this: + PCintPort::pinState=curr & p->mask ? HIGH : LOW; + Also added a few lines of (commented-out) debug code. + + Version 1.5 Thu Feb 2 18:09:49 CST 2012 + Added the PCintPort::pinState static variable to allow the programmer to query the state of the pin + at the time of interrupt. + Added two new #defines, NO_PIN_STATE and NO_PIN_NUMBER so as to reduce the code size by 20-50 bytes, + and to speed up the interrupt routine slightly by declaring that you don't care if the static variables + PCintPort::pinState and/or PCintPort::arduinoPin are set and made available to your interrupt routine. + // #define NO_PIN_STATE // to indicate that you don't need the pinState + // #define NO_PIN_NUMBER // to indicate that you don't need the arduinoPin + + Version 1.4 Tue Jan 10 09:41:14 CST 2012 + All the code has been moved into this .h file, so as to allow #define's to work from the user's + sketch. Thanks to Paul Stoffregen from pjrc.com for the inspiration! (Check out his website for + some nice [lots more memory] Arduino-like boards at really good prices. ...This has been an unsolicited + plug. Now back to our regular programming. ...Hehe, "programming", get it?) + + As a result, we no longer use the PinChangeIntConfig.h file. The user must #define things in his/her + sketch. Which is better anyway. + + Removed the pcIntPorts[] array, which created all the ports by default no matter what. Now, only + those ports (PCintPort objects) that you need will get created if you use the NO_PORTx_PINCHANGES #defines. + This saves flash memory, and actually we get a bit of a memory savings anyway even if all the ports are + left enabled. + + The attachInterrupt and detachInterrupt routines were modified to handle the new PCintPort objects. + + Version 1.3 Sat Dec 3 22:56:20 CST 2011 + Significant internal changes: + Tested and modified to work with Arduino 1.0. + + Modified to use the new() operator and symbolic links instead of creating a pre-populated + PCintPins[]. Renamed some variables to simplify or make their meaning more obvious (IMHO anyway). + Modified the PCintPort::PCint() code (ie, the interrupt code) to loop over a linked-list. For + those who love arrays, I have left some code in there that should work to loop over an array + instead. But it is commented out in the release version. + + For Arduino versions prior to 1.0: The new() operator requires the cppfix.h library, which is + included with this package. For Arduino 1.0 and above: new.h comes with the distribution, and + that is #included. + + Version 1.2 Sat Dec 3 Sat Dec 3 09:15:52 CST 2011 + Modified Thu Sep 8 07:33:17 CDT 2011 by GreyGnome. Fixes a bug with the initial port + value. Now it sets the initial value to be the state of the port at the time of + attachInterrupt(). The line is port.PCintLast=port.portInputReg; in attachInterrupt(). + See GreyGnome comment, below. + + Added the "arduinoPin" variable, so the user's function will know exactly which pin on + the Arduino was triggered. + + Version 1.1 Sat Dec 3 00:06:03 CST 2011 + ...updated to fix the "delPin" function as per "pekka"'s bug report. Thanks! + + ---- ^^^ VERSIONS ^^^ (NOTE TO SELF: Update the PCINT_VERSION define, below) ------------- + + See google code project for latest, bugs and info http://code.google.com/p/arduino-pinchangeint/ + For more information Refer to avr-gcc header files, arduino source and atmega datasheet. + + This library was inspired by and derived from "johnboiles" (it seems) + PCInt Arduino Playground example here: http://www.arduino.cc/playground/Main/PcInt + If you are the original author, please let us know at the google code page + + It provides an extension to the interrupt support for arduino by + adding pin change interrupts, giving a way for users to have + interrupts drive off of any pin. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . diff --git a/libraries/PinChangeInt/gpl.txt b/libraries/PinChangeInt/gpl.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/libraries/PinChangeInt/gpl.txt @@ -0,0 +1,674 @@ + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/libraries/PinChangeInt/keywords.txt b/libraries/PinChangeInt/keywords.txt new file mode 100644 index 0000000..24e1cec --- /dev/null +++ b/libraries/PinChangeInt/keywords.txt @@ -0,0 +1,10 @@ +# LITERAL1 specifies constants + +# KEYWORD1 specifies datatypes and C/C++ keywords +pinState KEYWORD1 PinState +arduinoPin KEYWORD1 ArduinoPin +PCintPort KEYWORD1 PCInterruptPort + +# KEYWORD2 specifies methods and functions +attachInterrupt KEYWORD2 AttachInterrupt +detachInterrupt KEYWORD2 DetachInterrupt diff --git a/libraries/PubSubClient/CHANGES.txt b/libraries/PubSubClient/CHANGES.txt new file mode 100755 index 0000000..8688011 --- /dev/null +++ b/libraries/PubSubClient/CHANGES.txt @@ -0,0 +1,47 @@ +1.9 + * Do not split MQTT packets over multiple calls to _client->write() + * API change: All constructors now require an instance of Client + to be passed in. + * Fixed example to match 1.8 api changes - dpslwk + * Added username/password support - WilHall + * Added publish_P - publishes messages from PROGMEM - jobytaffey + +1.8 + * KeepAlive interval is configurable in PubSubClient.h + * Maximum packet size is configurable in PubSubClient.h + * API change: Return boolean rather than int from various functions + * API change: Length parameter in message callback changed + from int to unsigned int + * Various internal tidy-ups around types +1.7 + * Improved keepalive handling + * Updated to the Arduino-1.0 API +1.6 + * Added the ability to publish a retained message + +1.5 + * Added default constructor + * Fixed compile error when used with arduino-0021 or later + +1.4 + * Fixed connection lost handling + +1.3 + * Fixed packet reading bug in PubSubClient.readPacket + +1.2 + * Fixed compile error when used with arduino-0016 or later + + +1.1 + * Reduced size of library + * Added support for Will messages + * Clarified licensing - see LICENSE.txt + + +1.0 + * Only Quality of Service (QOS) 0 messaging is supported + * The maximum message size, including header, is 128 bytes + * The keepalive interval is set to 30 seconds + * No support for Will messages + diff --git a/libraries/PubSubClient/LICENSE.txt b/libraries/PubSubClient/LICENSE.txt new file mode 100755 index 0000000..f512cba --- /dev/null +++ b/libraries/PubSubClient/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2012 Nicholas O'Leary + +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. diff --git a/libraries/PubSubClient/PubSubClient.cpp b/libraries/PubSubClient/PubSubClient.cpp new file mode 100755 index 0000000..dbb538a --- /dev/null +++ b/libraries/PubSubClient/PubSubClient.cpp @@ -0,0 +1,427 @@ +/* + PubSubClient.cpp - A simple client for MQTT. + Nicholas O'Leary + http://knolleary.net +*/ + +#include "PubSubClient.h" +#include + +PubSubClient::PubSubClient() { + this->_client = NULL; + this->stream = NULL; +} + +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client) { + this->_client = &client; + this->callback = callback; + this->ip = ip; + this->port = port; + this->domain = NULL; + this->stream = NULL; +} + +PubSubClient::PubSubClient(char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client) { + this->_client = &client; + this->callback = callback; + this->domain = domain; + this->port = port; + this->stream = NULL; +} + +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client, Stream& stream) { + this->_client = &client; + this->callback = callback; + this->ip = ip; + this->port = port; + this->domain = NULL; + this->stream = &stream; +} + +PubSubClient::PubSubClient(char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client, Stream& stream) { + this->_client = &client; + this->callback = callback; + this->domain = domain; + this->port = port; + this->stream = &stream; +} + +boolean PubSubClient::connect(char *id) { + return connect(id,NULL,NULL,0,0,0,0); +} + +boolean PubSubClient::connect(char *id, char *user, char *pass) { + return connect(id,user,pass,0,0,0,0); +} + +boolean PubSubClient::connect(char *id, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) +{ + return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); +} + +boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) { + if (!connected()) { + int result = 0; + + if (domain != NULL) { + result = _client->connect(this->domain, this->port); + } else { + result = _client->connect(this->ip, this->port); + } + + if (result) { + nextMsgId = 1; + uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p',MQTTPROTOCOLVERSION}; + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + unsigned int j; + for (j = 0;j<9;j++) { + buffer[length++] = d[j]; + } + + uint8_t v; + if (willTopic) { + v = 0x06|(willQos<<3)|(willRetain<<5); + } else { + v = 0x02; + } + + if(user != NULL) { + v = v|0x80; + + if(pass != NULL) { + v = v|(0x80>>1); + } + } + + buffer[length++] = v; + + buffer[length++] = ((MQTT_KEEPALIVE) >> 8); + buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); + length = writeString(id,buffer,length); + if (willTopic) { + length = writeString(willTopic,buffer,length); + length = writeString(willMessage,buffer,length); + } + + if(user != NULL) { + length = writeString(user,buffer,length); + if(pass != NULL) { + length = writeString(pass,buffer,length); + } + } + + write(MQTTCONNECT,buffer,length-5); + + lastInActivity = lastOutActivity = millis(); + + while (!_client->available()) { + unsigned long t = millis(); + if (t-lastInActivity > MQTT_KEEPALIVE*1000UL) { + _client->stop(); + return false; + } + } + uint8_t llen; + uint16_t len = readPacket(&llen); + + if (len == 4 && buffer[3] == 0) { + lastInActivity = millis(); + pingOutstanding = false; + return true; + } + } + _client->stop(); + } + return false; +} + +uint8_t PubSubClient::readByte() { + while(!_client->available()) {} + return _client->read(); +} + +uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { + uint16_t len = 0; + buffer[len++] = readByte(); + bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; + uint32_t multiplier = 1; + uint16_t length = 0; + uint8_t digit = 0; + uint16_t skip = 0; + uint8_t start = 0; + + do { + digit = readByte(); + buffer[len++] = digit; + length += (digit & 127) * multiplier; + multiplier *= 128; + } while ((digit & 128) != 0); + *lengthLength = len-1; + + if (isPublish) { + // Read in topic length to calculate bytes to skip over for Stream writing + buffer[len++] = readByte(); + buffer[len++] = readByte(); + skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; + start = 2; + if (buffer[0]&MQTTQOS1) { + // skip message id + skip += 2; + } + } + + for (uint16_t i = start;istream) { + if (isPublish && len-*lengthLength-2>skip) { + this->stream->write(digit); + } + } + if (len < MQTT_MAX_PACKET_SIZE) { + buffer[len] = digit; + } + len++; + } + + if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { + len = 0; // This will cause the packet to be ignored. + } + + return len; +} + +boolean PubSubClient::loop() { + if (connected()) { + unsigned long t = millis(); + if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { + if (pingOutstanding) { + _client->stop(); + return false; + } else { + buffer[0] = MQTTPINGREQ; + buffer[1] = 0; + _client->write(buffer,2); + lastOutActivity = t; + lastInActivity = t; + pingOutstanding = true; + } + } + if (_client->available()) { + uint8_t llen; + uint16_t len = readPacket(&llen); + uint16_t msgId = 0; + uint8_t *payload; + if (len > 0) { + lastInActivity = t; + uint8_t type = buffer[0]&0xF0; + if (type == MQTTPUBLISH) { + if (callback) { + uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; + char topic[tl+1]; + for (uint16_t i=0;i0 + if ((buffer[0]&0x06) == MQTTQOS1) { + msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; + payload = buffer+llen+3+tl+2; + callback(topic,payload,len-llen-3-tl-2); + + buffer[0] = MQTTPUBACK; + buffer[1] = 2; + buffer[2] = (msgId >> 8); + buffer[3] = (msgId & 0xFF); + _client->write(buffer,4); + lastOutActivity = t; + + } else { + payload = buffer+llen+3+tl; + callback(topic,payload,len-llen-3-tl); + } + } + } else if (type == MQTTPINGREQ) { + buffer[0] = MQTTPINGRESP; + buffer[1] = 0; + _client->write(buffer,2); + } else if (type == MQTTPINGRESP) { + pingOutstanding = false; + } + } + } + return true; + } + return false; +} + +boolean PubSubClient::publish(char* topic, char* payload) { + return publish(topic,(uint8_t*)payload,strlen(payload),false); +} + +boolean PubSubClient::publish(char* topic, uint8_t* payload, unsigned int plength) { + return publish(topic, payload, plength, false); +} + +boolean PubSubClient::publish(char* topic, uint8_t* payload, unsigned int plength, boolean retained) { + if (connected()) { + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + length = writeString(topic,buffer,length); + uint16_t i; + for (i=0;i 0) { + digit |= 0x80; + } + buffer[pos++] = digit; + llen++; + } while(len>0); + + pos = writeString(topic,buffer,pos); + + rc += _client->write(buffer,pos); + + for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); + } + + lastOutActivity = millis(); + + return rc == tlen + 4 + plength; +} + +boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { + uint8_t lenBuf[4]; + uint8_t llen = 0; + uint8_t digit; + uint8_t pos = 0; + uint8_t rc; + uint8_t len = length; + do { + digit = len % 128; + len = len / 128; + if (len > 0) { + digit |= 0x80; + } + lenBuf[pos++] = digit; + llen++; + } while(len>0); + + buf[4-llen] = header; + for (int i=0;iwrite(buf+(4-llen),length+1+llen); + + lastOutActivity = millis(); + return (rc == 1+llen+length); +} + +boolean PubSubClient::subscribe(char* topic) { + return subscribe(topic, 0); +} + +boolean PubSubClient::subscribe(char* topic, uint8_t qos) { + if (qos > 1) + return false; + + if (connected()) { + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, buffer,length); + buffer[length++] = qos; + return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +boolean PubSubClient::unsubscribe(char* topic) { + if (connected()) { + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, buffer,length); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +void PubSubClient::disconnect() { + buffer[0] = MQTTDISCONNECT; + buffer[1] = 0; + _client->write(buffer,2); + _client->stop(); + lastInActivity = lastOutActivity = millis(); +} + +uint16_t PubSubClient::writeString(char* string, uint8_t* buf, uint16_t pos) { + char* idp = string; + uint16_t i = 0; + pos += 2; + while (*idp) { + buf[pos++] = *idp++; + i++; + } + buf[pos-i-2] = (i >> 8); + buf[pos-i-1] = (i & 0xFF); + return pos; +} + + +boolean PubSubClient::connected() { + boolean rc; + if (_client == NULL ) { + rc = false; + } else { + rc = (int)_client->connected(); + if (!rc) _client->stop(); + } + return rc; +} + diff --git a/libraries/PubSubClient/PubSubClient.h b/libraries/PubSubClient/PubSubClient.h new file mode 100755 index 0000000..f2faff8 --- /dev/null +++ b/libraries/PubSubClient/PubSubClient.h @@ -0,0 +1,81 @@ +/* + PubSubClient.h - A simple client for MQTT. + Nicholas O'Leary + http://knolleary.net +*/ + +#ifndef PubSubClient_h +#define PubSubClient_h + +#include +#include "Client.h" +#include "Stream.h" + +// MQTT_MAX_PACKET_SIZE : Maximum packet size +#define MQTT_MAX_PACKET_SIZE 128 + +// MQTT_KEEPALIVE : keepAlive interval in Seconds +#define MQTT_KEEPALIVE 15 + +#define MQTTPROTOCOLVERSION 3 +#define MQTTCONNECT 1 << 4 // Client request to connect to Server +#define MQTTCONNACK 2 << 4 // Connect Acknowledgment +#define MQTTPUBLISH 3 << 4 // Publish message +#define MQTTPUBACK 4 << 4 // Publish Acknowledgment +#define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1) +#define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2) +#define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3) +#define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request +#define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment +#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request +#define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment +#define MQTTPINGREQ 12 << 4 // PING Request +#define MQTTPINGRESP 13 << 4 // PING Response +#define MQTTDISCONNECT 14 << 4 // Client is Disconnecting +#define MQTTReserved 15 << 4 // Reserved + +#define MQTTQOS0 (0 << 1) +#define MQTTQOS1 (1 << 1) +#define MQTTQOS2 (2 << 1) + +class PubSubClient { +private: + Client* _client; + uint8_t buffer[MQTT_MAX_PACKET_SIZE]; + uint16_t nextMsgId; + unsigned long lastOutActivity; + unsigned long lastInActivity; + bool pingOutstanding; + void (*callback)(char*,uint8_t*,unsigned int); + uint16_t readPacket(uint8_t*); + uint8_t readByte(); + boolean write(uint8_t header, uint8_t* buf, uint16_t length); + uint16_t writeString(char* string, uint8_t* buf, uint16_t pos); + uint8_t *ip; + char* domain; + uint16_t port; + Stream* stream; +public: + PubSubClient(); + PubSubClient(uint8_t *, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client); + PubSubClient(uint8_t *, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client, Stream&); + PubSubClient(char*, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client); + PubSubClient(char*, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client, Stream&); + boolean connect(char *); + boolean connect(char *, char *, char *); + boolean connect(char *, char *, uint8_t, uint8_t, char *); + boolean connect(char *, char *, char *, char *, uint8_t, uint8_t, char*); + void disconnect(); + boolean publish(char *, char *); + boolean publish(char *, uint8_t *, unsigned int); + boolean publish(char *, uint8_t *, unsigned int, boolean); + boolean publish_P(char *, uint8_t *, unsigned int, boolean); + boolean subscribe(char *); + boolean subscribe(char *, uint8_t qos); + boolean unsubscribe(char *); + boolean loop(); + boolean connected(); +}; + + +#endif diff --git a/libraries/PubSubClient/examples/mqtt_auth/mqtt_auth.ino b/libraries/PubSubClient/examples/mqtt_auth/mqtt_auth.ino new file mode 100755 index 0000000..c8a519a --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_auth/mqtt_auth.ino @@ -0,0 +1,39 @@ +/* + Basic MQTT example with Authentication + + - connects to an MQTT server, providing username + and password + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +void setup() +{ + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient", "testuser", "testpass")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} + diff --git a/libraries/PubSubClient/examples/mqtt_basic/mqtt_basic.ino b/libraries/PubSubClient/examples/mqtt_basic/mqtt_basic.ino new file mode 100755 index 0000000..72276cd --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_basic/mqtt_basic.ino @@ -0,0 +1,38 @@ +/* + Basic MQTT example + + - connects to an MQTT server + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +void setup() +{ + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} + diff --git a/libraries/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/libraries/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino new file mode 100755 index 0000000..ece5c2e --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino @@ -0,0 +1,61 @@ +/* + Publishing in the callback + + - connects to an MQTT server + - subscribes to the topic "inTopic" + - when a message is received, republishes it to "outTopic" + + This example shows how to publish messages within the + callback function. The callback function header needs to + be declared before the PubSubClient constructor and the + actual callback defined afterwards. + This ensures the client reference in the callback function + is valid. + +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +// Callback function header +void callback(char* topic, byte* payload, unsigned int length); + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +// Callback function +void callback(char* topic, byte* payload, unsigned int length) { + // In order to republish this payload, a copy must be made + // as the orignal payload buffer will be overwritten whilst + // constructing the PUBLISH packet. + + // Allocate the correct amount of memory for the payload copy + byte* p = (byte*)malloc(length); + // Copy the payload to the new buffer + memcpy(p,payload,length); + client.publish("outTopic", p, length); + // Free the memory + free(p); +} + +void setup() +{ + + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} + diff --git a/libraries/PubSubClient/examples/mqtt_stream/mqtt_stream.ino b/libraries/PubSubClient/examples/mqtt_stream/mqtt_stream.ino new file mode 100755 index 0000000..a416ee2 --- /dev/null +++ b/libraries/PubSubClient/examples/mqtt_stream/mqtt_stream.ino @@ -0,0 +1,58 @@ +/* + Example of using a Stream object to store the message payload + + Uses SRAM library: https://github.com/ennui2342/arduino-sram + but could use any Stream based class such as SD + + - connects to an MQTT server + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +SRAM sram(4, SRAM_1024); + +void callback(char* topic, byte* payload, unsigned int length) { + sram.seek(1); + + // do something with the message + for(uint8_t i=0; i/libraries/) + See http://arduino.cc/en/Guide/Libraries for detailed instructions. + +Default installation sender & demo: + - Connect tha data-in-pin of a 433MHz transmitter to digital pin 11. See + docs/hardware setup.jpg. + (Note: your hardware may have a different pin configuration!) + - Start Arduino, and open the example: File -> Examples -> RemoteSensor -> + ThermoHygroTransmitter + - Alter addresses/devices to reflect your own setup. Otherwise nothing will + happen. + - Compile, upload and run! + +Default installation receiver & demo: + - Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo. + (Note: your hardware may have a different pin configuration!) + - Start Arduino, and open the example: File -> Examples -> RemoteSensor -> + ThermoHygroReceiver + - Compile, upload and run + - Open serial monitor in Arduino (115200 baud) + - Wait for your 433MHz-sensor to transmit (less than 1 minute), and watch the + serial monitor + + +Changelog: +RemoteSensor library v1.0.2 (20130601) for Arduino 1.0 + - Reduced memory usage (Flash, RAM). Because of this, a small backwards + incompatibility is introduced: The last parameter of + SensorReceiver::decodeThermoHygro now is a byte instead of short. + - Dropped support for Arduino pre-1.0 + +RemoteSensor library v1.0.1 (20120213) for Arduino 0022/1.0 + - Ignore obviously too short or too long signals in SensorReceiver, for better + recognition rate. + - Support for Arduino 1.0. + +RemoteSensor library v1.0.0 (20110919) for Arduino 0022 + - Initial version \ No newline at end of file diff --git a/libraries/RemoteSensor/SensorReceiver.cpp b/libraries/RemoteSensor/SensorReceiver.cpp new file mode 100644 index 0000000..cde2b6f --- /dev/null +++ b/libraries/RemoteSensor/SensorReceiver.cpp @@ -0,0 +1,221 @@ +/* + * RemoteSensor library v1.0.2 (20130601) for Arduino 1.0 + * + * This library encodes, encrypts en transmits data to + * remote weather stations made by Hideki Electronics.. + * + * Copyright 20112-2013 by Randy Simons http://randysimons.nl/ + * + * Parts of this code based on Oopsje's CrestaProtocol.pdf, for which + * I thank him very much! + * + * License: GPLv3. See license.txt + */ + +#include + +byte SensorReceiver::halfBit = 0; +word SensorReceiver::clockTime; +boolean SensorReceiver::isOne; +unsigned long SensorReceiver::lastChange=0; +SensorReceiverCallback SensorReceiver::callback; +byte SensorReceiver::data[14]; +byte SensorReceiver::packageLength; +word SensorReceiver::duration; +boolean SensorReceiver::enabled; + +void SensorReceiver::init(int8_t interrupt, SensorReceiverCallback callbackIn) { + callback = callbackIn; + + enable(); + + if (interrupt >= 0) { + attachInterrupt(interrupt, interruptHandler, CHANGE); + } +} + +void SensorReceiver::interruptHandler() { + if (!enabled) { + return; + } + + /* I'll follow CrestaProtocol documentation here. However, I suspect it is inaccurate at some points: + * - there is no stop-bit after every byte. Instead, there's a start-bit (0) before every byte. + * - Conversely, there is no start-bit "1" before every byte. + * - An up-flank is 0, down-flank is 1, at least with both my receivers. + * + * However, since the first start-bit 0 is hard to distinguish given the current clock-detecting + * algorithm, I pretend there *is* a stop-bit 0 instead of start-bit. However, this means the + * last stop-bit of a package must be ignored, as it simply isn't there. + * + * This manchester decoder is based on the principle that short edges indicate the current bit is the + * same as previous bit, and that long edge indicate that the current bit is the complement of the + * previous bit. + */ + + static byte halfBitCounter = 255; + unsigned long currentTime=micros(); + duration=currentTime-lastChange; // Duration = Time between edges + + lastChange=currentTime; + + if (halfBit==0) { + // Automatic clock detection. One clock-period is half the duration of the first edge. + clockTime = duration >> 1; + + // Some sanity checking, very short (<200us) or very long (>1000us) signals are ignored. + if (clockTime < 200 || clockTime > 1000) { + return; + } + isOne = true; + } + else { + // Edge is not too long, nor too short? + if (duration < (clockTime >> 1) || duration > (clockTime << 1) + clockTime) { // read as: duration < 0.5 * clockTime || duration > 3 * clockTime + // Fail. Abort. + reset(); + return; + } + + // Only process every second half bit, i.e. every whole bit. + if (halfBit & 1) { + byte currentByte = halfBit / 18; + byte currentBit = (halfBit >> 1) % 9; // nine bits in a byte. + + if (currentBit < 8) { + if (isOne) { + // Set current bit of current byte + data[currentByte] |= 1 << currentBit; + } + else { + // Reset current bit of current byte + data[currentByte] &= ~(1 << currentBit); + } + } + else { + // Ninth bit must be 0 + if (isOne) { + // Bit is 1. Fail. Abort. + reset(); + return; + } + } + + if (halfBit == 17) { // First byte has been received + // First data byte must be x75. + if (data[0] != 0x75) { + reset(); + return; + } + } + else if (halfBit == 53) { // Third byte has been received + // Obtain the length of the data + byte decodedByte = data[2]^(data[2]<<1); + packageLength = (decodedByte >> 1) & 0x1f; + + // Do some checking to see if we should proceed + if (packageLength < 6 || packageLength > 11) { + reset(); + return; + } + + halfBitCounter = (packageLength + 3) * 9 * 2 - 2 - 1; // 9 bits per byte, 2 edges per bit, minus last stop-bit (see comment above) + } + + // Done? + if (halfBit >= halfBitCounter) { + if (halfBit == halfBitCounter) { + // Yes! Decrypt and call the callback + if (decryptAndCheck()) { + (callback)(data); + } + } + + // reset + halfBit = 0; + return; + } + } + + // Edge is long? + if (duration > clockTime + (clockTime >> 1)) { // read as: duration > 1.5 * clockTime + // Long edge. + isOne = !isOne; + // Long edge takes 2 halfbits + halfBit++; + } + } + + halfBit++; + return; +} + +void SensorReceiver::reset() { + halfBit = 1; + clockTime = duration >> 1; + isOne = true; +} + +boolean SensorReceiver::decryptAndCheck() { + byte cs1,cs2,i; + + cs1=0; + cs2=0; + for (i=1; i>1); + if (b&1) + c^=0x5f; + if (c&1) + b^=0x5f; + + return b^(c>>1); +} + +void SensorReceiver::enable() { + halfBit = 0; + enabled = true; +} + +void SensorReceiver::disable() { + enabled = false; +} + +void SensorReceiver::decodeThermoHygro(byte *data, byte &channel, byte &randomId, int &temp, byte &humidity) { + channel = data[1] >> 5; + + // Internally channel 4 is used for the other sensor types (rain, uv, anemo). + // Therefore, if channel is decoded 5 or 6, the real value set on the device itself is 4 resp 5. + if (channel >= 5) { + channel--; + } + + randomId = data[1] & 0x1f; + + temp = 100 * (data[5] & 0x0f) + 10 * (data[4] >> 4) + (data[4] & 0x0f); + // temp is negative? + if (!(data[5] & 0x80)) { + temp = -temp; + } + + humidity = 10 * (data[6] >> 4) + (data[6] & 0x0f); +} \ No newline at end of file diff --git a/libraries/RemoteSensor/SensorReceiver.h b/libraries/RemoteSensor/SensorReceiver.h new file mode 100644 index 0000000..f68603c --- /dev/null +++ b/libraries/RemoteSensor/SensorReceiver.h @@ -0,0 +1,107 @@ +/* + * RemoteSensor library v1.0.2 (20130601) for Arduino 1.0 + * + * This library receives, decodes, decrypts and receives data of + * remote weather sensors made by Hideki Electronics. + * + * Copyright 2011-2013 by Randy Simons http://randysimons.nl/ + * + * Parts of this code based on Oopsje's CrestaProtocol.pdf, for which + * I thank him very much! + * + * For more details about the data format, see CrestaProtocol.pdf + * + * License: GPLv3. See license.txt + */ + +#ifndef SensorReceiver_h +#define SensorReceiver_h + +#include + +typedef void (*SensorReceiverCallback)(byte *); // pointer to data + +/** + * Generic class for receiving and decoding 433MHz remote weather sensors as made by Cresta. + * E.g. http://www.cresta.nl/index.php?Itemid=2&option=com_zoo&view=item&category_id=32&item_id=281&lang=en + * + * Cresta is just a brandname. The original OEM seems to be Hideki Electronics. There are + * other brands which use the same hardware and / or protocol. As far as I know these include + * Mebus, Irox, Honeywell, Cresta and RST. + * + * + * This class should be able to receive all sensor types: thermo/hygro, rain, uv, anemo. + * However, only thermo/hygro is tested and has special support. + * + * Hardware required for this library: + * A 433MHz/434MHz SAW receiver, e.g. http://www.sparkfun.com/products/10532 + */ +class SensorReceiver { + public: + /** + * Initializes the receiver. When a valid data package has been received, the callback is called + * with a pointer to the validated and decrypted data. For more details about the data format, + * see CrestaProtocol.pdf + * + * For the thermo/hygro-sensor, you can use decodeThermoHygro() for easy decoding the data. + * + * If interrupt >= 0, init will register pin to this library. + * If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler() + * yourself whenever the output of the receiver changes, or you can use InterruptChain. + * + * @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details. + If < 0, you must call interruptHandler() yourself. + * @param callbackIn Pointer to a callback function, with signature void (*func)(byte *, byte). + * First parameter is the decoded data, the second the length of the package in bytes, including checksums. + * + */ + static void init(int8_t interrupt, SensorReceiverCallback callbackIn); + + /** + * Decodes data of a Thermo Hygro sensor. Note that the unit of the temp is in dec-degree, or degrees times 10. + * Thus, a value of temp of 235 is actually 23.5 degrees. + */ + static void decodeThermoHygro(byte *data, byte &channel, byte &randomId, int &temp, byte &humidity); + + /** + * Enable decoding. No need to call enable() after init(). + */ + static void enable(); + + /** + * Disable decoding. You can re-enable decoding by calling enable(); + */ + static void disable(); + + /** + * interruptHandler is called on every change in the input signal. If SensorReceiver::init is called + * with interrupt <0, you have to call interruptHandler() yourself. (Or use InterruptChain) + */ + static void interruptHandler(); + + private: + /** + * Quasi-reset. Called when the current edge is too long or short. + * reset "promotes" the current edge as being the first edge of a new sequence. + */ + static void reset(); + + /** + * Internal functions, based on CrestaProtocol.pdf + */ + static boolean decryptAndCheck(); + static byte secondCheck(byte b); + + static byte halfBit; // 9 bytes of 9 bits each, 2 edges per bit = 162 halfbits for thermo/hygro + static word clockTime; // Measured duration of half a period, i.e. the the duration of a short edge. + static boolean isOne; // true if the the last bit is a logic 1. + static unsigned long lastChange; // Timestamp of previous edge + static SensorReceiverCallback callback; // Pointer to callback function, which is called after valid package has been received + static byte packageLength; + static word duration; // Duration of current edge. + static boolean enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately. + + static byte data[14]; // Maximum number of bytes used by Cresta +}; + +#endif \ No newline at end of file diff --git a/libraries/RemoteSensor/SensorTransmitter.cpp b/libraries/RemoteSensor/SensorTransmitter.cpp new file mode 100644 index 0000000..e2675d8 --- /dev/null +++ b/libraries/RemoteSensor/SensorTransmitter.cpp @@ -0,0 +1,166 @@ +/* + * RemoteSensor library v1.0.2 (20130601) for Arduino 1.0 + * + * This library encodes, encrypts en transmits data to + * remote weather stations made by Hideki Electronics.. + * + * Copyright 2011-2013 by Randy Simons http://randysimons.nl/ + * + * Parts of this code based on Oopsje's CrestaProtocol.pdf, for which + * I thank him very much! + * + * License: GPLv3. See license.txt + */ + +#include + + + +/******************* + * Sensor base class + ******************/ + +SensorTransmitter::SensorTransmitter(byte transmitterPin, byte randomId) { + _transmitterPin = transmitterPin; + _randomId = randomId; + + pinMode(_transmitterPin, OUTPUT); +} + +/* Encrypt data byte to send to station */ +byte SensorTransmitter::encryptByte(byte b) { + byte a; + for(a=0; b; b<<=1) { + a^=b; + } + return a; +} + +/* The second checksum. Input is OldChecksum^NewByte */ +byte SensorTransmitter::secondCheck(byte b) { + byte c; + if (b&0x80) { + b^=0x95; + } + c = b^(b>>1); + if (b&1) { + c^=0x5f; + } + if (c&1) { + b^=0x5f; + } + return b^(c>>1); +} + +/* Example to encrypt a package for sending, + Input: Buffer holds the unencrypted data. + Returns the number of bytes to send, + Buffer now holds data ready for sending. + */ +byte SensorTransmitter::encryptAndAddCheck(byte *buffer) { + byte cs1,cs2,count,i; + + count=(buffer[2]>>1) & 0x1f; + cs1=0; + cs2=0; + for(i=1; i>=1; + } + } +} + +/* Send bytes (prepared by “encryptAndAddCheck”) and pause at the end. */ +void SensorTransmitter::sendManchesterPackage(byte transmitterPin, byte *data, byte cnt) { + byte i; + + for (i=0; i0x40; temp+=0x40) { /* Sends 3 packages */ + memcpy(buffer, data, ((data[2] >> 1) & 0x1f) + 1); + + buffer[3] = temp; + + count = encryptAndAddCheck(buffer); /* Encrypt, add checksum bytes */ + sendManchesterPackage(transmitterPin, buffer,count); /* Send the package */ + + delay(30); + } +} + + +/************************************ + * Thermo / Hygro sensor transmitter + ***********************************/ + +ThermoHygroTransmitter::ThermoHygroTransmitter(byte transmitterPin, byte randomId, byte channel) : SensorTransmitter(transmitterPin, randomId) { + _channel = channel; +} + +void ThermoHygroTransmitter::sendTempHumi(int temperature, byte humidity) { + byte buffer[10]; + + // Note: temperature is 10x the actual temperature! So, 23.5 degrees is passed as 235. + + buffer[0] = 0x75; /* Header byte */ + buffer[1] = (_channel << 5) | _randomId ; /* Thermo-hygro at channel 1 (see table1)*/ + buffer[2] = 0xce; /* Package size byte for th-sensor */ + + if ( temperature < 0 ) { + buffer[5] = 0x4 << 4; // High nibble is 0x4 for sub zero temperatures... + temperature = -temperature; // Make temperature positive + } else { + buffer[5] = 0xc << 4; // ...0xc for positive + } + + // Note: temperature is now always positive! + buffer[4] = (((temperature % 100) / 10 ) << 4) | // the "3" from 23.5 + (temperature % 10); // the "5" from 23.5 + buffer[5] |= (temperature / 100); // the "2" from 23.5 + + buffer[6] = ((humidity / 10) << 4) | (humidity % 10); // BCD encoded + + buffer[7]=0xff; /* Comfort flag */ + + sendPackage(_transmitterPin, buffer); +} + diff --git a/libraries/RemoteSensor/SensorTransmitter.h b/libraries/RemoteSensor/SensorTransmitter.h new file mode 100644 index 0000000..6a5141a --- /dev/null +++ b/libraries/RemoteSensor/SensorTransmitter.h @@ -0,0 +1,111 @@ +/* + * RemoteSensor library v1.0.2 (20130601) for Arduino 1.0 + * + * This library encodes, encrypts en transmits data to + * remote weather stations made by Hideki Electronics.. + * + * Copyright 2011-2013 by Randy Simons http://randysimons.nl/ + * + * Parts of this code based on Oopsje's CrestaProtocol.pdf, for which + * I thank him very much! + * + * License: GPLv3. See license.txt + */ + +#ifndef SensorTransmitter_h +#define SensorTransmitter_h + +#include + +/** + * SensorTransmitter provides a generic class to simulate Cresta weather sensors, for use + * with Cresta weather stations. + * E.g. http://www.cresta.nl/index.php?Itemid=2&option=com_zoo&view=item&category_id=32&item_id=281&lang=en + * + * Cresta is just a brand name. The original OEM seems to be Hideki Electronics. There are + * other brands which use the same hardware and / or protocol. As far as I know these include + * Mebus, Irox, Honeywell, Cresta and RST. + * + * Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g. + * http://www.sparkfun.com/products/10534 + * http://www.conrad.nl/goto/?product=130428 + */ +class SensorTransmitter { + public: + /** + * Initializes the transmitter. About the random id: "A sensor selects a random value + * in the range of column 1 when it is reset. It keeps the same ID until it is reset again." + * You can leave it at 0 for most purposes + * The transmitter pin is set in OUTPUT mode; you don't have to do this yourself. + * + * @param transmitterPin Arduino-pin connected to the 433MHz transmitter + * @param randomId A "random" value in the range [0..31] + */ + SensorTransmitter(byte transmitterPin, byte randomId); + + /** + * Sends a raw sensor package. Before transmitting, the data is encrypted and checksums are + * added. The buffer of the data doesn't need to have room for the checksums, as the data is + * copied internally to a new buffer which is always large enough. + * However, the data must be valid! + * + * The data is transmitted 3 times. + * + * Note that this is a static method. + * + * @param transmitterPin Arduino-pin connected to the 433MHz transmitter + * @param data Pointer to data to transmit + */ + static void sendPackage(byte transmitterPin, byte *data); + + protected: + byte _transmitterPin; + byte _randomId; + + private: + /** + * Sends data as manchester encoded stream + */ + static void sendManchesterPackage(byte transmitterPin, byte *data, byte cnt); + + /** + * Sends a single byte as manchester encoded stream + */ + static void sendManchesterByte(byte transmitterPin, byte b); + + /** + * Encryption and checksum + */ + static byte encryptAndAddCheck(byte *buffer); + static byte secondCheck(byte b); + static byte encryptByte(byte b); +}; + +class ThermoHygroTransmitter : public SensorTransmitter { + public: + /** + * Mimics a Thermo / Hygro sensor. The channel of this device can be 1..5, but note + * that only the more expensive receivers can use channels 4 and 5. However, for use + * in conjunction with SensorReceiver this is of no concern. + * + * @param transmitterPin Arduino-pin connected to the 433MHz transmitter + * @param randomId A "random" value in the range [0..31] + * @channel The channel of this sensor, range [1..5] + * @see SensorTransmitter::SensorTransmitter (constructor) + */ + ThermoHygroTransmitter(byte transmitterPin, byte randomId, byte channel); + + /** + * Sends temperature and humidity. + * + * @param temperature 10x the actual temperature. You want to send 23,5 degrees, then temperature should be 235. + * @param humidty Humidity in percentage-points REL. Thus, for 34% REH humidity should be 34. + */ + void sendTempHumi(int temperature, byte humidity); + + private: + byte _channel; // Note: internally, the channels for the thermo/hygro-sensor are mapped as follow: + // 1=>1, 2=>2, 3=>3, 4=>5, 5=>6. + // This because interally the rain sensor, UV sensor and anemometer are on channel 4. +}; +#endif \ No newline at end of file diff --git a/libraries/RemoteSensor/docs/Cresta weather station wx580m.jpg b/libraries/RemoteSensor/docs/Cresta weather station wx580m.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9038110a5b9aad2f433290bbc649e6fb2bd8653e GIT binary patch literal 21472 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%0Ax5ySJTu^PFBP)@Q`p@kXjHfep= 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%0D)n_-;r>ixi0D<=a|D*g@kSJjWiT z9oxVz-Jt5Ghe+Bvr|#H(Ml=00)uuku_B``#&m1mM%Fuf%YUPSPb>bHI8OBFn&xO_E zIf;kF6AxU|iRU9_!4y>v-`N|_Uvc#Jr!}kxmpE{93dV-?&_h*017?AnEqHKfXyORoPBM6Pt=HC8 zG3Aj=<}`dpwZ4F<8*xm=_B+S!UV&@IS6UPJTOBlj#8ld6*+`_kPk#{fNR5dQ$szk4V7WA#FDrtXIy_GI|{ zar&V+lKTP>g$9NCmY%lHS4~>SKAKh*$kw>Dk={3j$L>6la(`O#`E9i=dHg2SxSyvh zu-_b6X{vKTE)3ic14fc*Mf5Iy*1E&*kTay&zFy<-rKYZ*G!FX|-xYHFW9M00SvSW%bu?`TpQANPI$Cb( zKeM~+SR~S#jlDYs(0^xl*r#}|lztIcirITpOSA=cp1rrFWw{UR?)w#K^zGhv>?oywX${N%&%=@kKnh=u8y91OKh)+#jl{N1b3M;ZMPwpz%gq@QXS$AU*hb}8sUYd(y>+`~*Z>7t1L082RL+w|}H z7hBU-SK2Lf)H2K^F=r$U4eliUB|mPvjDT(ckdY~AoiwiA0Ls;bNVq-5KO`o0tKW2g zkks*q+?nKr&(%MDU*t7n6wJQbA-PgX46P1p!2}fD(;{jKrl7bJ&cqKk_kT#tZaw{} z_CR**Em^4ImEX=WuH1Nz3faEWR*aLit!M-v3)T@WPSnoX8Q!*iqX&Y}Bmf?%UG}Wb zqJ_^pO>_LY9Pde3@vE|AlE~4L#{t?#76VXD;O2g?OVQ9k-i$G~xuIngz-|W$_|-QH z;4*e`ASG8D=YcXra6xxE*OA!uiZgYXi zFL68jxGjkzcTg#HwC%?QYoTvqvPtPSaB_dNEi>(YJpERuIzrLy47bb&<4>R^)tl|0 Igdsuy+47GXK>z>% literal 0 HcmV?d00001 diff --git a/libraries/RemoteSensor/docs/CrestaProtocol.pdf b/libraries/RemoteSensor/docs/CrestaProtocol.pdf new file mode 100644 index 0000000000000000000000000000000000000000..405e53b04e79cdeb4654a62a20b15d961848a2c2 GIT binary patch literal 164256 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

48zc z?rdsnAI)PWDbiIBUrkMUb%^_?(Ci*)&OXXa+{zfY2r=J2P0bn2&haM1oqK0z5gGbM z9f`fTG|-qp15*R}Y!p`Pb=WzoWI)W5?DT*QE+GpV$?O6hO5R#6nZFK)RvM=7S2ji9yE zqPqHb&V6~b&3R}4jhBy&o}S)FclXQi^HWRKD|wv>#Xp~;dxHXyyntVZ_5MH)Nv@45 zM-|Ee0L4WY8SIKuu|XI-?G6ML4M=I3kd;bWnRqT6t)W6|e)6jILb-i$L7A*_gxZFO z^_ncOccYKJ4}6^-{^^Izlgx)rxX&8nT|ZIAkHe6a zO1;kbw*4Nz?TSi@ynW*_#!s#~(=wyzj661YOiU-spKqGkjD&$RhHXHvz^(C_5%M3i zoHbjvIO0FV(;5$D8j*W1%o{t9LCYNRa1cU>@eIApsG%;YL}vK#Y-5@CY9$6~r-Esp z-JTE$+{>MZ<~A>TqR9M}~{wFG+0$@k-G~Mr4F% z=b7C`5h9~xS(fWr1-aj6lL)6p6mlT1^N92kty+kdYjQKoO7|uX245t()9*;NfrCkHA zJp^l#7UwSD~eF0Vm~J(Ax5z$iCTegh2>x>t|=`XACgf;;$)gbm+0q^ z2Pz4n-|Wz6*QWP7@M@Vslxe)_@ZLXP9X$%#nrwT)|1+uv({;DCVV0BOUiFgKdig2~ z#tLrSjwFCC{5!e~yQ);IVcC2cdrGT7(+XT{GF3)N07l^664(iA;tnc1VpkgpHyra1 zc&`!G>@FtrqDl_8{V#p8aic-8CB16qht&B2!Mk_`_WpbHYWH+Pz zeU@7CuocGChFj~{Et?Z+bIuO!<_^*7#u4KO3D+f4+9rqmjwr9^Zrfk>R^}I}iutW% z5!(NqdU*}*h;vq;X7B$UKU8~VK9*f#P=IaWVB@Nea3}$&@)nzFYr7zjDJ`&bm^~7W>ohZC?5Nl(DCWLCH-j4^Tm-yuW5PPz z7-ag1e*)i>vyal*=41Kzz@`yYZHr-6c+%r%mumWb9vTf3cVbk4rMiXm?>bqL=TkIj0xD zI%RnFio6KE)u&n~lu~=Tt&jnbB8gm7Xcc0Rq%Z+0WT-ZL@u0L?JMzm6=nvEW?zBlr z<~1aQL`D5NW77NDaCf@#-k(v$)U5FVg2PX;&y#~wUN@b94GJS(RwvdqagyC9N zQ>ZExN2ll{t4c|m?sIBo!4mAaHbZ=33`Km3(9G)GNk$(NI-x?44?@lW zqhvHc?dY{0wSs-0VTEW5zdhOBoWNy0dG2>Sbv!N+Dv?B?|4szGGKc@DMW861blM@X z3|2w4cZ>|~%B*$?$j+_DX51-6W8)lN7=AFCta-BfdOxwwopCW?ADu3Hl@`bp@n9s} ze8nXlu<3kUc1{VGaH`yz&sk1szUP{Czb`aV5!0eQ#UODaoPrO&6|8#I0tnM?%exOU zHe}Qke~F}Y;dd4;*`ghQPPp(ByGvlqzCDoh|o4r=V?^7r^veZ zZx}5mw;Y1BU`Th}pC3IMpJ^PPE&EOGPQs@2AF7u;fel(r4e>W^c>#wuPl=SXRTc0f zwbmC+p-L|`YNb%$|4l&8*i4!YQo!P8TK(btY8PyFh)Y_3qfS_Bwf_rPK&QV<#c4-# z4a6;CM%T!0$pl;GN;TC7@0dgnRlXq#n`H@lKV#dmZ2vOG(%R}sB>1?~sTTf6TR;lq zYiJV$p3D)R%n_c<5uVHuo>ZDAvIK{kaS@F+bPkxE4okw>7B~2t2K-;Ej)}A#?0O1- zR(&RTc3UkHyO$=MEkohZk(CvWdqjQtvW9hA1cdU5=o{F{PBwtaxR` zC!3j44~CiHazc?~?q>t74Nen2q{k=Bsz2g-!RnTTx#rycVARMPbu5@N_)I!mdw;Q| zK~S6A4>#&A`dVCOljK$COg^R;(Ngs7yk@n^l+5yJrKhEQ-XmnnluWryrjL)ulZ4Eq z(@Gw2F=-P>1Xq&eiVgX?vV7dCu`aUFi9*Ws5%M16E|H>=sW1h-5w5RSzJf2G&XJ1D zQx$v6qNtWdsum6_rDp@nJq*KelHcj{+qsyU^=f{vh@bFwCfl4C42|S>)d%ccj||_1 zW^Yns{@(q~#jDTsKK#7aEti`@yrbD){9XI-j$ESuXZ_3#_-X=A1cL&+>+tLy_O?C< zBTGXg8C516$V5;wF|IN(uClX2Qz~N$pjLDozN>tcTpv}ck6HpBwFEv&u5S{|J&#;q z0IVCrq_gxx3k_`Uk;z!y=oSAu&&{*9dryBd`u#tjT+uuF$>^z>*H=zxTi)Ei|IO{q zk-e=844{bFm-4 zwQl#S2HokMKis>d6tDFKl-lS>Z#}ZHe@}Z|@jp#H!>EFoH3Q;Kv;zH?@@kE3>O8~e zI~U)MeeC1o9N**njpM|z#v>Ldn)fLnf)AFyfr)k&+WP3?rVPE<_%=zgs2Xw2U4__Gt>&*n(yd_IXIzt8tP z&-XkR)OK5^STw-5F5)SQ+7v}RRT1xU5q9}{N`<$nvWTI8l}Mlw2{a;sMkLUP0L>L& zrwwxcwPPw$Rp$U8uo{|n5|h!=JubCRblMV82^I;{$vgpx>}+R9wRK9ejPmhBJl-rd zyv`AA_kr5sgeVY=Tt}x(OfiV_PX$A zz1YCLHXFXcN4$7DydTh6?BXk4EpXgiag)2FaldB8;n3W910|>;#O%1ri@_o)s=OJE z!~WbpICuGAH=K);tnBh>=3{-N+tu# zWMG*LER%s{GO+vsZNvE*Hw_b}kP-fcDL!MH@viemD;C7Tm34|#(USqt@p#B(Pi;9< zTYBlzt0RpfD;d(WOWSuWO)DBSA;`FYd-?q{LxZQTon#_SIKKVY-XHAgNbf#7&p0<` z_At2H3xGfc*w~U$#QA>awAY86$hRi&!Lv>3$V!@W@05Pov9tkcuiS;3v~%ORI&)-&}z z24qi$eIdJ%MaL03%oxDB0#OTNXy*k3gCN232KI{V6NLW^DFUwl&d}bS{=s1jsXP?c#+JYm`!^ULtz(Qq{7G*#EXtB>gYlpQPdGZ#hFbr zkuILuSQH__lws%Kg_LUZC)Ub%Omp@4n2!$3onvjjRC_@232gmK`ag`|Nd-e`pOvY< zr$b^q7>G)G8buItFh)nL-4}8g8I+=tpV3JXe|yA+xVRwVTp|k0pT5mB*X(bc9*l~> zKe)yA@>X1Nto(!Dv3(|3bArc-5$Xb^{~Hj>P+h7&l|iXa6nCMx6D4Gnq)=)m!i)YH zaYKaxwN|xP48FduF`|}iVa_7jFl}o@#C&ey?5S`t+Qzf>JN3^vb6d1M6t{8~bfErQ zv)%><6_-sqBqIlBlEVH#LS)VLOM|k<%0Zbk(#+Z##4d)jdSrT*F3Vmk%jm%reCTt7 zMX&Am+HE{fyOvTM)Fx`r|JOv#AY3P!Fk|5Yp(o6-8L!Shqa$2K8~uFUsMg1YQ`XsC zC={g@leagTO`DGfb4newN2pmbYPj z=4){?{$t1d}^LxsSFOKT22x1b#Y&{8BuR3`>Lf(BfI4wu8;17I|fg@d-$}Roh%I;*q${TAd>67 zLvzpN5BzXf{GA_=4!(S*V7ZG(cN(@Q~@8`@5C$F^ojqWbpI6o@Jds9b%iaBegkVn>=@EY0KGX2ke`M za`ole`Tm7hKyP~iu^{sYs)zc~WuKO?8iKn+g!aW%EU*MQLK8%Z3DR~F1WdT!!yic0 zXkN8s1SGic22_(}TOe9P^i^q$`DYgA52IyUHeExy%SM20?a#`6?Se9-3*Bmz1W3lZ z4TT8um97!5bj?bHabtosr+4@7*qu4>^FuwA#pON9^hl4(sH5!`Yoh?mQfly0DJD2mE7P|FaoG6bv)QEY~QmBEBE zNug1`l<=|w$dbF_8Uv}bE5ZafjsuoPr*f+*lKO!8)NBopND%5mi&YHtgbn4f$h@r= zeU3Jt-LQ4}>4i7vlevQzzO(b3s&@o1r;NWI{{BcA7zB)}ga*{ngu6+glM{0j=Pn;S zapU~fEyFagw_uC2=-0LYcMhIbN6sDsE)8cfT2(-68C*@F^3+9jQ>IWZ94#;sR+AJ2 z2qY<##@RlN(Mn?&)0)2l7rt2?QQlE#1wdNGYRj{Pd@SLZ_MX@74TEDbexXqM_h;C* zSo$W5K4KBe`ZAx!$6WXJ3&#XnF#ebEY71`SI>URkmR4Fx)~;47SzcR~(9M!8UnF5$ z#+FvtSe7hf9B!t;;24um=>XmxBICN+`(@V&7X!F2Jp)+kmF)k+12Ojd!Jdj~J zAv0;43@@DtVLa1hrkx}cw0v9_{Kr za(Ul@*T>^m=u2zV=;K?1$Vy(zjyX{uNW-+^Kgv{w%r;opNc2nQ6Uylki z7n@7_JFxEsm%h}U*Pn!>Gdbtva04ohClS?>G_{h5oJoXC5KX_BYmEkPE!~&x91KN4 zcCkHQ8(M4~@Rqm%WeQDXq59a{$xqcDOTN84(x@YgsMc+$oI*k7HFZ~TsM4K>tY%N> zUp>ZguL=&d=nV+9JTtcEhdUxxn?;Z)il)|=U!yP3f1xteW@;~WUl#50Jnpi*5lYT` zIRTaO$tdD?@h{|7O|xu_%sr(vP|aqTY=kbQYigz&lK-mYG!? zbMbvu`eVs^7+eL9m_m*CobY+1#;Dvb%Eak9(({YfgRl%8`SYCYm^3 zo42hc5o`#gcAqUp@(qaN`Eq&xSZlt;wg36Hffm=+y(5pjks8zNiNXCDi9YUc2<&Xx zd~$13z0=<8@i*&Oov&xthRoFVwxGN#<;!#?-R@FT&v+;}wsGk6wz$dYD}TEC+uqJX zB{Pi?s%k8%=Ol{W-z}mL9V+D&YYl5&1X|6DiHn(8nFdJY=JOdz_#r2 zn6ccNv0|99c9<2}FynhHCF2a}iMly(l!bUP(C;oO@`>FTcBDlOe5x6*&`w^lTm!?e z^<*^-iu7fpUG?0W=0a;`x({Buf#-~7#rdBVzV&j+=hpbFvkmR(3yf}m@?-5vrT-2V zdS1Nn0#?dbm%cF!>J&Zv#wqZlmHu>_ln31*ecB{RXWAu*rK!N_< zS~%1`n1((`QLoFEY&(jyp*Go$h9Dl@SBh&R_Sc51w8J>hVtxcexPkeyBp@Gb)v~?E8j+ktmazW5HR+c&}U`q+BW&>uP`ZD zO*ELQ$x_3WZliWSlM3C$ePcuy$cZ3UOu&DurwCaq2nLU!h~m0*8B8AU!M)RxA4E@i^hs<4Les z=2$FqEdEedkvSIly|6{*(a@Gmn0#zS;{MmFM6Li5zJopok>!wKZms-!yjw$`L(7CIxm5YxI<^wxV6dJzPSbutz#;(0W&q6SvX_MLb z()QunmRw_7UsM3`EomMEJD8v@$~JWe@qyUU>Rlo(w0bx3u;?-4{I9wa&JL}ds10MIygCp-;)1PBRK znEI_;myMuCJBsiqWJMth3K>y|K~Wk-bjU-791j7^LuAWCQoDx$=D}gz)50RwQ3H=V zFkB8i7dY(jlmlbtxUFL;YU%ERjT)MQZF1j2XwFvj!{m5fKSZfa9V3uwqaxNS@`EbU z6Gn$gkz7ksJ^fMFu|FI={F_7V>0`e?25ZNgQs%&L;X8dkDSKde;6R@j{qxXU=La|b zVE!nqMOdc`GZX35-kG7|%nRw%o*BUAQu!kN0I-QtJ=80I0#Wg`vxFrqVF|0L4@;_N zl@KGwaKSNLaI6O3j^VOn7#R~KvhC}ARr*$#0&j+jQh^&z!zn2|n^nW*dlgAW83VPN z!%yLe+IJcX4DVEP;)CSAU+ih@%gKQXvN%M^&O}N>Bk_qJ?QDEgOzx1q85jclPWNVZ zb=0CqC;ogc&#g=O%Nb1zs~!PoXd2jaDw>IirP*uW+jMraTZr_wm4CH$w0m+IGie;q zdV`>KUX}o^26GHIOpH}vzyK&B7rTSLfTxlwZIXmeNurWTLbD_RG>JiD#bCkQ6KkmA z!1DETwZ%?w{2Sa5_IxFpyV9EElZ3MZv-Ny6UC9^M@~B6LLY2hnpx-dzHfwM&k>Wrh zj3G+w`}y9+{!RI)(OxGy>Uic#@Avz%qaAKBwIk>20qDx}8dB(9B<;5iox479{LXBi z4{nGY)SxT>d+W~biD`M$%w&%}+S{h8lkO@YmZbL0PpwBG8zGgAly1|=Wh1P!VRG3i zS-?IICP87AQMJIiplpg2LpIS{5V7hga<3SEY&i>84uDS+8ihm#-Bq2zWHh?!1ERZi zeV2c=%mi~?>3XX#P;aTC5k2Ab@FtVV=x8o=Jo)2Vp*h#y7q-zxmNivN*ilE87Ip7J z#RckJ+0rtY9ULA!Gk9%KpCbk42m(1m3Rv&rSezqbog;ZMcMJVPZU`g-35$d&CSi(6 zSfVAY?-JG=={EWg78#kvvB)ATQ3+m#;PbMUYZjfQ`NIzOF~5Z$=cjnOgYV#--G9$X z`bg3FvD%CP<07Ai`EHE+FXh!1H_yeM@n!9q@ont&+TOd9&1H?+P1Z^_ z3xTvCnp7ZAB}B?Y6jEtR!zB?ZC<1XQQmKT*LkkZGrMVGGK}Z$wfFmlE1SBXRB*M!I zArNU)cEb5*W}QvCePFfg|F)hv|98&$&Ue=Jh>}`K;cS^?`<|9Y_vy==J|x)Ai=d*prnpm})haCLd1nc*?0BZ(8s z^MmeqznN+D4a9_1T77ZtZe({-<$qK6QnN6W~OHf3{Ox^13cdBD)ffZTi!^N_$iCpc#i9@vJRjs_i z-{9fD7*T?!Vltfm`l6!vxD&7nDC!h(w)^|Y($N`C$a z3*EUAXPTR!;wGrT_*RsgWI|wZHzQifFY5fz0LxAk5f{+DfDeqQDyQ)hMLy zYgp$v?g1$tQPg~Iw1HpX&0@wW8r;frQR(N?agXA3mnZkGE%9j=GS?JGis00dL%W}N z_M>!pGdnl_z54h=wGSSlPj2oIe9EAi)&QRg>aW+R%3Y{tMCiH#`K-C96i-UXPVSjW z#`Hb;8;xc%8gSn4!K4SO!a#wJ8Z0U|U}H}iRm;dH(?uUuedI;E9;$jMNTE;r$cG-O zFB+L;--E1$)!+Lfgre`I;uZ0PPoA&97yZV-m-7QTCP2V9LX~PAjg&(x{zXJT#JIz{ z)gp<@qqsZ-XiJH(oSqfeRlJ61Oou~8%{NM=MoweG>kNwo%XNwsOJqU@zfDV)UvNqW zkH5o+lEVM@`?4lrM$jbusA7s3dO{jL#Erb7(0>yZ0n>s^(4K=H;|!p^M7?>9+7I-! z2d)NP2wG|GKs_?nI;ifWx`*m6s+Ul`h=MWHU{DjIg0i>K31RP=0)3N4H)zrF z^VuSC3!hHia|(T46gN)Xb5SbIi!yi!I@OK5D1wJnAYNV(HnN*5T9Ampnvfj_z+YYJ zbA7{`LR~@`9YPknIw%XFcm<}jS>zH1i;%XhIAKZR`Z&I8&#KoUYG#v5q8W=s zk8P)Udgdu^YC7*3H21Wq(x?;bq-mm9&O-GNyzd%Vaec z3n_J@L*KAu7HWhEH~A0<+MD<))uMJ?qjb254Ow%ru9MF$oX?66i?moXpkcX~TTTU0 z;{t}SPs1+fA={lCf zKcVyZo6x^@DgQz>{R+KG)!|_6vgEcV*%Z|s!b_pnzVVk|Y`K2&Qe%5l&XfCk4RYUx zNAAn1j&Y7v&72vT_65bM=CWWK_Phyl=LxUeCS!YJB{KHcg2XdK^&?|sEKR*~_jY1y zKou@f=^xQ+SEW)VcaTjjQ;WmJA(2kg+go{`i{4@1gX?$N)$rpDa1NB9e4FI!x4@n! z!8x!9E2Z z7Qw^&;hVAj|Br*&x;xWtXRq^0M7kofPUk(7z3*ONb4fZ4Q7anf=csR^&@F;L~B`QwYFt z{ap@-wJm&#etl%E95^#0Ye%Tm>$CS@VYdZ~ew`R|j#14lF$SNJoJ!8A*mC&%mIE-K ziB5?1Y~X@5*`Xkl&;t|=K+)hh!^^+h0r(Gvx3I+i6u3gTptDrBJ2mMf#-Iey?=fn+ zn92Dj!_h|>)hcB`iZkp#)s(>Ss-<#kYD$Frr&S7}FNI&HYwYvzJn?0nU8NSgTjF`7 zUFjNcmK?ie@-W&CjN!#iM&W+N$1|S9*Alu!cj!G-iqbAoyu8j(UFa~PAmbu#h1iT( zv|}3KF%y2!cY!NebSEge^?Hdj^6-?i;Y;XW?3bwuRqkgnsn(dZh&Up2oN?u|U?^l? zBwi2)J&EZ+;f#xG2S9A)-7WrS+>Ck zuCc*qupJJY!I;AgS4jp;Ovurc(oQ>5NCHj6z@*bM5NIk0p=74hG|lv&;}AL|)A)}z zOlE-cPtr+hyYE}AAT#NDthf92nD>6~_b&8cY-H>S8tLp7!D`S@iQbgWneL4uHD@!4 zHjbn>yuUbf>!Zct4>WuUO)@Ha;^ys7rl&vt``7WM6Vki z9aWH=O)RzXDsuB4(lY(Y?VA&{iXmxeF@HqoKDvd@y|3n2u#QpuX|WsZ>tDQ1w$L*~ zH(}3eGa36I3@IFE-k%$+#Y!am%51vw%>*T)Y zpg_VpgKv>7u&FUZnW4EqBJiH1ANDq!P3n$zL$ohvum~`e!8WH=1 zYTw+utb|>*W}@TzV1J!}7`=#NvIl$~2cLVe&%t2V?`fKg-N`xbaNqVB&@U|%8lS&d znv<}>7J5B^fWh!Qx>cA~B(Ei>$8o)=OnG$1NPm;TYJ@9>0nbB_$t)jejYeAoJoYhA zqGuH}j03RA=K3QBj1X?SWRf%Klt>X>y|GR55!MT>?4u9{A3Jt$YAa!@ng=_s5A_v% z6gW|*EF#rfW1&_0QtbCB@)c@;ejYlgIjeI7oc>x-splBB#8UzVK@edvMKDD&jNflC z;f9bjC>fvM=SwF2n12aTqyx1O zd6bi2_avF5j?q@499LReu=hguiAcs4QNRr;a;HJmP*5yY@QsC!G2oQeWFVgh8bWE(stJl9mbA=%x`xQ1F*wr1K(^G^61ZM;8q zq^I-2D6lIt2lPryU`Kf18Fw$jM>(i;@BR*}-{o%J;?wDQ_?PIXki3)Xv;z30kUUEk zNT#G1Q#7(%ArY`#$4HqLkqfU;2f%oxor{sWkIx6sC`yg^6)5@4e%`lycwbj=MWR9( z=xl3shjLM`nbo;cYj&-2ElWhKyu#)aEIOJT;=;|rTm%SPyX&{d_vT;P)LLm$Mi0)t z*1mTj!7^%^gv8UN*FW=}w-*;)Z!2-8h7SGeAKyRo;FVPi*L;F=y<=D}E!%>4bT@groIo=&^XsZnE*gHLx)Vsp&L7h&aguNp+uqL=-Wb;&H;MILA zV?(=VUpTbWzaxLNgE#O>y~yhXy@oX!b%SUAbu9MWiPJxQZoIzx_+M^hTY^o!{XNc( z)x0O|r+RS=sl#M9-6Kt80m69=vSA}(Bv`cmErs{kV_C??lOm*!eXsrTU~#X*WIu-8XZ{fEnl`a zSyo$aFqGF=?cs8R(Nl8+&k5htz?9ZNT|qMqz}vIB+oWY9zgHD^#P zgS;7($&<}lqsC^_9EhXIIO>d}`Zx;3Q5-Zh%=+~B3s2UM<-A(aDI7k(r8?X*4k0Ic0o$vz8)BX$R-$LF5Q(LKU)J+z zRRS9CW!!k#M`TF@SLQ?bn3I0x3#qP2f|C@5U(6mNBp=^QtYl$;kgFA*6)1^8QXLZ$2}4Y( zd{V_qP*)qK&u-mxYI}X4b9-yUx~#iy_kc?VB1C+iwFCqdZ6a zp$a9cq)?DV)qr)j0<)tU8O;y`Bc4BvCJ2L(g{{kogJ(43v$siD&Is4iT^uWyOfHb0 z@as@)%kTRZN3AVbb zERWbX^=qJMu@~unDTus)3egIUghn9ILyrSi2-%2y{GU>&_(myIQ18`lyKwlxxrtDC z>cY%ZATQ|3LJeKvzR5b=dQyPk#ebsp08G%XS}#6PoMuLF7Q$ZJEMGUT-)uLb$c$S0zpguUS6aCU*G zS`2p>5g1w`m@fbtlmV5bR+18+Ape6Y9?X+G3_)i6(*O9bw%91HGdySRJF`32-SOV< zSFgS6-Sw`$-q;?D12$m5n5!{qNCSaDYmA_3A%Uc-qADRmA_*_8l%%R?ODkEFOBSlC zAkkK>>OLei%|jnbpC}4aljfm<*zSL3$Ht9N*VfF=**&Y7@BhEc?-lV;RBax?+2WOI z^JvBTP5cw81wHI|PerP(HPPVZ#Fm`WMBF8IE5KVGoS#F*7N+^R{Ox?@GwbbdZ8D%e z%dZrMH@1XtOoi-ac{bUTYN@J6#YgI0R&a6iQ=C(T^yuP|^iXe;7>X4gsGWAgi0Fku z^*%2-m|@+oaGc`THNWbhK6yu=UEwy>t2o);P&5rbEwYc!Lde8<@F<}DL+I%N;%&&m zHIxsdTnMGZ$ZRgzkckZ3#fGIk28PLiHoR6z!5>k#v98}BPZMGb91*}WMH$1{TaQNT z(0qk!6@x8IDD@`FE+GUe@c{BqOH4pO=5RY&4QOGs2YnTs9({nalg?5@vdh}R;mHsl z#UVT9tCC0NC_#2U+HtV11*@C8`}dBPoSX>G!|>k5u0xGy-rQ3#*1k49M^<=QWY%dx z-N7kg!wu2Zg@mbd-+nHiAM1<9vvFPvdt^hAJjsN&I(6ddfsccgDQuibZ`|nB(HKB{&rHKt(or~=u$ne0 zDS&qd@Xmm>Gk|vn?3N7x@>dC7Y}xx2%x}qVP08+d2^UU>GDr;*E*mEPkzxZ`t!uY% z%K;i{Lp5qmB$~qLM906QQD$_)fJ<8;tQkmw5?Lw%y^PC*_1@O{Hdx0is#brj^R`&9 z)ov@G;uK(&Y*|2-SDsWv4>-WNfnygBt(w`{C-W>Nxg6Dr>EWU0hvWH)?~I* zIcA0qj%NJbs8_EI{mLgeR@7p$QPJVxPXLMk)v3h!QCpx<8?EW54C?ZMjkS7_8 zrlRqIZRMVwW*q3@(S0%(H+S`9M{AKpHo?dN14l|7>Ri}*d~N^1@w!NI)y-J@yA~f( zA2DvC9dzlD*_SGybSKJmpkxLm(SSt0+sTjR2xbgDD6RMH%coAN}Oa+5~i^L zveZgzsa2=pg*OHkF~cq*K7RnUGlGSJ(p>z~48b=POg}s*!2x7U!6u?8&;!b^NEMO| z-O?%=3;@%Q#`F{5W18+NW&#DPz;r&QC_-$Du#FhRmDTE%2jw#M09?X~E&DKt%vtBh z4E)Lqx!FWQU2+6F))LD`MU)9&-p&gxP8F5^Na+F zb<1>RdQhf@-8W5Higm3eSUt8X_25(^LaX=O0Hm@2eHK=;m={@TQ+c|4x=fWr7~T+u zH)Ihmgb5eAK~^AK-Lu2h&8s+EnL51t0LLX=_X2S`OlL>m7tuJ1$C-|C@BdI|&jU=I zVjd|U+l;xr=T3_}EpRcqkJ-|)*2m<4(Jft7fkZKj8*Cz`wnjec{F+xT9e(QY)|$*R zB*lxI(7yKI$m%2Gh0OR%+xvH>gWgDp?B`{Hacc{q#Aw&_h3Pta@4%0y`&6G-a;kn! z4XC^?@TdHgftq8WCSb^4KJF*A=mS~@4>-_htu*buwP1JeWKQ7|Ve^9nW3@q8I0%RPk z@9mSNUL2Ar06$&pL9uwcWy%=$S&DJ63k61QOZww!m1NQV`L}eP5hMrsx#SU9`nDDd z_@qaFcFGQlb?Gj8T{fwMudrGW(6lEJK=V%op8D|h1#pfoVu<*)spkr)ok2MoJW2uPZ#~ubdaVsafBdSV?b*hxPm*jfqetE zHgI0i@b=>kRBNnh>~B!X25L0PyeSn^C}n;gjdHaw+9#lk`AgjP6+@vl4nq3^O!h=r zUfIJ|7t{7+xZK4(EW08z(o2(JD>K%p3+}G*lRrC>A79ns2Czh4%=T}o?0sWr2U&gl z*~4$`%9LOH@zL>@r_78x8y|XhaMe^J=coimE`CPtBhN#A&k%7_a}!}f z@gd)=d^(aqiCN~m@X#~xkBYbM+$wcFA@{C$h5?e?7hiK|Wc0vLBsP3#bkiZze@2Pb zQi<-Eq9>~HY$f7CYsXIQDi?OVym|Dc$?n?j6QjL5`a;3piQeJeRZqAv0j%nTyHen; z#))UH6P@U?=^7bJj`Sr*Mv{G$)7M0QF{6aDTFoh4sO#eDNDk$G8j)ppB*Lsd9dRS~ z&+QwxRK2J?n1O##9#p(@x8>26L6^Ext>>Ztk2Tk--RUP9bC@EP?8yFs_+WQRW*rVb z*#1;|q7;#}%s|HwC$KclI@ncf*LBxJ-MJ7;gLfl}5t6ml>E10p0XK!uC8;hhp*eQbC$WuX7vxq7j3w_L`6 zfR}les$5+eGnc)LN>CND-zl!=lzV<#sP7a4?_ESn~OL&7BpRitVeMG;4niwy}Dv(ihy2(@4}jcSvb~)o?iHnK#S`a|3-b2sS+L{cb(7|Z(gxH1^A97 zP3N)SfX49(LlmKo`6A{Uw=7He_6&pN;*8`Dx{ZKH@znPi$rJE+0#1tO9S)A-UAmKT z@FGiblKa1mmkUr-*BQsZd(OFcVRvC!gau>)SwJ>wOGG8MDxoSqBGcy+ELTav`v$=j%l!_X-tN=?Ct-Ydlzvr z6PWq&o%8KE=iYPAx#$1CF2eaU)%>gO$2Ids3Jqp^5QEx-IEfr0mAy~0#Wb|opjsqR zf@+b(U8+S;dsr#J6sqPO!bb&^bZS^`W~b&p-ZAFuhNS%D%ZyHRz98LD4jCSP`o4A^_u1+L0~P$+K{ zf+`PpsjoioZ8hGS;^}dFd`VvRd16xEGUvgptYB^+5MC6_%narQ0`i%Z(sJG`hEfK( zPp5d&uw)l5UQnCM7@DuypK@A}PrXN)28Y`$oE}%G%jxEhSc7|0yxbAz?s=Hi#d%`* z(X^~MXv=1|quYU5dR5d!AKdm%0GQ2sq z!*LkZSgeZbL1a*vv~$kc__Z;%LuLE?iAoWFtET+{nKsH9C`P*Zjzlb_b}^YM??@MZ z>!N01Qo4j+rFKwi$0;^dpaMK@=iB*lYS-O#e>5V5@qk`JLztj;Cd?U#LB#KXkzg*E z1Ad5nCdd~D&~6_&*go@^2%)FNL? zjiQxGv@UAXy3EChX^7K6K3D+efsM#}L8?fnHdc&ds@QDgzsJ~s{X?;bU9rob;@&P% zn_*!5r+aAuwW_=tyg;kJkzZP1oYnj-TnmVkC|^U_qEy8>G~L3y0lw(1FCjl)Vur1V z{kV^gfS=g08Em!7{op;6Z4}cz(ZKZ<@ts(+Xx7qXn-~=@(XuEq?~qd%1r}m7wc!0( zYBL)wiqsuHpryv&fM$WVD?}q$2S!sRzlrmE0I-deXFN-JF_$P$yomB4yF5OMIZ@bo zV_OsrQP}z0+Q;G=llqLk^VVX%VB%<6@H8tzD*i?XtNZ z(Sx`Y3;~``dkZpvc!&_p&L=h;@!BvrcyRv>hh zE$pAe{SmJKDi=Be)6SLej$8VYP01R!l&R3<|!X= zka8n>k7rzFX}IZAeW2U?MR*fShoP6@^)ecRa82l`LG+Y9m&*0I;ciP4&8<=k*-fP} zIhK}%|0vH^OSi%o#Ti;{=~nnx(5U%Jk3Jx8M0fZeDz~)694GrI4Y{9YDm_r=cKE1_ zI-Zm~*Y(A;N9v0>X|93xS1L;Io)%(19)R}Ujdsstj{^2PoB{XYH_7*K9@Ub;3aN<| znq6QA@Tha;4Cc2Qu^D@v(JapK?nKUnY6^-(+J^p1u>Q+<8ga3Jp0ara`1B%LppT;k zn0KOnjGFWVv`WGn)LJ_6tmIl3F`b%w$;G}mX}v_P=PWv|)^mf+Hmp%T@jl+M(s&Tp zI8QTm>91^TKR8!hnZ6Y?0Th$UbpEfa^QDLQLmsBeJ65P!9VFC{we%RA<8E7y@Ikt6~G$^4cAm2`Y$Ho zxyZeB3FrDb8@{rz(S{SsJ)W>KgArUm%jnXD}M1 zucZnx6*?BQwQ3|7c1zEc$B;UcMoy`9_Su}u|3m>1MjmH3_F{_|r8IP+evw-AFzPeN zsn195O|TbxdmrxYHz>bNV?~+SEwvfzoyyl^ZZ_Df&r8@L&B+eY>k|G7)q`@y-?6t> z&^2(9uc95$f(q>8VRBD{SLOcJchfV-HOhP>VvU{v!z0no4QCy+1-uc7A`PA|4ex^; zc?xOleQ3f<+LJt_oj~1%`nT9-Xb9jT_(|X>rh|P!uA7JGZ0|c)L-k+>+k!c5p`~mW zEd*Ox3C`6L&3OLuHbT}ms})`dk-0Ra&uA_nQ5x$`vy0%xM< zpy!xyzI?y`+wwwQW^Oj}aT|F~>q9xA!}ztLkze1B@H5_-VytUvuJ#){p} zV5#N%*vbC~Ih4fDMxJFi74!WRa#nE+P6a2OQ{%hmjr{y<HIU#%b=hevX>y0#pGmn$NDffFO zhku9oXC?c~IMck(bI@@bVhy4Z!7q`6fA)6m6wiN+6zZKfymNr}Ju}$g*Wyx|ZS6t1 z{5!XvvyQXZmvDL_BwVGV+ZE9I;57c*t(pe;#vf9d&7+mKKKu?r);%pJXhZV^uL~?8 zwM3y$U!AaqrnI|1@U)*M=}_v=nU)itOVn{$%jvYRb?IEulrFoPr`w#C(>=afu(OlQ~DiiUHUgP zWnlbe+1_#nyNKe~UONffTbCgRB#E7flC+qj845QM~TL){R}xO89V%nENNZFb>M7i z%J@f!COjB;G77Je7q1=Ln(JrckS}kt?vqU3|HUSUAFSNRi1LmRrp12FtO+nXu9KIWXS(N#oM_67a?YzaG>XV-r>zu1TR0kZ zq9ii-FNFxTf~?-X6i(atvxU4LRld(&htLIHDUy#ARqnTi!qsZOt?Uhc2eY^M9YRah zGkm17hIy~4jr3blwDyqS8ii{+{kHJ-XZ^Oa5BnX=zUVjKk0p{elTIm=%>PnZ`Q)HV za*>nVoNDs$HXF-D3w@vMyv4z)r$pY9L3R93r()h#L$$om?OPe#1|PkcKUeXQHa@S8 zkE!5o4nD%+JI>(t@LAp?bv{DpHuyT;y&m6I@7X%r`*o{$wSe12^Ld-||L3&4x4Ko| zi}#M|eb@5djZS5}a`^7S`}Ip$cHheF`n@|l;r19Vqe}O<>{Z4ByKBDg^zONAS>5ve=#F}wFQb>$ zJ3M@TiO23S+`7HKDv2-P^nHO!=c0O#%VD?^Z^&blNjWr=uam(_xZ)uy_B|?#c#HRk ze!U|<>%On-L+gLxqDv99l3MsM!z}tP?dvZUYtqPM{uG0Mr5Vfm;CwPz%%m)qnw10hK@nU&o(1**e+K>p{1NyA@O$8_y#tUgO}8c7wsqRJZJ)Mn z+qP}nw(aiIr=PZM+cr+mdFQ(`b8o~qG53%7Bc6I9Gi%q%UArPGGIwRJ<=$@}xYchT zU>=|k+8vPFztCSFfY+}a0L=?+1DOZZ2CN-O*Uu0*5;)aw+|Ljo+dmVS4=ezV5AFxT z3t|Jt4ul9Q0D%v(3@QME59S9|1L_A<1Kx*N1KbB$1JMV|3seJg4cQ0kgY$~vKyWK- zKz0icWE?-RTFm%N8N&zj-z(|>9TSAUi5vb=%SF;~;A!fF#!t1fk>OP7-RhLHJeKGYaZEH$z!bw<5a2);j{@=$yxSd=8jv`M+sG_Rf$#X#S~6h zO;t%%DOCwg(o@MTxP{peKahR<2!OUhN@Hkb5Evg~fD=fq2z&#p=5 zlsJG=yQFi%k9FzRWSC^%LM0-l-)1I6>IqnygQlrXqhhjZQc*so^pd{kJR-U&s>O>G zN7U13ddsVom&!@zrug1S?C-7`7bV;`zWgt^xx%xA!V0I5?WFL(?c0xq`+o4spK<*1 zp5c38-COV$bdq;cFWXFP-bm6G)8TPih_IHnlc<~6WgAl+LmxBEbdq#ZgkX@EmY$ZJ z9#3IOT445&a#C^|QcX%tLQgtMGHqH_ z(lm`UY1Gjs)uhxU%w*u0Om6N>;!0X`vQ4XDR%ZTLCz~#lER!meD3g|XGrq=?)J~R6 zib`gWbxm&)w0A8vEIo{Mjc-z860^4~*|%rLqE-y=Zp$o{MA06f@*yS>hI38JEMrGN zjYW(_3oYeD#?|B^Xh%SbWzo@{2;8LMpSdPKuRbq6uRSk)eL*#r=Dz&X?uLFWDRYZd zmrR#5mn@ew^S+R0oachjl7WExXPR6(K?=Dgg?)SNC!wyIWNJ%dOIisgJ%OcZ2eAOr znuDlcuQqm_V@c>X0l`bHPE3UjrV1<;kv}qLRK*Jtkj4EtxQ+m!Oh3l$WlOrjn$>nv?je^n?`MWXjxh z%G{*!zA1{FisI!j8GWJ$X(`!VSTPBeDJQdJ&fckr5t&`2w33pNu${v=JOWmWv=J%0 zWXojB_#`EkkCu|oeM(8jBrP>d^k{*oQ5t3Bn7YMHmFTDKP1%>}%>19jSH#b_9n6o^ zM*UkBzX9W6|3O5ZkGuzQkBFOFx`Ulv>pI_|xAa$#{DbBUo2!M4ymg9KOoF|i!}zlw zuRu4>fAD+5yE}q6+W6P$v}LczdkrtDb=y_v>-MNe)NP>GO?3uD>+}sSdusFD;trZ| z^Y>m`YTMn$m!)|uFDi2zOsz*cUobE5hLB%j5FfmtARP(4650f~3$CK4=bpt*th^g= zx-oYm@pLw(TWw>oCc#F`AY^ma}G7c_)W(Cx>Y#5BsocIQXhc+3Bb?v$0caWh1qU zW#hEUWgAo$hqZgwIggfx&)?oN6#DqJW){Rl?_I3(nvOm1lkUY1L+`JT-n7u7u`3Z* z#6!X^0FOlPv$IIP4wMx?pu2)Pg(eOPV8B%Y1y#r@X3De3v;-|8C+EO?6lk-ufog%D zf}9E^cAU3_2JGM}i`N5x7dq!T`JLlnHE?|fKLWq^&jR)O$NPENZ>urbw{5ee)V|!B zoo)Tp^y08r?~QJ6-X7afoPl#)vg3Rm49wq z)Mnlu$S&bPBs-hxk$o&HB=<6|*S8-OXHRuZq0%4TkLU?ZGxeY#kFU}P96a#e^4_B{ zc@E?O@TH->Eo)mkqxkgLB;wRT_r*u#quW=db*W9CQ>&Dg?Bl!9+y$-;brO^MI;fYv z$~44n-ZY|l?$?a8OWyNY8w*>^YANztMQuW*{JOQ*wz4)hC7fxJ9|9i|7xwuNI}RB) zuEy;cTC#oJ$~KH!Fr5!e8He|yD>X;#+b!Au)@IEjpVlxVYc#mJRI7IEmTJuS=CW+q zK58Q2Kl!a&vHg-oQ`N^ya0iugIyX|aAGDuYOqkKxsMvZ5TV;iX=dbt6mL>Q0YuCe< zN*spR6V>&l#5z_>8YE{d^3@6!7au`P?Gmuv$VyE{-$JOAWlS$9LMPfJS!gHH(`)nd z(5B;YKYZllU`a;E%StFrj=`K!P@Gsi$0o;QJ?^J6VZ^3Uh=UVva&)Fi{Db7DWud>{ z$rdEaar>OUS<*gkIKJxrE5Dy{UcbMo8SkvK)aqw>w^K~CK zDZ>mHgGNOWAPfm13IyH@8Qu#xyb39r=0N|_v)G+R(Vxc1jf#l72zr|k;#pdRx6LL- zv0KEVwFon76@h1wKu^u0$u?qiW74%&UMvU}8wcmAJ9J2O6*IN{_T^ykCz+xyQ zx7rm|5oc2o1SB7TDLZ0&~wPo|P)D*H36|BC9r>;4(0e+TO~EbkFRa0l8qLc%-f z{)+MUh2ay*a0kvmV*ZMjziaFhf_Mk?atFLU;@$B--xD37*&Trw9bwfSK@%Mz(H#K~ zoZ-!!!3&(B$((@)oMFYBK>*H>V9tQA)$rcc;H}lr+||IVRR~aUC}Wy70~U6okl59L zCynq{jo>AX&{U1UBaN_9ji4cokWh_)w~X-4jNrA5(9Dd$vy8CHjG!@(A2++UG6Nz# zq0nVDUT;w+`gfl+dHzEW^&WrFXMXL!sq=pS-y5reRzcCc1B?(AE`g)?1REhKpMi$( z3;sVhzJ_OUmjMHT1rcUA2C`w_-UPYc?V;(gR6|q%TLoYjK#czSocMJ)(f6Nze_X-^ zcJlad-d-K<6@&{CgfygqUU1PWso&Bu{8X@pH?t*`U^$K#`sTfN(@S- z&i1ZO#-`4HJN;>IWACKwU}$XmPeu7JF!R5RekwB&va|eS&(F^w_Sczz&NJ&X60-k? zL(KYr4gO`TqVmsm|I?U3MTO~a`Cs>-qVm_p|7F5L$obdxf8hQCD%rajx|k9&GAO$^ zxf;9t%Ry&CCI%Hx2U7+GLvvGpet1(mlYc_}e@erMynIwh9qz_|jYHJZ>l^4UJ^rPqz{m+!W+;p=iKTWf2T{GKP zB>ETay=LmxLwyJA&9M2zrb+&NCL$pHO(vYo`#t&1|5zZOGDl;)i}JMR?VJ?#?ekYa zDNh3{`JFP^v3|(1QYTPCz7!daqShyKm;YficlR-1pni2hfZM~YnT}|`ePh#<$L~A_ zrH#9L%v_ZG`XTBh0xy1Zj@wVeAV8esPI=Yf_r(C@q#o@9c6xca^d^7IYR+?6JUIYE z9j;y%^R~v~3H0k~fRXS4ff%U2k2Cv(DF^&ujc)#k-s6~FgYzB+)CwLnFZnJ~kZH#9 zL-x9vjmRwN^nF4nm{q~Tkv{g?5nIpwu^pr53X@4{vZaO1myZlvtGS8G4K8&DSjVR% zU)+WP3q5{U=Glxre^YRxO zPilHvFEtlYy@O@#367NU1>+g-2NV(_Fto1mgn~UXa=`hkWAxtXtH?v#P1qYwULTYk z^g3h!bH3oCy_%%*T7*#I1CqXZa*l;22KO}idh0kCvVeoW@mdy-1JL&XZ1--~K?hOs zg}*~;Uj9a2K4en^oPWO7NgRKs!8tbL8QNJjGZ)gVp1yBU?F!L0E5Z_cchP2H(+%Ws z(|nrlwcmTF)0TV+$jmjyMhbW=l`*~#k2v)r5jrvWu*>Qc4_i5)(MCB%PEEGUGg@1K z8UE!W!5$4z{E$5shLXdWN-C8?3xAZ79Q_MC!9JYu%caWh@1lGSS8zc(dS>Kq|NGQ9 zL+;SRxboPyxI|UB$cIb)$ju?@uIakieYDM;K!Qdngxk=Q1+bObddhF#+^DrK(?*k< z8xcTqi<&=1ZD`uG?0nTn%e$7BGi|L3w?4oc#ErC`T=g^YbLZd*ZO~UNw`(Al>#Kgq z8!ciXn36_Z4sWm6kBeXmAmYlfY0&_$)KMcNFP4z%;z9}VAaSh&vJ_WZF^iQv|I2^G z04-V_UwWw?M_n~ksMa2;^@#)REWLEZJV?6o(w7=#n43*FM~?V@P;z_wIM9TeM3Y2K zYAZ2g(zY}Bykuye`#5B>x`ydSFf3>3#@OV58uH9wR-L|mA(~QN4YrK+l<%FOR^}aJ z5r@^4%yO3pR3JMh4hfdlpVS!_#<-sVSwZ`wlRotzGc*?k%zQTIB5h+Oh*wa>6Qb zYxM01QHb7k+dc=$yl3E#LHh`lYIG1^C3M`uHawq^NBhI^QoTrs%dA6Hj>dkNiVDYY zOOwW)q1zhe&Zu69@|RN2AXTcGg0l&jrVG&pk96388RIRS^DCHN=;g`cA#HSWHUvyl z#Z?#t;U*^vIJqsYA?&Pdn%^-%a2ntDlXTwU8B-6GsOp4!emW&z1Zm8NNPFi=#OBzw z=?s-qw6lhB^9iTBbqI&D zLhC2tTBeFVwd(jv4)CJSEukXU=0#g*V~s9g969PGyc)2ym)wS;*hZR|HQWC=B;|z` z>lB1cG`o}Q@kV_vDaIo+fx+^y5e`iC;kOy*PjMSoyF>&|u#M}Fifey1_+1HR|HD`L zP^_K9N|#1g;W!13yQ;rzl{P5GL*9G4cswDxnX*FB(*nSEtvxo->e%>Po3w&ZG>de1O0%JO;{n{1;1cFz9CE=CL{#G?OE7%M0vGY zAmNd5QzE!E#5znlF_+Y&SXSk}&7-4i*8_<8P8h9_dJzM0ZzOp9cJpmrw!O#3Z4bI% zI;9`)y#(PkqgQCVcF3n1?Q>2_9e`s03Z=60Eeiehl~E!zHzdErg_1Ih)lXXyqXySa zR`;HfhzI$y`>2smL8p=GW=$yrBkUS7{M|4%;|UJx1WRQ7Ml)_|Y(`VK=DTFA^R3Cf)6W7kv75#0NXU16?~_cbHN5QF%wi)bzC#_VbAfEMdBW zwBdIMgEOw;IIcXoLG?mz_lRE|qPI~)Y}tgLQN9OZ4!s37%z4A|9UxANVPP2gfqCX` zPRjZoxsZiJAT(9A;j_?9yN`xG;j*umY$~W}W3VeJ;;ptz5*uNQaSa~B(2t68yAbmg zCkXs5K`)NocaqP@p=Z0|(r#NJOTkWI=!TslC`j41!Z?wMcCh z9hwjyf8jOkfrv8=UOe{%WD)?>FF#6yd4cv@i6>8eM%r?GjeD=~#?MN7-^^!`Fc>t= zOE3BmGd!vC2bBTj3~tq#{G$wJtA6mT>d3m8)t8eY_$3#@&TiQWAOd9~qeO+_;flrH zr){&L4-3n#%Bad{1B!{akMZveQ6MMSp=EsT4O0~qGQE4j7L@yGn`3MfRl;gtuKq4@ zHLxflU3h|&QY}&8&1Aloq&SNMGoGk8r{p@F6xQaTgz?5%Sp%*=Hgfb21_0p*XK zrv$NPdz{Qwr%g+kKf*};ZM}SQ*x6s!@TJCUR0GSr$K_VPcp8ID}g7w))q?uqh#u`HxKb5C?x zNYW*o=dcwLT(OoefaWz($1j$$ZY7>(kwm*77X^gHw8Hh`#b97+nxDm(<+fq(ZDT!_ znca&m^D&{(W7O1!X%g0DW11PG;OUCXjak!*x6eEFtE);59IHe!8vRn%PYjJkffSWV zZ*0#1XEGDdiv8oL!frcHWN6N#^8P)jMR!qRA)cD6*5)j<)oGybimll)Ue4gDfwD=6 zTY$B_Yq&7l90e*KPSqZ+t6JO5k*^Rmhkdfv!W~R*#0TJpelJbs+$b^P-j8;%TwJ9q zlB(LrvQFhA;-y?XJW>40F`tfVhOn27iprJ;#jQ~!x_A%gaT)^v3eCLc;DNEhWgT4S z>6H~Hjg=jFyBNio5#>hiPuDT0cscQA4g%ij#|yb-!mb8yC04C$^^n`!*k_$`J6!!W zH{b1Jv~@rIhiip4!@^D&eR`SXv8O7^0V{8dZrtB1A@xjOx2kG#7>4-SFgtUhOg^5s z{)g(?@_6DXelztM8zjnGFeY+5M zp#(?~3o?}#wp5p%e4kYD{<1+K^qJHE+AkT0i>89?R(7>n(s!$ee}U{|h6O_PEfoKD z_e-?(;c!~IpAo4uJ3P)%6}yp1U+!k&F(lKPoQ@CH`m_t(rT8AhjRZzmg^g6@^OkINA zTbGg#-@iJLG9ZfI7q}5|2}%VDC{hX>ID(}p3k0^w;#qml$?@+};MT?u4f7-*z^_Hm zH>{qP+PnPfw=DW<4fgYDHSIZlJ}<%njCoX`yP^x$bcn1^sA`S7gQ3hV^? zG&qiQr@~KLs$*d;k}{*bdzHl>*4z`=rDe`AnH3@zQ$xM(+I)#$<~RFWwkkZ$;vaqQ z`lj>ymQID%kmp`7rgnY-USL5AJ;ING45+~vo|5oTL#hkNS`rmT*jU;S@sM(>v#TPU z^@-8j#EM}29XD9Qja&CAM`zEN>h0eI^xQu+SW;joT^Ieth`HUg5v~Y)MA(~viOo<) zLX0Ew#hp6+yz;7CfkTPZOL{rw@7F4O`NvkWf9Lkq!WYfkw&%rhk`OS?^D?VmQY3F! zQ_E;2!rwEZ+y~9HPMg@v+nr;k*qx{ef(J@Y8R@PT+T^3*47*ogf5STDO&>-I3%{ zTW&{Rg&=#t8F&CV2|hyYGZ1vGu5jS@oTNzfAUPz<=Gn+`3Vzl?HG&xkRP1h0-~bJO z!yBgmH&FNjfa)q?r1ua|7NH{9iHe>0mjdo7R&-8Gaia|Anen9nyu_-$9qdfZkmQrU zqd=-vRRM(m!aHMF8RUVj)W?{|3-MRyHww=uG)r{LtiL#zQ|@W{adJ8gC9WS}ptKz^ zE?^f&55EO+<5MhW#tERdjwmrYnny))JqD!_%X%NT$QTfK1>f^|?5<$~5&7k+BX&xM z^8r!wUBy-Y^@1qc><{J57XI-q%0xAC9JZKy>|B_`04pvh@xC|e?0qP|Y^i&V4&z0W zLqPZWa`3@ztUW~XV}AMSVwvY7qCAUql0(w3Aah(Q2xCtE&XgZLxyTJh*RdtTn>r7V z_hYZ|p{$e;9hI!Edxy@Nt3;?~>|Ohh;kd?u;(;PdZ2E7SJM{B@_}0BefnVd5SxBii;Ce&?$ zhKVS?zm!TXNpe4!&{<6pNx&1?NakT*&Lj?bB-dC}7VSSV(qByhLiy?Mc&5Pq#SCX0 z>$%T++iM{W?0Ub9xXJ$Virkm>T7}sSgTsEK+9A8Nbmr$A>N^i@urldY0W^qQ6$+EK z#O31wd`=Q_LPz_wRSCuH6^wEhJU*W>Y@$K8wveT5rnO!x_scu#atN_8>M*u1{?G%yzo>I3(gC66g7)$p4%bF6W$0Wx6quK--ysa&9p>Al za=i4Lb*T!6@*3++6TsoeBQ-7bH4EaV7pz^vg~=&rVN5W+UmjB7d@_k}`C-CEKz8HK z3k%c3hkvP+!&I*{dCe!U(Wh$GlIkK_Md8VC&V@FP#gcG;KrquZM`oR0mr}$#@)-m|f61hKg8Q`n=mS(|YC|kfwdo0n zdm$7j8QZCmAcU(9s-^dVj>cxX8$6I9n@lfzvt(psZfJK4IW> zTGchE^ov&%vOL!RzM@Zv*>ORuggFN(fU&8aqp9>RyyP6*$DkkT8{i0j(K){4IGr21 zElE~6THGa*f;9d@PpCW27}|g*f6v(3q9SL{!lDl2*uHo34%40uUD!G>eOThqeE0Q{ z_(RXzNYaBYDwZ@_#A>_Z@~uN;4}wy=t{O_7SB0jP*$ObSH!biQj#Lq>*nVI}U)8It z>g64s38Q}7%=bTdiE{}%nN{^>*ZcT*OU8b5XFx3C677DbjXghFl;C?tg`&z3cM*VV z<1@a%i(xZ@m8|Kp<^6&)T&dLGtV4DE@*r#RU1L?ZpCQRAg3Vtr%cTLaOv86)t03GQ zG%2M?4psbtRCwuAkR;tsT0gdshWe%x1Gsw zAUa>d)!m^mFey3KEj~a_F;TA6*MjoJN(#->fG+P!*N97oMnXhILmHusf$H*l_R0&^ z7(pw_Ia~Bmusw_AQ|6C5rmGg2G^1rscumCKeVP8FI&q*y4Z6!&=2DO(a?|2f!?VxUw=ockYZ$J?oJQ5W{~-G zd(M5toL3JBkl%QlrR}xqbn{CGScbvr2rLd-^NTi+)#e<6c3sP|p;Zg}XsC{LRf{2Z zeeNnej+@M0X$ap?uekKfo9T6L|P|f85~IkdDGjX^H;*~8#;7q zD122RO$tkTu1v^eoHfMGgEfSm(v!8B^;6bF^cGultKU>>@fs785KfJr^IDe_<0u8r z%}w11{j3aAk;PH=BM!nd#nf3ZJ~5yh~`@+}-c zDaM&>WA`ReRvPAYI)BqKMLnD#sJ4lLn?^)r#V_6oG}D4aO5aRnrP?UrAMRJBpI2t3 zv@9Os-tSveqd66>u4&Od-y5l4+SLB=zOwKt)LFFZwV`FoLeZbJC<`PVElD|g@CkzT ztr#%3s<>U-#l@s;oEk>f<`&WM0*+gM=kXyVk%g<-XXv~+@|}L=Z{MpFi~gP4Xe6Uk z^KPm0a>8a_MRhPKy3eLk6%pG?OwG{BHaKhry%blPp4sNE%A7fQzSh*xWK(P~sulz8 zYG_FmG5{gc#vIB>oyTo$xuDD5)$$F?2vlmc&i-#cAN-SZ|9|GjnV9}_X50!0iV+AX z5Ge59z_I>!;8-{q8UMF}HybC%e-ZGGQS)>_UBUYHy}6PafJ`C^sPC_emi^7Xx);%i zZross;EXv*1YC&H6dQ;+sTc==@dOUY-TY24?=D*BEZJqcHWUGB;E^&SJ= zr+(z<^9;ZIC&VR&nmYgAo=Gn^JtzsVg5zB4V5!DyWzQ#g%vyO)KdeN`!78grN9|Cn z@Zxoik7u&u_p{e!m30Z|ivPrUa4*eLE9Z;mabxp&luk@ZfKJY6ucTJ&^b}5q;^!Lc zogbMTacHYgpo>756>x~{q1o+oJ_&(mO+7&Urbr_We`7d!u^29=6h#M9vIJ*+SkZ`= zsTrn+Q&XBM#*DQ_py(>1fU)5Jt5vPJDwNLncj1mWQP_dG#^}r4 zjlZI?zjqP`c%FyAn-+8*5GjSoMs9iI_LN;Sx)5^joG$@>IfDWf3|EC0_tp;;p39#U z+D~Hm5Qf-h%soNsn)U>LXkFg4S(bdZKXc#k=egcNbDkt~4E5b5ipS7UypQfr{U<$- zf$M&Pj7-k4z#Z8P8!_n_Pr-J`<6){n%fcZSS|qK(yFCVk(Z<=MoZo^h8-bcP!t*#{ zu2?`V{l(KFje>9#u5E~KjlXgrzE9-Z>;dqj>>gW`8_=gU9?`slw>2D9UtX{RWJN5H z(3Oy5OQ0W_zf$yy{iA6e6*trIN|nu|f5DBS-#7J~D3BZ!X&0YN!8l{BBy}7+ZjPZ$ zI}?``<3~53(Y(gg42gxw>hyxbL99H00XAO2^ci)A*nEai%bnsJ7sH9t3lpL&(PWDV zW@)uVw9n|QiVj@D>K5pj1mRGEhd7ypCQ+V@8dpi-<|ySNX!f<^ngqR$h~J8M3FXIL z4k7Q2!N)1dDkjzZDs0r?j!2HmoTMYG6kNmltQ5A;*YN1#dJEE_c^8m%L$Reg0&7hRy8a<&2Ev>`-*Xba#vl zHQrwc+l?3U*4?nM<``1HSVGqpK&(q_bWF#(q!eb-JEkd4J2c%!V;Mzi5V1$p8g+A$ zXAOa0hfvvWMw)Qxq)kvcW#th4n4r5)zgKq(-=xYmY4#CEmI_oVq*YO)$xhiCH$2ik z`gxR;RgF<)2=SAz>W^fv)rE<4Gkk;Ude$ZTh|@@V9OZU@x5ePxh&+ES*$=jTLSHKM zHNt6_{D>bvEK=|JpY{Fx}!jne~5++%ee1ZY%Qx937F9Uu%)0 za&zooFX@grrc8K|B7O3x-}sdDc}*ndSn>vfe!s~h;?90o_H6q3IyW`HKmPHnpNz?S zf7#TEzy3=iRa!>sezATOIh~uNGaVNRedmaW>y}+5AvF4YZVEg#3Wq6G#&0ANCwd`d z21Z~A1{bSodgTg7horo)ZjI4wHf5YOM3*&Wn{_zPdwXbNt*6T}oqDc?DvNhx?DMno zdL;&j$wvlGo!MA~7}btL+hY50U1_Qy;FxVZZ85AjP-(lKiN8*Sp)zh_Ow3q^xA-mw zYwPh{>|9NRNyOy=gB6Aog^QX*mEj4S%BvDRh=`@AAz@{8$MnEb;?;U9l7Gz} zR&w^oz|!jg6-r*?kC;?r+Pq#;^46)86_t&#xH(Ny!YifH7J0NGlPfGu{;Zm26Y;$G zy$Gh3#DRnl_eqNVR@DPC!cjA}zMm0IaTE{p#;F1dR5uK5pQ(KX7QHU)4upJw-$C_r zjseX`+FlntZ0m7}?Xt!nB#x%07=GUxOdd9L9iOg=^mZ^>lLs+De5KZiGk->vZP zu$u*P0!jsq^0;ZEc$!i$8 z=)*{wuTETCuP$rp7%MKmk<{BqCupAT@05MBIB+d$ZQlmnRHAu*$u37>IL)4BWSY<&4+vt@G7Rj(fKG%qv8 z2Gu;f81i)KdO#bF0n=m_`Rp$`a9%57g{ZPFz0aq7x@&1{ZkZu6$*T&ZII^>mmP%Y1 zs0)XniQjx4)-={>=P@DAXsqDPV5$!W6XivWXnA&Cle#NG>_EZbTQt21HAa2RrW|YN z^P~MZBKm{-&G5GLV_^|}_?NS{_YFEy1MyGjXCrV3beJV*^deg-YBcVW+<8t4I<L*FlX&eotTngk*OxK2{U$40+>^^m<^u|z30P$q$|;b{Hvi(+DS6A!jIgErx|t@ z0w2vL=Leo&{|q6f-My~QI!|bFh(Nn{Cv`{{qK4-0V}{&e-x}0*rY<*HDv#t;$tDtM ztE2Qa+Wl(z)L#vs4=dN!lqt-?S3qX0ilHGbPn%;Jw=`XUQGrK2zkOI-9BEA}PwnW* zmmYKMD`(b`0om+bNR*V!90b+bOJ|1%*a({OszH}TnUX-M2Kz?X zRBltQ^oj1l^j`sGuPN>IxpGK6n_F=K`{Ru~68hCHuWuZ;#EbDfZF^U>t3c_B_DeTa zZZ|hxk!$%F{SCt#)cR<_AxL-^10hBoR0Xt^n;ny(ft3)?O<-MC3CGoG)T{~64$=tX zW8be9>1j24vQsmoZ#=mW=IY9Ko1Rqx$FCL~`57OGZ-lT?#Z}^r-Mny%74$6zY+2zb z^XdVtV$WC_ha)pk2Tl%qxWX33z!N(dKKe(%JLtPHJYQVh0R*d+MWVo_DG_xZ&p6Fb zxRj{S)4{5@&7llgpuKrkD?xPhpo><>k3bFOMl)Bk4SjUN ziHl}YY7iCU{Es!9^Oy?rB|&!)+sLP3h(e_c<1gRFKeGn%HR@NAVIm}A!Cnlh=X2-blNU&jd|HU;S(KkNgr2Ov zr&!`md^wp>CZrHsvjBe3S+<}b`>Khc@?@zONxBPNyU5_}zsq5rF&BH*8MlFElx3I`Lvx2IcJ%ChmXZ51O*r{|Db1ATimtq4eJVqH&5%xI&73U|vp>FWO>V67S0?a8@N^F^2zz1csfzm<&gN!s zwJUntw}yH`-ZMlFPAhOLWxz%AG-B?SIjMI>XEzvjP@$gFZl$;vv@!n81Q%yF73vu| zCcBQlw=?&{9_4l|{-3jAW|sdlan(uq zZ3SS23%l`y!Q1%hcs}6<6*$Kc1us3@{-I3=8lA&?$kyFoE7bfrt--k>h!c|C7m0=ZUxfiT4%~NzvS*D6{I;x(b)G^m$)*z!|`p_Lp_A z7gcIf#42e~5FHJ-dL92m_p3~iVt1qtM}5!11&!a9z#D_eQ9Y7mibed;w+Sw-s$=mAg9f5I@-G{Q2tewB&>o1`3}i z%;$O5>iM&`d#^SaCOd9A_e!ffKj-m2JF#EdsBfUjh_ej^S7m?a1{W+!yxI08K}%3+ zNn;X#iU-fL>2OtkUVEvePx86ST1oYs!fPjygM%%7h}S+9UoFy)(84LdSyY2!?F|SW z1=uN>f#d`;zPb0XZ<5QGt5^L})2GUD7w(J{eGIlj!Xj~eA-(kBQ0|6c((x&2#=I77 zHU1~iQp=i|MxM93)(wMi3On~*;$q?o!x`FF%ysj$@1wHU_^^Oz_?hXz8dRtu}Hzjf< z4E`|@2zoqc$ea6q>w!6K9*?CX;{E$Q#8 zlSFfGoEK0}f-kdAu-s7{c!GZJghm&M=>&j}_q`$;Y8sI(7X=!epEq+?-^COp^>T{? zVk(;)hUR#7bqg>mE4dyNx0{&{rU=>+8;MT@O=ph~w@WR5hx-iGML#Tf9%jjJZ@{04 zxQDCyyYmnlD<2t7^`o@)S{V^HpLq%A(rs|x!Fs8FQ5d|{uX!eHt)X#qdEhg~q8Dz* z%?hph$2>EJjy)puN>QmrLT`-Jm8akJ1a#mPA4KekI(VGo8m~NqqijvPh0FG?|4{h= z{b{zK<}zM$KozPF?|2z96k@_ab0RZ6L(84y_wKn5hD8 zeC_JT>*K`PLfY1XX60hs=3D#evHI-HQwDl|jr{VrqvRVw&-G`q$_4I)$r%S8WSE_oh;Vn7_03kM&sPQGz0$)1G+@3n>Nq=O!$2TGr6?4zkqHJlH_ zFR2TVx!0?9U(>bu<%;e3O^uhK(fxJN_QjB(B@ReCtqy}fKaQuK{QagcXQr||ja83g z&K7()bOfHdX4GWn_zzSC_}-M0QzB7$4@OecQ`6A8N8+fQV(D>J6Y@`7Mp23_Cjopy ze4D>1z~Havg|oDe>d4YBsJT)p^=dV8Rk3pIoE^*Kl`TWkmo6k>UW<8WIC4y((`h!< zdywjs7a84EcFXDFhTay%wyHa4sJXn*n0<^CUcAuhRd>~4QT(Eft#Z0A0$-@HWa!Gh zba{KvRz3xjc5sHaD;~x)8L{!k#)>g{zW|#$12XROY($v*DruxE);Z(g8>Rw(G&5$( z-*+Q$D5P;zoz&byo0X==FLv)0P=zmh{6jE94)C-%`(Th`aX^`Rb0RC$*;Jbq8S+Al zk6c3XZDx~;VS}|AdXb=-kWy%I;U_Hu1EQu$o#{-Lg`7f9$jGQEgdUe?6Ngj6D2+py?PXFA(;-q(Sfa3 z6!cAP)Ze1?0D4wOqWjfa&frDa0ePxbK(fx+<1c_MA(i@7MKJshyD&D5;3fz0RtZT{ zdRsNN<>A^xur6cj8>@@aMZFpd?Qgw>Dcu{dM7%@Dq_hIO@s2qno$H85>o6Xb=I*U7 zt9Vzo#cJ$ps7P_BqW4Ph`C2c|!ca)K{e8|+bbx8E9{=BGF3Uoz6En2uJ8X&s@%e+V z@D=kD`d+a4smP25vH>$9w1|D&%mUpg$S9;p(VqOq;OGr~BZq}`2@U&!#v^m)$`_&K z&)-o}tQTjAM*E49g1*C8vCaUOQvOdCM32dFX(@8CL~^?MgvuZhHd;T?E#ufpOvB1^U> zP*1hcOh0ui)r>;Hd^j(5(0qPrN;{O4dRh`H2kYS!s%4j$FJhf-vj&agiJI13yO@2> z3&%m+_u~V|uiW?f0(zPx-y}5692j3r(}y>Yd@@R-ph(Luwx^ikE&gk`^RMyGigWtm z3gcbPLsYzwNG~y-p+VeIW)AZQE*y&6kWQ;uch4SzK^>w>!-WPK+uPR5cp+Y<`>pq#6HlQR{DgvWn^qk<(3xi-NGF5D9km z*aS9|qHzNk`}ZDX6cQwQSd1Zh$IHxFgxc1#g+Cj@H^PPXSCQn$Lejesn}WIU&1&te z7j7w^QCo@wYPB8X3SRV4n)svyu_s5WsPdi)6{vjaMI@oT^Sof#CX+>P&dG(ECv1H+ z_i#SZ@>p>6*kW~4Nlg6gG}(jZB1PvV!)+X-pf=vh)qabzC3g19`H2~5tX0KhR0U_^ zszm{zsbFe^-~})N#NTE;HUULlb)0_N-Y>mdrkY?TKQ5_*CiZ_cH4so!!=ivEQe)@9 zRTm+Vf)2h4B@r7_n68s!FD_b=4`;}j=d3R`=1wnXp>0@V%YxUr{=4W%^>A%eVB5l5_HNL(=5 zYAxIz*u`qd%=T`Sc9IjfH_^g`-M^(V7;O*T3Wg;1RQj4$B%6=kbD^v@=8dH?uue@1S3g6yEX_H*iagb_~ zN7zk5W<_({Jx=`aYy=mfFHLI1%^=;q4}W|0Sb>L+PA-Xc1LUfpI?=c5{zK=etlT4G z>Fcq=9CDhFhfchyfcr0VW*gyd#@AJY$1w%BF>N*L9cH;~b*OnBH9?E@yRpFC;~~Y@ zB-Q<{o84ioq+JgY4b?oyGLmk1za^fvtAw+D{?gqyPllH!UNIHULz)|HCaCSsumA?b zskH?Jx*{}qW!?P6Be?k_ZBY@`^ZdR+VsFQ)9vWI%?1v+9`hUIO5lWwPfSi(MaiU%VXH=srCfUSdusPD8R_iH=~3DTUBC$oh+jUUm-^-- zz{#0EWNLh=Dff*?BK!9`cG{U#zk?ME?%N(bO&Egx*6B>%d0tChua4{)TgoLkY_D8* zmtAfi6P-?NUbd!!&O&7h8$qzXNEH8*@ariB4h8KyVrT8W{!FquLYlMJ_=nw6?rtpi z%2kdw<$6KkrH~01tCCns@3Wl4Ys5uc3;CCc+nKb7dEr?%xlsh1W2Tn~gX@KB%THY4 zJ_H@%H?DI<#2|BvC_9#`Vc5r-ZEy^Q_SK(!%)Rn_>%Qyc+hx>S;?_g@qo!*T^mo2a zQC}%kYO@e;xsC=tVuK9=#)jXIONZ(F{BW=Na5JJibSJ0@&VRQ|1cFctL75C)@p)C{ zG?Or$D5@p@ge&T!sS{cOrNbA-FCBK}}c$`A?@u9pGz{-P#GUCVQ zDsNha;tc;(*%kTYyb#w}d&D*JXUKV&7sq2;D=o)Avnv=k3&z`BC!F*BL4}0v&1#ux zSZ^|rO&aKGn3%uJ%N2Qf&-K2k?wkuo(sl&cIv=iH=zlPF&cT&L(Yl}5wlNdiKCv~i zCz@Cjp4hf|Vryb+V%xTDColKjcOR^Qmzr$C8l0#IS zS;7bYIa(sujwo+QJ<1JEvbL1K=wR^$%zWb8{Wrv6=rch6&Zi)|G#JwJK^4#vn&AK- z<0-~YFKO)iON!*5CKR!{+E3sxA!9U=59)qi^LNkkVXf%am>t6vC{l;htgHEgL02d5 z`Zg#8b0`MiE0VsOAf*^YHyxd7bBt^F$jGnASSkzVQ||N5mp+=;sLMtqZO+Q zPTYJ5NXYbq-eO8N;{BXRto40K{$=^!lvi7+Ry`_zo3Wk$uf)8hkPZSS*ODz=`8MF|Xe?m3o!Db@^eSPKAB5df)wT=rX zYhT}S7p^T{MH6rrpDaQ3?@X)=dCG)2-AK?H5@m+UqA*oLQ92aAAFeO8@70KhTOQ1f z>sH_n^z0J*$go*QvU?HJ#ZaBnw%4%?&9{NOV^13g+}Sj4iZZ!F?4pa59ICPtr~lx> zdx^O=J))RF-ew7V)$Izr0dFU3?tnNJ2GyP4Irimdk~2Ig_LWoBd(D+X{Xr%$*54ss zrQyu6;~>JhHOF&u$bF-n2-Bk*%?p; z&(13h4u5zej+r#RP0bOijP@cO6wZdMwIRRA3XCaCq}yf8o|H9}OR|T(mZXo0`eF2! zQ;dN%3lvOLqwxwe9%oOEN-#&#D-hsX-X+1-Cw|ns>qscq_ot7C&2$i&0%yO)9p?3h z=WHLPTJn(&cq9bAQ9R;Z23@zO{egDceX14ZOgESrb6?LNT_4wY%G5Ie`OlO#_7qS5 zaJpfyiLh$_n_E=S6@pc%sE-~+b|Ho_*gL-(9)!6EHepU>GSZEF^1vo0__Ni~r@%?_ zW#N+t(}zoWqTPHmN^<621AhcpxuG}8%GumzZ(I1gmV(>OdtGoRh366ilW|Au@aQGX zd)Hcu)gQHayx`5Vjzxg3HaolnoiL*kY5^7tYLB>o!%wll!mu^M{;1?xLgb{VIp)%c zNKks&`hj_XTk3azJA*x5yR8*aeA6&yB%w? zHLJAKdwAJsP{DbQQErN09o5wQ_gTDisW9V0QeINa~gUx2S!o|5K`0%zaO}xQm>m=b>U*b;cYIXR;Ed z7`IIjFt&ZRXK?O)*mC>ptSh`yMWgL=TfyX6(#cV1Gg|(Nz}eZ1mej$`VVMe!nTG_T4!B%t#9}LgjGs zICLnaI^6Mw{=6%N5QRiW4%^~%(#7Nt<%KQlYQxfo;hIT6n34=%1&4Rh zLZ5c&3VLTnbI|K{?UkaZ@pBn7i!)s9T>mn+XH;E6;r_%x!}7VY4^p9Zb)9`@P53}I zButpNRx2W3Y;E~+RkNThkQ1+8;J#*Oj)A=K{;KJO)`#FxCmA{i%@+Q}0?(v(Xi!?Q z?tBZ5I>@Avh#ygQOY*N?vMKWb>t(h33(WkwU?9`%7o@Zn=DBs&C*ou0%?BOGb-pz` z^fx%}Ck(Kgcad>IFK$#Xshr{`$ zY;|1?TSkK!(@vRhVcfdWZru2(c^*A&-CkCb0!xT1H(+RP{{aya3jcC)>fRLAL*dPy z<-5LOkSxdYo9?;)w6@|J?NixD>*F+M{ZED!GsM$25Qe!duk%$Hm)=vQD(jB&%tXY$HR zCj0X0NE`da)2@@Bpcutn*9u9X9p1_BRk!<>U=8Vx%t6|_YpnFc6q?P|fB4o^n=vfB z@qn;#5xOr0^Jf6hQd7jHgi8Cx3UbGLT$~!Zh!A&hVi|?v9!{wV!~yd zVu)dt-)nx2f&?Ht7;75D*&SG*|HWnlIzAcBnbGRwMzzr0jMqNbd4dOJRG+HDjnnWE zKR?(zM4jPN{>%uoo_S!HMU5oK9@kJQj~VYxN5jsup|WV67gtzCoFnq4VX+Fte!8un z{uJ1}(A6VJEM?PfVS70^tuKA(iUEjcFMU4iGz&JF!=|324%;oJQ!kVn$?Kw4pv_&|?hrki60MJ;&9$jURm zeA;^rzNtIvRb0j>w7_I83g7ldOlxOPU8vR1LDbXClO`-SZxXCLb$XcP7|KVFgjTwZ zF%9be?J;Ot*wHXE@=)|)s%cL#?YEthOBm;>i}OYRQQF{~&GS0>aLNA6jo#)T&>nUt zQbKzC?I+k^?@yy1RjPXX2Zm*jCo1gBoV}v1D7(x+Ml7kaDMyFCsgKqiC^oCi`R40B zT3XVjvSRvLW7kq0eZ#wsaoXp@XJI-^dj_2ZlffZCid0otVG&k2N3;#Tk%3UZ6shD* zFWChjQUWef^mcVvY*KTWFPM^jc~Har)>y=AMKgl}Fe6JYx}nUtCX0Gw8CV_2xWP?_ zUHz@eYWKkQ`92a+67HPi1tUP@0r4u~Fk$<_5PvJbd==U#?DoW%zQu!ONK(IGAIr79 z%x-Q`(a;#uaYrpzV^TB!w)mod`6mCD#|p~|BkqsYk$J89{!w4KKixBNmMX_#?Mk3_ zs5kELvz9ThCDLJA@SV1#u2rwq>`D&J%{a}xb_Mb6rc#oA{yu1vG5U3?K#kYn@2uva zP5P<)99R`vWxEOtcfhjwJ0R9%#JP*YRYbgo9E-!MpZ}4TSf|RhZu>3)nPJP4T_KZG zvweA`f7P;lIbXcp%d(f=^O-IuWt{BB(V|PWWrO8>d%g9?{wWXPi@(4##reNz{Th;s0ydD!C;KZ*4YbWi)ti#X#DLsx*LT;5 zwa~1!{trpcqk#>G$7MfeiA_9a<}{!Qkm?pxD)PkgssqOHC!=tfL)$hC$zdPsr4}Pz-bmrnPN{c#sxFf#7PbT*n&>1Ej!EdeUZJ}A4Vy=%K-c-ZCMgqRvU z7ZyQ*s(XgU@Qg^Vn{h$3W-w{+q>_FuvTRRLMG=@-3TXe1QdV%>nNx8L=)fsD?X4Sv zoefZ0n0Xke8@l@?<1waPH$`BFeG*sTe5|Tfbk274J#Br(%;F;}xtF7xWrr{o=NX%A z+I3V7#mp0qfSoQ#tM{d=(yZ5T%%-|1t(lQ!*KP59ivO1XVex07@~z&@J?(vTPsWMO zMPa*g;WpWeCY(-~KFf-hj)Y!gc&MK-H%@}QqH|z zPW%@0xt%&(js0(C35Wo9q(@GxJdH}^ZhfgmOKvkq@>f=trywi4PaPS;%%iRn8gI6X zx?X&&NR^O3fZe<4AkOn_gSWc@j05e9_VvC%EX|AVEmW2Uyl1bqF!>zuU1k-@XH=6A zkNL$nJkzppKESH>Y;r4D-!YEs?s{d2TsnNqceC`1D3TnoaIJjPZe620^POAuGl-)^ zAERQf527wsZUU&W!U4V|ZVGBLy+W*Q70ce$LV4!IHfLfN%uhG1%6F>i=5_YP`F*yH z*As%hnL&|$&GN<%MQ1YOyBnCYDIXjUKFl7O1$MoTv(+IFR3ab9*D&{O$EqBLdk=Gc zyk)hepX<}F>u(9#vTsLL68TB`hU2#V8zRqL!%UCGWq;|SeJ*)kK^|VD1Efzs$k8^V z$f^kWre4+EilrSMeWke_ek|Gs0?EOlTVMx8ymPgh?fR9eDgu-@T{T~XT%r5 zBE_~2Jt(efyvdDfl*t8v9Dn{ll_8Y~(9v)7nhdog^g^?7#BolPTcQp*E~gIvP1lD9EB9{a zig%EJiGkql#EEcatknbLBwrhz&rq|fxC_K559FnSlcum&>|dNU&kKq-TP*{$$Ab=n z$Fq*KN6L*hH@g8HCmWwS2K;?5gzLaf#)yuMwt4DlxjCoH@go9<((4cd7`F42*sA3F zkY|1UjV-fui%iojf5c_l8xBjq^_XXf6B7*)KDwD!x$~2bRT-q5!PIcis340VjgZk-5nyJQVTE%Ck?w>Dl3bwgfc-A>Q3E@=#tvjJI+| zzoCYZ6kK*|rjgv&vP-9JRfoK}eqIU?=jlAD2UWg>G|$U{JOjC(Y3yrhpC~$n{V=3K zcRM>+XSLr?;Ue|FSskHW(^-x$F97d&yuuQ)**Z&UeaITQ2{Sgr);Iir1qzC?44_gu zsvaO3o>%O|+OzZ596a7+e4H%*Reb!37=w7+`zfFYV!9H&yLJ*D7^-GG&>xy|(BF(z zxZ+{4c^OmBYr_&0!#R1Om?O~Renfq&L+uJeHWU37<{UA6V$`r9)ro%X?NNbR>XIHl;7P~OsL<$I~qyh>X`h@NnFdIYhuz;vQJ*TEPG|a&2b-z_ifg}6xaCsQ zNZi^WjIz0^&Ws5th~SRhDq}4A_-Xgn9`u@BS?~}0f+X9SWPhxqebqB5-K>-%zUB7P z3jbajt;Q)QZPYV)Kyww-_?(o|r&4%9y|8sL)Y%8dVy@z}#>%L<1H`*6zhNc#ysJE< zk-s)yv91Pl%ge53d{qvsQblPrzLSoam?jQHi5y*&QnO5 z)--IBpYgm)FReI1Q77d`#Kb0Y3_`qOLx)r|GbX9ohRtWIO<5c8X?EPd5Sbt#Xs z>LJ33jXtw$aQYm<;#B0pvgB?j>V63Px60tEr6)QlHtP|_vGhU@rHXGb+R3-PUjLkzy#;o`S3lwB`` z^%DC;HNkwAkfFphUEBcL>an^)?e*13F3R)6kbiBT)hNJto`%naR*Cmbv7eOiC!h!n z^Q%}a5PrecLr@Bq)9_Cj)$s*>;@cO&x)leSGrSRn#tC4B$p0<%Ieo6 z4ndZ<*azABgJuXv=$;?S@$DX_RSK?R=>Np>r+Iy5w=1SMMQ=QVNGxQw^!q-ByI1#~ zG@cp>1!Tf_=;T>=F=1}cPWw{M`>F^Z8c08Rj_mK2!`gdOvk%TpC$4fQrH_!K?q9!< zkKUk5?m|8o^mod?7%R8;o6CutQ&j>=ZsY6C5m={m5?11bj@d5Zfs~Oi~oEO4v z!MD-I>Ea-JjL#?RUkl?fSCTbdSRW|cr9#=dcRc<8lOsnkuOZQcn6ttKn@jzUENAY9 z@0ql_+$!!1oKUPU7irnGZ$lJ z5G#zG%9E^=L6~}71-nV!UT27}Df;aqY_JvAueIg?$2mOz1fY)*5wS?0h@Gcg-dF8i zD-3l_17vmE`_r?ZqYcUl2A`g{kboUUEwXqdB8TcbhGs1X#e0oE79L85-l0DvcI@&k zh2b<&;=5N3@HAl#0^HiqEnji)g9Q*NffT!Z3FCAXz(M3eE7n$e6Og=u4${WAh;ET9 z#3h6Uf062Mdso5b!UEJVN&j^CzTo)dI04EI+pk;HOUTH+JX@HqDAv&PIq}WBL*d_n zl`5@jC5)Y$w6j3X_1-ymd4fu-ZvOHr&L?E3(G?4wOx(YMJB(w-V40bOdn{aYW=)LJuD zk97mP_&kaAMw{RV!sg({L0ScVesOyPkVsBDL*iy1quwnrl6rdfZ*8w0HsE3qD{|&E zqEbgcVRwt-=2-C2=ZsVsa%kB1$rz+?5ObE%B2Y!eq|=rEp&NjOSbF(|`h`uFY6{Wk zyXTR64 z!4Bn+UxUpm=X^sjg43y6GV&-JL5d7};7DaxE_}G?cC$2E-3QV#rDQ`elZi?grvRuwdk7!Vz zd?jM1I@Fa&$7y%|zGB=$+p!wo*qp1JS!{iv@Tk$&p_EO#W%1>rKyEuQI4~r|RV8VK zH0w7RJ0^^@J6$wfL@oxt8=OVb=bvLQ+*5xM&i{n7CpX!E*s^&*{!;(G< zI>a@qey?l~&$nyKX?G0jBsWc{H4b>ES_gNezuw6lN^aH&;_@{=?J!17l^K$r0 z;GLdPOQ*2j^(rKy8wZb<`>z_o@~M2-`fIDsDRlvE%i3RMKa$%}sHSQZ{R6(htIAZ5 zGmaIu=fhdJp-kHkX@ zMjpi|0pHISxX;eg&c1TTuw3sG6KW7YMCNIuJc}!K@;~FBU`*W(u4Vb&#Mhs#Kl&UL zMf_GXJg27u>b%8Rb`nC?;)b55AfodYX-$!WJ6ru7QFjUZLV?B?id)(OeMGUbm&`F- z_umdZ1Nr=K9W+Hn+pZpQDz4Fo_SaWO`6+9eC|M>LmM#s~z*-Xs?OWOKx;9j8uCNXq zYREyap^FpvV!5cVY2hv;mwKGY_mYq_?Y!1#Vzi5wA{ze{(}r9qZJvQi6bZ zc}2oq80{)vepKYJxgGKM3`o`Usuhi(PxW@)r@MEv((TX!?>>c$4X^Ci>6w?rfJ+MllqDs_|D^BG=h z3Kz}6g!yY)2=`aKFVIHj3o&)6=L*8asx3_^?YlhGbNFUvA!~}O_B$YIGc!NH)<+4V zfaqU7(9;g!rbuF9Se3!?##Lt|Zhp)I>c+@~2dSc;o1q@uy_;8tN8`S4Z8C^;2_Z&= z*QIGzFa{9SI>tNkyfF-LS2dg%L!Ioi5Lo`aZK<=0mG-eTz}m(0dGgtfNGrb{eCi?e zpz^Zc_!(ru#+eD2pThA0p|G#iHLqUxw}E9)w5H!%{D{$$xKNv1pIUu}cO@xt?jYLEt#=A$42hByw1;~ezC@87z|)L%TJ7=QIie_iAhyNT zi^pC50dST~>B&D6to#FXlDk32pPHt*HVNNgW6*&ld7e@rqbo$HCfz|GX=oLyOiw5m z{GsW-%z-K|uCsUm?Vb)nMq%}E{pux}pt=!IL_U+h7eCP=pJvrdbxP|K+j9ZxWW7AB zRNdjhxDSMO0ZOBV9aj>55umNEMLe*1Z~Y5L{1dc9X&Ypiw{!IT zUu{9AL6am-g^29eXFzg(O5T6Ac%QyujGeVQ`?kOvyCaN4`C(u5eV7>YtnOCaf#-dT zKQu3eM=2lWpO@CzPdw+9-s{W8^_EjSXMZn6h<}o}_9QNszb}V)t^2;T=?CfFn|Zyq zohI&nsPk-8j==3x7q6C&)HKoVNMOO~o19jeH2kaq=m3(}<9 z>a1<~Y<4|qSkzY{|IPefUdq-|IK^_M^=fd}e+tbSf=}Sn6Z^~x{~e4qT&CJb%hSQd zR`zvkxsPB4JqaxL#fNyt^MTIoIU4=!v^l<&gctfdilb>CeJWGT%gEMu?UU=^#5A`H z-b>LtvuTu^$0y14OGkk7WoG^aC`Nr_fYgEFupo(_PD+6@_||Xzr?rWCCtQz<1(L*x;i2 z{|2?#PD=%NAiitn0ijYssP%Z2Zz)_os1lD$B7)?FfKoqjfK5}iA=VUtrRnu;FlYhH*cMBA);60i783E zHH+%U-hEaO5=j> zg51ex=O6yEvWr~;KjRbvp{WWSrF7cMkX_2T1yuT_(_Dmf&aBjKKBI5(4V%Sl5oYduRq}Yvnv!2@ zE?J|R9?eDmU_Z}L4ijX@PFyP9y4^2C_@%BB;$ricP}1d%KlEBUT+Ev`$;fY1)$_1R z$y+d4)@hX9Png`b&~q=R`9Yon`g6zDi|(c6+SV)dq(%53^j&T$1}nXn9#uNj0_m0O z^ipFbP|o80bucttz^lYgArxmH5bu+S=tEKrV7IIcU~YiQN95wIkE%b|Dx}m4$v1$i zbLR>-Wd#*775d81gSE(od-jD=4&1RFN{%@yWkh#)pEpen56Wkh%vIBteqid2lp^*w zubMVb(?zug85{ndR<)GfNe}P>&?f4N9Z=5;((-=FRAsNZbFJYoUzJ03_%)+~h!JDPXf6%e zz^_#ugOmy!<-bc75MTsyLWOW4{yJFVcQN=2s(ze-Hi@Vray|2~<^*!S*!FV@f$m}s z>z8k?7~*OLMao#>C%%BqOQ5%7yBnL82M2zXMEf(0Ps1O$P+Yf)^oczaCkK8RN z1jqQ>zt0BmnO7&})Q4`aeF$d|56sl)`}`}2=c<`4DWu36LG|cZg37-8d4r?LJ6*%3 z`Rb!5QyPj4Bx@nlbh-1mTK;aMOGc`1Qk1IEx81#|6q4zxC}fMucBy3!jbZfJI#CO( zuAvOV3{TG>rpwCbstxfAY9XuP^;BzOZSR!;&kw=^8O!-uHi(h~9zIy_ZKSd(ZNClX zj$*>hwoUr6NfNV(D~%xk`|k8=Ep$W%lwjK44+GN0J4QXriHF67pwsc?PIrCt!YbY- zBllzf!6F@sq*3gUw&UT6Kn9kE$`yO+0ZUj3m8cF|64AFm~x8?}t>pC%1h~<_n(B8*)DX`dAOzeFY<*9ea`t^*gliN+x>2h24eJ{)m$j-n^bTb|uIBgvywZ zSq6W=U3+OlnM2gBi#DC#flr=+*)AV@(vN!XdiNzUr2IV0ZO(0<;~x`L*(RZV(+lb< zz0$yHRXbANW};nF+HQnzQhiE*UsP)@>QTc2sBeeEXVQXHwkzPxRG)-`9@V%DMMB^! zX|2_A#e*oZILog5;R#e-MS?ENs)d3E)l$nv(%@&+Qj0`N;dfPsG{_W#SZMc3P>V$( z;cXR}3fl^@zXN z>lE0W7E~566zE8CC2%Hi#@UkVDZcO@$K+(e$c{@`a>N2; zTce#=EO;#Nj`Istq+Vt9_PpktF?<3D^nl9|Iaq|>l>Xp5`P-t7-bB_^;EsVu2%)n3 zRvIvwLktS>kFtj|x5DN}{O{cr&MUfGOxW5#z^dxmcL+Zu)B2JHwP*y&R3R>oI%1 z3ps^h?oYm<^oHSMtA(O0o{07vyrJ6t*h1ljPS>@9Njg*3DO(^9KC?mdAILJ}ogP|WT;d(|~r*w^>*fm%iKhpb67g7o%GAr=5 zl5#w{?fzZ*kv$lWl~-ghMYIS8U3RZ&Xm)K7)r=oU4h(Df<841R$$bwO9pm`6 z8l4f1!*dHyI0-yK;r?KV3)C>bfu1^`M{*a#+(}aD`xzH5D~;+UF6dejigE44Q$q?C zlI_1fu;YOKhX<}1gsH1Q&qxK8f)VjSKQ=UAg4ipQcEw(i2sYUxjtF5v3iZQRlQV2` zn{6-SIxTwga5KTI|B&YwSjxTZ8^3px)|>zCqFb>in|J@Uf_Fqa0^{K3LDQcF;n zzW&`1hLI?#uVnj`sADsi`%$Lc>;SCB530cr4xl}u_>bGpitntAk|8LQ%Ke7Dsx04k zZ;jkrX^|Bim5qBysoZvU;vf&tvuaI$Fj`4%xMJdE^s|~s^K$l)o7|e4RS3|@UW9gV zS~s7!#APY0zTFO4dwduYpW^j>x^~;hzx`PW>2V~@&3<1kS?&2Y`P2~ry__ZB_WY2g zx3@ayo(7+q;T-?t(EYiT~ur^Z-UrcaK231H`7TlN0> zqI>*(l>+=@^+xwb#TUqNSNJNqO2c$rK-5qCx`X_|OETzq_1LrX9H$Z-R0S7@Y++1Z ztXoZ}<(a8?Sjb+)KC{&reMR-8`=(3buJWwgexXbG1l<|OcnHEGyVPqP02T;@#F{dvQ^VQc?BBe`KMS5Q5byl@adIQ238r&WE@R}fLYZd2g6 zRw0X-eliU0aoF-TjErV)&^~={*n*w+bSV|Qt%C6IYx?SpUTk&2iYm{STrK9kf;&mQ zL5;e^<&b%?BBHT)$l&7H;AM0OBR<3PVB=fu^i1&BkRdT`B5~4zv1iFT+8cJMAFrNh zXsK*;escD*FsOZhP_k{jD!^t;u_os7OSUC8nO29-sChVGu(kTKcDJ!~(2?gJY|~>r zon>sgm(H(l)j=vpklbz2)BNpWyKCX#ZuNZT@o_ch0Wd^oNSO+c=vo`mVNqG|iJa`J z$hPZy=3o3*X;xG2?Ak~4C)bawVsc`wIqNf`$vw;lA8z*>0E6oozs(*_(<$r)Rk*M( zC=t6=+xe%g44MIQ?p|!H0OnI*A6x;hExnY%QLXHDIQJ9;h@06@R#=3zUK=bganJz)veKx9 zd2M=KJmj!vB~e$S?5T>8up&S=^Y?whRBf%LK7^h~bJaGo;mRLe^ou=$;siP+ZYzc^ z>*2U#Q;6kJ4aaVkId(G-b?+~LQxa3+Luf9(cy*A5hH8>xWi?%~YTpQ@M!}rBv(SAx znX|O`idqP7UO{VVkF_s>qzbLGKS4z%0a4xP20X>DFq}N4AL0QeIJ5oiN>r9&x~gzG zeSs8CXlUsM zV0TPoHf~dM%mIggFVZeA&DTxgjUvM^kxQINdU%-&!bd(EX4#v4J}FOKZGS(23UCu1 zxCPJBFsQ0+ ztoA^&E6l8a#;%Yk+kmxzwm&eoy$sE88r$%?!DP*_0e`?=3{md78IOW8t0Ca4(Qje{ z=zkmFHCJP5=fWv7Bj5{%IKToc@(=Gw-eo6`XatHR?|d(&^;$)nj-d7OyN+p*W}tW# z50B{I#eHV*c;$Wo1za(+aT52ocY0FuJ z&orZq0b|}i*~UGpz;4yFLA`C@y4n1>A5a!{ zlRH=T4ovpV`?I{)~+_O5dBjX9bw>-iH%Xen&SCb(B&InwEV*{7-h( z_*}M6C;P$|VV_c|Srfe(CoebGij1;nFA5qndouCRTa||vw2bdwgctVr=-(;ESBKHQ zCZcUGzit>(OTIJ7FIyCwBj>jNNAP(5e}c!t!^+A2ze!~5JY1~*r+RoUIZQ)U5__Pl z)tP{0WuQK~?J2!T7?P_Gshh#JnN%wB)t{P`4LuY+pGBB0Z2EVkk`a3TfB_^9B#tVo zxRR1R4h||#AGSG;w!Kr{E_A8wbV5SfGlcS?YS)Xcnubrq+NKrkH}|msv8$=6Mu2@% z_PAM}@N9xgqeq`-;sAJ90@tZ%{ z#D9R8Tq?CP(Lh@$$=gssdRpF~s&nc+?<#UZB!wNsIiV}m-UFv{?wO`mme4 zjKFOAO@&AMI)p?n?!x|r*QzAyrEiF)t|SvXyN`%RCm74NAL5VWTn8r}FpHAKE-r!aS1FJlxdW_K1-W*L}!k zM#Fl*?1}L98VcKhtg}z!i3)q$ihh7g)4wouut_uc@=Cz_pTk=ymS&h5v=4glx8+~Y zz#u%Et$?4ABJAqBR1H2>vA$vjMg)!INPKg|X1m`U{t)9R`HJWcP^fMZU+jW$#HZC} zBNkBZ$;sR6ybS-X&5*+2c_A|ovv-K;>;i}h%0W*HrBOKU3B%7U|E@;NMb?b5>Y=nf z72OB$NRj-g>vy~sNi0=y@I(8~0=5_y+7EI4a}5LQ#qS2S?5ajC5$r1$6DEZ@Jf}%Q zO&m7pkk5OHZ0;9r9`oxc3UCw#WD%+S!(BuM?<4tF3TK&I1BCizb#5;X!Vx#(YF;4c zFfAWppsIKLtp!S@+Y!g&DAeVZ5O)ZSR6oR_>WYup!*|opO2B>&rTW9|^G{aqppAd7 zKwY-{tA3Jh&X`_)@V8;slS7a}=(IR$s;3^;rY1QL%L;qEY@MaHre%8m$c%7L+oa5d zHC;Q6Rc>+ox2>rQn@5J%cy>BY`tG>ZSn0v}!R|rAh2aGnF?NhY4DDBulSzC2&Zr9i zmwOfEIX+;wjCK%dt~`l~dQh81kTc%xl(_=LY;pO+v5zyV=iZ@%gIgu~E-7KvEKNLw%XO8d0G#QCWvMU1XPH zZ7sCPJv~%aB1PMmNXARHvBSp0-cCi@W@~_Tp4g7SnBa>nRmSqO?0{~VTAEf%X$NTy ztI3aC+`)T~B|6{9=~~Jya#-ZJ=ytkt)Y=|-96?uuqo z<&d8*uOgqY@ac95ljO?R+{}!pDTRlsLPqIzYTzS-_ea$3{#;i0=qh@cI5#YNV?icRsj|G8%359?K z#&im^lb&Y~lo{Yk<`gbZ`3BBa5d^c4i^bW4F#P3f=4yZEghvW(9KC zViw3^)JT5Be!Rdf`i*WV#9p2~_=F zMi2w}xGMIefRwz83(Es+nvX0ToqpsRSwhr7*A8xzqu)nk1btd@Otr4xsctD1wpHyj zxo)v*Vw!F^6?V_t1Aq>^W><_8d+Y5Xb*@a8yVgqdf5WZXvr(>uC$>dBQ)B)xlI$CM zf)uZ$0sY0#h=(wX zA*0I!Knnl^ss2kmuQJt%ocEsMZYdrI6^^AaKHhMW+@6G~0~Ly;bkohgKys5RDc3<#)FnqB93s|V>pYXW`_!7Ba zpa9wL=0BqHnbU*C^H1~~ zKnhdRyyC^ji2Ku8ypo5<;QK0IdIch_VkthxUG2O1WwqSin_joCEJ7Qxs4~nYVWQvQ zC{Sh0Sqi?9L9-xm!!h`gii@Y?Vq*T(J|apcmr(-SkD3vN)YZblQD4AXC=B}54{Ovv zmL;9*voP73J^8Vprg6d7l*!Wsx||QWGxQQ8nICk@0{m4xa(rnAR4SgZy;OAOFrCQ0 zSY=jqO{d&zyo7g_0gvqN6};pxXErT#vXv)GN#>aE^GB2f%ePN>iSHym8cZ#|A zoPGWx*TFg$3w*9=SxYw==aNjzA7?qBL*E`q-yOUDavaP{vl?TklJ3hOXR%A?SqB+T zu$z6^Rq!0>I%e@~>Kce^-B&`Z*UwK`{^pQyE)T;p=4eRQ8n47wm!-pQK&5#F5*@-V z_ns!nh$Y_sIN_U2)tUM>ZJK^|7&V0}4@yA|C^8Q|;MI0{N)GM+9_mOeL01R0lQ{@- zllqe-P98snZ!?8GY#xH>B&^{i3cM4dtewK>h>hBCMfaM*d7mOt+_vBk0CUBLV1W%_ zffT(a4BmFzGvNO9F9O#u&J~Wy7*oO+@mF^_ZiGE<3|wlcu3XP=xo%atUZ=5ta$`N# zW8J!Ay`J=_MZZGDH6tlpkz}uVH~z8G55iaUWw;{P8Dps%BW-lIX(AB(Y7cp=K|ZYk zBdCGPsDaX{K_W5W1N0%E^)Y$|3T_*p4P;-#efSGJsiwYGEk$@8ggg-ddcEI>vUf?I zz+uMpxXrzPHw*|~7bf}pY@;Hd&K$T9b}JFGHIbtX+JjTs!x!5_o7p2D+JoWP!|89c zc1i#`yRmfpo0|V?ArSKfC%DV&Eez(V%3fkIBOFUFUOb;ws10Ia$h(!ySEMZeU7Dba$7fJ6;|fH@s$ zIW%fHki~k$)OrHjdRPHHa&@5;XD8s%(A;cSfR z$dH$9DM)WQYJE8%ZOn-2;UM9xxASc9!!um*77ux=j&MkraEy#_+p9=rgOOIiBrR#WATcpbF`uUc;CY_`?NWWpgAt1IZdZIY4r)LNoP?n zcyu4$B`A^0Kl%z&@fLAXJF{Yfv8fz-@|vG1QD-3HucF&{J&AIg2*6@}gt_@P)S-S=^6lHGS(DWc%LOvzteq}e5* zX;@L;EdLqxQ7N5_ZXhKA#X|+A5oWHGly=gp&&3PsN7lJns!;noTuz~|5HF) zkwX&BFcKA+k9LejPo8dRfAkZHxI?W7!J;U1vuGsM6jsNDnawWpylPnDdQst8K00zl z1}}!fvK5VNj`!CPm5{4_#`G5F!)FjQ%l z`ulBB*9fz2&u@VbN!beq2ouJ=p-6)7?}*7h7ij7gOmVB<^Dp9nVGL1GnuZ_3mT5|o z&)+@T-KCM3d!nex7U3j9nO*d+HQUF^86*-DiSickI4B-aFgY{bflaj}kl2?nBVCM9 zGPMf7ZPEpwyT%bHUWJEeODKPPj(Qt3Bgr1DN*G?P_v|A?{UqDA66u6;=&Ydq{#d=j z^k{p%irt{{29%ZwEC~p{K5dkWl0G`8p6FP`PCHkzUCodfmC^cfYE>|n>s-449FaB; zXr~(e@$blQ|E@A+$F%YDl*oDC ziT82hfe?bwiztRKnU9swSxL0BT&6-sMNz6^B+>Ob5uY$6Ydzni>8~E^j6f!DQ6V6G zhOxyaW8sV6TDe0UX0x2+ay7_xbGw)Uj@ zzUUYC#Bln4<`grf7R{o33$slGCPt&bzhE`8y-vzwH4?TRoiRy8v^U;bGEn!zMQhn* zoL#Y*?@H(>>dmRtcr#@S4h5ybIZ$^vo~OovFwN`ndE!*RL@^LnqWwo zvT6>sNlsebnka+Sl2lsC&5fWg?O$U8p0SDRo0*C0iu~!BZnMSD;>1WOqe!Fjw~*qp zwNpo!uL*+!8?`3rYj7Q-p(0qciA{1^(~0+V1z~=_zLPFc%N_X^nEt8+B{x^KZ?66L zT;Gh&NTh)S<~_+f_}d*=-<+pWaBpA)pi@KXOq6!nT#F*l$P20-s0!U<_L7hus|tOWR&!6=kxLr|1}a&M zkU+3x0g39d`P5q> z#M}rvY>L$UABlP=i_(4ip)vKFSmNd-5#i9hSohY}+P2j;32h0Sf>o(S)zExt z>I{#>E!NzMbESu-4BQ>;Qu_CpH$duYawx=2fyBF_&SiLq78HSCRQEIa9{_7I9YMV__BaJ*>EvZPkv9Fmr1r{XHJ-|DJ%nS1# zmXpndjm-c1QF(ob<2D@W1y#Im?U;HI5qtSPv!(@LnR5$`IhBg%&FC8j!e-%l<$OcF ziLyrg&Yv-Y#+WM8R5xoM8mLFWw)i%rYGsy;0FxyeKg|?lT4C{or!JR z=ESybJL%ZYOl;e>ZQHiZ-puptp5Ob&yL-0#be+0gx>cuc)vc;qpRdYOAlDgksgoVY z8@jtq49vxz<}CC+LvQYhW^zldo1|$abw*;vtq8K!Utvj@S?^m=gzK@J`0GYlp*MJQ%} z{F~_E z^%ACYE`+#Z^!;s1u)gOb7|2-qM8JRB#$my?{t^9+2$^V?yu&`S0hY=}AB$NC zv+0sEh(w%6CHjf;H$W?}sFlj)j}DGPL})tH>AlM`Ae_5w-Dxug#P8Y_D>#o^yP^qw z+p6dCN0b4C*2?O)&F{0=Ghm-**_8TT5uxhq{6#m$#R9p^3H#u+7g3W7IXmocT;F?; zJ<|jdLj;8fwIQ65$J&met(^^@NWFD9uCZhc+&Gth8xTTn5;z;F#ehDlo26$C$B!*m^rtEEB~!57 zdVS_8igTbjL3j@XUaK?8d^mgFNl?N`9d3j)T#!^{p0FqGeVX{3*)?&)4`Px+5{v-V zRUcGUovn8{XJlD`o`)$PAT~_ksyD9H!CIm`$XCTSR`zPYK7XnOj3et0r#Q_=(l_;UC8o#r7^78h%s;t+W=+Kzgm zvHkANfCaT z{{l)ijc=gP9nfph=0W~UVk^|kzb5Neq<(fXuC3khQ(s00h-+~}G(O%t>N!)f`Hyp` zzG&^0(0#g<+$=sF>ZZ~pvD>m|e!MC27Fdkl>iUB=sPpJ{J0d(a28z}8W?L2aFRzJ$dn5mOt2hq<~}RDJUQ}bKBToi z!n*ORUYes3nY(do!9)(O<4W3-SUwAngaJOd71@5Cx6ITW6d?=9%1U9KKn*jA6n4C? zuTSgW43E6rPcBSN>0SLKkV;BndoZo9CL8KHEIodnKJHCQbXk;iXaClYEE?*W_QrxK zM&&AJ@MLI^4Q1=$fk~gMFpF2$BQH=SB76iOgPss!j8OWKb_}S-{0>S3IZvWn7`@}Qy-2K=3>q3|Q zrboZK(Mk(rB{2y8$MZKuIOMfZ5EilKUPLyWq{L=@Br`KEEtyd~8Yf04QtJ|PUnv4} zUwU&2;vd0@!HI&t6t0puyW2(HPvRg0K0o$f+w@#nlE-!6W#ZyffNq!{Ir#eWd zCdQ*HiBgDfD`4FJl@5P_5U1#?RkM}}IGa!Kf7S9*SJdi_X`}hNRr27KGC-0in>9f- zT2~VVE6!Tr5Yu;3U6cj|mCMu6>OHH;)SRs+C$BIW3opA|dl7B=BXGnafj-E%WvIZS z7Q7ja{$^bSEemSgnlz!oWw^;LCV3&%n4J=)RM&mTtzu`746Z% zS{ctmdXqyzLP6M~Hm*$_>+PU5ZrLzS4FT0y8V1kY)LyY=I~`A*Qe>7*7ngCktB0yq zdWl2v(%RP<}vvMSQXp?)QgGcp0F!jzvR7MP_od z6ZD_RJRK&#Zeg629E`NLwfps4cr3YOi@tD-%{O!+mA0hS;4(Wd4J)+aDGIZ}UQuX1 z)Kui`ER+0JXHHYa!ny8P#xy1&QC1k4Zs+O#K-HN`IIg~aTwgywuN3m06dW_Q_j|%Q zLA9tkAwt;}Ft@-wdh(Q5(Y3R(zCOQ$tC*_nSZ>!m?zttl*%rhREpj+^w>;8IvwCC^1A<)T-{o>enmRQ_HMA;`WKz3#Ff z&2YFd#vvk|Ly^|eLVR?sCgq^Q`NMo{4T=F-XlZiXFe~0niUubu1Et~_P-?8^4vWXa zy{4%#bnf_MKxbu4a%u^Hqef0KuP57da*G(1DFMn|6~D7lD#BlHZlxsjIfXv`P1*W- zE~k0ZK|@1ji@HyyXU-5?t(^YJsGE*kl74nN`=PBp9&YC8#5Se)qz6v@HiE(v3XS=X zU^SE_^mQxSh!;t88*Q|Ny3=h>he#iJmlVFnZW8xl?eoiPRa+7OVu8GzdJmRRvFVbqmTimfbj!NU zv|bcYUN%qZz9zWz6c8GcA4WA#usFx*%-Dh7sxJ$kB!86;XAGexZEm4dt^Gz&A+PGE zph2cn0G9{g$9ex=fe$9Kzb1@yGR2?obE-ti z3;-Zq^C4kGw9bSMnfKQRFn$BYm4iVNy1=oBM0B)bKNOQHP@4%kDig#k_b4AgR>NnY zfwn*uwO~ak(MK;in8R;~?w{sHD)IT*r(3e)0suN&pm>iS(ajOo_@mue&R0?wfO}_A z_8T1U=8}@cDarpvmB3XtvsH*wgP@!Sy5EMi%uiw!hgD^(81orNkeD$k`m6jle#Fu!;l{;rn}6|g`9UxgJ;F9IKka(Bz9EvOvD zpk%H0g35pVGt3d%pB#gbi}RV($Hs>mn&?ZbBG|@Nd{rF z(yvk9C4F(qRnL!I@L~X($u%RJ7;$68_U`&e@*O30ULm&;iVQ12!p%GMypWg(&XY*UUB(t}*fdA7Org{A} z?!^dOTtAE_nBfRi^!}dsdLac})Zzu@cLmX(R58K_c*AEZmU6*JS2L)p99#0PTr?e7 zno(;DeKxb&TMlIhJmp$G1)j4UV%|XRbNt6yu+k%GeE1KnlCPFxW$nTbqi4)QJ#?JB z7}k*S5!g&BEi&q}D$#NokBBV73GxA2TdN$)I?JBLJw^g87}mPJ+GcoxuP*hD7II5- zR>}n{5;Tu`G{y)IPXV&}T~I2BC%m!nnu->n9d5yj6G`+>SW`u+HH64z^+*$iDF1EGWYM4+srQj=k@sYuG9N*Pn}GyKV*hj44ag$PggxeGKi7) z4(&l#@bU*A&pRPasnRNc3T!7G{18FoXJ=R=rOxWe>#^AL$uy{FkmLce_V*Zx@(|YR zW-Y-719To!erCyg{Gq_BUvb^?4w$BO+##F+t`K|e2}kGd=^r_5V2ihud+S=hF6#{a z+@oxh{ap~3=E&v^?W$(T#d6xwTJO5E^SZl})woT|Hd;0InPo}xbOShok1--Gpl? zS(9hhEI#;&DY?jGnfyy3+V^js&kotDUNNOCU>{!$A%LS18`+40#V;nx{#ph-&zAiP zH!ub)-ezCBg^v!xvGh+!tdFoWKm3u_XY9KuFGsk`zK(a8D3*IK#<8O5cDg{Pvg@qf zS3u9<8)ICUBfI?;y-B!x3@zrzg*LUM47D*l!zdg5Cv#2o7MT^a((go3E$_&OLX)Pj zhZQiUyoYnl@CW5UN8QIBWmHq_&x7>3qw5(1dHFyjUZU)5RC**3kgwPlf8ZenfBFXs zhTec95rF(rq6wT<6Zoy6kBwvYVIhK&&)%qE34y^CuQDI5B=H|NY@iVJR61+J(?%FW z19w%O>XG1lJbi*ND$)LC{ngIDGi19D~u5+A0ZPs-3g2+CNJyUb(d4Yz+>m~`cW;|LLU^fPpTte79)3A!HDe^VyqfBEW zSK72_Q?!s1s&QY2wB2B7st-CgF`Dt2;5q#$c&!d(mr_#`<`B=rA0&XLgjL(}R{7XF z&AROhX1HiG19~|Z1(pb}fJb8mgscF@y7^fTQ8i5G)v2*1t=IYqjtUxzj0f|~_!$wi*Zb5!Jvz^L4mfXT%}|dBEY0R@j9GOvy5mfxjv1qNFUp^z#>bU` zs-0iE^vjludv9qSj5L}EZX!r$DcI3)2kJo!5QhUG+yR6?>D?^M2AV z>S?L=10b)SfVzdW?Te3c+8>sGAm|*uMb&iRWjG7gy$de>S1Q|(QY_>XY#A@xnsx;p;*(`v3?GiA3AyO86EBm0jp;6qh=Bbj`eNwsJh~Cq= zzY)>cPb%xyoWiyu;Y;Ri{ricY7Nvq4LI6Aec;#|uiT`fvyT1}oQlq{cr;)iX z&6#w6Wf?Cn^3A^X@Dv)j}oS<|_N)&>1o@NTEnr*g6%u?(@Z_U;3o z=oWt-rfvR3m6h0k$SQnMWup3YAtAe+ywP5~kY&3JJm2CJy;rgxwxV`C?bA-)Bb%pi zYHSmuvJT_O*Yh))P^S}X;SINVB_{r4^buPyr3kHd8mIc(_vcD9G`=o#=eF#?)L$q? zHMS0$r|Gv&&=HwL%^3LnVST1^boq6fnytk%J<2o9rduFW0mQkdcp|LwWz*luhe1K6N&{7!te2({>Z96NA3bBmb7s=rKhbklV z$s9~p=44BcS@aZLAcg+`=64!<7X;BR!V46Y3m-Yl8@s`2oL$X(qS7>kaT>SI?z3Ip zRa$s2budj=ld2x{F9HUWEIlkms}(J8${=bwvbsXlyu&2&&X}k6?MzswZF1)FGyHip zLN2ciAxr03w1jn^=yk=EhIrJErz|q9!j(-`imjWY&~N=o`(3y(7uA{6Sm>Dw2fhDM zWo%-~^IW+r=2)FWu47@%9bZjU*8Wjtez)Kik*#-Im#Isw;B7jnJ)#qkzxyoBEhh&m zr>%DkHq#=ULsGK+$yNE_#Y&+D3qP)@m}=GUZn8#HTkWYKyGqn2HNx*Vrqn_im1Zo6 zc#UHDM13^f6mf-+^);g;4kma9yJTM&Smb}5y3W+iU@fyL7`p7)CSlsH28-2$QTFoX zLF&jMJ`OE%!rhW`Cy*+O9a&nsh2e&zG*W9!_*4L+Cb#C(nN;P6lJnDq#L5~<`N?$9 z?vJ>+D>NRBDx?!RdXlI zR?Xor^zbo@1kPwS0TVs~R(Uxz+fD^HV-;)F1)|M|7S>JR2oZJo@_pB{=;er-<32NgJy=zFXX z7b_pfkNb}40Y~+m=h@n5ju2X->BNfl-gF|z1;3NhK(jQHm?peDI-&>D^D`PtpGxn~ zu4xwcgeF0!2P*^=;34if0>meC58~@DKs9C6d5(yUx0EuPG^6b7BY1|nZnGscu3$$s zuNJuUJv)4$QuN>S(i`SGK2d7hH!x(?EEC=0#*uguYiToR$7-#?1BmMsJ!!1BW*nNi z*+tVq@1RT>pre|!qNaBxm-AWq=(xuopNDHFxc z*zL+q@y7b+l>J)Irqw6;fSFygTIG`gUZlmOA+Eb~g+Z28uLtxH7+7H4dbS{I3bY-{ z7y8})8HId0hPo3=F2cNg#0;t;0h5G4oCxIG~ z;%WNOAi{uMsJ|MT7qe(a$E_dhVz@rSZ+)&8o|7v_>m5@odAldtyV9gJ4M?2PJfiBMy-}9NYrVGL|x-5hRer=LqD^XypKo_e-$0gn1 z*ql>CEE{O}%3a@NnGKnCa{>EyZ9PFjqH1W{S)ng9gQ(dTjMV4ysOe_QvrR-7`1Smj zFBX$@s)>b70QzQ%HC@vZv$_g?2jfSkaHhq+Fc}j^t0{d%PFh(dN#pg8PiBHCnCEAbK>lFMvn9_Syb8dP zYD^;3Wx0#F?xJn)nPOSt>|uw+xK%=8FX3=e9lV&I(Sf$EFgs&xCza^D`P z)79BFarPvcZSAfvp%^M$mq|Sb*Qh{j^lAjPrs8jT&3H1s0cG!aoOevKt=g@_e!Ws$!NRjjib;CjuGo(I=V;=*c0pH^aHLnzgm*h-*`- zN%UQ#PRexN@eCCJl$VLkRBb2$2NoTGeNE11P`KElNATvhr4VuhoExOd~eo(ST+4gf?p4v4YH2o zV#jSr7zR7;h`@{BFQ}{zrt2;EMWww@Og&@yb#TUZ;>r! zg%nbP@t`*P6`>wHDp}q(3Eq*o5}ip$CJDvGUjQcEf3YlL1ie?yS^~zOv-yrT2(PH( zzi(;V{lvNI_K9+IDj*^PA%H zIU?mTE@=9ukP@(&a;0-(_!$JB~XCZ`awDC3EvkwvY21Qf;)#(su4_3{}on&?VpkB#|==q?vWQfj?~HVSv`V z>meSg&r5MU>hozcHpupl5T9MaZfO-a^Pc9H%z%gT@bw0XyAs6#%_-kadChlLM4;4u zCvq5SSWXb;NoRj%$NC4#vH7tBEc_O*>-w&29jH_g%<2GqE`K98y*$`3DO=|jp<#&U z0%nrRWyK>%dZu7R7MX=Mh}bW(8r&vHG_q1{bjXyyVGU=SXh&%y_gzSw1}?c(eeB0b z>gz_?tJ1s5(u_+^Q^WRDh7u&)^T4*-gW4|WP2QpjE$A7)Tvw)5jQeDRJDJ&y z_Q-7(W~bQbUF4IdL`xjvoR#1h2F%U>d0otzj3k;gS_5`Ngex1;6;4rrC!%S1f9NYZ z=9iFepG5f{W#p1RbXi{KVft)F!rd)Bdlt7@o-<&Y;)orGFL8Um(93{J~vQP%1Avr=_p!MHF9lDwov5bVc{$+#lX;W>O z%OZn&d*}M#c^;CvwJUUvd0NStcos>2BXU0M)JRpkf-;47)!5cljTZpW5CogZiJ_(v z9y1Jbj8+%=@#qln#_AuLHMj9&-1B4fry%X)U==Q0H{pwt7Gtrt1ZvnRUMqS`F7!WX zUEY${vpJ|b407$qJMOeA81Yp})x~5IM)~afHx0+R!+(yv89m<}Yxlp*6vBMEpX2Rq z5Df7RX^?otBReK0D>#uqKwV(SCs52g8MJ84Ek6Im+`7DN#jW$c=}ZS zQPS}KnczKlr9G1~dZqiZnc&UJI@`7@X}r_yDuo5mssUi1~>h?|b z){Sak*EWlkcGHA**ez}8*k#YNb!oqH@rNtoR>Sf7Z*D7^rT577#L;!!gl63ypTEzZ z3JcjV<={d+SljB=P~+fC?rW%zRSWQ*$I_RW;a8CiQw&?*xyI+woz(kXaXGBP+)$~% zIrhMJ>s*5*!yozrHtoQQL6!Aru8-gXex(jU^K-OZTic;qfkAXL+hMW~5Y z(BnZY^mEaO$eo1`-xoVpLChyD9uxH;Tl7l~?R>@^Hw9g$vERViv*I=#IIq!XCG*E-Jr@h-_!{r5nkvGdAa% zTBfL)RVk;b&|T9%5MH*)Fwt~MA$LM&Z$JkdQR4UaYTai)KqY4aF4 z8+8FBHXNLtfu);|=#SG5&P3i(V4ureDN{cW4c~WwQFJDigLr$;tkzfn^D;3nzRm%gLT}KV1&7!4?z5c<4 z=MRd5KNhwZg&WT|h6RLdoIJ`V8F`gtuM{ktw?^NrCHvl&PvQ*(QPT-s&poecPysgl-68DXZ(4o-xzAm6yeMNkckeyYmBlpVGJ4Dhs7fYRkumw zB3D0n7vr#1<1j4>QtZZh4wLAsGK*?}z>87zmM-fsKOJp#F}|Q&w*At`jy|s}G8Ezg zPPo<>{R--rQ_DwFj;2M^Y^oO{TZH|iFXg74bN+4*A;X)ac2|OMCLdiw)M|$-?c-@3$mRZ}FyP zoE)+#8!5mREMR8=Tz}bISk9pv4Jzy;e_!i`GPX-Eh#G{@jg!WpP$CWf0eSP`yWT` z-89?n=?YiF1n(almhInW-JhZvVrI@G7$P0<9;@hWOr?p$(zhcAs+yE=d3&{1$p>3v z+?~q>D2xpG#0&1VdtYeCOj5_*p)>5~SrqxI6q@dA9$1V$3r8{E!@A`^x}QRTY@Nw1 zm_7jAO=XYm2quvTDXbdT_2+&rT|GdKPbph`hacW15#|o9=pC^YdVy7b5nTkZTTfm$KRYj?sX_~ zYWyC&6nHhAE|Tynk73_}SP`>CJs7{gmP%g?|KN+`YJ3_xgLw_$qS37MV^Sf*Hj@2Wo_bRAKVrWOD5lb_2~@sG*;=K?Oy$ z42=i*Ki@fxQp__Uhtj$JGoNXL`_JQ#nYX+rGGH-@Z1F*6MZ+C=mvENGW_)67(fGCb z1ihNIUZ5^6e8;qB&eN+ZaBG_P)p0fE)p;q}UTLG!&{d3x(f4(lRMDi$#Q@L6PUv*s z8)tSQ?BQa+QZ@CBs=)n;iso-&y-Al!YKIs@lTyvFbvOw!v?mpcq=!PyA?S1wehh_+ zA>U?RTq?@4w&7hjD%KHISj}J3U^H-JLmy|366fQT{R0cvJxps0EE3n&u+OgmE@705 zjlUVFu0}Vl)O&R<%x>A7PBqZ-*leaO=WWhSbvw_`;y^k&d8Wzo==kYAo}3LtZzhXZ zpcNw63gY9>mfZ2OuY`R-I|lepy|d^PTz5E~4*}Q*)-Xg#4l>byO@l^8g6(->*0u>@ z&VuS{IhoL_GI8cX%fT`JRHDWDR3fl}FVMafli> zx424L#XTuJ&EHtPL^ThX3*q(ZHOvV6U5%?sv)|^~K+s*krs+(M??8XAOxEYIdK&5_ zrmVp+jBVXehdg_nBc$La3o<6NePAwhtiI|Zr>it&;D+Jxtuy$M$cIS8MxorDYCs`3 zyn#kx{H@X5=nzpPaFrLe2)1evyUgbk6tmug)_tB?+c)7>y9hN^GoGt1fL^`wS3P2be}=Z z$oefM2fh-IvcxDLH^V!&^}nxeum^bY20W^?o{Snf)~FwTI&<95u)<2#Z*djzxQe=DHk#A;v>Po_3&v+5c8ShGx0#I_$#YG4f#=iwL zs2jk)kMujFX!}(Xw~Hf;<|e!{hc+GtB;d zz;_5ZhaD+RwkC);Tg++riJMP4528EX;%NJ^|8;!!U24{GtKqDd=o%A30EzC@VX!O%;Lm|4cn$$r-Ftu+KfPtpR+>< zbdl^szn+%MRToY+6_YL-feB9~r9QZJvW;z7>0?-`)bRzrEaardRt=PzSB?#Ve0TR- z?f!cxH+^L}@>bOzNUF#oouhy)in`L&kzF{(f^|?1j@={pBKSjrSwm-cBozIM zEA{~Ab755DgB^`CS*T%s?uhzX*lS9;uCx;j#Y3s3`bC%l%6nN*D@(7*P-)Ai3wlXV zc@=hYzX-GTqFxMCnX>CjsH+0tsApcYDiY*2`jn_N%| zrBd;=FVvh;a%ry`D%3y4Of?7_)j&B^rRU%z?nJR9>-R_5JZ{NSfj9L->by-!Qh|$j z2k}GhJbXcBl84Hvr-H1+MXZP5sis1VBoFC>bBS1iXg=i$-0FE#Tz8HGEKYdyBpqD}6e2MU*8OIGGX$O!0M+cDC zWoa@4W`~0w|83$Mi5~B=p^1B~77t!cK*t{)+!LOKwUxCw%S}e2S=Z94x~ifnt@9|R zI{P)mV~S}=k8vwmzPh`H%&%7ke_Y`+Aw!#nM9TQOfJBcChBab1CX+-OKyE5A zX*A|#Te|(lZcAh2=OzEn)D1uo`IWsSfVXu~!b+(b-ECpoDF{??b-cLG8=i)AD5iZ`a;aIdcKrj z==rWIs4Z;V)B_u_WeR_`AYgJ;FXGy}7=Xl^eigu?8;xhos(bM4z$>mf12+_B7a8j-X=(5 zg?^m%f(F!d2cQQ99d1bS{UeoI2a{SN89k0DN5iye155 zQHp67oj@^}-9C3lIFih#y^kFR?!=*yzOe5%%kRYN)-Z5nxFN_fed4`4{o8hb?bsQP zr+Oo;uthmlMtzI)3Ygu{;0ST@eTfm^4a`8wOy&mSY8-}4>#ia?4C=76Kz}{loqGWq zSI*1#lGKab7+q#=WL%VAotx2pqO=EeJg+D4qNDoKXnM!(^mCA}3(e0Wu)Uf391H^y zCr9josTeSth?C7!W!n9V!=Z@krOBC<;pXPLD2j^8_GaO6i-Yj?f5}+k!k89MOO^xs zg<(gqLI`JIMiEGMnhBs($N##DR;a7*Mjs#CBic+Q%qzL4`QWBpWNr)^a0@NtO|_oi z;7PstdcqApxdK^tYZh)`J&_tr}s%nU3B@Pn{x2Q22Q^ysl_9~?I z5i3$$S5o`NOzYT?J7O*DOT}ngJri+15$pB)7Mkj{aq?av_&Yzdh?=nYw7Z zc=nZJJNZAF%io2pgw8^U_G>)AKlI(g-zt!Uy>^?;J)=!GNlGh*LP*5}C~LNoZq&4srkj~P>fekYbOdk;;`X1T+pf?)9mEvE-^|$h6o-PR#-Ke1 zolH&J=$x3Q&Pq-$7lmlw5a0%pQ`m2^+81Q4)|9Xz?7G;+A!YWE=;KAK^Nj0Bs;EhD z^p)`}eye_dwRAX$rN)MO|7VD~t+%3Cn`pO!!)X=b41brwz6D8wGdB?Q1z$y%gERbH zT@wXbpPvTaCnN~SsGkG>g2bLl@VcIlp1h}S9Mg9US?F|2U)-!QW6qd%xI*|iM{`jZ z<@IewUgjT7PF{F7xfAxeE%3CiZ-Q!*@W|iXFqUp4gbtFhc)iUR`&7$xHoFVN>ByR3 zi;@`9xY{`xRxF0_tQ*!u>e5vPdVN%ll_Q<*s`frz?{p`2U)#C+o^jI`mnd4wD@3f4E9FZje;}eJiV-ck={oY`K**T;z z#$`KNb9s~5dnXsr4^JodxR~3ohiYb$QdgIdBA!kIOFMU=A%dyZ{RBCuI89)nO%?(^ zYcv82XVAOwgvY8SM+5A0ds1`KII`i0#vv9Zwp3fk-qJHl(s=TsAYcvXZsI)U*l^gh zT`K-!$%FnU&A9s77a7)Rt5MNyt9_eXtH_hklUOnf90!2QXR(a>uN&o#i#HSzQl4Zx z#G8hxjHC7UDpyy%h^hm02K@aZUB{@J{U(U08-#?MK?J>mzrOGMDwPvxv2Q< zII2T#w@EUxo|06j4VL1>*S@GMCzX;O`$sL<7KOy}$wRYtQNfKRZ*z-_c5hF1%FT3mUNe<lSJL zcC_Qk4q>Vf*%?T;jRF8C+xeliqg>37aj3`F4kEG)1~x1NS9?vIeElO|4*|&z4~GBS zYIl-%X63YTt8m$THmXJ;-U*?0_MKC7X91H_YT_|*Mz-t;GN%mQT*&=*oV=$K@(xMo z(izQrQsojsXs6i25-Et`La+KH6Z7E5X=WZF)@BEylbG;UC}qtZzU=G zi~kGC#X$f6N9AHikFOzBioSj1 z9`@~H+}?B#Ory8pE427wQ)_9|WB1kuIoAEOc^E$N#pC)D{U>M3$L_S1RXprzx8K>+0{UV>I)PrO zpdh-&AsX^pZwLITU6E4*ghpjqgC_gMcC~`J$c17m#7+|AnJ4iuQLkU;QT4SE+a0w( zLHoo6LV$1p6d)P^2M7ZYOd5LQ-rg}gU^a(qA>tWk7#2H@s*nl+VgO{`;SVE$q)j%0 zZS~4-=Yo@yGnk7DRd*pH4Lw6w%QGM)y~bT2FyG|<1pja383V)r=hhW9cW`vVXJh%l zy)%3kCJs6od-+VF2IciXAGt@ukvZ{(t6Mr4y8%6j&^Ia0^;?F%zSe^fcxI<_hKvrp?6bVQI+~$z?)l9RrRO^=;j1zq~SKr*C4SIopWS)3A>@zDK zM$tmY*e4bdCK9*=Z|!$u{?~ZQC&!9Z))Ec+PPI6={dr&G@W&nG{&o@ zO6nzC_8uEPS!ih$cwHZ1c-__Jm06tr!bKBL{JUD(+4UBc3e0E=!nnf~7q|5zO!BZO zT3o-JYGXz7UzP`p>c*p~fU8o3dK$O*%z9Y&hw_R}4*kmG=em044LadCWA|UuCgviU zJ_%APjS{cBBoUiBVOgw$r`=_&-4?f#qr;Q}1&~Qj9k?(^xBw7tJgy^*Ou%aKi>cq#wb3Z4Rg;XuE=aHdUr9{A+;bPCcbHGr&>65t9XqW^o7>2?lx(l*p6 zg5<^E=tt+8&wXFOlW9m$)!Ri3&EehDam{t>(BzYmtvcleqYJ`4T7JzarL!PwE(*}>4*k(>K#Iaam~igx;j#{UwEUo&R> z??^(54EU`7SvD^(o#UwT|MW9__5U}cN=pB-^=}m3uMeGq zt&_f!F+M$=qLYKOq0@hJ^0ij<|1Cap`liObys*YLMz#hPu>V=te?4Ez5;eDSGIpR7 zwfdS|*x1n4$oT&$fUNWk%>Spr{SNC_U9(yHjpVhYdQa4XHG6*Oh42G?4Z{j8dE?tm z8V|Z!Beo}zq>g0t-pgx+q;9x0Wvwa5dBikf+J-ZS^XdEzz~x@P!^`vjY$QZcx!Cn8 zT2^-c{CHn6hqmdO->c@+=}_RQQ(}5*6d&Hbf2VSGgmG#54QP>S5fvkyhmWZO{k9HvH3@#;q8`SV9uWirA_&y2v;VFb6*N=5tLMufh zV6@CJLwOX(x3gS&+9Zvb$;=`RA##G*@LWKO|HyroiY`9<+B|X0^?o!`gYN(=!VqZY>ZwfOI!rj7o%H_Vjig9trgH<8Uo-Mgo& zqJhwjQP3&@Ov9p=s)sdB#(kO*>@^zG^1LZ4=#`?qsP?bGkg^vzEwTJJf=7o4_+2Uz z5|*GM;@$5eHTggERt$r&wF!OPkZ!p;pS5^2gdgHgj7ke^LCe;!OBf^kMm9eD;*u#( zuvQ~&PXs-%XsaW^e|I_xlVid{C@nHqRy!nq#e*LMbMgFk8x@Hyr0CT@_7&<}UzAVN*xV^+Uhp_bVB~DWu z=7c}e!BTzj#iI}@qY-&N3Ab%YW}=0y+vKuIOs1nDj7VbY_$ryx{5J~oT=5|MXHw?f zxH5rJx?ys~gN{e#7w}7!Bgk6JnqcD-Nb)5ja!IStCB~8fyKk=i6|yWvaW?F-LWriB z?Ddf4{OJB`(I=Mo`C^#h-RGvSc5bXH_uM6^{r~+&<>rOFN|Lsh`E2<*&-~~QozQipH()0IE z%oseH7AXhxkHKt#7_iG{0s7gi_CHA+t@UEv8(ftfnzxok1^Rnr5YfNgW-@)b8!u5P zBV%$jJB4r9VtpIA(!X6`j;qya*($IDe85bNlU$YAzWpLvUBF`}neDk!(%Tb9#VUs) z8pb$5nMX(8p>=QWZYJXH>0Wk(%~B4K@o+NmZt9D-yQZ1mKj8vgh*kK%yTgj^=@Sem zNS0#ip2p{YYg|^%^6S$N35T-|!Ypq8(L>Y9_{~_1lEJY=&CNgcTkb$omj}7w-;H2j z;_&q;bGpc+tC2GP8N*QF=H@3-;0=V&uLv>|juO-IWJ?RC+9^(w^4FBqNtp{9D;Cce zsne^EuOrdPrvZ*=VyPYFHTq@-VD{7jI)or{{?UO3pCxCP->KK%Wv=uzqMfrdWxQ553A@SZ2fh2d8^q>re5Mt z{XJ|8QN^-k#K)aba2_*DfoNg`_sm?tfhI2$n0p(JKm6Y|F}kas%q1)}yd19(HO2pn zx_9idEZovzr9q1Iy&Y8weGR%7?b7lVCU`c}Om ziWIeN$*v02_=N&+8ZW{pA5gVxpeb?Rtj&D7RbL@Nb`q4 z0EDVlcddkAqt%x4VP(w1gpd^v|GeN%e8<)3|H5TV^Lw?%!6u~23ca+jv`g9iY?}Sz1 z-qCC~cr_m{lf)_{Onc9sXaWY-V{%LgrLoyOQx-!bIBqWhr%D+rYk=r8F?)}qn#UoG zVL|E~uzSm3RV1tGqVj-dyySSjNB&70HB2jptcQcMQp|)gg~>`~sYt-`lA%-3Jyy|> z1E#V{Sb+0y|4zdHZsrS9xppF7Y=gs;5{EDN9iArC0-Z4l9!y;M77PnGY^ znfE3^s3DdEYo1+0{E50^l}*hdI(}hC{+&KK_lgpn$R{@+MyEtpJ)ROrL5jrwbL3!U zI*Va-O+=VQd7pr{p)ed}S$WteZk%u@VuWK?o}(#%?1?{6Q8pYMV3l18uw3AYro%jx z)K!>FXx=RNtZI9_`dxpy;iO0f6cg{OqBD?W*F^Ka#p=!o?d}Bwg)9)n(m&||Q9y6m zM3?o(`PaY*#&R@Jd&997*?s!yBcz#|?+=}>=@txh9uThL{>4ZOJ)fK77*!>>*NI1_ zQd#!VedDwX7dFFb;;5QenNrSc%iUwi_Q|o%jTk~T`;FX#4YM~2fmTtii6!MOuuqkT z%x-4woML6|0^&6Va>^he7!g7#vaKqcwrhszt)0-B&{;Yi$*YLK!(u|7H#v#YgvxDH zf-OWQxZ%<_N&qDk{rl=SK5L7Eg0^Nq8)6JdAwXD!fz13v79NJM`D$;hklj%CoReh| zbl$JP>->Bna+w|2cX>FsKr{FDqC76+teQbcTcpxfN5x^VjWbeZ>X|x}6bc}yIhX0n zs9DucD_du<$gTLKvuGcu+yiKr7%}eXcCzxD085xnOgoK;&yP8@_!WgdJL*i9WiOg? z*Dy>lnGz>1WEA?vg~YtVR&*vufKiQy+oi&6iAX6TLS(UC-tbKA3F)jXQFw9}(2lwQ zd<8NW{bJG6JeO7+3?c)OY70#W7vYe?sn%ANE?i8v`+=!5WVj>WL(#ZUv6i}8 zIdjAF3C8}R7{Q$e<&V9nu z&DbR6l;U#1BX@)GzIz<|6BSUATOABw;;f}gK}N^fQAL1n)o}v>wb$i`R zX42;d(l8v)4p9}E*b{&DBl`K-SCrCNJld(qdes!u9&G9a-+6_`Z*QT-9b`Xz_|$vP4-YK8y2~7TMWx#VZ@DJuz zjCFnTrm8a$lU`h0{Lq?Z(&nuIZABqfd32!Sc^e#Lx2YPZO?!*8 z;K9hS&avMnw%_f|&5lQPF&`z3OBuV(swmUNb`Hs2H(Bd&+W@^T1)hKqgJNc z^%U-JEtXdP%UeizH|ym2;y1j?LHd>6tE=H0cGv(G7;WCRyVFWj+84MO754U(jU>#2 z)KK?^I$h9S0MZxyjzFQiJ^Vfb^$jSe`m?>LwVKupsGh0As^!-ar=0tnSB4*|2+#;O z+_@xQsmmQ1X(3B~bMA*K;ipkmZ=|FwGR2mvTl znUL+92$J2(?Z*c4hZV@pdM6R}_Kq@uTKwLF{VC)Y^;jv%Z^blaCAS7KKE3Yp+&|tD zAXnWV_oH~Uy4~D$r59y+xp|A9y>(CJ=3hZkDicdKQsUk(H@CB-nhly{SC%=F>u2yk z_h2fA)NsrW*_o`&%t$?_X|u{I*LJN=7i*u%3~tJmrjAQ%WL7EJ#nHWG%)F zvht73Ah1m!6i8x?WAbH?Aqt_U^yr_H9Xx3<%OyrEL8re{ z`CMvgZ&%cp%H^(BD}|2VM`zcBZrvyO8NHgFhGXjCHMKn7aw3yh89%`c8TxrD2D+d~ zTe(j>ww1QfP$qI|Cn2p^f9%BlNRrafvGUq8L`yY_4&b>Rt5j=zM)QJdta6t(?f_l6 z9Wq=l38~9lJid8>M=s;CYWldgr}F2EQqCeK0w16k!u1@z!h~_sKqjLFJVXSwVl_mT z=Uh0ef+uKGG_y}sU~MpDoh%I%%7V;mUByX%L3zHrXrffB$2;0W?keb*@1{+dFVI5GgMn9n8-9k&QmkQpjZFt6bbRS#5sWRRH30RkC zb%exEgvQ=wQ0~woSMFaSM09BCR8OxyLKP4RDhHSCdd$1%vpMQtdhmpU`)+|dqp1v7N%tOf20=IEuk5jH>{dS*A2d>`;nzVisauvpz4|AsbrbC#=Gpevk0Sy_{M#lC25^+)`Gxy$r{Sk zJ+HaiHNHc|eHv5-V15hII@^Ij@)5CA2!TH}%Lq*XSqXK{w3}I{JHJYVQi*OKa$>$u zNoVBDN6b%DmIkWg*u&v`W#F;C62ZPfd)hbhj}ODH@5%L*o{@mE!Hqbb?iP|nmu2>M zbQ01qRn$n&Fi2L5JAse5%S^4AD4NT%y{_7ftCq5%7GRFgp2w4g;9FulXMc6hy~>qg z3nj_NLe}Rp*b0)}vDe_@()>bKgMT;yrf)yyXdi9%*57B*{Tcwb#i&fbHj-vSUHs9C zI;8(1LS@WmH3iR!)nHokf$X8C+GndeL!izifjLzH9WKlmcKCaH1>4M1psO_tC}{IM z5`VaB4+>o`AI2-^W??z7el3~*=At0N>xxH4 z3tosWL1JS1KrO?prBBO3<^O=|xHp|#pO>4MF*jXrs40xkm1Q%h(aj{(Pr&VS)|51P zo?2Tf6EJg@(g=XUmTMlGHFR$=kG{Q#^P=O7y);KJR+>KoR9zLHuX{; zhE~PasG|+EP1E{ip2hr>I<>#{*3EIOVc$y z@sC*pRdmA8Iub_N8u7~2o#r<8JB)8G-_u!_^t(Y-2PASOStcn&l5udv7Yz00xOsKO zsCODoc+FcfS}r!z`&>|dJ5z7f{qiz7$13^Pzk=vSQt2Ajv)Js*W@6nsE z+|RPl&`-C%5ek)Bf=Ow_APSL{rZr1NNHQa4C0k9L(ujp5c@ZW{%d{X%L$$JuhKQO> zp+;qCccpTYxoH)}Ev49eT&@Yl&2EI@-|2$BoZbDW+_pbYNlKJu*Wi!BL=v!aF__063m+NjB(>8fl|Q-MR+(yI%!YSt&9 z7I2xBTo{=&kLLW3%*rxycBhhA#d%)ez{xZ99ODsYSskY` z(IO8JSbFV7Tl7Rtr#k~vVJ$3w`WItyYYX1MsUA*^!y3}=Q!Fyd`sZjj+m0{Avm!8t zV%DIreGF(fBOs)%iR&&lB9>`dk^&o>|5og5$Uwt5(8u=+4b%BA@>L=U&%v(K;-0L59TbQw6toobO!@U`xJf>66L@GqfKUUa3E*_~eZw)>lt>^> zrK(1QX+HpSKb}*D*0LdZ{L=khiycQuO?-=b$3y*O{-Et=Nk-fVr@hO!4jj`0surXT z55HqI9EX~s4Y?JNL&XHW_@aKH;b1Xu<%f;1KW)#^yuKy@7@YF!0#3WKXj&lwD|4PPp9s#;D8!-Ei`sZ71&I6f<`gHOUa;v_c)&)51VHmX9Tbm3Ej8@~ zc;Ak&;LVU|A0yO+6SyQ8tx1G1%zbcBBaa@pf^9NO-#JjRsr3?k>72T9j&0M&;+nJz z8!`ryi?M2rj>Y9}iXmKIN%fYOrkDj`koh4se=kQEG@mm2L^($16HJ9%^eD>MP}b|y^6YzShlIT$|O zxAz-o;~v7xe9}9l#DSo3WCdme0(Ft_69Y9*pURd{V9IB@KpRt$#f%(=L=UP0Un-He zwqEkYlJq#A0hY!gdt^1uD=fWz4droXWdU~W)z7> zQ6R4LNT@AK#IoiXP`>3MB6mOzkj+Kk$K*VKuQ&?C_%CCv!s750>@vyFFt&CSJi8gu zQ61X0HFsMZ>SWK3gwu#rHFfoInE*VM*66icox<9&uFCa@K*nSx9f?JC>w2jZ7bQ~v z{GJMrxgzn!B4m$<+9R0~pT5FEUlJ7rY&t3`3#T@w{$(r2d)wfN`*X`N@*wZx)5E42 zI|-UqUqA3O%K%jrJ2)EfHuP3RMc^(2CB#$q-Li5{MGHzlt0Petbh9ea8qL%?rk%nk z&~Zs-P3N&zk?l%}<&9jLn;paG>`Syt8p6mn4O{>pd8y%0P07K&zG6Pit=Aj1(W zNceIzgr=3Qh;@=XwWDL6cyqBS?YGctzT%T@RZY|Hzk)|R=&?W4hMswE?}#&aWu1?O zJ27D=CCE4%2X-liUAyETKhcGH>M}(jR}__su;Q4WS>-+}bo%FwJJSnAw vrIU7< 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%0D<1{wwu{RL9B19GKiyQJk|GovFGJNbm`55# zaifmydgAduSmrclRALWN0;NoOUiW(!2uLQDa~03MF1%&|B4vG!&81vH<;)1y4x2b@ zNz?WK(tg93XfifrJvixbm=yl#SjsJTW_dk&sA<8^`O7kI9EU|S22`vpB`rD4yS|97 z&dc+6z0KRz;%kds$cE-<(QAB`bmVm_C54UtFy{3)ctJTF+yyAIVotygwlNR4x+Lm>LK9>iZy@9Ay@GtueV6j z80;nEYhW7s5aoU;sjIR#TpuHAWg+9~F6L}4yxv3dax6bm77qXF^~-{Ox82Y>Yq$Ay zN`%e>`=yMqe6YoEivX($D|uVrnE6lOpSJz={h8F+?6qaY3#^DyM%dtNNJ~K|g4YG; z(|U+|n5zL@jbfheMAvV~cGyag*sYZAcBR}b%T&jLw8Tw&goQ0EwL__G3)lB2Z|~|> zqumaRy~a42$41Ozz6`xVWEDBTFd7x$!NFA854GhAgXD!Xn$}=IU**ta1-&vTCYAFO z>4Gp}xu_y#64JHrk`AYC#c5qtOZx=*#--5S{ml?EPpkx#7(@0fVR?=0zTgFCxas1< z3Wf0HikwEf@@U0v1I6k{5^NaCdy7W#Jtf^<1}`J>zJwr=VC*DF zjF5iFYc-|HQfU+UTAq%dF+D#$W|I6+pVW3&^mp_s5+JokiPbECr3R=n5EdD`ZXxx+ z;tjoTN$Lu|(w<+!pb7;#^zI);CF7(iG<4ZKWh&Quc7y!o2&&3+QeUv+Z-n0A?wd{&d<~0O4a$suJbESm;0pReFT^Mk z;VTiP0Hct-xHA-f;f48dYj+<68h8g1Mq$KxC95uOwcsbp0Sp|G{*pn&*c#Kx9wQ49 zo8hQ#&6htNY@}1n&0$O$w`MI9!B0c)@xkN8{HB?t*_s?--vF#;X$xLm`~K45Nm}SH zXpDrus`cxc&&mx!-LQ>IU@=t_3A_f)8(-{^fVc)jPFB%&qBhg3eS@*e==X~^9a)`y zN_y0VW#o$D;8OhtctfGJl(|}Xz!q2585tp8irhJ5D9o9QG>WoMzp~7YyJ<317zOx) zWv9O#AnBFTQm?!S4I4K^Pd|WX-)saDe-OZili4XsF;k}im`p`r)7DFsWSU3rZ3TN? zRvJ_+Y8Lt^LowBze-DjknvOQ9VjS3A26L$KKIT`f>CgmQTILtF)y{g0QZ=n`R53^Y zz0-Fza{c?zZ@(|JH#;qBUAya%V-w#p*n6z5v@V8hq%!;zvY1H_VWmIj{-6j|&9R16 z?3erTB?;j4k@C-t?B^?J@DU=x)0FX*lOrMt6rfl=PV3-|k~EcNgl0RsoJ>vKc7FYy zcE()EX^!^v8z{{;Y;LUZn&s?^g6CxZZEl@wdc2SKKb^_m(GrcJdWpk{m zc5j`cR4pIuaz5a8z)~r+=PPd{?XuT^f4-#3EU{W{~5AY;r8Sv%5zL(V-2mSEm(-83Djh*JN{z+WV+ z%$Y0@&|L+EBGFC!IJB50xM=l-bUU`Lv4ArR*>LpAfjL4nHwJ?9l(`aodaX(oluj-r$O zl$0`(|5&NH#$C}@HIt%d5+TV_i8fy%NxoGt>V^SHfp(`x;I=-uYUSauZu@3ekJV7m z&s-zdeESA7LI&vTJte|Mz~A~7UA6*S-Irh`Qb*8lY^Pe>zwYYlr9rGZ{l+kZSaSvW z82LLtD?cT0$#%n^+M3160if?-1X8^^&p9h>lfzcszqrc&jR?(2L~_?8Xqx3x%koSb zC+A=V8RkosD2SeW`-xDc7Fo$*XurBq0Rka2Iax=zCZ>;2q{y^Ub(SFeut-e&Dc>`iS$8 zKL~JtJwRLgj*;+KsY7zEV#6Y8b=M_U*^{9$`%0wiD^tz4WH6Yu^_vSeD3l6LJz02#%=xwU#L= zsWeWZDz023L^pL(Nh6w}#Qxqus+mhD5RQVU{Q4&xlYP_%K)Zt=GoVIm8?^kf;1^H! z4t;OytOk`(=(@6kSQfsbCLQzep2BWn(rq3>A}k%Nz{_O8gT6qj?abC^EqkQWa>OMH+}n&h9$5s0sQ z&uuK+<;?_2XI7C3u9eh2_S-|8$!}-hZk`IL!c(!5B7F#vERwA0-c#pK#L=Iu#>Ve#}e$ES%Why7>iy^%@(k=f^<{LvIH^MW;8UnqQ`{?C=9 zC55qH!eUX9KfKh2qD5cL219FHR0G^6H&$9?Ov#da&@|@NOT`hL6YUN_KKLvEr}Co; zs*IO$I(&EQL

bo--M?5=BN$Q?@|UN^ZVf7!u$DsbeI37^70V*>U{w#zJnDOLzf@ z*cYONf)?wYHi*aPEZRQdM!sc*UaNe?i4w`dv#DA{ON0RZnW3*l90^gr(GN>yh89rY zG0Rx4^cvfW!+DLdESpyxAmk&laJZqpl*8;{Zrjoy7Hxh^>VS9o!2b4SnE-1FiV^OJ z>W>xGsXv`=$VlHN#jYsT%|Rdh?(4sX(VhOv!}!*D8dNGcwQGJFEgVxgMge^`NqHRO z6Lc*SP_l>xi~eA(xR_QBjSfzZHEwpE@_WK&C0TtC+Q^|?B{I*R!*-`X>*w%yLDLW7 z8jINx5Is?+!1ZkbM47TUYxAo$T+r!!Wjt1@>dK2(l*B>;HD6~+6+T`Mie#p(yAJ72 zgL|MgfZN+^wkr$SW%JqelNNZp`eJKpe^-=a^`EtavT{dTb+J;0speXltH6hS+V}$p z6|+Q(`fV{Me@L;6TavixvzXHExppYLJIyF{mnTyCFX_buC#nr>d7chyx+^wrudVLw zSpLu?hp%PR@4F5JF~Q;UbKgv)#%QNm?XWBzr;ug^rPXVBT>49I%EFCyXMcM3nl&c_ zQ{Z5}ZPlE_cO$gB#2<>woPZi0oPFdYZyrP!i?Z5oHO@rSn&4+(T}DN~)kZt2n};qQ z#(l~A+8A+Wo|)gTD~ULoLG7|T)pffvYvI?ASJ9#D1)Hs*UgzlSIyzKnj-*@N!kyL0 z%q?0b;c|*Hxp-TnI3f&3VGiQ}ShrM~vkW_k$0#QL>UV4DWp>N}eC;~o$K>|cuEp3} zkvZ$Q9CV2pJk$k3h9h%Diu>^qBCwh%l1B<=R2|A|m^C*W&@iKv3FXV3sWjDCf<{AG zi)Io!8&Fk(ZI}J2-WVb$rO9)-P|522-LWL=HzGx$izz`+d*VsV!WxnRRlr zpN3A~Nf6lBo6}>jONF#Z0YCDH=5Hj2ZN7Xq489Unq{9{_l}yf6V!cG_KW;flPXLNm z;eO=0=6W7+`18>r^dzprt}ry7pY`-vFmT*S6;32*b;<4_^Ho8ZU1tu}ob_b?$FzR? zd|E+q)TOkNhu|K1N#8;>qu*+QVzicwi_0QKhHP@IX?jL!;e)vfXq~zFYek*-og5Fv zYbb>0fugb>!pXb?qDV$04@xxmvPGs@KZ-~o2dODw*KDH1Xp@Y6bcwtMCH9N=iWit{98Dsc(%aa$UGd6> zzH6SnU-V4-rQ@a=+><+-#-~w4S`G6;J0AZEvSzKlVC_H`+x*8TN14pi&v9KWTO{zc zc!6@%dYXf!2KH0+-{h!oVCzDc-46F!UzQ zoS|&=l|HKVo4@HDysl!d5so|*&5hz&Wx$P!a$jYjtiU6-c^`$r&|Q&V0$2o~l9G#S z*0nl+N6@pop^L$A^b0W}14|SHHr;EWHP5S7t?V-)Viv(Q`yGwqL-^RitfvGO`$z0O?vu{WF)y8~QUM)hvGM5w4@@$&L5|TKv@>s%DxU9+ZEfn!^ ztD7p7d&_0ka-<-|LAA)(Cq-nv(Mx7E;K7Q9P&pH9m4-TfvAdhb_VFh*_9`3{7Ashu zY;Y(~(V{8iZl&;bBl2&xWnqm+tavaDpP}x2iB4&4vtj%m;ON^gJ>e4o*N}qqwUG8D zs5X~86?G}gjDe|rlLD7OyDW%_XmVu2cCOikX}x|{liq#u@B35HL6}v8P;Qyf1mhju zxbwvu5;cc*`g(g~8uP>E8&8t}43q|GyZJJGZn?w5c8D#nlA+^(xsyf7aNe<0ic}#M ztbd5X(-pf(FHl+FS@yHAC?l}T9)2~uu#}#k2Qv{%n-@P#AQNyI6zHJ?9}@*6hVt|? zfAyrQeA=H!on{xInjI6w0HBedjD-TRj=C_>t>bGhns6m)kIJ+%dRbDbF|$6_5}m9Q zb2I%vZA{*4T03~2F2b|3Dd@>gyzNfTspHrhk7iEOhVj(4qjF_Em6S{su58NGZ~O$3 z-m-NTJKoamR7?{EJ;|Ax4UCj2%tGKAj%ED?H#K#$>T_Kk9zT2DlMj`yPAD{&W;IQz zK`AIxm$%_3MziqE@oB}(vr2ohC!CZLlUFYxD=}|yp|u;QuBf0SRoX1p~h~H z(eRZ+-8U}=0=pmLppJ_|W0d8wWfEp>6%7g%#A(1Mkh95}5t<&k9Dk3hDyio)6M8Ny z;8JVW(Ie9=b2QuEM&q+|F(U*~YsAcaQZ#7ZYz&24QdFehY)EV;dvv>)aiAR}qNVib z>P6-~oipZA45_Y$Z|csvO`0hrSJ!UWn`Ss#n-!mSitBQCW{v#NCwyRU5HG4%vrRZ6 z*q++qW+8@q^yi9>$(nCoetejDD48<~eIuaTwV+-p$}zD0jcCy**B%9?Yn7v7o8+Ln zr_Iu`XXI%PiQO!#w91v`@)6|E8ev2(sZ)Z=;xq(3*aO$ARHNYye~i@$A!}E$>R}kq zm6trEdZ{Cim*48v012wR-`5ZKlh2!V14&_nX3J;Ua*>bH2WnHcDRFnnc_};rX~bi~ zYys@(;g-q@u2syx6yL|0^KwEd@JmAHrDn?D?T>|jT$zF!AAo_T7|)C%^beU~=vVV3 zgTQ+Myg@tS9)e(qSj5PX#H+-=kkA?^*W#cYq0yk~05J$)s7YXM1=9T&LQx2<#V{}j zoT(;&r)<1z$an*Aj34g3gLM2&A*y7?c*gWQ@*_VnUT1Q_xFf5Be>#zZv;c1;&rBQc ztE|EruGwz}>V>Ka&e8qi_kM#DGSYNIh{Z$%;2PKOuB7yHf|wY&yb_=iM}HAtJVdziEAsS$ht4vk1x7kG~XwV1Nlf*q>y;8^H#M1m(#1YzG}%`Q-&T5x5Tc9pd>6 z{tC1TB0pkObq4Zlp|b->mRrsVX&(lXn-*G$Jj4l)36O+bY9w)CQZdJS{ID2de*-c@ z#`W?G9XSZ-fTMc@65)VDr-hd4)8w?{t86E?5|H?PR+a1yHtqz9oX}Sl{DvEbi^zZY zi`}ip)BQP-)W_~l`emB{JVHFNUrQJmF<%inV^|wB?ypxmbNnLppyKv7LssxlJJ^;5HRpQcqbH!F$F2T>h^Y^JHbb)3aCw7 zx3>y(FP|&?+AQDe&@DnBS`xlfM0fYMjdK}_u;MEaV|zf}$NXS>>q2!Xuk?~e`hd7l zAE3Ji7B*^W+l9Q)G$XLTbIcBJ{9_;KK<2BMq+%wSe-zWK(WM)->2HYr8x0~f&b61i zS4+fg4crdmi`*Wc)hJ4uX0ao^y~i|Oi9lR9RyijqBS`3oX)q+69+W#w_0$8s9SO6^Gv%g9oN59F+cR}@rfP-k&+M;#tEI+kc5Pgrp+|TgfP56z&Iph~>lrB-yE=~hBv>g0>c1(v|$a#?P4@~G7*_g1`iy?-P zPJYc{7f6euZ>ZwiCguZsm#i&wX3Tx0lAZ(ecH@Z!uyu1 z>+VgDcWdwF?yGmFbag#MS<6Xt-W9gBrQa%{TqxZhcHd;hHn7RvPg*Ua^&x+{g)TVS z17Mk{U&N#%^AlPgIg+7ZwjICa5xa6E;%%6K%m)Czhgn}mmFUE&Uq$7r7LLzWunMEJM24o+? zyl(-c*e8ey@G2BhjfcNIh6@~8?8_KOHa}GM^D~2=|L#`fIc`(#n{clSl8x9dJWCT% ztm`ax*%N`6<|&4Qv>D@g-im)r`)aZ7`fQW4F4XnVt)$Y2dC2-s(%ZXS1blr-sx-_)M;rP_NY$-3r2Q9Wz1>BP>11og*F+h$8e4-iAus=i3TEw8=tO^Z5 zxCNeeH!&(x#S9~A6-MPp`sD|}^tr_%Jc*`IyZ()o(63&I9Krpi_E;|OQe`BIXGA+A zYvF6ZRy)YMiag6}Zv2{#Br~7P4*Ttv)6;L(e^gOux+fK9QLoeykJ?V3ae}H;Q zYNz!%g5fhfim7|g(}Dv ze66(%4r4KH9439v5NBwV<5<#9Ro;l%ekvQ*nrbJTwLJpz>Gey~Zj4`weM>}}VQ>;3 z`Wqtg&UjRQe0O4NupK%~VMt^=v1J95$9OZ?xK5zLCZUEqbI5tr%UN+yJ5M@?9(97h zAZi7+><^?PfKPy4L=dAok!JE;4rPDCm|Fxh^vZFEfv~53HII1*Vg^QajN#U+Y(@4L z>ck(t&rwA7tuM#z_FTLdK+>I#A(JI+`AeB|IuqC0O_g&1>kI&TK`<|gjhKu@u{I6d zjCgIapi3R4;G1OSk#TLhqAWx?{8c>+tTB##EJcn&lSrn4;mFW1Zd2RLHD5RRGlX9Z?jW(q4>fpEF z$BTyaj&09;^|UpDHXJ_MD{FpqST~wk zV{GsZw}`N1!LDa`-zut*NDtHgfQTJxrcej)#E)dDcfd9;jHcAw3-N$lO#2Nj3;#H5 zQ2Qy26WiG9s@Pv`mOT!h)1QmKt9o4z@(ldLz#CO<*P)x|!tZM-9>0|J<>O@i5lG-HmOnhj9@aWk43dBnSm|YS) zAADW2X|O&u29S4zlb$ul8d-ErMSgY%J#_t#J<2zye$}`P!7Hm@;}W1X?wV!+=3xid zON6!+>`o^ZMeuP%tU8!OBs2q)4s#t2KW}s> z+f;t(oGoakfH8Gq#rn$_#g4Mj6ww~&wzV|UFDqG~2c=Syd`UaB6@X~@nwB4T6Ce!I zZQpGBrcwN+me4SRXuaul1Q9(<6cA<~=pR3dJi5K=F~-?Bgu$ZFEZaqeD{odVI+Ma~ zz7N=QV51o)53}xgvKQ>_GNj)2*jV5ihnZ5lcwA&QmP22A;jiuU&AJTA=hq!B|1PYl8>E2p=rWk6*BjpI< zD|-6`U(yT36vHzl3%CW}@)&{6sdKo|*{cTs2a(PzA@^AAn0(L}!?SbxjR}tR*z1Ns zuzG8kba@=lSz5=Y+?Gi&*aPjW2IOOT7tG83;-++JiDHzm()=WG9m*1bcM1pzil7#! zBp{_~o^7-Hf}=tbElkPew^nj=Yh$GtOMc}?zQ1SMk+VooQlo7WPwC;TbRKTXyztCH z@(rcIcxX$3?nldU7RiM)Nypxja+LvKW@sBt;kKtc`BFRWK|ZFgRx+uvoYOt-oE>O zLdTKiwzWMso$<@gv;4HQ9@jR$?+<~0bj_TYr(?@l!KW7%vu3daDHM_xb%G3r6BGK| z9gvS%(JX6x?GJqt^3W)I@D-=1@9!8AqH1*Q@4yR840bOP8f!>2yEP@5QLF%)Tmah8 zFg-OB(FE@Y*~f`CeF;rE(ZE}#ml#*1P-s9k9a)YqCRCD&O17kkYcvc%@&*|Fgm!$y z*j8K&0_0>SB{O%6GjT3BR6wXH)G7NDSQtX<2hnZ-<1RpAe@DF)b(#vAr|vTaGfIv<|L?aj9`We!@} zdw3x_hljsY;~Teo47X$sp={$L#REyCY~1L$;gS6D=xxGF*h6YS=(ym-F33xK_YwaC zz`EcK*{l6dw-H<9Yh35Jwh{WeILi4!7s;ywnW$^r=DGtm!&vnZngi46^+LnwB z30vIdxU&)VxtUKNZT^F6c6z2)D{&%e_UM(vcj@WF=wh0Rv-c+XqWg}AYI8-AJ z^%Ac)>6MfRs8hRh(jzM!!kKQTI2Rqdk@LuLbt6QML~0V#xW#uBv^$SS@yv&4pvN(- zV{O=zf0>AFYvmnfy_ScJN0WMXMfbryW;9JTE0vvOy^x0*z*5RvjkzN3Hb~3p2_^*Q zIFIA{z;mOFhdtI>@#Fq)?MmWiql*8WmdW95t~6N671B>?sFY1Wl;S9;MaGTL$l}9| z0w#vM6(j46xg!t7+8ty8j3=yr6mtr;o(Zb9VDpsPvHQo5NRC;1tH~1Tk3bkj+5-uS zwuJSX9AW_r$Hb0V>72OfoNzc)+NWjff>5Yh-}&(bMeOJX#SvRkj#5J61#HgE7?UzF z1i%viRih01ziPCT1ly zIRZIOIkY);IfQtwaLBR!qS?X+h)Z}Q_kuIQL|GfBS_Chgr;*^<)(3!D>xa~cuf(r} zuO)P7or{JCIZrP3t{$On(CfihLu&oBPbBeN@mz76@tX+1?Wpa;^$J^8YJXhVQzA0= zTt=bn3yBGB_`W@kIE}CyP}|Yg1GECIL~2}M&{YXlH(bN0t~Q5{?--91j*yNFJTu$I zdNiyWY|*f{Yu6Y$R{v z7}jluibz#(FQZ5e%?%U(fl!u_7Oy%LKV3$EfQjk5h)$e@(I$l-s14(}9d88M0X8%6 zGsrfh+#PJnlxG+;j<4pZIhdR>tRSc3rbl4hEz0CsF{2v@mFP+feKpEtBno9#LM)Dy z3Pn_cDUC@lQ1i>O41|u4=7c!L)5yt!h#a_g8c1i8RpU$@)3M8@24$!LtE<=%;GRI> zKo_X}jr4T;Qp!&wv@G*;3X@fj%_1FCj;*HZ&)2utSL|H$<%MQ1W;o-V>8YlXXDD$H z>)*70fO@A*d)R!1wTo64?3;{?Zau5-;IWYAy)$l*c`n`d7pZUXUI|;LTUVE_8!kFZ zE-ALLR_1F=!(b}k6DI0{nIuF+ol5OArc;v^PvE)a8B}pHbhOduaR>C1i(@E5S+2-w zVuNr8BZ<*6Rr1Wyra`T~=Q|}I!^5oMCD0`CBTK9=Dk@>Y3OhfGOGFZZD>4%{I*#@< z9$B;&)2=#c&Eun`pS3eu^7ADdQ&vg4=QBiNR%>)^$LS*fJX&5RTW_{}HH4ToEONtz zdd4cA)PvH%_Mg1CdD5@VN2Q*;#OU236Vuql1enZwwYch8{S14KrtIzVtbu84+@HNw zuH3&S{@CJg@OJzAz7uyAzsvq30@r)Xul`Tl;QxOY-G5Vvnb`g}hKzubft}?a8KfLea_k|A2zccCOU_`C!ISuVwc~L4wEKc_W17cr%6~NisENOj<*D$5<_) zsU$*YeI3h(>WYZc|v7Oh#V;s7ffVKCElmfr7*kJr9RU* zQq{|uMt$VQyyDU$)rSD+7%8g8x`y8TT&D_AcUUwo8Exl8lHD`K3+b2ghoAld*AW$s z7c9C&o6?x{c*vweP>q}zp(z)U9zmng9zg@q9`z{%t@@2epzhpT+~Cvg{V)tn3KG;& z%mDvLT=56N2v#$?t(r0LWK0-l$6_qK|ihx;f(H688i9tYy3 zoY06HW8XTcm-#@ir;QSQcvY&)U9mUIK8l@g2Yqx{+`XN9apag?-Vzk6Opw0)gn=`Y z%W^hy-r?S^{fk=%zyeJ(3;$0eZ-wxSX`?%7sQ1OG4Y}4>cHjCYxg#J=yu$GcpSl#> z@I^j^Ao&!u{L*9#dC_d4@?R7mh+uDu2#fWg0a7|5M_do`Ed;1n1r&2-ER&i&)+`2h z1aA}@$m_0plE?Ix`T)(pXaPlKnOllW9MlMriTQAS#(sjxq?zBpatnDesYrG=jO{i8a;*^9@M=K%(?|wR|^~^oSKfEzi9@uH7%O0d@un9xfe5x#~&Cu$&LWd%CP*!R!<9xW3WyavP zR{X+38&La6{QxxB9&iWH0Ny=L0@68B>c*MuVJBWH@y4V(P`c zJ(>QZ-J#B2{k`LzZV*t^JtwiV3JE4q0&wprV5x@!t&HSw+__&n|0j(Efgum5uCVTFBv=hAsH0NpU?_qi<>26FNi26RmwFIy##IgrrkPNR ztl(VFj(*lrvdHZIqtL`()$dGGX|$J|?;(<<1oaLxVsFg@t~e}f=`<~vPT=8?>txh2 zV$MENVha3gAb0NQ-D3V5ML$xU(jemyQI+zYaa9zvd;*abnh0hfXqDMdf@e_RVE~nC z?FWFw9)teO4p5+n1-iywH?uD?TnWlqCt;@q@Irdmqk!|1LmW^Np}1^=+w2=RtIs@Nk`qZ)m9JD(_V@pV&~???9rv0 z(mLAcJLA4PG(P9f>FetCWbd^qKpxXma(MkYC%5bd%MC*cykAyx$<6dajp1$MWkCse z?f5ELg@qi0RIG)H4L9m~J30OgTj67AK|#~_7enaYg|nwe^myDH9`58)@vX&6gY}3nSe2H}HbVAs_}VR_qeo>d4i05> z^4`gzowqY5C5)Ch>|V8vtbXH7LT=c0Iwnab^Ea53Y{hd~?2RR2=5qYo;r`9y*TP4> zCq(Y{rsSCBmG(k|^~&S6C}{d`7N{);wS)z#fDADcW$5pDa)SbF(vtpaBw3)byW_;f z&Oc+!3B!P2_e|jBU>q>%vqyTSM4`We8@8+^DOs=A``4?kypIf78SiVwqPL8RzSA!C z!K-rKhE*+}qE`b-LBm!k>W}(TCCnmhm@#J>rK;hfO>-%8c$Aa!WR73)gM;a|Uvliu2Ttc{igcrnL3TeD#&jY~Su9+ZbA73G`sh`D$pJ z$(zgeT`T_UtNJ&dH0k=c-#YfGQcpG^s&t1CQy{3jdMKp@R&ZHj>D< z0?vH?GYwp!k&W@y;oA$%e%YIYgOrCeSB_NbV{hNHcG6SU$^XZC61d9IFa zx6OjZorndrq~&esW9V>^);~@2vwPEFFhpr_^XJ!Em!=lKT7AIo z&3&HxFR53}Uu2h~kOF*FPRM2Cd+XI%o{bKz`jZsa)*Kd(sbIe8N@H5q!_7HS4Iisr z2GdrC)rCfbY4=C}0Uqya7Q6t4@7X3s7~@Gne|uiV)$4R= zY{zJ_!TF&6?bj$Ojd?+6o9qXctcGx4)DcVUz*O2ETC&Bq8?aY7Y|%(0hY8iAmp_2Rn&O5(i;8TIinFI^fIN$y90r34A*uz&XitprU`+Cw zpBU*J8=JwB4R6N5xc!^CKlkQmJYi4P_%|jhwu?|N(`$$br|r;P9z9yNMvC-ih-hjo z-5Su~D9fD&2-zxLKQjQf3xwmwh&5^~$N)F)RE8lZ05VLN-GQtTvuks&Y|jXJtRbp( zE4*sP2c{?O0+T~+)W6*rEyfU^l#Ph^bE;BQ1kRWXrwb!uIttIQo`b>R z$Xn3hD9!D8Xsn@sXskSli@||*EDLQsWm%n8U3aNboHX3;H6?m;WNxw;-KsmDkr zQau%TeI!)f-1BU5hkMFI!0>ioRVSxTBUg3T{rSmZJx1Od?;SMI(KOnGxwDC{;|!vY zpjsdH7~b9X$TNGlz+qGDyz9K{>aCT<{@E%2oLmF7J#l=;ZBAW{jXHIWGhRJKOcoq; zZ!XZFp*=!RR0FJ@D^?-)Oz%=|tj2gCr{;KiY?FN^XS022Y;&o`@#J$m1!L(OZS zN=GiR?!kS@2c2?)f zf)d~;L93_^ej1+6zF=ZDE%{;tg`LCm1!4;{k803QANQmM_+eoI$t+_ z>yq=Xwx%<1nO!WhXqbX5vUd9r7K~EeJ~AXl*U5OUmOjmuE{l!MojwhuXfyQ`{T_~3 z>wA`wFEo=Y?K^f_-Xrs3u90oT!7)W|_G4r!M=iDW0D`5{E^3|IY%^%w*y7r3I z(QMncyZVk--At*0J*N&8t&N;kW80)|E>||`Yrh>^zqnamQPTFZq1TLcZlcC`+e**l z{teqk{6wQsN!xaubb`HOP&E*v^a&H)rx>vShujI7KFU+dbz}kZX*(`Ih*`F&{@Jt{ z_v;IG7|9j}{reyJcqXi$)F-+)>wgeQ7wty-Bph=T)KuIt=1$*nSWZ45;cD;0Dfh{N z^@I>ZZi%Q6^K3L%AS$}3ol;!b-Ax^L_b_o!5$xdpU(N0TG3r$R`$BnPYd^%a}A*xhHCq&hq}VVBU}Un zTyUS>^d*cIi9I!9}}v5tT~panN3C&d3C+*9A557Ekn!ZdhpuH`r1mB?5-&W zyrEF89TJYz7G0WlL7tbCs~CBzY;t5Ev<5JYwUG}61Ci}*IuwG5$jj+6)e*2h5 z6Bis>sC9BOhNHi04tn)jTtoUzc1MAvFF_5#E(kmF_Ps7W(~OpBNk9I`J7NzFxUN>6 z_B@md(oyBv7auF$Avjxnlbo?(cYvy7&A!c^506JT_RKC9HD z1GNacOV%=dObW}drvvluWtYvjYgxYJlU4BMDrJ>j=h?Pyv2EhYLC3n2hFYJN-zTgW zg@SD5yP_{oly1@{QUlhQL(yreQ=XMqh395AV){)RHO9+}s||?b+d744E((qJ9Vx_~ zmv%Y=a%8%ltuQhXWcSHHu2Vy4IqFtqIsEXO8&_lo8pCQ=U%p5pzVpks=&$JZ>pu84 zdU}3?cBp%A<+Ra<%Cc+c97jbu&2caIUcXpnopqMlJvR1wno^NC=6BCc{$-+-LJE>a zx@~GK3x0qYGEPAWfRbc_xO6mwD_hGh||<0_K|dgBW-NZU)mqMAEQ~YuCMP|WxYF@) z0$<-)PjQB&B+2CQ`pS>DXtiIfcQMv2o0gDX!ST`#FGK$d_uZz@k6T1yTL zNELzi2s2(u&r1a3D}{H=W~R>iB5@x!X`ZW?B_dRQ*OA)tc>MLS{}U84!5Qxckl5;6 z>4E=yzX}2Q)~|v>5vc#suQG15$0In__xmcE&9|}!(_iV<0@w`a@PU&x_c29E^X!26 zr|P@ks`WTIF>sjGe8N04`m}6Dc4J{M5Axw9B;=Wb1w=2c6GBQ;Tw} zR101=;5Z;GYv8E+_F}lmHs;&*ytVpw?T_!cUl)<66JgzA?aXD(W2F%o4xx{dqL z6>&#WfgzJXviQrmO2;CIZ1)uht2o&Xoc6OhPL0&@!V7oDp^Wxk;bvV+hMKp;bu}N2 zALk0AeUrwI*G5N@istz&a$}xxsv)+xK+@(q7P^xozQMe6C4Dkz)Q;;M=7x0N&==F2xRMe$o(ATKTLk&~bD^IGy-`#|vYTv~nCF|;@`ThsVxq~l^;-N>xm28Z%yng5RB z)s3+s!IxtkPW7On`ItxjpaSzS+l66|l%6nwOQYu|&mkFI$aKy06Li2F%AbedLqhWa2TEo&w$l;>>xqE0Q}(pt+G$f=tnAIU?Qg7We3mSJU}v)H6e! zT`ajCwM$}ymC~w9%}~;a@r2(^gBku?*D;&-`QJqi4%W^1mEo5+PEN4xK)~@>y&TXU? z-<~Ot6EOz2$KMT~vjZ&YxmA_ZrTAXjB?g-2eyQ%^oC5m92F!QH*wVQxSY>tOiO#z= z-WrXVcz{A^aci5CsO()aKvwroL)U|kIz);hCf2SflC6-N>>QSpIpQUoJ)WDi<5XMO zH#&Z241aRt_xFwA_dzBUiuzxJOk+z2JYv^6aD!3MeB;vg#wYE*8aFUWa%|MDhd0D7 zWL)4Z-F$rV-c-glbLrXG5bLp1X!J_KWWBD^E|h&1A1PdsS%c-caSo^6z8nF^W|CB9@tSD+v-S?G$r48F zeVS(iRXSb+*c_r2IXzGTN9H6LomxY*!tqIgT0tURncF>42*Twx8!W>|PUtWO@Ml}xBQP8io{VJ#aTw14STC`Pk?2Vn05`z6(VU*-RB%@zj|B)( zYhE(YxHEmHo5TuCJ1Ql&|GA@&=p|V{m6)z213<*I;^i2gR3=>(k62{iRHtEtUmNO^uXtz5<4i0^q|BZvM&kixAj6KX=io>pssF_5-CC)Ghu zGJFHMlvH93Ktu={WSLIB--V43Y}?CErH7dxVtlT&!1x@S%=ldB2*bVfLok6WMym|? z{rXJ(XDf~Z#@-n@U~p#*bf(_Wr-^pqKWLbk2t7v|R?KR4_r!mUaF2|5>h)aZ)xpp- zm299_uF1hyCIy9}f!bklIuGz+aoDE@IhnjKfo;!E)CNa^f_5KdH$LfbiRUrJe<^&S z;Oh8-%SYb}o9wUs)0ur28;3?4>n_@a#LdBJbw7KN(-*dVprv!n}eryA&t6c%bL!xEo@?(Lm8 zRlF=f^$`~XVp3Q>Hk_(R3e4!ek6W0C^__{2@h!Qx439_b#}ZcUY)xBy=D%Tea0Dw9mAmg7l>qc>hRLN?~0` zWkxtp?#rrdA`e7@jh{J3GAtLp zfp?Y_kFG4fA6T}mXdF#hYfJ8VvRX;=47HjeD)t-uDEX7i(Z6jUp+9vNp>-Y`g*s>?yv{a zwk?q@kv4?-I8scXe#c>vOr`w}>anawr!p>F-KSq88uqflewh6cgII~6)c%|T_r)o7 zX72`deisA1X3j3rsy&%Kea3pY&73=in-=;X1RXSLqaWb~sXE$%CPT@kLR|5kvT_g+ znnU(NDCJx(XU5T-uAQVe;SvN-`>s%LUa6?U@jEW67Cz?1Pc&Gh1g#isb_+Au+zE{; zj}UU*1IaF>^%glSt1K*cJO#e&V{K}FsRKcH8bcm^LI-rqurc1J^6BJ}oZswX$q z8Skf)0>dwRSo0-huOO`Rn0B?_8nt3;Vq@6Z6P&onKA|4h&)PJKLO}RqVwgs=ZU&Ux zJieVzcX1-kCRx|2njYy*JcMcq<_JCl1VtD+rj@=i2Zf5M1>Ink66BxaByZan%W(lS zGw|NpM*j2;32!lhFy3zU9rr2yZP}A4LdSNUysGQ%v0IV8ntt6q)_B0}UpJs#*A^eZc)u5uYn z4c~h=H~j~F(Y+eNOy2y9c>h~_lLpTeuf1p+=d3tEUdFV^XH4#ax>>1|3yj+IdfXJ0 zCidiO;S7cvwdqzQz39umDq)5@(uQm`WrO>G30~~C?M@H4spMm0=wf+0)I8Z9D(UA} zJK9DYA2c5QbWToM{O~)vE`e4Ci0nJS8I(~Lw*$CD?^rQ`uUw_D^fWyuyy{k}%~4^X zpo8T-;hyGb$>K(tB_WU&eR*i(>}139@Y)6qkDRjZLPo3=lG!!)1${&@H8CYByytx> zBg@I&=F=L0(Vz~F*AoI9!)8gg2+>lP9Gx|@`2I=zK133C9%y)mvz5!0aJ@h4{gXna zp<`v;Ma8Zkb6mLP4_3;tZ(vb=V=1&lx~ppE#Ec%+*~&=G*%{qAZM)wJ9dOJo@7?&4 zXkM%77`I9tW1B0~i@haoY-YZgwwOP&lAf=1{vouDYp1}9l}5C1NTPk zYFrPG%YU+SlSLz~CJSG=ofLbNu=e1~+RzdjgSfVbk(so2nqNef6JptfWuM6q4@~f@ zwwPbfOdx|~#^VZGqQD!VwjAw|_wuw269}H#(cjs#pFG`tKPw-C0_(eD$y+-jOtdt= zm?|v-8H2}=F+Vm($jDP%FgOPS8Gt3&+BwS#O_fy&0qpRyLdI|{h?a{o;jEpS7m1+n zb=m;u<$y!sh2-T}WGHBglZz9L8-U{E=WbL@WVK3vWe(g#e#P$PThXid#1T zCR#cGWg>|HkOaX%P;neY5(ciRC6isyV6dmBC&*I*L?qdQp(qpz41s}RFmW1%xEs}(jG>4- zy9s|`@{NxQ!3{^Ub0OOiodH{XF<7EISyo7BE2Hn9uaY^re9y?)4fI(`5RT{sreIva zP!I(Coii<=3=I{u77=e}Lsh|$334>4P~s3NaTvk?f}%+UgurNm$$|32+Dk3;!(6uW5fp zhIUWg*^P{G#u2{ph2x+Yn3N4f9D|U+i%a4ONO6n=K~mfXj(`y0P$(8Jf&0eyr?mgU z*UcSkPr#AC;q;|8env~5;QDLqHy9o5oG@fLjEjq-9S*bAFu^W(8yWDATR+5- zp+(}h+6a;KCtnb9pJhEieVG zPjn~Y2%pWO9RV+=g5ENV5Gfb}f{;YOBtIAVKdAn)7&BJlTT(XW-^i{}6N z>yLW)&-4Dy@!w3oL-BV4|HAcmQ2I{uFI?ZD_&b4r;rcr$eW&>suJ2I%oxs0v{T-CP z)BF`&EI&rGv;|;UAy3*^^>@SNzjk!~Wz(J1x20jk*1HAJ|2EYJgF_4;It7Joo-N>J zpl(6uVvFYSXel^^F`Vf*kCK}3PR9NB>GV~ZI2w4A6yHWRDH`PXsSy`Lr5vo3VWO z)z_kT)@pT+oQh19Ejd%ismguVZh$sN`*sFh`a9u&atWwHz!C8T9Sq6IO-2T+OmuX2 za&`m2!8#-Y-VR3_1^}QiIl130^sB3w%fL}mDhL&*vMTh1s?-TdWkm_(3CR=6N+(oQ zRS`;1+Pet|q#_iq3{i$FAyrl3l1eB^MTisvrmCn6K}tZCROKwe>drPq035PabM(H| z3>Xvv)*}+hwD_&U>Vfs`ya=>EU+0BQ^awU!V{<4#0syuAG2?P}0E?xgKcX6}aeJ5M zu3eE006hyP71+{wwT%&LS0@NB^I_gx-fBm4j&a%jDzIk(_4Wlw`OsJ-i%o>EiVCpG zChq)+$AM~x{4R(sIu zp%{gnEEEopIY7plg}Nz4FkAb}zBU&gk&_)SkD(ItRO^RSVdC_eyiDilw$Z)H783Z4 c5@|zZ5}86G*s!rcp;BxtA|fZWRoPhn4{W64dH?_b literal 0 HcmV?d00001 diff --git a/libraries/RemoteSensor/docs/hardware setup.jpg b/libraries/RemoteSensor/docs/hardware setup.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bea017e4c0bc5bcac747f08726b9ffffbc64b63d GIT binary patch literal 132303 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%0AdUzN1-(er_@4 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%0D?wKxCk~EpKvx~IB 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�Qxg%Uw&-*G}cIx)@OT*fb zBYk)Nr(#sSJqN*m8X1gV*+;cJu2+>abOlso-#?OgwW^^LT8_>@#6o<+3l3+naR?0e zo$=Ap7t87mI=2P*LT&M*XWNQTn#`fv)>Z=Zm7YXiNQQZ6b;Cxby&HofuyVL?*W^Ld z5Nk^ko~%^pd+D4#BY^;x#$%0peGVj1wY;kmkM!izloi3}bU%$~um&gg@*x5+{0m3T7vs{J(4iFH|0x6VL*lot zqtb*n`@t{GG3yzLRk;s0V)$~HC4nU2n{Lll={o{&P^PsMB(MHPFe$?4z(^TIh&I)_ zy;0`;C9SMv%_l*>dWQ0x>p;OY43@Q-2#m4w<0NBai*v8PO>BB6v8~>w=>3?i9~1UD z4VGf>+*U#aVv#PlhX@;K9{BOM+?%lBw0Y8j1^c>2l$7)7aA1p6=>r=&8A*Wq1WCw=QH~_Nj71d46B|eA)6=AQe(*?9lt$Bb+a;2Mf|G^`tsQmG2e?u_+<3rMTCoe zSzbk`Y^BbFby=9Ym5r$PgEe8^8ZX9t;PWqbLnBO&DLq<@A4@z0bU&&bs7&e^Ok*tM zUO5*;x$-t^gac(#7a{5I!L(PgxTLm*ZCcJqCjk(zlQ*BH$l(s`6o|sV=4#;R!XJseLunjXyYi>(&{ORM zC_NuG+h%@4Lc@jAKh9tCjc}4%HHI~>bhTQ65&enxwmT-M90YPLnZBNa-cYbRA%Bo? z)^`g7MZ83Yd~>^%K0p7k8Gocev!T?E8g!ZTS(o3 z+fJ&~&-C>?=S22?X+}qOJ2uX|XC<})(u>RG*LXwo70oLQwg~kI+rUopxt+aw$MFVa zK}4E8hL2w&O3%PDrVESR{=jsZz7F)5l94E~>Co$Vz(A|i!@8rrB0*I_S5EDEQElb;4s6wMVm z+I<}JlSa?fH+j5;l{m9!KdbD=Ia`0){fS>&KGiV^SpY6k^p{cto0lSv(rysC`B(3e zPg%38KGwZzoRs5TDwG-j_ zk0ByYS=9Rz)!*~YXEu}iAEu4(WW)lgAhwX8gFDII`C1}}nRdhytZ_dx+U}Gq*!yor zbIn^mqdy=yxNSHUEFmcFvw+JCA@GK1li17yI|{t5#x~tVPFCJaYcv-)KShN?fD+;7 zHteDJ7+w3&l4xVC_RQA~CgerNm+>VQLM}|MWjLO&w0_R2d2iN3qgo`rRcqd{Qv#3W zWmJWSnD+!7*(X+L5u{RX3|K_oXC(20=ZRz%BcC%a88gbZcZ`(WKkr(U33-QcyD#Nh z=~D(^(D_$nEo95n_Y_domW-O=*9M&en#LQhz@wf#1m)8mK7IMtJ}20#6~Txq3}817P`f zmZ}}Oob^?U;1y5@o(K{=0n78mq~yGx%hNO5@z;ue`N(qqNXCl&PO^2sh0hMsT$g}C zSEtR_G6#)y5mS9?t#r{=;ljlb#PWU7+BUTual^;8R_RK)@8ZUmYZl-(kc0lX>FY>$ z%7Zb!PJs=8k^-l5`^CMA7zy zTpJl#dr^3zB07H#E={shdO3P^KlIW4ZX((4N$ydd%y^eXGM59!+|7;h*k!k0nYpL3 ziES+&Tn-l2mbf-^KT7YG(t)`Y^e5XMVJv#I?scXcTo1}-`GBf<^4|r$!$Vgew0@V< zkSs1r2yCPol~E5_eve5cq9hqx@9bq97)uUEia$nP)9NzFTmDDu_3u}4?%hV}eio)I zqO<$j#7Il)w|t=^rW))4w-!Pr;zSLrX|~F z5?>0fL-{DDK6?JiyM_DJuA;&*{gnx(&U~a?`zPJO&0%8~5xENJ> z@;rM7GSLqEv}@0amI9d@-%R<&EreLE5PnPs-y+_pY}cRhnVMD%3yQcRU&W7p9GKeZ zxBcB3F9;k>?mmHqGrJSB6kLs>6au-ivL?{ZnCIF~R}_^xJKiCH8ON?x>$PAS1{3Mx z;zB8sp6?s|ERip=ZoJ;pn-CVQXCyyF7Ut{eCh8hoWHaKdh14F%UlUHyHDZz;x^wAe zbJ)vaiJHUAl2l`OU5+x|kl{&vPo^gvZ(63DX zn^W4`V;K^(@=tRdi@c_|{whMty3SRSwN;)9J#?f7B==o0mc=lfg2U_KbANKqblJ%L znh>+0d7uJ1-Ae&K`}qnd?}57N*!ywYs2y&5E}9{ zH4s{$kH}xfcS-ojB!Ahx83#j*@vlNO#a5XgbcF84D_#8&Wq@Cu#4a(WHAE0I62$G2 zUz7ds>*uMNL!sa8G(tkYaGK&Y&{2WMpa%MpV-P`Blz!8N#j-8|q?#}vqbo2UdMvJH z1>&jj4aj!j*OoCd{Z5e{lE`RfyNf~v=j`WtE;57xli@&d37}!G5pxDnwCA~=lZdX= zt)jK<2EO9;Js=JW0<|t|?4Ny1;1fQ1Jm!;?-oBOvtQ2K7S=;G<&h(uA<7J!8@5Lv< z1s@J&6Pc+Wj$jU}(*3t9rigQ6O_5Tv&7tU*T{~tk4rcn3) zk0hu2pCq4)^k6C*x+A`?V30-_+Ye8;p7pEzAb3u7x9K^<+Nr4L=z&Vwi#yypv%>WW)dmP z2E*<72IiTW1Lm2et5cZshH(lit^2^T9-OjKB>2+V)Vz}mSP9)tL5+&#;U>>jF7$s= z7s_mk^q-uofXju@JSSH+t>(P32tEF8Jtl#pVcz%4oklE7Se6ITc z*K(Urb8AjBWwLXK5tUk56xEj9c#dhMG{-Z6`$qw(?4IQFRQZ2`r55XV-j%S;vMO}W z{8rvP%ld8b@tg8yd;UM0jx*LzujA(s_;xHx=cY~NP%4yuL-0Mm4g&35UessLqj_`U zq@27NSTYoDrI(CEh1^&^*4(hRZxyk#zuqk=);;xp{~0^#IC|~RBTnJl1fq}6`jJZ3 z9n>aj_LDjOYu)5F@=jCO#2)%tV-yEHPhCil8~BIyRpzp7T_5h~No(VcHj@-)u@o3g z9ECy?_Lcf~ltl`u3Ds@{CP~bhLn~O7uJgIaQY4>1f0$A`O@^b8)PH? z(r@rFq>aJqr4n-?V;xPFoi@Ym60-jX|38b6>xaJQ1X`LMfzHg`t%`^H}0ud6Ao zfWuEb=|{zgrLSwna)f`4akQ9F*u1S+lnWl$fAGDEJNW0nZlJ5)s>C*?PMiyG~ zE;|~fNdR4UmyTPxaB-*L;kxL6QkoLv1P*@)g3=a)drGn~J7 zaruvT=F6cZrnNt!+3*lrr`madNdHd|UyS}$zdXS1&IQDYKn3)a)uTcr`^k6YBe0_y zD>||RiXf;rR0V+e8f3br?f##)W$xB8 z+gfWqlh!6*Jd^K1tS#(;ChXc&j488?)xHPuMvF^GD0$sWJ`6NqotAP_CLJl6Ch1%? zQacqI)%^9+88_j)H^z}zC78J06-qlq1vCI{#;YMp_K*WR#c0jxFH!ODHHV@x#@rI~ zD~T22g*5ZUBH>P99X>O>Udo{4b)S^4juKUnihM}~#``EbCneIK09H=8pC z6=L{l{k*oTUWSWQ3C8wTb%{iJSze=;4*#GtqbF^ER1FDPyUMGLNV?5)mu& z;2H8?mpO8~LJotUe+^xHQLz6LFDMK!Nv7rEr<*^Pdp_v#ccjm^>WIJgbmJ>Sajh`v z885v_1GtHuz@;!Z-I;y91CHV#&QZMA_sivUx54ufl%!UKNH-OAjH3xQ|4$Ypf+R4e-=dG4Wh| zlj*bW{fnjU39rI!IKs8TIUm?KZH{Y$!c%?MmgduuVuXn0gkf_dTSrPW$y{4eBcM>^ zcwbf?f+?9#NUM*9(q~5ZtZtRyJ8q2~M&%S>opV#d(n8g*q8u6DI!Bur?XZQiDhzGo zN9l|6h8{$1v*PD_c}E{&2`cV6`R95*${_kvRt0E>u{i`w7L2DgK4{u5JKI@-<0;uMrl3&GXO+N9CE+TgG z3J*V2-G+sDQ8D9hp?z}hT#O;u#4PfLeS@IKSd<3l!40s8D6_clcEQ|oiR4^Vl+>J8 z0S%%vxDPCeVQ4X;8a0w2tSvr-A>iw@m6W#n)LOE4QFlmy^B+(X#g2NGn2SK4>Jrv1ru6bzWT# zt!N7y2^)L=U?6-{*S_cPBr?^sD#y)fSeu2uM29lt?|>L}Y!qr>Vt>NZMm73LN3@ zeI&c>(-m)A|Kh&)PHVFjEa3F|EJ%mkxS(_KDMu}Of_m$p$l4A>P_?UgI#9KzTl(hq zt$FjjHT@yjd_y!baQE6dx_6Pwduxk*R661)oWGCrHPjisl4`$@dp!nE<&wc`N8dwe zLEFDxDcR{d2*CWeTx|9>r%b-DOWL^Ipw2q+e>VAkg#!cG@61j zRuB1!b`0=Xpk1?d&5LHG5`k~T1x2x8Lo5(MS>d!VAWJsiVC7oZ?L=IX>LYh(mXR5V zfgIDs&bxnXi8)dl|HU!l$5COB)xZnZVh-tvOR%j=}8S^%A%T{*&Pd zGX{NBMg{Lfc@tzPV_>7;-DLBJKCfS-Um|hFY%*hV=8vdepKRmRT6m9lZ&itM&Yw!6|@YuFNPeir*EMrAPPP-LBTTMUoLX>nm8tD%j z!?IjvS|Kqrdlx|1tZejM{{YxxibZxOVgCSv2j4lxbDjy5u9>QZ64W~u2i1W?il~#? z3dG>#ws#vHwlqG_lYJt+k8a1XjN>Opf=LL_RW>JIY~8N~H{&9f5~PsSpU>7;1nrBn zvAxF2NVpwGI~2MSE|Ca5DkUhCsz!|zHE9H8)2K|=%2Dla7pwz?RVzbYT_N?RF5sR`^#RiSzfi@ZkcP1C0hoWgDG^1CfPaL}&UlvVc6keL4f zpe*``rG)83$ExuE0I6ef5sZ^mV3wzILRQU+NP{#QE*LYXC}^mI2u9w9x%xK`q&X*h z{{Ybx{hvHMqp-X1xYv#ObRk3BEOd~RCe771s3&TSx&FuFZ01d8kikNNtrA-=kurWGC35M7a9P z$L|ec^IjN(PKmggv9dZ_HCq%kLkzFr*|HEsL}*=`hL0DYa}r^`J1N(EH{oK+%S1GT zQ=s;UN~CMp*Vfrp57Dus(~Pd%M3%Ze_?q+2I@z$#UE*@n<$Nf5!+Hw0@IHrn5Y?Jy z&q8yge3@%SD-umcG4K=bn!;NnM~I@`DfyejTrPLZ@Yu0N@VYx2TNy;`x*ujzrag;$ z6GOE2ZH;;o+sojvyAsI=LJ)#NM3))nye271*w9Q=6%&rgrtUWFA0j>zLsAhUCX3RL zM(x57p|L*3i?F>6Nlu1WLZ@maO0gqqq+3CZQ?bqLT`qlp3d3ESXzneD(I$5~k7|&l zn8hI`{f%u6f)o4=>)6;p*w9;4rh>F>aI4XCOmVq)aF!rF#E@2kQ=_iP>WM;#u<`6> zu(0^`;(HTlN;y%qV>=ML8*dgdA&B}A-9#~sM8;KNOiM?gML`Wl2H;5>n2`&jix@wc zZSq-pDYuq(d*JZ%GVr;rR3W9<o3E8F|Hc&J}aEU!r|UmI5WJi8ug9hao3Z1>kAjbG1)v56;kk7)_N}lOeKe}2LAw^ zZ2iOd;XEB-VHbkocrP~icf-6-0?%Aie#E>JE@9?-CO3agMgwtBHbk;s7RBt81sQ^H z#IR;6ykc_mFD{7P3d{!f)UAxd>sfhM+yJ$QmL{6SqnNCvxKYMqZEB`exm4~ZRf;rO zDO<8Jq}rod!~<+X$|#NE>Iu{;jS|X)DqG-{cEk&HnOi$1Erey3$^g4&K`b61Jt_x# zn<}7INl&PY!$d&?mSL%2w=>?N8dP!>UZ7#xBxski$PBKdNa9=yrltpMscKvsr%8Fj z6>OFkVZ!bNXo4AYi1PG>)tOj}h1AFa?optXO5UZ0oyrYBQZF&gmf~_BFuqU+J7rEe z{LCjfh@#p^g1owg9DGF^9FPG~%-d;G0?frha`g*co6t%rS(dL81)g9HlGUqa74m|q zTjDUvsycX-w%tK0Lj+wAr#{ z!S_5lW(?qn8At>zaN=W#wdN&gH5@b^U`pcUycaQGX@Y{+5VMAG9KbDR6sGaiLxF4s zg{eSdJ8N+$ZR!ELrYnj??&wVpAhm5*ai;YZ09ix~Ji?YLqt|Gg91spjShev1K{7)Y z8dOz=sfb`f9JrenQz>X}4|ZI)LB z=$BYb9EC=5ib^8MxOVx1P~E{AoWvlkL^*0&#Bmk1n2RG(4F+x&DJx~>C~2->nO0$m ztUz4gfmEtx0s{<}aiXZp3@Y5fn^>*hh%U=x5o~-*7$bBzm*!*{WVPxlsupBiWvT8U zUKa#~u{}zdwq*%cnw5AlGb+tB|wOmQlsHdyEG0`g#e5F;N!5sdfyp1mEyOCW^8_vB zmUWb%EW3g%nI#U`oRuw3Ys^+9#cttCynL^N63$~7fpK_=F42cdumYa z5ljS_Q0(SdZ%$@bDJ9bu#8q(WS;#3ArJ{8#D%om+L0;R$un5#pF^H8=Wya-(B~3QQ zxij5C-IwNMZ#+OWYs^DxAQ#z|))Ts=>Ijyp*#x6RN&|^l5hYC~*5(0zQd~i4m!pDi zhyxPXnuW6Ohzg!zK;AAlZsAo`aCvSaiPqq|7$HuQt56MHqR;UepWzbX>6ED5N@~rr z#9gq-q%4_$L0POz1=UOkL@AOrB#BxSfJ;dqD^rn#J7UfEAK=Gs|j9WGbKw zOu!8lsJ5yy)iD530(BNCk5FBYmr)j*-K?q4rwn9fx7GaMz> z7_A`zt3yqzh%Li&AVnG?AO_x`3XQ<9X?;X2hHez~a@kxomRY#6E4CJRB^$cLt9T%a zQBwsDC7dn_(MpMwaU6rM5xt)TrB#s?P9|Z;1xo_sSb`QN;)1N7#7-YLAlViq1(kq% z5!&YXkFhNKcLf4PM@fEW1qof1;yUW1l&9P>{-U>L=2c}kF?qsoS}|T5 zh|een+wKFC4d~XT7|g(@UCT3%nag5YvSMwnC&N&zn3OE2i9j4Og?j23RhUg@B+LPM zTviM19JRI7BI~)Fn4(aGD9QaLYB_mZ9TyC_Qw6ExXLfgJg^axPk(vN zNaT=SG2(;7eWj&Pea5^8=2mI6^H9!WY?eot;!}~cnC{ihy)9G)8YK!8^#oKV+`vR~J(A4? z6f*UgV2CI*V3etBYfwkcPQ`v8$MH=M#TvLhMQMCMAHgqy5k>w8lnO2wBusii+NL6A zzjICbusYM)|LnKfY-#z8ESmuseOe>@yithg>!YHZYe zD871`R=;tyiI*@VwE78YkE$j7Q^@*?Yw$*`{-BN*)E;m31Tf$*6Q9&gsbb|0y8V8g zqCZf5J|g(P5j}`HRTZ@(vH{o-f##bu1Dl0gVS*Xu-b&p-pEL>mbCWZ>@Ijr=sgL+( zOnou`00%6e!xR!7YV{rv)<_w*es~u$Pcp2Vv-(K$OS9~XntjHM{!#Az$Nbb5h7?&N zST0o2?khp_6ap*UQE4^}-%^3xD5a{3%JtlDCokR_+6+`WUYOCM>Q(};o0Vq0%b*6@ z&XJi)e{8g%mp%ixMt;bSaH6{BCj1kj^7kHU;1ddyYldIYc25c|fMs7%DE6UG_P%3= zW0?3OP=^7PcULkRt=%9=`$j1N(cwEt^8?v0*;%-&zC0KXp#U|Tnczt$4p-&{YKINp zdG`eDN{kM7nWm2gY1hJ3^-!}?YTD^|2b2Q;mI;_z7HaS*K` zRg8k-4+1tAHB&QYR2Wv`hIKADl)4#<5Iny~8_NL@Qz~BQj59A-jkZ`~1!r)#2~NpK z%t~TL=!M$_7?v$98io5JBT*(Q1umjWrVFW?BB`j6aT1z{6;k(d&LQyjk7 z!YtekYHPw+ktKC62X0_kH|l1ZXzEZ6D1a5N7Ex&h@?1a>m{ie#mJ$J+>xP}~MHE-4inS}YEUaIYW5KkEA+ zz=pN@nXmSTZGW{M+k;J)%*fsT{7*4##qdFjjCy7V8W=h@W>E#`Ryv|TdF~`y$ic(J zL~uY+ynjr5wuxEJ^&Nz*><@|~3=V3i2Bq6ym-j#ICzJU@lj&n_4`vZDXr;k_aa77k z27~AQMGxeEQ%Ujv0E|~}{`^Xs{CMok<0$3zn+^TaG2|>4(jcooNo7Owe{gF0NB0S% z>wj@e56AnBU^&5v;Gwm^(!1JHM80!2Wb>3~?ZfNx=IkU8R7zTZv&8fN0JFpavHt*f zh|#~l`h%|i{{ZSFul2o7OFuvAY`)+10uRalra>>1r$hTiyZxc6@5%z${?Ssc_JUor zjGW@jM!(XT&B0>hr-iu@=JPnfg$W#8EzAGQa(y~i+5nAcyD3F7w#*X|F0 zWY7<}Ln#xGeagI$@CX9tlz~>U#|V``OAMLyFsRH?gB(!=vrU{N6wnBQo3sTfQ|1LJ z&1yZFWy0D`)Bx6VaYF9OMhDOF*y|nX?r}Zjt zd3S2sqP3`|-qV$3D;o1JqDe4ab5By0_Q#vYOdvqIWAI9dP-;OpSlqLz>a|-N0|*;u z;;}9P)zN6)yhM1qhP7?n29GYE5~lO8J=IEahQg$b1HoeH?otPpxQ9@ehS%F1!w4t# zLg(rV#UTYSBP1lWY7USg87_im8eL?nXN{gFcp2@N=k+iB6Sww*N_ja;J42%3fAN7v z>GFfo72V;R56%l@9>2vOr7nAUg0vn=e-W6EhEnyVI7Q6a4QDQhq9ejkl$>k@edL!YAf^IPMVjiKq{V*S@Wm54x1n?8WPXRmx@R785P=A3>3+i9P z>RZDeCFk)@kE(KhDgOW>CAxi2V;lDTPx!H7pRGURqs#RrZ}FnLe~5{Hi3BtB5Dk3^ zXZ628dp}Z%mCJvr{{RkE{d4|I==x*&5qF8<{m1_17)r-?6e@)?gC-kh%rUWNH@M_h ze9H17f`dE<#A^*kLURIa!NwD0LBAinQtw zE23K9BD~BM6eu4rY%2xRF*pf>6!*fS8C2U=tAma4bOOGZ9fpWF7~&bq&R4NrW#X(gBY- zl&37nfQ~W)my3*|95scYfsHd-xM2*cJfK~EhH(J}T@73bjc^-z_XCK}j-hzfsifL6 z*%usC3vvU#qX%n+&2a}^8FQVtnNhZmq0F4>KkaZ8x)IF$;46==CTnt4Trvgm0$o$Y z$fcL4EVpH94S1}ypgWemXLR9|BTt!O792++uv`|S51tYLk!yvxECN_-FdC9<>Tz*- zKW1XlnIcOE6fVRDPXJsVT7Qt#wgbF zEEs`rF5*%Rw2Y4k)~aS$shAAS(5saA3^Xe7Qk;b2GNFJ~IDw`}3@NWrxq*6K;6}jm z6ZeUk9mOhBce7?89*u7?=ubBj01ug)lpbM&2e{Z2c0~=9WkT;)83MwMo>HTbZRv44 z0Ru#25G)(Kx%@?lb+*G&LhQG6VpcJAr1esWNx5xxFh$?;N*K_){{UC@1YhJo>Y+Cl zO9I}15lPv&*J`&5>T;49dvy|v64inC8VV>?1o1sZB~VLa3jnH>IYW4lRl1o7gA(Py zS`jTp3JuSYh$YEUEPANPWYGbbA&BHl4NtKYDrBevsvy)s5@HpeVs!v+ppy`=;3K#( z8z2`lg-xB2GDdosxpxdTF{xSGK)lF(qkI~&l89a9^vKy&wC-}6~8f>*SdX0vlnq@Y zpXAd3<+sTX_bli(8z0FXf-~B7W(Sl2h=K^=0H{?7VVOe40;0f%;utKz!hu0^FfgE| za~2V5OrQtCF4O|aDOloJ+EhQ1RWJ*O7&olTgHrs$T0nOmTt#r)nl?=SVPfBUOCIqs z%r$nvV5*amja6`t+n%Fja*kVHiEt5&ZG>QWK>L_V;8P-6DjKjAT06!*3DhFE`}G`` znHE=r69kP=yj~jr0Cx)A)~ODdmcVet$WN4xZ9!qdZU<{B=2eFSvQ^nHfL@p9_k(mP zCpUqwZ`5+LQ@T5-jCR!{rZ^%l&XVJ6@DViIh=zeBLdA=bWkU@yk)=-sEmbtY#TvZv z1eh2Mx?wd@rXUH$6CE%^vl1W{h4_fu8yc7j+@azu5C%xbAw)`rW-gFg;H?oXOGL`d zY*j(Q5(4qe!_~yGL#iTc0}9t?h9U=`u)0Z&W z9q6nP`EBPBl;G$k$3arVDE|O5;qw-z1z9oWh{G4l6v6t$ET?C^G1{|j62X1a0TNMM zgX+A&(#msIVZ`#v$B4=W%6I(_xVvhUr!R?ad6Ty*!=#t)g8Zkah?{OCt72F#6mAL( zz=jqft-uE28eDL~!0pVqVl8u-K^GMi8zZ(DF3C2L1=m#sS|#r2fiMXRs!;|3WDcyU zN@vssRRFM7FSv5G)HokY=2?PKicAZ(sUM^*w<~5P_-4NSOa=UnMQkg&*Qr9W=Jf;2 zY!&%{i^pY_D-Gq^cgng^0Rw;-ecT<9vn2e=0s`SmjZKEQ81%aYb`Fy;%R7()&cC<|@}RHkmSjWYlR zmrM{WMMVU%SuQY98ethzRT#xL3gRVIFs#%PYEarsCJ55iEld!-5mcat#Awv9RRC%s zgn=4~)GL~p7$L(3>8mUqKwBeBMGIZ|nL99tbI}G}(p3kFf3mbyc@rk1X~buktAH--h#e0pIvwjtJGiEXI^7IAX3a-p^k$kf^b zW;NvjT4IBE?W72X*ukjW8FiR)#}Hj`<~0s9soe-2Dxs-YDFswUij9mR00#sv(?+fX z8zwADaW=P?EY4buJ#hwvOw%LTm@vTr4g6kWP&8x6TVwW>5-n_xTuv$v1gif46cDtJ zQL{-RV}(2;;00q!I^HCEiH;w;C2%C8I5#7&9aK7 zOGmFi5gD5n<%XkHrP->9TA2o*t4ke~En7@9ii{CDBB?|rHbq95(p+hb8kcy2twOU< zT`ak}f~`!K1?o08ElopD7VxkFD5j#(WqBc?gAV4`MYtkXqRd75#JG<_Lh80EFEDkM z7_Ee2L=I*!(_ZBmXuKCO52eIZr|uwYX=17!zM2}gJwaJ0*9pZBY}Cb&HZjSRY|6~h zD=r$;L20XDLvEk}D-gk}7I|>R!;IsM!U)}us)RezpR@~&A-J8(inu4Jp|}?@rmktC z(BdcrZ1E7NXqA??>Iy-|p;1(Q zN_#~J)T64L)M7ZRLDgW0C_UaQ)OS`^R{mrCT7y%p=Q7094P)G4w8kMc3=w7GHz@&6 z(};d&aBuX)P!(u4#Vl>#EJGif9(mfGPej8ZLf3bsWu<`~3#g)7hzA8MPtDW_WmaYJ zGg(S$xprk#z;sH@OcxU2wrG1^putous&ncFAx0QVix*<0lEC5$l)y}lF(a6)pkqfQ zcYuzJk=}_>k}J_LY9+`+43g`03^f;OnnufaG_T@oNa3hsA}*B`I*Q5&k}JhQO_Igq zd=kvB*p^1P83Jh-~yTSK9>}b2xEK*c&tiGd6eMG1=qMM=<1fjAATdM#K zeMai$Y=pb;nvKL!sNJ$K;`vQn{&SOGN>nVJsu{MNWT{O>7U(zy(J5x~ zhWCcDZeoW%k`P3<1A3NV3t%Y&&-D(%tv(&65er;#F>efWMg#u0QL} zO7;3rRPjXhJW;z+lDDaYQ^7nF#VIMl0+4iVWi_U}K(dH^5NfY54X;a-)Jv7@<|W0R zSz0ap%G&gFO0?Y(k%2X@#J~}}w-aF4zy{?{FdOO zPl)IW=@bg3aF<%x+}VSsqWu#B!N|>_V%l{MYS>^0B3Cq2lF2ve6hkyhen%!7}I9WW|pK)U{sAqy1FIlr|l^@f}RoA|DND1vY9n!gQ}t z%XI+_kGW?kf|$HOL3wugB3lG$>(n0zmR8z!%f}7LpSh8iYJ(+TL|9U?+y^Wdtl|=& z3laRI7A><#>4u;33SIahz_x(+VZw`{k>$VMX27tqPJ5!|wsfN*mXD(`JFlo7MeZO* zjv%WH=s|SLbjx(l13V13Ot(z6X_o1h>6Yo1>6SQUx@Ed$x?;MD>6YqSrdy_4sp&7& zw6wM>4whQ+0nTnZJsGa%MQp`NCQf|_m=n%*0RTqM0Df6gvPY83C8Xa^iBq9l9zJEm1DZ0)U2KaDAX5i1 zs2Y!SJ77JG0)y?!`J;K5L(mAjG^&EN5p{FiN!j-YkgHLLS;PTT03y+v_K!vw%urR4 zf+nGcMqPkwOk33hQEkmaiDo*2mpD2i?TAh~odhfZsc0G?DMcYctfEz;C}G3yIwpKa zVl2UMMY}1^Vq%b+c7|mJt7To;307gDl`-)N zswq};Nm1PdFnZJ#xmgi7ce zdOy0rl{Vr4jH4>KBao4yag8AyIE1K@gG6G98W%)kRj4=!)+o3Eap1uyHJFXctOdjx zm0%H~(hy=aLRKP1p#~}>L2cp67$vP2KHyX%50MEo1I8GE(R+zDmB(;M&^ziH$Az-h zf_BR&(-6*RiHaU8FT@nfEV6@C+$mzZq|*g1HLlST(_e9Oc62PNiV3uAmMH=Y0J6~H zr+Hd~Aq**^wdDuUA-L>B&%|Moj?hNPxm9tpal>s!flC79V-twI)sNLnfQf4`>$!d{ zbx-ul0|5sPI>Z&ea^PUnz=A;Z+^5h=cc>a}7{f#nx0uz$Jh@LA7HNpJ;u6#5`ojxVO zsgOKHvb1ctrDRkf#T+hc6RCf|8wF*vpO{&qg|(}_$7NI~xwJQhfb?-3Ve;7; zMApX~AT0Lf1t#@>*w;xT9VJ6kiJtp2;-+^HFlJb5GK&EVGD=n< zESZ65W&p{U0_tocBv}}dxTI>^6c;O7LsH`ELV?VhVZNpyoy4YvXSZ&uU>;c)3^ zn5JY(-lEYXkZ#}1Y$v8mp)ROG5OrpPuLB5!AXGE3`X(a6_+{^pQJNK4 zy#V`^Y1@*q&G&pl3LDID7x$@!JtEu9c-*U~ss|FRyb%*~4Xi}m$7>3hW;WPV+{2a? zD&`%-Wf6yPt_EP-H-jm0xE)-yt)L&(%qRd$A(Ex{@ileu-E14A(}C1$d~hQliB;s_KL?@KHoK*-8LUPn0ig5sK3 zsUq;2iUojlV3r&)P@%B$0J7!lfxj-^B~TXqIEo~Lq`D_Cmdr$Kfh`CQEw2$MUa&EH zmpa3CJi(?EtXjORR#OEFmSECB5F8H?4dOMjo*`9|E2-nmtuQzx8>k9Jmjr}Ca78N= zU9bk$Tal?kTqT97juzo9%7#~jS2Rj)5mwZtvSb!uBdET~RnlaPvFUmtEEXL>utx@A zI+iFiC@5BR;g$fdL~d3f6)~BWGRbKbe^V&AvgJCKL=m3Ch=qu1i{Ckc$E0jl5fC*+ zIVM7nm2GwSnCIg>T=G*UeHSqQ0Bom3dx!mL<^95qzcJu&r+>`qp#c8?sElJ$I=u!I zX=1IX>KDlo+kUHgnv zLbzGfsMG~CZ`=l&yQ-LcL=q}-P@ssos3><8JVV$-P>`vz5EU^93Y=Hy6wW_Dr5i38 zNbws9NZAy*Oo|(T&5#Y;25w)fCE_5oMc?^?z^q-iObrLE!Dd=?mw*Wlvsyylo zae`L7?Ky~GnuvbzGa1y`LDPHp1-UeT5df4&A#`<6U7={!JQAS|^atWz;4)Rf);dzz z(TjmhOOq_<<`mHW0FOr`S|hj=+$Br6io1^iwT(j8mK4kTm$O%u%P@U=wxDJ1GYMLz z7fVsd{P32B3~dW-Y!VjLa{(dHED44o1%=k4aI;;g8B7kPr6wk*xT=*7V3$RS#4`{m z>{MF7+_0krz-6U%%m)FiLl6vx)0pK#uTt{67rWdV!bx;z9Ax{vHfl*ULdI{1awgO_*t3>f77zuE}3n>q|QNVbLm?AcnDBQKi zVrT;dF>V2XYG;Ncc0Q#l>LoE9s1nr6RaCKgdeat$pzBj5)E#POx`VAto2rAYOS4gH zQtZ=lYg2NfR;J}j8inCdoJtuW3Q5#r7^!Cw3{>bum|{%Bfr2C!@1u7MB41S(2~$P{uo%mmzY$%3$iwj#mnZMUQOtsXf`!O`wFtNa zgYcH)(;~rCTb7uK_yyT~L<-8yF;hA9llO~Vco2dl3IU>0s0tzO6kz%=1$^op1dFS> z`HY3HsO9r>CC#C%#tF{Bjm#)SBVELaOI>J05OZyZ`C{xs^j(irFsQQ1mZ)TlR-

8JgHbM9E6x_L5&mnPIDiVXVc9)4?=@J;AeO zL2OG%m?Lp0)euXn*{GIuQn)o6%3KnOSR~@zv&I>4P6u1u)F?orD4`I@gNVH#B@so` zN`gEyT@n~nv_P&{AceT13|PVhg{c~K2Ee{!{c;^d@gGrXF$Aa!1|Xy{#6_wzihzh5 zL9D^5Al79nH#4L zY;TE2xCy{ReIUi$LLTFcqu`p$8Xvhp7N_5B+}L zTJ3rZ5YZj5t6IdZC5TDmCS%k*XRP&}vGM&W0m>W9cK!&#j%v4yJWRNrK*PioCrXuz zsfEP&nP%xj%yb+^4@^qy$q+1F-OLMOM#F}iV{EGcm2tAJVCey1P8+Ij6^&=A2Ca4R z5TMP21_*XAg+s{(nPCHi_9#(yv5|A!mkOC+impz<-8nvBA+`iY)%8-&6{t0v%M$J_ zme*x)^)Id^6)pilHQ=CQksPoKP3G_eEMujB*m+JN;XP-p!;jWxmaH29oR>H3&QElOLEGh#eN zhN+ZBciX7IUyTbYB(ov0Qn(Y9cPV5>q-pfc%dn=xHUpqHF}ml>rAx48-r-Q1Rqo#7 zR5;r!%K)HzIX*ncG)2L%JiwJ!tRT-g6s9WgO0~Z{PF4e86P&PAgSF_4EdgMZ%XYzS z>bLeo>h5w6%xi=`gr<`mRdrkd83NVBC2@GbF)g6KZ9@M5D-1ukgKO!*we{eRAK^G@ z@r9qkfa!k^&<)`H%l`n>zj^JA`AYVHaKJZzQ`z-A--v(BKh#eH>NV*uG(}JjmB4?t z1OmDL0OsNtUxXfrX+I2PqWmK$$EXwywF2T97HmWXieZs3F!vhyp$po?$Fd$|PQ(@2 zaHs_dT6>mU%H7l1G_Vd!p3=J!@+Yx9iR?tC$+Z9mmDuqM$j^$suXi=cZ54f%P;OF; z;vJC&8Rv-=bIlPl-Yyfchc$37QC*1KTke)(4#K1J_9Kt3#s;*E?CXQ?30xz-3!o5yTXRvEnuLQoO zIq?RmT>`(>2py}CwRaF4TnBLFYVZ3>s)^ZlOVtqK%KXC)!J`DH7K)hHfN;Bww(mIg z5H^~jpnY>G&8qZ&nTi#-cg>!aH^)_$pP$#UoM$ogMq11sL4q>hFzIhcsOs5gh!fPs zm!+uZKT1F0a7LQ_V&;CldYAkq`}%XY>&03^aDBxZJumkFEzd#x%^?2(r*YvAU)=?0 z8DpS+b0r1-yhDusAJkJHXY`#PSM-Mm&jIxb{y_!)=){lQKim@|f4?z2*nh6#w4Xoj zRsHYo3#Iu-gphFL5N9;eK@u8K%V@#}FwqE4I8jl1pMFx!e&5sqE!sN>NV-Q1!@$jQ z`i>NiX^4?$`h80JKi^R!{hx?){{XwxNBh5Mhx&hL@c#g#)c*iW{ZI7&0MvND*Xm{e z08ip!{{U~|Kkfejh%U?h_?~}v`i+>U+xnb>`F~Jezt-^=pZcC5S3mA}mgnU(1+s@| zedD?M!VG;f-;qDtn6ZQZ08Zm$WOx2aQU3SbZ~p*G?hbSR0H-r10pWjg?S0Sgdar-( zaDG?!JwLbi9VgiS;Z|?={^NE(*7Gp`0IBy9b6@&%Iw#NfLj1%L;fDw5gDw6sV>tST z>|qHSl~*uBWE|J%VH97%aAlf3!Dsm*g;m|7`9ioT&ADcqjvM^PE0I-`_b%1DvQ#F= z90b9xLg~z;y)B`qxt5?}iUZUQkDGG~0AXoE>LEaAG{sW6vnCmtzM{xx(*Uz&Pz}Uu zA#RxNDo)5^w=keVF~juze?+yW!IsT}#`e$dO6RBMVQg)DN)VNzsZEs-q9wM=3^7M6 zN10K#^i(Y=)(BSE9ZSk#8kBVaY%?p_10*TQ5k=?q5{#n*6%cCT&=IyST!5&HnC8P0 z%+FR*w;3o|V`sU6f6=$7Evzvdqj5F5jAvtnmj>C#h~{-f;y~h71@+h*@gH z%)rH~OpFrOWc8V5rX5VPD)agR6v7yS6vIezYB;MRY%w|nJAo~ixJIZ(1(3sW3PQ|T z_<>Kg&$#o%(OZa1I$X*0B%zP-b%~?cQmphusIwI0tHGP%2p29WW_{V+pW6p zxFzinD$>*FnCuJPGyY-0Swhg)seYBL-h9KioTEOW5mCe}_G4U_ec$3#YETd+a+yK1 z%=C|hUYNK9#Gzw*%($Cg{^Pc$5w~mvQ8bZ(4GdF=lxViFK+&TNGhIg63KdQw>N8y? zATu`@DMVFgU!WHLiiJExL5za@$3m()U|f0vHL@(!MQjP?KIL2bD1=aRQQ{%Y?KDg2 z;ZeJ3?r?-3B0j`_5c1QHGbnWUV%sPeH!1=89)=-I0icv28i5xHs1?~L;!-jzDUsa3 z%0xx#TxJE1YEr3!nB1k(MAD;Z#ZwGnF2fNm;sj!1)T&}KvoT^K>4`{@CJdv51Hx&< z6E0EthG%FNT91N432l#yb06qMsWPGfqQgS}020izmnX$U5*vaRpjw_qXdf|T3%cQ8 zJ-;9a_Z%vQ+rJWs*;qs@0jHuqZrcX)?})vs%@m{fog&`;<&$>oG(%DMOi{{XcC z-M>^4zs!G9hc~DFOxaIg;XNn%>Q$xmVdSA+{wNk;e3Gonpu1P0Oz!$$-0UBMQL=zM zQ&hCLKPV;BcbpGl@_=k5f?)e2%mNEgE{)Wugpx*xoHhIYiT;-Tp#1*;>8O25>3qaa z1e_r2d7R_)&+vvH;n`>Pv;BsD#bpit{8N7@!v6s8n7@2~ss8{4{-^wh`iXyA{Xjph z{-uA`{{T_H0rcO*N0-O+M}6P)>SnL@y-fA>e@ye9zpiu-*YwKpXZa#skT_#l;sKJE z4&joDcPTo@7O>M}S<&E0jG?IqnPQTEP7NjX|jPDZ8&LpYK1&KivNS zsEW`$Xz$!cBxP*JA2yq$BxM!IJVP!#f{Ql!js@*(_z6)I9FN$t>o^fl#1<(du#($V=;-GNGMVT#v)tV^#_!lBCrJQTY}0Kt4pfHtUIR3pTv39Lm3Pf>{z z$LKPVMV@>^AuuGPw}s{p9XS{r#(sdPR4M_~1F1<#PN#|=_@MHBmMxRjDcLzJgK|!U zlr-@F8jnkK;r9 z8Vg@qf5T7s>Hh!?KjEkRlo0+DM=&l4nhG=Zr~G990Gyxlpn82u-jAtHkFU|=7y4gm zu36^Kf74l6Sy@?GSy@PlNQjtF($ZP9q5-G|rH<{0w!R>zE1-r|OZEAH0010H%3q(- zpaSqY^>aH%7s-}_BGfhW5fuh3FKk3?xXJj-a+Wu<@d(O>g#{k_k0~-NSLR*ioUlcR zZd#Q=s;0@PObccI0KOv?LkO7i{{T>sz$&XyF~DK9=!4e-hiCT_pB74^(V2slm$`~4 zGXDTniTWpE2Yex-p2U_(+~N3?g2&oJ$G~1-Ig9!u+#8q(2pAvKxpL3_;#8?pph}hc z80K5tx45rt&uq_gJ+nQrdo#?3kqPwB_}hEr8Lu^_3A}FhGQ$UdNwMirKZ>DdY51 zsZ|vPQuDmQHcR0N)Xi^X#z-;!nMx$PIQmK~a*imK6hpMvtVS^V#vNZM0JL$V|)z5~<(8Ei^oh^l_44*GITAELx=5%HNzUIq{=^iTvBF@HcE z!Fhr10pr=xe{{6$Uf+Q3&AgZ<$pDWGoHrviypexe;glJS0}hbYbNRqgMxTvc5>dGRYs zSk^NSbM1On?}+!Tfnt;aa;-1i6~@6@qAkW49k296D;mh)A29<)p|4O#a4e1tKlMao z5YKcnXYMUg`Vr^gL-~(aom&oyW`l{-kJK*%pvGG0Ifcd#bz}{EE@u6&3Yka&a6aH1 zz&V2N^bW|5NDnX{&_7XdWy}2+E@A%wkYR=tC;*P-xH(j~xhO(3Zpn%sa6Q6Itd^4D z7|sW55G6zZ0E;j5S?)ij#r+Ck9K$Ra%^7@7QexY11X1yW#IC180D>3ZGWwW!y}Ym` zO8p=FWmiGUdGjpB0>FUi9!mxJh$4o=rw|(3N>lLzBaTt?5&*Z5<@MA+fl7A`fCbAB zmFLtzpoLH$h`3;?Kfi3N=!0)dF(lmPsnkP5!Mc`Zbz~phsQVX@I6Xv6THCet8Idll zA4DKEd5)v~1SdcE2%Sq%aVjI3oNj4Or{+vWlxwylvX6krTHdTmqJxSVfLYD6^((f{ zdYD2r%*zep+KFXb(|D~7Tse+|0W{d@pTPT!R&OOu=Jduni`=%Ymz#iudwz=dE8GWg zyriDey~_6~+^2G##CH?iPjEYe2D^bYPe?f31>}cYhh(R4fL$;Whx7;acp8CRFb+P* z85i{r{x9hN0Oex@LAGN&;%DfVklM8Je9NLND!+)b2L^%W7=Sg-K65^Mb;h1@ThNY~`yO#YK;f2?=5QfR^BtqNk zFWy|&T}E5|PjPSuyf8J+*ay>8-z>MDCHlu#AIvzYy@2^8sV^2xWFqqN{l=SR`y;O9 zqxukIn91yqWP2jvP^e?re&(z9Mrfu5Ib}te^Ebo`b5;(VTuf9^j0`aCD?(XCQXHu$ z04#fj1%#+E`lf&JQl&(RDV5?QEA%Ib7Zn54p&vBN3IJI-8DOYU9O!NL5EcWWqBK-g zx2KpEaOwh>AgT(rDU|gQjml*`N_zbq*c9maCVa~g`UcoBQI;s0pV}}O5*LFyubj4Y$d>GY%p==3r5-tx_q2OcLd#tq!Q@Py#!led^UF}vV6F4 zWCJj0!agr?1+ef3h;8niYy8SqAg~#WnO+Q6thkFJtT6q&zMyDB8wFtrD6}8S>QtjL zEK%kST{^3;z6omsK`}>H+A9mpzmVuI9l*D+m;wYPy9@T}4jA@h++t9ozs6!LE|IbY zP=-_x_tZ5Uy8i$qseVmAK{A?n-*scn`xv!Beal?>Ym19Qo7 zmCEsHS(X}qaU{zn!S+2DE9SmqNSi@ri~W;<%(84q&{NX6g9`!Wfa)&sEf^@}&1zZf zEkPC|3Ri%R0S5`pP-jV9{LAB87S1;i*_4WS`|ei~!vz~$OHkHTDa1-d#?-2S&?!Uy zpwGn~0{qNXuz~P~_uv(0P{;|UnuiGz`x72FXsf7oCt|ZH3?6Oen5$OHEZVJYcj_!> zh+qe0m4~?Vqq$MFSxU^b)`el$h_DMZJWMQU0#H?8BnavX*a^`@wMz3Tz2Z|Tl*(mZ zM-sftclehu+$y)OW=(Z+`l>z421nf6Nn6Q@fZph&y&FBneK9mO!o)>L+YCYw4dzmf zy#%LVI-5|zhG^Qf3BEk#gV75-pD>YHqR@u`+bK|?!|1?JHI|YZn)nPu9`#~BL@721 z@(6x377sN2CA6{CVpVn1P>Jj9O-A$Ij2#EV8)0Z@@(6YAAT{0s`d}gi0Ojr@ZhV=o z^2NY6m3>S~0@OHSV(l%VisAx5uS_2LhAPh6HF_Zd)u7SS)GFM-Du@8J8Q34(tlkYF zE1a;oGhxbcPg0*_kZk~MK$5@FP^QPRzjQ%tToJd$L-4A@c=tFjRAqaKuF?CF5Ve#l z`iNp|=3g*BDg||)GRrdxwf7Jfd(wPa8;VNb(;i}Ant%}kEN&<-ZbpXvAIw$?k z!DInKvK>lcX__jfV^~<7GUzTHxkxB=ScXPZAE;gv%&P`k$qeaL@XGLU7h7Ew$!0?r zD%YBn)o?0SXHgb8zll^?r42JLXi-vx$}7#>D8ub@0|VR$mQj7pvU_H$qB-3>nScu; z)B>%DaMC<5Hk0Lsi2H+kLAWVZlIkj9mxyG+UM6vNaDx@4*2?f^3Y8X8j|Xu;Lw9SG z#ui_};syhBvQM}aK`xj*%v!7?M{Id0hBL)R&9>FPj}W2N12Hx|EJK6LT9lhD3+9-F z04Ob=o5T-^qPBFgwHVM6z85McLmRc@{KSV&(Dej2GN`9`aLmFbbAli=P4B^R3fZGi zjm?%7p^p}b*o&24?puh?Zx=Mca`W{Q?;Fn$5={^irf!t|6u#vDKZwJCC8r_&z)Yq%5WQt+# zvb*_(oErk|<~uAAUPcN8veAD8$S5;-A#%!WK2shz)Y|!ajtPEG=2EQH2+8W=&!n<= zB6_OWtMEf%gfWD9>JVyL77!)%tYKjcv=Ltts8A<_?Sh2n^R@m6-Q^3Hm#DgwL0XIE zVhHWy+(NViKCUN=u)Fy%aT9}ya#&a}>6lP7JO@xdR4`-WUc!1{d&{inz#h^ausDgc z%t}(lbM1V=ajDPBFc?G9&o69R#T&^JxHQL7h`(&EHNkTQ1XC~Na3w=0&!{#lz?pZL zPz`BSuf5I>CA0XNP@t>6>N~6fYw-YQEQy~Hix;aDdGQ23g8u*sjbKEgoVr*j(YqwZr_ zcse4QElX}Rzm|`QV)d5Wb^Sx#lSJQsqHA$7zllSIEtiQ(DGDTpQz4vsg4Mo%v`u2)0(`;PItwj)#Ndo;Q{tkq zH8Dzk#B4VKeZXy2DdrVD&W5H`msOcw2%%Ki9Qc9JxolbHq6Nu@%zN$?J%HGHQGoF6 zdxC@vyz;(CBsggpEiJ~GKcX3{29=fT%qRj5>waFM8xR$RU#}5#MSL&NM=7^%cJ86+ zgJnP`5YhoDk^Go3h~Z=*b%Etrrj?~F=2K>^t;OkPi`Dv;*q1gpEp?}pDFl?pn%uxP z4oj!R&^E(%1S950u?-B?>IhD4pmO{&_5w2B%Ur~)*G827rsHL`*Tu?4prozKt1G<8sDNFU z?2bgl?kTdkV+|1nE(cS}B{x;c#LF`0vo2^0YBMc)ZH`bCf|?=MDmdk9FnI$?VX2BG z9If1TQkA=oWVtkV#4Tc4uc#^7&F82f??qweJ#Iw65p0E`(D*G4#jupVWhH{JJDj#b zm?(kABx!KU+j_*>qQNzKH+9mrgIh}Yml?)EC?->W;RfDM9-mXqATBwK(-wq zFbK^+6E2A`EJI@EFb#B8ZJ&N&yhYJUCDt>nfl#n$B33Ns@sK_c(L_x z4XCQ4PUbR8QiBm&XDc(MNolCTWcV3RkmZ0Z3r;Nc97~=M!kWP{IxW>h?3IHAw zEXi!a)DH@$V=Q}kfB;hIW1wxz*R};~4huXH1ubDu<`@*sxICAbl}QzmYFk@=L63f5 zBdMU@v(%+kjxm_~QX;?XZL;2liy(shGJqv!R#U?$Zp5+Q+yRhQiTz9?AS|Rj#UMGA zH^Vh7MqJJI8@Razmrz?}vvDY?NXo*Z!tPJ?mk7`UW89!14P$SH9-Zmn9L5y^obv*x z1PwmJsLvKz^~b2hmn&dSUS(?oVQKdX3UaI5$l+dPgqgy-nJPmS{K5bhtp3jvFDSQ& zm3puQNbG>HpVwU3D!ds9d914qzTrfRy-R z5!`4w@|dzZp`U;9E=I}2bxc)v57fv?kxaj zQo$W5+z}3|+(5kbaox7dC8r?gSLP^y>Y0|+t@UxXZ!+Ag7X&SqAka=jxLyOBJV7rC zGc5^<9#@-yTfk_lSt+hX(dJpJ!5IGlh?J%TvZ0h4<_UMz!~;{HpAyxt$jlb%*kQ4L zU|h2%>FyD91`AMn&R@y(4%0-Y*l#(04QZf$RJ(J$q#h1SbvyNB^YQv zr_%{ftA(29b|^eS75C6qS(0qG5AHQ^wY``MK{i$&=1^P>_F(K@BZy`iR@On>B^k8P zFIi%#gbZ0(hd{EnrXv72OYsV{8q4tkJJt;DA`LB(v?`=+Ey>r8rH9O|tC_Gq!|;hf zG^cJ!N1ZdbDPK?otsk4GsK*z>*0}QwY^eN^G3{Iy2QN`dHEo=;vN})%hcq0(y`-_1 zZZ&WjNqdGjG~Mz#I)+8T3o!QuT$XJFS}yFg!=**s(MPd~OKCf;O57__Rw#@qLyk#K zvmKI5iOz8V=fq)Z8hL>+p`i#tmlEmijd;t>4;301om?3%I#jO_IRy z8j;(o*P2OCrJVE#L_XL1ODgc*idhr}Go<)(}L}odban%}#!`mxx z2!dUUZ>e-V%IW+{Z5YsmlwiQev{w#*5B!2asZC`IxB#JNUM1N0IhKgqGQQ!Y$S#3} z8W70jlxhbe%j$1VTTKZNt2QzZaN~<^#HfNXwX(cMtcw(N^$-;*<>{GoOeR(pf*@?yGhh_aV5dbA-wNBjQJ51$jJsyABeE^RkX+0M1Ke=5 zwW^yXYw~G<+bYDGzwk>xvK0uaYRQw_LhM_2iCr>m?U=c&;EEkBo2D*Ghlzrtd};x? zyl`qN9%1S!C%x(MQ@U9H01!%rYZ0TJ%4VJ*PGiI}l0IN>TTm`#|oJ zaBxFZN>SDG5DbR%RqkDY&e~V^6KEJ}1>88*rXrUYb{Eh@Dqgau<|;IF4KUah(`u{P z<{)E313~7<$^>NLPY?oJ4;%Q22bvEaW;QZ`-?loIjj*`8%VE2w3l^C`*l%vcEF zQFtPV(AYVS6!51BTW*CXN#2jKW%uCT4r4;LDsd<7Ka%DtNuWxZ;nM${qgT6~G zM0arjrr=99O48hQ(`vafGQx&l3-K!rZeM#*=s1*V$^rAg)CxSLABS+3BFL}g<(H(6 z$bRrsbTF;PkO3(m?wM936<&8*ixa^b6(At81qSa{T&mnJG27xb*%-OjKN5yxQ}Lr_ zC}6$$f5fV6WU~0Fl7gzRTKCkmh+R0nR>&C0Q)IC5HlsB!b9e3#U_eUw4ddJ-AwgZY z!&f*=27#U$?z2gd+g(f!}YKdeau1uOy%WbcmP1P-Wmz-(wA+ z{oTGIw567)^6LCbG-z8^+O`7=5sO_buQ4i%D-x(P09H6UJj;;;HoubvyMXN9D!~+_ zOR~DN4Bs?p(}MVx0rk7eYA9WF4gAzHj}_C`1W?<^M!>?OS_gt2v(V<|nPOFnI$%B{ z1zZkIAGswpA)p^gVo_KN9|xG3C9zsVnS~c+d4M5|rk*Y;W+9wI<~dlzR*!wb4RWmu z0z^RBQ5xCY)7%j%EVZ8mSH6I+<$)6glKGTxSF_-kz#e;<+8&^kMZ^#?qH@t4sPGpn z6<8MPTqE65n`}m!a&dD9EG0!f&IO(Ym3Xq z2o%Nih8tvHL(Lv)6heU%%q-Qg;w;%OHN--|rqJq~9%C((gm3_Sp9<)+y(yt zDuKwpSjd~7>_aX{Uzd~O8aBnoH#s69aS>r&hs<)|N~RBT@)wbOdY6veTGi*MlZp)5 z%JOp>T}4K1;x@%4rwM8<8(_Ul(V{iC#qL@z*FZW#QjK9%>LN}o7=+B{fhtGw4~Wj2 zm1S?4L>|}}3aN7m?*QhEDy4C zUgDjgS%=K0;$T$xTmU5il;4|}8K5gqSNp?+wdAi5?v&R-+Ef9{Gy=v60Ma+y6$UFt{)k!2t%gaol*-V5h-3&%gEuVXEjmwP zU=3MgaYE71+E$1r?6|GbIwKTPv}oLAO|U5fUN0zk8tNrPD|mxq3xrj`GmXtAGXQC7 zeM$oSh?Ox!%G~!Zxq}5}3be|`ATSnOpvAyhU@BsPW4KXEmn`Ap41~(Sz80nrLNNwV z%B%EIaA>S*&f+(rUGd@{vq_=MYbLZs7bb%e4IpyHDIHH#dFLTE&ybr7(B~6m5g0uH+z@306x;qGQD9ImBBM{z4)!m7MwZ-GL`itqRhLS)xA6!FXr0#X`(Q;k*0SXElu=4+^6OD+q*h$aO+ zKIKZQ(5rZj7Qm6G#B#g?3iB{x-2*Ic-tzf<%Ck__zNTvz<`4q=ms9}=)9w313cspQjl^i8(n`u<{8A!%-#I(ymH|81ow`DPaYlCrKCz27X zN0-FGS+R4UaRUwVdRcP?9tp#i&Cvhnh9T!r0uSZqtmC^mawN zR2dE(ox!(ost6U=K`>J2I*gX-=4e&Ha7ep)WkIZwcPmAd7fftqJFN{_B zk1P}o2b$ccYl4f_{^&l7EPNJo?SzG*$a)i^SXd!f0#M(anW(eq0SzwMI&X$98W$$( z)%Q1E1fsbPn8@Ytx^l6Ii)gJcM58et`hx404lbB<5ZTMhv2`y%E|~Q3D&!0+mKzNU zs{Z9)I_8H26}fgQ#MQtJnP+nf)fGbVp%WrIHe3rtK4+OrgPNtUTo4;nvg6;WdsB37 zr3MR0OFhH`o+Y+aDn@B*ak6f0ZUdotYnens`Fuo(uO%*MDrO?O2$_|;2xtHi-9U_$ zik9dh3Ngtq-k@8E6J7So8WfKs+YwNA(<}Eagubwq@h_mI6-DugUxcsCjrE!?FqKQY z5rzH6+Q7}y{$n%%DZczgJ@X0K2Wu?5s)!`uTli6MhU9bRARz%QR8Tf(3@?W=Vo(6S}3xneT?o`gQjhXlCPMjf;Vs}%*Y0%RV^%GidOL{9r;!^DSjrYa{)7MQj9Kpn6j;eSAz=M z_2vd>mvyD_6eyZFo+?`$UF@(`06QpNZd8;2T!+QxJACxBu#1>nwSo~qF?C{elgCj_ zcT*DUNAi!YmZ4enO#1+dq3WHIkm`dbrxe1}O0V{Yj7{}g9 z`mUfVvvT7|j1NN_3qsct_@JxHXT*H!ySPfqCo;yg_biaQ$KWP47r#9OPvF|i<&;DU zvyb~96r2nf?J0HvzR}wmZCr`~@o|I0kmdITGe|j&;_?lA!T|?FQG{nW+`QB-_mqB! zOou|_q}gCk0)l_xG%+eJN74Juw&_JI<8G`!Hv&X!FnvIX#cj9S+aU6_A@!&4L+lo0CP!Pprgy;QXIz34-n*;0o^lJu3)Jky&^!`tu7rY zeL?F_6)qNuT%$D>|^@#Yc7#51ay9mQ5Th>=L#+f!%1;nv3wjNKI_OWjbM$*7z6+ls0NA(;S zpw?Nq0Sc{rj1rnU6dHY84_K^OS-K`|2W%d4#?1k`?oisGQL*tJSVFoY3COsGC0uZX zR!euqY6Y(Xs0(5@Oc+0upb(;jH}LhcI;Sk^HF$xT;ND79MPJxZo6 z9hpoE+8cPTCtp7r^&eYp*HZ9o$wUBhB3Bp);Wz-?P?p_w3WEf{pb2)x>#1Dbq$ne= zGN)c3Qjq0PKIIZA70DVjVCF3Lbtxe!)AJBMAy-5!&MSF7VqR5%!Z8p*WuxUTv?x_8 zUf@y|IjK)kYXOF{PY{5srNmzm>5^N9(O#e>9qwc3y!Q1{+7)2$sKmljj9-biszXlh z2x2rA)7cV4+J$eXT2qi*dlJ+Wkuy+BL1glIl^{n0x0pGgSas=$>PBTRYn|ma+Xj#v zsFSiJ1A`xvnQFh9WNz>l$|NU+D%nc~F>5Roly-!wp*tl)3@oF<65A;N3Ky=~fD)bD z(auX;p~Td=MdA-D%n;G;JBtsP72TKw2K$I;`KWA(&bJ-YvNH=Kqjgct?W!pxKRA}H z(}Vp*sC}CEP$_NZ;NLWE7REN|ipyvgdwfLaY|JyQ67MVJgMsAUcLqAGt<9R!*!_{5 zlC`vaL_j=+egYdx(Oh;uU|B?=EM8J$6{|Kvt6dI4K9dsxZe8+{7rVrylnOD&9tjT`GkS;BjTX#i#vha53z$P8s=KUsd?&A zpc-=kJR*5W#u1w{Y$U}(u3>hSb*~M=>JNQO0KIvZrG~Y1#6Sk2GXDUOQjjc&7C}%B z2XHNPUJfJ7FQNwn@|6JdRu-b!!ml$q9;6ciyyH+(88F1a@Ie3#Gfp6&iC530q?f~z z#6S{&s)l$3O~W=H<_jor5eY!NvEkbf4~cY7Hv~XbMxaI)m8<*9r2{!D#qkW97LV-2 z(P)CE`k9IfSx7uUtF{!i@Jrb&ruIOnBEnz#m&VEf2T>S|VD3FC!n)6%WsaaSIDTMB zYXZQy+0fi9fD6Jp6oqyfm4tJMhz0pjL(IU5Qcy~YRJ^(F7??de^%U@wkxZ*oukIoD zV~YM}1>m9eU@vlp25thd(jk?5fEsT%1B7l}zr<4US>Am0GNlhJmeUHTR4o20W}j(= z-EJzN%LCXWwdOmid^KgFG%mN|Ty6n(NkZ&;mg2%iw5?_>ZYfE(%tFDB69Z92qM><@ zBB(yvn%jy!9^-|W=2Fbqt%L~A%9@w63&J53Y=ZV^g*t~w2QK42(|OlAvhbG#bs%iLR&dls8}{? z*Ma9gA*$gEkxw4uyQI|r7s=+%17R8SZZ-AkjQD_$w$58f;I9aY->YAm3jDba8z zkVF>M!QuuEE22~hY70!vMx^4tek0q_ZxZjgz_XrEtq-Y#bPRNkphxQVMCPR;ENQr) zSq!@-qGV20fEAgL#puh_9RvqG{KeXohWbL{NYxy~9?;5}jT?CtnNcn5hn&kp7yvz@ z2l%Xo^i59|Y96?Y`m0p4QSyLEMrOj;RFLShSdL?W3}#J{Vm0QglqqL)+#6HP8Gs^6 z6HeApR@EQL2Rqrss1y|? zUUVz!56G!SeIu|#8UZLHXTaUQYpG)NX-pO6iWwVLyhOx?DZj+0X;p>#S;RvMM`TW* z&;Z*UOBTtO;g&!f1yaOz@oWo9;?7TN34+%ZK>q-JcVC&2LI{6i<18E3hwfni01@Zy znV1aKGnMG0(Sa9uY%x)LBxYYbrp*vzG@vn1>@l1b;FHQPTq}N>Ai{WNQdE4=T?sH*21Mcoxpv15CBnMLsde34zyZ5z1E8`OwhKVJqquYz4ye@W)$W2mEt6>P043ZmT5As;Y7Fi9>+EKa?Qz8DVpi zP+?Lr>~U~R+eD75zHu%CX;syFCdDc&v9SC`0^s5uH@F}PHx(}%Y}^u6#8j^kuOmguD%H?i)B>nr%lU&|ZPn-E;l@>cAbPD_ zqMhDm3DH;%dYno&!8=ma?73q>Mzc9O4=B{rqdI_1L5?tS!-6a*ZDT4p9v>3?BISZ1 z4&VVAiVYEGPr#@&g;kvSsK5%ywZHBaNZo%Bf`>yNYUU8B4Uo^=V#Q{V2Z>UOmW7I$ zxL9+kpvr9PxQs$jq<&@t9EAH@hR~aFQ2CZX0`BsAnLpKNk|4sfEday`0@MOn4J2fW zxf@Ir6Jviyp(acff%8znCdZ2P3}Jw8Jxd0*Du-4;?x`I@(g-Nv!%ZV@rOn@(;UN4I z7vU4J+Nw!Oaw!^V^$w(SPAKe@BYM}LX-8!O%H{DkK+Yc(83%0#Q#20%it_XjilrW6 zjqdj>fnkY{yTG69sSWh^8=HA$=i> zNYQMwf{n1q$VzzTX&Sp{Os*O>Rk0!fFs>!YDv{Kn^l0`m3ZU_bwSXCrE2vMYDqd<) zSPi_vSPujR7N-rr5XxxwynBWoR=~VGKxWH5zODk1aW2h8pwI&X0B6dnX4`=IUs35y zit~~oq$Ri>ASMn<3B49XTx#ur;pYwX1jMfL=L@c&x{q8-I}!-l?ir*R*mqpU7T=4q zdkAa+yEo+slAN&JxPgmFr36BJ+Jt;+N^c&1B_4B$ekUYkEqj6ui0g1sc2{@W$aro^ z-pa>NfSiP+zV>T5@?s){(>RXoPXg9~@JD9RMPcgUl-*)4#HTmWc6R}y=+TYLh_$NS z%~ggHy)(^(o4BBZlcalqB1&I>mt7E zQc;C`O?9MxCJWoV%>i=0V`$HSiI-Dm9#~B!tN>{MKH3qU>N;2yN)Nm~$17)vNn3Ag z;ed$gD9PLj>V%fhQq6SaSbagL7l40=MT=ij&B|_7AlM>@v!XpIQvS&ndxSFx;2H&E ziAya7J0KP;tCRafzD@Dw2LWMOd`4+Qw>5rh5aXaU4@?nQInaqIhtT%LFQ#p?(j9gf zD*7d|46ASMQYj^+U7lcvy$gK|s1jRp(~`b_O%#{rHmYeSQ!!TxSCkcGV&n)S9g@xA zxZt3kDwXg?$c^HifXP|ht%`2kP|8EuB!;F-6r zpt|-j=}}DvdPS%ffl|A;GM3dRhNlGA#1|rm1$AS@QS=5Aes9DEr3p~9m}NTw2h7U` z%EV}>T7c5Sruwgx)@m{9PE%2L@hd>0X>o2U1gKs;$3sx1jB*~X4&^Lv9Px>o3ku2I zgU=BL-;5|AIJMx=Vgo`xC&CVH0ZOH^@#+BhXj0zJQ3tNS`XfqGtet41qT|L3tz5fC=1m>)RXrRqCtJQV!%5V0NV zt_s8)1951Y>f2%{4Z9*^0*C>N+2w-FO8)=`0h%>e2Xd-&nTWh8IXUonfX-KnCKY7@ z{*YGLX-(8IcC};-L<}}R5vtT;*|W2WN72A?tfcyaoWHqHE9h-Kz*;l|tWAq_8JQ>+ z4Jn6QQfb0)#Z3h_l(!oF*7!$YskLN|yhKG&v}p=31rf>Rh_aztSBOaTDYw+QQ_dax zA_5(N?poFq(+Ft03u&~!JQC9`QEI(K4if+@LfM+;2n+#mE}kWzq(OkS8BwQwe8z`~@iY13AoqM*)TDd(sHsayxt z-fmDRyQ=0ci#lmE$AO`~w=RB|urGO}n@&k^oS*!vI>4wk@SZJSqlp00N#F zv^$JjoNfUo0^2Ri9xhqgyn3SY$8!K|cQvG4DOcs3l((ptK1C*4RPp27yL}5(SkP=W zUN4AXqM-%(f0<&-D^&2BsEUkX9WFQ@2(Q`9X^)`*ax`3O+hKr+j1lMfwA z7jzUEYVGB?T}s)zG)j?gtg70V$tVJ(y07LAV=7j1Rm#y#)E>)iXog#n8k7K_fS3lmi$`)BgK1fI^D)sfzz8uc;FllH zGQ%KeC2;|GeqYogZ>|~p5y~sgwf4lmU=h=PU^pvD=ju{erC^EX^(_mzOZPo6)qj{Z zK&uUT5DSn_Q40N<1dXy<1U%*8c#}EOe>mx`hO6#5~KyU79;f^zIy@aNiFidF3vm6u+`CE(ZaASArOU$mr|N zHEYB28NeXqz#AUmQmECNM%iW_hda1_8gmkkUwL81r3 z6fhtQT8CC1^DHLoHdj&H?!yer7gj(g!3JdRa6vM%Z5;W;K-A*fhr=iYJOxUVOXkfm z;t5TP;^5iN!JiP6*rYDbr3K~|#pWMO)tcEW00u;|+h8MqTtyt%ab*spg@=QL#C{7@ zj4B<3uwbp3(0_+!z!l%Be67NHwd+5OBi)~!#*9e3O|BKf!sKq)wN z6d}f!h>odS3ct{>X@hJUln-r1O9NL4N~1)s>>3NIly&EeKXBQquUYO}>{ZyjcPPXg zOWD*3-7Y$YhcQ+dfB@!OfdT_QQJ%gFj0;7fF(wucaTG*~Z-|-uN)`!dQm*1Jk+?v< zB~ZcH1Lj-_D6q{+g%CdF{JNlwMCl~i;jzc>5&(c~J6K&L9LGpL8-@U{K-&71P-vlM z*2*&*25aIkaJGqj{?XF6SXlNLBGMj1Fm+JDJS>$xjGFkY2f0o?gGYh3Yj{?b_XaRE zXd{{(u|!*gxHgRnwVoKfai!I9UBM=E0voR|a?;vSa5WUstPEiDGKVc1B@oLqh9?4X z>RmNg&E*rYCE;u8ET_93J|*K6Ej3DztYxwZLE9&tuGsY1x~c_nNXETvz$Wm;<};FlCDcCm;`#s_h^q5PMqZ)3?> z_b`;$n3lK{T+6rAxs+#pK_a%ol^8J7xggLR#3%2}OBW0)PT15G8{% z2BY_FK2I#{Dn(P#Db8#(_?MTB&U~Squ?KPLUu*%LN8$}xQnq81F~X5qam9&-N`<_d zjfEWzBed=-y6nM21CH(#wFP_me<1-dmM|X zoit16gF$5h)Bu2TON1H`6K}Mk0{nsZ8Yo>0Y!v2_4q$U`zNI3PxaUy})=Px`B^*wr1VOMbdH(xw%=?<4HZNck?2tmj;1^*v4-sY zz!mZpadF$W`-($M+ytNj1(lcLA(U*QBhPVE@EKK|VlX}6XUkH8D6qk$64sKSEGv2$ zjkEGNg0*SDafLFm#G-qtm|ssX=Qp&)PF;Wo`g5f^~&0xSq{H=2}_lHx7|T>R=)y`jC>QDjJk0 zI16vYBPwDBQN~lDF1sRehV#J2qlZK8DOgmN)8YatuFGT8Y!}JDF}QKzRBkI-HYkp( zKyh@G!46CSH5>v(<%?^F$58>?Yh>|qkx|K1_XKf+%@9R*67%ea3>BxBn6jXv3d{tA z7zPh;%AuE~mO%kY!d%r^xrtN}bC7}!0-jO1yT>;&jAV*us+~+Q*%7=C2Z$=7$gP(X zKUH!pOh7Po@hq`#0WKQg<}At`Gw7Bl#3@ws1go>gTlX$N(z}lm@WQY@mmY;2(Wp}q zqll9WZPaMvA!Z2S3SIO{woG3&E0IVPYB-{Btwc=$FFi_>RN2kNc~sRE3P76KQ2zii z8hpW@WETy)a`6^|0S4Dng6k*>Lbl4bokSIJ!^BC7rx&SRVM;J{re!zH4`UKq$5{UW zE)PSm2UQ#plyDAeHtdI>?RbeA;i??dFSa#_UGpx!{6m&bM<sdz^RMbMi~8C zV6d^wb7jz>dEBF*F;RaE<006LZMX|=6R~Tfm^eY=IzSFtXe~Bz4wlvfh%{HR(gG-P z0aXCz5{0pb6u!1+6Fdo;h$z6Rg29)6S1OowP=Azujtx>C+m;)>x>ZR*EdUbSD5C?} zneaJ1a~E(qDK5w*Ua!t~GK~Qx#1Li?${oh)F^h>zm2E{ZX*y~>K`5b>UlA`XWefKc zqZ>GDxkYlc5Rn@}xty(FoXccV=yNU|u#H1l7#p=RbG%&E+y3W5K`?gw*Fu(w);#j52_un(H*p}Ll*A!SM;fY_XVefEjX_)n^9o1%wqvddQ7x?TCN+ac{n4bmy>ebjW&!zM*^XMXjUA;D5}yNM&c8ELs?;B zeiM*Fl;^e*N`(Ts5(2nlD6ZH54v=y)c!C1nhDbf4#l}tD$}+-++hXhDI-B4QLJ)vZ zGCcT|opB$H#AJDF&GvJK|~&e!k1AMWo%k&y5?UA!gPEk9V(Wg zxXKv|ZL_%hV9P3$%5RqM+-P*2q3TsSr5K+bu-hpVVZ+paA0Z_VtlLC##b}}{zcT6+ zS)Gfc!8C&DsgF~#C@LOiHKqe&3Taw~NG&yVJ^7Ad2RwHjPewxqy~|caruHzCVQ9Tf zkc`>8xRuF4ZW16n?N`GPnT0&YRS3Fnm}#8A-O7W*oN+gc@3tu?(=#$#sT@QvRrtT`wk`_Ng~>7v`(ofmn_$8!UjRlt>3PR&M%oRg2$QqZ!sQ`XOr86O z#n?Q`iDXgxz<75Y6CR^y5`lC!1rsswAshh0oWLN4J7H<%!OV7%`BYlbYs5l~Br1fp zOSnKRyST`d$;;G6J!u+gZdyT8o9N0ToW-q;DR93iy|*q^#{l}vOjQRv+ByZjG|Z(% z+)%IRfXW6ga3ZtYb9)TEq z#v=*4F_`!^W8{ckD1AzbI0L^-E{;kE1T$3`C73H}4*ijF{seP^riS2Rd#qt_L2{#! z{4P|jR)s^WxD91{Wx^;+ZMIV~jxQGj3!`n+Tv5KRp#_IDHH6-81Y4X+5*Y`Qvfm7=W5xo*2Q>)xF?hC8kp@l-zj2Oefw~|_al^Pg z_zmg;_<%Eh;gToMIYiZ~dWeLp(C5CPp2PAlhzlIq;Na+We7KM5-3xrGFcmJ5~)Gz$yMC=-U}NUIE{by^?_ojjrPH37DEn=uCn zQtdSj00V*`2ndi52zLQ3vcna-BoF`%1Wq7rWyrSaZZrisRhCj$+zxJ7-{Cj4Y75G+ z8zK}l&?suUl)AOb8CDS4nwOYMd0mo`79Lm|zNUm)I`kdzAG| z0HybHBF4aN{-9c}jUY0yg?|W)MI4QwtdWz?%o-A6{{Rq#03k}@@d7L!e_+d;{cT;L zPT`0-_b$K=pP~#MmYtEs!E1KK2{>DEi@Ox01RSI`u_0A4o*|_LSFAr0$M=-0Wi_yd zHJ8F3pxG@bxXALMOiId*7I60q3xbi%1jCY0j!+f3fC|vcO}+&hR46lI&PG>hnJ(Vr zt|o@@4N5NBZJ6|I8K_F4;?7nvZC$IF-~gaN)rSGZ9stF+aX~GWH&TQlA_Aj(0MlBW zEGpp3<4~O9I@-IZEY60`Z*b+1USFA4v;iK4s@9{x1T>;L`X?|8JExzRj6q3aT}xcz zYgEea^fv{l4K_g3#OAZxF8aNLE%g8h=&mA-4ko^HzR`mptRg{ z(F9v|l;BBpN~L?Yq4S*ceqwSapD{p9sA}p^RxnY2aKU8-0n}8PCig3A{6HHDc#0@W z=Q9xCJ2w>~+0AfANwhSvE+LRwAYm61Jo5n>P=g_*E6la~f!bK>a8+Dd#M`K?+bpv5 zfi>_zitM_?yRNhjkx7t|I{cwAg)wHetM8n$V#P-r}c)?kN8<7nZ07KzBcQ-UQ` zcCZ2>2p)GI1RB2L74nMcq+f4PdWDO+hRgVa0f;22b-3CsPJG8Y1y?J9U{b(u6L>Q1 z%@CNQNEz`j06}X(EgH8=a|3V@mCwX)F%`cM80Li-APHZ9W2czCqy0vJylG1iYScH&%76B|32pnQ<(9c=-=FAPXN4V{NulKbDs5yfyL3T}_MQd9)@s^ea0 zxp1Q4z^#cR%{m>$5x7!A#Z`(UoVmkMInWfbT$v^IQ%WlO-75WX~kW{nv zV%;pXCb|U@w!{m)jVxs3h{ky?b;~VHMah0a`b&)ceo>^gM+N%WaC3ca=(4b04x59J zQ61|AZ_%sI`FiGgdEL{xooPea>>sVn$EJFt4UE}da#G$_ggY3c4~2(GX^b>Q1@hwf z)!_@dlAu5*AjTp601v~v!!Y7?gY(2Euf||KS)Y_N zRO&Ag%n-SZ7>M;fu7=im1IK38LV%SrE|u$Kpec(qxB9#w-nSI+vY<#U8L91=$z}aj z2P!Kyb%9w#FNDs(WZtG!WIl4epg`d+S@&yA7pY`dcN4kY8Pvq`dH#8dtc-`ehEuo5 z&>1ay$bUtD6LqI*#NZQ|qMfrmfK&u;9b4L{KN_Vt%womdzmfaNjK0t4g1@;sI}3kQbRr%nhMGMRF% zv7Fu(T*~_*J(&f)NxU`btDw)sAS&G= z81&qrOYrH1`&>vSu0hPhvxr*NH_adThw}<%uLA?q5Q3JchFcLX)1k>qd zr#)C;2{1u|QP{Aa9DA)41np15zUbRp=;8IpdM|F<$tJhb z0=Xq1Z7&HycIaDxH*qe0=9$V{=vt(p=f?g!@1!p>O(I;8+Le@g6nGzU53kUuW{@oI z@7$c&-m4bUstEii1)i4%%`?ng_fB!0@{H4?t8s^DA6ymGwP$aZ|!+E zMzgn)UtFSnf@acReMMdF6SVlO9uEmd7L~>kp9B4>#;nL8wikNUHXWE|v$Qi0o(dJm ztExi<6ehyvMRJeetyV_{W4xr?OYAxGBSB3do!ccVo5tG?x;$4^s=|Q}f7KgBn^He4 zCI0KDqq8mNb5{u#Tqq@*RcH&K3eT<>X3$3SRRdicbKsP80Y(Z~#)o)O>j0X#46(lb zOwB1)o@<>`3Gch~?d7h|)NJ`23&{6Qn9k>aUkRPPu23eH{8V;0&mbP4VX%HePbQ2o zgDvEAq>1hqgWt8BmOl4o7sjOiEans*~U5bA?{kDx^X`AYUj}uP`-j?;e}3 zSEEx8accE%1V&!L#&hd@^FyKCuq=~4Y8S$q-l`JfRT(uhPIKO}+t=ycNTb9$(uUI<*y`E_)3+b7^D$Rjr56*&SA&US>>n6~Q>>q7qmE5uY}lVmf1cz=FwC*jj&Z?tDsw)P{x-E*xi?Xtce1JC|}@UKBUk##8`wQIs94B&^XE3a`005n+h@pAjvo=!o{(T>gDMSG3*Y7ldH256ac6Qm+&4oRtaTgh$DB zWQd)=?%lU`+^af~$N?|EE}GsezG_!uN+OZks;|ETtg*BG0X2Ld$s4hSg)Nr~vp;CK z*Z;Z5o7SBa)m_iHA{S~Iks|@WZ%CSvI7jPj+_$`fxFZrg=$rarAMUfgGcu#UB2z66 z7BSnor{QBrAk4|s(J#;Xby2*Yr_oJyE>+EI{}1DlDEmK6CD5#>CP#)xKFvy4j2iy&1CitKF{eF$q#kQfc$xdpBN-t(utfQKXKP^iNs2{un?*qZ zGSRuCu2}2e@%snCK5_vZiNQ3V#}5O6fuA;N1DGI_AntPjoXq4&$3JZT;ZV`t1ff4npoRB{BjOIkX%Pm z13vL-&owvG0G#Fa_;B8qJLUqAc9XeXb?*ZVXvVA2R^hoWW(}2(Bg!^Shlm~^n5E&8_<<@Y= z#BVsbqtiPqh%K{MHB3?Ga@gA?Y%KpWk9yCfNQ<1a^B>;H1i_jd;O;F zDY)0kPh<+mQ|cpp0WBW(Ytotdu>fp-vxgu~Zv5zRKyl;8~xtZ<#`qr==hH$I>c1EmknM>x9#pUF$@Q_UC%8k z*gMlQloQ_bV6ZOGBI;rS=7T4v=t;jPB;`^4A@Ot4t#7$?EqcTGHovBOJ@v143->Il zGB5WyN4|v^>!&DVUDpl58HyGoh*tON&QjcQ4I0e8`7;nkWXps6`7 zKZh_jXgFm{Pc4WSoSti{mv~X@uJa{Xjd8djt=ENRxhgg+IcWJ({`Fu+Cp^_JVM}Vw zxpNMEfKs;}{pA~K|iT>h;a(}K6W+YdKf<<0j0r8ONivd`Lv$?Lmtej}pFXXEvY zn;N9C7eAJ3f>J-}=jvVHylI~Jqzm?i=}U9Zf3Yg=s_U;r>liir(D%Xgk(OhpbV zSm`F?TyY0xz}vL}3_(X#snqf1sT`AU8IbkQM{)(v?$F;>Lu5mw^zql9Qt?*Bhdkzn zZtC*uSe3bginDQfKb#I6J6@-VI~EjYcqx0#E{u927?PBx5`Vr;lU%t4_~NoR`gr#; zK(L%EOk9vI`a8>`Bcl)h-anWTVKaq~^Ypl08X(^HQ2)VTh~;P;`2AguXPDK0boKcy z2oXm123ODh0qM4F?q0NJ5e^jr=PK1F^jJOuOz(nYbckA!#BJ#f#=CZf5A_iS!sdZa z=)@YIryadu&yr_{{>Q#`Qn0a@iGrc`z3=hfBfD_{)2!@b%jPrcMN;ZQ*PCg(G<5*0 zo-W|zRQ05WBHL-rXCwm|vZ3?41w(>nlOsCY4bvn~Q4gWdk_7k-{4H*0X2BxSl9w@p zrH5N)u|x$htmjQUJg&@D`YrD`l*ffXdk9tMhTE@SJ`g6i+&ZIXmZz*Gi!gc0i&+(} z=xdnrx?t2Y!s5%Kw3ST{k-7 zT1M0xlzR7cCs>7WiSIQQ8vWqtyKpHNUiy%w5w=fVI_wJ0mgpK|j=|iOLaS4WZpq(P zL8IC1$%d`qT3xcO7rWHs z{7gwuMbn7ID34`@R=IbvIPa_}n^;7w#rD+av(T5mv+U`63ug!EsiNj8g!;jA7!g9? zHcwWhD_QhMVbfPG8aVTcO}I9~H<4&{DjZqU)b_NzRJtH1BHs0Mo9+9`s$^!+7ovz7 ztIiuyneFb#Cl)hdSsMG2=ib07uj%(ed0c1U%?dDn&D8?(v5?U^ff9Xh6hjJbAEntc zLOJ>;mSq31tvuu+Qrn^0+d@)gRN%7gf=D8`=wr{ znE9X3pzbq(8WhB;TV*}k-lA5TaTr?HsI_olz>fG)fK+h@$%(Zhs7`o*Ghhz7v-&>G z$^vO~OO(L$a|#JWOW(Z|)XpjFZ~y$s_+ov8_{TwGc@wz!eb|MmoF5uuCz$^Sh-l1P zCNN0Oq=-+T`iKS3=(#2bjWju&;R2s2V{qnbxUS^l&5lQLez zk`;O91$?S9$0Ax{WNWPzsGIKE`l=H7+U4)scSu6&TXsh9w}m3OSIEaSC1Q}Q0n=XR zY5abo-}Y_^fcZ(*t@ZmCBZVYUr>95I%3%z<&n?IIS#v3QfgH!!a~yh_Y_PG5kmCQQdBn6AqSJ?>>KN~S(Z)y+jXh_$bv-14yuiwLTiJ<$B( z*^Uw?z1K+geL#T)?+u*N!e}rFHD(w=yL6{er94w#vhaGhWJ=XWR?n>(5EzdIHMZk?K>21j(J*7CBbg z)2pE~%l^{&3cojXb088v{7}d#+jL*~{x5>F#)PV}ePJDU*I)T#51XSok3a+!%bX(& z(*M1o_t2ChLEcRNh*~Xe8qbo0zWw7gf}w}p;0P9o$!6ZThH*Lx$O z^uAWi)4LGiF9q#vXO5Bo1IsR+TOWLqKau)_b~krGRe~IuVfa$vHd;-1aMO9Qs7Yhx z76mso>*xS~PdMeHXM;(YDE7M4l9uiZ^Ii{R_ytR@#5X#at564Io!1Is9&&$i9F=|a zpY6YeiM+f69Bp{)VWU31!g*69oL5lFG;d0ViT1=$9_UTiwoF{->FKV1APKn)ai zV9=o4;u|3@QP(qTW#WWCpJ1B)(Vlls#g3xk4w?|u;Rof2PPbIIJb)lhy-q{c$rHM} z@#im4O0yo1Mn*_>hL0~x3lB-CwNR2$i@Bz3ZZMVeg2Ix~jws1EVfc4z7O{8l4(WnI z0%_7De6x7pC#9<}?6`a|AG(;=e`s=6GG51D0A!@G|0n4H6zJEQY%_^_LXFsH_uL|D z{Vf!{i0^x5k|EMX$<*shBV#Jm^=`dMCrUI0Fm5-u+cwaDQS(^fjY93uN(kUa3Ysv$M8$t{d?MTctbuLDw)8 z#rz8=5lY5-Df*sv|CVXnH|0K{Zz|Nwe}-qGrtw*}x;s^rp?yVP6nK7fanI{iM@i(F;tSUiL7}#*^qrWYh)olXI>GT9Ue${&*YQ|Z>~7VwizUsFU>jR;^-qGn z3~k0&nLb{KD~q@rzm%aPOd6|-mvb>rdc38CoFCSJ93djF?o;;-cnOoUvz}q zFFDKKkPIBx+95#}uDCio1ss#0#}FX3iFM^vrRa~{P)2Mgb$GOWuT`W_H|_q$;IG0AhgDMT>U zAyCca{eGK&(=XR#UilRqHRg=a%js6u zVQKkJUaHA?ya-(U`PDF1_&<9AUvmqqwOElhngoaB6mpUBJc(ro2sZaJt3G7Wg0kw# zF7A_Q(0O6kX9Y?op6m*(Gv#6l-a!^QPe}$5xP;Ogfu!O;(P9HeV#*GQ>+_jH7?cDN z(^M!}pF7=LPPwSa)-#KI22t`v^XyY=hM$6n_Q00}@vo9f>rcB_ynUXs}V0n~k#qAh=-42tTlDoVojIOf2Xqe{8`CP9R^^{uR$yZ0EhR;`BX==V99 zSHdIZ4)G~PR<#a7jp@Nt(0MH!30NV>lg&HjL9P@i|Al>aPYpockrQV>sU-?^$JJ|& zydV|SS9eZ0)l`#yWS0n?bwU3ik5+N6ipP`Rwy(o%0V_%(0XcX4OZrAaZry^OF&8WOXcA*&oSa zkk|$ANH=H7T@q(NFgZ53)f~^vJ=Y+f>A#FM`|b=17nfTf5sX|w?l;Tu`a6pHTu$IF>uK>)t1|i#zZ8oI^|D)U=nm8>E(U1**u%Tu z47iG3mdk^uDW7H(5enMq9-mbFjAM!NGtPQ>7=xOGI_nm0)bK{Sa z{nl+xW@!Cajgw#P4mL?@H%&x=|4`cI=s2yLCO)$mHnqz?y2}UA!R|vMl;`=yoOA-< zL$p=@A|_#88dAvd-Er736v$0CC3&r^aUXP~sj|pTnRxIJG?h};CT&+#z4!6M>u&e)Ooslg-%T}w&cAo! z#FBR-$PWMYS-lgSA`PjtM1|p!C$%4{-mDD2%EorQn$=@y)W1K$Y(+=Q^Fimdl}MGk?I?PZ@TE;?q{G# zgPu!SV$M2;FEr6EWhOfRPSD@b)?_y%X zE{InWk${fJY#&LSzKPm3>8$pm#pwORlLT#q*FBwdij$BBe*Ea@+~7AF@WXh$A4Vwt zv(>wQ-^9e1#*37$JC&>~rO(HSDOu%<-{U$aaVFQjS)C*5%bF=mZ!%=&-Zd}i2%VXK zNHBhFiUO9Dofz$ryf%3xtpO-$R~czBB1t`Hay}hB{!tH8AhTww^K;f-$qamP40h{h zq;d>^W4iSRHC30_k~lS>xBihQkO6$QKL1M?2AwyVWQ$4lAjDLd$>($yF60}gdUd# zn88&WP)tY-}+I?iT|P? zwgmlR-@lcl5;>(0E6x0lK&op6C9lrh_>DkXCIxWYb9Xhy=JKQ#EluA4?+%?;NT*Yl zUUL@yUGkWn$;DqQ7GTP_!pRxC@)t;r;CRQaJ;6TaTImvSh{9asw93_-0 zoGYyG_JV?jbl?9lC{tt{Uk@f+;1Q46_tvfTfUSEXEpptkDU%y9^v7pQW|@mY zg~GY$J_(0>vT@@l!w6I6NBHj8x13=LpOY0Hr=hGHW=XY=>gJ?8Wtc)gPc2aSUjJP2 zcDLsBZ)WOYv>~}980{iT$>4t!U^v+;+3c74r}7d-k#doEd?wyD14y_kJtAyTzOvr7 z@dGic^YcNQ8{ceSElTv4-Smiallhg%1l`H}pKIO_lh6z}r?~Qx1sVGFVoB~RR!>tR z^`fNObEYvA{G72GhmDF8dPr(Qo)TG#qpUOI-d4(w((jVcI>|oTQXu$ks z*G0hH+Zc&e$&tngh{=@?`{Q_DgQZkC*=Ld-_|5Ag*%V=)e;k1_z~|a;=uSxAg_#S# zBXg=(4e~OBXO2q_Bd~+-Z z_eXR~`mMmS97$R3MZzUDr2OwyZk*AZGPX?}zt- z`8^&IaBkaiWIog-90uVunu<0K(SA^t!FwISoNcTGFm&j?FW^!ccxaYwftRt>RcQQ% zR5uMjGd)b{2ybxWwz*ar+-Fx0p?89d+Om0K30L-H|JEEHvT6%E2yP2uw?zx-4=oA& zoaWs&aJR(0%cBXJO{J&@<%XUhJ^$HmUv#La6aX}V>mMJ?$|s6yizE*eS1v;$PmbmE zopU}XeNN~^Y9l0St6hEwl*aSb&8}t-GMg?bJQ8fJzy229CR|(^tDHI!T{1a*FGaMJ^iH7$m(ad$`#f9c*L$aD6=j zy~9RhWOBI$#};Ks06pUb1&mh3U#h=7U>*Ft>D@{S02ny=y^5({unRN8byZ%n*B2P(s=akn#$A@%IXzMgGcY^80L#~Ql?txS*VEymc^8uEst7jyRFnQ( zKYwEGBE8&)2n|;QjQbg|0q1yEEHQpd$O0+iQL^F%nT_DFcJaK~w*KhJII7BxPndo;Lc69TMz zy51ewM!JKU@xO*qYro36jGj1Vnb6atMM7Hxf0;WzKM$H`n8a+$W5hNM10IGNz-|)(eXHXuW8vG zK^!6ny^=0Td1?t2Jslh0YLRO!o5XCuG-uT3D6~yG{#jQo=BwX)sX%xPr8#T;Fqk$< zYD&z3iUH^EY56JcYrQ^6@5)eB7&=eAY5Net+;Yrj%nMcV{Z2$+63a1(9GdMxRG(?e z%g1*BEO~py)Kq(ZcT!cRVaJ6Q^r1h`fLk=-bQ$cd(y!O1yVNHr&@2MtkOrI_gz(Ms1oZ|jaAJXt*#iK-7GBHK(FjSdPLa^ z4b|}T)e#MLTHkG92~qbI<@nH97a%q1YMjHAzC?d{O;b0Q@VyTZ=9(hYkFwo5j9hM^ zHr%$5M`!q^8B4QIsGX`<#+t|ng4*PtunNw-k)K|q8^8XRqmf-@a!tfHLJ2q!6pLi# z8E2EXPiT^IcI@T8YJ;}S&9dCMCk}k!f~26m5$O5bJX+2<7HlHW!N++G0s zU(*Z>B?$;MvBL*izzI%s0PjTuv@CDpNczbe9HmLFxMNwnGa^(|(d%P{{rdp=_bMYa zPJMNmY@l==A_-)-tB@U^s5X(4B0!x?SEbaMYC#GYj%-5VAat~0-cZt@uBgR1YTEZ+HpH>S})l*hMb9xU#2zR+m$`iZc1_L z0J5q?q%8}wdcze>NU)8WYJYcCMz_~24&%7B|>k;=(zdUo%fG>IB6*pcdEHd>OB;s@Wep10S zTULfHi(~kFj@00?Ojhy#W(mfgzen;`$#exJEw+ptVpwRxJ^CF3$i|R8;8YY(^=tW+4wDP{i$Ck(**8AN9 zwTalN;oy#3%IIH#Dvtksx3%L0u7{~(a`!RsJfb$#ECfeTyxc8|Xo#eQ^Gk(wL40W~2^jjej9{>kj%+CX;F-QeGwHL3@nXHwAl@sb zy6x>1_c6&Hs#cDKpcJFpHDr$_t76u1*k;Nwd)>@3L&{R8-@wW1XG>`2X#UY9!VQxn z2+zZqx}PS;QS=#wP7m{PdAc+OJ*1S^vfGWwtN~jaI!)MDHDx5Q(MjLvzP`PGou zC=n%>%8ZV`n%L|Dwdv5|79h)#lHW!msm(n2)NYAtu!cN2!Sw4nXY?$p=X=eLY5Vb` z+@<7Asca}m2EDGHb7(T7Cj33FM2AHA;Pfu%RKKFMs?TtH3wX=TA%~kqfQ(Pq*En6W z+glxCgO~ZZhDI*nIZ|1FT;}wZ9pH=FsKBPlHv~PzRQ}7#mMM||x-k=&VB;v7v~S+Q z2riU#-9Y}SoD+d|;}hsDjSjRPQjeyLy|g)zBiDqer2~Fqc=` zw6r#mMydN=1?SXpPe-tY%G7k`3R*Djz!%s~?bh%PKP0(|I(rU`JP(wIehZyTIUfD2 z=taugb@Z0wwTT(VD+g8uelHijY=Mubl29)YO@}z^lF?%3@~t4Pd4qQTNnS!h8F;lJ z&8L0R)_)1gv#ez(=Gc`If6Vd&R~l`JRiRAI5;GXSp|08Vc+$D5mJ}RDtZ^@pNG2vs zsn`-wl0exiTn=3FQXTs%5HD;7JW%aE!+7$y%wLahFCX+}1z3)LRWTaXpqo|`7RHD< z8ag6{K$>4{3`IDN<1QT!nmmo5?5xXNuA{#u@g8+`)Dd2SPc`wIG{Dt$Fgg)mrVgct zJ3ieb2B~1nR4Q{FlQo>Ii;FFJ@V!R&0-ee|n|lPg-oTEoZ+$$zBIen0`l2s`2zDq6MXA^7PTfdG4rx%shvkXh2Y?_qR@W{4dqwE@8}BlkJ&&vT zHW@-WUxfs$?VA%kUUa0m6ol|iVl2C%55X&H=d(S~{;5bq$%zBhC!Vzk-W2d$|d5+u8#^DnkH_^*Hudg%jR=p)AEo zt>qc!_8qU6|A-qX((T_Xf*se8-VuP;D+2b5FpAnce~w%oYCcZH>>v8WU|(q!rIIH^ zq+2sDE68(d=`FqZNu}3vD~t1*BAyuqDsiXg)tXwW^pmo;fPStpR!JvFT2N5BR}KTw zQlhPdM*Du0ubz9xSle)@6($5>vRO~P!SFSSV<_a8hn6*ozWRdm_WwfrAt;#ulx;3n z4_a_CFnVWb`dcxFIuNWpG)r(0N8@oa5}%AV<-KS}3bVWD*VmxAFZ>pUl*^MXj)}WT z?EC)zqKkx=xVOve-}NFB6&`cohTeydO4>C_sauqbE6SdWn;3euR%W2{P^Y!Vc1U(X zo(o$18)R0=qLA>RaJ9Cel*aezvmk;77^|rH=Zh=Cv=y3#b&-JlyONmK9LSOoil;B} zN#}>wuXb2V+<(u*-YDmo ztlx3F?D~YQ7!YWd_e>sV+_>0xpo996e@Tcjl!olJ zadbW&iw+`Z%NJGTJMJ8T%C-c+HIzHs3wV$Gw&WKZI!}%dq}DjDB2BKVsLn%8P1=k2 zTAI@8Ze4HZy>jV%+Ji*975A@_lDCcOmBg;ff`112mg{n};A3Q=Z|Yw5Rn=a*6l5He zDjvhqEx7m!7cOq|xOEg&9<74sSQ(1XsUky6UgmK~CYXJYC2@cLiBUSl5t$ef4 z0S`7(h16X7P@`k=nwYCY4V&pKZ2KS6t#wGbWwC^+iI(?{br$*Ob!s|X!42;^NJQTHk|bJo)8QiU>v69 zF+k~KG^woVritrhf$Gq{(#4v9hj;`<6sI zHN`xZuPlpVj)$`4uH{4Pd)2@A8C`#c$@O;kw<*tyep;n$;G}rF5GMaV`qaWYPc2O- z;uB@#w3ZlcH($1wSm$A9FPir!HGit`j=}O4y*B@VKvJ1GB~wV8FqTx}vH;Bf9*1o` zCfh}+Ozz?C&>mEUH%Vm!>nw_2jBAC?&^dk#KRLEnu_DxjWNdz#nrHf z)sH7gCa?ifF(;(Mlclv05ooRuMkol@5&rlf>{wxsHQH-zSG(qV#hKYU2kbg94oRQ` zo@R0F<;8(66*7vpqUUrv6)&lIVxj%yd~5oz8-!&)qc6;bCK-t-z=${d?u9m=XO>ih zy)07+uENyWT2DcqnnkFG{OUV8r#sl_lxKtyGw8HtQ%4qC{sd)oed%7q)V1>>%F>G| zIMLJxVftJ8%UQHayX>uet!8mmvlf4TE#-S{mmov6-{)5%mf5rqK|6FDB32vGbX-fp zOQ+o#FG0a2$A9!>-T5MX?5X(k(6D+-%5LkiW9VmPU`HDG=v0op1E`7!d5E{4?nyJA z+hkptui;8BIm4QU7T!0l`-;`9G0&T+TG5hcqC^5CO@r;Q`d?xTCv=>rkKT1>fQqWa z0!Ls{uFNIDA#Itg8h^g#6kiN;4T1(U_q7U4Y@C{7JUroAVQg=$46$dlct{XW^^J6i zW|VeafmWwAyd|AoSjN~2m6JDM{&@XKHv)$>k4!s6rP-NkMoNYck-`k zwCxYvp4*uL|8U9aEB$wYa-m3k_WLj4sG%{oBD%QEd#E4~?)a~vsl<+K1fAE_3h%-R(2b3Ls@;8<~34w>mRCtK#G%h&&@ehY>a3GxU0$ugn zKAiYfN?a0Apvo^D?q4d~6T^u9msK_V0?@vy_c(NE@|0a&uZB|Lx4fYmXwsq%S#)ic iB#^E=8y;Q)pgczrP8qo8X<8Pk)9R{qZEybH)Bgt=F{XzA literal 0 HcmV?d00001 diff --git a/libraries/RemoteSensor/examples/Repeater/Repeater.ino b/libraries/RemoteSensor/examples/Repeater/Repeater.ino new file mode 100644 index 0000000..1c38105 --- /dev/null +++ b/libraries/RemoteSensor/examples/Repeater/Repeater.ino @@ -0,0 +1,54 @@ +/* + * This sketch simply repeats data received from remote weather sensors made by Cresta. + * + * Setup: + * - connect digital output of a 433MHz receiver to digital pin 2 of Arduino. + * - connect transmitter input of a 433MHz transmitter to digital pin 11 + * - An LED on pin 13 will tell you if and when a signal has been received and transmitted. + */ + +#include +#include + +#define LED_PIN 13 +#define TRANSMITTER_PIN 11 + +void setup() { + pinMode(LED_PIN, OUTPUT); + + // Since we're not instantiating SensorTransmitter, but only use the static methods of SensorTransmitter, + // the pin mode must be set manually. + pinMode(TRANSMITTER_PIN, OUTPUT); + + // When no signal has been received, the LED is lit. + digitalWrite(LED_PIN, HIGH); + + // Init the receiver on interrupt pin 0 (digital pin 2). + // Set the callback to function "retransmit", which is called + // whenever valid sensor data has been received. + SensorReceiver::init(0, retransmit); +} + +void loop() { +} + +void retransmit(byte *data) { + // Data received + + // Wait a second after a receiving. There's little point for decoding and sending the same signal multiple times. + SensorReceiver::disable(); + interrupts(); // delay() requires that interrupts are enabled + delay(1000); + + // Flash LED when transmitting. + digitalWrite(LED_PIN, HIGH); + + // Transmit signal. Note: this is a static method, no object required! + SensorTransmitter::sendPackage(TRANSMITTER_PIN, data); + + digitalWrite(LED_PIN, LOW); + + noInterrupts(); + SensorReceiver::enable(); +} + diff --git a/libraries/RemoteSensor/examples/ThermoHygroReceiver/ThermoHygroReceiver.ino b/libraries/RemoteSensor/examples/ThermoHygroReceiver/ThermoHygroReceiver.ino new file mode 100644 index 0000000..645b073 --- /dev/null +++ b/libraries/RemoteSensor/examples/ThermoHygroReceiver/ThermoHygroReceiver.ino @@ -0,0 +1,54 @@ +/* + * This sketch receives and decodes data from a 433MHz thermo/hygro weather sensor. + * The received data (temperature, humidity, channel) is echo + * + * Setup: + * - Connect digital output of a 433MHz receiver to digital pin 2 of Arduino + * - Enable the serial monitor at 115200 baud. + * + */ + +#include + +void setup() { + Serial.begin(115200); + + // Init the receiver on interrupt pin 0 (digital pin 2). + // Set the callback to function "showTempHumi", which is called + // whenever valid sensor data has been received. + SensorReceiver::init(0, showTempHumi); +} + +void loop() { + // Empty! However, you can do other stuff here if you like. +} + +void showTempHumi(byte *data) { + // is data a ThermoHygro-device? + if ((data[3] & 0x1f) == 0x1e) { + // Yes! + + byte channel, randomId; + int temp; + byte humidity; + + // Decode the data + SensorReceiver::decodeThermoHygro(data, channel, randomId, temp, humidity); + + // Print temperature. Note: temp is 10x the actual temperature! + Serial.print("Temperature: "); + Serial.print(temp / 10); // units + Serial.print('.'); + Serial.print(temp % 10); // decimal + + // Print humidity + Serial.print(" deg, Humidity: "); + Serial.print(humidity); + Serial.print("% REL"); + + // Print channel + Serial.print(", Channel: "); + Serial.println(channel, DEC); + } +} + diff --git a/libraries/RemoteSensor/examples/ThermoHygroTransmitter/ThermoHygroTransmitter.ino b/libraries/RemoteSensor/examples/ThermoHygroTransmitter/ThermoHygroTransmitter.ino new file mode 100644 index 0000000..f0505a0 --- /dev/null +++ b/libraries/RemoteSensor/examples/ThermoHygroTransmitter/ThermoHygroTransmitter.ino @@ -0,0 +1,28 @@ +/* + * This sketch sends (bogus) thermo / hygro data to a remote weather sensors made by Cresta. + * + * Setup: + * - connect transmitter input of a 433MHz transmitter to digital pin 11 + * - On the weather station, activate the "scan" function for channel 1. + */ + + #include + + // Initializes a ThermoHygroTransmitter on pin 11, with "random" ID 0, on channel 1. + ThermoHygroTransmitter transmitter(11, 0, 1); + + void setup() { + } + + void loop() { + // Displays temperatures from -10 degrees Celsius to +20, + // and humidity from 10% REL to 40% REL, with increments of 2 + for (int i = -10; i<=20; i+=2) { + // Temperatures are passed at 10 times the real value, + // to avoid using floating point math. + transmitter.sendTempHumi(i * 10, i + 20); + + // Wait two seconds before sending next. + delay(2000); + } + } diff --git a/libraries/RemoteSensor/keywords.txt b/libraries/RemoteSensor/keywords.txt new file mode 100644 index 0000000..a2cbaf4 --- /dev/null +++ b/libraries/RemoteSensor/keywords.txt @@ -0,0 +1,9 @@ +SensorReceiver KEYWORD1 +init KEYWORD2 +decodeThermoHygro KEYWORD2 +enable KEYWORD2 +disable KEYWORD2 +interruptHandler KEYWORD2 +SensorTransmitter KEYWORD1 +sendPackage KEYWORD2 +ThermoHygroTransmitter KEYWORD1 \ No newline at end of file diff --git a/libraries/RemoteSensor/license.txt b/libraries/RemoteSensor/license.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/libraries/RemoteSensor/license.txt @@ -0,0 +1,674 @@ + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/libraries/RemoteSwitch/README.TXT b/libraries/RemoteSwitch/README.TXT new file mode 100644 index 0000000..02aaccf --- /dev/null +++ b/libraries/RemoteSwitch/README.TXT @@ -0,0 +1,81 @@ +RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0 +Made by Randy Simons http://randysimons.nl/ + +This library provides an easy class for Arduino, to send and receive signals +used by some common "old style" 433MHz remote control switches. + +There are two styles of remote: + - "old style", which uses switches or a dial to set the house code. Use this + library. + - "new style", which use a button on the receivers to "learn" a signal. Use + the NewRemoteSwitch library instead. + +See RemoteTransmitter.h and RemoteReceiver.h for details! + +License: GPLv3. See ./RemoteSwitch/license.txt + +Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino + + +Installation of library: + - Make sure Arduino is closed + - Copy the directory RemoteSwitch to the Arduino library directory (usually + /libraries/) + See http://arduino.cc/en/Guide/Libraries for detailed instructions. + +Default installation sender & demo: + - Connect tha data-in-pin of a 433MHz transmitter to digital pin 11. See + docs/hardware setup.jpg. + (Note: your hardware may have a different pin configuration!) + - Start Arduino, and open the example: File -> Examples -> RemoteSwitch -> + LightShow + - Alter addresses/devices to reflect your own setup. Otherwise nothing will + happen. + - Compile, upload and run! + +Default installation receiver & demo: + - Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo. + (Note: your hardware may have a different pin configuration!) + - Start Arduino, and open the example: File -> Examples -> RemoteSwitch -> + ShowReceivedCode or ShowReceivedCodeNewKaku, depending on your remote. + - Compile, upload and run + - Open serial monitor in Arduino (115200 baud) + - Press buttons on a 433MHz-remote, and watch the serial monitor + +Notes: + - These transmitters often use the PT2262 IC, or equivalent. For details about + the waveforms used by these remotes, the datasheet of the PT2262 is provided. + Page 4 and 5 will be of most interest. + + +Changelog: +RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0 + - Improved reception quality by filtering too short pulses. + - Dropped pre-v1.0 Arduino support. + - Added RemoteReceiver::deinit() + +RemoteSwitch library v2.2.1 (20120314) for Arduino 0022/1.0 + - Fixed Elro code, it caused memory corruption. + - Renamed old-style .pde files to new-style .ino + +RemoteSwitch library v2.2.0 (20120213) for Arduino 0022/1.0 + - Added support for Elro switches (http://www.elro.eu/en/m/products/category/home_automation/home_control) + (untested; I don't have these kind of devices) + - Allowed the number of repeated signals transmitted by RemoteTransmitter to be + changed. + - By default, 16 instead of 8 repeats are sent. + - Support for Arduino 1.0. + - Added Datasheet PT2262, which (or equivalent) is often used in the transmitters. + - RemoteReceiver::isReceiving timeout changed to 150ms; 100ms was too short. + +RemoteSwitch library v2.1.1 (20110920) for Arduino 0022 + - Improved RemoteReceiver::isReceiving + +RemoteSwitch library v2.1.0 (20110919) for Arduino 0022 + - Changed classnames from *Switch to *Transmitter + - Added RemoteTransmitter::sendCode. See example "retransmitter". + - RemoteReceiver::interruptHandler() is now public, for use with InterruptChain + +RemoteSwitch library v2.0.0 (20100130) for Arduino 0017 + - Complete rewrite; can now receive and decode signals directly from + the receiver's digital out. \ No newline at end of file diff --git a/libraries/RemoteSwitch/RemoteReceiver.cpp b/libraries/RemoteSwitch/RemoteReceiver.cpp new file mode 100644 index 0000000..fe5421f --- /dev/null +++ b/libraries/RemoteSwitch/RemoteReceiver.cpp @@ -0,0 +1,193 @@ +/* + * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ + * See RemoteReceiver.h for details. + * + * License: GPLv3. See license.txt + */ + +#include "RemoteReceiver.h" + + +/************ +* RemoteReceiver +************/ + +int8_t RemoteReceiver::_interrupt; +volatile int8_t RemoteReceiver::_state; +byte RemoteReceiver::_minRepeats; +RemoteReceiverCallBack RemoteReceiver::_callback; +boolean RemoteReceiver::_inCallback = false; +boolean RemoteReceiver::_enabled = false; + +void RemoteReceiver::init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback) { + _interrupt = interrupt; + _minRepeats = minRepeats; + _callback = callback; + + enable(); + if (_interrupt >= 0) { + attachInterrupt(_interrupt, interruptHandler, CHANGE); + } +} + +void RemoteReceiver::enable() { + _state = -1; + _enabled = true; +} + +void RemoteReceiver::disable() { + _enabled = false; +} + +void RemoteReceiver::deinit() { + _enabled = false; + if (_interrupt >= 0) { + detachInterrupt(_interrupt); + } +} + +void RemoteReceiver::interruptHandler() { + if (!_enabled) { + return; + } + + static unsigned int period; // Calculated duration of 1 period + static byte receivedBit; // Contains "bit" currently receiving + static unsigned long receivedCode; // Contains received code + static unsigned long previousCode; // Contains previous received code + static byte repeats = 0; // The number of times the an identical code is received in a row. + static unsigned long edgeTimeStamp[3] = {0, }; // Timestamp of edges + static unsigned int min1Period, max1Period, min3Period, max3Period; + static bool skip; + + // Filter out too short pulses. This method works as a low pass filter. + edgeTimeStamp[1] = edgeTimeStamp[2]; + edgeTimeStamp[2] = micros(); + + if (skip) { + skip = false; + return; + } + + if (_state >= 0 && edgeTimeStamp[2]-edgeTimeStamp[1] < min1Period) { + // Last edge was too short. + // Skip this edge, and the next too. + skip = true; + return; + } + + unsigned int duration = edgeTimeStamp[1] - edgeTimeStamp[0]; + edgeTimeStamp[0] = edgeTimeStamp[1]; + + // Note that if state>=0, duration is always >= 1 period. + + if (_state==-1) { // Waiting for sync-signal + if (duration>3720) { // =31*120 minimal time between two edges before decoding starts. + // Sync signal received.. Preparing for decoding + period=duration/31; + receivedCode=previousCode=repeats=0; + + // Allow for large error-margin. ElCheapo-hardware :( + min1Period=period*4/10; // Avoid floating point math; saves memory. + max1Period=period*16/10; + min3Period=period*23/10; + max3Period=period*37/10; + } + else { + return; + } + } else if (_state<48) { // Decoding message + receivedBit <<= 1; + + // bit part durations can ONLY be 1 or 3 periods. + if (duration<=max1Period) { + receivedBit &= B1110; // Clear LSB of receivedBit + } + else if (duration>=min3Period && duration<=max3Period) { + receivedBit |= B1; // Set LSB of receivedBit + } + else { // Otherwise the entire sequence is invalid + _state=-1; + return; + } + + if ((_state%4)==3) { // Last bit part? + // Shift + receivedCode*=3; + + // Only 4 LSB's are used; trim the rest. + switch (receivedBit & B1111) { + case B0101: // short long short long == B0101 + // bit "0" received + receivedCode+=0; // I hope the optimizer handles this ;) + break; + case B1010: // long short long short == B1010 + // bit "1" received + receivedCode+=1; + break; + case B0110: // short long long short + // bit "f" received + receivedCode+=2; + break; + default: + // Bit was rubbish. Abort. + _state=-1; + return; + } + } + } else if (_state==48) { // Waiting for sync bit part 1 + // Must be 1 period. + if (duration>max1Period) { + _state=-1; + return; + } + } else { // Waiting for sync bit part 2 + // Must be 31 periods. + if (durationperiod*36) { + _state=-1; + return; + } + + // receivedCode is a valid code! + + if (receivedCode!=previousCode) { + repeats=0; + previousCode=receivedCode; + } + + repeats++; + + if (repeats>=_minRepeats) { + if (!_inCallback) { + _inCallback = true; + (_callback)(receivedCode, period); + _inCallback = false; + } + // Reset after callback. + _state=-1; + return; + } + + // Reset for next round + receivedCode = 0; + _state=0; // no need to wait for another sync-bit! + return; + } + + _state++; + return; +} + +boolean RemoteReceiver::isReceiving(int waitMillis) { + unsigned long startTime=millis(); + + int waited; // Signed int! + do { + if (_state == 48) { // Abort if a valid code has been received in the mean time + return true; + } + waited = (millis()-startTime); + } while(waited>=0 && waited <= waitMillis); // Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time. + + return false; +} diff --git a/libraries/RemoteSwitch/RemoteReceiver.h b/libraries/RemoteSwitch/RemoteReceiver.h new file mode 100644 index 0000000..f965d9e --- /dev/null +++ b/libraries/RemoteSwitch/RemoteReceiver.h @@ -0,0 +1,88 @@ +/* + * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ + * + * License: GPLv3. See license.txt + */ + +#ifndef RemoteReceiver_h +#define RemoteReceiver_h + +#include + +typedef void (*RemoteReceiverCallBack)(unsigned long, unsigned int); + +/** +* See RemoteSwitch for introduction. +* +* RemoteReceiver decodes the signal received from a 433MHz-receiver, like the "KlikAanKlikUit"-system +* as well as the signal sent by the RemoteSwtich class. When a correct signal is received, +* a user-defined callback function is called. +* +* Note that in the callback function, the interrupts are still disabled. You can enabled them, if needed. +* A call to the callback must b finished before RemoteReceiver will call the callback function again, thus +* there is no re-entrant problem. +* +* When sending your own code using RemoteSwich, disable() the receiver first. +* +* This is a pure static class, for simplicity and to limit memory-use. +*/ + +class RemoteReceiver { + public: + /** + * Initializes the decoder. + * + * If interrupt >= 0, init will register pin to this library. + * If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler() + * yourself whenever the output of the receiver changes, or you can use InterruptChain. + * + * @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details. + If < 0, you must call interruptHandler() yourself. + * @param minRepeats The number of times the same code must be received in a row before the callback is calles + * @param callback Pointer to a callback function, with signature void (*func)(unsigned long, unsigned int). First parameter is the decoded data, the second the period of the timing. + */ + static void init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback); + + /** + * Enable decoding. No need to call enable() after init(). + */ + static void enable(); + + /** + * Disable decoding. You can re-enable decoding by calling enable(); + */ + static void disable(); + + /** + * Deinitializes the decoder. Disables decoding and detaches the interrupt handler. If you want to + * re-enable decoding, call init() again. + */ + static void deinit(); + + /** + * Tells wether a signal is being received. If a compatible signal is detected within the time out, isReceiving returns true. + * Since it makes no sense to transmit while another transmitter is active, it's best to wait for isReceiving() to false. + * By default it waits for 150ms, in which a (relative slow) KaKu signal can be broadcasted three times. + * + * Note: isReceiving() depends on interrupts enabled. Thus, when disabled()'ed, or when interrupts are disabled (as is + * the case in the callback), isReceiving() will not work properly. + * + * @param waitMillis number of milliseconds to monitor for signal. + * @return boolean If after waitMillis no signal was being processed, returns false. If before expiration a signal was being processed, returns true. + */ + static boolean isReceiving(int waitMillis = 150); + + static void interruptHandler(); + + private: + + static int8_t _interrupt; // Radio input interrupt + volatile static int8_t _state; // State of decoding process. There are 49 states, 1 for "waiting for signal" and 48 for decoding the 48 edges in a valid code. + static byte _minRepeats; + static RemoteReceiverCallBack _callback; + static boolean _inCallback; // When true, the callback function is being executed; prevents re-entrance. + static boolean _enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately. + +}; + +#endif diff --git a/libraries/RemoteSwitch/RemoteTransmitter.cpp b/libraries/RemoteSwitch/RemoteTransmitter.cpp new file mode 100644 index 0000000..648b5a8 --- /dev/null +++ b/libraries/RemoteSwitch/RemoteTransmitter.cpp @@ -0,0 +1,306 @@ +/* + * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ + * See RemoteTransmitter.h for details. + * + * License: GPLv3. See license.txt + */ + +#include "RemoteTransmitter.h" + + +/************ +* RemoteTransmitter +************/ + +RemoteTransmitter::RemoteTransmitter(byte pin, unsigned int periodusec, byte repeats) { + _pin=pin; + _periodusec=periodusec; + _repeats=repeats; + + pinMode(_pin, OUTPUT); +} + +unsigned long RemoteTransmitter::encodeTelegram(byte trits[]) { + unsigned long data = 0; + + // Encode data + for (byte i=0;i<12;i++) { + data*=3; + data+=trits[i]; + } + + // Encode period duration + data |= (unsigned long)_periodusec << 23; + + // Encode repeats + data |= (unsigned long)_repeats << 20; + + return data; +} + +void RemoteTransmitter::sendTelegram(byte trits[]) { + sendTelegram(encodeTelegram(trits),_pin); +} + +/** +* Format data: +* pppppppp|prrrdddd|dddddddd|dddddddd (32 bit) +* p = perioud (9 bit unsigned int +* r = repeats as 2log. Thus, if r = 3, then signal is sent 2^3=8 times +* d = data +*/ +void RemoteTransmitter::sendTelegram(unsigned long data, byte pin) { + unsigned int periodusec = (unsigned long)data >> 23; + byte repeats = ((unsigned long)data >> 20) & B111; + + sendCode(pin, data, periodusec, repeats); +} + +void RemoteTransmitter::sendCode(byte pin, unsigned long code, unsigned int periodusec, byte repeats) { + code &= 0xfffff; // Truncate to 20 bit ; + // Convert the base3-code to base4, to avoid lengthy calculations when transmitting.. Messes op timings. + // Also note this swaps endianess in the process. The MSB must be transmitted first, but is converted to + // LSB here. This is easier when actually transmitting later on. + unsigned long dataBase4 = 0; + + for (byte i=0; i<12; i++) { + dataBase4<<=2; + dataBase4|=(code%3); + code/=3; + } + + repeats = 1 << (repeats & B111); // repeats := 2^repeats; + + for (byte j=0;j>=2; + } + + // Send termination/synchronization-signal. Total length: 32 periods + digitalWrite(pin, HIGH); + delayMicroseconds(periodusec); + digitalWrite(pin, LOW); + delayMicroseconds(periodusec*31); + } +} + +boolean RemoteTransmitter::isSameCode(unsigned long encodedTelegram, unsigned long receivedData) { + return (receivedData==(encodedTelegram & 0xFFFFF)); // compare the 20 LSB's +} + + +/************ +* ActionTransmitter +************/ + +ActionTransmitter::ActionTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) { + // Call constructor +} + + +void ActionTransmitter::sendSignal(byte systemCode, char device, boolean on) { + sendTelegram(getTelegram(systemCode,device,on), _pin); +} + +unsigned long ActionTransmitter::getTelegram(byte systemCode, char device, boolean on) { + byte trits[12]; + + device-=65; + + for (byte i=0; i<5; i++) { + // Trits 0-4 contain address (2^5=32 addresses) + trits[i]=(systemCode & 1)?1:2; + systemCode>>=1; + + // Trits 5-9 contain device. Only one trit has value 0, others have 2 (float)! + trits[i+5]=(i==device?0:2); + } + + // Switch on or off + trits[10]=(!on?0:2); + trits[11]=(on?0:2); + + return encodeTelegram(trits); +} + +/************ +* BlokkerTransmitter +************/ + +BlokkerTransmitter::BlokkerTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) { + // Call constructor +} + + +void BlokkerTransmitter::sendSignal(byte device, boolean on) { + sendTelegram(getTelegram(device,on), _pin); +} + +unsigned long BlokkerTransmitter::getTelegram(byte device, boolean on) { + byte trits[12]={0}; + + device--; + + for (byte i=1; i<4; i++) { + // Trits 1-3 contain device + trits[i]=(device & 1)?0:1; + device>>=1; + } + + // Switch on or off + trits[8]=(on?1:0); + + return encodeTelegram(trits); +} + +/************ +* KaKuTransmitter +************/ + +KaKuTransmitter::KaKuTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) { + // Call constructor +} + +void KaKuTransmitter::sendSignal(char address, byte device, boolean on) { + sendTelegram(getTelegram(address, device, on), _pin); +} + +unsigned long KaKuTransmitter::getTelegram(char address, byte device, boolean on) { + byte trits[12]; + + address-=65; + device-=1; + + for (byte i=0; i<4; i++) { + // Trits 0-3 contain address (2^4 = 16 addresses) + trits[i]=(address & 1)?2:0; + address>>=1; + + // Trits 4-8 contain device (2^4 = 16 addresses) + trits[i+4]=(device & 1)?2:0; + device>>=1; + } + + // Trits 8-10 seem to be fixed + trits[8]=0; + trits[9]=2; + trits[10]=2; + + // Switch on or off + trits[11]=(on?2:0); + + return encodeTelegram(trits); +} + +void KaKuTransmitter::sendSignal(char address, byte group, byte device, boolean on) { + (void)device; + sendTelegram(getTelegram(address, group, on), _pin); +} + +unsigned long KaKuTransmitter::getTelegram(char address, byte group, byte device, boolean on) { + byte trits[12], i; + + address-=65; + group-=1; + device-=1; + + // Address. M3E Pin A0-A3 + for (i=0; i<4; i++) { + // Trits 0-3 contain address (2^4 = 16 addresses) + trits[i]=(address & 1)?2:0; + address>>=1; + } + + // Device. M3E Pin A4-A5 + for (; i<6; i++) { + trits[i]=(device & 1)?2:0; + device>>=1; + } + + // Group. M3E Pin A6-A7 + for (; i<8; i++) { + trits[i]=(group & 1)?2:0; + group>>=1; + } + + // Trits 8-10 are be fixed. M3E Pin A8/D0-A10/D2 + trits[8]=0; + trits[9]=2; + trits[10]=2; + + // Switch on or off, M3E Pin A11/D3 + trits[11]=(on?2:0); + + return encodeTelegram(trits); +} + + +/************ +* ElroTransmitter +************/ + +ElroTransmitter::ElroTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin, periodusec, repeats) { + //Call constructor +} + +void ElroTransmitter::sendSignal(byte systemCode, char device, boolean on) { + sendTelegram(getTelegram(systemCode, device, on), _pin); +} + +unsigned long ElroTransmitter::getTelegram(byte systemCode, char device, boolean on) { + byte trits[12]; + + device-=65; + + for (byte i=0; i<5; i++) { + //trits 0-4 contain address (2^5=32 addresses) + trits[i]=(systemCode & 1)?0:2; + systemCode>>=1; + + //trits 5-9 contain device. Only one trit has value 0, others have 2 (float)! + trits[i+5]=(i==device?0:2); + } + + //switch on or off + trits[10]=(on?0:2); + trits[11]=(!on?0:2); + + return encodeTelegram(trits); +} diff --git a/libraries/RemoteSwitch/RemoteTransmitter.h b/libraries/RemoteSwitch/RemoteTransmitter.h new file mode 100644 index 0000000..4916e6c --- /dev/null +++ b/libraries/RemoteSwitch/RemoteTransmitter.h @@ -0,0 +1,249 @@ +/* + * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ + * + * License: GPLv3. See license.txt + */ + +#ifndef RemoteTransmitter_h +#define RemoteTransmitter_h + +#include + +/** +* RemoteTransmitter provides a generic class for simulation of common RF remote controls, like the 'Klik aan Klik uit'-system +* (http://www.klikaanklikuit.nl/), used to remotely switch lights etc. +* +* Many of these remotes seem to use a 433MHz SAW resonator and one of these chips: LP801B, HX2262, PT2262, M3E. +* Datasheet for the HX2262/PT2262 ICs: +* http://www.princeton.com.tw/downloadprocess/downloadfile.asp?mydownload=PT2262_1.pdf +* +* Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g. +* http://www.sparkfun.com/products/10534 +* http://www.conrad.nl/goto/?product=130428 +* +* Notes: +* - Since these chips use (and send!) tri-state inputs (low, high and floating) I use 'trits' instead of 'bits', +* when appropriate. +* - I measured the period lengths with a scope. Thus: they work for my remotes, but may fail for yours... +* A better way would be to calculate the 'target'-timings using the datasheets and the resistor-values on the remotes. +*/ +class RemoteTransmitter { + public: + /** + * Constructor. + * + * To obtain the correct period length, an oscilloscope is convenient, but you can also read the + * datasheet of the transmitter, measure the resistor for the oscillator and calculate the frequency. + * + * @param pin output pin on Arduino to which the transmitter is connected + * @param periodusec [0..511] Duration of one period, in microseconds. A trit is 6 periods. + * @param repeats [0..7] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust. + */ + RemoteTransmitter(byte pin, unsigned int periodusec, byte repeats); + + /** + * Encodes the data base on the current object and the given trits. The data can be reused, e.g. + * for use with the static version of sendTelegram, so you won't need to instantiate costly objects! + * + * @return The data suited for use with RemoteTransmitter::sendTelegram. + */ + unsigned long encodeTelegram(byte trits[]); + + /** + * Send a telegram, including synchronization-part. + * + * @param trits Array of size 12. "trits" should be either 0, 1 or 2, where 2 indicates "float" + */ + void sendTelegram(byte trits[]); + + /** + * Send a telegram, including synchronization-part. The data-param encodes the period duration, number of repeats and the actual data. + * Note: static method, which allows for use in low-mem situations. + * + * Format data: + * pppppppp|prrrdddd|dddddddd|dddddddd (32 bit) + * p = period (9 bit unsigned integer) + * r = repeats as 2log. Thus, if r = 3, then signal is sent 2^3=8 times + * d = data + * + * @param data data, period and repeats. + * @param pin Pin number of the transmitter. + */ + static void sendTelegram(unsigned long data, byte pin); + + /** + * The complement of RemoteReceiver. Send a telegram with specified code as data. + * + * Note: static method, which allows for use in low-mem situations. + * + * @param pin output pin on Arduino to which the transmitter is connected + * @param periodusec [0..511] Duration of one period, in microseconds. A trit is 6 periods. + * @param repeats [0..7] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust. + * @param code The code to transmit. Note: only the first 20 bits are used, the rest is ignored. Also see sendTelegram. + */ + static void sendCode(byte pin, unsigned long code, unsigned int periodusec, byte repeats); + + /** + * Compares the data received with RemoteReceive with the data obtained by one of the getTelegram-functions. + * Period duration and repetitions are ignored by this function; only the data-payload is compared. + * + * @return true, if the codes are identical (the 20 least significant bits match) + */ + static boolean isSameCode(unsigned long encodedTelegram, unsigned long receivedData); + + protected: + byte _pin; // Transmitter output pin + unsigned int _periodusec; // Oscillator period in microseconds + byte _repeats; // Number over repetitions of one telegram +}; + +/** +* ActionTransmitter simulates a remote, as sold in the Dutch 'Action' stores. But there are many similar systems on the market. +* If your remote has setting for 5 address bits, and can control 5 devices on or off, then you can try to use the ActionTransmitter. +* Otherwise you may have luck with the ElroTransmitter, which is similar. +*/ +class ActionTransmitter: RemoteTransmitter { + public: + /** + * Constructor + * + * @param pin output pin on Arduino to which the transmitter is connected + * @param periodsec Duration of one period, in microseconds. Default is 190usec + * @param repeats [0..7] The 2log-Number of times the signal is repeated. + * @see RemoteTransmitter + */ + ActionTransmitter(byte pin, unsigned int periodusec=190, byte repeats=4); + + /** + * Send a on or off signal to a device. + * + * @param systemCode 5-bit address (dip switches in remote). Range [0..31] + * @param device Device to switch. Range: [A..E] (case sensitive!) + * @param on True, to switch on. False to switch off, + */ + void sendSignal(byte systemCode, char device, boolean on); + + /** + * Generates the telegram (data) which can be used for RemoteTransmitter::sendTelegram. + * See sendSignal for details on the parameters + * + * @return Encoded data, including repeats and period duration. + */ + unsigned long getTelegram(byte systemCode, char device, boolean on); +}; + +/** +* BlokkerTransmitter simulates a remote, as sold in the Dutch 'Blokker' stores. But there are many similar systems on the market. +* These remotes have 4 on, 4 off buttons and a switch to switch between device 1-4 and 5-8. No further configuration +* possible. +*/ +class BlokkerTransmitter: RemoteTransmitter { + public: + /** + * Constructor + * + * @param pin output pin on Arduino to which the transmitter is connected + * @param periodsec Duration of one period, in microseconds. Default is 307usec + * @param repeats [0..7] The 2log-Number of times the signal is repeated. + * @see RemoteTransmitter + */ + BlokkerTransmitter(byte pin, unsigned int periodusec=230, byte repeats=4); + + /** + * Send a on or off signal to a device. + * + * @param device Device to switch. Range: [1..8] + * @param on True, to switch on. False to switch off, + */ + void sendSignal(byte device, boolean on); + + /** + * @see RemoteTransmitter::getTelegram + */ + unsigned long getTelegram(byte device, boolean on); +}; + +/** +* KaKuTransmitter simulates a KlikAanKlikUit-remote, but there are many clones. +* If your transmitter has a address dial with the characters A till P, you can try this class. +*/ +class KaKuTransmitter: RemoteTransmitter { + public: + /** + * Constructor + * + * @param pin output pin on Arduino to which the transmitter is connected + * @param periodsec Duration of one period, in microseconds. Default is 375usec + * @param repeats [0..7] The 2log-Number of times the signal is repeated. + * @see RemoteTransmitter + */ + KaKuTransmitter(byte pin, unsigned int periodusec=375, byte repeats=4); + + /** + * Send a on or off signal to a device. + * + * @param address address (dial switches in remote). Range [A..P] (case sensitive!) + * @param group Group to switch. Range: [1..4] + * @param device Device to switch. Range: [1..4] + * @param on True, to switch on. False to switch off, + */ + void sendSignal(char address, byte group, byte device, boolean on); + + /** + * Send a on or off signal to a device. + * + * @param address address (dip switches in remote). Range [A..P] (case sensitive!) + * @param device device (dial switches in remote). Range [1..16] + * @param on True, to switch on. False to switch off, + */ + void sendSignal(char address, byte device, boolean on); + + /** + * @see RemoteTransmitter::getTelegram + */ + unsigned long getTelegram(char address, byte group, byte device, boolean on); + + /** + * @see RemoteTransmitter::getTelegram + */ + unsigned long getTelegram(char address, byte device, boolean on); +}; + +/** +* ElroTransmitter simulates remotes of the Elro "Home Control" series +* see http://www.elro.eu/en/m/products/category/home_automation/home_control +* There are are many similar systems on the market. If your remote has setting for 5 address bits, and can control +* 4 devices on or off, then you can try to use the ElroTransmitter. Otherwise you may have luck with the +* ActionTransmitter, which is similar. +*/ +class ElroTransmitter: RemoteTransmitter { + public: + /** + * Constructor + * + * @param pin output pin on Arduino to which the transmitter is connected + * @param periodsec Duration of one period, in microseconds. Default is 320usec + * @param repeats [0..7] The 2log-Number of times the signal is repeated. + * @see RemoteSwitch + */ + ElroTransmitter(byte pin, unsigned int periodusec=320, byte repeats=4); + + /** + * Send a on or off signal to a device. + * + * @param systemCode 5-bit address (dip switches in remote). Range [0..31] + * @param device Device to switch. Range: [A..D] (case sensitive!) + * @param on True, to switch on. False to switch off, + */ + void sendSignal(byte systemCode, char device, boolean on); + + /** + * Generates the telegram (data) which can be used for RemoteSwitch::sendTelegram. + * See sendSignal for details on the parameters + * + * @return Encoded data, including repeats and period duration. + */ + unsigned long getTelegram(byte systemCode, char device, boolean on); +}; + +#endif diff --git a/libraries/RemoteSwitch/docs/Datasheet PT2262 (encoder for transmitter).pdf b/libraries/RemoteSwitch/docs/Datasheet PT2262 (encoder for transmitter).pdf new file mode 100644 index 0000000000000000000000000000000000000000..f5d27709711e11a7c85f88614242b77ccf058530 GIT binary patch literal 602722 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

e-Vn(i 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�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

|OpYwSrV;55<2?EzCXHM_^AI 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⩔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%0AdUzN1-(er_@4 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%0D?wKxCk~EpKvx~IB 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�Qxg%Uw&-*G}cIx)@OT*fb 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

8JgHbM9E6x_L5&mnPIDiVXVc9)4?=@J;AeO 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 literal 0 HcmV?d00001 diff --git a/libraries/RemoteSwitch/examples/LightShow/LightShow.ino b/libraries/RemoteSwitch/examples/LightShow/LightShow.ino new file mode 100644 index 0000000..f52f969 --- /dev/null +++ b/libraries/RemoteSwitch/examples/LightShow/LightShow.ino @@ -0,0 +1,63 @@ +/* +* Demo for RF remote switch transmitter. +* For details, see RemoteTransmitter.h! +* +* This sketch switches some devices on and off in a loop. +* +* Setup: +* - Connect a 433MHz transmitter to digital pin 11. +*/ + +#include + +// Intantiate a new ActionTransmitter remote, use pin 11 +ActionTransmitter actionTransmitter(11); + +// Intantiate a new KaKuTransmitter remote, also use pin 11 (same transmitter!) +KaKuTransmitter kaKuTransmitter(11); + +// Intantiate a new Blokker remote, also use pin 11 (same transmitter!) +BlokkerTransmitter blokkerTransmitter(11); + +// Intantiate a new Elro remote, also use pin 11 (same transmitter!) +ElroTransmitter elroTransmitter(11); + + +void setup() { +} + +void loop() { + // Switch off KaKu-device 10 on address M + kaKuTransmitter.sendSignal('M',10,false); + + // Switch on Action-device B on system code 1. + actionTransmitter.sendSignal(1,'B',true); + + // Switch on Blokker-device 7. + blokkerTransmitter.sendSignal(7,true); + + // Switch on Elro-device C on system code 1. + elroTransmitter.sendSignal(1,'C',true); + + + // Wait 2 seconds + delay(2000); + + + + // Switch on KaKu-device 2 of group 3 on address M (which is the same as device 10 on address M!) + kaKuTransmitter.sendSignal('M',3,2,true); + + // Switch off Action-device B on system code 1. + actionTransmitter.sendSignal(1,'B',false); + + // Switch off Blokker-device 7. + blokkerTransmitter.sendSignal(7,false); + + // Switch off Elro-device C on system code 1. + elroTransmitter.sendSignal(1,'C',false); + + + // Wait 4 seconds + delay(4000); +} diff --git a/libraries/RemoteSwitch/examples/RemoteTranslator/RemoteTranslator.ino b/libraries/RemoteSwitch/examples/RemoteTranslator/RemoteTranslator.ino new file mode 100644 index 0000000..d29eed6 --- /dev/null +++ b/libraries/RemoteSwitch/examples/RemoteTranslator/RemoteTranslator.ino @@ -0,0 +1,58 @@ +/* +* Demo for RF remote switch receiver. +* For details, see RemoteReceiver.h! +* +* This sketch "translates" an Action-remote to a Blokker-remote. +* When the A-On-button of the Action-remote is pressed, the Blokker-devices +* 5, 6 and 7 are switched on. The A-Off-button switches the devices off again. +* +* Connect the transmitter to digital pin 11, and the receiver to digital pin 2. +*/ + +#include +#include + +ActionTransmitter actionTransmitter(11); +BlokkerTransmitter blokkerTransmitter(11); + +// Prepare the code for switch A (system code 1) on and off, for easy comparision later. +unsigned long actionAOn = actionTransmitter.getTelegram(1,'A',true); +unsigned long actionAOff = actionTransmitter.getTelegram(1,'A',false); + +void setup() { + // See example Show_received_code for info on this + RemoteReceiver::init(0, 3, translateCode); +} + +void loop() { +} + +// Callback function is called only when a valid code is received. +void translateCode(unsigned long receivedCode, unsigned int period) { + // Enabled interrupts, so RemoteReceiver::isReceiving() can be used. + interrupts(); + + // Compare the signals + if (RemoteTransmitter::isSameCode(actionAOn, receivedCode)) { + // A-On-button pressed! + + // Wait for a free ether + while(RemoteReceiver::isReceiving()); + + // Switch devices on + blokkerTransmitter.sendSignal(5,true); + blokkerTransmitter.sendSignal(6,true); + blokkerTransmitter.sendSignal(7,true); + + } else if (RemoteTransmitter::isSameCode(actionAOff, receivedCode)) { + // A-Off-button pressed! + + // Wait for a free ether + while(RemoteReceiver::isReceiving()); + + // Switch devices off + blokkerTransmitter.sendSignal(5,false); + blokkerTransmitter.sendSignal(6,false); + blokkerTransmitter.sendSignal(7,false); + } +} diff --git a/libraries/RemoteSwitch/examples/Retransmitter/Retransmitter.ino b/libraries/RemoteSwitch/examples/Retransmitter/Retransmitter.ino new file mode 100644 index 0000000..3263785 --- /dev/null +++ b/libraries/RemoteSwitch/examples/Retransmitter/Retransmitter.ino @@ -0,0 +1,40 @@ +/* +* Demo for RF remote switch receiver. +* For details, see RemoteReceiver.h! +* +* This sketch demonstrates how to use the static version of +* RemoteReceiver::sendCode, which can be used in low-memory +* situations. +* +* Connect the transmitter to digital pin 11, and the receiver to digital pin 2. +* +* When run, this sketch waits for a valid code from the receiver, decodes it, +* and retransmits it after 5 seconds. +*/ + +#include +#include + +void setup() { + // See example Show_received_code for info on this + RemoteReceiver::init(0, 3, retransmitter); +} + +void loop() { +} + +void retransmitter(unsigned long receivedCode, unsigned int period) { + // Disable the receiver; otherwise it might pick up the retransmit as well. + RemoteReceiver::disable(); + + // Need interrupts for delay() + interrupts(); + + // Wait 5 seconds before sending. + delay(5000); + + // Retransmit the signal 8 times ( == 2^3) on pin 11. Note: no object was created! + RemoteTransmitter::sendCode(11, receivedCode, period, 3); + + RemoteReceiver::enable(); +} diff --git a/libraries/RemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino b/libraries/RemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino new file mode 100644 index 0000000..eb3cebf --- /dev/null +++ b/libraries/RemoteSwitch/examples/ShowReceivedCode/ShowReceivedCode.ino @@ -0,0 +1,38 @@ +/* +* Demo for RF remote switch receiver. +* For details, see RemoteReceiver.h! +* +* This sketch shows the received signals on the serial port. +* Connect the receiver to digital pin 2. +*/ + +#include + +void setup() { + Serial.begin(115200); + + // Initialize receiver on interrupt 0 (= digital pin 2), calls the callback "showCode" + // after 3 identical codes have been received in a row. (thus, keep the button pressed + // for a moment) + // + // See the interrupt-parameter of attachInterrupt for possible values (and pins) + // to connect the receiver. + RemoteReceiver::init(0, 3, showCode); +} + +void loop() { +} + +// Callback function is called only when a valid code is received. +void showCode(unsigned long receivedCode, unsigned int period) { + // Note: interrupts are disabled. You can re-enable them if needed. + + // Print the received code. + Serial.print("Code: "); + Serial.print(receivedCode); + Serial.print(", period duration: "); + Serial.print(period); + Serial.println("us."); +} + + diff --git a/libraries/RemoteSwitch/keywords.txt b/libraries/RemoteSwitch/keywords.txt new file mode 100644 index 0000000..ece29b0 --- /dev/null +++ b/libraries/RemoteSwitch/keywords.txt @@ -0,0 +1,15 @@ +RemoteTransmitter KEYWORD1 +ActionTransmitter KEYWORD1 +BlokkerTransmitter KEYWORD1 +KaKuTransmitter KEYWORD1 +ElroTransmitter KEYWORD1 +sendTelegram KEYWORD2 +sendCode KEYWORD2 +sendSignal KEYWORD2 +isSameCode KEYWORD2 +RemoteReceiver KEYWORD1 +init KEYWORD2 +enable KEYWORD2 +disable KEYWORD2 +deinit KEYWORD2 +isReceiving KEYWORD2 \ No newline at end of file diff --git a/libraries/RemoteSwitch/license.txt b/libraries/RemoteSwitch/license.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/libraries/RemoteSwitch/license.txt @@ -0,0 +1,674 @@ + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/libraries/RunningAverage/RunningAverage.cpp b/libraries/RunningAverage/RunningAverage.cpp new file mode 100644 index 0000000..ae26b8b --- /dev/null +++ b/libraries/RunningAverage/RunningAverage.cpp @@ -0,0 +1,101 @@ +// +// FILE: RunningAverage.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.2.08 +// DATE: 2015-apr-10 +// PURPOSE: RunningAverage library for Arduino +// +// The library stores N individual values in a circular buffer, +// to calculate the running average. +// +// HISTORY: +// 0.1.00 - 2011-01-30 initial version +// 0.1.01 - 2011-02-28 fixed missing destructor in .h +// 0.2.00 - 2012-??-?? Yuval Naveh added trimValue (found on web) +// http://stromputer.googlecode.com/svn-history/r74/trunk/Arduino/Libraries/RunningAverage/RunningAverage.cpp +// 0.2.01 - 2012-11-21 refactored +// 0.2.02 - 2012-12-30 refactored trimValue -> fillValue +// 0.2.03 - 2013-11-31 getElement +// 0.2.04 - 2014-07-03 added memory protection +// 0.2.05 - 2014-12-16 changed float -> double +// 0.2.06 - 2015-03-07 all size uint8_t +// 0.2.07 - 2015-03-16 added getMin() and getMax() functions (Eric Mulder) +// 0.2.08 - 2015-04-10 refactored getMin() and getMax() implementation +// +// Released to the public domain +// + +#include "RunningAverage.h" +#include + +RunningAverage::RunningAverage(uint8_t size) +{ + _size = size; + _ar = (double*) malloc(_size * sizeof(double)); + if (_ar == NULL) _size = 0; + clear(); +} + +RunningAverage::~RunningAverage() +{ + if (_ar != NULL) free(_ar); +} + +// resets all counters +void RunningAverage::clear() +{ + _cnt = 0; + _idx = 0; + _sum = 0.0; + _min = NAN; + _max = NAN; + for (uint8_t i = 0; i < _size; i++) + { + _ar[i] = 0.0; // keeps addValue simple + } +} + +// adds a new value to the data-set +void RunningAverage::addValue(double value) +{ + if (_ar == NULL) return; // allocation error + _sum -= _ar[_idx]; + _ar[_idx] = value; + _sum += _ar[_idx]; + _idx++; + if (_idx == _size) _idx = 0; // faster than % + // handle min max + if (_cnt == 0) _min = _max = value; + else if (value < _min) _min = value; + else if (value > _max) _max = value; + // update count as last otherwise if( _cnt == 0) above will fail + if (_cnt < _size) _cnt++; +} + +// returns the average of the data-set added sofar +double RunningAverage::getAverage() +{ + if (_cnt == 0) return NAN; + return _sum / _cnt; +} + +// returns the value of an element if exist, NAN otherwise +double RunningAverage::getElement(uint8_t idx) +{ + if (idx >=_cnt ) return NAN; + return _ar[idx]; +} + +// fill the average with a value +// the param number determines how often value is added (weight) +// number should preferably be between 1 and size +void RunningAverage::fillValue(double value, uint8_t number) +{ + clear(); // TODO conditional? if (clr) clear(); + + for (uint8_t i = 0; i < number; i++) + { + addValue(value); + } +} +// END OF FILE \ No newline at end of file diff --git a/libraries/RunningAverage/RunningAverage.h b/libraries/RunningAverage/RunningAverage.h new file mode 100644 index 0000000..c17240a --- /dev/null +++ b/libraries/RunningAverage/RunningAverage.h @@ -0,0 +1,56 @@ +// +// FILE: RunningAverage.h +// AUTHOR: Rob dot Tillaart at gmail dot com +// VERSION: 0.2.08 +// DATE: 2015-apr-10 +// PURPOSE: RunningAverage library for Arduino +// URL: http://arduino.cc/playground/Main/RunningAverage +// HISTORY: See RunningAverage.cpp +// +// Released to the public domain +// +// backwards compatibility +// clr() clear() +// add(x) addValue(x) +// avg() getAverage() + +#ifndef RunningAverage_h +#define RunningAverage_h + +#define RUNNINGAVERAGE_LIB_VERSION "0.2.08" + +#include "Arduino.h" + +class RunningAverage +{ +public: + RunningAverage(void); + RunningAverage(uint8_t); + ~RunningAverage(); + + void clear(); + void addValue(double); + void fillValue(double, uint8_t); + + double getAverage(); + // returns lowest value added to the data-set since last clear + double getMin() { return _min; }; + // returns highest value added to the data-set since last clear + double getMax() { return _max; }; + + double getElement(uint8_t idx); + uint8_t getSize() { return _size; } + uint8_t getCount() { return _cnt; } + +protected: + uint8_t _size; + uint8_t _cnt; + uint8_t _idx; + double _sum; + double * _ar; + double _min; + double _max; +}; + +#endif +// END OF FILE \ No newline at end of file diff --git a/libraries/RunningAverage/examples/fillValue/fillValue.ino b/libraries/RunningAverage/examples/fillValue/fillValue.ino new file mode 100644 index 0000000..aaf8900 --- /dev/null +++ b/libraries/RunningAverage/examples/fillValue/fillValue.ino @@ -0,0 +1,38 @@ +// +// FILE: fillValue.pde +// AUTHOR: Rob Tillaart +// DATE: 2012-12-30 +// +// PUPROSE: show working of fillValue +// + +#include "RunningAverage.h" + +RunningAverage myRA(10); +int samples = 0; + +void setup(void) +{ + Serial.begin(115200); + Serial.print("Demo RunningAverage lib - fillValue "); + Serial.print("Version: "); + Serial.println(RUNNINGAVERAGE_LIB_VERSION); + + myRA.fillValue(100,5); +} + +void loop(void) +{ + long rn = random(0, 100); + myRA.addValue(rn/100.0); + samples++; + Serial.print("Running Average: "); + Serial.println(myRA.getAverage(), 4); + + if (samples == 300) + { + samples = 0; + myRA.fillValue(100, 10); + } + delay(100); +} \ No newline at end of file diff --git a/libraries/RunningAverage/examples/ra_MinMaxTest/ra_MinMaxTest.ino b/libraries/RunningAverage/examples/ra_MinMaxTest/ra_MinMaxTest.ino new file mode 100644 index 0000000..437251a --- /dev/null +++ b/libraries/RunningAverage/examples/ra_MinMaxTest/ra_MinMaxTest.ino @@ -0,0 +1,46 @@ +// +// FILE: runningAverageMinMaxTest.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.00 +// DATE: 2015-apr-10 +// +// PUPROSE: demo +// + +#include "RunningAverage.h" + +RunningAverage myRA(10); +int samples = 0; + +void setup(void) +{ + Serial.begin(115200); + Serial.println("\nDemo runningAverageMinMaxTest"); + Serial.print("Version: "); + Serial.println(RUNNINGAVERAGE_LIB_VERSION); + myRA.clear(); // explicitly start clean + + Serial.println("\nCNT\tMIN\tAVG\tMAX"); +} + +void loop(void) +{ + long rn = random(0, 1000); + myRA.addValue(rn * 0.001); + samples++; + Serial.print(samples); + Serial.print("\t"); + Serial.print(myRA.getMin(), 3); + Serial.print("\t"); + Serial.print(myRA.getAverage(), 3); + Serial.print("\t"); + Serial.println(myRA.getMax(), 3); + + if (samples == 100) + { + samples = 0; + myRA.clear(); + Serial.println("\nCNT\tMIN\tAVG\tMAX"); + } + delay(10); +} diff --git a/libraries/RunningAverage/examples/ra_hour/ra_hour.ino b/libraries/RunningAverage/examples/ra_hour/ra_hour.ino new file mode 100644 index 0000000..09d9214 --- /dev/null +++ b/libraries/RunningAverage/examples/ra_hour/ra_hour.ino @@ -0,0 +1,40 @@ +// +// FILE: runningAverageHour.pde +// AUTHOR: Rob Tillaart +// DATE: 2012-12-30 +// +// PUPROSE: show working of runningAverage per hour +// in 2 steps - last minute + last hour +// 3 or more steps also possible +// + +#include "RunningAverage.h" + +RunningAverage raMinute(60); +RunningAverage raHour(60); + +int samples = 0; + +void setup(void) +{ + Serial.begin(115200); + Serial.println("Demo RunningAverage lib - average per minute & hour"); + Serial.print("Version: "); + Serial.println(RUNNINGAVERAGE_LIB_VERSION); + raHour.clear(); + raMinute.clear(); +} + +void loop(void) +{ + long rn = random(0, 100); + raMinute.addValue(rn); + samples++; + + if (samples % 60 == 0) raHour.addValue(raMinute.getAverage()); + + Serial.print(" raMinute: "); + Serial.print(raMinute.getAverage(), 4); + Serial.print(" raHour: "); + Serial.println(raHour.getAverage(), 4); +} \ No newline at end of file diff --git a/libraries/RunningAverage/examples/ra_test/ra_test.ino b/libraries/RunningAverage/examples/ra_test/ra_test.ino new file mode 100644 index 0000000..146112e --- /dev/null +++ b/libraries/RunningAverage/examples/ra_test/ra_test.ino @@ -0,0 +1,40 @@ +// +// FILE: runningAverageTest.pde +// AUTHOR: Rob Tillaart +// VERSION: 0.1.01 +// DATE: 2012-12-30 +// +// PUPROSE: show working of runningAverage +// + +#include "RunningAverage.h" + +RunningAverage myRA(10); +int samples = 0; + +void setup(void) +{ + Serial.begin(115200); + Serial.println("Demo RunningAverage lib"); + Serial.print("Version: "); + Serial.println(RUNNINGAVERAGE_LIB_VERSION); + myRA.clear(); // explicitly start clean +} + +void loop(void) +{ + long rn = random(0, 1000); + myRA.addValue(rn * 0.001); + samples++; + Serial.print(samples); + Serial.print("\t Running Average: "); + Serial.println(myRA.getAverage(), 3); + + if (samples == 300) + { + samples = 0; + myRA.clear(); + Serial.println(); + } + delay(10); +} \ No newline at end of file diff --git a/libraries/RunningAverage/keywords.txt b/libraries/RunningAverage/keywords.txt new file mode 100644 index 0000000..3bac631 --- /dev/null +++ b/libraries/RunningAverage/keywords.txt @@ -0,0 +1,32 @@ +####################################### +# Syntax Coloring Map For RunningAverage +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +RunningAverage KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +clear KEYWORD2 +addValue KEYWORD2 +getAverage KEYWORD2 +getMin KEYWORD2 +getMax KEYWORD2 +fillValue KEYWORD2 +getElement KEYWORD2 +getSize KEYWORD2 +getCount KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### \ No newline at end of file diff --git a/libraries/SFE_BMP180/SFE_BMP180.cpp b/libraries/SFE_BMP180/SFE_BMP180.cpp new file mode 100644 index 0000000..4383fc5 --- /dev/null +++ b/libraries/SFE_BMP180/SFE_BMP180.cpp @@ -0,0 +1,387 @@ +/* + 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 + + 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(0); + } +} + + +char SFE_BMP180::readInt(char address, int &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 = (((int)data[0]<<8)|(int)data[1]); + //if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative + return(1); + } + value = 0; + return(0); +} + + +char SFE_BMP180::readUInt(char address, unsigned int &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 = (((unsigned int)data[0]<<8)|(unsigned int)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, int &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, unsigned int &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 + + int AC1,AC2,AC3,VB1,VB2,MB,MC,MD; + unsigned int 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/SFE_BMP180/examples/BMP180_altitude_example/BMP180_altitude_example.ino b/libraries/SFE_BMP180/examples/BMP180_altitude_example/BMP180_altitude_example.ino new file mode 100644 index 0000000..fdb8358 --- /dev/null +++ b/libraries/SFE_BMP180/examples/BMP180_altitude_example/BMP180_altitude_example.ino @@ -0,0 +1,168 @@ +/* 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 +*/ + +// 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/SFE_BMP180/examples/SFE_BMP180_example/SFE_BMP180_example.ino b/libraries/SFE_BMP180/examples/SFE_BMP180_example/SFE_BMP180_example.ino new file mode 100644 index 0000000..a43c905 --- /dev/null +++ b/libraries/SFE_BMP180/examples/SFE_BMP180_example/SFE_BMP180_example.ino @@ -0,0 +1,200 @@ +/* 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 +*/ + +// 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/SFE_BMP180/keywords.txt b/libraries/SFE_BMP180/keywords.txt new file mode 100644 index 0000000..664167d --- /dev/null +++ b/libraries/SFE_BMP180/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/SI7021/LICENSE b/libraries/SI7021/LICENSE new file mode 100644 index 0000000..d7f1051 --- /dev/null +++ b/libraries/SI7021/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/libraries/SI7021/README.md b/libraries/SI7021/README.md new file mode 100644 index 0000000..38f42bf --- /dev/null +++ b/libraries/SI7021/README.md @@ -0,0 +1,4 @@ +SI7021 +====== + +Arduino library for SI7020 and SI7021 environmental sensors diff --git a/libraries/SI7021/SI7021.cpp b/libraries/SI7021/SI7021.cpp new file mode 100644 index 0000000..c51ab6b --- /dev/null +++ b/libraries/SI7021/SI7021.cpp @@ -0,0 +1,135 @@ +/* +Copyright 2014 Marcus Sorensen + +This program is licensed under the GNU GPL v2 +*/ +#include "Arduino.h" +#include "SI7021.h" +#include + +#define I2C_ADDR 0x40 + +// I2C commands +byte RH_READ[] = { 0xE5 }; +byte TEMP_READ[] = { 0xE3 }; +byte POST_RH_TEMP_READ[] = { 0xE0 }; +byte RESET[] = { 0xFE }; +byte USER1_READ[] = { 0xE7 }; +byte USER1_WRITE[] = { 0xE6 }; +byte SERIAL1_READ[] = { 0xFA, 0x0F }; +byte SERIAL2_READ[] = { 0xFC, 0xC9 }; + +bool _si_exists = false; + +SI7021::SI7021() { +} + +bool SI7021::begin() { + Wire.begin(); + Wire.beginTransmission(I2C_ADDR); + if (Wire.endTransmission() == 0) { + _si_exists = true; + } + return _si_exists; +} + +bool SI7021::sensorExists() { + return _si_exists; +} + +int SI7021::getFahrenheitHundredths() { + unsigned int c = getCelsiusHundredths(); + return (1.8 * c) + 3200; +} + +int SI7021::getCelsiusHundredths() { + byte tempbytes[2]; + _command(TEMP_READ, tempbytes); + long tempraw = (long)tempbytes[0] << 8 | tempbytes[1]; + return ((17572 * tempraw) >> 16) - 4685; +} + +int SI7021::_getCelsiusPostHumidity() { + byte tempbytes[2]; + _command(POST_RH_TEMP_READ, tempbytes); + long tempraw = (long)tempbytes[0] << 8 | tempbytes[1]; + return ((17572 * tempraw) >> 16) - 4685; +} + + +unsigned int SI7021::getHumidityPercent() { + byte humbytes[2]; + _command(RH_READ, humbytes); + long humraw = (long)humbytes[0] << 8 | humbytes[1]; + return ((125 * humraw) >> 16) - 6; +} + +unsigned int SI7021::getHumidityBasisPoints() { + byte humbytes[2]; + _command(RH_READ, humbytes); + long humraw = (long)humbytes[0] << 8 | humbytes[1]; + return ((12500 * humraw) >> 16) - 600; +} + +void SI7021::_command(byte * cmd, byte * buf ) { + _writeReg(cmd, sizeof cmd); + _readReg(buf, sizeof buf); +} + +void SI7021::_writeReg(byte * reg, int reglen) { + Wire.beginTransmission(I2C_ADDR); + for(int i = 0; i < reglen; i++) { + reg += i; + Wire.write(*reg); + } + Wire.endTransmission(); +} + +int SI7021::_readReg(byte * reg, int reglen) { + Wire.requestFrom(I2C_ADDR, reglen); + while(Wire.available() < reglen) { + } + for(int i = 0; i < reglen; i++) { + reg[i] = Wire.read(); + } + return 1; +} + +//note this has crc bytes embedded, per datasheet, so provide 12 byte buf +int SI7021::getSerialBytes(byte * buf) { + _writeReg(SERIAL1_READ, sizeof SERIAL1_READ); + _readReg(buf, 6); + + _writeReg(SERIAL2_READ, sizeof SERIAL2_READ); + _readReg(buf + 6, 6); + + // could verify crc here and return only the 8 bytes that matter + return 1; +} + +int SI7021::getDeviceId() { + byte serial[12]; + getSerialBytes(serial); + int id = serial[6]; + return id; +} + +void SI7021::setHeater(bool on) { + byte userbyte; + if (on) { + userbyte = 0x3E; + } else { + userbyte = 0x3A; + } + byte userwrite[] = {USER1_WRITE[0], userbyte}; + _writeReg(userwrite, sizeof userwrite); +} + +// get humidity, then get temperature reading from humidity measurement +struct si7021_env SI7021::getHumidityAndTemperature() { + si7021_env ret = {0, 0, 0}; + ret.humidityPercent = getHumidityPercent(); + ret.celsiusHundredths = _getCelsiusPostHumidity(); + ret.fahrenheitHundredths = (1.8 * ret.celsiusHundredths) + 3200; + return ret; +} diff --git a/libraries/SI7021/SI7021.h b/libraries/SI7021/SI7021.h new file mode 100644 index 0000000..d577900 --- /dev/null +++ b/libraries/SI7021/SI7021.h @@ -0,0 +1,51 @@ +/* + Copyright 2014 Marcus Sorensen + +This program is licensed under the GNU GPL v2 +*/ +#ifndef si7021_h +#define si7021_h + +#if (ARDUINO >= 100) + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#ifdef __AVR_ATtiny85__ + #include "TinyWireM.h" + #define Wire TinyWireM +#else + #include + #include +#endif + +typedef struct si7021_env { + int celsiusHundredths; + int fahrenheitHundredths; + unsigned int humidityPercent; +} si7021_env; + +class SI7021 +{ + public: + SI7021(); + bool begin(); + bool sensorExists(); + int getFahrenheitHundredths(); + int getCelsiusHundredths(); + unsigned int getHumidityPercent(); + unsigned int getHumidityBasisPoints(); + struct si7021_env getHumidityAndTemperature(); + int getSerialBytes(byte * buf); + int getDeviceId(); + void setHeater(bool on); + private: + void _command(byte * cmd, byte * buf ); + void _writeReg(byte * reg, int reglen); + int _readReg(byte * reg, int reglen); + int _getCelsiusPostHumidity(); +}; + +#endif + diff --git a/libraries/SI7021/examples/readsensor/readsensor.ino b/libraries/SI7021/examples/readsensor/readsensor.ino new file mode 100644 index 0000000..95194cf --- /dev/null +++ b/libraries/SI7021/examples/readsensor/readsensor.ino @@ -0,0 +1,80 @@ +#include +#include + + +SI7021 sensor; +int led1 = 3; +int led2 = 4; + +void setup() { + pinMode(led1, OUTPUT); + pinMode(led2, OUTPUT); + sensor.begin(); +} + + +void loop() { + + // temperature is an integer in hundredths + int temperature = sensor.getCelsiusHundredths(); + temperature = temperature / 100; + for (int i = 0; i < temperature; i++) { + pulse(led1); + } + + delay(5000); + + // humidity is an integer representing percent + int humidity = sensor.getHumidityPercent(); + for (int i = 0; i < humidity; i++) { + pulse(led2); + } + + delay(5000); + + // this driver should work for SI7020 and SI7021, this returns 20 or 21 + int deviceid = sensor.getDeviceId(); + for (int i = 0; i < deviceid; i++) { + pulse(led1); + } + delay(5000); + + // enable internal heater for testing + sensor.setHeater(true); + delay(20000); + sensor.setHeater(false); + + // see if heater changed temperature + int temperature = sensor.getCelsiusHundredths(); + temperature = temperature / 100; + for (int i = 0; i < temperature; i++) { + pulse(led2); + } + + //cool down + delay(20000); + + // get humidity and temperature in one shot, saves power because sensor takes temperature when doing humidity anyway + si7021_env data = sensor.getHumidityAndTemperature(); + for (int i = 0; i < data.celsiusHundredths/100; i++) { + pulse(led1); + } + for (int i = 0; i < data.humidityPercent; i++) { + pulse(led2); + } + delay(5000); +} + +void pulse(int pin) { + // software pwm, flash light for ~1 second with short duty cycle + for (int i = 0; i < 20; i++) { + digitalWrite(pin, HIGH); + delay(1); + digitalWrite(pin,LOW); + delay(9); + } + digitalWrite(pin,LOW); + delay(300); +} + + diff --git a/libraries/SPIFlash/README.md b/libraries/SPIFlash/README.md new file mode 100644 index 0000000..63a1cac --- /dev/null +++ b/libraries/SPIFlash/README.md @@ -0,0 +1,24 @@ +SPIFlash +======== +Arduino/Moteino library for read/write access to SPI flash memory chips. +This works with 256byte/page SPI flash memory such as the 4MBIT W25X40CLSNIG used on (Moteinos)[www.moteino.com] for data storage and wireless programming. +
+For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes). +
Minimal modifications should allow chips that have different page size to work. +
DEPENDS ON: Arduino *SPI library*. +
+This library was primarily developed to enable **safe** wireless programming on Moteino nodes and Moteino based applications such as the SwitchMote. This has been documented at [lowpowerlab](http://lowpowerlab.com/blog/category/moteino/wireless-programming/). [Dualoptiboot](https://github.com/LowPowerLab/DualOptiboot) (all Moteinos come with it) and [WirelessProgramming library](https://github.com/LowPowerLab/WirelessProgramming) are required to be able to wirelessly re-flash a remote Moteino. + +###Installation +Copy the content of this library in the "Arduino/libraries/SPIFlash" folder. +
+To find your Arduino folder go to File>Preferences in the Arduino IDE. +
+See [this tutorial](http://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-libraries) on Arduino libraries. + +###License +Copyright (c) 2013 by Felix Rusu +
+This library is free software; you can redistribute it and/or modify it under the terms of either the GNU General Public License version 2 or the GNU Lesser General Public License version 2.1, both as published by the Free Software Foundation. +
+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. diff --git a/libraries/SPIFlash/SPIFlash.cpp b/libraries/SPIFlash/SPIFlash.cpp new file mode 100644 index 0000000..bad4cdf --- /dev/null +++ b/libraries/SPIFlash/SPIFlash.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2013 by Felix Rusu + * SPI Flash memory library for arduino/moteino. + * This works with 256byte/page SPI flash memory + * For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes) + * Minimal modifications should allow chips that have different page size but modifications + * DEPENDS ON: Arduino SPI library + * + * Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment. + * Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above) + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include + +byte SPIFlash::UNIQUEID[8]; + +/// IMPORTANT: NAND FLASH memory requires erase before write, because +/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s +/// See http://en.wikipedia.org/wiki/Flash_memory +/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command + +/// Constructor. JedecID is optional but recommended, since this will ensure that the device is present and has a valid response +/// get this from the datasheet of your flash chip +/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) +/// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) +SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) { + _slaveSelectPin = slaveSelectPin; + _jedecID = jedecID; +} + +/// Select the flash chip +void SPIFlash::select() { + //save current SPI settings +#ifndef SPI_HAS_TRANSACTION + _SREG = SREG; + noInterrupts(); +#endif + _SPCR = SPCR; + _SPSR = SPSR; + +#ifdef SPI_HAS_TRANSACTION + SPI.beginTransaction(_settings); +#else + // set FLASH SPI settings + SPI.setDataMode(SPI_MODE0); + SPI.setBitOrder(MSBFIRST); + SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present +#endif + digitalWrite(_slaveSelectPin, LOW); +} + +/// UNselect the flash chip +void SPIFlash::unselect() { + digitalWrite(_slaveSelectPin, HIGH); + //restore SPI settings to what they were before talking to the FLASH chip +#ifdef SPI_HAS_TRANSACTION + SPI.endTransaction(); +#else + SREG = _SREG; // restore interrupts IFF they were enabled +#endif + SPCR = _SPCR; + SPSR = _SPSR; +} + +/// setup SPI, read device ID etc... +boolean SPIFlash::initialize() +{ + _SPCR = SPCR; + _SPSR = SPSR; + digitalWrite(_slaveSelectPin, HIGH); + pinMode(_slaveSelectPin, OUTPUT); + SPI.begin(); + _settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); + unselect(); + wakeup(); + + if (_jedecID == 0 || readDeviceId() == _jedecID) { + command(SPIFLASH_STATUSWRITE, true); // Write Status Register + SPI.transfer(0); // Global Unprotect + unselect(); + return true; + } + return false; +} + +/// Get the manufacturer and device ID bytes (as a short word) +word SPIFlash::readDeviceId() +{ +#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo + command(SPIFLASH_IDREAD); // Read JEDEC ID +#else + select(); + SPI.transfer(SPIFLASH_IDREAD); +#endif + word jedecid = SPI.transfer(0) << 8; + jedecid |= SPI.transfer(0); + unselect(); + return jedecid; +} + +/// Get the 64 bit unique identifier, stores it in UNIQUEID[8]. Only needs to be called once, ie after initialize +/// Returns the byte pointer to the UNIQUEID byte array +/// Read UNIQUEID like this: +/// flash.readUniqueId(); for (byte i=0;i<8;i++) { Serial.print(flash.UNIQUEID[i], HEX); Serial.print(' '); } +/// or like this: +/// flash.readUniqueId(); byte* MAC = flash.readUniqueId(); for (byte i=0;i<8;i++) { Serial.print(MAC[i], HEX); Serial.print(' '); } +byte* SPIFlash::readUniqueId() +{ + command(SPIFLASH_MACREAD); + SPI.transfer(0); + SPI.transfer(0); + SPI.transfer(0); + SPI.transfer(0); + for (byte i=0;i<8;i++) + UNIQUEID[i] = SPI.transfer(0); + unselect(); + return UNIQUEID; +} + +/// read 1 byte from flash memory +byte SPIFlash::readByte(long addr) { + command(SPIFLASH_ARRAYREADLOWFREQ); + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + byte result = SPI.transfer(0); + unselect(); + return result; +} + +/// read unlimited # of bytes +void SPIFlash::readBytes(long addr, void* buf, word len) { + command(SPIFLASH_ARRAYREAD); + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + SPI.transfer(0); //"dont care" + for (word i = 0; i < len; ++i) + ((byte*) buf)[i] = SPI.transfer(0); + unselect(); +} + +/// Send a command to the flash chip, pass TRUE for isWrite when its a write command +void SPIFlash::command(byte cmd, boolean isWrite){ +#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo + DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH! + PORTB |= B00000001; +#endif + if (isWrite) + { + command(SPIFLASH_WRITEENABLE); // Write Enable + unselect(); + } + //wait for any write/erase to complete + // a time limit cannot really be added here without it being a very large safe limit + // that is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations + // a recommended alternative to such situations where chip can be or not be present is to add a 10k or similar weak pulldown on the + // open drain MISO input which can read noise/static and hence return a non 0 status byte, causing the while() to hang when a flash chip is not present + while(busy()); + select(); + SPI.transfer(cmd); +} + +/// check if the chip is busy erasing/writing +boolean SPIFlash::busy() +{ + /* + select(); + SPI.transfer(SPIFLASH_STATUSREAD); + byte status = SPI.transfer(0); + unselect(); + return status & 1; + */ + return readStatus() & 1; +} + +/// return the STATUS register +byte SPIFlash::readStatus() +{ + select(); + SPI.transfer(SPIFLASH_STATUSREAD); + byte status = SPI.transfer(0); + unselect(); + return status; +} + + +/// Write 1 byte to flash memory +/// WARNING: you can only write to previously erased memory locations (see datasheet) +/// use the block erase commands to first clear memory (write 0xFFs) +void SPIFlash::writeByte(long addr, uint8_t byt) { + command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + SPI.transfer(byt); + unselect(); +} + +/// write multiple bytes to flash memory (up to 64K) +/// WARNING: you can only write to previously erased memory locations (see datasheet) +/// use the block erase commands to first clear memory (write 0xFFs) +/// This version handles both page alignment and data blocks larger than 256 bytes. +/// +void SPIFlash::writeBytes(long addr, const void* buf, uint16_t len) { + uint16_t n; + uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page + uint16_t offset = 0; + while (len>0) + { + n = (len<=maxBytes) ? len : maxBytes; + command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + for (uint16_t i = 0; i < n; i++) + SPI.transfer(((byte*) buf)[offset + i]); + unselect(); + addr+=n; // adjust the addresses and remaining bytes by what we've just transferred. + offset +=n; + len -= n; + maxBytes = 256; // now we can do up to 256 bytes per loop + } +} + + +/// erase entire flash memory array +/// may take several seconds depending on size, but is non blocking +/// so you may wait for this to complete using busy() or continue doing +/// other things and later check if the chip is done with busy() +/// note that any command will first wait for chip to become available using busy() +/// so no need to do that twice +void SPIFlash::chipErase() { + command(SPIFLASH_CHIPERASE, true); + unselect(); +} + +/// erase a 4Kbyte block +void SPIFlash::blockErase4K(long addr) { + command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + unselect(); +} + +/// erase a 32Kbyte block +void SPIFlash::blockErase32K(long addr) { + command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + unselect(); +} + +void SPIFlash::sleep() { + command(SPIFLASH_SLEEP); + unselect(); +} + +void SPIFlash::wakeup() { + command(SPIFLASH_WAKE); + unselect(); +} + +/// cleanup +void SPIFlash::end() { + SPI.end(); +} \ No newline at end of file diff --git a/libraries/SPIFlash/SPIFlash.h b/libraries/SPIFlash/SPIFlash.h new file mode 100644 index 0000000..8f530b7 --- /dev/null +++ b/libraries/SPIFlash/SPIFlash.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013 by Felix Rusu + * SPI Flash memory library for arduino/moteino. + * This works with 256uint8_t/page SPI flash memory + * For instance a 4MBit (512Kuint8_t) flash chip will have 2048 pages: 256*2048 = 524288 uint8_ts (512Kuint8_ts) + * Minimal modifications should allow chips that have different page size but modifications + * DEPENDS ON: Arduino SPI library + * + * Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above) + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef _SPIFLASH_H_ +#define _SPIFLASH_H_ + +#if ARDUINO >= 100 +#include +#else +#include +#include "pins_arduino.h" +#endif + +#include + +/// IMPORTANT: NAND FLASH memory requires erase before write, because +/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s +/// See http://en.wikipedia.org/wiki/Flash_memory +/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command + +/// Standard SPI flash commands +/// Assuming the WP pin is pulled up (to disable hardware write protection) +/// To use any write commands the WEL bit in the status register must be set to 1. +/// This is accomplished by sending a 0x06 command before any such write/erase command. +/// The WEL bit in the status register resets to the logical “0” state after a +/// device power-up or reset. In addition, the WEL bit will be reset to the logical “0” state automatically under the following conditions: +/// • Write Disable operation completes successfully +/// • Write Status Register operation completes successfully or aborts +/// • Protect Sector operation completes successfully or aborts +/// • Unprotect Sector operation completes successfully or aborts +/// • Byte/Page Program operation completes successfully or aborts +/// • Sequential Program Mode reaches highest unprotected memory location +/// • Sequential Program Mode reaches the end of the memory array +/// • Sequential Program Mode aborts +/// • Block Erase operation completes successfully or aborts +/// • Chip Erase operation completes successfully or aborts +/// • Hold condition aborts +#define SPIFLASH_WRITEENABLE 0x06 // write enable +#define SPIFLASH_WRITEDISABLE 0x04 // write disable + +#define SPIFLASH_BLOCKERASE_4K 0x20 // erase one 4K block of flash memory +#define SPIFLASH_BLOCKERASE_32K 0x52 // erase one 32K block of flash memory +#define SPIFLASH_BLOCKERASE_64K 0xD8 // erase one 64K block of flash memory +#define SPIFLASH_CHIPERASE 0x60 // chip erase (may take several seconds depending on size) + // but no actual need to wait for completion (instead need to check the status register BUSY bit) +#define SPIFLASH_STATUSREAD 0x05 // read status register +#define SPIFLASH_STATUSWRITE 0x01 // write status register +#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy uint8_t after 3 address uint8_ts) +#define SPIFLASH_ARRAYREADLOWFREQ 0x03 // read array (low frequency) + +#define SPIFLASH_SLEEP 0xB9 // deep power down +#define SPIFLASH_WAKE 0xAB // deep power wake up +#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256uint8_ts) +#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 uint8_ts, specific uint8_ts for each manufacturer and device) + // Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) + // Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) +#define SPIFLASH_MACREAD 0x4B // read unique ID number (MAC) + +class SPIFlash { +public: + static uint8_t UNIQUEID[8]; + SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); + boolean initialize(); + void command(uint8_t cmd, boolean isWrite=false); + uint8_t readStatus(); + uint8_t readByte(long addr); + void readBytes(long addr, void* buf, word len); + void writeByte(long addr, uint8_t byt); + void writeBytes(long addr, const void* buf, uint16_t len); + boolean busy(); + void chipErase(); + void blockErase4K(long address); + void blockErase32K(long address); + word readDeviceId(); + uint8_t* readUniqueId(); + + void sleep(); + void wakeup(); + void end(); +protected: + void select(); + void unselect(); + uint8_t _slaveSelectPin; + uint16_t _jedecID; + uint8_t _SPCR; + uint8_t _SPSR; + uint8_t _SREG; + +#ifdef SPI_HAS_TRANSACTION + SPISettings _settings; +#endif + +}; + +#endif \ No newline at end of file diff --git a/libraries/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino b/libraries/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino new file mode 100644 index 0000000..dd8d0e8 --- /dev/null +++ b/libraries/SPIFlash/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino @@ -0,0 +1,116 @@ +// ********************************************************************************** +// This sketch is an example of using the SPIFlash library with a Moteino +// that has an onboard SPI Flash chip. This sketch listens to a few serial commands +// Hence type the following commands to interact with the SPI flash memory array: +// - 'd' dumps the first 256bytes of the flash chip to screen +// - 'e' erases the entire memory chip +// - 'i' print manufacturer/device ID +// - [0-9] writes a random byte to addresses [0-9] (either 0xAA or 0xBB) +// Get the SPIFlash library from here: https://github.com/LowPowerLab/SPIFlash +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** + + +#include //get it here: https://github.com/LowPowerLab/SPIFlash +#include + +#define SERIAL_BAUD 115200 +char input = 0; +long lastPeriod = -1; + +#ifdef __AVR_ATmega1284P__ + #define LED 15 // Moteino MEGAs have LEDs on D15 + #define FLASH_SS 23 // and FLASH SS on D23 +#else + #define LED 9 // Moteinos have LEDs on D9 + #define FLASH_SS 8 // and FLASH SS on D8 +#endif + +////////////////////////////////////////// +// flash(SPI_CS, MANUFACTURER_ID) +// SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) +// MANUFACTURER_ID - OPTIONAL, 0x1F44 for adesto(ex atmel) 4mbit flash +// 0xEF30 for windbond 4mbit flash +////////////////////////////////////////// +SPIFlash flash(FLASH_SS, 0xEF30); + +void setup(){ + Serial.begin(SERIAL_BAUD); + Serial.print("Start..."); + + if (flash.initialize()) + Serial.println("Init OK!"); + else + Serial.println("Init FAIL!"); +} + +void loop(){ + // Handle serial input (to allow basic DEBUGGING of FLASH chip) + // ie: display first 256 bytes in FLASH, erase chip, write bytes at first 10 positions, etc + if (Serial.available() > 0) { + input = Serial.read(); + if (input == 'd') //d=dump flash area + { + Serial.println("Flash content:"); + int counter = 0; + + while(counter<=256){ + Serial.print(flash.readByte(counter++), HEX); + Serial.print('.'); + } + + Serial.println(); + } + else if (input == 'e') + { + Serial.print("Erasing Flash chip ... "); + flash.chipErase(); + while(flash.busy()); + Serial.println("DONE"); + } + else if (input == 'i') + { + Serial.print("DeviceID: "); + Serial.println(flash.readDeviceId(), HEX); + } + else if (input >= 48 && input <= 57) //0-9 + { + Serial.print("\nWriteByte("); Serial.print(input); Serial.print(")"); + flash.writeByte(input-48, millis()%2 ? 0xaa : 0xbb); + } + } + + // Periodically blink the onboard LED while listening for serial commands + if ((int)(millis()/500) > lastPeriod) + { + lastPeriod++; + pinMode(9, OUTPUT); + digitalWrite(9, lastPeriod%2); + } +} \ No newline at end of file diff --git a/libraries/SPIFlash/keywords.txt b/libraries/SPIFlash/keywords.txt new file mode 100644 index 0000000..652da98 --- /dev/null +++ b/libraries/SPIFlash/keywords.txt @@ -0,0 +1,18 @@ +SPIFlash KEYWORD1 +initialize KEYWORD2 +command KEYWORD2 +readStatus KEYWORD2 +readByte KEYWORD2 +readBytes KEYWORD2 +writeByte KEYWORD2 +writeBytes KEYWORD2 +flashBusy KEYWORD2 +chipErase KEYWORD2 +blockErase4K KEYWORD2 +blockErase32K KEYWORD2 +readDeviceId KEYWORD2 +readUniqueId KEYWORD2 +UNIQUEID KEYWORD2 +sleep KEYWORD2 +wakeup KEYWORD2 +end KEYWORD2 \ No newline at end of file diff --git a/libraries/SPIFlash/library.json b/libraries/SPIFlash/library.json new file mode 100644 index 0000000..b199318 --- /dev/null +++ b/libraries/SPIFlash/library.json @@ -0,0 +1,12 @@ +{ + "name": "SPIFlash", + "keywords": "flash, spi", + "description": "Library for read/write access to SPI flash memory chips", + "repository": + { + "type": "git", + "url": "https://github.com/LowPowerLab/SPIFlash.git" + }, + "frameworks": "arduino", + "platforms": "atmelavr" +} diff --git a/libraries/SimpleTimer/README.markdown b/libraries/SimpleTimer/README.markdown new file mode 100644 index 0000000..19aa6be --- /dev/null +++ b/libraries/SimpleTimer/README.markdown @@ -0,0 +1,34 @@ +## SimpleTimer - A timer library for Arduino. + +### Uploader +Derek Chafin +Jun 16, 2012 +info
...@gmail.com + +###Disclaimer +I am pushing this library to github because I like git better than I like the Windows clipboard. + +For reference this library can also be found at http://playground.arduino.cc/Code/SimpleTimer. + +### Original Author +Marcello Romani +mrom...@ottotecnica.com +Copyright (c) 2010 OTTOTECNICA Italy + +### License - GNU LGPL 2.1+ +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 \ No newline at end of file diff --git a/libraries/SimpleTimer/SimpleTimer.cpp b/libraries/SimpleTimer/SimpleTimer.cpp new file mode 100644 index 0000000..5a88acb --- /dev/null +++ b/libraries/SimpleTimer/SimpleTimer.cpp @@ -0,0 +1,224 @@ +/* + * SimpleTimer.cpp + * + * SimpleTimer - A timer library for Arduino. + * Author: mromani@ottotecnica.com + * Copyright (c) 2010 OTTOTECNICA Italy + * + * 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 "SimpleTimer.h" + + +SimpleTimer::SimpleTimer() { + unsigned long current_millis = millis(); + + for (int i = 0; i < MAX_TIMERS; i++) { + enabled[i] = false; + callbacks[i] = 0; // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer + prev_millis[i] = current_millis; + numRuns[i] = 0; + } + + numTimers = 0; +} + + +void SimpleTimer::run() { + int i; + unsigned long current_millis; + + // get current time + current_millis = millis(); + + for (i = 0; i < MAX_TIMERS; i++) { + + toBeCalled[i] = DEFCALL_DONTRUN; + + // no callback == no timer, i.e. jump over empty slots + if (callbacks[i]) { + + // is it time to process this timer ? + if (current_millis - prev_millis[i] >= delays[i]) { + + // update time + prev_millis[i] = current_millis; + + // check if the timer callback has to be executed + if (enabled[i]) { + + // "run forever" timers must always be executed + if (maxNumRuns[i] == RUN_FOREVER) { + toBeCalled[i] = DEFCALL_RUNONLY; + } + // other timers get executed the specified number of times + else if (numRuns[i] < maxNumRuns[i]) { + toBeCalled[i] = DEFCALL_RUNONLY; + numRuns[i]++; + + // after the last run, delete the timer + if (numRuns[i] >= maxNumRuns[i]) { + toBeCalled[i] = DEFCALL_RUNANDDEL; + } + } + } + } + } + } + + for (i = 0; i < MAX_TIMERS; i++) { + switch(toBeCalled[i]) { + case DEFCALL_DONTRUN: + break; + + case DEFCALL_RUNONLY: + (*callbacks[i])(); + break; + + case DEFCALL_RUNANDDEL: + (*callbacks[i])(); + deleteTimer(i); + break; + } + } +} + + +// find the first available slot +// return -1 if none found +int SimpleTimer::findFirstFreeSlot() { + int i; + + // all slots are used + if (numTimers >= MAX_TIMERS) { + return -1; + } + + // return the first slot with no callback (i.e. free) + for (i = 0; i < MAX_TIMERS; i++) { + if (callbacks[i] == 0) { + return i; + } + } + + // we should never reach this point... + return -1; +} + + +int SimpleTimer::setTimer(long d, timer_callback f, int n) { + int freeTimer; + + freeTimer = findFirstFreeSlot(); + if (freeTimer < 0) { + return -1; + } + + delays[freeTimer] = d; + callbacks[freeTimer] = f; + maxNumRuns[freeTimer] = n; + enabled[freeTimer] = true; + prev_millis[freeTimer] = millis(); + + numTimers++; + + return freeTimer; +} + + +int SimpleTimer::setInterval(long d, timer_callback f) { + return setTimer(d, f, RUN_FOREVER); +} + + +int SimpleTimer::setTimeout(long d, timer_callback f) { + return setTimer(d, f, RUN_ONCE); +} + + +void SimpleTimer::deleteTimer(int numTimer) { + if (numTimer >= MAX_TIMERS) { + return; + } + + // nothing to delete if no timers are in use + if (numTimers == 0) { + return; + } + + callbacks[numTimer] = 0; + enabled[numTimer] = false; + delays[numTimer] = 0; + numRuns[numTimer] = 0; + + // update number of timers + numTimers--; +} + + +// function contributed by code@rowansimms.com +void SimpleTimer::restartTimer(int numTimer) { + if (numTimer >= MAX_TIMERS) { + return; + } + + prev_millis[numTimer] = millis(); +} + + +boolean SimpleTimer::isEnabled(int numTimer) { + if (numTimer >= MAX_TIMERS) { + return false; + } + + return enabled[numTimer]; +} + + +void SimpleTimer::enable(int numTimer) { + if (numTimer >= MAX_TIMERS) { + return; + } + + enabled[numTimer] = true; +} + + +void SimpleTimer::disable(int numTimer) { + if (numTimer >= MAX_TIMERS) { + return; + } + + enabled[numTimer] = false; +} + + +void SimpleTimer::toggle(int numTimer) { + if (numTimer >= MAX_TIMERS) { + return; + } + + enabled[numTimer] = !enabled[numTimer]; +} + + +int SimpleTimer::getNumTimers() { + return numTimers; +} diff --git a/libraries/SimpleTimer/SimpleTimer.h b/libraries/SimpleTimer/SimpleTimer.h new file mode 100644 index 0000000..4ed39b5 --- /dev/null +++ b/libraries/SimpleTimer/SimpleTimer.h @@ -0,0 +1,124 @@ +/* + * SimpleTimer.h + * + * SimpleTimer - A timer library for Arduino. + * Author: mromani@ottotecnica.com + * Copyright (c) 2010 OTTOTECNICA Italy + * + * 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 SIMPLETIMER_H +#define SIMPLETIMER_H + +#if defined(ARDUINO) && ARDUINO >= 100 +#include +#else +#include +#endif + +typedef void (*timer_callback)(void); + +class SimpleTimer { + +public: + // maximum number of timers + const static int MAX_TIMERS = 10; + + // setTimer() constants + const static int RUN_FOREVER = 0; + const static int RUN_ONCE = 1; + + // constructor + SimpleTimer(); + + // this function must be called inside loop() + void run(); + + // call function f every d milliseconds + int setInterval(long d, timer_callback f); + + // call function f once after d milliseconds + int setTimeout(long d, timer_callback f); + + // call function f every d milliseconds for n times + int setTimer(long d, timer_callback f, int n); + + // destroy the specified timer + void deleteTimer(int numTimer); + + // restart the specified timer + void restartTimer(int numTimer); + + // returns true if the specified timer is enabled + boolean isEnabled(int numTimer); + + // enables the specified timer + void enable(int numTimer); + + // disables the specified timer + void disable(int numTimer); + + // enables the specified timer if it's currently disabled, + // and vice-versa + void toggle(int numTimer); + + // returns the number of used timers + int getNumTimers(); + + // returns the number of available timers + int getNumAvailableTimers() { return MAX_TIMERS - numTimers; }; + +private: + // deferred call constants + const static int DEFCALL_DONTRUN = 0; // don't call the callback function + const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer + const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer + + // find the first available slot + int findFirstFreeSlot(); + + // value returned by the millis() function + // in the previous run() call + unsigned long prev_millis[MAX_TIMERS]; + + // pointers to the callback functions + timer_callback callbacks[MAX_TIMERS]; + + // delay values + long delays[MAX_TIMERS]; + + // number of runs to be executed for each timer + int maxNumRuns[MAX_TIMERS]; + + // number of executed runs for each timer + int numRuns[MAX_TIMERS]; + + // which timers are enabled + boolean enabled[MAX_TIMERS]; + + // deferred function call (sort of) - N.B.: this array is only used in run() + int toBeCalled[MAX_TIMERS]; + + // actual number of timers in use + int numTimers; +}; + +#endif diff --git a/libraries/SimpleTimer/keywords.txt b/libraries/SimpleTimer/keywords.txt new file mode 100644 index 0000000..c9643fe --- /dev/null +++ b/libraries/SimpleTimer/keywords.txt @@ -0,0 +1,32 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SimpleTimer KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +run KEYWORD2 +setInterval KEYWORD2 +setTimeout KEYWORD2 +setTimer KEYWORD2 +deleteTimer KEYWORD2 +restartTimer KEYWORD2 +isEnabled KEYWORD2 +enable KEYWORD2 +disable KEYWORD2 +toggle KEYWORD2 +getNumTimers KEYWORD2 +getNumAvailableTimers KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +MAX_TIMERS LITERAL1 +RUN_ONCE LITERAL1 +RUN_FOREVER LITERAL1 diff --git a/libraries/Time/DateStrings.cpp b/libraries/Time/DateStrings.cpp new file mode 100644 index 0000000..a0eef9d --- /dev/null +++ b/libraries/Time/DateStrings.cpp @@ -0,0 +1,80 @@ +/* DateStrings.cpp + * Definitions for date strings for use with the Time library + * + * No memory is consumed in the sketch if your code does not call any of the string methods + * You can change the text of the strings, make sure the short strings are each exactly 3 characters + * the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in Time.h + * + */ + +#include +#include "Time.h" + +// the short strings for each day or month must be exactly dt_SHORT_STR_LEN +#define dt_SHORT_STR_LEN 3 // the length of short strings + +static char buffer[dt_MAX_STRING_LEN+1]; // must be big enough for longest string and the terminating null + +const char monthStr1[] PROGMEM = "January"; +const char monthStr2[] PROGMEM = "February"; +const char monthStr3[] PROGMEM = "March"; +const char monthStr4[] PROGMEM = "April"; +const char monthStr5[] PROGMEM = "May"; +const char monthStr6[] PROGMEM = "June"; +const char monthStr7[] PROGMEM = "July"; +const char monthStr8[] PROGMEM = "August"; +const char monthStr9[] PROGMEM = "September"; +const char monthStr10[] PROGMEM = "October"; +const char monthStr11[] PROGMEM = "November"; +const char monthStr12[] PROGMEM = "December"; + +PGM_P const monthNames_P[] PROGMEM = +{ + "",monthStr1,monthStr2,monthStr3,monthStr4,monthStr5,monthStr6, + monthStr7,monthStr8,monthStr9,monthStr10,monthStr11,monthStr12 +}; + +const char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec"; + +const char dayStr0[] PROGMEM = "Err"; +const char dayStr1[] PROGMEM = "Sunday"; +const char dayStr2[] PROGMEM = "Monday"; +const char dayStr3[] PROGMEM = "Tuesday"; +const char dayStr4[] PROGMEM = "Wednesday"; +const char dayStr5[] PROGMEM = "Thursday"; +const char dayStr6[] PROGMEM = "Friday"; +const char dayStr7[] PROGMEM = "Saturday"; + +PGM_P const dayNames_P[] PROGMEM = { dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7}; +const char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThrFriSat"; + +/* functions to return date strings */ + +char* monthStr(uint8_t month) +{ + strcpy_P(buffer, (PGM_P)pgm_read_word(&(monthNames_P[month]))); + return buffer; +} + +char* monthShortStr(uint8_t month) +{ + for (int i=0; i < dt_SHORT_STR_LEN; i++) + buffer[i] = pgm_read_byte(&(monthShortNames_P[i+ (month*dt_SHORT_STR_LEN)])); + buffer[dt_SHORT_STR_LEN] = 0; + return buffer; +} + +char* dayStr(uint8_t day) +{ + strcpy_P(buffer, (PGM_P)pgm_read_word(&(dayNames_P[day]))); + return buffer; +} + +char* dayShortStr(uint8_t day) +{ + uint8_t index = day*dt_SHORT_STR_LEN; + for (int i=0; i < dt_SHORT_STR_LEN; i++) + buffer[i] = pgm_read_byte(&(dayShortNames_P[index + i])); + buffer[dt_SHORT_STR_LEN] = 0; + return buffer; +} diff --git a/libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde b/libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde new file mode 100644 index 0000000..4c74d4b --- /dev/null +++ b/libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde @@ -0,0 +1,70 @@ +/** + * SyncArduinoClock. + * + * portIndex must be set to the port connected to the Arduino + * + * The current time is sent in response to request message from Arduino + * or by clicking the display window + * + * The time message is 11 ASCII text characters; a header (the letter 'T') + * followed by the ten digit system time (unix time) + */ + + +import processing.serial.*; + +public static final short portIndex = 1; // select the com port, 0 is the first port +public static final char TIME_HEADER = 'T'; //header byte for arduino serial time message +public static final char TIME_REQUEST = 7; // ASCII bell character +public static final char LF = 10; // ASCII linefeed +public static final char CR = 13; // ASCII linefeed +Serial myPort; // Create object from Serial class + +void setup() { + size(200, 200); + println(Serial.list()); + println(" Connecting to -> " + Serial.list()[portIndex]); + myPort = new Serial(this,Serial.list()[portIndex], 9600); +} + +void draw() +{ + if ( myPort.available() > 0) { // If data is available, + char val = char(myPort.read()); // read it and store it in val + if(val == TIME_REQUEST){ + long t = getTimeNow(); + sendTimeMessage(TIME_HEADER, t); + } + else + { + if(val == LF) + ; //igonore + else if(val == CR) + println(); + else + print(val); // echo everying but time request + } + } +} + +void mousePressed() { + sendTimeMessage( TIME_HEADER, getTimeNow()); +} + + +void sendTimeMessage(char header, long time) { + String timeStr = String.valueOf(time); + myPort.write(header); // send header and time to arduino + myPort.write(timeStr); +} + +long getTimeNow(){ + // java time is in ms, we want secs + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(new Date()); + int tzo = cal.get(Calendar.ZONE_OFFSET); + int dst = cal.get(Calendar.DST_OFFSET); + long now = (cal.getTimeInMillis() / 1000) ; + now = now + (tzo/1000) + (dst/1000); + return now; +} diff --git a/libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt b/libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt new file mode 100644 index 0000000..985bd80 --- /dev/null +++ b/libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt @@ -0,0 +1,9 @@ +SyncArduinoClock is a Processing sketch that responds to Arduino requests for +time synchronization messages. + +The portIndex must be set the Serial port connected to Arduino. + +Download TimeSerial.pde onto Arduino and you should see the time +message displayed when you run SyncArduinoClock in Processing. +The Arduino time is set from the time on your computer through the +Processing sketch. \ No newline at end of file diff --git a/libraries/Time/Examples/TimeGPS/TimeGPS.pde b/libraries/Time/Examples/TimeGPS/TimeGPS.pde new file mode 100644 index 0000000..1c7b25e --- /dev/null +++ b/libraries/Time/Examples/TimeGPS/TimeGPS.pde @@ -0,0 +1,82 @@ +/* + * TimeGPS.pde + * example code illustrating time synced from a GPS + * + */ + +#include +#include //http://arduiniana.org/libraries/TinyGPS/ +#include //http://arduiniana.org/libraries/newsoftserial/ +// GPS and NewSoftSerial libraries are the work of Mikal Hart + +TinyGPS gps; +NewSoftSerial serial_gps = NewSoftSerial(3, 2); // receive on pin 3 + +const int offset = 1; // offset hours from gps time (UTC) +time_t prevDisplay = 0; // when the digital clock was displayed + +void setup() +{ + Serial.begin(9600); + serial_gps.begin(4800); + Serial.println("Waiting for GPS time ... "); + setSyncProvider(gpsTimeSync); +} + +void loop() +{ + while (serial_gps.available()) + { + gps.encode(serial_gps.read()); // process gps messages + } + if(timeStatus()!= timeNotSet) + { + if( now() != prevDisplay) //update the display only if the time has changed + { + prevDisplay = now(); + digitalClockDisplay(); + } + } +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +time_t gpsTimeSync(){ + // returns time if avail from gps, else returns 0 + unsigned long fix_age = 0 ; + gps.get_datetime(NULL,NULL, &fix_age); + unsigned long time_since_last_fix; + if(fix_age < 1000) + return gpsTimeToArduinoTime(); // return time only if updated recently by gps + return 0; +} + +time_t gpsTimeToArduinoTime(){ + // returns time_t from gps date and time with the given offset hours + tmElements_t tm; + int year; + gps.crack_datetime(&year, &tm.Month, &tm.Day, &tm.Hour, &tm.Minute, &tm.Second, NULL, NULL); + tm.Year = year - 1970; + time_t time = makeTime(tm); + return time + (offset * SECS_PER_HOUR); +} diff --git a/libraries/Time/Examples/TimeNTP/TimeNTP.pde b/libraries/Time/Examples/TimeNTP/TimeNTP.pde new file mode 100644 index 0000000..ff9311a --- /dev/null +++ b/libraries/Time/Examples/TimeNTP/TimeNTP.pde @@ -0,0 +1,120 @@ +/* + * Time_NTP.pde + * Example showing time sync to NTP time source + * + * This sketch uses the Ethenet library with the user contributed UdpBytewise extension + */ + +#include +#include +#include // UDP library from: bjoern@cs.stanford.edu 12/30/2008 +#if UDP_TX_PACKET_MAX_SIZE <64 || UDP_RX_PACKET_MAX_SIZE < 64 +#error : UDP packet size to small - modify UdpBytewise.h to set buffers to 64 bytes +#endif +/* + * + * You may need to modify the UdpBytewise.h library to allow enough space in the buffers for the NTP packets. + * Open up UdpBytewse.h and set the following buffers to 64 bytes: + * #define UDP_TX_PACKET_MAX_SIZE 64 + * #define UDP_RX_PACKET_MAX_SIZE 64 + */ + + +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +byte ip[] = { 192, 168, 1, 44 }; // set the IP address to an unused address on your network + +byte SNTP_server_IP[] = { 192, 43, 244, 18}; // time.nist.gov +//byte SNTP_server_IP[] = { 130,149,17,21}; // ntps1-0.cs.tu-berlin.de +//byte SNTP_server_IP[] = { 192,53,103,108}; // ptbtime1.ptb.de + + +time_t prevDisplay = 0; // when the digital clock was displayed +const long timeZoneOffset = 0L; // set this to the offset in seconds to your local time; + +void setup() +{ + Serial.begin(9600); + Ethernet.begin(mac,ip); + Serial.println("waiting for sync"); + setSyncProvider(getNtpTime); + while(timeStatus()== timeNotSet) + ; // wait until the time is set by the sync provider +} + +void loop() +{ + if( now() != prevDisplay) //update the display only if the time has changed + { + prevDisplay = now(); + digitalClockDisplay(); + } +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +/*-------- NTP code ----------*/ + +unsigned long getNtpTime() +{ + sendNTPpacket(SNTP_server_IP); + delay(1000); + if ( UdpBytewise.available() ) { + for(int i=0; i < 40; i++) + UdpBytewise.read(); // ignore every field except the time + const unsigned long seventy_years = 2208988800UL + timeZoneOffset; + return getUlong() - seventy_years; + } + return 0; // return 0 if unable to get the time +} + +unsigned long sendNTPpacket(byte *address) +{ + UdpBytewise.begin(123); + UdpBytewise.beginPacket(address, 123); + UdpBytewise.write(B11100011); // LI, Version, Mode + UdpBytewise.write(0); // Stratum + UdpBytewise.write(6); // Polling Interval + UdpBytewise.write(0xEC); // Peer Clock Precision + write_n(0, 8); // Root Delay & Root Dispersion + UdpBytewise.write(49); + UdpBytewise.write(0x4E); + UdpBytewise.write(49); + UdpBytewise.write(52); + write_n(0, 32); //Reference and time stamps + UdpBytewise.endPacket(); +} + +unsigned long getUlong() +{ + unsigned long ulong = (unsigned long)UdpBytewise.read() << 24; + ulong |= (unsigned long)UdpBytewise.read() << 16; + ulong |= (unsigned long)UdpBytewise.read() << 8; + ulong |= (unsigned long)UdpBytewise.read(); + return ulong; +} + +void write_n(int what, int how_many) +{ + for( int i = 0; i < how_many; i++ ) + UdpBytewise.write(what); +} diff --git a/libraries/Time/Examples/TimeRTC/TimeRTC.pde b/libraries/Time/Examples/TimeRTC/TimeRTC.pde new file mode 100644 index 0000000..0e37c51 --- /dev/null +++ b/libraries/Time/Examples/TimeRTC/TimeRTC.pde @@ -0,0 +1,47 @@ +/* + * TimeRTC.pde + * example code illustrating Time library with Real Time Clock. + * + */ + +#include +#include +#include // a basic DS1307 library that returns time as a time_t + +void setup() { + Serial.begin(9600); + setSyncProvider(RTC.get); // the function to get the time from the RTC + if(timeStatus()!= timeSet) + Serial.println("Unable to sync with the RTC"); + else + Serial.println("RTC has set the system time"); +} + +void loop() +{ + digitalClockDisplay(); + delay(1000); +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + diff --git a/libraries/Time/Examples/TimeRTCLog/TimeRTCLog.pde b/libraries/Time/Examples/TimeRTCLog/TimeRTCLog.pde new file mode 100644 index 0000000..b8297b6 --- /dev/null +++ b/libraries/Time/Examples/TimeRTCLog/TimeRTCLog.pde @@ -0,0 +1,106 @@ +/* + * TimeRTCLogger.pde + * example code illustrating adding and subtracting Time. + * + * this sketch logs pin state change events + * the time of the event and time since the previous event is calculated and sent to the serial port. + */ + +#include +#include +#include // a basic DS1307 library that returns time as a time_t + +const int nbrInputPins = 6; // monitor 6 digital pins +const int inputPins[nbrInputPins] = {2,3,4,5,6,7}; // pins to monitor +boolean state[nbrInputPins] ; // the state of the monitored pins +time_t prevEventTime[nbrInputPins] ; // the time of the previous event + +void setup() { + Serial.begin(9600); + setSyncProvider(RTC.get); // the function to sync the time from the RTC + for(int i=0; i < nbrInputPins; i++){ + pinMode( inputPins[i], INPUT); + // digitalWrite( inputPins[i], HIGH); // uncomment these lines if + // state[i] = HIGH; // pull-up resistors are wanted + } +} + +void loop() +{ + for(int i=0; i < nbrInputPins; i++) + { + boolean val = digitalRead(inputPins[i]); + if(val != state[i]) + { + time_t duration = 0; // the time since the previous event + state[i] = val; + time_t timeNow = now(); + if(prevEventTime[i] > 0) + // if this was not the first state change, calculate the time from the previous change + duration = duration = timeNow - prevEventTime[i]; + logEvent(inputPins[i], val, timeNow, duration ); // log the event + prevEventTime[i] = timeNow; // store the time for this event + } + } +} + +void logEvent( int pin, boolean state, time_t timeNow, time_t duration) +{ + Serial.print("Pin "); + Serial.print(pin); + if( state == HIGH) + Serial.print(" went High at "); + else + Serial.print(" went Low at "); + showTime(timeNow); + if(duration > 0){ + // only display duration if greater than 0 + Serial.print(", Duration was "); + showDuration(duration); + } + Serial.println(); +} + + +void showTime(time_t t){ + // display the given time + Serial.print(hour(t)); + printDigits(minute(t)); + printDigits(second(t)); + Serial.print(" "); + Serial.print(day(t)); + Serial.print(" "); + Serial.print(month(t)); + Serial.print(" "); + Serial.print(year(t)); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +void showDuration(time_t duration){ +// prints the duration in days, hours, minutes and seconds + if(duration >= SECS_PER_DAY){ + Serial.print(duration / SECS_PER_DAY); + Serial.print(" day(s) "); + duration = duration % SECS_PER_DAY; + } + if(duration >= SECS_PER_HOUR){ + Serial.print(duration / SECS_PER_HOUR); + Serial.print(" hour(s) "); + duration = duration % SECS_PER_HOUR; + } + if(duration >= SECS_PER_MIN){ + Serial.print(duration / SECS_PER_MIN); + Serial.print(" minute(s) "); + duration = duration % SECS_PER_MIN; + } + Serial.print(duration); + Serial.print(" second(s) "); +} + diff --git a/libraries/Time/Examples/TimeRTCSet/TimeRTCSet.pde b/libraries/Time/Examples/TimeRTCSet/TimeRTCSet.pde new file mode 100644 index 0000000..e798164 --- /dev/null +++ b/libraries/Time/Examples/TimeRTCSet/TimeRTCSet.pde @@ -0,0 +1,82 @@ +/* + * TimeRTCSet.pde + * example code illustrating Time library with Real Time Clock. + * + * RTC clock is set in response to serial port time message + * A Processing example sketch to set the time is inclided in the download + */ + +#include +#include +#include // a basic DS1307 library that returns time as a time_t + + +void setup() { + Serial.begin(9600); + setSyncProvider(RTC.get); // the function to get the time from the RTC + if(timeStatus()!= timeSet) + Serial.println("Unable to sync with the RTC"); + else + Serial.println("RTC has set the system time"); +} + +void loop() +{ + if(Serial.available()) + { + time_t t = processSyncMessage(); + if(t >0) + { + RTC.set(t); // set the RTC and the system time to the received value + setTime(t); + } + } + digitalClockDisplay(); + delay(1000); +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +/* code to process time sync messages from the serial port */ +#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits +#define TIME_HEADER 'T' // Header tag for serial time sync message + +time_t processSyncMessage() { + // return the time if a valid sync message is received on the serial port. + while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits + char c = Serial.read() ; + Serial.print(c); + if( c == TIME_HEADER ) { + time_t pctime = 0; + for(int i=0; i < TIME_MSG_LEN -1; i++){ + c = Serial.read(); + if( c >= '0' && c <= '9'){ + pctime = (10 * pctime) + (c - '0') ; // convert digits to a number + } + } + return pctime; + } + } + return 0; +} + diff --git a/libraries/Time/Examples/TimeSerial/TimeSerial.pde b/libraries/Time/Examples/TimeSerial/TimeSerial.pde new file mode 100644 index 0000000..382c598 --- /dev/null +++ b/libraries/Time/Examples/TimeSerial/TimeSerial.pde @@ -0,0 +1,82 @@ +/* + * TimeSerial.pde + * example code illustrating Time library set through serial port messages. + * + * Messages consist of the letter T followed by ten digit time (as seconds since Jan 1 1970) + * you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2010 + T1262347200 + * + * A Processing example sketch to automatically send the messages is inclided in the download + */ + +#include + +#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits +#define TIME_HEADER 'T' // Header tag for serial time sync message +#define TIME_REQUEST 7 // ASCII bell character requests a time sync message + +void setup() { + Serial.begin(9600); + setSyncProvider( requestSync); //set function to call when sync required + Serial.println("Waiting for sync message"); +} + +void loop(){ + if(Serial.available() ) + { + processSyncMessage(); + } + if(timeStatus()!= timeNotSet) + { + digitalWrite(13,timeStatus() == timeSet); // on if synced, off if needs refresh + digitalClockDisplay(); + } + delay(1000); +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +void processSyncMessage() { + // if time sync available from serial port, update time and return true + while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits + char c = Serial.read() ; + Serial.print(c); + if( c == TIME_HEADER ) { + time_t pctime = 0; + for(int i=0; i < TIME_MSG_LEN -1; i++){ + c = Serial.read(); + if( c >= '0' && c <= '9'){ + pctime = (10 * pctime) + (c - '0') ; // convert digits to a number + } + } + setTime(pctime); // Sync Arduino clock to the time received on the serial port + } + } +} + +time_t requestSync() +{ + Serial.print(TIME_REQUEST,BYTE); + return 0; // the time will be sent later in response to serial mesg +} + diff --git a/libraries/Time/Examples/TimeSerialDateStrings/TimeSerialDateStrings.pde b/libraries/Time/Examples/TimeSerialDateStrings/TimeSerialDateStrings.pde new file mode 100644 index 0000000..62eac10 --- /dev/null +++ b/libraries/Time/Examples/TimeSerialDateStrings/TimeSerialDateStrings.pde @@ -0,0 +1,80 @@ +/* + * TimeSerialDateStrings.pde + * example code illustrating Time library date strings + * + * This sketch adds date string functionality to TimeSerial.pde + * + */ + +#include + +#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits +#define TIME_HEADER 'T' // Header tag for serial time sync message +#define TIME_REQUEST 7 // ASCII bell character requests a time sync message + +void setup() { + Serial.begin(9600); + setSyncProvider( requestSync); //set function to call when sync required + Serial.println("Waiting for sync message"); +} + +void loop(){ + if(Serial.available() ) + { + processSyncMessage(); + } + if(timeStatus()!= timeNotSet) + { + digitalClockDisplay(); + } + delay(1000); +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(dayStr(weekday())); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(monthShortStr(month())); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +void processSyncMessage() { + // if time sync available from serial port, update time and return true + while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits + char c = Serial.read() ; + Serial.print(c); + if( c == TIME_HEADER ) { + time_t pctime = 0; + for(int i=0; i < TIME_MSG_LEN -1; i++){ + c = Serial.read(); + if( c >= '0' && c <= '9'){ + pctime = (10 * pctime) + (c - '0') ; // convert digits to a number + } + } + setTime(pctime); // Sync Arduino clock to the time received on the serial port + } + } +} + +time_t requestSync() +{ + Serial.print(TIME_REQUEST,BYTE); + return 0; // the time will be sent later in response to serial mesg +} + diff --git a/libraries/Time/Readme.txt b/libraries/Time/Readme.txt new file mode 100644 index 0000000..06d82f1 --- /dev/null +++ b/libraries/Time/Readme.txt @@ -0,0 +1,131 @@ +Readme file for Arduino Time Library + +Time is a library that provides timekeeping functionality for Arduino. + +The code is derived from the Playground DateTime library but is updated +to provide an API that is more flexable and easier to use. + +A primary goal was to enable date and time functionality that can be used with +a variety of external time sources with minimum differences required in sketch logic. + +Example sketches illustrate how similar sketch code can be used with: a Real Time Clock, +internet NTP time service, GPS time data, and Serial time messages from a computer +for time synchronization. + +The functions available in the library include: + +hour(); // the hour now (0-23) +minute(); // the minute now (0-59) +second(); // the second now (0-59) +day(); // the day now (1-31) +weekday(); // day of the week, Sunday is day 0 +month(); // the month now (1-12) +year(); // the full four digit year: (2009, 2010 etc) + +there are also functions to return the hour in 12 hour format +hourFormat12(); // the hour now in 12 hour format +isAM(); // returns true if time now is AM +isPM(); // returns true if time now is PM + +now(); // returns the current time as seconds since Jan 1 1970 + +The time and date functions can take an optional parameter for the time. This prevents +errors if the time rolls over between elements. For example, if a new minute begins +between getting the minute and second, the values will be inconsistent. Using the +following functions eliminates this probglem + time_t t = now(); // store the current time in time variable t + hour(t); // returns the hour for the given time t + minute(t); // returns the minute for the given time t + second(t); // returns the second for the given time t + day(t); // the day for the given time t + weekday(t); // day of the week for the given time t + month(t); // the month for the given time t + year(t); // the year for the given time t + + +Functions for managing the timer services are: +setTime(t); // set the system time to the give time t +setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr (2010 or 10 sets year to 2010) +adjustTime(adjustment); // adjust system time by adding the adjustment value + +timeStatus(); // indicates if time has been set and recently synchronized + // returns one of the following enumerations: + timeNotSet // the time has never been set, the clock started at Jan 1 1970 + timeNeedsSync // the time had been set but a sync attempt did not succeed + timeSet // the time is set and is synced +Time and Date values are not valid if the status is timeNotSet. Otherwise values can be used but +the returned time may have drifted if the status is timeNeedsSync. + +setSyncProvider(getTimeFunction); // set the external time provider +setSyncInterval(interval); // set the number of seconds between re-sync + + +There are many convenience macros in the time.h file for time constants and conversion of time units. + +To use the library, copy the download to the Library directory. + +The Time directory contains the Time library and some example sketches +illustrating how the library can be used with various time sources: + +- TimeSerial.pde shows Arduino as a clock without external hardware. + It is synchronized by time messages sent over the serial port. + A companion Processing sketch will automatically provide these messages + if it is running and connected to the Arduino serial port. + +- TimeSerialDateStrings.pde adds day and month name strings to the sketch above + Short (3 character) and long strings are available to print the days of + the week and names of the months. + +- TimeRTC uses a DS1307 real time clock to provide time synchronization. + A basic RTC library named DS1307RTC is included in the download. + To run this sketch the DS1307RTC library must be installed. + +- TimeRTCSet is similar to the above and adds the ability to set the Real Time Clock + +- TimeRTCLog demonstrates how to calculate the difference between times. + It is a vary simple logger application that monitors events on digtial pins + and prints (to the serial port) the time of an event and the time period since the previous event. + +- TimeNTP uses the Arduino Ethernet shield to access time using the internet NTP time service. + The NTP protocol uses UDP and the UdpBytewise library is required, see: + http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/ + +-TimeGPS gets time from a GPS + This requires the TinyGPS and NewSoftSerial libraries from Mikal Hart: + http://arduiniana.org/libraries/TinyGPS and http://arduiniana.org/libraries/newsoftserial/ + +Differences between this code and the playground DateTime library +although the Time library is based on the DateTime codebase, the API has changed. +Changes in the Time library API: +- time elements are functions returning int (they are variables in DateTime) +- Years start from 1970 +- days of the week and months start from 1 (they start from 0 in DateTime) +- DateStrings do not require a seperate library +- time elements can be accessed non-atomically (in DateTime they are always atomic) +- function added to automatically sync time with extrnal source +- localTime and maketime parameters changed, localTime renamed to breakTime + +Technical notes: + +Internal system time is based on the standard Unix time_t. +The value is the number of seconds since Jan 1 1970. +System time begins at zero when the sketch starts. + +The internal time can be automatically synchronized at regular intervals to an external time source. +This is enabled by calling the setSyncProvider(provider) function - the provider argument is +the address of a function that returns the current time as a time_t. +See the sketches in the examples directory for usage. + +The default interval for re-syncing the time is 5 minutes but can be changed by calling the +setSyncInterval( interval) method to set the number of seconds between re-sync attempts. + +The Time library defines a structure for holding time elements that is a compact version of the C tm structure. +All the members of the Arduino tm structure are bytes and the year is offset from 1970. +Convenience macros provide conversion to and from the Arduino format. + +Low level functions to convert between system time and individual time elements are provided: + breakTime( time, &tm); // break time_t into elements stored in tm struct + makeTime( &tm); // return time_t from elements stored in tm struct + +The DS1307RTC library included in the download provides an example of how a time provider +can use the low level functions to interface with the Time library. \ No newline at end of file diff --git a/libraries/Time/Time.cpp b/libraries/Time/Time.cpp new file mode 100644 index 0000000..86bdcd5 --- /dev/null +++ b/libraries/Time/Time.cpp @@ -0,0 +1,307 @@ +/* + time.c - low level time and date functions + Copyright (c) Michael Margolis 2009 + + 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 + + 6 Jan 2010 - initial release + 12 Feb 2010 - fixed leap year calculation error + 1 Nov 2010 - fixed setTime bug (thanks to Korman for this) +*/ + +#if ARDUINO >= 100 +#include +#else +#include +#endif + +#include "Time.h" + +static tmElements_t tm; // a cache of time elements +static time_t cacheTime; // the time the cache was updated +static time_t syncInterval = 300; // time sync will be attempted after this many seconds + +void refreshCache( time_t t){ + if( t != cacheTime) + { + breakTime(t, tm); + cacheTime = t; + } +} + +int hour() { // the hour now + return hour(now()); +} + +int hour(time_t t) { // the hour for the given time + refreshCache(t); + return tm.Hour; +} + +int hourFormat12() { // the hour now in 12 hour format + return hourFormat12(now()); +} + +int hourFormat12(time_t t) { // the hour for the given time in 12 hour format + refreshCache(t); + if( tm.Hour == 0 ) + return 12; // 12 midnight + else if( tm.Hour > 12) + return tm.Hour - 12 ; + else + return tm.Hour ; +} + +uint8_t isAM() { // returns true if time now is AM + return !isPM(now()); +} + +uint8_t isAM(time_t t) { // returns true if given time is AM + return !isPM(t); +} + +uint8_t isPM() { // returns true if PM + return isPM(now()); +} + +uint8_t isPM(time_t t) { // returns true if PM + return (hour(t) >= 12); +} + +int minute() { + return minute(now()); +} + +int minute(time_t t) { // the minute for the given time + refreshCache(t); + return tm.Minute; +} + +int second() { + return second(now()); +} + +int second(time_t t) { // the second for the given time + refreshCache(t); + return tm.Second; +} + +int day(){ + return(day(now())); +} + +int day(time_t t) { // the day for the given time (0-6) + refreshCache(t); + return tm.Day; +} + +int weekday() { // Sunday is day 1 + return weekday(now()); +} + +int weekday(time_t t) { + refreshCache(t); + return tm.Wday; +} + +int month(){ + return month(now()); +} + +int month(time_t t) { // the month for the given time + refreshCache(t); + return tm.Month; +} + +int year() { // as in Processing, the full four digit year: (2009, 2010 etc) + return year(now()); +} + +int year(time_t t) { // the year for the given time + refreshCache(t); + return tmYearToCalendar(tm.Year); +} + +/*============================================================================*/ +/* functions to convert to and from system time */ +/* These are for interfacing with time serivces and are not normally needed in a sketch */ + +// leap year calulator expects year argument as years offset from 1970 +#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) + +static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0 + +void breakTime(time_t time, tmElements_t &tm){ +// break the given time_t into time components +// this is a more compact version of the C library localtime function +// note that year is offset from 1970 !!! + + uint8_t year; + uint8_t month, monthLength; + unsigned long days; + + tm.Second = time % 60; + time /= 60; // now it is minutes + tm.Minute = time % 60; + time /= 60; // now it is hours + tm.Hour = time % 24; + time /= 24; // now it is days + tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1 + + year = 0; + days = 0; + while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { + year++; + } + tm.Year = year; // year is offset from 1970 + + days -= LEAP_YEAR(year) ? 366 : 365; + time -= days; // now it is days in this year, starting at 0 + + days=0; + month=0; + monthLength=0; + for (month=0; month<12; month++) { + if (month==1) { // february + if (LEAP_YEAR(year)) { + monthLength=29; + } else { + monthLength=28; + } + } else { + monthLength = monthDays[month]; + } + + if (time >= monthLength) { + time -= monthLength; + } else { + break; + } + } + tm.Month = month + 1; // jan is month 1 + tm.Day = time + 1; // day of month +} + +time_t makeTime(tmElements_t &tm){ +// assemble time elements into time_t +// note year argument is offset from 1970 (see macros in time.h to convert to other formats) +// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9 + + int i; + time_t seconds; + + // seconds from 1970 till 1 jan 00:00:00 of the given year + seconds= tm.Year*(SECS_PER_DAY * 365); + for (i = 0; i < tm.Year; i++) { + if (LEAP_YEAR(i)) { + seconds += SECS_PER_DAY; // add extra days for leap years + } + } + + // add days for this year, months start from 1 + for (i = 1; i < tm.Month; i++) { + if ( (i == 2) && LEAP_YEAR(tm.Year)) { + seconds += SECS_PER_DAY * 29; + } else { + seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0 + } + } + seconds+= (tm.Day-1) * SECS_PER_DAY; + seconds+= tm.Hour * SECS_PER_HOUR; + seconds+= tm.Minute * SECS_PER_MIN; + seconds+= tm.Second; + return seconds; +} +/*=====================================================*/ +/* Low level system time functions */ + +static time_t sysTime = 0; +static time_t prevMillis = 0; +static time_t nextSyncTime = 0; +static timeStatus_t Status = timeNotSet; + +getExternalTime getTimePtr; // pointer to external sync function +//setExternalTime setTimePtr; // not used in this version + +#ifdef TIME_DRIFT_INFO // define this to get drift data +time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync +#endif + + +time_t now(){ + while( millis() - prevMillis >= 1000){ + sysTime++; + prevMillis += 1000; +#ifdef TIME_DRIFT_INFO + sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift +#endif + } + if(nextSyncTime <= sysTime){ + if(getTimePtr != 0){ + time_t t = getTimePtr(); + if( t != 0) + setTime(t); + else + Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync; + } + } + return sysTime; +} + +void setTime(time_t t){ +#ifdef TIME_DRIFT_INFO + if(sysUnsyncedTime == 0) + sysUnsyncedTime = t; // store the time of the first call to set a valid Time +#endif + + sysTime = t; + nextSyncTime = t + syncInterval; + Status = timeSet; + prevMillis = millis(); // restart counting from now (thanks to Korman for this fix) +} + +void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ + // year can be given as full four digit year or two digts (2010 or 10 for 2010); + //it is converted to years since 1970 + if( yr > 99) + yr = yr - 1970; + else + yr += 30; + tm.Year = yr; + tm.Month = mnth; + tm.Day = dy; + tm.Hour = hr; + tm.Minute = min; + tm.Second = sec; + setTime(makeTime(tm)); +} + +void adjustTime(long adjustment){ + sysTime += adjustment; +} + +timeStatus_t timeStatus(){ // indicates if time has been set and recently synchronized + return Status; +} + +void setSyncProvider( getExternalTime getTimeFunction){ + getTimePtr = getTimeFunction; + nextSyncTime = sysTime; + now(); // this will sync the clock +} + +void setSyncInterval(time_t interval){ // set the number of seconds between re-sync + syncInterval = interval; +} \ No newline at end of file diff --git a/libraries/Time/Time.h b/libraries/Time/Time.h new file mode 100644 index 0000000..e54f3b0 --- /dev/null +++ b/libraries/Time/Time.h @@ -0,0 +1,126 @@ +/* + time.h - low level time and date functions +*/ + +/* + July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this) + - fixed daysToTime_t macro (thanks maniacbug) +*/ + +#ifndef _Time_h +#define _Time_h + +#include + +typedef unsigned long time_t; + +typedef enum {timeNotSet, timeNeedsSync, timeSet +} timeStatus_t ; + +typedef enum { + dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday +} timeDayOfWeek_t; + +typedef enum { + tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields +} tmByteFields; + +typedef struct { + uint8_t Second; + uint8_t Minute; + uint8_t Hour; + uint8_t Wday; // day of week, sunday is day 1 + uint8_t Day; + uint8_t Month; + uint8_t Year; // offset from 1970; +} tmElements_t, TimeElements, *tmElementsPtr_t; + +//convenience macros to convert to and from tm years +#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year +#define CalendarYrToTm(Y) ((Y) - 1970) +#define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000 +#define y2kYearToTm(Y) ((Y) + 30) + +typedef time_t(*getExternalTime)(); +//typedef void (*setExternalTime)(const time_t); // not used in this version + + +/*==============================================================================*/ +/* Useful Constants */ +#define SECS_PER_MIN (60UL) +#define SECS_PER_HOUR (3600UL) +#define SECS_PER_DAY (SECS_PER_HOUR * 24UL) +#define DAYS_PER_WEEK (7UL) +#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK) +#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL) +#define SECS_YR_2000 (946684800UL) // the time at the start of y2k + +/* Useful Macros for getting elapsed time */ +#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) +#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) +#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR) +#define dayOfWeek(_time_) ((( _time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday +#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) // this is number of days since Jan 1 1970 +#define elapsedSecsToday(_time_) (_time_ % SECS_PER_DAY) // the number of seconds since last midnight +// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971 +// Always set the correct time before settting alarms +#define previousMidnight(_time_) (( _time_ / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day +#define nextMidnight(_time_) ( previousMidnight(_time_) + SECS_PER_DAY ) // time at the end of the given day +#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY) ) // note that week starts on day 1 +#define previousSunday(_time_) (_time_ - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time +#define nextSunday(_time_) ( previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time + + +/* Useful Macros for converting elapsed time to a time_t */ +#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN) +#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR) +#define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011 +#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK) + +/*============================================================================*/ +/* time and date functions */ +int hour(); // the hour now +int hour(time_t t); // the hour for the given time +int hourFormat12(); // the hour now in 12 hour format +int hourFormat12(time_t t); // the hour for the given time in 12 hour format +uint8_t isAM(); // returns true if time now is AM +uint8_t isAM(time_t t); // returns true the given time is AM +uint8_t isPM(); // returns true if time now is PM +uint8_t isPM(time_t t); // returns true the given time is PM +int minute(); // the minute now +int minute(time_t t); // the minute for the given time +int second(); // the second now +int second(time_t t); // the second for the given time +int day(); // the day now +int day(time_t t); // the day for the given time +int weekday(); // the weekday now (Sunday is day 1) +int weekday(time_t t); // the weekday for the given time +int month(); // the month now (Jan is month 1) +int month(time_t t); // the month for the given time +int year(); // the full four digit year: (2009, 2010 etc) +int year(time_t t); // the year for the given time + +time_t now(); // return the current time as seconds since Jan 1 1970 +void setTime(time_t t); +void setTime(int hr,int min,int sec,int day, int month, int yr); +void adjustTime(long adjustment); + +/* date strings */ +#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null) +char* monthStr(uint8_t month); +char* dayStr(uint8_t day); +char* monthShortStr(uint8_t month); +char* dayShortStr(uint8_t day); + +/* time sync functions */ +timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized +void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider +void setSyncInterval(time_t interval); // set the number of seconds between re-sync + +/* low level functions to convert to and from system time */ +void breakTime(time_t time, tmElements_t &tm); // break time_t into elements +time_t makeTime(tmElements_t &tm); // convert time elements into time_t + + +#endif /* _Time_h */ + diff --git a/libraries/Time/keywords.txt b/libraries/Time/keywords.txt new file mode 100644 index 0000000..f921672 --- /dev/null +++ b/libraries/Time/keywords.txt @@ -0,0 +1,33 @@ +####################################### +# Syntax Coloring Map For Time +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### +time_t KEYWORD1 +####################################### +# Methods and Functions (KEYWORD2) +####################################### +now KEYWORD2 +second KEYWORD2 +minute KEYWORD2 +hour KEYWORD2 +day KEYWORD2 +month KEYWORD2 +year KEYWORD2 +isAM KEYWORD2 +isPM KEYWORD2 +weekday KEYWORD2 +setTime KEYWORD2 +adjustTime KEYWORD2 +setSyncProvider KEYWORD2 +setSyncInteval KEYWORD2 +timeStatus KEYWORD2 +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/UIPEthernet/Dhcp.cpp b/libraries/UIPEthernet/Dhcp.cpp new file mode 100644 index 0000000..d34e8e2 --- /dev/null +++ b/libraries/UIPEthernet/Dhcp.cpp @@ -0,0 +1,478 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#include +#include +#include "Dhcp.h" +#include "Arduino.h" +#include "utility/util.h" + +int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) +{ + _dhcpLeaseTime=0; + _dhcpT1=0; + _dhcpT2=0; + _lastCheck=0; + _timeout = timeout; + _responseTimeout = responseTimeout; + + // zero out _dhcpMacAddr + memset(_dhcpMacAddr, 0, 6); + reset_DHCP_lease(); + + memcpy((void*)_dhcpMacAddr, (void*)mac, 6); + _dhcp_state = STATE_DHCP_START; + return request_DHCP_lease(); +} + +void DhcpClass::reset_DHCP_lease(){ + // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp + memset(_dhcpLocalIp, 0, 20); +} + +//return:0 on error, 1 if request is sent and response is received +int DhcpClass::request_DHCP_lease(){ + + uint8_t messageType = 0; + + + + // Pick an initial transaction ID + _dhcpTransactionId = random(1UL, 2000UL); + _dhcpInitialTransactionId = _dhcpTransactionId; + + _dhcpUdpSocket.stop(); + if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) + { + // Couldn't get a socket + return 0; + } + + presend_DHCP(); + + int result = 0; + + unsigned long startTime = millis(); + + while(_dhcp_state != STATE_DHCP_LEASED) + { + if(_dhcp_state == STATE_DHCP_START) + { + _dhcpTransactionId++; + + send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_DISCOVER; + } + else if(_dhcp_state == STATE_DHCP_REREQUEST){ + _dhcpTransactionId++; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + else if(_dhcp_state == STATE_DHCP_DISCOVER) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_OFFER) + { + // We'll use the transaction ID that the offer came with, + // rather than the one we were up to + _dhcpTransactionId = respId; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + } + else if(_dhcp_state == STATE_DHCP_REQUEST) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_ACK) + { + _dhcp_state = STATE_DHCP_LEASED; + result = 1; + //use default lease time if we didn't get it + if(_dhcpLeaseTime == 0){ + _dhcpLeaseTime = DEFAULT_LEASE; + } + //calculate T1 & T2 if we didn't get it + if(_dhcpT1 == 0){ + //T1 should be 50% of _dhcpLeaseTime + _dhcpT1 = _dhcpLeaseTime >> 1; + } + if(_dhcpT2 == 0){ + //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime + _dhcpT2 = _dhcpT1 << 1; + } + _renewInSec = _dhcpT1; + _rebindInSec = _dhcpT2; + } + else if(messageType == DHCP_NAK) + _dhcp_state = STATE_DHCP_START; + } + + if(messageType == 255) + { + messageType = 0; + _dhcp_state = STATE_DHCP_START; + } + + if(result != 1 && ((millis() - startTime) > _timeout)) + break; + } + + // We're done with the socket now + _dhcpUdpSocket.stop(); + _dhcpTransactionId++; + + return result; +} + +void DhcpClass::presend_DHCP() +{ +} + +void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) +{ + uint8_t buffer[32]; + memset(buffer, 0, 32); + IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address + + if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) + { + // FIXME Need to return errors + return; + } + + buffer[0] = DHCP_BOOTREQUEST; // op + buffer[1] = DHCP_HTYPE10MB; // htype + buffer[2] = DHCP_HLENETHERNET; // hlen + buffer[3] = DHCP_HOPS; // hops + + // xid + unsigned long xid = htonl(_dhcpTransactionId); + memcpy(buffer + 4, &(xid), 4); + + // 8, 9 - seconds elapsed + buffer[8] = ((secondsElapsed & 0xff00) >> 8); + buffer[9] = (secondsElapsed & 0x00ff); + + // flags + unsigned short flags = htons(DHCP_FLAGSBROADCAST); + memcpy(buffer + 10, &(flags), 2); + + // ciaddr: already zeroed + // yiaddr: already zeroed + // siaddr: already zeroed + // giaddr: already zeroed + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 28); + + memset(buffer, 0, 32); // clear local buffer + + memcpy(buffer, _dhcpMacAddr, 6); // chaddr + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 16); + + memset(buffer, 0, 32); // clear local buffer + + // leave zeroed out for sname && file + // put in W5100 transmit buffer x 6 (192 bytes) + + for(int i = 0; i < 6; i++) { + _dhcpUdpSocket.write(buffer, 32); + } + + // OPT - Magic Cookie + buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); + buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); + buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); + buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); + + // OPT - message type + buffer[4] = dhcpMessageType; + buffer[5] = 0x01; + buffer[6] = messageType; //DHCP_REQUEST; + + // OPT - client identifier + buffer[7] = dhcpClientIdentifier; + buffer[8] = 0x07; + buffer[9] = 0x01; + memcpy(buffer + 10, _dhcpMacAddr, 6); + + // OPT - host name + buffer[16] = hostName; + buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address + strcpy((char*)&(buffer[18]), HOST_NAME); + + printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); + printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); + printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 30); + + if(messageType == DHCP_REQUEST) + { + buffer[0] = dhcpRequestedIPaddr; + buffer[1] = 0x04; + buffer[2] = _dhcpLocalIp[0]; + buffer[3] = _dhcpLocalIp[1]; + buffer[4] = _dhcpLocalIp[2]; + buffer[5] = _dhcpLocalIp[3]; + + buffer[6] = dhcpServerIdentifier; + buffer[7] = 0x04; + buffer[8] = _dhcpDhcpServerIp[0]; + buffer[9] = _dhcpDhcpServerIp[1]; + buffer[10] = _dhcpDhcpServerIp[2]; + buffer[11] = _dhcpDhcpServerIp[3]; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 12); + } + + buffer[0] = dhcpParamRequest; + buffer[1] = 0x06; + buffer[2] = subnetMask; + buffer[3] = routersOnSubnet; + buffer[4] = dns; + buffer[5] = domainName; + buffer[6] = dhcpT1value; + buffer[7] = dhcpT2value; + buffer[8] = endOption; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 9); + + _dhcpUdpSocket.endPacket(); +} + +uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) +{ + uint8_t type = 0; + uint8_t opt_len = 0; + + unsigned long startTime = millis(); + + while(_dhcpUdpSocket.parsePacket() <= 0) + { + if((millis() - startTime) > responseTimeout) + { + return 255; + } + delay(50); + } + // start reading in the packet + RIP_MSG_FIXED fixedMsg; + _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); + + if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) + { + transactionId = ntohl(fixedMsg.xid); + if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) + { + // Need to read the rest of the packet here regardless + _dhcpUdpSocket.flush(); + return 0; + } + + memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); + + // Skip to the option part + // Doing this a byte at a time so we don't have to put a big buffer + // on the stack (as we don't have lots of memory lying around) + for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) + { + _dhcpUdpSocket.read(); // we don't care about the returned byte + } + + while (_dhcpUdpSocket.available() > 0) + { + switch (_dhcpUdpSocket.read()) + { + case endOption : + break; + + case padOption : + break; + + case dhcpMessageType : + opt_len = _dhcpUdpSocket.read(); + type = _dhcpUdpSocket.read(); + break; + + case subnetMask : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpSubnetMask, 4); + break; + + case routersOnSubnet : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpGatewayIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dns : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpDnsServerIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dhcpServerIdentifier : + opt_len = _dhcpUdpSocket.read(); + if( *((uint32_t*)_dhcpDhcpServerIp) == 0 || + IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() ) + { + _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); + } + else + { + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + } + break; + + case dhcpT1value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); + _dhcpT1 = ntohl(_dhcpT1); + break; + + case dhcpT2value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); + _dhcpT2 = ntohl(_dhcpT2); + break; + + case dhcpIPaddrLeaseTime : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); + _dhcpLeaseTime = ntohl(_dhcpLeaseTime); + _renewInSec = _dhcpLeaseTime; + break; + + default : + opt_len = _dhcpUdpSocket.read(); + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + break; + } + } + } + + // Need to skip to end of the packet regardless here + _dhcpUdpSocket.flush(); + + return type; +} + + +/* + returns: + 0/DHCP_CHECK_NONE: nothing happened + 1/DHCP_CHECK_RENEW_FAIL: renew failed + 2/DHCP_CHECK_RENEW_OK: renew success + 3/DHCP_CHECK_REBIND_FAIL: rebind fail + 4/DHCP_CHECK_REBIND_OK: rebind success +*/ +int DhcpClass::checkLease(){ + //this uses a signed / unsigned trick to deal with millis overflow + unsigned long now = millis(); + signed long snow = (long)now; + int rc=DHCP_CHECK_NONE; + if (_lastCheck != 0){ + signed long factor; + //calc how many ms past the timeout we are + factor = snow - (long)_secTimeout; + //if on or passed the timeout, reduce the counters + if ( factor >= 0 ){ + //next timeout should be now plus 1000 ms minus parts of second in factor + _secTimeout = snow + 1000 - factor % 1000; + //how many seconds late are we, minimum 1 + factor = factor / 1000 +1; + + //reduce the counters by that mouch + //if we can assume that the cycle time (factor) is fairly constant + //and if the remainder is less than cycle time * 2 + //do it early instead of late + if(_renewInSec < factor*2 ) + _renewInSec = 0; + else + _renewInSec -= factor; + + if(_rebindInSec < factor*2 ) + _rebindInSec = 0; + else + _rebindInSec -= factor; + } + + //if we have a lease but should renew, do it + if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ + _dhcp_state = STATE_DHCP_REREQUEST; + rc = 1 + request_DHCP_lease(); + } + + //if we have a lease or is renewing but should bind, do it + if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ + //this should basically restart completely + _dhcp_state = STATE_DHCP_START; + reset_DHCP_lease(); + rc = 3 + request_DHCP_lease(); + } + } + else{ + _secTimeout = snow + 1000; + } + + _lastCheck = now; + return rc; +} + +IPAddress DhcpClass::getLocalIp() +{ + return IPAddress(_dhcpLocalIp); +} + +IPAddress DhcpClass::getSubnetMask() +{ + return IPAddress(_dhcpSubnetMask); +} + +IPAddress DhcpClass::getGatewayIp() +{ + return IPAddress(_dhcpGatewayIp); +} + +IPAddress DhcpClass::getDhcpServerIp() +{ + return IPAddress(_dhcpDhcpServerIp); +} + +IPAddress DhcpClass::getDnsServerIp() +{ + return IPAddress(_dhcpDnsServerIp); +} + +void DhcpClass::printByte(char * buf, uint8_t n ) { + char *str = &buf[1]; + buf[0]='0'; + do { + unsigned long m = n; + n /= 16; + char c = m - 16 * n; + *str-- = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); +} diff --git a/libraries/UIPEthernet/Dhcp.h b/libraries/UIPEthernet/Dhcp.h new file mode 100644 index 0000000..01405d7 --- /dev/null +++ b/libraries/UIPEthernet/Dhcp.h @@ -0,0 +1,178 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#ifndef Dhcp_h +#define Dhcp_h + +#include "UIPUdp.h" + +/* DHCP state machine. */ +#define STATE_DHCP_START 0 +#define STATE_DHCP_DISCOVER 1 +#define STATE_DHCP_REQUEST 2 +#define STATE_DHCP_LEASED 3 +#define STATE_DHCP_REREQUEST 4 +#define STATE_DHCP_RELEASE 5 + +#define DHCP_FLAGSBROADCAST 0x8000 + +/* UDP port numbers for DHCP */ +#define DHCP_SERVER_PORT 67 /* from server to client */ +#define DHCP_CLIENT_PORT 68 /* from client to server */ + +/* DHCP message OP code */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_HTYPE10MB 1 +#define DHCP_HTYPE100MB 2 + +#define DHCP_HLENETHERNET 6 +#define DHCP_HOPS 0 +#define DHCP_SECS 0 + +#define MAGIC_COOKIE 0x63825363 +#define MAX_DHCP_OPT 16 + +#define HOST_NAME "ENC28J" +#define DEFAULT_LEASE (900) //default lease time in seconds + +#define DHCP_CHECK_NONE (0) +#define DHCP_CHECK_RENEW_FAIL (1) +#define DHCP_CHECK_RENEW_OK (2) +#define DHCP_CHECK_REBIND_FAIL (3) +#define DHCP_CHECK_REBIND_OK (4) + +enum +{ + padOption = 0, + subnetMask = 1, + timerOffset = 2, + routersOnSubnet = 3, + /* timeServer = 4, + nameServer = 5,*/ + dns = 6, + /*logServer = 7, + cookieServer = 8, + lprServer = 9, + impressServer = 10, + resourceLocationServer = 11,*/ + hostName = 12, + /*bootFileSize = 13, + meritDumpFile = 14,*/ + domainName = 15, + /*swapServer = 16, + rootPath = 17, + extentionsPath = 18, + IPforwarding = 19, + nonLocalSourceRouting = 20, + policyFilter = 21, + maxDgramReasmSize = 22, + defaultIPTTL = 23, + pathMTUagingTimeout = 24, + pathMTUplateauTable = 25, + ifMTU = 26, + allSubnetsLocal = 27, + broadcastAddr = 28, + performMaskDiscovery = 29, + maskSupplier = 30, + performRouterDiscovery = 31, + routerSolicitationAddr = 32, + staticRoute = 33, + trailerEncapsulation = 34, + arpCacheTimeout = 35, + ethernetEncapsulation = 36, + tcpDefaultTTL = 37, + tcpKeepaliveInterval = 38, + tcpKeepaliveGarbage = 39, + nisDomainName = 40, + nisServers = 41, + ntpServers = 42, + vendorSpecificInfo = 43, + netBIOSnameServer = 44, + netBIOSdgramDistServer = 45, + netBIOSnodeType = 46, + netBIOSscope = 47, + xFontServer = 48, + xDisplayManager = 49,*/ + dhcpRequestedIPaddr = 50, + dhcpIPaddrLeaseTime = 51, + /*dhcpOptionOverload = 52,*/ + dhcpMessageType = 53, + dhcpServerIdentifier = 54, + dhcpParamRequest = 55, + /*dhcpMsg = 56, + dhcpMaxMsgSize = 57,*/ + dhcpT1value = 58, + dhcpT2value = 59, + /*dhcpClassIdentifier = 60,*/ + dhcpClientIdentifier = 61, + endOption = 255 +}; + +typedef struct _RIP_MSG_FIXED +{ + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint8_t ciaddr[4]; + uint8_t yiaddr[4]; + uint8_t siaddr[4]; + uint8_t giaddr[4]; + uint8_t chaddr[6]; +}RIP_MSG_FIXED; + +class DhcpClass { +private: + uint32_t _dhcpInitialTransactionId; + uint32_t _dhcpTransactionId; + uint8_t _dhcpMacAddr[6]; + uint8_t _dhcpLocalIp[4]; + uint8_t _dhcpSubnetMask[4]; + uint8_t _dhcpGatewayIp[4]; + uint8_t _dhcpDhcpServerIp[4]; + uint8_t _dhcpDnsServerIp[4]; + uint32_t _dhcpLeaseTime; + uint32_t _dhcpT1, _dhcpT2; + signed long _renewInSec; + signed long _rebindInSec; + signed long _lastCheck; + unsigned long _timeout; + unsigned long _responseTimeout; + unsigned long _secTimeout; + uint8_t _dhcp_state; + UIPUDP _dhcpUdpSocket; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + void presend_DHCP(); + void send_DHCP_MESSAGE(uint8_t, uint16_t); + void printByte(char *, uint8_t); + + uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); +public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); +}; + +#endif diff --git a/libraries/UIPEthernet/Dns.cpp b/libraries/UIPEthernet/Dns.cpp new file mode 100644 index 0000000..2b97fb7 --- /dev/null +++ b/libraries/UIPEthernet/Dns.cpp @@ -0,0 +1,422 @@ +// Arduino DNS client for Enc28J60-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#include "Udp.h" +#include "utility/util.h" + +#include "Dns.h" +#include +//#include +#include "Arduino.h" + + +#define SOCKET_NONE 255 +// Various flags and header field values for a DNS message +#define UDP_HEADER_SIZE 8 +#define DNS_HEADER_SIZE 12 +#define TTL_SIZE 4 +#define QUERY_FLAG (0) +#define RESPONSE_FLAG (1<<15) +#define QUERY_RESPONSE_MASK (1<<15) +#define OPCODE_STANDARD_QUERY (0) +#define OPCODE_INVERSE_QUERY (1<<11) +#define OPCODE_STATUS_REQUEST (2<<11) +#define OPCODE_MASK (15<<11) +#define AUTHORITATIVE_FLAG (1<<10) +#define TRUNCATION_FLAG (1<<9) +#define RECURSION_DESIRED_FLAG (1<<8) +#define RECURSION_AVAILABLE_FLAG (1<<7) +#define RESP_NO_ERROR (0) +#define RESP_FORMAT_ERROR (1) +#define RESP_SERVER_FAILURE (2) +#define RESP_NAME_ERROR (3) +#define RESP_NOT_IMPLEMENTED (4) +#define RESP_REFUSED (5) +#define RESP_MASK (15) +#define TYPE_A (0x0001) +#define CLASS_IN (0x0001) +#define LABEL_COMPRESSION_MASK (0xC0) +// Port number that DNS servers listen on +#define DNS_PORT 53 + +// Possible return codes from ProcessResponse +#define SUCCESS 1 +#define TIMED_OUT -1 +#define INVALID_SERVER -2 +#define TRUNCATED -3 +#define INVALID_RESPONSE -4 + +void DNSClient::begin(const IPAddress& aDNSServer) +{ + iDNSServer = aDNSServer; + iRequestId = 0; +} + + +int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult) +{ + // See if we've been given a valid IP address + const char* p =aIPAddrString; + while (*p && + ( (*p == '.') || (*p >= '0') || (*p <= '9') )) + { + p++; + } + + if (*p == '\0') + { + // It's looking promising, we haven't found any invalid characters + p = aIPAddrString; + int segment =0; + int segmentValue =0; + while (*p && (segment < 4)) + { + if (*p == '.') + { + // We've reached the end of a segment + if (segmentValue > 255) + { + // You can't have IP address segments that don't fit in a byte + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + segment++; + segmentValue = 0; + } + } + else + { + // Next digit + segmentValue = (segmentValue*10)+(*p - '0'); + } + p++; + } + // We've reached the end of address, but there'll still be the last + // segment to deal with + if ((segmentValue > 255) || (segment > 3)) + { + // You can't have IP address segments that don't fit in a byte, + // or more than four segments + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + return 1; + } + } + else + { + return 0; + } +} + +int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) +{ + int ret =0; + + // See if it's a numeric IP address + if (inet_aton(aHostname, aResult)) + { + // It is, our work here is done + return 1; + } + + // Check we've got a valid DNS server to use + if (iDNSServer == INADDR_NONE) + { + return INVALID_SERVER; + } + + // Find a socket to use + if (iUdp.begin(1024+(millis() & 0xF)) == 1) + { + // Try up to three times + int retries = 0; +// while ((retries < 3) && (ret <= 0)) + { + // Send DNS request + ret = iUdp.beginPacket(iDNSServer, DNS_PORT); + if (ret != 0) + { + // Now output the request data + ret = BuildRequest(aHostname); + if (ret != 0) + { + // And finally send the request + ret = iUdp.endPacket(); + if (ret != 0) + { + // Now wait for a response + int wait_retries = 0; + ret = TIMED_OUT; + while ((wait_retries < 3) && (ret == TIMED_OUT)) + { + ret = ProcessResponse(5000, aResult); + wait_retries++; + } + } + } + } + retries++; + } + + // We're done with the socket now + iUdp.stop(); + } + + return ret; +} + +uint16_t DNSClient::BuildRequest(const char* aName) +{ + // Build header + // 1 1 1 1 1 1 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ID | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | QDCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ANCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | NSCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ARCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // As we only support one request at a time at present, we can simplify + // some of this header + iRequestId = millis(); // generate a random ID + uint16_t twoByteBuffer; + + // FIXME We should also check that there's enough space available to write to, rather + // FIXME than assume there's enough space (as the code does at present) + iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId)); + + twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(1); // One question record + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = 0; // Zero answer records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // and zero additional records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + // Build question + const char* start =aName; + const char* end =start; + uint8_t len; + // Run through the name being requested + while (*end) + { + // Find out how long this section of the name is + end = start; + while (*end && (*end != '.') ) + { + end++; + } + + if (end-start > 0) + { + // Write out the size of this section + len = end-start; + iUdp.write(&len, sizeof(len)); + // And then write out the section + iUdp.write((uint8_t*)start, end-start); + } + start = end+1; + } + + // We've got to the end of the question name, so + // terminate it with a zero-length section + len = 0; + iUdp.write(&len, sizeof(len)); + // Finally the type and class of question + twoByteBuffer = htons(TYPE_A); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(CLASS_IN); // Internet class of question + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // Success! Everything buffered okay + return 1; +} + + +uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) +{ + uint32_t startTime = millis(); + + // Wait for a response packet + while(iUdp.parsePacket() <= 0) + { + if((millis() - startTime) > aTimeout) + return TIMED_OUT; + delay(50); + } + + // We've had a reply! + // Read the UDP header + uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header + // Check that it's a response from the right server and the right port + if ( (iDNSServer != iUdp.remoteIP()) || + (iUdp.remotePort() != DNS_PORT) ) + { + // It's not from who we expected + return INVALID_SERVER; + } + + // Read through the rest of the response + if (iUdp.available() < DNS_HEADER_SIZE) + { + return TRUNCATED; + } + iUdp.read(header, DNS_HEADER_SIZE); + + uint16_t header_flags = htons(*((uint16_t*)&header[2])); + // Check that it's a response to this request + if ( ( iRequestId != (*((uint16_t*)&header[0])) ) || + ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) ) + { + // Mark the entire packet as read + iUdp.flush(); + return INVALID_RESPONSE; + } + // Check for any errors in the response (or in our request) + // although we don't do anything to get round these + if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) ) + { + // Mark the entire packet as read + iUdp.flush(); + return -5; //INVALID_RESPONSE; + } + + // And make sure we've got (at least) one answer + uint16_t answerCount = htons(*((uint16_t*)&header[6])); + if (answerCount == 0 ) + { + // Mark the entire packet as read + iUdp.flush(); + return -6; //INVALID_RESPONSE; + } + + // Skip over any questions + for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++) + { + // Skip over the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if (len > 0) + { + // Don't need to actually read the data out for the string, just + // advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } while (len != 0); + + // Now jump over the type and class + for (int i =0; i < 4; i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + + // Now we're up to the bit we're interested in, the answer + // There might be more than one answer (although we'll just use the first + // type A answer) and some authority and additional resource records but + // we're going to ignore all of them. + + for (uint16_t i =0; i < answerCount; i++) + { + // Skip the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if ((len & LABEL_COMPRESSION_MASK) == 0) + { + // It's just a normal label + if (len > 0) + { + // And it's got a length + // Don't need to actually read the data out for the string, + // just advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + else + { + // This is a pointer to a somewhere else in the message for the + // rest of the name. We don't care about the name, and RFC1035 + // says that a name is either a sequence of labels ended with a + // 0 length octet or a pointer or a sequence of labels ending in + // a pointer. Either way, when we get here we're at the end of + // the name + // Skip over the pointer + iUdp.read(); // we don't care about the returned byte + // And set len so that we drop out of the name loop + len = 0; + } + } while (len != 0); + + // Check the type and class + uint16_t answerType; + uint16_t answerClass; + iUdp.read((uint8_t*)&answerType, sizeof(answerType)); + iUdp.read((uint8_t*)&answerClass, sizeof(answerClass)); + + // Ignore the Time-To-Live as we don't do any caching + for (int i =0; i < TTL_SIZE; i++) + { + iUdp.read(); // we don't care about the returned byte + } + + // And read out the length of this answer + // Don't need header_flags anymore, so we can reuse it here + iUdp.read((uint8_t*)&header_flags, sizeof(header_flags)); + + if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) ) + { + if (htons(header_flags) != 4) + { + // It's a weird size + // Mark the entire packet as read + iUdp.flush(); + return -9;//INVALID_RESPONSE; + } + iUdp.read(aAddress.raw_address(), 4); + return SUCCESS; + } + else + { + // This isn't an answer type we're after, move onto the next one + for (uint16_t i =0; i < htons(header_flags); i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + + // Mark the entire packet as read + iUdp.flush(); + + // If we get here then we haven't found an answer + return -10;//INVALID_RESPONSE; +} + diff --git a/libraries/UIPEthernet/Dns.h b/libraries/UIPEthernet/Dns.h new file mode 100644 index 0000000..4913ca8 --- /dev/null +++ b/libraries/UIPEthernet/Dns.h @@ -0,0 +1,41 @@ +// Arduino DNS client for Enc28J60-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#ifndef DNSClient_h +#define DNSClient_h + +#include + +class DNSClient +{ +public: + // ctor + void begin(const IPAddress& aDNSServer); + + /** Convert a numeric IP address string into a four-byte IP address. + @param aIPAddrString IP address to convert + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int inet_aton(const char *aIPAddrString, IPAddress& aResult); + + /** Resolve the given hostname to an IP address. + @param aHostname Name to be resolved + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int getHostByName(const char* aHostname, IPAddress& aResult); + +protected: + uint16_t BuildRequest(const char* aName); + uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); + + IPAddress iDNSServer; + uint16_t iRequestId; + UIPUDP iUdp; +}; + +#endif diff --git a/libraries/UIPEthernet/README b/libraries/UIPEthernet/README new file mode 100644 index 0000000..321b334 --- /dev/null +++ b/libraries/UIPEthernet/README @@ -0,0 +1,227 @@ +This is UIPEthernet version 1.09 + +An plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. +Just include 'UIPEthernet.h' instead of 'Ethernet.h' and use all your code written for the stock Arduino Ethernet lib! + +UIPEthernet is written as a wrapper around the mature uIP Stack by Adam Dunkels, which provides the low-level implementation for all supported protocols. To overcome the memory-constrains (a 'regular' uIP-application does all processing in RAM) the ENC28J60 internal memory is used for all stream buffers (in and out). Only 400-600 Bytes of Arduinos RAM are used (depending on the number of concurrently open connections). As of Flash-memory a ATmega368-based Arduino is the minimum requirenment. + +This library is written by Norbert Truchsess + +uIP was written by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science. + +This library was inspired by the SerialIP implementation by Adam Nielsen , actually I took this code as a starting point, but in the latest versions there are very few lines left. + +Installation +------------ + +To install the libraries, you need to place them into your "libraries" folder. You can find it within your Arduino IDE distribution within the "hardware" folder. + + C:\> cd [path to Arduino distribution]\libraries + C:\> git clone https://github.com/ntruchsess/arduino_uip UIPEthernet + +Be sure to restart the IDE if it was running. + +On a Mac, you will want to create a folder named "libraries" in in the "Documents" -> "Arduino" folder within your home directory. Clone the project there (and restart the IDE, if it was running during this process). + + $ cd ~/Documents/Arduino/libraries + $ git clone https://github.com/ntruchsess/arduino_uip UIPEthernet + +Or you download the zipped version of the library from https://github.com/ntruchsess/arduino_uip/releases, and copy the contained directory UIPEthernet to [path to Arduino distribution]\libraries\UIPEthernet. + +If you are running Arduino-IDE 1.5.x use release-version 1.59 or checkout branch 'Arduino_1.5.x' + +Additional information can be found on the Arduino website: http://www.arduino.cc/en/Hacking/Libraries + +Documentation +------------- + +For more information visit: + + - UIPEthernet Repository on github: + https://github.com/ntruchsess/arduino_uip + + - Arduino Ethernet library description + http://arduino.cc/en/Reference/Ethernet + (Arduino_uip uses the same API as that, just include "UIPEthernet.h", "UIPClient.h", "UIPServer.h" and "UIPUDP.h" instead of the stock "Ethernet.h", "EthernetClient.h", "EthernetServer.h " and "EthernetUDP.h") + + - uIP API reference: + http://www.sics.se/~adam/uip/uip-1.0-refman/ + + - Arduino forums + http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl + + - uIP homepage: + http://www.sics.se/~adam/uip/index.php/Main_Page + +Licenses +------------- + +UIPEthernet.h +UIPEthernet.cpp +UIPServer.h +UIPServer.cpp +UIPClient.h +UIPClient.cpp +UIPUdp.h +UIPUdp.cpp +utility/mempool.h +utility/mempool.cpp + +Copyright (c) 2013 Norbert Truchsess +All rights reserved. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +-------------- + +utility/enc28j60.h + +Author : Pascal Stang (c)2005 +Modified by Norbert Truchsess +Copyright: GPL V2 + +-------------- + +utility/Enc28J60Network.h +utility/Enc28J60Network.cpp + +Copyright (c) 2013 Norbert Truchsess +All rights reserved. + +inspired and based on enc28j60.c file from the AVRlib library by Pascal Stang. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +-------------- + +utility/uip.c +utility/uip_arp.h +utility/uip_arp.c +utility/uip_arch.h +utility/uip.h +utility/uipopt.h + +Copyright (c) 2001-2003, Adam Dunkels , . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. +3. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + +-------------- + +uip-conf.h +utility/uip-neighbor.h +utility/uip-neighbor.c +utility/uip_timer.h +utility/uip_timer.c +utility/uip_clock.h + +Author Adam Dunkels Adam Dunkels , +Copyright (c) 2004,2006, Swedish Institute of Computer Science. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. +3. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + +-------------- + +Dhcp.h +Dhcp.cpp + +DHCP Library v0.3 - April 25, 2009 +Author: Jordan Terrell - blog.jordanterrell.com +- as included in Arduinos stock Ethernet-library, no special licence mentioned here + +-------------- + +Dns.h +Dns.cpp + +(c) Copyright 2009-2010 MCQN Ltd. +Released under Apache License, version 2.0 + +-------------- + +clock-arch.h +clock-arch.c + +Copyright (c) 2010 Adam Nielsen +All rights 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/UIPEthernet/UIPClient.cpp b/libraries/UIPEthernet/UIPClient.cpp new file mode 100644 index 0000000..d199cfe --- /dev/null +++ b/libraries/UIPEthernet/UIPClient.cpp @@ -0,0 +1,583 @@ +/* + UIPClient.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +extern "C" +{ +#import "utility/uip-conf.h" +#import "utility/uip.h" +#import "utility/uip_arp.h" +#import "string.h" +} +#include "UIPEthernet.h" +#include "UIPClient.h" +#include "Dns.h" + +#ifdef UIPETHERNET_DEBUG_CLIENT +#include "HardwareSerial.h" +#endif + +#define UIP_TCP_PHYH_LEN UIP_LLH_LEN+UIP_IPTCPH_LEN + +uip_userdata_t UIPClient::all_data[UIP_CONNS]; + +UIPClient::UIPClient() : + data(NULL) +{ +} + +UIPClient::UIPClient(uip_userdata_t* conn_data) : + data(conn_data) +{ +} + +int +UIPClient::connect(IPAddress ip, uint16_t port) +{ + stop(); + uip_ipaddr_t ipaddr; + uip_ip_addr(ipaddr, ip); + struct uip_conn* conn = uip_connect(&ipaddr, htons(port)); + if (conn) + { +#if UIP_CONNECT_TIMEOUT > 0 + int32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT; +#endif + while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) + { + UIPEthernetClass::tick(); + if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) + { + data = (uip_userdata_t*) conn->appstate; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("connected, state: ")); + Serial.print(data->state); + Serial.print(F(", first packet in: ")); + Serial.println(data->packets_in[0]); +#endif + return 1; + } +#if UIP_CONNECT_TIMEOUT > 0 + if (((int32_t)(millis() - timeout)) > 0) + { + conn->tcpstateflags = UIP_CLOSED; + break; + } +#endif + } + } + return 0; +} + +int +UIPClient::connect(const char *host, uint16_t port) +{ + // Look up the host first + int ret = 0; +#if UIP_UDP + DNSClient dns; + IPAddress remote_addr; + + dns.begin(UIPEthernetClass::_dnsServerAddress); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return connect(remote_addr, port); + } +#endif + return ret; +} + +void +UIPClient::stop() +{ + if (data && data->state) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("before stop(), with data")); + _dumpAllData(); +#endif + _flushBlocks(&data->packets_in[0]); + if (data->state & UIP_CLIENT_REMOTECLOSED) + { + data->state = 0; + } + else + { + data->state |= UIP_CLIENT_CLOSE; + } +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after stop()")); + _dumpAllData(); +#endif + } +#ifdef UIPETHERNET_DEBUG_CLIENT + else + { + Serial.println(F("stop(), data: NULL")); + } +#endif + data = NULL; + UIPEthernetClass::tick(); +} + +uint8_t +UIPClient::connected() +{ + return (data && (data->packets_in[0] != NOBLOCK || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0; +} + +bool +UIPClient::operator==(const UIPClient& rhs) +{ + return data && rhs.data && (data == rhs.data); +} + +UIPClient::operator bool() +{ + UIPEthernetClass::tick(); + return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK); +} + +size_t +UIPClient::write(uint8_t c) +{ + return _write(data, &c, 1); +} + +size_t +UIPClient::write(const uint8_t *buf, size_t size) +{ + return _write(data, buf, size); +} + +size_t +UIPClient::_write(uip_userdata_t* u, const uint8_t *buf, size_t size) +{ + int remain = size; + uint16_t written; +#if UIP_ATTEMPTS_ON_WRITE > 0 + uint16_t attempts = UIP_ATTEMPTS_ON_WRITE; +#endif + repeat: + UIPEthernetClass::tick(); + if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) + { + uint8_t p = _currentBlock(&u->packets_out[0]); + if (u->packets_out[p] == NOBLOCK) + { +newpacket: + u->packets_out[p] = Enc28J60Network::allocBlock(UIP_SOCKET_DATALEN); + if (u->packets_out[p] == NOBLOCK) + { +#if UIP_ATTEMPTS_ON_WRITE > 0 + if ((--attempts)>0) +#endif +#if UIP_ATTEMPTS_ON_WRITE != 0 + goto repeat; +#endif + goto ready; + } + u->out_pos = 0; + } +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient.write: writePacket(")); + Serial.print(u->packets_out[p]); + Serial.print(F(") pos: ")); + Serial.print(u->out_pos); + Serial.print(F(", buf[")); + Serial.print(size-remain); + Serial.print(F("-")); + Serial.print(remain); + Serial.print(F("]: '")); + Serial.write((uint8_t*)buf+size-remain,remain); + Serial.println(F("'")); +#endif + written = Enc28J60Network::writePacket(u->packets_out[p],u->out_pos,(uint8_t*)buf+size-remain,remain); + remain -= written; + u->out_pos+=written; + if (remain > 0) + { + if (p == UIP_SOCKET_NUMPACKETS-1) + { +#if UIP_ATTEMPTS_ON_WRITE > 0 + if ((--attempts)>0) +#endif +#if UIP_ATTEMPTS_ON_WRITE != 0 + goto repeat; +#endif + goto ready; + } + p++; + goto newpacket; + } +ready: +#if UIP_CLIENT_TIMER >= 0 + u->timer = millis()+UIP_CLIENT_TIMER; +#endif + return size-remain; + } + return -1; +} + +int +UIPClient::available() +{ + if (*this) + return _available(data); + return 0; +} + +int +UIPClient::_available(uip_userdata_t *u) +{ + int len = 0; + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + len += Enc28J60Network::blockSize(u->packets_in[i]); + } + return len; +} + +int +UIPClient::read(uint8_t *buf, size_t size) +{ + if (*this) + { + uint16_t remain = size; + if (data->packets_in[0] == NOBLOCK) + return 0; + uint16_t read; + do + { + read = Enc28J60Network::readPacket(data->packets_in[0],0,buf+size-remain,remain); + if (read == Enc28J60Network::blockSize(data->packets_in[0])) + { + remain -= read; + _eatBlock(&data->packets_in[0]); + if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) + data->state |= UIP_CLIENT_RESTART; + if (data->packets_in[0] == NOBLOCK) + { + if (data->state & UIP_CLIENT_REMOTECLOSED) + { + data->state = 0; + data = NULL; + } + return size-remain; + } + } + else + { + Enc28J60Network::resizeBlock(data->packets_in[0],read); + break; + } + } + while(remain > 0); + return size; + } + return -1; +} + +int +UIPClient::read() +{ + uint8_t c; + if (read(&c,1) < 0) + return -1; + return c; +} + +int +UIPClient::peek() +{ + if (*this) + { + if (data->packets_in[0] != NOBLOCK) + { + uint8_t c; + Enc28J60Network::readPacket(data->packets_in[0],0,&c,1); + return c; + } + } + return -1; +} + +void +UIPClient::flush() +{ + if (*this) + { + _flushBlocks(&data->packets_in[0]); + } +} + +void +uipclient_appcall(void) +{ + uint16_t send_len = 0; + uip_userdata_t *u = (uip_userdata_t*)uip_conn->appstate; + if (!u && uip_connected()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient uip_connected")); + UIPClient::_dumpAllData(); +#endif + u = (uip_userdata_t*) UIPClient::_allocateData(); + if (u) + { + uip_conn->appstate = u; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient allocated state: ")); + Serial.println(u->state,BIN); +#endif + } +#ifdef UIPETHERNET_DEBUG_CLIENT + else + Serial.println(F("UIPClient allocation failed")); +#endif + } + if (u) + { + if (uip_newdata()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient uip_newdata, uip_len:")); + Serial.println(uip_len); +#endif + if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) + { + for (uint8_t i=0; i < UIP_SOCKET_NUMPACKETS; i++) + { + if (u->packets_in[i] == NOBLOCK) + { + u->packets_in[i] = Enc28J60Network::allocBlock(uip_len); + if (u->packets_in[i] != NOBLOCK) + { + Enc28J60Network::copyPacket(u->packets_in[i],0,UIPEthernetClass::in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len); + if (i == UIP_SOCKET_NUMPACKETS-1) + uip_stop(); + goto finish_newdata; + } + } + } + UIPEthernetClass::packetstate &= ~UIPETHERNET_FREEPACKET; + uip_stop(); + } + } +finish_newdata: + if (u->state & UIP_CLIENT_RESTART) + { + u->state &= ~UIP_CLIENT_RESTART; + uip_restart(); + } + // If the connection has been closed, save received but unread data. + if (uip_closed() || uip_timedout()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient uip_closed")); + UIPClient::_dumpAllData(); +#endif + // drop outgoing packets not sent yet: + UIPClient::_flushBlocks(&u->packets_out[0]); + if (u->packets_in[0] != NOBLOCK) + { + ((uip_userdata_closed_t *)u)->lport = uip_conn->lport; + u->state |= UIP_CLIENT_REMOTECLOSED; + } + else + u->state = 0; + // disassociate appdata. +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after UIPClient uip_closed")); + UIPClient::_dumpAllData(); +#endif + uip_conn->appstate = NULL; + goto finish; + } + if (uip_acked()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient uip_acked")); +#endif + UIPClient::_eatBlock(&u->packets_out[0]); + } + if (uip_poll() || uip_rexmit()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + //Serial.println(F("UIPClient uip_poll")); +#endif + if (u->packets_out[0] != NOBLOCK) + { + if (u->packets_out[1] == NOBLOCK) + { + send_len = u->out_pos; + if (send_len > 0) + { + Enc28J60Network::resizeBlock(u->packets_out[0],0,send_len); + } + } + else + send_len = Enc28J60Network::blockSize(u->packets_out[0]); + if (send_len > 0) + { + UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf; + UIPEthernetClass::uip_packet = Enc28J60Network::allocBlock(UIPEthernetClass::uip_hdrlen+send_len); + if (UIPEthernetClass::uip_packet != NOBLOCK) + { + Enc28J60Network::copyPacket(UIPEthernetClass::uip_packet,UIPEthernetClass::uip_hdrlen,u->packets_out[0],0,send_len); + UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; + } + } + goto finish; + } + } + // don't close connection unless all outgoing packets are sent + if (u->state & UIP_CLIENT_CLOSE) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient state UIP_CLIENT_CLOSE")); + UIPClient::_dumpAllData(); +#endif + if (u->packets_out[0] == NOBLOCK) + { + u->state = 0; + uip_conn->appstate = NULL; + uip_close(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("no blocks out -> free userdata")); + UIPClient::_dumpAllData(); +#endif + } + else + { + uip_stop(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("blocks outstanding transfer -> uip_stop()")); +#endif + } + } + } + finish: + uip_send(uip_appdata,send_len); + uip_len = send_len; +} + +uip_userdata_t * +UIPClient::_allocateData() +{ + for ( uint8_t sock = 0; sock < UIP_CONNS; sock++ ) + { + uip_userdata_t* data = &UIPClient::all_data[sock]; + if (!data->state) + { + data->state = sock | UIP_CLIENT_CONNECTED; + memset(&data->packets_in[0],0,sizeof(uip_userdata_t)-sizeof(data->state)); + return data; + } + } + return NULL; +} + +uint8_t +UIPClient::_currentBlock(memhandle* block) +{ + for (uint8_t i = 1; i < UIP_SOCKET_NUMPACKETS; i++) + { + if (block[i] == NOBLOCK) + return i-1; + } + return UIP_SOCKET_NUMPACKETS-1; +} + +void +UIPClient::_eatBlock(memhandle* block) +{ +#ifdef UIPETHERNET_DEBUG_CLIENT + memhandle* start = block; + Serial.print(F("eatblock(")); + Serial.print(*block); + Serial.print(F("): ")); + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + Serial.print(start[i]); + Serial.print(F(" ")); + } + Serial.print(F("-> ")); +#endif + Enc28J60Network::freeBlock(block[0]); + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS-1; i++) + { + block[i] = block[i+1]; + } + block[UIP_SOCKET_NUMPACKETS-1] = NOBLOCK; +#ifdef UIPETHERNET_DEBUG_CLIENT + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + Serial.print(start[i]); + Serial.print(F(" ")); + } + Serial.println(); +#endif +} + +void +UIPClient::_flushBlocks(memhandle* block) +{ + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + Enc28J60Network::freeBlock(block[i]); + block[i] = NOBLOCK; + } +} + +#ifdef UIPETHERNET_DEBUG_CLIENT +void +UIPClient::_dumpAllData() { + for (uint8_t i=0; i < UIP_CONNS; i++) + { + Serial.print(F("UIPClient::all_data[")); + Serial.print(i); + Serial.print(F("], state:")); + Serial.println(all_data[i].state, BIN); + Serial.print(F("packets_in: ")); + for (uint8_t j=0; j < UIP_SOCKET_NUMPACKETS; j++) + { + Serial.print(all_data[i].packets_in[j]); + Serial.print(F(" ")); + } + Serial.println(); + if (all_data[i].state & UIP_CLIENT_REMOTECLOSED) + { + Serial.print(F("state remote closed, local port: ")); + Serial.println(htons(((uip_userdata_closed_t *)(&all_data[i]))->lport)); + } + else + { + Serial.print(F("packets_out: ")); + for (uint8_t j=0; j < UIP_SOCKET_NUMPACKETS; j++) + { + Serial.print(all_data[i].packets_out[j]); + Serial.print(F(" ")); + } + Serial.println(); + Serial.print(F("out_pos: ")); + Serial.println(all_data[i].out_pos); + } + } +} +#endif diff --git a/libraries/UIPEthernet/UIPClient.h b/libraries/UIPEthernet/UIPClient.h new file mode 100644 index 0000000..6c0c006 --- /dev/null +++ b/libraries/UIPEthernet/UIPClient.h @@ -0,0 +1,112 @@ +/* + UIPClient.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef UIPCLIENT_H +#define UIPCLIENT_H + +#include "ethernet_comp.h" +#include "Print.h" +#import "Client.h" +#import "utility/mempool.h" + +extern "C" { + #import "utility/uip.h" +} + +#define UIP_SOCKET_DATALEN UIP_TCP_MSS +//#define UIP_SOCKET_NUMPACKETS UIP_RECEIVE_WINDOW/UIP_TCP_MSS+1 +#ifndef UIP_SOCKET_NUMPACKETS +#define UIP_SOCKET_NUMPACKETS 5 +#endif + +#define UIP_CLIENT_CONNECTED 0x10 +#define UIP_CLIENT_CLOSE 0x20 +#define UIP_CLIENT_REMOTECLOSED 0x40 +#define UIP_CLIENT_RESTART 0x80 +#define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED | UIP_CLIENT_RESTART) +#define UIP_CLIENT_SOCKETS ~UIP_CLIENT_STATEFLAGS + +typedef uint8_t uip_socket_ptr; + +typedef struct { + uint8_t state; + memhandle packets_in[UIP_SOCKET_NUMPACKETS]; + uint16_t lport; /**< The local TCP port, in network byte order. */ +} uip_userdata_closed_t; + +typedef struct { + uint8_t state; + memhandle packets_in[UIP_SOCKET_NUMPACKETS]; + memhandle packets_out[UIP_SOCKET_NUMPACKETS]; + memaddress out_pos; +#if UIP_CLIENT_TIMER >= 0 + unsigned long timer; +#endif +} uip_userdata_t; + +class UIPClient : public Client { + +public: + UIPClient(); + int connect(IPAddress ip, uint16_t port); + int connect(const char *host, uint16_t port); + int read(uint8_t *buf, size_t size); + void stop(); + uint8_t connected(); + operator bool(); + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; + + size_t write(uint8_t); + size_t write(const uint8_t *buf, size_t size); + int available(); + int read(); + int peek(); + void flush(); + + using Print::write; + +private: + UIPClient(struct uip_conn *_conn); + UIPClient(uip_userdata_t* conn_data); + + uip_userdata_t* data; + + static uip_userdata_t all_data[UIP_CONNS]; + static uip_userdata_t* _allocateData(); + + static size_t _write(uip_userdata_t *,const uint8_t *buf, size_t size); + static int _available(uip_userdata_t *); + + static uint8_t _currentBlock(memhandle* blocks); + static void _eatBlock(memhandle* blocks); + static void _flushBlocks(memhandle* blocks); + +#ifdef UIPETHERNET_DEBUG_CLIENT + static void _dumpAllData(); +#endif + + friend class UIPEthernetClass; + friend class UIPServer; + + friend void uipclient_appcall(void); + +}; + +#endif diff --git a/libraries/UIPEthernet/UIPEthernet.cpp b/libraries/UIPEthernet/UIPEthernet.cpp new file mode 100644 index 0000000..91ec70a --- /dev/null +++ b/libraries/UIPEthernet/UIPEthernet.cpp @@ -0,0 +1,485 @@ +/* + UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include "UIPEthernet.h" +#include "utility/Enc28J60Network.h" + +#if(defined UIPETHERNET_DEBUG || defined UIPETHERNET_DEBUG_CHKSUM) +#include "HardwareSerial.h" +#endif + +#include "UIPUdp.h" + +extern "C" +{ +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +#include "utility/uip_timer.h" +} + +#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0]) + +memhandle UIPEthernetClass::in_packet(NOBLOCK); +memhandle UIPEthernetClass::uip_packet(NOBLOCK); +uint8_t UIPEthernetClass::uip_hdrlen(0); +uint8_t UIPEthernetClass::packetstate(0); + +IPAddress UIPEthernetClass::_dnsServerAddress; +DhcpClass* UIPEthernetClass::_dhcp(NULL); + +unsigned long UIPEthernetClass::periodic_timer; + +// Because uIP isn't encapsulated within a class we have to use global +// variables, so we can only have one TCP/IP stack per program. + +UIPEthernetClass::UIPEthernetClass() +{ +} + +#if UIP_UDP +int +UIPEthernetClass::begin(const uint8_t* mac) +{ + static DhcpClass s_dhcp; + _dhcp = &s_dhcp; + + // Initialise the basic info + init(mac); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP((uint8_t*)mac); + if(ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); + } + return ret; +} +#endif + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) +{ + IPAddress dns = ip; + dns[3] = 1; + begin(mac, ip, dns); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) +{ + IPAddress gateway = ip; + gateway[3] = 1; + begin(mac, ip, dns, gateway); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) +{ + IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) +{ + init(mac); + configure(ip,dns,gateway,subnet); +} + +int UIPEthernetClass::maintain(){ + tick(); + int rc = DHCP_CHECK_NONE; +#if UIP_UDP + if(_dhcp != NULL){ + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + switch ( rc ){ + case DHCP_CHECK_NONE: + //nothing done + break; + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); + break; + default: + //this is actually a error, it will retry though + break; + } + } + return rc; +#endif +} + +IPAddress UIPEthernetClass::localIP() +{ + IPAddress ret; + uip_ipaddr_t a; + uip_gethostaddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::subnetMask() +{ + IPAddress ret; + uip_ipaddr_t a; + uip_getnetmask(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::gatewayIP() +{ + IPAddress ret; + uip_ipaddr_t a; + uip_getdraddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::dnsServerIP() +{ + return _dnsServerAddress; +} + +void +UIPEthernetClass::tick() +{ + if (in_packet == NOBLOCK) + { + in_packet = Enc28J60Network::receivePacket(); +#ifdef UIPETHERNET_DEBUG + if (in_packet != NOBLOCK) + { + Serial.print(F("--------------\nreceivePacket: ")); + Serial.println(in_packet); + } +#endif + } + if (in_packet != NOBLOCK) + { + packetstate = UIPETHERNET_FREEPACKET; + uip_len = Enc28J60Network::blockSize(in_packet); + if (uip_len > 0) + { + Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE); + if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) + { + uip_packet = in_packet; //required for upper_layer_checksum of in_packet! +#ifdef UIPETHERNET_DEBUG + Serial.print(F("readPacket type IP, uip_len: ")); + Serial.println(uip_len); +#endif + uip_arp_ipin(); + uip_input(); + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } + else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP)) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("readPacket type ARP, uip_len: ")); + Serial.println(uip_len); +#endif + uip_arp_arpin(); + if (uip_len > 0) + { + network_send(); + } + } + } + if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("freeing packet: ")); + Serial.println(in_packet); +#endif + Enc28J60Network::freePacket(); + in_packet = NOBLOCK; + } + } + + unsigned long now = millis(); + +#if UIP_CLIENT_TIMER >= 0 + boolean periodic = (long)( now - periodic_timer ) >= 0; + for (int i = 0; i < UIP_CONNS; i++) + { +#else + if ((long)( now - periodic_timer ) >= 0) + { + periodic_timer = now + UIP_PERIODIC_TIMER; + + for (int i = 0; i < UIP_CONNS; i++) + { +#endif + uip_conn = &uip_conns[i]; +#if UIP_CLIENT_TIMER >= 0 + if (periodic) + { +#endif + uip_process(UIP_TIMER); +#if UIP_CLIENT_TIMER >= 0 + } + else + { + if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) + uip_process(UIP_POLL_REQUEST); + else + continue; + } +#endif + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } +#if UIP_CLIENT_TIMER >= 0 + if (periodic) + { + periodic_timer = now + UIP_PERIODIC_TIMER; +#endif +#if UIP_UDP + for (int i = 0; i < UIP_UDP_CONNS; i++) + { + uip_udp_periodic(i); + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. */ + if (uip_len > 0) + { + UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate)); + } + } +#endif /* UIP_UDP */ + } +} + +boolean UIPEthernetClass::network_send() +{ + if (packetstate & UIPETHERNET_SENDPACKET) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("Enc28J60Network_send uip_packet: ")); + Serial.print(uip_packet); + Serial.print(F(", hdrlen: ")); + Serial.println(uip_hdrlen); +#endif + Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_hdrlen); + packetstate &= ~ UIPETHERNET_SENDPACKET; + goto sendandfree; + } + uip_packet = Enc28J60Network::allocBlock(uip_len); + if (uip_packet != NOBLOCK) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("Enc28J60Network_send uip_buf (uip_len): ")); + Serial.print(uip_len); + Serial.print(F(", packet: ")); + Serial.println(uip_packet); +#endif + Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_len); + goto sendandfree; + } + return false; +sendandfree: + Enc28J60Network::sendPacket(uip_packet); + Enc28J60Network::freeBlock(uip_packet); + uip_packet = NOBLOCK; + return true; +} + +void UIPEthernetClass::init(const uint8_t* mac) { + periodic_timer = millis() + UIP_PERIODIC_TIMER; + + Enc28J60Network::init((uint8_t*)mac); + uip_seteth_addr(mac); + + uip_init(); + uip_arp_init(); +} + +void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + uip_ipaddr_t ipaddr; + + uip_ip_addr(ipaddr, ip); + uip_sethostaddr(ipaddr); + + uip_ip_addr(ipaddr, gateway); + uip_setdraddr(ipaddr); + + uip_ip_addr(ipaddr, subnet); + uip_setnetmask(ipaddr); + + _dnsServerAddress = dns; +} + +UIPEthernetClass UIPEthernet; + +/*---------------------------------------------------------------------------*/ +uint16_t +UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) +{ + uint16_t t; + const uint8_t *dataptr; + const uint8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) { /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + dataptr += 2; + } + + if(dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} + +/*---------------------------------------------------------------------------*/ + +uint16_t +UIPEthernetClass::ipchksum(void) +{ + uint16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + return (sum == 0) ? 0xffff : htons(sum); +} + +/*---------------------------------------------------------------------------*/ +uint16_t +#if UIP_UDP +UIPEthernetClass::upper_layer_chksum(uint8_t proto) +#else +uip_tcpchksum(void) +#endif +{ + uint16_t upper_layer_len; + uint16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ +#if UIP_UDP + sum = upper_layer_len + proto; +#else + sum = upper_layer_len + UIP_PROTO_TCP; +#endif + /* Sum IP source and destination addresses. */ + sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + uint8_t upper_layer_memlen; +#if UIP_UDP + switch(proto) + { +// case UIP_PROTO_ICMP: +// case UIP_PROTO_ICMP6: +// upper_layer_memlen = upper_layer_len; +// break; + case UIP_PROTO_UDP: + upper_layer_memlen = UIP_UDPH_LEN; + break; + default: +// case UIP_PROTO_TCP: +#endif + upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; +#if UIP_UDP + break; + } +#endif + sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); +#ifdef UIPETHERNET_DEBUG_CHKSUM + Serial.print(F("chksum uip_buf[")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN); + Serial.print(F("-")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + Serial.print(F("]: ")); + Serial.println(htons(sum),HEX); +#endif + if (upper_layer_memlen < upper_layer_len) + { + sum = Enc28J60Network::chksum( + sum, + UIPEthernetClass::uip_packet, + UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, + upper_layer_len - upper_layer_memlen + ); +#ifdef UIPETHERNET_DEBUG_CHKSUM + Serial.print(F("chksum uip_packet(")); + Serial.print(uip_packet); + Serial.print(F(")[")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + Serial.print(F("-")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); + Serial.print(F("]: ")); + Serial.println(htons(sum),HEX); +#endif + } + return (sum == 0) ? 0xffff : htons(sum); +} + +uint16_t +uip_ipchksum(void) +{ + return UIPEthernet.ipchksum(); +} + +#if UIP_UDP +uint16_t +uip_tcpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); + return sum; +} + +uint16_t +uip_udpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); + return sum; +} +#endif diff --git a/libraries/UIPEthernet/UIPEthernet.h b/libraries/UIPEthernet/UIPEthernet.h new file mode 100644 index 0000000..c68d578 --- /dev/null +++ b/libraries/UIPEthernet/UIPEthernet.h @@ -0,0 +1,127 @@ +/* + UIPEthernet.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef UIPETHERNET_H +#define UIPETHERNET_H + +//#define UIPETHERNET_DEBUG +//#define UIPETHERNET_DEBUG_CHKSUM +//#define UIPETHERNET_DEBUG_UDP +//#define UIPETHERNET_DEBUG_CLIENT + +#include "ethernet_comp.h" +#include +#include "Dhcp.h" +#include "IPAddress.h" +#include "utility/Enc28J60Network.h" +#include "UIPClient.h" +#include "UIPServer.h" +#include "UIPUdp.h" + +extern "C" +{ +#include "utility/uip_timer.h" +#include "utility/uip.h" +} + +#define UIPETHERNET_FREEPACKET 1 +#define UIPETHERNET_SENDPACKET 2 +#define UIPETHERNET_BUFFERREAD 4 + +#define uip_ip_addr(addr, ip) do { \ + ((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ + ((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ + } while(0) + +#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable + +#define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \ + uip_ethaddr.addr[1] = eaddr[1];\ + uip_ethaddr.addr[2] = eaddr[2];\ + uip_ethaddr.addr[3] = eaddr[3];\ + uip_ethaddr.addr[4] = eaddr[4];\ + uip_ethaddr.addr[5] = eaddr[5];} while(0) + +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +class UIPEthernetClass +{ +public: + UIPEthernetClass(); + + int begin(const uint8_t* mac); + void begin(const uint8_t* mac, IPAddress ip); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + // maintain() must be called at regular intervals to process the incoming serial + // data and issue IP events to the sketch. It does not return until all IP + // events have been processed. Renews dhcp-lease if required. + int maintain(); + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + +private: + static memhandle in_packet; + static memhandle uip_packet; + static uint8_t uip_hdrlen; + static uint8_t packetstate; + + static IPAddress _dnsServerAddress; + static DhcpClass* _dhcp; + + static unsigned long periodic_timer; + + static void init(const uint8_t* mac); + static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + static void tick(); + + static boolean network_send(); + + friend class UIPServer; + + friend class UIPClient; + + friend class UIPUDP; + + static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); + static uint16_t ipchksum(void); +#if UIP_UDP + static uint16_t upper_layer_chksum(uint8_t proto); +#endif + friend uint16_t uip_ipchksum(void); + friend uint16_t uip_tcpchksum(void); + friend uint16_t uip_udpchksum(void); + + friend void uipclient_appcall(void); + friend void uipudp_appcall(void); + +#if UIP_CONF_IPV6 + uint16_t uip_icmp6chksum(void); +#endif /* UIP_CONF_IPV6 */ +}; + +extern UIPEthernetClass UIPEthernet; + +#endif diff --git a/libraries/UIPEthernet/UIPServer.cpp b/libraries/UIPEthernet/UIPServer.cpp new file mode 100644 index 0000000..21c7ef5 --- /dev/null +++ b/libraries/UIPEthernet/UIPServer.cpp @@ -0,0 +1,63 @@ +/* + UIPServer.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include "UIPEthernet.h" +#include "UIPServer.h" +extern "C" { + #include "utility/uip-conf.h" +} + +UIPServer::UIPServer(uint16_t port) : _port(htons(port)) +{ +} + +UIPClient UIPServer::available() +{ + UIPEthernetClass::tick(); + for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ ) + { + if (data->packets_in[0] != NOBLOCK + && (((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port) + || ((data->state & UIP_CLIENT_REMOTECLOSED) && ((uip_userdata_closed_t *)data)->lport == _port))) + return UIPClient(data); + } + return UIPClient(); +} + +void UIPServer::begin() +{ + uip_listen(_port); + UIPEthernetClass::tick(); +} + +size_t UIPServer::write(uint8_t c) +{ + return write(&c,1); +} + +size_t UIPServer::write(const uint8_t *buf, size_t size) +{ + size_t ret = 0; + for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ ) + { + if ((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port) + ret += UIPClient::_write(data,buf,size); + } + return ret; +} + diff --git a/libraries/UIPEthernet/UIPServer.h b/libraries/UIPEthernet/UIPServer.h new file mode 100644 index 0000000..0cc0619 --- /dev/null +++ b/libraries/UIPEthernet/UIPServer.h @@ -0,0 +1,40 @@ +/* + UIPServer.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef UIPSERVER_H +#define UIPSERVER_H + +#include "ethernet_comp.h" +#import "Server.h" +#import "UIPClient.h" + +class UIPServer : public Server { + +public: + UIPServer(uint16_t); + UIPClient available(); + void begin(); + size_t write(uint8_t); + size_t write(const uint8_t *buf, size_t size); + using Print::write; + +private: + uint16_t _port; +}; + +#endif diff --git a/libraries/UIPEthernet/UIPUdp.cpp b/libraries/UIPEthernet/UIPUdp.cpp new file mode 100644 index 0000000..3deb2c4 --- /dev/null +++ b/libraries/UIPEthernet/UIPUdp.cpp @@ -0,0 +1,383 @@ +/* + UIPUdp.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "UIPEthernet.h" +#include "UIPUdp.h" +#include "Dns.h" + +#ifdef UIPETHERNET_DEBUG_UDP +#include "HardwareSerial.h" +#endif + +extern "C" { +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +} + +#if UIP_UDP +#define UIP_ARPHDRSIZE 42 +#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +// Constructor +UIPUDP::UIPUDP() : + _uip_udp_conn(NULL) +{ + memset(&appdata,0,sizeof(appdata)); +} + +// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use +uint8_t +UIPUDP::begin(uint16_t port) +{ + if (!_uip_udp_conn) + { + _uip_udp_conn = uip_udp_new(NULL, 0); + } + if (_uip_udp_conn) + { + uip_udp_bind(_uip_udp_conn,htons(port)); + _uip_udp_conn->appstate = &appdata; + return 1; + } + return 0; +} + +// Finish with the UDP socket +void +UIPUDP::stop() +{ + if (_uip_udp_conn) + { + uip_udp_remove(_uip_udp_conn); + _uip_udp_conn->appstate = NULL; + _uip_udp_conn=NULL; + Enc28J60Network::freeBlock(appdata.packet_in); + Enc28J60Network::freeBlock(appdata.packet_next); + Enc28J60Network::freeBlock(appdata.packet_out); + memset(&appdata,0,sizeof(appdata)); + } +} + +// Sending UDP packets + +// Start building up a packet to send to the remote host specific in ip and port +// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port +int +UIPUDP::beginPacket(IPAddress ip, uint16_t port) +{ + UIPEthernetClass::tick(); + if (ip && port) + { + uip_ipaddr_t ripaddr; + uip_ip_addr(&ripaddr, ip); +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp beginPacket, ")); +#endif + if (_uip_udp_conn) + { + _uip_udp_conn->rport = htons(port); + uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr); + } + else + { + _uip_udp_conn = uip_udp_new(&ripaddr,htons(port)); + if (_uip_udp_conn) + { +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("new connection, ")); +#endif + _uip_udp_conn->appstate = &appdata; + } + else + { +#ifdef UIPETHERNET_DEBUG_UDP + Serial.println(F("failed to allocate new connection")); +#endif + return 0; + } + } +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("rip: ")); + Serial.print(ip); + Serial.print(F(", port: ")); + Serial.println(port); +#endif + } + if (_uip_udp_conn) + { + if (appdata.packet_out == NOBLOCK) + { + appdata.packet_out = Enc28J60Network::allocBlock(UIP_UDP_MAXPACKETSIZE); + appdata.out_pos = UIP_UDP_PHYH_LEN; + if (appdata.packet_out != NOBLOCK) + return 1; +#ifdef UIPETHERNET_DEBUG_UDP + else + Serial.println(F("failed to allocate memory for packet")); +#endif + } +#ifdef UIPETHERNET_DEBUG_UDP + else + Serial.println(F("previous packet on that connection not sent yet")); +#endif + } + return 0; +} + +// Start building up a packet to send to the remote host specific in host and port +// Returns 1 if successful, 0 if there was a problem resolving the hostname or port +int +UIPUDP::beginPacket(const char *host, uint16_t port) +{ + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(UIPEthernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return beginPacket(remote_addr, port); + } else { + return ret; + } +} + +// Finish off this packet and send it +// Returns 1 if the packet was sent successfully, 0 if there was an error +int +UIPUDP::endPacket() +{ + if (_uip_udp_conn && appdata.packet_out != NOBLOCK) + { + appdata.send = true; + Enc28J60Network::resizeBlock(appdata.packet_out,0,appdata.out_pos); + uip_udp_periodic_conn(_uip_udp_conn); + if (uip_len > 0) + { + _send(&appdata); + return 1; + } + } + return 0; +} + +// Write a single byte into the packet +size_t +UIPUDP::write(uint8_t c) +{ + return write(&c,1); +} + +// Write size bytes from buffer into the packet +size_t +UIPUDP::write(const uint8_t *buffer, size_t size) +{ + if (appdata.packet_out != NOBLOCK) + { + size_t ret = Enc28J60Network::writePacket(appdata.packet_out,appdata.out_pos,(uint8_t*)buffer,size); + appdata.out_pos += ret; + return ret; + } + return 0; +} + +// Start processing the next available incoming packet +// Returns the size of the packet in bytes, or 0 if no packets are available +int +UIPUDP::parsePacket() +{ + UIPEthernetClass::tick(); +#ifdef UIPETHERNET_DEBUG_UDP + if (appdata.packet_in != NOBLOCK) + { + Serial.print(F("udp parsePacket freeing previous packet: ")); + Serial.println(appdata.packet_in); + } +#endif + Enc28J60Network::freeBlock(appdata.packet_in); + + appdata.packet_in = appdata.packet_next; + appdata.packet_next = NOBLOCK; + +#ifdef UIPETHERNET_DEBUG_UDP + if (appdata.packet_in != NOBLOCK) + { + Serial.print(F("udp parsePacket received packet: ")); + Serial.print(appdata.packet_in); + } +#endif + int size = Enc28J60Network::blockSize(appdata.packet_in); +#ifdef UIPETHERNET_DEBUG_UDP + if (appdata.packet_in != NOBLOCK) + { + Serial.print(F(", size: ")); + Serial.println(size); + } +#endif + return size; +} + +// Number of bytes remaining in the current packet +int +UIPUDP::available() +{ + UIPEthernetClass::tick(); + return Enc28J60Network::blockSize(appdata.packet_in); +} + +// Read a single byte from the current packet +int +UIPUDP::read() +{ + unsigned char c; + if (read(&c,1) > 0) + { + return c; + } + return -1; +} + +// Read up to len bytes from the current packet and place them into buffer +// Returns the number of bytes read, or 0 if none are available +int +UIPUDP::read(unsigned char* buffer, size_t len) +{ + UIPEthernetClass::tick(); + if (appdata.packet_in != NOBLOCK) + { + memaddress read = Enc28J60Network::readPacket(appdata.packet_in,0,buffer,len); + if (read == Enc28J60Network::blockSize(appdata.packet_in)) + { + Enc28J60Network::freeBlock(appdata.packet_in); + appdata.packet_in = NOBLOCK; + } + else + Enc28J60Network::resizeBlock(appdata.packet_in,read); + return read; + } + return 0; +} + +// Return the next byte from the current packet without moving on to the next byte +int +UIPUDP::peek() +{ + UIPEthernetClass::tick(); + if (appdata.packet_in != NOBLOCK) + { + unsigned char c; + if (Enc28J60Network::readPacket(appdata.packet_in,0,&c,1) == 1) + return c; + } + return -1; +} + +// Finish reading the current packet +void +UIPUDP::flush() +{ + UIPEthernetClass::tick(); + Enc28J60Network::freeBlock(appdata.packet_in); + appdata.packet_in = NOBLOCK; +} + +// Return the IP address of the host who sent the current incoming packet +IPAddress +UIPUDP::remoteIP() +{ + return _uip_udp_conn ? ip_addr_uip(_uip_udp_conn->ripaddr) : IPAddress(); +} + +// Return the port of the host who sent the current incoming packet +uint16_t +UIPUDP::remotePort() +{ + return _uip_udp_conn ? ntohs(_uip_udp_conn->rport) : 0; +} + +// uIP callback function + +void +uipudp_appcall(void) { + if (uip_udp_userdata_t *data = (uip_udp_userdata_t *)(uip_udp_conn->appstate)) + { + if (uip_newdata()) + { + if (data->packet_next == NOBLOCK) + { + uip_udp_conn->rport = UDPBUF->srcport; + uip_ipaddr_copy(uip_udp_conn->ripaddr,UDPBUF->srcipaddr); + data->packet_next = Enc28J60Network::allocBlock(ntohs(UDPBUF->udplen)-UIP_UDPH_LEN); + //if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery + if (data->packet_next != NOBLOCK) + { + //discard Linklevel and IP and udp-header and any trailing bytes: + Enc28J60Network::copyPacket(data->packet_next,0,UIPEthernetClass::in_packet,UIP_UDP_PHYH_LEN,Enc28J60Network::blockSize(data->packet_next)); + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_newdata received packet: ")); + Serial.print(data->packet_next); + Serial.print(F(", size: ")); + Serial.println(Enc28J60Network::blockSize(data->packet_next)); + #endif + } + } + } + if (uip_poll() && data->send) + { + //set uip_slen (uip private) by calling uip_udp_send +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_poll preparing packet to send: ")); + Serial.print(data->packet_out); + Serial.print(F(", size: ")); + Serial.println(Enc28J60Network::blockSize(data->packet_out)); +#endif + UIPEthernetClass::uip_packet = data->packet_out; + UIPEthernetClass::uip_hdrlen = UIP_UDP_PHYH_LEN; + uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN)); + } + } +} + +void +UIPUDP::_send(uip_udp_userdata_t *data) { + uip_arp_out(); //add arp + if (uip_len == UIP_ARPHDRSIZE) + { + UIPEthernetClass::uip_packet = NOBLOCK; + UIPEthernetClass::packetstate &= ~UIPETHERNET_SENDPACKET; +#ifdef UIPETHERNET_DEBUG_UDP + Serial.println(F("udp, uip_poll results in ARP-packet")); +#endif + } + else + //arp found ethaddr for ip (otherwise packet is replaced by arp-request) + { + data->send = false; + data->packet_out = NOBLOCK; + UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_packet to send: ")); + Serial.println(UIPEthernetClass::uip_packet); +#endif + } + UIPEthernetClass::network_send(); +} +#endif diff --git a/libraries/UIPEthernet/UIPUdp.h b/libraries/UIPEthernet/UIPUdp.h new file mode 100644 index 0000000..b007a3c --- /dev/null +++ b/libraries/UIPEthernet/UIPUdp.h @@ -0,0 +1,126 @@ +/* + UIPUdp.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef UIPUDP_H +#define UIPUDP_H + +#include "ethernet_comp.h" +#include "Arduino.h" +#include +#include "utility/mempool.h" +extern "C" { + #include "utility/uip.h" +} + +#define UIP_UDP_MAXDATALEN 1500 +#define UIP_UDP_PHYH_LEN UIP_LLH_LEN+UIP_IPUDPH_LEN +#define UIP_UDP_MAXPACKETSIZE UIP_UDP_MAXDATALEN+UIP_UDP_PHYH_LEN + +typedef struct { + memaddress out_pos; + memhandle packet_next; + memhandle packet_in; + memhandle packet_out; + boolean send; +} uip_udp_userdata_t; + +class UIPUDP : public UDP +{ + +private: + struct uip_udp_conn *_uip_udp_conn; + + uip_udp_userdata_t appdata; + +public: + UIPUDP(); // Constructor + uint8_t + begin(uint16_t);// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + void + stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + int + beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + int + beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + int + endPacket(); + // Write a single byte into the packet + size_t + write(uint8_t); + // Write size bytes from buffer into the packet + size_t + write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + int + parsePacket(); + // Number of bytes remaining in the current packet + int + available(); + // Read a single byte from the current packet + int + read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + int + read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + int + read(char* buffer, size_t len) + { + return read((unsigned char*) buffer, len); + } + ; + // Return the next byte from the current packet without moving on to the next byte + int + peek(); + void + flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + IPAddress + remoteIP(); + + // Return the port of the host who sent the current incoming packet + uint16_t + remotePort(); + +private: + + friend void uipudp_appcall(void); + + friend class UIPEthernetClass; + static void _send(uip_udp_userdata_t *data); + +}; + +#endif diff --git a/libraries/UIPEthernet/ethernet_comp.h b/libraries/UIPEthernet/ethernet_comp.h new file mode 100644 index 0000000..4cec2ab --- /dev/null +++ b/libraries/UIPEthernet/ethernet_comp.h @@ -0,0 +1,9 @@ +#ifndef ETHERNET_COMP_H +#define ETHERNET_COMP_H + +#define Ethernet UIPEthernet +#define EthernetClient UIPClient +#define EthernetServer UIPServer +#define EthernetUDP UIPUDP + +#endif diff --git a/libraries/UIPEthernet/examples/AdvancedChatServer/AdvancedChatServer.ino b/libraries/UIPEthernet/examples/AdvancedChatServer/AdvancedChatServer.ino new file mode 100644 index 0000000..bc2f094 --- /dev/null +++ b/libraries/UIPEthernet/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -0,0 +1,104 @@ +/* + Advanced Chat Server + + A simple server that distributes any incoming messages to all + connected clients but the client the message comes from. + To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + redesigned to make use of operator== 25 Nov 2013 + by Norbert Truchsess + + */ + +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. + +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +IPAddress ip(192,168,0,6); + +// telnet defaults to port 23 +EthernetServer server(23); + +EthernetClient clients[4]; + +void setup() { + // initialize the ethernet device + Ethernet.begin(mac, ip); + // start listening for clients + server.begin(); + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + Serial.print("Chat server address:"); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + if (client) { + + boolean newClient = true; + for (byte i=0;i<4;i++) { + //check whether this client refers to the same socket as one of the existing instances: + if (clients[i]==client) { + newClient = false; + break; + } + } + + if (newClient) { + //check which of the existing clients can be overridden: + for (byte i=0;i<4;i++) { + if (!clients[i] && clients[i]!=client) { + clients[i] = client; + // clead out the input buffer: + client.flush(); + // clead out the input buffer: + client.flush(); + Serial.println("We have a new client"); + client.println("Hello, client!"); + client.print("my IP: "); + client.println(Ethernet.localIP()); + break; + } + } + } + + if (client.available() > 0) { + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to all other connected clients: + for (byte i=0;i<4;i++) { + if (clients[i] && clients[i]!=client) { + clients[i].write(thisChar); + } + } + // echo the bytes to the server as well: + Serial.write(thisChar); + } + } + for (byte i=0;i<4;i++) { + if (!(clients[i].connected())) { + // client.stop() invalidates the internal socket-descriptor, so next use of == will allways return false; + clients[i].stop(); + } + } +} diff --git a/libraries/UIPEthernet/examples/EchoServer/EchoServer.ino b/libraries/UIPEthernet/examples/EchoServer/EchoServer.ino new file mode 100644 index 0000000..62d66e4 --- /dev/null +++ b/libraries/UIPEthernet/examples/EchoServer/EchoServer.ino @@ -0,0 +1,58 @@ +/* + * UIPEthernet EchoServer example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This Hello World example sets up a server at 192.168.1.6 on port 1000. + * Telnet here to access the service. The uIP stack will also respond to + * pings to test if you have successfully established a TCP connection to + * the Arduino. + * + * This example was based upon uIP hello-world by Adam Dunkels + * Ported to the Arduino IDE by Adam Nielsen + * Adaption to Enc28J60 by Norbert Truchsess + */ + +#include +// The connection_data struct needs to be defined in an external file. +#include +#include + +EthernetServer server = EthernetServer(1000); + +void setup() +{ + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + IPAddress myIP(192,168,0,6); + + Ethernet.begin(mac,myIP); + + server.begin(); +} + +void loop() +{ + size_t size; + + if (EthernetClient client = server.available()) + { + if (client) + { + while((size = client.available()) > 0) + { + uint8_t* msg = (uint8_t*)malloc(size); + size = client.read(msg,size); + Serial.write(msg,size); + client.write(msg,size); + free(msg); + } + } + } +} diff --git a/libraries/UIPEthernet/examples/TcpClient/TcpClient.ino b/libraries/UIPEthernet/examples/TcpClient/TcpClient.ino new file mode 100644 index 0000000..dca685c --- /dev/null +++ b/libraries/UIPEthernet/examples/TcpClient/TcpClient.ino @@ -0,0 +1,76 @@ +/* + * UIPEthernet TcpClient example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This TcpClient example gets its local ip-address via dhcp and sets + * up a tcp socket-connection to 192.168.0.1 port 5000 every 5 Seconds. + * After sending a message it waits for a response. After receiving the + * response the client disconnects and tries to reconnect after 5 seconds. + * + * Copyright (C) 2013 by Norbert Truchsess + */ + +#include + +EthernetClient client; +signed long next; + +void setup() { + + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + Ethernet.begin(mac); + + Serial.print("localIP: "); + Serial.println(Ethernet.localIP()); + Serial.print("subnetMask: "); + Serial.println(Ethernet.subnetMask()); + Serial.print("gatewayIP: "); + Serial.println(Ethernet.gatewayIP()); + Serial.print("dnsServerIP: "); + Serial.println(Ethernet.dnsServerIP()); + + next = 0; +} + +void loop() { + + if (((signed long)(millis() - next)) > 0) + { + next = millis() + 5000; + Serial.println("Client connect"); + // replace hostname with name of machine running tcpserver.pl +// if (client.connect("server.local",5000)) + if (client.connect(IPAddress(192,168,0,1),5000)) + { + Serial.println("Client connected"); + client.println("DATA from Client"); + while(client.available()==0) + { + if (next - millis() < 0) + goto close; + } + int size; + while((size = client.available()) > 0) + { + uint8_t* msg = (uint8_t*)malloc(size); + size = client.read(msg,size); + Serial.write(msg,size); + free(msg); + } +close: + //disconnect client + Serial.println("Client disconnect"); + client.stop(); + } + else + Serial.println("Client connect failed"); + } +} diff --git a/libraries/UIPEthernet/examples/TcpServer/TcpServer.ino b/libraries/UIPEthernet/examples/TcpServer/TcpServer.ino new file mode 100644 index 0000000..10512ec --- /dev/null +++ b/libraries/UIPEthernet/examples/TcpServer/TcpServer.ino @@ -0,0 +1,53 @@ +/* + * UIPEthernet EchoServer example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This Hello World example sets up a server at 192.168.1.6 on port 1000. + * Telnet here to access the service. The uIP stack will also respond to + * pings to test if you have successfully established a TCP connection to + * the Arduino. + * + * This example was based upon uIP hello-world by Adam Dunkels + * Ported to the Arduino IDE by Adam Nielsen + * Adaption to Enc28J60 by Norbert Truchsess + */ + +#include + +EthernetServer server = EthernetServer(1000); + +void setup() +{ + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + IPAddress myIP(192,168,0,6); + + Ethernet.begin(mac,myIP); + + server.begin(); +} + +void loop() +{ + size_t size; + + if (EthernetClient client = server.available()) + { + while((size = client.available()) > 0) + { + uint8_t* msg = (uint8_t*)malloc(size); + size = client.read(msg,size); + Serial.write(msg,size); + free(msg); + } + client.println("DATA from Server!"); + client.stop(); + } +} diff --git a/libraries/UIPEthernet/examples/UdpClient/UdpClient.ino b/libraries/UIPEthernet/examples/UdpClient/UdpClient.ino new file mode 100644 index 0000000..aad56b4 --- /dev/null +++ b/libraries/UIPEthernet/examples/UdpClient/UdpClient.ino @@ -0,0 +1,93 @@ +/* + * UIPEthernet UdpClient example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This UdpClient example tries to send a packet via udp to 192.168.0.1 + * on port 5000 every 5 seconds. After successfully sending the packet it + * waits for up to 5 seconds for a response on the local port that has been + * implicitly opened when sending the packet. + * + * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) + */ + +#include + +EthernetUDP udp; +unsigned long next; + +void setup() { + + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + + Ethernet.begin(mac,IPAddress(192,168,0,6)); + + next = millis()+5000; +} + +void loop() { + + int success; + int len = 0; + + if (((signed long)(millis()-next))>0) + { + do + { + success = udp.beginPacket(IPAddress(192,168,0,1),5000); + Serial.print("beginPacket: "); + Serial.println(success ? "success" : "failed"); + //beginPacket fails if remote ethaddr is unknown. In this case an + //arp-request is send out first and beginPacket succeeds as soon + //the arp-response is received. + } + while (!success && ((signed long)(millis()-next))<0); + if (!success ) + goto stop; + + success = udp.write("hello world from arduino"); + + Serial.print("bytes written: "); + Serial.println(success); + + success = udp.endPacket(); + + Serial.print("endPacket: "); + Serial.println(success ? "success" : "failed"); + + do + { + //check for new udp-packet: + success = udp.parsePacket(); + } + while (!success && ((signed long)(millis()-next))<0); + if (!success ) + goto stop; + + Serial.print("received: '"); + do + { + int c = udp.read(); + Serial.write(c); + len++; + } + while ((success = udp.available())>0); + Serial.print("', "); + Serial.print(len); + Serial.println(" bytes"); + + //finish reading this packet: + udp.flush(); + + stop: + udp.stop(); + next = millis()+5000; + } +} diff --git a/libraries/UIPEthernet/examples/UdpServer/UdpServer.ino b/libraries/UIPEthernet/examples/UdpServer/UdpServer.ino new file mode 100644 index 0000000..3b12d75 --- /dev/null +++ b/libraries/UIPEthernet/examples/UdpServer/UdpServer.ino @@ -0,0 +1,88 @@ +/* + * UIPEthernet UdpServer example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This UdpServer example sets up a udp-server at 192.168.0.6 on port 5000. + * send packet via upd to test + * + * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) + */ + +#include + +EthernetUDP udp; + +void setup() { + + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + + Ethernet.begin(mac,IPAddress(192,168,0,6)); + + int success = udp.begin(5000); + + Serial.print("initialize: "); + Serial.println(success ? "success" : "failed"); + +} + +void loop() { + + //check for new udp-packet: + int size = udp.parsePacket(); + if (size > 0) { + do + { + char* msg = (char*)malloc(size+1); + int len = udp.read(msg,size+1); + msg[len]=0; + Serial.print("received: '"); + Serial.print(msg); + free(msg); + } + while ((size = udp.available())>0); + //finish reading this packet: + udp.flush(); + Serial.println("'"); + int success; + do + { + Serial.print("remote ip: "); + Serial.println(udp.remoteIP()); + Serial.print("remote port: "); + Serial.println(udp.remotePort()); + //send new packet back to ip/port of client. This also + //configures the current connection to ignore packets from + //other clients! + success = udp.beginPacket(udp.remoteIP(),udp.remotePort()); + Serial.print("beginPacket: "); + Serial.println(success ? "success" : "failed"); + //beginPacket fails if remote ethaddr is unknown. In this case an + //arp-request is send out first and beginPacket succeeds as soon + //the arp-response is received. + } + while (!success); + + success = udp.println("hello world from arduino"); + + Serial.print("bytes written: "); + Serial.println(success); + + success = udp.endPacket(); + + Serial.print("endPacket: "); + Serial.println(success ? "success" : "failed"); + + udp.stop(); + //restart with new connection to receive packets from other clients + Serial.print("restart connection: "); + Serial.println (udp.begin(5000) ? "success" : "failed"); + } +} diff --git a/libraries/UIPEthernet/keywords.txt b/libraries/UIPEthernet/keywords.txt new file mode 100644 index 0000000..83ff854 --- /dev/null +++ b/libraries/UIPEthernet/keywords.txt @@ -0,0 +1,58 @@ +####################################### +# Syntax Coloring Map for SerialIP +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +UIPEthernet KEYWORD1 +UIPServer KEYWORD1 +UIPClient KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +PSOCK_BEGIN KEYWORD2 +PSOCK_CLOSE KEYWORD2 +PSOCK_END KEYWORD2 +PSOCK_EXIT KEYWORD2 +PSOCK_INIT KEYWORD2 +PSOCK_READBUF KEYWORD2 +PSOCK_READTO KEYWORD2 +PSOCK_SEND KEYWORD2 +PSOCK_SEND_STR KEYWORD2 + +uip_listen KEYWORD2 +uip_unlisten KEYWORD2 +uip_connect KEYWORD2 +uip_outstanding KEYWORD2 +uip_send KEYWORD2 +uip_datalen KEYWORD2 +uip_close KEYWORD2 +uip_abort KEYWORD2 +uip_stop KEYWORD2 +uip_stopped KEYWORD2 +uip_restart KEYWORD2 +uip_acked KEYWORD2 +uip_connected KEYWORD2 +uip_closed KEYWORD2 +uip_aborted KEYWORD2 +uip_timedout KEYWORD2 +uip_rexmit KEYWORD2 +uip_poll KEYWORD2 +uip_initialmss KEYWORD2 +uip_mss KEYWORD2 +uip_ipaddr KEYWORD2 +uip_ipaddr_maskcmp KEYWORD2 +uip_ipaddr_mask KEYWORD2 +HTONS KEYWORD2 +htons KEYWORD2 + +use_device KEYWORD2 +set_uip_callback KEYWORD2 +set_gateway KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/UIPEthernet/library.properties b/libraries/UIPEthernet/library.properties new file mode 100644 index 0000000..158ae31 --- /dev/null +++ b/libraries/UIPEthernet/library.properties @@ -0,0 +1,10 @@ +name=UIPEthernet +author=ntruchsess +email=Norbert Truchsess +sentence=Ethernet library for ENC28J60 +paragraph=implements the same API as stock Ethernet-lib. Just replace the include of Ethernet.h with UIPEthernet.h +url=https://github.com/ntruchsess/arduino_uip +architectures=avr +version=1.04 +dependencies= +core-dependencies=arduino (>=1.5.0) diff --git a/libraries/UIPEthernet/tests/perl/tcpclient.pl b/libraries/UIPEthernet/tests/perl/tcpclient.pl new file mode 100644 index 0000000..e6884dc --- /dev/null +++ b/libraries/UIPEthernet/tests/perl/tcpclient.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl +#tcpclient.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$client_socket); + +# creating object interface of IO::Socket::INET modules which internally creates +# socket, binds and connects to the TCP server running on the specific port. +$socket = new IO::Socket::INET ( +PeerHost => '192.168.0.6', +PeerPort => '1000', +Proto => 'tcp', +) or die "ERROR in Socket Creation : $!\n"; + +print "TCP Connection Success.\n"; + +# write on the socket to server. +$data = "DATA from Client"; +print $socket "$data\n"; +# we can also send the data through IO::Socket::INET module, +# $socket->send($data); + +# read the socket data sent by server. +$data = <$socket>; +# we can also read from socket through recv() in IO::Socket::INET +# $socket->recv($data,1024); +print "Received from Server : $data\n"; + +sleep (10); +$socket->close(); \ No newline at end of file diff --git a/libraries/UIPEthernet/tests/perl/tcpserver.pl b/libraries/UIPEthernet/tests/perl/tcpserver.pl new file mode 100644 index 0000000..17405a3 --- /dev/null +++ b/libraries/UIPEthernet/tests/perl/tcpserver.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +#tcpserver.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$client_socket); +my ($peeraddress,$peerport); + +# creating object interface of IO::Socket::INET modules which internally does +# socket creation, binding and listening at the specified port address. +$socket = new IO::Socket::INET ( +LocalHost => '192.168.0.1', +LocalPort => '5000', +Proto => 'tcp', +Listen => 5, +Reuse => 1 +) or die "ERROR in Socket Creation : $!\n"; + +print "SERVER Waiting for client connection on port 5000\n"; + +while(1) +{ + # waiting for new client connection. + $client_socket = $socket->accept(); + + # get the host and port number of newly connected client. + $peer_address = $client_socket->peerhost(); + $peer_port = $client_socket->peerport(); + + print "Accepted New Client Connection From : $peer_address, $peer_port\n "; + + # read operation on the newly accepted client + $data = <$client_socket>; + # we can also read from socket through recv() in IO::Socket::INET + # $client_socket->recv($data,1024); + print "Received from Client : $data\n"; + + # write operation on the newly accepted client. + $data = "DATA from Server"; + print $client_socket "$data\n"; + # we can also send the data through IO::Socket::INET module, + # $client_socket->send($data); + + sleep(1); + + $client_socket->close(); +} + +$socket->close(); + diff --git a/libraries/UIPEthernet/tests/perl/udpclient.pl b/libraries/UIPEthernet/tests/perl/udpclient.pl new file mode 100644 index 0000000..bc9e6a2 --- /dev/null +++ b/libraries/UIPEthernet/tests/perl/udpclient.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl +#udpclient.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$data); + +# We call IO::Socket::INET->new() to create the UDP Socket +# and bind with the PeerAddr. +$socket = new IO::Socket::INET ( +PeerAddr => '192.168.0.6:5000', +Proto => 'udp' +) or die "ERROR in Socket Creation : $!\n"; +#send operation +$data = "data from client"; +$socket->send($data); + +#read operation +$data = <$socket>; +print "Data received from socket : $data\n "; + +sleep(10); +$socket->close(); diff --git a/libraries/UIPEthernet/tests/perl/udpserver.pl b/libraries/UIPEthernet/tests/perl/udpserver.pl new file mode 100644 index 0000000..e728a46 --- /dev/null +++ b/libraries/UIPEthernet/tests/perl/udpserver.pl @@ -0,0 +1,40 @@ +#!/usr/bin/perl +#udpserver.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$received_data); +my ($peeraddress,$peerport); + +# we call IO::Socket::INET->new() to create the UDP Socket and bound +# to specific port number mentioned in LocalPort and there is no need to provide +# LocalAddr explicitly as in TCPServer. +$socket = new IO::Socket::INET ( +LocalPort => '5000', +Proto => 'udp', +) or die "ERROR in Socket Creation : $!\n"; + +while(1) +{ +# read operation on the socket +$socket->recv($recieved_data,1024); + +#get the peerhost and peerport at which the recent data received. +$peer_address = $socket->peerhost(); +$peer_port = $socket->peerport(); +print "($peer_address , $peer_port) said : $recieved_data\n"; + +#send the data to the client at which the read/write operations done recently. +$data = "data from server\n"; + +$socket->send($data); + +print $socket "$data"; + +} + +$socket->close(); + diff --git a/libraries/UIPEthernet/utility/Enc28J60Network.cpp b/libraries/UIPEthernet/utility/Enc28J60Network.cpp new file mode 100644 index 0000000..c7c66fb --- /dev/null +++ b/libraries/UIPEthernet/utility/Enc28J60Network.cpp @@ -0,0 +1,612 @@ +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "Enc28J60Network.h" +#include "Arduino.h" + +extern "C" { +#include +#include "enc28j60.h" +#include "uip.h" +} + +#ifdef ENC28J60DEBUG +#include "HardwareSerial.h" +#endif + +// set CS to 0 = active +#define CSACTIVE digitalWrite(ENC28J60_CONTROL_CS, LOW) +// set CS to 1 = passive +#define CSPASSIVE digitalWrite(ENC28J60_CONTROL_CS, HIGH) +// +#define waitspi() while(!(SPSR&(1< ip checksum for theses bytes=f7f9 + // in binary these poitions are:11 0000 0011 1111 + // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 + //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! + writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN); + writeRegPair(EPMM0, 0x303f); + writeRegPair(EPMCSL, 0xf7f9); + // + // + // do bank 2 stuff + // enable MAC receive + // and bring MAC out of reset (writes 0x00 to MACON2) + writeRegPair(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); + // enable automatic padding to 60bytes and CRC operations + writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); + // set inter-frame gap (non-back-to-back) + writeRegPair(MAIPGL, 0x0C12); + // set inter-frame gap (back-to-back) + writeReg(MABBIPG, 0x12); + // Set the maximum packet size which the controller will accept + // Do not send packets longer than MAX_FRAMELEN: + writeRegPair(MAMXFLL, MAX_FRAMELEN); + // do bank 3 stuff + // write MAC address + // NOTE: MAC address in ENC28J60 is byte-backward + writeReg(MAADR5, macaddr[0]); + writeReg(MAADR4, macaddr[1]); + writeReg(MAADR3, macaddr[2]); + writeReg(MAADR2, macaddr[3]); + writeReg(MAADR1, macaddr[4]); + writeReg(MAADR0, macaddr[5]); + // no loopback of transmitted frames + phyWrite(PHCON2, PHCON2_HDLDIS); + // switch to bank 0 + setBank(ECON1); + // enable interrutps + writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); + // enable packet reception + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + //Configure leds + phyWrite(PHLCON,0x476); +} + +memhandle +Enc28J60Network::receivePacket() +{ + uint8_t rxstat; + uint16_t len; + // check if a packet has been received and buffered + //if( !(readReg(EIR) & EIR_PKTIF) ){ + // The above does not work. See Rev. B4 Silicon Errata point 6. + if (readReg(EPKTCNT) != 0) + { + uint16_t readPtr = nextPacketPtr+6 > RXSTOP_INIT ? nextPacketPtr+6-RXSTOP_INIT+RXSTART_INIT : nextPacketPtr+6; + // Set the read pointer to the start of the received packet + writeRegPair(ERDPTL, nextPacketPtr); + // read the next packet pointer + nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); + nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + // read the packet length (see datasheet page 43) + len = readOp(ENC28J60_READ_BUF_MEM, 0); + len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + len -= 4; //remove the CRC count + // read the receive status (see datasheet page 43) + rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); + //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; +#ifdef ENC28J60DEBUG + Serial.print("receivePacket ["); + Serial.print(readPtr,HEX); + Serial.print("-"); + Serial.print((readPtr+len) % (RXSTOP_INIT+1),HEX); + Serial.print("], next: "); + Serial.print(nextPacketPtr,HEX); + Serial.print(", stat: "); + Serial.print(rxstat,HEX); + Serial.print(", count: "); + Serial.print(readReg(EPKTCNT)); + Serial.print(" -> "); + Serial.println((rxstat & 0x80)!=0 ? "OK" : "failed"); +#endif + // decrement the packet counter indicate we are done with this packet + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); + // check CRC and symbol errors (see datasheet page 44, table 7-3): + // The ERXFCON.CRCEN is set by default. Normally we should not + // need to check this. + if ((rxstat & 0x80) != 0) + { + receivePkt.begin = readPtr; + receivePkt.size = len; + return UIP_RECEIVEBUFFERHANDLE; + } + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); + } + return (NOBLOCK); +} + +void +Enc28J60Network::setERXRDPT() +{ + writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr-1); +} + +memaddress +Enc28J60Network::blockSize(memhandle handle) +{ + return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; +} + +void +Enc28J60Network::sendPacket(memhandle handle) +{ + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin-1; + uint16_t end = start + packet->size; + + // backup data at control-byte position + uint8_t data = readByte(start); + // write control-byte (if not 0 anyway) + if (data) + writeByte(start, 0); + +#ifdef ENC28J60DEBUG + Serial.print("sendPacket("); + Serial.print(handle); + Serial.print(") ["); + Serial.print(start,HEX); + Serial.print("-"); + Serial.print(end,HEX); + Serial.print("]: "); + for (uint16_t i=start; i<=end; i++) + { + Serial.print(readByte(i),HEX); + Serial.print(" "); + } + Serial.println(); +#endif + + // TX start + writeRegPair(ETXSTL, start); + // Set the TXND pointer to correspond to the packet size given + writeRegPair(ETXNDL, end); + // send the contents of the transmit buffer onto the network + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); + // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. + if( (readReg(EIR) & EIR_TXERIF) ) + { + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); + } + + //restore data on control-byte position + if (data) + writeByte(start, data); +} + +uint16_t +Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) +{ + memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; + memaddress start = handle == UIP_RECEIVEBUFFERHANDLE && packet->begin + position > RXSTOP_INIT ? packet->begin + position-RXSTOP_INIT+RXSTART_INIT : packet->begin + position; + + writeRegPair(ERDPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + return len; +} + +uint16_t +Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ + len = setReadPtr(handle, position, len); + readBuffer(len, buffer); + return len; +} + +uint16_t +Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin + position; + + writeRegPair(EWRPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + writeBuffer(len, buffer); + return len; +} + +uint8_t Enc28J60Network::readByte(uint16_t addr) +{ + writeRegPair(ERDPTL, addr); + + CSACTIVE; + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + CSPASSIVE; + return (SPDR); +} + +void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) +{ + writeRegPair(EWRPTL, addr); + + CSACTIVE; + // issue write command + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); + // write data + SPDR = data; + waitspi(); + CSPASSIVE; +} + +void +Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) +{ + memblock *dest = &blocks[dest_pkt]; + memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; + memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE && src->begin + src_pos > RXSTOP_INIT ? src->begin + src_pos-RXSTOP_INIT+RXSTART_INIT : src->begin + src_pos; + enc28J60_mempool_block_move_callback(dest->begin+dest_pos,start,len); + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); +} + +void +enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) +{ +//void +//Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) +//{ + //as ENC28J60 DMA is unable to copy single bytes: + if (len == 1) + { + Enc28J60Network::writeByte(dest,Enc28J60Network::readByte(src)); + } + else + { + // calculate address of last byte + len += src - 1; + + /* 1. Appropriately program the EDMAST, EDMAND + and EDMADST register pairs. The EDMAST + registers should point to the first byte to copy + from, the EDMAND registers should point to the + last byte to copy and the EDMADST registers + should point to the first byte in the destination + range. The destination range will always be + linear, never wrapping at any values except from + 8191 to 0 (the 8-Kbyte memory boundary). + Extreme care should be taken when + programming the start and end pointers to + prevent a never ending DMA operation which + would overwrite the entire 8-Kbyte buffer. + */ + Enc28J60Network::writeRegPair(EDMASTL, src); + Enc28J60Network::writeRegPair(EDMADSTL, dest); + + if ((src <= RXSTOP_INIT)&& (len > RXSTOP_INIT))len -= (RXSTOP_INIT-RXSTART_INIT); + Enc28J60Network::writeRegPair(EDMANDL, len); + + /* + 2. If an interrupt at the end of the copy process is + desired, set EIE.DMAIE and EIE.INTIE and + clear EIR.DMAIF. + + 3. Verify that ECON1.CSUMEN is clear. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); + + /* 4. Start the DMA copy by setting ECON1.DMAST. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + + // wait until runnig DMA is completed + while (Enc28J60Network::readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST); + } +} + +void +Enc28J60Network::freePacket() +{ + setERXRDPT(); +} + +uint8_t +Enc28J60Network::readOp(uint8_t op, uint8_t address) +{ + CSACTIVE; + // issue read command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + // do dummy read if needed (for mac and mii, see datasheet page 29) + if(address & 0x80) + { + SPDR = 0x00; + waitspi(); + } + // release CS + CSPASSIVE; + return(SPDR); +} + +void +Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) +{ + CSACTIVE; + // issue write command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // write data + SPDR = data; + waitspi(); + CSPASSIVE; +} + +void +Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) +{ + CSACTIVE; + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + while(len) + { + len--; + // read data + SPDR = 0x00; + waitspi(); + *data = SPDR; + data++; + } + //*data='\0'; + CSPASSIVE; +} + +void +Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) +{ + CSACTIVE; + // issue write command + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); + while(len) + { + len--; + // write data + SPDR = *data; + data++; + waitspi(); + } + CSPASSIVE; +} + +void +Enc28J60Network::setBank(uint8_t address) +{ + // set the bank (if needed) + if((address & BANK_MASK) != bank) + { + // set the bank + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); + bank = (address & BANK_MASK); + } +} + +uint8_t +Enc28J60Network::readReg(uint8_t address) +{ + // set the bank + setBank(address); + // do the read + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +void +Enc28J60Network::writeReg(uint8_t address, uint8_t data) +{ + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +void +Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) +{ + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, (data&0xFF)); + writeOp(ENC28J60_WRITE_CTRL_REG, address+1, (data) >> 8); +} + +void +Enc28J60Network::phyWrite(uint8_t address, uint16_t data) +{ + // set the PHY register address + writeReg(MIREGADR, address); + // write the PHY data + writeRegPair(MIWRL, data); + // wait until the PHY write completes + while(readReg(MISTAT) & MISTAT_BUSY){ + delayMicroseconds(15); + } +} + +uint16_t +Enc28J60Network::phyRead(uint8_t address) +{ + writeReg(MIREGADR,address); + writeReg(MICMD, MICMD_MIIRD); + // wait until the PHY read completes + while(readReg(MISTAT) & MISTAT_BUSY){ + delayMicroseconds(15); + } //and MIRDH + writeReg(MICMD, 0); + return (readReg(MIRDL) | readReg(MIRDH) << 8); +} + +void +Enc28J60Network::clkout(uint8_t clk) +{ + //setup clkout: 2 is 12.5MHz: + writeReg(ECOCON, clk & 0x7); +} + +// read the revision of the chip: +uint8_t +Enc28J60Network::getrev(void) +{ + return(readReg(EREVID)); +} + +uint16_t +Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) +{ + uint16_t t; + len = setReadPtr(handle, pos, len)-1; + CSACTIVE; + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + uint16_t i; + for (i = 0; i < len; i+=2) + { + // read data + SPDR = 0x00; + waitspi(); + t = SPDR << 8; + SPDR = 0x00; + waitspi(); + t += SPDR; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + if(i == len) { + SPDR = 0x00; + waitspi(); + t = (SPDR << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + CSPASSIVE; + + /* Return sum in host byte order. */ + return sum; +} + +void +Enc28J60Network::powerOff() +{ + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); +} + +void +Enc28J60Network::powerOn() +{ + writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + delay(50); +} + +bool +Enc28J60Network::linkStatus() +{ + return (phyRead(PHSTAT2) & 0x0400) > 0; +} + +Enc28J60Network Enc28J60; diff --git a/libraries/UIPEthernet/utility/Enc28J60Network.h b/libraries/UIPEthernet/utility/Enc28J60Network.h new file mode 100644 index 0000000..7346e47 --- /dev/null +++ b/libraries/UIPEthernet/utility/Enc28J60Network.h @@ -0,0 +1,91 @@ +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + inspired by enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef Enc28J60Network_H_ +#define Enc28J60Network_H_ + +#include "mempool.h" + +#define ENC28J60_CONTROL_CS SS +#define SPI_MOSI MOSI +#define SPI_MISO MISO +#define SPI_SCK SCK +#define SPI_SS SS + +#define UIP_RECEIVEBUFFERHANDLE 0xff + +//#define ENC28J60DEBUG + +/* + * Empfangen von ip-header, arp etc... + * wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection + */ + +class Enc28J60Network : public MemoryPool +{ + +private: + static uint16_t nextPacketPtr; + static uint8_t bank; + + static struct memblock receivePkt; + + static uint8_t readOp(uint8_t op, uint8_t address); + static void writeOp(uint8_t op, uint8_t address, uint8_t data); + static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); + static void setERXRDPT(); + static void readBuffer(uint16_t len, uint8_t* data); + static void writeBuffer(uint16_t len, uint8_t* data); + static uint8_t readByte(uint16_t addr); + static void writeByte(uint16_t addr, uint8_t data); + static void setBank(uint8_t address); + static uint8_t readReg(uint8_t address); + static void writeReg(uint8_t address, uint8_t data); + static void writeRegPair(uint8_t address, uint16_t data); + static void phyWrite(uint8_t address, uint16_t data); + static uint16_t phyRead(uint8_t address); + static void clkout(uint8_t clk); + + friend void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); + +public: + + uint8_t getrev(void); + void powerOn(); + void powerOff(); + bool linkStatus(); + + static void init(uint8_t* macaddr); + static memhandle receivePacket(); + static void freePacket(); + static memaddress blockSize(memhandle handle); + static void sendPacket(memhandle handle); + static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); + static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); +}; + +extern Enc28J60Network Enc28J60; +#endif /* Enc28J60NetworkClass_H_ */ diff --git a/libraries/UIPEthernet/utility/clock-arch.c b/libraries/UIPEthernet/utility/clock-arch.c new file mode 100644 index 0000000..13b886d --- /dev/null +++ b/libraries/UIPEthernet/utility/clock-arch.c @@ -0,0 +1,28 @@ +/* + clock-arch.c - Arduino implementation of uIP clock device. + Copyright (c) 2010 Adam Nielsen + All rights 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 "clock-arch.h" + +clock_time_t +clock_time(void) +{ + return (clock_time_t) millis(); +} diff --git a/libraries/UIPEthernet/utility/clock-arch.h b/libraries/UIPEthernet/utility/clock-arch.h new file mode 100644 index 0000000..d7a828b --- /dev/null +++ b/libraries/UIPEthernet/utility/clock-arch.h @@ -0,0 +1,27 @@ +/* + clock-arch.h - Arduino implementation of uIP clock device. + Copyright (c) 2010 Adam Nielsen + All rights 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 clock_h_ +#define clock_h_ + +typedef unsigned long clock_time_t; +#define CLOCK_CONF_SECOND 1000 + +#endif diff --git a/libraries/UIPEthernet/utility/enc28j60.h b/libraries/UIPEthernet/utility/enc28j60.h new file mode 100644 index 0000000..3a45c59 --- /dev/null +++ b/libraries/UIPEthernet/utility/enc28j60.h @@ -0,0 +1,257 @@ +/***************************************************************************** +* +* Title : Microchip ENC28J60 Ethernet Interface Driver +* Author : Pascal Stang (c)2005 +* Modified by Norbert Truchsess +* Copyright: GPL V2 +* +*This driver provides initialization and transmit/receive +*functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY. +*This chip is novel in that it is a full MAC+PHY interface all in a 28-pin +*chip, using an SPI interface to the host processor. +* +* +*****************************************************************************/ + +#ifndef ENC28J60_H +#define ENC28J60_H +#include + +// ENC28J60 Control Registers +// Control register definitions are a combination of address, +// bank number, and Ethernet/MAC/PHY indicator bits. +// - Register address (bits 0-4) +// - Bank number (bits 5-6) +// - MAC/PHY indicator (bit 7) +#define ADDR_MASK 0x1F +#define BANK_MASK 0x60 +#define SPRD_MASK 0x80 +// All-bank registers +#define EIE 0x1B +#define EIR 0x1C +#define ESTAT 0x1D +#define ECON2 0x1E +#define ECON1 0x1F +// Bank 0 registers +#define ERDPTL (0x00|0x00) +#define ERDPTH (0x01|0x00) +#define EWRPTL (0x02|0x00) +#define EWRPTH (0x03|0x00) +#define ETXSTL (0x04|0x00) +#define ETXSTH (0x05|0x00) +#define ETXNDL (0x06|0x00) +#define ETXNDH (0x07|0x00) +#define ERXSTL (0x08|0x00) +#define ERXSTH (0x09|0x00) +#define ERXNDL (0x0A|0x00) +#define ERXNDH (0x0B|0x00) +#define ERXRDPTL (0x0C|0x00) +#define ERXRDPTH (0x0D|0x00) +#define ERXWRPTL (0x0E|0x00) +#define ERXWRPTH (0x0F|0x00) +#define EDMASTL (0x10|0x00) +#define EDMASTH (0x11|0x00) +#define EDMANDL (0x12|0x00) +#define EDMANDH (0x13|0x00) +#define EDMADSTL (0x14|0x00) +#define EDMADSTH (0x15|0x00) +#define EDMACSL (0x16|0x00) +#define EDMACSH (0x17|0x00) +// Bank 1 registers +#define EHT0 (0x00|0x20) +#define EHT1 (0x01|0x20) +#define EHT2 (0x02|0x20) +#define EHT3 (0x03|0x20) +#define EHT4 (0x04|0x20) +#define EHT5 (0x05|0x20) +#define EHT6 (0x06|0x20) +#define EHT7 (0x07|0x20) +#define EPMM0 (0x08|0x20) +#define EPMM1 (0x09|0x20) +#define EPMM2 (0x0A|0x20) +#define EPMM3 (0x0B|0x20) +#define EPMM4 (0x0C|0x20) +#define EPMM5 (0x0D|0x20) +#define EPMM6 (0x0E|0x20) +#define EPMM7 (0x0F|0x20) +#define EPMCSL (0x10|0x20) +#define EPMCSH (0x11|0x20) +#define EPMOL (0x14|0x20) +#define EPMOH (0x15|0x20) +#define EWOLIE (0x16|0x20) +#define EWOLIR (0x17|0x20) +#define ERXFCON (0x18|0x20) +#define EPKTCNT (0x19|0x20) +// Bank 2 registers +#define MACON1 (0x00|0x40|0x80) +#define MACON2 (0x01|0x40|0x80) +#define MACON3 (0x02|0x40|0x80) +#define MACON4 (0x03|0x40|0x80) +#define MABBIPG (0x04|0x40|0x80) +#define MAIPGL (0x06|0x40|0x80) +#define MAIPGH (0x07|0x40|0x80) +#define MACLCON1 (0x08|0x40|0x80) +#define MACLCON2 (0x09|0x40|0x80) +#define MAMXFLL (0x0A|0x40|0x80) +#define MAMXFLH (0x0B|0x40|0x80) +#define MAPHSUP (0x0D|0x40|0x80) +#define MICON (0x11|0x40|0x80) +#define MICMD (0x12|0x40|0x80) +#define MIREGADR (0x14|0x40|0x80) +#define MIWRL (0x16|0x40|0x80) +#define MIWRH (0x17|0x40|0x80) +#define MIRDL (0x18|0x40|0x80) +#define MIRDH (0x19|0x40|0x80) +// Bank 3 registers +#define MAADR1 (0x00|0x60|0x80) +#define MAADR0 (0x01|0x60|0x80) +#define MAADR3 (0x02|0x60|0x80) +#define MAADR2 (0x03|0x60|0x80) +#define MAADR5 (0x04|0x60|0x80) +#define MAADR4 (0x05|0x60|0x80) +#define EBSTSD (0x06|0x60) +#define EBSTCON (0x07|0x60) +#define EBSTCSL (0x08|0x60) +#define EBSTCSH (0x09|0x60) +#define MISTAT (0x0A|0x60|0x80) +#define EREVID (0x12|0x60) +#define ECOCON (0x15|0x60) +#define EFLOCON (0x17|0x60) +#define EPAUSL (0x18|0x60) +#define EPAUSH (0x19|0x60) +// PHY registers +#define PHCON1 0x00 +#define PHSTAT1 0x01 +#define PHHID1 0x02 +#define PHHID2 0x03 +#define PHCON2 0x10 +#define PHSTAT2 0x11 +#define PHIE 0x12 +#define PHIR 0x13 +#define PHLCON 0x14 + +// ENC28J60 ERXFCON Register Bit Definitions +#define ERXFCON_UCEN 0x80 +#define ERXFCON_ANDOR 0x40 +#define ERXFCON_CRCEN 0x20 +#define ERXFCON_PMEN 0x10 +#define ERXFCON_MPEN 0x08 +#define ERXFCON_HTEN 0x04 +#define ERXFCON_MCEN 0x02 +#define ERXFCON_BCEN 0x01 +// ENC28J60 EIE Register Bit Definitions +#define EIE_INTIE 0x80 +#define EIE_PKTIE 0x40 +#define EIE_DMAIE 0x20 +#define EIE_LINKIE 0x10 +#define EIE_TXIE 0x08 +#define EIE_WOLIE 0x04 +#define EIE_TXERIE 0x02 +#define EIE_RXERIE 0x01 +// ENC28J60 EIR Register Bit Definitions +#define EIR_PKTIF 0x40 +#define EIR_DMAIF 0x20 +#define EIR_LINKIF 0x10 +#define EIR_TXIF 0x08 +#define EIR_WOLIF 0x04 +#define EIR_TXERIF 0x02 +#define EIR_RXERIF 0x01 +// ENC28J60 ESTAT Register Bit Definitions +#define ESTAT_INT 0x80 +#define ESTAT_LATECOL 0x10 +#define ESTAT_RXBUSY 0x04 +#define ESTAT_TXABRT 0x02 +#define ESTAT_CLKRDY 0x01 +// ENC28J60 ECON2 Register Bit Definitions +#define ECON2_AUTOINC 0x80 +#define ECON2_PKTDEC 0x40 +#define ECON2_PWRSV 0x20 +#define ECON2_VRPS 0x08 +// ENC28J60 ECON1 Register Bit Definitions +#define ECON1_TXRST 0x80 +#define ECON1_RXRST 0x40 +#define ECON1_DMAST 0x20 +#define ECON1_CSUMEN 0x10 +#define ECON1_TXRTS 0x08 +#define ECON1_RXEN 0x04 +#define ECON1_BSEL1 0x02 +#define ECON1_BSEL0 0x01 +// ENC28J60 MACON1 Register Bit Definitions +#define MACON1_LOOPBK 0x10 +#define MACON1_TXPAUS 0x08 +#define MACON1_RXPAUS 0x04 +#define MACON1_PASSALL 0x02 +#define MACON1_MARXEN 0x01 +// ENC28J60 MACON2 Register Bit Definitions +#define MACON2_MARST 0x80 +#define MACON2_RNDRST 0x40 +#define MACON2_MARXRST 0x08 +#define MACON2_RFUNRST 0x04 +#define MACON2_MATXRST 0x02 +#define MACON2_TFUNRST 0x01 +// ENC28J60 MACON3 Register Bit Definitions +#define MACON3_PADCFG2 0x80 +#define MACON3_PADCFG1 0x40 +#define MACON3_PADCFG0 0x20 +#define MACON3_TXCRCEN 0x10 +#define MACON3_PHDRLEN 0x08 +#define MACON3_HFRMLEN 0x04 +#define MACON3_FRMLNEN 0x02 +#define MACON3_FULDPX 0x01 +// ENC28J60 MICMD Register Bit Definitions +#define MICMD_MIISCAN 0x02 +#define MICMD_MIIRD 0x01 +// ENC28J60 MISTAT Register Bit Definitions +#define MISTAT_NVALID 0x04 +#define MISTAT_SCAN 0x02 +#define MISTAT_BUSY 0x01 +// ENC28J60 PHY PHCON1 Register Bit Definitions +#define PHCON1_PRST 0x8000 +#define PHCON1_PLOOPBK 0x4000 +#define PHCON1_PPWRSV 0x0800 +#define PHCON1_PDPXMD 0x0100 +// ENC28J60 PHY PHSTAT1 Register Bit Definitions +#define PHSTAT1_PFDPX 0x1000 +#define PHSTAT1_PHDPX 0x0800 +#define PHSTAT1_LLSTAT 0x0004 +#define PHSTAT1_JBSTAT 0x0002 +// ENC28J60 PHY PHCON2 Register Bit Definitions +#define PHCON2_FRCLINK 0x4000 +#define PHCON2_TXDIS 0x2000 +#define PHCON2_JABBER 0x0400 +#define PHCON2_HDLDIS 0x0100 + +// ENC28J60 Packet Control Byte Bit Definitions +#define PKTCTRL_PHUGEEN 0x08 +#define PKTCTRL_PPADEN 0x04 +#define PKTCTRL_PCRCEN 0x02 +#define PKTCTRL_POVERRIDE 0x01 + +// SPI operation codes +#define ENC28J60_READ_CTRL_REG 0x00 +#define ENC28J60_READ_BUF_MEM 0x3A +#define ENC28J60_WRITE_CTRL_REG 0x40 +#define ENC28J60_WRITE_BUF_MEM 0x7A +#define ENC28J60_BIT_FIELD_SET 0x80 +#define ENC28J60_BIT_FIELD_CLR 0xA0 +#define ENC28J60_SOFT_RESET 0xFF + + +// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata +// buffer boundaries applied to internal 8K ram +// the entire available packet buffer space is allocated +// +// start with recbuf at 0/ +#define RXSTART_INIT 0x0 +// receive buffer end. make sure this is an odd value ( See Rev. B1,B4,B5,B7 Silicon Errata 'Memory (Ethernet Buffer)') +#define RXSTOP_INIT (0x1FFF-0x1800) +// start TX buffer RXSTOP_INIT+1 +#define TXSTART_INIT (RXSTOP_INIT+1) +// stp TX buffer at end of mem +#define TXSTOP_INIT 0x1FFF +// +// max frame length which the conroller will accept: +#define MAX_FRAMELEN 1500 // (note: maximum ethernet frame length would be 1518) +//#define MAX_FRAMELEN 600 + +#endif diff --git a/libraries/UIPEthernet/utility/mempool.cpp b/libraries/UIPEthernet/utility/mempool.cpp new file mode 100644 index 0000000..c2f7abf --- /dev/null +++ b/libraries/UIPEthernet/utility/mempool.cpp @@ -0,0 +1,168 @@ +/* + mempool.cpp - sleek implementation of a memory pool + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "mempool.h" +#include + +#define POOLOFFSET 1 + +struct memblock MemoryPool::blocks[MEMPOOL_NUM_MEMBLOCKS+1]; + +void +MemoryPool::init() +{ + memset(&blocks[0], 0, sizeof(blocks)); + blocks[POOLSTART].begin = MEMPOOL_STARTADDRESS; + blocks[POOLSTART].size = 0; + blocks[POOLSTART].nextblock = NOBLOCK; +} + +memhandle +MemoryPool::allocBlock(memaddress size) +{ + memblock* best = NULL; + memhandle cur = POOLSTART; + memblock* block = &blocks[POOLSTART]; + memaddress bestsize = MEMPOOL_SIZE + 1; + + do + { + memhandle next = block->nextblock; + memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - block->begin - block->size; + if (freesize == size) + { + best = &blocks[cur]; + goto found; + } + if (freesize > size && freesize < bestsize) + { + bestsize = freesize; + best = &blocks[cur]; + } + if (next == NOBLOCK) + { + if (best) + goto found; + else + goto collect; + } + block = &blocks[next]; + cur = next; + } + while (true); + + collect: + { + cur = POOLSTART; + block = &blocks[POOLSTART]; + memhandle next; + while ((next = block->nextblock) != NOBLOCK) + { + memaddress dest = block->begin + block->size; + memblock* nextblock = &blocks[next]; + memaddress* src = &nextblock->begin; + if (dest != *src) + { +#ifdef MEMPOOL_MEMBLOCK_MV + MEMPOOL_MEMBLOCK_MV(dest,*src,nextblock->size); +#endif + *src = dest; + } + block = nextblock; + } + if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size) + best = block; + else + goto notfound; + } + + found: + { + block = &blocks[POOLOFFSET]; + for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++) + { + if (block->size) + { + block++; + continue; + } + memaddress address = best->begin + best->size; +#ifdef MEMBLOCK_ALLOC + MEMBLOCK_ALLOC(address,size); +#endif + block->begin = address; + block->size = size; + block->nextblock = best->nextblock; + best->nextblock = cur; + return cur; + } + } + + notfound: return NOBLOCK; +} + +void +MemoryPool::freeBlock(memhandle handle) +{ + if (handle == NOBLOCK) + return; + memblock *b = &blocks[POOLSTART]; + + do + { + memhandle next = b->nextblock; + if (next == handle) + { + memblock *f = &blocks[next]; +#ifdef MEMBLOCK_FREE + MEMBLOCK_FREE(f->begin,f->size); +#endif + b->nextblock = f->nextblock; + f->size = 0; + f->nextblock = NOBLOCK; + return; + } + if (next == NOBLOCK) + return; + b = &blocks[next]; + } + while (true); +} + +void +MemoryPool::resizeBlock(memhandle handle, memaddress position) +{ + memblock * block = &blocks[handle]; + block->begin += position; + block->size -= position; +} + +void +MemoryPool::resizeBlock(memhandle handle, memaddress position, memaddress size) +{ + memblock * block = &blocks[handle]; + block->begin += position; + block->size = size; +} + +memaddress +MemoryPool::blockSize(memhandle handle) +{ + return blocks[handle].size; +} diff --git a/libraries/UIPEthernet/utility/mempool.h b/libraries/UIPEthernet/utility/mempool.h new file mode 100644 index 0000000..2a1db21 --- /dev/null +++ b/libraries/UIPEthernet/utility/mempool.h @@ -0,0 +1,54 @@ +/* + mempool.h - sleek implementation of a memory pool + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef MEMPOOL_H +#define MEMPOOL_H + +#include + +#define POOLSTART 0 +#define NOBLOCK 0 + +#include "mempool_conf.h" + +struct memblock +{ + memaddress begin; + memaddress size; + memhandle nextblock; +}; + +class MemoryPool +{ +#ifdef MEMPOOLTEST_H + friend class MemoryPoolTest; +#endif + +protected: + static struct memblock blocks[MEMPOOL_NUM_MEMBLOCKS+1]; + +public: + static void init(); + static memhandle allocBlock(memaddress); + static void freeBlock(memhandle); + static void resizeBlock(memhandle handle, memaddress position); + static void resizeBlock(memhandle handle, memaddress position, memaddress size); + static memaddress blockSize(memhandle); +}; +#endif diff --git a/libraries/UIPEthernet/utility/mempool_conf.h b/libraries/UIPEthernet/utility/mempool_conf.h new file mode 100644 index 0000000..9615f92 --- /dev/null +++ b/libraries/UIPEthernet/utility/mempool_conf.h @@ -0,0 +1,34 @@ +#ifndef MEMPOOLCONF_H +#define MEMPOOLCONF_H +#include "uipethernet-conf.h" +extern "C" { + #include "uipopt.h" + #include "enc28j60.h" +} +#include + +typedef uint16_t memaddress; +typedef uint8_t memhandle; + +#if UIP_SOCKET_NUMPACKETS and UIP_CONNS +#define NUM_TCP_MEMBLOCKS (UIP_SOCKET_NUMPACKETS*2)*UIP_CONNS +#else +#define NUM_TCP_MEMBLOCKS 0 +#endif + +#if UIP_UDP and UIP_UDP_CONNS +#define NUM_UDP_MEMBLOCKS 3*UIP_UDP_CONNS +#else +#define NUM_UDP_MEMBLOCKS 0 +#endif + +#define MEMPOOL_NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS+NUM_UDP_MEMBLOCKS) + +#define MEMPOOL_STARTADDRESS TXSTART_INIT+1 +#define MEMPOOL_SIZE TXSTOP_INIT-TXSTART_INIT + +void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); + +#define MEMPOOL_MEMBLOCK_MV(dest,src,size) enc28J60_mempool_block_move_callback(dest,src,size) + +#endif diff --git a/libraries/UIPEthernet/utility/uip-conf.h b/libraries/UIPEthernet/utility/uip-conf.h new file mode 100644 index 0000000..814aeb9 --- /dev/null +++ b/libraries/UIPEthernet/utility/uip-conf.h @@ -0,0 +1,185 @@ +/** + * UIPEthernet Project-specific configuration options + * Copyright (c) 2013 Norbert Truchsess + * @{ + * + * uIP has a number of configuration options that can be overridden + * for each project. These are kept in a project-specific uip-conf.h + * file and all configuration names have the prefix UIP_CONF. + */ + +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + */ + +#ifndef __UIP_CONF_H__ +#define __UIP_CONF_H__ + +#include +#include "uipethernet-conf.h" + +/** + * 8 bit datatype + * + * This typedef defines the 8-bit type used throughout uIP. + * + * \hideinitializer + */ +typedef uint8_t u8_t; + +/** + * 16 bit datatype + * + * This typedef defines the 16-bit type used throughout uIP. + * + * \hideinitializer + */ +typedef uint16_t u16_t; + +/** + * Statistics datatype + * + * This typedef defines the dataype used for keeping statistics in + * uIP. + * + * \hideinitializer + */ +typedef unsigned short uip_stats_t; + +/** + * Maximum number of TCP connections. + * (see uipethernet-conf.h) + * \hideinitializer + * + * #define UIP_CONF_MAX_CONNECTIONS 4 + */ + +/** + * Maximum number of listening TCP ports. + * + * \hideinitializer + */ +#define UIP_CONF_MAX_LISTENPORTS 4 + +/** + * uIP buffer size. + * + * \hideinitializer + */ +#define UIP_CONF_BUFFER_SIZE 98 +//#define UIP_CONF_BUFFER_SIZE 118 + +/** + * The TCP maximum segment size. + * + * This is should not be to set to more than + * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. + */ + +#define UIP_CONF_TCP_MSS 512 + +/** + * The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the uip_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + * + * \hideinitializer + */ +#define UIP_CONF_RECEIVE_WINDOW 512 + +/** + * CPU byte order. + * + * \hideinitializer + */ +#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN + +/** + * Logging on or off + * + * \hideinitializer + */ +#define UIP_CONF_LOGGING 0 + +/** + * UDP support on or off + * (see uipethernet-conf.h) + * \hideinitializer + * + * #define UIP_CONF_UDP 1 + * + * #define UIP_CONF_UDP_CONNS 4 + */ + +/** + * UDP checksums on or off + * + * \hideinitializer + */ +#define UIP_CONF_UDP_CHECKSUMS 1 + +/** + * UDP Broadcast (receive) on or off + * (see uipethernet-conf.h) + * \hideinitializer + * #define UIP_CONF_BROADCAST 1 + */ + + +/** + * uIP statistics on or off + * + * \hideinitializer + */ +#define UIP_CONF_STATISTICS 0 + +// SLIP +//#define UIP_CONF_LLH_LEN 0 + +typedef void* uip_tcp_appstate_t; + +void uipclient_appcall(void); + +#define UIP_APPCALL uipclient_appcall + +typedef void* uip_udp_appstate_t; + +void uipudp_appcall(void); + +#define UIP_UDP_APPCALL uipudp_appcall + +#define CC_REGISTER_ARG register + +#define UIP_ARCH_CHKSUM 1 + +#endif /* __UIP_CONF_H__ */ diff --git a/libraries/UIPEthernet/utility/uip.c b/libraries/UIPEthernet/utility/uip.c new file mode 100644 index 0000000..84ea8c3 --- /dev/null +++ b/libraries/UIPEthernet/utility/uip.c @@ -0,0 +1,1897 @@ +#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/ + +/** + * \defgroup uip The uIP TCP/IP stack + * @{ + * + * uIP is an implementation of the TCP/IP protocol stack intended for + * small 8-bit and 16-bit microcontrollers. + * + * uIP provides the necessary protocols for Internet communication, + * with a very small code footprint and RAM requirements - the uIP + * code size is on the order of a few kilobytes and RAM usage is on + * the order of a few hundred bytes. + */ + +/** + * \file + * The uIP TCP/IP stack code. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $ + * + */ + +/* + * uIP is a small implementation of the IP, UDP and TCP protocols (as + * well as some basic ICMP stuff). The implementation couples the IP, + * UDP, TCP and the application layers very tightly. To keep the size + * of the compiled code down, this code frequently uses the goto + * statement. While it would be possible to break the uip_process() + * function into many smaller functions, this would increase the code + * size because of the overhead of parameter passing and the fact that + * the optimier would not be as efficient. + * + * The principle is that we have a small buffer, called the uip_buf, + * in which the device driver puts an incoming packet. The TCP/IP + * stack parses the headers in the packet, and calls the + * application. If the remote host has sent data to the application, + * this data is present in the uip_buf and the application read the + * data from there. It is up to the application to put this data into + * a byte stream if needed. The application will not be fed with data + * that is out of sequence. + * + * If the application whishes to send data to the peer, it should put + * its data into the uip_buf. The uip_appdata pointer points to the + * first available byte. The TCP/IP stack will calculate the + * checksums, and fill in the necessary header fields and finally send + * the packet back to the peer. +*/ + +#include "uip.h" +#include "uipopt.h" +#include "uip_arch.h" + +#if UIP_CONF_IPV6 +#include "uip-neighbor.h" +#endif /* UIP_CONF_IPV6 */ + +#include + +/*---------------------------------------------------------------------------*/ +/* Variable definitions. */ + + +/* The IP address of this host. If it is defined to be fixed (by + setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set + here. Otherwise, the address */ +#if UIP_FIXEDADDR > 0 +const uip_ipaddr_t uip_hostaddr = + {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), + HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; +const uip_ipaddr_t uip_draddr = + {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), + HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; +const uip_ipaddr_t uip_netmask = + {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), + HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; +#else +uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; +#endif /* UIP_FIXEDADDR */ + +static const uip_ipaddr_t all_ones_addr = +#if UIP_CONF_IPV6 + {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; +#else /* UIP_CONF_IPV6 */ + {0xffff,0xffff}; +#endif /* UIP_CONF_IPV6 */ +static const uip_ipaddr_t all_zeroes_addr = +#if UIP_CONF_IPV6 + {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; +#else /* UIP_CONF_IPV6 */ + {0x0000,0x0000}; +#endif /* UIP_CONF_IPV6 */ + + +#if UIP_FIXEDETHADDR +const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, + UIP_ETHADDR1, + UIP_ETHADDR2, + UIP_ETHADDR3, + UIP_ETHADDR4, + UIP_ETHADDR5}}; +#else +struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; +#endif + +#ifndef UIP_CONF_EXTERNAL_BUFFER +u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains + incoming packets. */ +#endif /* UIP_CONF_EXTERNAL_BUFFER */ + +void *uip_appdata; /* The uip_appdata pointer points to + application data. */ +void *uip_sappdata; /* The uip_appdata pointer points to + the application data which is to + be sent. */ +#if UIP_URGDATA > 0 +void *uip_urgdata; /* The uip_urgdata pointer points to + urgent data (out-of-band data), if + present. */ +u16_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + +u16_t uip_len, uip_slen; + /* The uip_len is either 8 or 16 bits, + depending on the maximum packet + size. */ + +u8_t uip_flags; /* The uip_flags variable is used for + communication between the TCP/IP stack + and the application program. */ +struct uip_conn *uip_conn; /* uip_conn always points to the current + connection. */ + +struct uip_conn uip_conns[UIP_CONNS]; + /* The uip_conns array holds all TCP + connections. */ +u16_t uip_listenports[UIP_LISTENPORTS]; + /* The uip_listenports list all currently + listning ports. */ +#if UIP_UDP +struct uip_udp_conn *uip_udp_conn; +struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +static u16_t ipid; /* Ths ipid variable is an increasing + number that is used for the IP ID + field. */ + +void uip_setipid(u16_t id) { ipid = id; } + +static u8_t iss[4]; /* The iss variable is used for the TCP + initial sequence number. */ + +#if UIP_ACTIVE_OPEN +static u16_t lastport; /* Keeps track of the last port used for + a new connection. */ +#endif /* UIP_ACTIVE_OPEN */ + +/* Temporary variables. */ +u8_t uip_acc32[4]; +static u8_t c, opt; +static u16_t tmp16; + +/* Structures and definitions. */ +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 +#define TCP_CTL 0x3f + +#define TCP_OPT_END 0 /* End of TCP options list */ +#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */ +#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */ + +#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ + +#define ICMP_ECHO_REPLY 0 +#define ICMP_ECHO 8 + +#define ICMP6_ECHO_REPLY 129 +#define ICMP6_ECHO 128 +#define ICMP6_NEIGHBOR_SOLICITATION 135 +#define ICMP6_NEIGHBOR_ADVERTISEMENT 136 + +#define ICMP6_FLAG_S (1 << 6) + +#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1 +#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2 + + +/* Macros. */ +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) +#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) + + +#if UIP_STATISTICS == 1 +struct uip_stats uip_stat; +#define UIP_STAT(s) s +#else +#define UIP_STAT(s) +#endif /* UIP_STATISTICS == 1 */ + +#if UIP_LOGGING == 1 +#include +void uip_log(char *msg); +#define UIP_LOG(m) uip_log(m) +#else +#define UIP_LOG(m) +#endif /* UIP_LOGGING == 1 */ + +#if ! UIP_ARCH_ADD32 +void +uip_add32(u8_t *op32, u16_t op16) +{ + uip_acc32[3] = op32[3] + (op16 & 0xff); + uip_acc32[2] = op32[2] + (op16 >> 8); + uip_acc32[1] = op32[1]; + uip_acc32[0] = op32[0]; + + if(uip_acc32[2] < (op16 >> 8)) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + + + if(uip_acc32[3] < (op16 & 0xff)) { + ++uip_acc32[2]; + if(uip_acc32[2] == 0) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + } +} + +#endif /* UIP_ARCH_ADD32 */ + +#if ! UIP_ARCH_CHKSUM +/*---------------------------------------------------------------------------*/ +static u16_t +chksum(u16_t sum, const u8_t *data, u16_t len) +{ + u16_t t; + const u8_t *dataptr; + const u8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) { /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + dataptr += 2; + } + + if(dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} +/*---------------------------------------------------------------------------*/ +u16_t +uip_chksum(u16_t *data, u16_t len) +{ + return htons(chksum(0, (u8_t *)data, len)); +} +/*---------------------------------------------------------------------------*/ +#ifndef UIP_ARCH_IPCHKSUM +u16_t +uip_ipchksum(void) +{ + u16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum); + return (sum == 0) ? 0xffff : htons(sum); +} +#endif +/*---------------------------------------------------------------------------*/ +static u16_t +upper_layer_chksum(u8_t proto) +{ + u16_t upper_layer_len; + u16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ + sum = upper_layer_len + proto; + /* Sum IP source and destination addresses. */ + sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + /* Sum TCP header and data. */ + sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], + upper_layer_len); + + return (sum == 0) ? 0xffff : htons(sum); +} +/*---------------------------------------------------------------------------*/ +#if UIP_CONF_IPV6 +u16_t +uip_icmp6chksum(void) +{ + return upper_layer_chksum(UIP_PROTO_ICMP6); + +} +#endif /* UIP_CONF_IPV6 */ +/*---------------------------------------------------------------------------*/ +u16_t +uip_tcpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_TCP); +} +/*---------------------------------------------------------------------------*/ +#if UIP_UDP_CHECKSUMS +u16_t +uip_udpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_UDP); +} +#endif /* UIP_UDP_CHECKSUMS */ +#endif /* UIP_ARCH_CHKSUM */ +/*---------------------------------------------------------------------------*/ +void +uip_init(void) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + uip_listenports[c] = 0; + } + for(c = 0; c < UIP_CONNS; ++c) { + uip_conns[c].tcpstateflags = UIP_CLOSED; + } +#if UIP_ACTIVE_OPEN + lastport = 1024; +#endif /* UIP_ACTIVE_OPEN */ + +#if UIP_UDP + for(c = 0; c < UIP_UDP_CONNS; ++c) { + uip_udp_conns[c].lport = 0; + } +#endif /* UIP_UDP */ + + + /* IPv4 initialization. */ +#if UIP_FIXEDADDR == 0 + /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/ +#endif /* UIP_FIXEDADDR */ + +} +/*---------------------------------------------------------------------------*/ +#if UIP_ACTIVE_OPEN +struct uip_conn * +uip_connect(uip_ipaddr_t *ripaddr, u16_t rport) +{ + register struct uip_conn *conn, *cconn; + + /* Find an unused local port. */ + again: + ++lastport; + + if(lastport >= 32000) { + lastport = 4096; + } + + /* Check if this port is already in use, and if so try to find + another one. */ + for(c = 0; c < UIP_CONNS; ++c) { + conn = &uip_conns[c]; + if(conn->tcpstateflags != UIP_CLOSED && + conn->lport == htons(lastport)) { + goto again; + } + } + + conn = 0; + for(c = 0; c < UIP_CONNS; ++c) { + cconn = &uip_conns[c]; + if(cconn->tcpstateflags == UIP_CLOSED) { + conn = cconn; + break; + } + if(cconn->tcpstateflags == UIP_TIME_WAIT) { + if(conn == 0 || + cconn->timer > conn->timer) { + conn = cconn; + } + } + } + + if(conn == 0) { + return 0; + } + + conn->tcpstateflags = UIP_SYN_SENT; + + conn->snd_nxt[0] = iss[0]; + conn->snd_nxt[1] = iss[1]; + conn->snd_nxt[2] = iss[2]; + conn->snd_nxt[3] = iss[3]; + + conn->initialmss = conn->mss = UIP_TCP_MSS; + + conn->len = 1; /* TCP length of the SYN is one. */ + conn->nrtx = 0; + conn->timer = 1; /* Send the SYN next time around. */ + conn->rto = UIP_RTO; + conn->sa = 0; + conn->sv = 16; /* Initial value of the RTT variance. */ + conn->lport = htons(lastport); + conn->rport = rport; + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + + return conn; +} +#endif /* UIP_ACTIVE_OPEN */ +/*---------------------------------------------------------------------------*/ +#if UIP_UDP +struct uip_udp_conn * +uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) +{ + register struct uip_udp_conn *conn; + + /* Find an unused local port. */ + again: + ++lastport; + + if(lastport >= 32000) { + lastport = 4096; + } + + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == htons(lastport)) { + goto again; + } + } + + + conn = 0; + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == 0) { + conn = &uip_udp_conns[c]; + break; + } + } + + if(conn == 0) { + return 0; + } + + conn->lport = HTONS(lastport); + conn->rport = rport; + if(ripaddr == NULL) { + memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t)); + } else { + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + } + conn->ttl = UIP_TTL; + + return conn; +} +#endif /* UIP_UDP */ +/*---------------------------------------------------------------------------*/ +void +uip_unlisten(u16_t port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(uip_listenports[c] == port) { + uip_listenports[c] = 0; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +void +uip_listen(u16_t port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(uip_listenports[c] == 0) { + uip_listenports[c] = port; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +/* XXX: IP fragment reassembly: not well-tested. */ + +#if UIP_REASSEMBLY && !UIP_CONF_IPV6 +#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) +static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; +static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; +static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, + 0x0f, 0x07, 0x03, 0x01}; +static u16_t uip_reasslen; +static u8_t uip_reassflags; +#define UIP_REASS_FLAG_LASTFRAG 0x01 +static u8_t uip_reasstmr; + +#define IP_MF 0x20 + +static u8_t +uip_reass(void) +{ + u16_t offset, len; + u16_t i; + + /* If ip_reasstmr is zero, no packet is present in the buffer, so we + write the IP header of the fragment into the reassembly + buffer. The timer is updated with the maximum age. */ + if(uip_reasstmr == 0) { + memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN); + uip_reasstmr = UIP_REASS_MAXAGE; + uip_reassflags = 0; + /* Clear the bitmap. */ + memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); + } + + /* Check if the incoming fragment matches the one currently present + in the reasembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && + BUF->srcipaddr[1] == FBUF->srcipaddr[1] && + BUF->destipaddr[0] == FBUF->destipaddr[0] && + BUF->destipaddr[1] == FBUF->destipaddr[1] && + BUF->ipid[0] == FBUF->ipid[0] && + BUF->ipid[1] == FBUF->ipid[1]) { + + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; + + /* If the offset or the offset + fragment length overflows the + reassembly buffer, we discard the entire packet. */ + if(offset > UIP_REASS_BUFSIZE || + offset + len > UIP_REASS_BUFSIZE) { + uip_reasstmr = 0; + goto nullreturn; + } + + /* Copy the fragment into the reassembly buffer, at the right + offset. */ + memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], + (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), + len); + + /* Update the bitmap. */ + if(offset / (8 * 8) == (offset + len) / (8 * 8)) { + /* If the two endpoints are in the same byte, we only update + that byte. */ + + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7] & + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } else { + /* If the two endpoints are in different bytes, we update the + bytes in the endpoints and fill the stuff inbetween with + 0xff. */ + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7]; + for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { + uip_reassbitmap[i] = 0xff; + } + uip_reassbitmap[(offset + len) / (8 * 8)] |= + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } + + /* If this fragment has the More Fragments flag set to zero, we + know that this is the last fragment, so we can calculate the + size of the entire packet. We also set the + IP_REASS_FLAG_LASTFRAG flag to indicate that we have received + the final fragment. */ + + if((BUF->ipoffset[0] & IP_MF) == 0) { + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; + uip_reasslen = offset + len; + } + + /* Finally, we check if we have a full packet in the buffer. We do + this by checking if we have the last fragment and if all bits + in the bitmap are set. */ + if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { + /* Check all bytes up to and including all but the last byte in + the bitmap. */ + for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { + if(uip_reassbitmap[i] != 0xff) { + goto nullreturn; + } + } + /* Check the last byte in the bitmap. It should contain just the + right amount of bits. */ + if(uip_reassbitmap[uip_reasslen / (8 * 8)] != + (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { + goto nullreturn; + } + + /* If we have come this far, we have a full packet in the + buffer, so we allocate a pbuf and copy the packet into it. We + also reset the timer. */ + uip_reasstmr = 0; + memcpy(BUF, FBUF, uip_reasslen); + + /* Pretend to be a "normal" (i.e., not fragmented) IP packet + from now on. */ + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + BUF->len[0] = uip_reasslen >> 8; + BUF->len[1] = uip_reasslen & 0xff; + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + + return uip_reasslen; + } + } + + nullreturn: + return 0; +} +#endif /* UIP_REASSEMBLY */ +/*---------------------------------------------------------------------------*/ +static void +uip_add_rcv_nxt(u16_t n) +{ + uip_add32(uip_conn->rcv_nxt, n); + uip_conn->rcv_nxt[0] = uip_acc32[0]; + uip_conn->rcv_nxt[1] = uip_acc32[1]; + uip_conn->rcv_nxt[2] = uip_acc32[2]; + uip_conn->rcv_nxt[3] = uip_acc32[3]; +} +/*---------------------------------------------------------------------------*/ +void +uip_process(u8_t flag) +{ + register struct uip_conn *uip_connr = uip_conn; + +#if UIP_UDP + if(flag == UIP_UDP_SEND_CONN) { + goto udp_send; + } +#endif /* UIP_UDP */ + + uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + + /* Check if we were invoked because of a poll request for a + particular connection. */ + if(flag == UIP_POLL_REQUEST) { + if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && + !uip_outstanding(uip_connr)) { + uip_flags = UIP_POLL; + UIP_APPCALL(); + goto appsend; + } + goto drop; + + /* Check if we were invoked because of the perodic timer fireing. */ + } else if(flag == UIP_TIMER) { +#if UIP_REASSEMBLY + if(uip_reasstmr != 0) { + --uip_reasstmr; + } +#endif /* UIP_REASSEMBLY */ + /* Increase the initial sequence number. */ + if(++iss[3] == 0) { + if(++iss[2] == 0) { + if(++iss[1] == 0) { + ++iss[0]; + } + } + } + + /* Reset the length variables. */ + uip_len = 0; + uip_slen = 0; + + /* Check if the connection is in a state in which we simply wait + for the connection to time out. If so, we increase the + connection's timer and remove the connection if it times + out. */ + if(uip_connr->tcpstateflags == UIP_TIME_WAIT || + uip_connr->tcpstateflags == UIP_FIN_WAIT_2) { + ++(uip_connr->timer); + if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { + uip_connr->tcpstateflags = UIP_CLOSED; + } + } else if(uip_connr->tcpstateflags != UIP_CLOSED) { + /* If the connection has outstanding data, we increase the + connection's timer and see if it has reached the RTO value + in which case we retransmit. */ + if(uip_outstanding(uip_connr)) { + if(uip_connr->timer-- == 0) { + if(uip_connr->nrtx == UIP_MAXRTX || + ((uip_connr->tcpstateflags == UIP_SYN_SENT || + uip_connr->tcpstateflags == UIP_SYN_RCVD) && + uip_connr->nrtx == UIP_MAXSYNRTX)) { + uip_connr->tcpstateflags = UIP_CLOSED; + + /* We call UIP_APPCALL() with uip_flags set to + UIP_TIMEDOUT to inform the application that the + connection has timed out. */ + uip_flags = UIP_TIMEDOUT; + UIP_APPCALL(); + + /* We also send a reset packet to the remote host. */ + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + /* Exponential backoff. */ + uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? + 4: + uip_connr->nrtx); + ++(uip_connr->nrtx); + + /* Ok, so we need to retransmit. We do this differently + depending on which state we are in. In ESTABLISHED, we + call upon the application so that it may prepare the + data for the retransmit. In SYN_RCVD, we resend the + SYNACK that we sent earlier and in LAST_ACK we have to + retransmit our FINACK. */ + UIP_STAT(++uip_stat.tcp.rexmit); + switch(uip_connr->tcpstateflags & UIP_TS_MASK) { + case UIP_SYN_RCVD: + /* In the SYN_RCVD state, we should retransmit our + SYNACK. */ + goto tcp_send_synack; + +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In the SYN_SENT state, we retransmit out SYN. */ + BUF->flags = 0; + goto tcp_send_syn; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application + to do the actual retransmit after which we jump into + the code for sending out the packet (the apprexmit + label). */ + uip_flags = UIP_REXMIT; + UIP_APPCALL(); + goto apprexmit; + + case UIP_FIN_WAIT_1: + case UIP_CLOSING: + case UIP_LAST_ACK: + /* In all these states we should retransmit a FINACK. */ + goto tcp_send_finack; + + } + } + } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { + /* If there was no need for a retransmission, we poll the + application for new data. */ + uip_flags = UIP_POLL; + UIP_APPCALL(); + goto appsend; + } + } + goto drop; + } +#if UIP_UDP + if(flag == UIP_UDP_TIMER) { + if(uip_udp_conn->lport != 0) { + uip_conn = NULL; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_len = uip_slen = 0; + uip_flags = UIP_POLL; + UIP_UDP_APPCALL(); + goto udp_send; + } else { + goto drop; + } + } +#endif + + /* This is where the input processing starts. */ + UIP_STAT(++uip_stat.ip.recv); + + /* Start of IP input header processing code. */ + +#if UIP_CONF_IPV6 + /* Check validity of the IP header. */ + if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ipv6: invalid version."); + goto drop; + } +#else /* UIP_CONF_IPV6 */ + /* Check validity of the IP header. */ + if(BUF->vhl != 0x45) { /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ip: invalid version or header length."); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + + /* Check the size of the packet. If the size reported to us in + uip_len is smaller the size reported in the IP header, we assume + that the packet has been corrupted in transit. If the size of + uip_len is larger than the size reported in the IP packet header, + the packet has been padded and we set uip_len to the correct + value.. */ + + if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) { + uip_len = (BUF->len[0] << 8) + BUF->len[1]; +#if UIP_CONF_IPV6 + uip_len += 40; /* The length reported in the IPv6 header is the + length of the payload that follows the + header. However, uIP uses the uip_len variable + for holding the size of the entire packet, + including the IP header. For IPv4 this is not a + problem as the length field in the IPv4 header + contains the length of the entire packet. But + for IPv6 we need to add the size of the IPv6 + header (40 bytes). */ +#endif /* UIP_CONF_IPV6 */ + } else { + UIP_LOG("ip: packet shorter than reported in IP header."); + goto drop; + } + +#if !UIP_CONF_IPV6 + /* Check the fragment flag. */ + if((BUF->ipoffset[0] & 0x3f) != 0 || + BUF->ipoffset[1] != 0) { +#if UIP_REASSEMBLY + uip_len = uip_reass(); + if(uip_len == 0) { + goto drop; + } +#else /* UIP_REASSEMBLY */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.fragerr); + UIP_LOG("ip: fragment dropped."); + goto drop; +#endif /* UIP_REASSEMBLY */ + } +#endif /* UIP_CONF_IPV6 */ + + if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) { + /* If we are configured to use ping IP address configuration and + hasn't been assigned an IP address yet, we accept all ICMP + packets. */ +#if UIP_PINGADDRCONF && !UIP_CONF_IPV6 + if(BUF->proto == UIP_PROTO_ICMP) { + UIP_LOG("ip: possible ping config packet received."); + goto icmp_input; + } else { + UIP_LOG("ip: packet dropped since no address assigned."); + goto drop; + } +#endif /* UIP_PINGADDRCONF */ + + } else { + /* If IP broadcast support is configured, we check for a broadcast + UDP packet, which may be destined to us. */ +#if UIP_BROADCAST + DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum()); + if(BUF->proto == UIP_PROTO_UDP && + uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) + /*&& + uip_ipchksum() == 0xffff*/) { + goto udp_input; + } +#endif /* UIP_BROADCAST */ + + /* Check if the packet is destined for our IP address. */ +#if !UIP_CONF_IPV6 + if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#else /* UIP_CONF_IPV6 */ + /* For IPv6, packet reception is a little trickier as we need to + make sure that we listen to certain multicast addresses (all + hosts multicast address, and the solicited-node multicast + address) as well. However, we will cheat here and accept all + multicast packets that are sent to the ff02::/16 addresses. */ + if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) && + BUF->destipaddr[0] != HTONS(0xff02)) { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + } + +#if !UIP_CONF_IPV6 + if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header + checksum. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.chkerr); + UIP_LOG("ip: bad checksum."); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + + if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so, + proceed with TCP input + processing. */ + goto tcp_input; + } + +#if UIP_UDP + if(BUF->proto == UIP_PROTO_UDP) { + goto udp_input; + } +#endif /* UIP_UDP */ + +#if !UIP_CONF_IPV6 + /* ICMPv4 processing code follows. */ + if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from + here. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp."); + goto drop; + } + +#if UIP_PINGADDRCONF + icmp_input: +#endif /* UIP_PINGADDRCONF */ + UIP_STAT(++uip_stat.icmp.recv); + + /* ICMP echo (i.e., ping) processing. This is simple, we only change + the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP + checksum before we return the packet. */ + if(ICMPBUF->type != ICMP_ECHO) { + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: not icmp echo."); + goto drop; + } + + /* If we are configured to use ping IP address assignment, we use + the destination IP address of this ping packet and assign it to + ourself. */ +#if UIP_PINGADDRCONF + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { + uip_hostaddr[0] = BUF->destipaddr[0]; + uip_hostaddr[1] = BUF->destipaddr[1]; + } +#endif /* UIP_PINGADDRCONF */ + + ICMPBUF->type = ICMP_ECHO_REPLY; + + if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; + } else { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); + } + + /* Swap IP addresses. */ + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + + /* End of IPv4 input header processing code. */ +#else /* !UIP_CONF_IPV6 */ + + /* This is IPv6 ICMPv6 processing code. */ + DEBUG_PRINTF("icmp6_input: length %d\n", uip_len); + + if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from + here. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp6."); + goto drop; + } + + UIP_STAT(++uip_stat.icmp.recv); + + /* If we get a neighbor solicitation for our address we should send + a neighbor advertisement message back. */ + if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) { + if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) { + + if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) { + /* Save the sender's address in our neighbor list. */ + uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); + } + + /* We should now send a neighbor advertisement back to where the + neighbor solicication came from. */ + ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; + ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ + + ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; + + uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr); + uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr); + ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; + ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ + memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr)); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + goto send; + + } + goto drop; + } else if(ICMPBUF->type == ICMP6_ECHO) { + /* ICMP echo (i.e., ping) processing. This is simple, we only + change the ICMP type from ECHO to ECHO_REPLY and update the + ICMP checksum before we return the packet. */ + + ICMPBUF->type = ICMP6_ECHO_REPLY; + + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + } else { + DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type); + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: unknown ICMP message."); + goto drop; + } + + /* End of IPv6 ICMP processing. */ + +#endif /* !UIP_CONF_IPV6 */ + +#if UIP_UDP + /* UDP input processing. */ + udp_input: + /* UDP processing is really just a hack. We don't do anything to the + UDP/IP headers, but let the UDP application do all the hard + work. If the application sets uip_slen, it has a packet to + send. */ +#if UIP_UDP_CHECKSUMS + uip_len = uip_len - UIP_IPUDPH_LEN; + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) { + UIP_STAT(++uip_stat.udp.drop); + UIP_STAT(++uip_stat.udp.chkerr); + UIP_LOG("udp: bad checksum."); + goto drop; + } +#else /* UIP_UDP_CHECKSUMS */ + uip_len = uip_len - UIP_IPUDPH_LEN; +#endif /* UIP_UDP_CHECKSUMS */ + + /* Demultiplex this UDP packet between the UDP "connections". */ + for(uip_udp_conn = &uip_udp_conns[0]; + uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; + ++uip_udp_conn) { + /* If the local UDP port is non-zero, the connection is considered + to be used. If so, the local port number is checked against the + destination port number in the received packet. If the two port + numbers match, the remote port number is checked if the + connection is bound to a remote port. Finally, if the + connection is bound to a remote IP address, the source IP + address of the packet is checked. */ + if(uip_udp_conn->lport != 0 && + UDPBUF->destport == uip_udp_conn->lport && + (uip_udp_conn->rport == 0 || + UDPBUF->srcport == uip_udp_conn->rport) && + (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) || + uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || + uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) { + goto udp_found; + } + } + UIP_LOG("udp: no matching connection found"); + goto drop; + + udp_found: + uip_conn = NULL; + uip_flags = UIP_NEWDATA; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_slen = 0; + UIP_UDP_APPCALL(); + udp_send: + if(uip_slen == 0) { + goto drop; + } + uip_len = uip_slen + UIP_IPUDPH_LEN; + +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* UIP_CONF_IPV6 */ + + BUF->ttl = uip_udp_conn->ttl; + BUF->proto = UIP_PROTO_UDP; + + UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN); + UDPBUF->udpchksum = 0; + + BUF->srcport = uip_udp_conn->lport; + BUF->destport = uip_udp_conn->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr); + + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; + +#if UIP_UDP_CHECKSUMS + /* Calculate UDP checksum. */ + UDPBUF->udpchksum = ~(uip_udpchksum()); + if(UDPBUF->udpchksum == 0) { + UDPBUF->udpchksum = 0xffff; + } +#endif /* UIP_UDP_CHECKSUMS */ + + goto ip_send_nolen; +#endif /* UIP_UDP */ + + /* TCP input processing. */ + tcp_input: + UIP_STAT(++uip_stat.tcp.recv); + + /* Start of TCP input header processing code. */ + + if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP + checksum. */ + UIP_STAT(++uip_stat.tcp.drop); + UIP_STAT(++uip_stat.tcp.chkerr); + UIP_LOG("tcp: bad checksum."); + goto drop; + } + + + /* Demultiplex this segment. */ + /* First check any active connections. */ + for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; + ++uip_connr) { + if(uip_connr->tcpstateflags != UIP_CLOSED && + BUF->destport == uip_connr->lport && + BUF->srcport == uip_connr->rport && + uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) { + goto found; + } + } + + /* If we didn't find and active connection that expected the packet, + either this packet is an old duplicate, or this is a SYN packet + destined for a connection in LISTEN. If the SYN flag isn't set, + it is an old packet and we send a RST. */ + if((BUF->flags & TCP_CTL) != TCP_SYN) { + goto reset; + } + + tmp16 = BUF->destport; + /* Next, check listening connections. */ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(tmp16 == uip_listenports[c]) + goto found_listen; + } + + /* No matching connection found, so we send a RST packet. */ + UIP_STAT(++uip_stat.tcp.synrst); + reset: + + /* We do not send resets in response to resets. */ + if(BUF->flags & TCP_RST) { + goto drop; + } + + UIP_STAT(++uip_stat.tcp.rst); + + BUF->flags = TCP_RST | TCP_ACK; + uip_len = UIP_IPTCPH_LEN; + BUF->tcpoffset = 5 << 4; + + /* Flip the seqno and ackno fields in the TCP header. */ + c = BUF->seqno[3]; + BUF->seqno[3] = BUF->ackno[3]; + BUF->ackno[3] = c; + + c = BUF->seqno[2]; + BUF->seqno[2] = BUF->ackno[2]; + BUF->ackno[2] = c; + + c = BUF->seqno[1]; + BUF->seqno[1] = BUF->ackno[1]; + BUF->ackno[1] = c; + + c = BUF->seqno[0]; + BUF->seqno[0] = BUF->ackno[0]; + BUF->ackno[0] = c; + + /* We also have to increase the sequence number we are + acknowledging. If the least significant byte overflowed, we need + to propagate the carry to the other bytes as well. */ + if(++BUF->ackno[3] == 0) { + if(++BUF->ackno[2] == 0) { + if(++BUF->ackno[1] == 0) { + ++BUF->ackno[0]; + } + } + } + + /* Swap port numbers. */ + tmp16 = BUF->srcport; + BUF->srcport = BUF->destport; + BUF->destport = tmp16; + + /* Swap IP addresses. */ + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + /* And send out the RST packet! */ + goto tcp_send_noconn; + + /* This label will be jumped to if we matched the incoming packet + with a connection in LISTEN. In that case, we should create a new + connection and send a SYNACK in return. */ + found_listen: + /* First we check if there are any connections avaliable. Unused + connections are kept in the same table as used connections, but + unused ones have the tcpstate set to CLOSED. Also, connections in + TIME_WAIT are kept track of and we'll use the oldest one if no + CLOSED connections are found. Thanks to Eddie C. Dost for a very + nice algorithm for the TIME_WAIT search. */ + uip_connr = 0; + for(c = 0; c < UIP_CONNS; ++c) { + if(uip_conns[c].tcpstateflags == UIP_CLOSED) { + uip_connr = &uip_conns[c]; + break; + } + if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) { + if(uip_connr == 0 || + uip_conns[c].timer > uip_connr->timer) { + uip_connr = &uip_conns[c]; + } + } + } + + if(uip_connr == 0) { + /* All connections are used already, we drop packet and hope that + the remote end will retransmit the packet at a time when we + have more spare connections. */ + UIP_STAT(++uip_stat.tcp.syndrop); + UIP_LOG("tcp: found no unused connections."); + goto drop; + } + uip_conn = uip_connr; + + /* Fill in the necessary fields for the new connection. */ + uip_connr->rto = uip_connr->timer = UIP_RTO; + uip_connr->sa = 0; + uip_connr->sv = 4; + uip_connr->nrtx = 0; + uip_connr->lport = BUF->destport; + uip_connr->rport = BUF->srcport; + uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr); + uip_connr->tcpstateflags = UIP_SYN_RCVD; + + uip_connr->snd_nxt[0] = iss[0]; + uip_connr->snd_nxt[1] = iss[1]; + uip_connr->snd_nxt[2] = iss[2]; + uip_connr->snd_nxt[3] = iss[3]; + uip_connr->len = 1; + + /* rcv_nxt should be the seqno from the incoming packet + 1. */ + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_add_rcv_nxt(1); + + /* Parse the TCP MSS option, if present. */ + if((BUF->tcpoffset & 0xf0) > 0x50) { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; + if(opt == TCP_OPT_END) { + /* End of options. */ + break; + } else if(opt == TCP_OPT_NOOP) { + ++c; + /* NOP option. */ + } else if(opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + /* An MSS option with the right option length. */ + tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = uip_connr->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } else { + /* All other options have a length field, so that we easily + can skip past them. */ + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + + /* Our response will be a SYNACK. */ +#if UIP_ACTIVE_OPEN + tcp_send_synack: + BUF->flags = TCP_ACK; + + tcp_send_syn: + BUF->flags |= TCP_SYN; +#else /* UIP_ACTIVE_OPEN */ + tcp_send_synack: + BUF->flags = TCP_SYN | TCP_ACK; +#endif /* UIP_ACTIVE_OPEN */ + + /* We send out the TCP Maximum Segment Size option with our + SYNACK. */ + BUF->optdata[0] = TCP_OPT_MSS; + BUF->optdata[1] = TCP_OPT_MSS_LEN; + BUF->optdata[2] = (UIP_TCP_MSS) / 256; + BUF->optdata[3] = (UIP_TCP_MSS) & 255; + uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; + BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; + goto tcp_send; + + /* This label will be jumped to if we found an active connection. */ + found: + uip_conn = uip_connr; + uip_flags = 0; + /* We do a very naive form of TCP reset processing; we just accept + any RST and kill our connection. We should in fact check if the + sequence number of this reset is wihtin our advertised window + before we accept the reset. */ + if(BUF->flags & TCP_RST) { + uip_connr->tcpstateflags = UIP_CLOSED; + UIP_LOG("tcp: got reset, aborting connection."); + uip_flags = UIP_ABORT; + UIP_APPCALL(); + goto drop; + } + /* Calculated the length of the data, if the application has sent + any data to us. */ + c = (BUF->tcpoffset >> 4) << 2; + /* uip_len will contain the length of the actual TCP data. This is + calculated by subtracing the length of the TCP header (in + c) and the length of the IP header (20 bytes). */ + uip_len = uip_len - c - UIP_IPH_LEN; + + /* First, check if the sequence number of the incoming packet is + what we're expecting next. If not, we send out an ACK with the + correct numbers in. */ + if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && + ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) { + if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) && + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || + BUF->seqno[1] != uip_connr->rcv_nxt[1] || + BUF->seqno[2] != uip_connr->rcv_nxt[2] || + BUF->seqno[3] != uip_connr->rcv_nxt[3])) { + goto tcp_send_ack; + } + } + + /* Next, check if the incoming segment acknowledges any outstanding + data. If so, we update the sequence number, reset the length of + the outstanding data, calculate RTT estimations, and reset the + retransmission timer. */ + if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { + uip_add32(uip_connr->snd_nxt, uip_connr->len); + + if(BUF->ackno[0] == uip_acc32[0] && + BUF->ackno[1] == uip_acc32[1] && + BUF->ackno[2] == uip_acc32[2] && + BUF->ackno[3] == uip_acc32[3]) { + /* Update sequence number. */ + uip_connr->snd_nxt[0] = uip_acc32[0]; + uip_connr->snd_nxt[1] = uip_acc32[1]; + uip_connr->snd_nxt[2] = uip_acc32[2]; + uip_connr->snd_nxt[3] = uip_acc32[3]; + + + /* Do RTT estimation, unless we have done retransmissions. */ + if(uip_connr->nrtx == 0) { + signed char m; + m = uip_connr->rto - uip_connr->timer; + /* This is taken directly from VJs original code in his paper */ + m = m - (uip_connr->sa >> 3); + uip_connr->sa += m; + if(m < 0) { + m = -m; + } + m = m - (uip_connr->sv >> 2); + uip_connr->sv += m; + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; + + } + /* Set the acknowledged flag. */ + uip_flags = UIP_ACKDATA; + /* Reset the retransmission timer. */ + uip_connr->timer = uip_connr->rto; + + /* Reset length of outstanding data. */ + uip_connr->len = 0; + } + + } + + /* Do different things depending on in what state the connection is. */ + switch(uip_connr->tcpstateflags & UIP_TS_MASK) { + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not + implemented, since we force the application to close when the + peer sends a FIN (hence the application goes directly from + ESTABLISHED to LAST_ACK). */ + case UIP_SYN_RCVD: + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and + we are waiting for an ACK that acknowledges the data we sent + out the last time. Therefore, we want to have the UIP_ACKDATA + flag set. If so, we enter the ESTABLISHED state. */ + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_flags = UIP_CONNECTED; + uip_connr->len = 0; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + uip_slen = 0; + UIP_APPCALL(); + goto appsend; + } + goto drop; +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In SYN_SENT, we wait for a SYNACK that is sent in response to + our SYN. The rcv_nxt is set to sequence number in the SYNACK + plus one, and we send an ACK. We move into the ESTABLISHED + state. */ + if((uip_flags & UIP_ACKDATA) && + (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) { + + /* Parse the TCP MSS option, if present. */ + if((BUF->tcpoffset & 0xf0) > 0x50) { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; + if(opt == TCP_OPT_END) { + /* End of options. */ + break; + } else if(opt == TCP_OPT_NOOP) { + ++c; + /* NOP option. */ + } else if(opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + /* An MSS option with the right option length. */ + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = + uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } else { + /* All other options have a length field, so that we easily + can skip past them. */ + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_add_rcv_nxt(1); + uip_flags = UIP_CONNECTED | UIP_NEWDATA; + uip_connr->len = 0; + uip_len = 0; + uip_slen = 0; + UIP_APPCALL(); + goto appsend; + } + /* Inform the application that the connection failed */ + uip_flags = UIP_ABORT; + UIP_APPCALL(); + /* The connection is closed after we send the RST */ + uip_conn->tcpstateflags = UIP_CLOSED; + goto reset; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application to feed + data into the uip_buf. If the UIP_ACKDATA flag is set, the + application should put new data into the buffer, otherwise we are + retransmitting an old segment, and the application should put that + data into the buffer. + + If the incoming packet is a FIN, we should close the connection on + this side as well, and we send out a FIN and enter the LAST_ACK + state. We require that there is no outstanding data; otherwise the + sequence numbers will be screwed up. */ + + if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + if(uip_outstanding(uip_connr)) { + goto drop; + } + uip_add_rcv_nxt(1 + uip_len); + uip_flags |= UIP_CLOSE; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + } + UIP_APPCALL(); + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_LAST_ACK; + uip_connr->nrtx = 0; + tcp_send_finack: + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* Check the URG flag. If this is set, the segment carries urgent + data that we must pass to the application. */ + if((BUF->flags & TCP_URG) != 0) { +#if UIP_URGDATA > 0 + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; + if(uip_urglen > uip_len) { + /* There is more urgent data in the next segment to come. */ + uip_urglen = uip_len; + } + uip_add_rcv_nxt(uip_urglen); + uip_len -= uip_urglen; + uip_urgdata = uip_appdata; + uip_appdata += uip_urglen; + } else { + uip_urglen = 0; +#else /* UIP_URGDATA > 0 */ + uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]); + uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; +#endif /* UIP_URGDATA > 0 */ + } + + /* If uip_len > 0 we have TCP data in the packet, and we flag this + by setting the UIP_NEWDATA flag and update the sequence number + we acknowledge. If the application has stopped the dataflow + using uip_stop(), we must not accept any data packets from the + remote host. */ + if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + + /* Check if the available buffer space advertised by the other end + is smaller than the initial MSS for this connection. If so, we + set the current MSS to the window size to ensure that the + application does not send more data than the other end can + handle. + + If the remote host advertises a zero window, we set the MSS to + the initial MSS so that the application will send an entire MSS + of data. This data will not be acknowledged by the receiver, + and the application will retransmit it. This is called the + "persistent timer" and uses the retransmission mechanim. + */ + tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1]; + if(tmp16 > uip_connr->initialmss || + tmp16 == 0) { + tmp16 = uip_connr->initialmss; + } + uip_connr->mss = tmp16; + + /* If this packet constitutes an ACK for outstanding data (flagged + by the UIP_ACKDATA flag, we should call the application since it + might want to send more data. If the incoming packet had data + from the peer (as flagged by the UIP_NEWDATA flag), the + application must also be notified. + + When the application is called, the global variable uip_len + contains the length of the incoming data. The application can + access the incoming data through the global pointer + uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN + bytes into the uip_buf array. + + If the application wishes to send any data, this data should be + put into the uip_appdata and the length of the data should be + put into uip_len. If the application don't have any data to + send, uip_len must be set to 0. */ + if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { + uip_slen = 0; + UIP_APPCALL(); + + appsend: + + if(uip_flags & UIP_ABORT) { + uip_slen = 0; + uip_connr->tcpstateflags = UIP_CLOSED; + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + if(uip_flags & UIP_CLOSE) { + uip_slen = 0; + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_FIN_WAIT_1; + uip_connr->nrtx = 0; + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* If uip_slen > 0, the application has data to be sent. */ + if(uip_slen > 0) { + + /* If the connection has acknowledged data, the contents of + the ->len variable should be discarded. */ + if((uip_flags & UIP_ACKDATA) != 0) { + uip_connr->len = 0; + } + + /* If the ->len variable is non-zero the connection has + already data in transit and cannot send anymore right + now. */ + if(uip_connr->len == 0) { + + /* The application cannot send more than what is allowed by + the mss (the minumum of the MSS and the available + window). */ + if(uip_slen > uip_connr->mss) { + uip_slen = uip_connr->mss; + } + + /* Remember how much data we send out now so that we know + when everything has been acknowledged. */ + uip_connr->len = uip_slen; + } else { + + /* If the application already had unacknowledged data, we + make sure that the application does not send (i.e., + retransmit) out more than it previously sent out. */ + uip_slen = uip_connr->len; + } + } + uip_connr->nrtx = 0; + apprexmit: + uip_appdata = uip_sappdata; + + /* If the application has data to be sent, or if the incoming + packet had new data in it, we must send out a packet. */ + if(uip_slen > 0 && uip_connr->len > 0) { + /* Add the length of the IP and TCP headers. */ + uip_len = uip_connr->len + UIP_TCPIP_HLEN; + /* We always set the ACK flag in response packets. */ + BUF->flags = TCP_ACK | TCP_PSH; + /* Send the packet. */ + goto tcp_send_noopts; + } + /* If there is no data to send, just send out a pure ACK if + there is newdata. */ + if(uip_flags & UIP_NEWDATA) { + uip_len = UIP_TCPIP_HLEN; + BUF->flags = TCP_ACK; + goto tcp_send_noopts; + } + } + goto drop; + case UIP_LAST_ACK: + /* We can close this connection if the peer has acknowledged our + FIN. This is indicated by the UIP_ACKDATA flag. */ + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_CLOSED; + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + } + break; + + case UIP_FIN_WAIT_1: + /* The application has closed the connection, but the remote host + hasn't closed its end yet. Thus we do nothing but wait for a + FIN from the other side. */ + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(BUF->flags & TCP_FIN) { + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_connr->len = 0; + } else { + uip_connr->tcpstateflags = UIP_CLOSING; + } + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } else if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_FIN_WAIT_2; + uip_connr->len = 0; + goto drop; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_FIN_WAIT_2: + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(BUF->flags & TCP_FIN) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_TIME_WAIT: + goto tcp_send_ack; + + case UIP_CLOSING: + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + } + } + goto drop; + + + /* We jump here when we are ready to send the packet, and just want + to set the appropriate TCP sequence numbers in the TCP header. */ + tcp_send_ack: + BUF->flags = TCP_ACK; + tcp_send_nodata: + uip_len = UIP_IPTCPH_LEN; + tcp_send_noopts: + BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; + tcp_send: + /* We're done with the input processing. We are now ready to send a + reply. Our job is to fill in all the fields of the TCP and IP + headers before calculating the checksum and finally send the + packet. */ + BUF->ackno[0] = uip_connr->rcv_nxt[0]; + BUF->ackno[1] = uip_connr->rcv_nxt[1]; + BUF->ackno[2] = uip_connr->rcv_nxt[2]; + BUF->ackno[3] = uip_connr->rcv_nxt[3]; + + BUF->seqno[0] = uip_connr->snd_nxt[0]; + BUF->seqno[1] = uip_connr->snd_nxt[1]; + BUF->seqno[2] = uip_connr->snd_nxt[2]; + BUF->seqno[3] = uip_connr->snd_nxt[3]; + + BUF->proto = UIP_PROTO_TCP; + + BUF->srcport = uip_connr->lport; + BUF->destport = uip_connr->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr); + + if(uip_connr->tcpstateflags & UIP_STOPPED) { + /* If the connection has issued uip_stop(), we advertise a zero + window so that the remote host will stop sending data. */ + BUF->wnd[0] = BUF->wnd[1] = 0; + } else { + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); + } + + tcp_send_noconn: + BUF->ttl = UIP_TTL; +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* UIP_CONF_IPV6 */ + + BUF->urgp[0] = BUF->urgp[1] = 0; + + /* Calculate TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + + ip_send_nolen: + +#if UIP_CONF_IPV6 + BUF->vtc = 0x60; + BUF->tcflow = 0x00; + BUF->flow = 0x00; +#else /* UIP_CONF_IPV6 */ + BUF->vhl = 0x45; + BUF->tos = 0; + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + ++ipid; + BUF->ipid[0] = ipid >> 8; + BUF->ipid[1] = ipid & 0xff; + /* Calculate IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum()); +#endif /* UIP_CONF_IPV6 */ + + UIP_STAT(++uip_stat.tcp.sent); + send: + DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len, + (BUF->len[0] << 8) | BUF->len[1]); + + UIP_STAT(++uip_stat.ip.sent); + /* Return and let the caller do the actual transmission. */ + uip_flags = 0; + return; + drop: + uip_len = 0; + uip_flags = 0; + return; +} +/*---------------------------------------------------------------------------*/ +u16_t +htons(u16_t val) +{ + return HTONS(val); +} +/*---------------------------------------------------------------------------*/ +void +uip_send(const void *data, int len) +{ + uip_slen = len; + if(len > 0) { + if(data != uip_sappdata) { + memcpy(uip_sappdata, (data), uip_slen); + } + } +} +/** @} */ diff --git a/libraries/UIPEthernet/utility/uip.h b/libraries/UIPEthernet/utility/uip.h new file mode 100644 index 0000000..4fc0452 --- /dev/null +++ b/libraries/UIPEthernet/utility/uip.h @@ -0,0 +1,1601 @@ + +/** + * \addtogroup uip + * @{ + */ + +/** + * \file + * Header file for the uIP TCP/IP stack. + * \author Adam Dunkels + * + * The uIP TCP/IP stack header file contains definitions for a number + * of C macros that are used by uIP programs as well as internal uIP + * structures, TCP/IP header structures and function declarations. + * + */ + + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip.h,v 1.40 2006/06/08 07:12:07 adam Exp $ + * + */ + +#ifndef __UIP_H__ +#define __UIP_H__ + +#include "uipopt.h" + +/** + * Repressentation of an IP address. + * + */ +typedef u16_t uip_ip4addr_t[2]; +typedef u16_t uip_ip6addr_t[8]; +#if UIP_CONF_IPV6 +typedef uip_ip6addr_t uip_ipaddr_t; +#else /* UIP_CONF_IPV6 */ +typedef uip_ip4addr_t uip_ipaddr_t; +#endif /* UIP_CONF_IPV6 */ + +/*---------------------------------------------------------------------------*/ +/* First, the functions that should be called from the + * system. Initialization, the periodic timer and incoming packets are + * handled by the following three functions. + */ + +/** + * \defgroup uipconffunc uIP configuration functions + * @{ + * + * The uIP configuration functions are used for setting run-time + * parameters in uIP such as IP addresses. + */ + +/** + * Set the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + \code + + uip_ipaddr_t addr; + + uip_ipaddr(&addr, 192,168,1,2); + uip_sethostaddr(&addr); + + \endcode + * \param addr A pointer to an IP address of type uip_ipaddr_t; + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr)) + +/** + * Get the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + \code + uip_ipaddr_t hostaddr; + + uip_gethostaddr(&hostaddr); + \endcode + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the currently configured IP address. + * + * \hideinitializer + */ +#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr) + +/** + * Set the default router's IP address. + * + * \param addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the default router. + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr)) + +/** + * Set the netmask. + * + * \param addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the netmask. + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr)) + + +/** + * Get the default router's IP address. + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address of the default router. + * + * \hideinitializer + */ +#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr) + +/** + * Get the netmask. + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the value of the netmask. + * + * \hideinitializer + */ +#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask) + +/** @} */ + +/** + * \defgroup uipinit uIP initialization functions + * @{ + * + * The uIP initialization functions are used for booting uIP. + */ + +/** + * uIP initialization function. + * + * This function should be called at boot up to initilize the uIP + * TCP/IP stack. + */ +void uip_init(void); + +/** + * uIP initialization function. + * + * This function may be used at boot time to set the initial ip_id. + */ +void uip_setipid(u16_t id); + +/** @} */ + +/** + * \defgroup uipdevfunc uIP device driver functions + * @{ + * + * These functions are used by a network device driver for interacting + * with uIP. + */ + +/** + * Process an incoming packet. + * + * This function should be called when the device driver has received + * a packet from the network. The packet from the device driver must + * be present in the uip_buf buffer, and the length of the packet + * should be placed in the uip_len variable. + * + * When the function returns, there may be an outbound packet placed + * in the uip_buf packet buffer. If so, the uip_len variable is set to + * the length of the packet. If no packet is to be sent out, the + * uip_len variable is set to 0. + * + * The usual way of calling the function is presented by the source + * code below. + \code + uip_len = devicedriver_poll(); + if(uip_len > 0) { + uip_input(); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uIP ARP code before calling + * this function: + \code + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + uip_len = ethernet_devicedrver_poll(); + if(uip_len > 0) { + if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { + uip_arp_ipin(); + uip_input(); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(); + if(uip_len > 0) { + ethernet_devicedriver_send(); + } + } + \endcode + * + * \hideinitializer + */ +#define uip_input() uip_process(UIP_DATA) + +/** + * Periodic processing for a connection identified by its number. + * + * This function does the necessary periodic processing (timers, + * polling) for a uIP TCP conneciton, and should be called when the + * periodic uIP timer goes off. It should be called for every + * connection, regardless of whether they are open of closed. + * + * When the function returns, it may have an outbound packet waiting + * for service in the uIP packet buffer, and if so the uip_len + * variable is set to a value larger than zero. The device driver + * should be called to send out the packet. + * + * The ususal way of calling the function is through a for() loop like + * this: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uip_arp_out() function before + * calling the device driver: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the connection which is to be periodically polled. + * + * \hideinitializer + */ +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ + uip_process(UIP_TIMER); } while (0) + +/** + * + * + */ +#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) + +/** + * Perform periodic processing for a connection identified by a pointer + * to its structure. + * + * Same as uip_periodic() but takes a pointer to the actual uip_conn + * struct instead of an integer as its argument. This function can be + * used to force periodic processing of a specific connection. + * + * \param conn A pointer to the uip_conn struct for the connection to + * be processed. + * + * \hideinitializer + */ +#define uip_periodic_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_TIMER); } while (0) + +/** + * Reuqest that a particular connection should be polled. + * + * Similar to uip_periodic_conn() but does not perform any timer + * processing. The application is polled for new data. + * + * \param conn A pointer to the uip_conn struct for the connection to + * be processed. + * + * \hideinitializer + */ +#define uip_poll_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_POLL_REQUEST); } while (0) + + +#if UIP_UDP +/** + * Periodic processing for a UDP connection identified by its number. + * + * This function is essentially the same as uip_periodic(), but for + * UDP connections. It is called in a similar fashion as the + * uip_periodic() function: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note As for the uip_periodic() function, special care has to be + * taken when using uIP together with ARP and Ethernet: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the UDP connection to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ + uip_process(UIP_UDP_TIMER); } while (0) + +/** + * Periodic processing for a UDP connection identified by a pointer to + * its structure. + * + * Same as uip_udp_periodic() but takes a pointer to the actual + * uip_conn struct instead of an integer as its argument. This + * function can be used to force periodic processing of a specific + * connection. + * + * \param conn A pointer to the uip_udp_conn struct for the connection + * to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ + uip_process(UIP_UDP_TIMER); } while (0) + + +#endif /* UIP_UDP */ + +/** + * The uIP packet buffer. + * + * The uip_buf array is used to hold incoming and outgoing + * packets. The device driver should place incoming data into this + * buffer. When sending data, the device driver should read the link + * level headers and the TCP/IP headers from this buffer. The size of + * the link level headers is configured by the UIP_LLH_LEN define. + * + * \note The application data need not be placed in this buffer, so + * the device driver must read it from the place pointed to by the + * uip_appdata pointer as illustrated by the following example: + \code + void + devicedriver_send(void) + { + hwsend(&uip_buf[0], UIP_LLH_LEN); + if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) { + hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN); + } else { + hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN); + hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN); + } + } + \endcode + */ +extern u8_t uip_buf[UIP_BUFSIZE+2]; + +/** @} */ + +/*---------------------------------------------------------------------------*/ +/* Functions that are used by the uIP application program. Opening and + * closing connections, sending and receiving data, etc. is all + * handled by the functions below. +*/ +/** + * \defgroup uipappfunc uIP application functions + * @{ + * + * Functions used by an application running of top of uIP. + */ + +/** + * Start listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_listen(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. + */ +void uip_listen(u16_t port); + +/** + * Stop listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_unlisten(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. + */ +void uip_unlisten(u16_t port); + +/** + * Connect to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It allocates a new connection identifier, + * sets the connection to the SYN_SENT state and sets the + * retransmission timer to 0. This will cause a TCP SYN segment to be + * sent out the next time this connection is periodically processed, + * which usually is done within 0.5 seconds after the call to + * uip_connect(). + * + * \note This function is avaliable only if support for active open + * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. + * + * \note Since this function requires the port number to be in network + * byte order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_ipaddr_t ipaddr; + + uip_ipaddr(&ipaddr, 192,168,1,2); + uip_connect(&ipaddr, HTONS(80)); + \endcode + * + * \param ripaddr The IP address of the remote hot. + * + * \param port A 16-bit port number in network byte order. + * + * \return A pointer to the uIP connection identifier for the new connection, + * or NULL if no connection could be allocated. + * + */ +struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port); + + + +/** + * \internal + * + * Check if a connection has outstanding (i.e., unacknowledged) data. + * + * \param conn A pointer to the uip_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_outstanding(conn) ((conn)->len) + +/** + * Send data on the current connection. + * + * This function is used to send out a single segment of TCP + * data. Only applications that have been invoked by uIP for event + * processing can send data. + * + * The amount of data that actually is sent out after a call to this + * funcion is determined by the maximum amount of data TCP allows. uIP + * will automatically crop the data so that only the appropriate + * amount of data is sent. The function uip_mss() can be used to query + * uIP for the amount of data that actually will be sent. + * + * \note This function does not guarantee that the sent data will + * arrive at the destination. If the data is lost in the network, the + * application will be invoked with the uip_rexmit() event being + * set. The application will then have to resend the data using this + * function. + * + * \param data A pointer to the data which is to be sent. + * + * \param len The maximum amount of data bytes to be sent. + * + * \hideinitializer + */ +void uip_send(const void *data, int len); + +/** + * The length of any incoming data that is currently avaliable (if avaliable) + * in the uip_appdata buffer. + * + * The test function uip_data() must first be used to check if there + * is any data available at all. + * + * \hideinitializer + */ +/*void uip_datalen(void);*/ +#define uip_datalen() uip_len + +/** + * The length of any out-of-band data (urgent data) that has arrived + * on the connection. + * + * \note The configuration parameter UIP_URGDATA must be set for this + * function to be enabled. + * + * \hideinitializer + */ +#define uip_urgdatalen() uip_urglen + +/** + * Close the current connection. + * + * This function will close the current connection in a nice way. + * + * \hideinitializer + */ +#define uip_close() (uip_flags = UIP_CLOSE) + +/** + * Abort the current connection. + * + * This function will abort (reset) the current connection, and is + * usually used when an error has occured that prevents using the + * uip_close() function. + * + * \hideinitializer + */ +#define uip_abort() (uip_flags = UIP_ABORT) + +/** + * Tell the sending host to stop sending data. + * + * This function will close our receiver's window so that we stop + * receiving data for the current connection. + * + * \hideinitializer + */ +#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) + +/** + * Find out if the current connection has been previously stopped with + * uip_stop(). + * + * \hideinitializer + */ +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) + +/** + * Restart the current connection, if is has previously been stopped + * with uip_stop(). + * + * This function will open the receiver's window again so that we + * start receiving data for the current connection. + * + * \hideinitializer + */ +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ + } while(0) + + +/* uIP tests that can be made to determine in what state the current + connection is, and what the application function should do. */ + +/** + * Is the current connection a UDP connection? + * + * This function checks whether the current connection is a UDP connection. + * + * \hideinitializer + * + */ +#define uip_udpconnection() (uip_conn == NULL) + +/** + * Is new incoming data available? + * + * Will reduce to non-zero if there is new data for the application + * present at the uip_appdata pointer. The size of the data is + * avaliable through the uip_len variable. + * + * \hideinitializer + */ +#define uip_newdata() (uip_flags & UIP_NEWDATA) + +/** + * Has previously sent data been acknowledged? + * + * Will reduce to non-zero if the previously sent data has been + * acknowledged by the remote host. This means that the application + * can send new data. + * + * \hideinitializer + */ +#define uip_acked() (uip_flags & UIP_ACKDATA) + +/** + * Has the connection just been connected? + * + * Reduces to non-zero if the current connection has been connected to + * a remote host. This will happen both if the connection has been + * actively opened (with uip_connect()) or passively opened (with + * uip_listen()). + * + * \hideinitializer + */ +#define uip_connected() (uip_flags & UIP_CONNECTED) + +/** + * Has the connection been closed by the other end? + * + * Is non-zero if the connection has been closed by the remote + * host. The application may then do the necessary clean-ups. + * + * \hideinitializer + */ +#define uip_closed() (uip_flags & UIP_CLOSE) + +/** + * Has the connection been aborted by the other end? + * + * Non-zero if the current connection has been aborted (reset) by the + * remote host. + * + * \hideinitializer + */ +#define uip_aborted() (uip_flags & UIP_ABORT) + +/** + * Has the connection timed out? + * + * Non-zero if the current connection has been aborted due to too many + * retransmissions. + * + * \hideinitializer + */ +#define uip_timedout() (uip_flags & UIP_TIMEDOUT) + +/** + * Do we need to retransmit previously data? + * + * Reduces to non-zero if the previously sent data has been lost in + * the network, and the application should retransmit it. The + * application should send the exact same data as it did the last + * time, using the uip_send() function. + * + * \hideinitializer + */ +#define uip_rexmit() (uip_flags & UIP_REXMIT) + +/** + * Is the connection being polled by uIP? + * + * Is non-zero if the reason the application is invoked is that the + * current connection has been idle for a while and should be + * polled. + * + * The polling event can be used for sending data without having to + * wait for the remote host to send data. + * + * \hideinitializer + */ +#define uip_poll() (uip_flags & UIP_POLL) + +/** + * Get the initial maxium segment size (MSS) of the current + * connection. + * + * \hideinitializer + */ +#define uip_initialmss() (uip_conn->initialmss) + +/** + * Get the current maxium segment size that can be sent on the current + * connection. + * + * The current maxiumum segment size that can be sent on the + * connection is computed from the receiver's window and the MSS of + * the connection (which also is available by calling + * uip_initialmss()). + * + * \hideinitializer + */ +#define uip_mss() (uip_conn->mss) + +/** + * Set up a new UDP connection. + * + * This function sets up a new UDP connection. The function will + * automatically allocate an unused local port for the new + * connection. However, another port can be chosen by using the + * uip_udp_bind() call, after the uip_udp_new() function has been + * called. + * + * Example: + \code + uip_ipaddr_t addr; + struct uip_udp_conn *c; + + uip_ipaddr(&addr, 192,168,2,1); + c = uip_udp_new(&addr, HTONS(12345)); + if(c != NULL) { + uip_udp_bind(c, HTONS(12344)); + } + \endcode + * \param ripaddr The IP address of the remote host. + * + * \param rport The remote port number in network byte order. + * + * \return The uip_udp_conn structure for the new connection or NULL + * if no connection could be allocated. + */ +struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport); + +/** + * Removed a UDP connection. + * + * \param conn A pointer to the uip_udp_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_udp_remove(conn) (conn)->lport = 0 + +/** + * Bind a UDP connection to a local port. + * + * \param conn A pointer to the uip_udp_conn structure for the + * connection. + * + * \param port The local port number, in network byte order. + * + * \hideinitializer + */ +#define uip_udp_bind(conn, port) (conn)->lport = port + +/** + * Send a UDP datagram of length len on the current connection. + * + * This function can only be called in response to a UDP event (poll + * or newdata). The data must be present in the uip_buf buffer, at the + * place pointed to by the uip_appdata pointer. + * + * \param len The length of the data in the uip_buf buffer. + * + * \hideinitializer + */ +#define uip_udp_send(len) uip_send((char *)uip_appdata, len) + +/** @} */ + +/* uIP convenience and converting functions. */ + +/** + * \defgroup uipconvfunc uIP conversion functions + * @{ + * + * These functions can be used for converting between different data + * formats used by uIP. + */ + +/** + * Construct an IP address from four bytes. + * + * This function constructs an IP address of the type that uIP handles + * internally from four bytes. The function is handy for specifying IP + * addresses to use with e.g. the uip_connect() function. + * + * Example: + \code + uip_ipaddr_t ipaddr; + struct uip_conn *c; + + uip_ipaddr(&ipaddr, 192,168,1,2); + c = uip_connect(&ipaddr, HTONS(80)); + \endcode + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address. + * + * \param addr0 The first octet of the IP address. + * \param addr1 The second octet of the IP address. + * \param addr2 The third octet of the IP address. + * \param addr3 The forth octet of the IP address. + * + * \hideinitializer + */ +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ + ((u16_t *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \ + ((u16_t *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \ + } while(0) + +/** + * Construct an IPv6 address from eight 16-bit words. + * + * This function constructs an IPv6 address. + * + * \hideinitializer + */ +#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \ + ((u16_t *)(addr))[0] = HTONS((addr0)); \ + ((u16_t *)(addr))[1] = HTONS((addr1)); \ + ((u16_t *)(addr))[2] = HTONS((addr2)); \ + ((u16_t *)(addr))[3] = HTONS((addr3)); \ + ((u16_t *)(addr))[4] = HTONS((addr4)); \ + ((u16_t *)(addr))[5] = HTONS((addr5)); \ + ((u16_t *)(addr))[6] = HTONS((addr6)); \ + ((u16_t *)(addr))[7] = HTONS((addr7)); \ + } while(0) + +/** + * Copy an IP address to another IP address. + * + * Copies an IP address from one place to another. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr_copy(&ipaddr2, &ipaddr1); + \endcode + * + * \param dest The destination for the copy. + * \param src The source from where to copy. + * + * \hideinitializer + */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_copy(dest, src) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1]; \ + } while(0) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t)) +#endif /* !UIP_CONF_IPV6 */ + +/** + * Compare two IP addresses + * + * Compares two IP addresses. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) { + printf("They are the same"); + } + \endcode + * + * \param addr1 The first IP address. + * \param addr2 The second IP address. + * + * \hideinitializer + */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \ + ((u16_t *)addr1)[1] == ((u16_t *)addr2)[1]) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) +#endif /* !UIP_CONF_IPV6 */ + +/** + * Compare two IP addresses with netmasks + * + * Compares two IP addresses with netmasks. The masks are used to mask + * out the bits that are to be compared. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2, mask; + + uip_ipaddr(&mask, 255,255,255,0); + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr(&ipaddr2, 192,16,1,3); + if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) { + printf("They are the same"); + } + \endcode + * + * \param addr1 The first IP address. + * \param addr2 The second IP address. + * \param mask The netmask. + * + * \hideinitializer + */ +#define uip_ipaddr_maskcmp(addr1, addr2, mask) \ + (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \ + (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \ + ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \ + (((u16_t *)addr2)[1] & ((u16_t *)mask)[1]))) + + +/** + * Mask out the network part of an IP address. + * + * Masks out the network part of an IP address, given the address and + * the netmask. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2, netmask; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr(&netmask, 255,255,255,0); + uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask); + \endcode + * + * In the example above, the variable "ipaddr2" will contain the IP + * address 192.168.1.0. + * + * \param dest Where the result is to be placed. + * \param src The IP address. + * \param mask The netmask. + * + * \hideinitializer + */ +#define uip_ipaddr_mask(dest, src, mask) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \ + } while(0) + +/** + * Pick the first octet of an IP address. + * + * Picks out the first octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr1(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 1. + * + * \hideinitializer + */ +#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8) + +/** + * Pick the second octet of an IP address. + * + * Picks out the second octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr2(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 2. + * + * \hideinitializer + */ +#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff) + +/** + * Pick the third octet of an IP address. + * + * Picks out the third octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr3(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 3. + * + * \hideinitializer + */ +#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8) + +/** + * Pick the fourth octet of an IP address. + * + * Picks out the fourth octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr4(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 4. + * + * \hideinitializer + */ +#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff) + +/** + * Convert 16-bit quantity from host byte order to network byte order. + * + * This macro is primarily used for converting constants from host + * byte order to network byte order. For converting variables to + * network byte order, use the htons() function instead. + * + * \hideinitializer + */ +#ifndef HTONS +# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN +# define HTONS(n) (n) +# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8)) +# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +#else +#error "HTONS already defined!" +#endif /* HTONS */ + +/** + * Convert 16-bit quantity from host byte order to network byte order. + * + * This function is primarily used for converting variables from host + * byte order to network byte order. For converting constants to + * network byte order, use the HTONS() macro instead. + */ +#ifndef htons +u16_t htons(u16_t val); +#endif /* htons */ +#ifndef ntohs +#define ntohs htons +#endif + +/** @} */ + +/** + * Pointer to the application data in the packet buffer. + * + * This pointer points to the application data when the application is + * called. If the application wishes to send data, the application may + * use this space to write the data into before calling uip_send(). + */ +extern void *uip_appdata; + +#if UIP_URGDATA > 0 +/* u8_t *uip_urgdata: + * + * This pointer points to any urgent data that has been received. Only + * present if compiled with support for urgent data (UIP_URGDATA). + */ +extern void *uip_urgdata; +#endif /* UIP_URGDATA > 0 */ + + +/** + * \defgroup uipdrivervars Variables used in uIP device drivers + * @{ + * + * uIP has a few global variables that are used in device drivers for + * uIP. + */ + +/** + * The length of the packet in the uip_buf buffer. + * + * The global variable uip_len holds the length of the packet in the + * uip_buf buffer. + * + * When the network device driver calls the uIP input function, + * uip_len should be set to the length of the packet in the uip_buf + * buffer. + * + * When sending packets, the device driver should use the contents of + * the uip_len variable to determine the length of the outgoing + * packet. + * + */ +extern u16_t uip_len; + +/** @} */ + +#if UIP_URGDATA > 0 +extern u16_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + + +/** + * Representation of a uIP TCP connection. + * + * The uip_conn structure is used for identifying a connection. All + * but one field in the structure are to be considered read-only by an + * application. The only exception is the appstate field whos purpose + * is to let the application store application-specific state (e.g., + * file pointers) for the connection. The type of this field is + * configured in the "uipopt.h" header file. + */ +struct uip_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote host. */ + + u16_t lport; /**< The local TCP port, in network byte order. */ + u16_t rport; /**< The local remote TCP port, in network byte + order. */ + + u8_t rcv_nxt[4]; /**< The sequence number that we expect to + receive next. */ + u8_t snd_nxt[4]; /**< The sequence number that was last sent by + us. */ + u16_t len; /**< Length of the data that was previously sent. */ + u16_t mss; /**< Current maximum segment size for the + connection. */ + u16_t initialmss; /**< Initial maximum segment size for the + connection. */ + u8_t sa; /**< Retransmission time-out calculation state + variable. */ + u8_t sv; /**< Retransmission time-out calculation state + variable. */ + u8_t rto; /**< Retransmission time-out. */ + u8_t tcpstateflags; /**< TCP state and flags. */ + u8_t timer; /**< The retransmission timer. */ + u8_t nrtx; /**< The number of retransmissions for the last + segment sent. */ + + /** The application state. */ + uip_tcp_appstate_t appstate; +}; + + +/** + * Pointer to the current TCP connection. + * + * The uip_conn pointer can be used to access the current TCP + * connection. + */ +extern struct uip_conn *uip_conn; +/* The array containing all uIP connections. */ +extern struct uip_conn uip_conns[UIP_CONNS]; +/** + * \addtogroup uiparch + * @{ + */ + +/** + * 4-byte array used for the 32-bit sequence number calculations. + */ +extern u8_t uip_acc32[4]; + +/** @} */ + + +#if UIP_UDP +/** + * Representation of a uIP UDP connection. + */ +struct uip_udp_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */ + u16_t lport; /**< The local port number in network byte order. */ + u16_t rport; /**< The remote port number in network byte order. */ + u8_t ttl; /**< Default time-to-live. */ + + /** The application state. */ + uip_udp_appstate_t appstate; +}; + +/** + * The current UDP connection. + */ +extern struct uip_udp_conn *uip_udp_conn; +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +/** + * The structure holding the TCP/IP statistics that are gathered if + * UIP_STATISTICS is set to 1. + * + */ +struct uip_stats { + struct { + uip_stats_t drop; /**< Number of dropped packets at the IP + layer. */ + uip_stats_t recv; /**< Number of received packets at the IP + layer. */ + uip_stats_t sent; /**< Number of sent packets at the IP + layer. */ + uip_stats_t vhlerr; /**< Number of packets dropped due to wrong + IP version or header length. */ + uip_stats_t hblenerr; /**< Number of packets dropped due to wrong + IP length, high byte. */ + uip_stats_t lblenerr; /**< Number of packets dropped due to wrong + IP length, low byte. */ + uip_stats_t fragerr; /**< Number of packets dropped since they + were IP fragments. */ + uip_stats_t chkerr; /**< Number of packets dropped due to IP + checksum errors. */ + uip_stats_t protoerr; /**< Number of packets dropped since they + were neither ICMP, UDP nor TCP. */ + } ip; /**< IP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped ICMP packets. */ + uip_stats_t recv; /**< Number of received ICMP packets. */ + uip_stats_t sent; /**< Number of sent ICMP packets. */ + uip_stats_t typeerr; /**< Number of ICMP packets with a wrong + type. */ + } icmp; /**< ICMP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped TCP segments. */ + uip_stats_t recv; /**< Number of recived TCP segments. */ + uip_stats_t sent; /**< Number of sent TCP segments. */ + uip_stats_t chkerr; /**< Number of TCP segments with a bad + checksum. */ + uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK + number. */ + uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ + uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ + uip_stats_t syndrop; /**< Number of dropped SYNs due to too few + connections was avaliable. */ + uip_stats_t synrst; /**< Number of SYNs for closed ports, + triggering a RST. */ + } tcp; /**< TCP statistics. */ +#if UIP_UDP + struct { + uip_stats_t drop; /**< Number of dropped UDP segments. */ + uip_stats_t recv; /**< Number of recived UDP segments. */ + uip_stats_t sent; /**< Number of sent UDP segments. */ + uip_stats_t chkerr; /**< Number of UDP segments with a bad + checksum. */ + } udp; /**< UDP statistics. */ +#endif /* UIP_UDP */ +}; + +/** + * The uIP TCP/IP statistics. + * + * This is the variable in which the uIP TCP/IP statistics are gathered. + */ +extern struct uip_stats uip_stat; + + +/*---------------------------------------------------------------------------*/ +/* All the stuff below this point is internal to uIP and should not be + * used directly by an application or by a device driver. + */ +/*---------------------------------------------------------------------------*/ +/* u8_t uip_flags: + * + * When the application is called, uip_flags will contain the flags + * that are defined in this file. Please read below for more + * infomation. + */ +extern u8_t uip_flags; + +/* The following flags may be set in the global variable uip_flags + before calling the application callback. The UIP_ACKDATA, + UIP_NEWDATA, and UIP_CLOSE flags may both be set at the same time, + whereas the others are mutualy exclusive. Note that these flags + should *NOT* be accessed directly, but only through the uIP + functions/macros. */ + +#define UIP_ACKDATA 1 /* Signifies that the outstanding data was + acked and the application should send + out new data instead of retransmitting + the last data. */ +#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent + us new data. */ +#define UIP_REXMIT 4 /* Tells the application to retransmit the + data that was last sent. */ +#define UIP_POLL 8 /* Used for polling the application, to + check if the application has data that + it wants to send. */ +#define UIP_CLOSE 16 /* The remote host has closed the + connection, thus the connection has + gone away. Or the application signals + that it wants to close the + connection. */ +#define UIP_ABORT 32 /* The remote host has aborted the + connection, thus the connection has + gone away. Or the application signals + that it wants to abort the + connection. */ +#define UIP_CONNECTED 64 /* We have got a connection from a remote + host and have set up a new connection + for it, or an active connection has + been successfully established. */ + +#define UIP_TIMEDOUT 128 /* The connection has been aborted due to + too many retransmissions. */ + +/* uip_process(flag): + * + * The actual uIP function which does all the work. + */ +void uip_process(u8_t flag); + +/* The following flags are passed as an argument to the uip_process() + function. They are used to distinguish between the two cases where + uip_process() is called. It can be called either because we have + incoming data that should be processed, or because the periodic + timer has fired. These values are never used directly, but only in + the macrose defined in this file. */ + +#define UIP_DATA 1 /* Tells uIP that there is incoming + data in the uip_buf buffer. The + length of the data is stored in the + global variable uip_len. */ +#define UIP_TIMER 2 /* Tells uIP that the periodic timer + has fired. */ +#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should + be polled. */ +#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram + should be constructed in the + uip_buf buffer. */ +#if UIP_UDP +#define UIP_UDP_TIMER 5 +#endif /* UIP_UDP */ + +/* The TCP states used in the uip_conn->tcpstateflags. */ +#define UIP_CLOSED 0 +#define UIP_SYN_RCVD 1 +#define UIP_SYN_SENT 2 +#define UIP_ESTABLISHED 3 +#define UIP_FIN_WAIT_1 4 +#define UIP_FIN_WAIT_2 5 +#define UIP_CLOSING 6 +#define UIP_TIME_WAIT 7 +#define UIP_LAST_ACK 8 +#define UIP_TS_MASK 15 + +#define UIP_STOPPED 16 + +/* The TCP and IP headers. */ +struct uip_tcpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcflow; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* TCP header. */ + u16_t srcport, + destport; + u8_t seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + u16_t tcpchksum; + u8_t urgp[2]; + u8_t optdata[4]; +}; + +/* The ICMP and IP headers. */ +struct uip_icmpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* ICMP (echo) header. */ + u8_t type, icode; + u16_t icmpchksum; +#if !UIP_CONF_IPV6 + u16_t id, seqno; +#else /* !UIP_CONF_IPV6 */ + u8_t flags, reserved1, reserved2, reserved3; + u8_t icmp6data[16]; + u8_t options[1]; +#endif /* !UIP_CONF_IPV6 */ +}; + + +/* The UDP and IP headers. */ +struct uip_udpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* UDP header. */ + u16_t srcport, + destport; + u16_t udplen; + u16_t udpchksum; +}; + + + +/** + * The buffer size available for user data in the \ref uip_buf buffer. + * + * This macro holds the available size for user data in the \ref + * uip_buf buffer. The macro is intended to be used for checking + * bounds of available user data. + * + * Example: + \code + snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i); + \endcode + * + * \hideinitializer + */ +#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + + +#define UIP_PROTO_ICMP 1 +#define UIP_PROTO_TCP 6 +#define UIP_PROTO_UDP 17 +#define UIP_PROTO_ICMP6 58 + +/* Header sizes. */ +#if UIP_CONF_IPV6 +#define UIP_IPH_LEN 40 +#else /* UIP_CONF_IPV6 */ +#define UIP_IPH_LEN 20 /* Size of IP header */ +#endif /* UIP_CONF_IPV6 */ +#define UIP_UDPH_LEN 8 /* Size of UDP header */ +#define UIP_TCPH_LEN 20 /* Size of TCP header */ +#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + + UDP + header */ +#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + + TCP + header */ +#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN + + +#if UIP_FIXEDADDR +extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#else /* UIP_FIXEDADDR */ +extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#endif /* UIP_FIXEDADDR */ + + + +/** + * Representation of a 48-bit Ethernet address. + */ +struct uip_eth_addr { + u8_t addr[6]; +}; + +/** + * Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * \param buf A pointer to the buffer over which the checksum is to be + * computed. + * + * \param len The length of the buffer over which the checksum is to + * be computed. + * + * \return The Internet checksum of the buffer. + */ +u16_t uip_chksum(u16_t *buf, u16_t len); + +/** + * Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * \return The IP header checksum of the IP header in the uip_buf + * buffer. + */ +u16_t uip_ipchksum(void); + +/** + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * \return The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_tcpchksum(void); + +/** + * Calculate the UDP checksum of the packet in uip_buf and uip_appdata. + * + * The UDP checksum is the Internet checksum of data contents of the + * UDP segment, and a pseudo-header as defined in RFC768. + * + * \return The UDP checksum of the UDP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_udpchksum(void); + + +#endif /* __UIP_H__ */ + + +/** @} */ diff --git a/libraries/UIPEthernet/utility/uip_arch.h b/libraries/UIPEthernet/utility/uip_arch.h new file mode 100644 index 0000000..71fd84b --- /dev/null +++ b/libraries/UIPEthernet/utility/uip_arch.h @@ -0,0 +1,138 @@ +/** + * \addtogroup uip + * {@ + */ + +/** + * \defgroup uiparch Architecture specific uIP functions + * @{ + * + * The functions in the architecture specific module implement the IP + * check sum and 32-bit additions. + * + * The IP checksum calculation is the most computationally expensive + * operation in the TCP/IP stack and it therefore pays off to + * implement this in efficient assembler. The purpose of the uip-arch + * module is to let the checksum functions to be implemented in + * architecture specific assembler. + * + */ + +/** + * \file + * Declarations of architecture specific functions. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2001, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $ + * + */ + +#ifndef __UIP_ARCH_H__ +#define __UIP_ARCH_H__ + +#include "uip.h" + +/** + * Carry out a 32-bit addition. + * + * Because not all architectures for which uIP is intended has native + * 32-bit arithmetic, uIP uses an external C function for doing the + * required 32-bit additions in the TCP protocol processing. This + * function should add the two arguments and place the result in the + * global variable uip_acc32. + * + * \note The 32-bit integer pointed to by the op32 parameter and the + * result in the uip_acc32 variable are in network byte order (big + * endian). + * + * \param op32 A pointer to a 4-byte array representing a 32-bit + * integer in network byte order (big endian). + * + * \param op16 A 16-bit integer in host byte order. + */ +void uip_add32(u8_t *op32, u16_t op16); + +/** + * Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * \note This function is not called in the current version of uIP, + * but future versions might make use of it. + * + * \param buf A pointer to the buffer over which the checksum is to be + * computed. + * + * \param len The length of the buffer over which the checksum is to + * be computed. + * + * \return The Internet checksum of the buffer. + */ +u16_t uip_chksum(u16_t *buf, u16_t len); + +/** + * Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * \return The IP header checksum of the IP header in the uip_buf + * buffer. + */ +u16_t uip_ipchksum(void); + +/** + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * \note The uip_appdata pointer that points to the packet data may + * point anywhere in memory, so it is not possible to simply calculate + * the Internet checksum of the contents of the uip_buf buffer. + * + * \return The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_tcpchksum(void); + +u16_t uip_udpchksum(void); + +/** @} */ +/** @} */ + +#endif /* __UIP_ARCH_H__ */ diff --git a/libraries/UIPEthernet/utility/uip_arp.c b/libraries/UIPEthernet/utility/uip_arp.c new file mode 100644 index 0000000..44ca7c4 --- /dev/null +++ b/libraries/UIPEthernet/utility/uip_arp.c @@ -0,0 +1,423 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uiparp uIP Address Resolution Protocol + * @{ + * + * The Address Resolution Protocol ARP is used for mapping between IP + * addresses and link level addresses such as the Ethernet MAC + * addresses. ARP uses broadcast queries to ask for the link level + * address of a known IP address and the host which is configured with + * the IP address for which the query was meant, will respond with its + * link level address. + * + * \note This ARP implementation only supports Ethernet. + */ + +/** + * \file + * Implementation of the ARP Address Resolution Protocol. + * \author Adam Dunkels + * + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $ + * + */ + + +#include "uip_arp.h" + +#include + +struct arp_hdr { + struct uip_eth_hdr ethhdr; + u16_t hwtype; + u16_t protocol; + u8_t hwlen; + u8_t protolen; + u16_t opcode; + struct uip_eth_addr shwaddr; + u16_t sipaddr[2]; + struct uip_eth_addr dhwaddr; + u16_t dipaddr[2]; +}; + +struct ethip_hdr { + struct uip_eth_hdr ethhdr; + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +}; + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#define ARP_HWTYPE_ETH 1 + +struct arp_entry { + u16_t ipaddr[2]; + struct uip_eth_addr ethaddr; + u8_t time; +}; + +static const struct uip_eth_addr broadcast_ethaddr = + {{0xff,0xff,0xff,0xff,0xff,0xff}}; +static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff}; + +static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; +static u16_t ipaddr[2]; +static u8_t i, c; + +static u8_t arptime; +static u8_t tmpage; + +#define BUF ((struct arp_hdr *)&uip_buf[0]) +#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) +/*-----------------------------------------------------------------------------------*/ +/** + * Initialize the ARP module. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_init(void) +{ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + memset(arp_table[i].ipaddr, 0, 4); + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Periodic ARP processing function. + * + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_timer(void) +{ + struct arp_entry *tabptr; + + ++arptime; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && + arptime - tabptr->time >= UIP_ARP_MAXAGE) { + memset(tabptr->ipaddr, 0, 4); + } + } + +} +/*-----------------------------------------------------------------------------------*/ +static void +uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) +{ + register struct arp_entry *tabptr; + /* Walk through the ARP mapping table and try to find an entry to + update. If none is found, the IP -> MAC address mapping is + inserted in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + + tabptr = &arp_table[i]; + /* Only check those entries that are actually in use. */ + if(tabptr->ipaddr[0] != 0 && + tabptr->ipaddr[1] != 0) { + + /* Check if the source IP address of the incoming packet matches + the IP address in this ARP table entry. */ + if(ipaddr[0] == tabptr->ipaddr[0] && + ipaddr[1] == tabptr->ipaddr[1]) { + + /* An old entry found, update this and return. */ + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; + + return; + } + } + } + + /* If we get here, no existing ARP table entry was found, so we + create one. */ + + /* First, we try to find an unused entry in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(tabptr->ipaddr[0] == 0 && + tabptr->ipaddr[1] == 0) { + break; + } + } + + /* If no unused entry is found, we try to find the oldest entry and + throw it away. */ + if(i == UIP_ARPTAB_SIZE) { + tmpage = 0; + c = 0; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(arptime - tabptr->time > tmpage) { + tmpage = arptime - tabptr->time; + c = i; + } + } + i = c; + tabptr = &arp_table[i]; + } + + /* Now, i is the ARP table entry which we will fill with the new + information. */ + memcpy(tabptr->ipaddr, ipaddr, 4); + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; +} +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming IP packets + * + * This function should be called by the device driver when an IP + * packet has been received. The function will check if the address is + * in the ARP cache, and if so the ARP cache entry will be + * refreshed. If no ARP cache entry was found, a new one is created. + * + * This function expects an IP packet with a prepended Ethernet header + * in the uip_buf[] buffer, and the length of the packet in the global + * variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +//#if 0 +void +uip_arp_ipin(void) +{ + uip_len -= sizeof(struct uip_eth_hdr); + + /* Only insert/update an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + if((IPBUF->srcipaddr[0] & uip_netmask[0]) != + (uip_hostaddr[0] & uip_netmask[0])) { + return; + } + if((IPBUF->srcipaddr[1] & uip_netmask[1]) != + (uip_hostaddr[1] & uip_netmask[1])) { + return; + } + uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); + + return; +} +//#endif /* 0 */ +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming ARP packets. + * + * This function should be called by the device driver when an ARP + * packet has been received. The function will act differently + * depending on the ARP packet type: if it is a reply for a request + * that we previously sent out, the ARP cache will be filled in with + * the values from the ARP reply. If the incoming ARP packet is an ARP + * request for our IP address, an ARP reply packet is created and put + * into the uip_buf[] buffer. + * + * When the function returns, the value of the global variable uip_len + * indicates whether the device driver should send out a packet or + * not. If uip_len is zero, no packet should be sent. If uip_len is + * non-zero, it contains the length of the outbound packet that is + * present in the uip_buf[] buffer. + * + * This function expects an ARP packet with a prepended Ethernet + * header in the uip_buf[] buffer, and the length of the packet in the + * global variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_arpin(void) +{ + + if(uip_len < sizeof(struct arp_hdr)) { + uip_len = 0; + return; + } + uip_len = 0; + + switch(BUF->opcode) { + case HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + reply. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + /* First, we register the one who made the request in our ARP + table, since it is likely that we will do more communication + with this host in the future. */ + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + + /* The reply opcode is 2. */ + BUF->opcode = HTONS(2); + + memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); + + BUF->dipaddr[0] = BUF->sipaddr[0]; + BUF->dipaddr[1] = BUF->sipaddr[1]; + BUF->sipaddr[0] = uip_hostaddr[0]; + BUF->sipaddr[1] = uip_hostaddr[1]; + + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + uip_len = sizeof(struct arp_hdr); + } + break; + case HTONS(ARP_REPLY): + /* ARP reply. We insert or update the ARP table if it was meant + for us. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + } + break; + } + + return; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Prepend Ethernet header to an outbound IP packet and see if we need + * to send out an ARP request. + * + * This function should be called before sending out an IP packet. The + * function checks the destination IP address of the IP packet to see + * what Ethernet MAC address that should be used as a destination MAC + * address on the Ethernet. + * + * If the destination IP address is in the local network (determined + * by logical ANDing of netmask and our IP address), the function + * checks the ARP cache to see if an entry for the destination IP + * address is found. If so, an Ethernet header is prepended and the + * function returns. If no ARP cache entry is found for the + * destination IP address, the packet in the uip_buf[] is replaced by + * an ARP request packet for the IP address. The IP packet is dropped + * and it is assumed that they higher level protocols (e.g., TCP) + * eventually will retransmit the dropped packet. + * + * If the destination IP address is not on the local network, the IP + * address of the default router is used instead. + * + * When the function returns, a packet is present in the uip_buf[] + * buffer, and the length of the packet is in the global variable + * uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_out(void) +{ + struct arp_entry *tabptr; + + /* Find the destination IP address in the ARP table and construct + the Ethernet header. If the destination IP addres isn't on the + local network, we use the default router's IP address instead. + + If not ARP table entry is found, we overwrite the original IP + packet with an ARP request for the IP address. */ + + /* First check if destination is a local broadcast. */ + if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { + memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); + } else { + /* Check if the destination address is on the local network. */ + if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { + /* Destination address was not on the local network, so we need to + use the default router's IP address instead of the destination + address when determining the MAC address. */ + uip_ipaddr_copy(ipaddr, uip_draddr); + } else { + /* Else, we use the destination IP address. */ + uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); + } + + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { + break; + } + } + + if(i == UIP_ARPTAB_SIZE) { + /* The destination address was not in our ARP table, so we + overwrite the IP packet with an ARP request. */ + + memset(BUF->ethhdr.dest.addr, 0xff, 6); + memset(BUF->dhwaddr.addr, 0x00, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + + uip_ipaddr_copy(BUF->dipaddr, ipaddr); + uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); + BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ + BUF->hwtype = HTONS(ARP_HWTYPE_ETH); + BUF->protocol = HTONS(UIP_ETHTYPE_IP); + BUF->hwlen = 6; + BUF->protolen = 4; + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + + uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; + + uip_len = sizeof(struct arp_hdr); + return; + } + + /* Build an ethernet header. */ + memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); + } + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + + IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); + + uip_len += sizeof(struct uip_eth_hdr); +} +/*-----------------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ diff --git a/libraries/UIPEthernet/utility/uip_arp.h b/libraries/UIPEthernet/utility/uip_arp.h new file mode 100644 index 0000000..ef93054 --- /dev/null +++ b/libraries/UIPEthernet/utility/uip_arp.h @@ -0,0 +1,144 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \addtogroup uiparp + * @{ + */ + +/** + * \file + * Macros and definitions for the ARP module. + * \author Adam Dunkels + */ + + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $ + * + */ + +#ifndef __UIP_ARP_H__ +#define __UIP_ARP_H__ + +#include "uip.h" + + +extern struct uip_eth_addr uip_ethaddr; + +/** + * The Ethernet header. + */ +struct uip_eth_hdr { + struct uip_eth_addr dest; + struct uip_eth_addr src; + u16_t type; +}; + +#define UIP_ETHTYPE_ARP 0x0806 +#define UIP_ETHTYPE_IP 0x0800 +#define UIP_ETHTYPE_IP6 0x86dd + + +/* The uip_arp_init() function must be called before any of the other + ARP functions. */ +void uip_arp_init(void); + +/* The uip_arp_ipin() function should be called whenever an IP packet + arrives from the Ethernet. This function refreshes the ARP table or + inserts a new mapping if none exists. The function assumes that an + IP packet with an Ethernet header is present in the uip_buf buffer + and that the length of the packet is in the uip_len variable. */ +void uip_arp_ipin(void); +//#define uip_arp_ipin() + +/* The uip_arp_arpin() should be called when an ARP packet is received + by the Ethernet driver. This function also assumes that the + Ethernet frame is present in the uip_buf buffer. When the + uip_arp_arpin() function returns, the contents of the uip_buf + buffer should be sent out on the Ethernet if the uip_len variable + is > 0. */ +void uip_arp_arpin(void); + +/* The uip_arp_out() function should be called when an IP packet + should be sent out on the Ethernet. This function creates an + Ethernet header before the IP header in the uip_buf buffer. The + Ethernet header will have the correct Ethernet MAC destination + address filled in if an ARP table entry for the destination IP + address (or the IP address of the default router) is present. If no + such table entry is found, the IP packet is overwritten with an ARP + request and we rely on TCP to retransmit the packet that was + overwritten. In any case, the uip_len variable holds the length of + the Ethernet frame that should be transmitted. */ +void uip_arp_out(void); + +/* The uip_arp_timer() function should be called every ten seconds. It + is responsible for flushing old entries in the ARP table. */ +void uip_arp_timer(void); + +/** @} */ + +/** + * \addtogroup uipconffunc + * @{ + */ + + +/** + * Specifiy the Ethernet MAC address. + * + * The ARP code needs to know the MAC address of the Ethernet card in + * order to be able to respond to ARP queries and to generate working + * Ethernet headers. + * + * \note This macro only specifies the Ethernet MAC address to the ARP + * code. It cannot be used to change the MAC address of the Ethernet + * card. + * + * \param eaddr A pointer to a struct uip_eth_addr containing the + * Ethernet MAC address of the Ethernet card. + * + * \hideinitializer + */ +#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ + uip_ethaddr.addr[1] = eaddr.addr[1];\ + uip_ethaddr.addr[2] = eaddr.addr[2];\ + uip_ethaddr.addr[3] = eaddr.addr[3];\ + uip_ethaddr.addr[4] = eaddr.addr[4];\ + uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) + +/** @} */ +/** @} */ + +#endif /* __UIP_ARP_H__ */ diff --git a/libraries/UIPEthernet/utility/uip_clock.h b/libraries/UIPEthernet/utility/uip_clock.h new file mode 100644 index 0000000..6dd72be --- /dev/null +++ b/libraries/UIPEthernet/utility/uip_clock.h @@ -0,0 +1,88 @@ +/** + * \defgroup clock Clock interface + * + * The clock interface is the interface between the \ref timer "timer library" + * and the platform specific clock functionality. The clock + * interface must be implemented for each platform that uses the \ref + * timer "timer library". + * + * The clock interface does only one this: it measures time. The clock + * interface provides a macro, CLOCK_SECOND, which corresponds to one + * second of system time. + * + * \sa \ref timer "Timer library" + * + * @{ + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $ + */ +#ifndef __UIP_CLOCK_H__ +#define __UIP_CLOCK_H__ + +#include "clock-arch.h" + +/** + * Initialize the clock library. + * + * This function initializes the clock library and should be called + * from the main() function of the system. + * + */ +void uip_clock_init(void); + +/** + * Get the current clock time. + * + * This function returns the current system clock time. + * + * \return The current clock time, measured in system ticks. + */ +clock_time_t clock_time(void); + +/** + * A second, measured in system clock time. + * + * \hideinitializer + */ +#ifdef CLOCK_CONF_SECOND +#define CLOCK_SECOND CLOCK_CONF_SECOND +#else +#define CLOCK_SECOND (clock_time_t)32 +#endif + +#endif /* __CLOCK_H__ */ + +/** @} */ diff --git a/libraries/UIPEthernet/utility/uip_debug.cpp b/libraries/UIPEthernet/utility/uip_debug.cpp new file mode 100644 index 0000000..444bd0e --- /dev/null +++ b/libraries/UIPEthernet/utility/uip_debug.cpp @@ -0,0 +1,170 @@ +#include +#include +#include +#include +extern "C" { + #import "utility/uip.h" +} + +struct uip_conn con[UIP_CONNS]; + +void +UIPDebug::uip_debug_printconns() +{ + for(uint8_t i=0;iripaddr,rhs->ripaddr)) + { + Serial.print(" ripaddr: "); + uip_debug_printbytes((const uint8_t *)lhs->ripaddr,4); + Serial.print(" -> "); + uip_debug_printbytes((const uint8_t *)rhs->ripaddr,4); + Serial.println(); + uip_ipaddr_copy(lhs->ripaddr,rhs->ripaddr); + changed = true; + } + if (lhs->lport != rhs->lport) + { + Serial.print(" lport: "); + Serial.print(htons(lhs->lport)); + Serial.print(" -> "); + Serial.println(htons(rhs->lport)); + lhs->lport = rhs->lport; + changed = true; + } + if (lhs->rport != rhs->rport) + { + Serial.print(" rport: "); + Serial.print(htons(lhs->rport)); + Serial.print(" -> "); + Serial.println(htons(rhs->rport)); + lhs->rport = rhs->rport; + changed = true; + } + if ((uint32_t)lhs->rcv_nxt[0] != (uint32_t)rhs->rcv_nxt[0]) + { + Serial.print(" rcv_nxt: "); + uip_debug_printbytes(lhs->rcv_nxt,4); + Serial.print(" -> "); + uip_debug_printbytes(rhs->rcv_nxt,4); + *((uint32_t *)&lhs->rcv_nxt[0]) = (uint32_t)rhs->rcv_nxt[0]; + Serial.println(); + changed = true; + } + if ((uint32_t)lhs->snd_nxt[0] != (uint32_t)rhs->snd_nxt[0]) + { + Serial.print(" snd_nxt: "); + uip_debug_printbytes(lhs->snd_nxt,4); + Serial.print(" -> "); + uip_debug_printbytes(rhs->snd_nxt,4); + *((uint32_t *)&lhs->snd_nxt[0]) = (uint32_t)rhs->snd_nxt[0]; + Serial.println(); + changed = true; + } + if (lhs->len != rhs->len) + { + Serial.print(" len: "); + Serial.print(lhs->len); + Serial.print(" -> "); + Serial.println(rhs->len); + lhs->len = rhs->len; + changed = true; + } + if (lhs->mss != rhs->mss) + { + Serial.print(" mss: "); + Serial.print(lhs->mss); + Serial.print(" -> "); + Serial.println(rhs->mss); + lhs->mss = rhs->mss; + changed = true; + } + if (lhs->initialmss != rhs->initialmss) + { + Serial.print(" initialmss: "); + Serial.print(lhs->initialmss); + Serial.print(" -> "); + Serial.println(rhs->initialmss); + lhs->initialmss = rhs->initialmss; + changed = true; + } + if (lhs->sa != rhs->sa) + { + Serial.print(" sa: "); + Serial.print(lhs->sa); + Serial.print(" -> "); + Serial.println(rhs->sa); + lhs->sa = rhs->sa; + changed = true; + } + if (lhs->sv != rhs->sv) + { + Serial.print(" sv: "); + Serial.print(lhs->sv); + Serial.print(" -> "); + Serial.println(rhs->sv); + lhs->sv = rhs->sv; + changed = true; + } + if (lhs->rto != rhs->rto) + { + Serial.print(" rto: "); + Serial.print(lhs->rto); + Serial.print(" -> "); + Serial.println(rhs->rto); + lhs->rto = rhs->rto; + changed = true; + } + if (lhs->tcpstateflags != rhs->tcpstateflags) + { + Serial.print(" tcpstateflags: "); + Serial.print(lhs->tcpstateflags); + Serial.print(" -> "); + Serial.println(rhs->tcpstateflags); + lhs->tcpstateflags = rhs->tcpstateflags; + changed = true; + } + if (lhs->timer != rhs->timer) + { + Serial.print(" timer: "); + Serial.print(lhs->timer); + Serial.print(" -> "); + Serial.println(rhs->timer); + lhs->timer = rhs->timer; + changed = true; + } + if (lhs->nrtx != rhs->nrtx) + { + Serial.print(" nrtx: "); + Serial.print(lhs->nrtx); + Serial.print(" -> "); + Serial.println(rhs->nrtx); + lhs->nrtx = rhs->nrtx; + changed = true; + } + return changed; +} + +void +UIPDebug::uip_debug_printbytes(const uint8_t *data, uint8_t len) +{ + for(uint8_t i=0;i + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +#include "uip_clock.h" +#include "uip_timer.h" + +/*---------------------------------------------------------------------------*/ +/** + * Set a timer. + * + * This function is used to set a timer for a time sometime in the + * future. The function timer_expired() will evaluate to true after + * the timer has expired. + * + * \param t A pointer to the timer + * \param interval The interval before the timer expires. + * + */ +void +uip_timer_set(struct uip_timer *t, clock_time_t interval) +{ + t->interval = interval; + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Reset the timer with the same interval. + * + * This function resets the timer with the same interval that was + * given to the timer_set() function. The start point of the interval + * is the exact time that the timer last expired. Therefore, this + * function will cause the timer to be stable over time, unlike the + * timer_rester() function. + * + * \param t A pointer to the timer. + * + * \sa timer_restart() + */ +void +uip_timer_reset(struct uip_timer *t) +{ + t->start += t->interval; +} +/*---------------------------------------------------------------------------*/ +/** + * Restart the timer from the current point in time + * + * This function restarts a timer with the same interval that was + * given to the timer_set() function. The timer will start at the + * current time. + * + * \note A periodic timer will drift if this function is used to reset + * it. For preioric timers, use the timer_reset() function instead. + * + * \param t A pointer to the timer. + * + * \sa timer_reset() + */ +void +uip_timer_restart(struct uip_timer *t) +{ + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Check if a timer has expired. + * + * This function tests if a timer has expired and returns true or + * false depending on its status. + * + * \param t A pointer to the timer + * + * \return Non-zero if the timer has expired, zero otherwise. + * + */ +int +uip_timer_expired(struct uip_timer *t) +{ + return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; +} +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/libraries/UIPEthernet/utility/uip_timer.h b/libraries/UIPEthernet/utility/uip_timer.h new file mode 100644 index 0000000..f260349 --- /dev/null +++ b/libraries/UIPEthernet/utility/uip_timer.h @@ -0,0 +1,86 @@ +/** + * \defgroup timer Timer library + * + * The timer library provides functions for setting, resetting and + * restarting timers, and for checking if a timer has expired. An + * application must "manually" check if its timers have expired; this + * is not done automatically. + * + * A timer is declared as a \c struct \c timer and all access to the + * timer is made by a pointer to the declared timer. + * + * \note The timer library uses the \ref clock "Clock library" to + * measure time. Intervals should be specified in the format used by + * the clock library. + * + * @{ + */ + + +/** + * \file + * Timer library header file. + * \author + * Adam Dunkels + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $ + */ +#ifndef __UIP_TIMER_H__ +#define __UIP_TIMER_H__ + +#include "uip_clock.h" + +/** + * A timer. + * + * This structure is used for declaring a timer. The timer must be set + * with timer_set() before it can be used. + * + * \hideinitializer + */ +struct uip_timer { + clock_time_t start; + clock_time_t interval; +}; + +void uip_timer_set(struct uip_timer *t, clock_time_t interval); +void uip_timer_reset(struct uip_timer *t); +void uip_timer_restart(struct uip_timer *t); +int uip_timer_expired(struct uip_timer *t); + +#endif /* __UIP_TIMER_H__ */ + +/** @} */ diff --git a/libraries/UIPEthernet/utility/uipethernet-conf.h b/libraries/UIPEthernet/utility/uipethernet-conf.h new file mode 100644 index 0000000..b9c8d73 --- /dev/null +++ b/libraries/UIPEthernet/utility/uipethernet-conf.h @@ -0,0 +1,29 @@ +#ifndef UIPETHERNET_CONF_H +#define UIPETHERNET_CONF_H + +/* for TCP */ +#define UIP_SOCKET_NUMPACKETS 5 +#define UIP_CONF_MAX_CONNECTIONS 1 + +/* for UDP + * set UIP_CONF_UDP to 0 to disable UDP (saves aprox. 5kb flash) */ +#define UIP_CONF_UDP 0 +#define UIP_CONF_BROADCAST 1 +#define UIP_CONF_UDP_CONNS 4 + +/* number of attempts on write before returning number of bytes sent so far + * set to -1 to block until connection is closed by timeout */ +#define UIP_ATTEMPTS_ON_WRITE -1 + +/* timeout after which UIPClient::connect gives up. The timeout is specified in seconds. + * if set to a number <= 0 connect will timeout when uIP does (which might be longer than you expect...) */ +#define UIP_CONNECT_TIMEOUT -1 + +/* periodic timer for uip (in ms) */ +#define UIP_PERIODIC_TIMER 250 + +/* timer to poll client for data after last write (in ms) + * set to -1 to disable fast polling and rely on periodic only (saves 100 bytes flash) */ +#define UIP_CLIENT_TIMER 10 + +#endif diff --git a/libraries/UIPEthernet/utility/uipopt.h b/libraries/UIPEthernet/utility/uipopt.h new file mode 100644 index 0000000..42badf8 --- /dev/null +++ b/libraries/UIPEthernet/utility/uipopt.h @@ -0,0 +1,543 @@ +/** + * \defgroup uipopt Configuration options for uIP + * @{ + * + * uIP is configured using the per-project configuration file + * uipopt.h. This file contains all compile-time options for uIP and + * should be tweaked to match each specific project. The uIP + * distribution contains a documented example "uipopt.h" that can be + * copied and modified for each project. + * + * \note Most of the configuration options in the uipopt.h should not + * be changed, but rather the per-project uip-conf.h file. + */ + +/** + * \file + * Configuration options for uIP. + * \author Adam Dunkels + * + * This file is used for tweaking various configuration options for + * uIP. You should make a copy of this file into one of your project's + * directories instead of editing this example "uipopt.h" file that + * comes with the uIP distribution. + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $ + * + */ + +#ifndef __UIPOPT_H__ +#define __UIPOPT_H__ + +#ifndef UIP_LITTLE_ENDIAN +#define UIP_LITTLE_ENDIAN 3412 +#endif /* UIP_LITTLE_ENDIAN */ +#ifndef UIP_BIG_ENDIAN +#define UIP_BIG_ENDIAN 1234 +#endif /* UIP_BIG_ENDIAN */ + +#include "uip-conf.h" + +/*------------------------------------------------------------------------------*/ + +/** + * \name Static configuration options + * @{ + * + * These configuration options can be used for setting the IP address + * settings statically, but only if UIP_FIXEDADDR is set to 1. The + * configuration options for a specific node includes IP address, + * netmask and default router as well as the Ethernet address. The + * netmask, default router and Ethernet address are appliciable only + * if uIP should be run over Ethernet. + * + * All of these should be changed to suit your project. +*/ + +/** + * Determines if uIP should use a fixed IP address or not. + * + * If uIP should use a fixed IP address, the settings are set in the + * uipopt.h file. If not, the macros uip_sethostaddr(), + * uip_setdraddr() and uip_setnetmask() should be used instead. + * + * \hideinitializer + */ +#define UIP_FIXEDADDR 0 + +/** + * Ping IP address asignment. + * + * uIP uses a "ping" packets for setting its own IP address if this + * option is set. If so, uIP will start with an empty IP address and + * the destination IP address of the first incoming "ping" (ICMP echo) + * packet will be used for setting the hosts IP address. + * + * \note This works only if UIP_FIXEDADDR is 0. + * + * \hideinitializer + */ +#ifdef UIP_CONF_PINGADDRCONF +#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF +#else /* UIP_CONF_PINGADDRCONF */ +#define UIP_PINGADDRCONF 0 +#endif /* UIP_CONF_PINGADDRCONF */ + + +/** + * Specifies if the uIP ARP module should be compiled with a fixed + * Ethernet MAC address or not. + * + * If this configuration option is 0, the macro uip_setethaddr() can + * be used to specify the Ethernet address at run-time. + * + * \hideinitializer + */ +#define UIP_FIXEDETHADDR 0 + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name IP configuration options + * @{ + * + */ +/** + * The IP TTL (time to live) of IP packets sent by uIP. + * + * This should normally not be changed. + */ +#define UIP_TTL 64 + +/** + * Turn on support for IP packet reassembly. + * + * uIP supports reassembly of fragmented IP packets. This features + * requires an additonal amount of RAM to hold the reassembly buffer + * and the reassembly code size is approximately 700 bytes. The + * reassembly buffer is of the same size as the uip_buf buffer + * (configured by UIP_BUFSIZE). + * + * \note IP packet reassembly is not heavily tested. + * + * \hideinitializer + */ +#define UIP_REASSEMBLY 0 + +/** + * The maximum time an IP fragment should wait in the reassembly + * buffer before it is dropped. + * + */ +#define UIP_REASS_MAXAGE 40 + +/** @} */ + +/*------------------------------------------------------------------------------*/ +/** + * \name UDP configuration options + * @{ + */ + +/** + * Toggles wether UDP support should be compiled in or not. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP +#define UIP_UDP UIP_CONF_UDP +#else /* UIP_CONF_UDP */ +#define UIP_UDP 0 +#endif /* UIP_CONF_UDP */ + +/** + * Toggles if UDP checksums should be used or not. + * + * \note Support for UDP checksums is currently not included in uIP, + * so this option has no function. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP_CHECKSUMS +#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS +#else +#define UIP_UDP_CHECKSUMS 0 +#endif + +/** + * The maximum amount of concurrent UDP connections. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP_CONNS +#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS +#else /* UIP_CONF_UDP_CONNS */ +#define UIP_UDP_CONNS 10 +#endif /* UIP_CONF_UDP_CONNS */ + +/** + * The name of the function that should be called when UDP datagrams arrive. + * + * \hideinitializer + */ + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name TCP configuration options + * @{ + */ + +/** + * Determines if support for opening connections from uIP should be + * compiled in. + * + * If the applications that are running on top of uIP for this project + * do not need to open outgoing TCP connections, this configration + * option can be turned off to reduce the code size of uIP. + * + * \hideinitializer + */ +#define UIP_ACTIVE_OPEN 1 + +/** + * The maximum number of simultaneously open TCP connections. + * + * Since the TCP connections are statically allocated, turning this + * configuration knob down results in less RAM used. Each TCP + * connection requires approximatly 30 bytes of memory. + * + * \hideinitializer + */ +#ifndef UIP_CONF_MAX_CONNECTIONS +#define UIP_CONNS 10 +#else /* UIP_CONF_MAX_CONNECTIONS */ +#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS +#endif /* UIP_CONF_MAX_CONNECTIONS */ + + +/** + * The maximum number of simultaneously listening TCP ports. + * + * Each listening TCP port requires 2 bytes of memory. + * + * \hideinitializer + */ +#ifndef UIP_CONF_MAX_LISTENPORTS +#define UIP_LISTENPORTS 20 +#else /* UIP_CONF_MAX_LISTENPORTS */ +#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS +#endif /* UIP_CONF_MAX_LISTENPORTS */ + +/** + * Determines if support for TCP urgent data notification should be + * compiled in. + * + * Urgent data (out-of-band data) is a rarely used TCP feature that + * very seldom would be required. + * + * \hideinitializer + */ +#define UIP_URGDATA 0 + +/** + * The initial retransmission timeout counted in timer pulses. + * + * This should not be changed. + */ +#define UIP_RTO 3 + +/** + * The maximum number of times a segment should be retransmitted + * before the connection should be aborted. + * + * This should not be changed. + */ +#define UIP_MAXRTX 8 + +/** + * The maximum number of times a SYN segment should be retransmitted + * before a connection request should be deemed to have been + * unsuccessful. + * + * This should not need to be changed. + */ +#define UIP_MAXSYNRTX 5 + +/** + * The TCP maximum segment size. + * + * This is should not be to set to more than + * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. + */ +#ifndef UIP_CONF_TCP_MSS +#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) +#else +#define UIP_TCP_MSS UIP_CONF_TCP_MSS +#endif + +/** + * The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the uip_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + * + * \hideinitializer + */ +#ifndef UIP_CONF_RECEIVE_WINDOW +#define UIP_RECEIVE_WINDOW UIP_TCP_MSS +#else +#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW +#endif + +/** + * How long a connection should stay in the TIME_WAIT state. + * + * This configiration option has no real implication, and it should be + * left untouched. + */ +#define UIP_TIME_WAIT_TIMEOUT 120 + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name ARP configuration options + * @{ + */ + +/** + * The size of the ARP table. + * + * This option should be set to a larger value if this uIP node will + * have many connections from the local network. + * + * \hideinitializer + */ +#ifdef UIP_CONF_ARPTAB_SIZE +#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE +#else +#define UIP_ARPTAB_SIZE 8 +#endif + +/** + * The maxium age of ARP table entries measured in 10ths of seconds. + * + * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD + * default). + */ +#define UIP_ARP_MAXAGE 120 + +/** @} */ + +/*------------------------------------------------------------------------------*/ + +/** + * \name General configuration options + * @{ + */ + +/** + * The size of the uIP packet buffer. + * + * The uIP packet buffer should not be smaller than 60 bytes, and does + * not need to be larger than 1500 bytes. Lower size results in lower + * TCP throughput, larger size results in higher TCP throughput. + * + * \hideinitializer + */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_BUFSIZE 400 +#else /* UIP_CONF_BUFFER_SIZE */ +#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE +#endif /* UIP_CONF_BUFFER_SIZE */ + + +/** + * Determines if statistics support should be compiled in. + * + * The statistics is useful for debugging and to show the user. + * + * \hideinitializer + */ +#ifndef UIP_CONF_STATISTICS +#define UIP_STATISTICS 0 +#else /* UIP_CONF_STATISTICS */ +#define UIP_STATISTICS UIP_CONF_STATISTICS +#endif /* UIP_CONF_STATISTICS */ + +/** + * Determines if logging of certain events should be compiled in. + * + * This is useful mostly for debugging. The function uip_log() + * must be implemented to suit the architecture of the project, if + * logging is turned on. + * + * \hideinitializer + */ +#ifndef UIP_CONF_LOGGING +#define UIP_LOGGING 0 +#else /* UIP_CONF_LOGGING */ +#define UIP_LOGGING UIP_CONF_LOGGING +#endif /* UIP_CONF_LOGGING */ + +/** + * Broadcast support. + * + * This flag configures IP broadcast support. This is useful only + * together with UDP. + * + * \hideinitializer + * + */ +#if UIP_UDP && UIP_CONF_BROADCAST +#define UIP_BROADCAST UIP_CONF_BROADCAST +#else /* UIP_CONF_BROADCAST */ +#define UIP_BROADCAST 0 +#endif /* UIP_CONF_BROADCAST */ + +/** + * Print out a uIP log message. + * + * This function must be implemented by the module that uses uIP, and + * is called by uIP whenever a log message is generated. + */ +void uip_log(char *msg); + +/** + * The link level header length. + * + * This is the offset into the uip_buf where the IP header can be + * found. For Ethernet, this should be set to 14. For SLIP, this + * should be set to 0. + * + * \hideinitializer + */ +#ifdef UIP_CONF_LLH_LEN +#define UIP_LLH_LEN UIP_CONF_LLH_LEN +#else /* UIP_CONF_LLH_LEN */ +#define UIP_LLH_LEN 14 +#endif /* UIP_CONF_LLH_LEN */ + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name CPU architecture configuration + * @{ + * + * The CPU architecture configuration is where the endianess of the + * CPU on which uIP is to be run is specified. Most CPUs today are + * little endian, and the most notable exception are the Motorolas + * which are big endian. The BYTE_ORDER macro should be changed to + * reflect the CPU architecture on which uIP is to be run. + */ + +/** + * The byte order of the CPU architecture on which uIP is to be run. + * + * This option can be either BIG_ENDIAN (Motorola byte order) or + * LITTLE_ENDIAN (Intel byte order). + * + * \hideinitializer + */ +#ifdef UIP_CONF_BYTE_ORDER +#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER +#else /* UIP_CONF_BYTE_ORDER */ +#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN +#endif /* UIP_CONF_BYTE_ORDER */ + +/** @} */ +/*------------------------------------------------------------------------------*/ + +/** + * \name Appication specific configurations + * @{ + * + * An uIP application is implemented using a single application + * function that is called by uIP whenever a TCP/IP event occurs. The + * name of this function must be registered with uIP at compile time + * using the UIP_APPCALL definition. + * + * uIP applications can store the application state within the + * uip_conn structure by specifying the type of the application + * structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t. + * + * The file containing the definitions must be included in the + * uipopt.h file. + * + * The following example illustrates how this can look. + \code + +void httpd_appcall(void); +#define UIP_APPCALL httpd_appcall + +struct httpd_state { + u8_t state; + u16_t count; + char *dataptr; + char *script; +}; +typedef struct httpd_state uip_tcp_appstate_t + \endcode + */ + +/** + * \var #define UIP_APPCALL + * + * The name of the application function that uIP should call in + * response to TCP/IP events. + * + */ + +/** + * \var typedef uip_tcp_appstate_t + * + * The type of the application state that is to be stored in the + * uip_conn structure. This usually is typedef:ed to a struct holding + * application state information. + */ + +/** + * \var typedef uip_udp_appstate_t + * + * The type of the application state that is to be stored in the + * uip_conn structure. This usually is typedef:ed to a struct holding + * application state information. + */ +/** @} */ +/** @} */ + +#endif /* __UIPOPT_H__ */ diff --git a/libraries/UIPEthernet/utility/util.h b/libraries/UIPEthernet/utility/util.h new file mode 100644 index 0000000..5042e82 --- /dev/null +++ b/libraries/UIPEthernet/utility/util.h @@ -0,0 +1,13 @@ +#ifndef UTIL_H +#define UTIL_H + +#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) ) +#define ntohs(x) htons(x) + +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#endif diff --git a/libraries/UTFT/DefaultFonts.c b/libraries/UTFT/DefaultFonts.c new file mode 100644 index 0000000..bc11d95 --- /dev/null +++ b/libraries/UTFT/DefaultFonts.c @@ -0,0 +1,246 @@ +// DO NOT ADD YOUR OWN FONTS TO THIS FILE +// If you want to use your own fonts you should just drop the font .c file into your sketch folder. +// ------------------------------------------------------------------------------------------------ + +#if defined(__AVR__) + #include + #define fontdatatype const uint8_t +#elif defined(__PIC32MX__) + #define PROGMEM + #define fontdatatype const unsigned char +#elif defined(__arm__) + #define PROGMEM + #define fontdatatype const unsigned char +#endif + +// SmallFont.c +// Font Size : 8x12 +// Memory usage : 1144 bytes +// # characters : 95 + +fontdatatype SmallFont[1144] PROGMEM={ +0x08,0x0C,0x20,0x5F, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // +0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, // ! +0x00,0x28,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " +0x00,0x00,0x28,0x28,0xFC,0x28,0x50,0xFC,0x50,0x50,0x00,0x00, // # +0x00,0x20,0x78,0xA8,0xA0,0x60,0x30,0x28,0xA8,0xF0,0x20,0x00, // $ +0x00,0x00,0x48,0xA8,0xB0,0x50,0x28,0x34,0x54,0x48,0x00,0x00, // % +0x00,0x00,0x20,0x50,0x50,0x78,0xA8,0xA8,0x90,0x6C,0x00,0x00, // & +0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' +0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x04,0x00, // ( +0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x40,0x00, // ) +0x00,0x00,0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00,0x00,0x00, // * +0x00,0x00,0x20,0x20,0x20,0xF8,0x20,0x20,0x20,0x00,0x00,0x00, // + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80, // , +0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, // - +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, // . +0x00,0x08,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x00, // / +0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, // 0 +0x00,0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, // 1 +0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x40,0x80,0xF8,0x00,0x00, // 2 +0x00,0x00,0x70,0x88,0x08,0x30,0x08,0x08,0x88,0x70,0x00,0x00, // 3 +0x00,0x00,0x10,0x30,0x50,0x50,0x90,0x78,0x10,0x18,0x00,0x00, // 4 +0x00,0x00,0xF8,0x80,0x80,0xF0,0x08,0x08,0x88,0x70,0x00,0x00, // 5 +0x00,0x00,0x70,0x90,0x80,0xF0,0x88,0x88,0x88,0x70,0x00,0x00, // 6 +0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x20,0x20,0x20,0x00,0x00, // 7 +0x00,0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00, // 8 +0x00,0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x48,0x70,0x00,0x00, // 9 +0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x20,0x00,0x00, // : +0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x20,0x00, // ; +0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, // < +0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, // = +0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, // > +0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00, // ? +0x00,0x00,0x70,0x88,0x98,0xA8,0xA8,0xB8,0x80,0x78,0x00,0x00, // @ +0x00,0x00,0x20,0x20,0x30,0x50,0x50,0x78,0x48,0xCC,0x00,0x00, // A +0x00,0x00,0xF0,0x48,0x48,0x70,0x48,0x48,0x48,0xF0,0x00,0x00, // B +0x00,0x00,0x78,0x88,0x80,0x80,0x80,0x80,0x88,0x70,0x00,0x00, // C +0x00,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0x48,0xF0,0x00,0x00, // D +0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x48,0xF8,0x00,0x00, // E +0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x40,0xE0,0x00,0x00, // F +0x00,0x00,0x38,0x48,0x80,0x80,0x9C,0x88,0x48,0x30,0x00,0x00, // G +0x00,0x00,0xCC,0x48,0x48,0x78,0x48,0x48,0x48,0xCC,0x00,0x00, // H +0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00, // I +0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0xE0,0x00, // J +0x00,0x00,0xEC,0x48,0x50,0x60,0x50,0x50,0x48,0xEC,0x00,0x00, // K +0x00,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x44,0xFC,0x00,0x00, // L +0x00,0x00,0xD8,0xD8,0xD8,0xD8,0xA8,0xA8,0xA8,0xA8,0x00,0x00, // M +0x00,0x00,0xDC,0x48,0x68,0x68,0x58,0x58,0x48,0xE8,0x00,0x00, // N +0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, // O +0x00,0x00,0xF0,0x48,0x48,0x70,0x40,0x40,0x40,0xE0,0x00,0x00, // P +0x00,0x00,0x70,0x88,0x88,0x88,0x88,0xE8,0x98,0x70,0x18,0x00, // Q +0x00,0x00,0xF0,0x48,0x48,0x70,0x50,0x48,0x48,0xEC,0x00,0x00, // R +0x00,0x00,0x78,0x88,0x80,0x60,0x10,0x08,0x88,0xF0,0x00,0x00, // S +0x00,0x00,0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, // T +0x00,0x00,0xCC,0x48,0x48,0x48,0x48,0x48,0x48,0x30,0x00,0x00, // U +0x00,0x00,0xCC,0x48,0x48,0x50,0x50,0x30,0x20,0x20,0x00,0x00, // V +0x00,0x00,0xA8,0xA8,0xA8,0x70,0x50,0x50,0x50,0x50,0x00,0x00, // W +0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x50,0x50,0xD8,0x00,0x00, // X +0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x20,0x20,0x70,0x00,0x00, // Y +0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x40,0x48,0xF8,0x00,0x00, // Z +0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, // [ +0x00,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x00,0x00, // +0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, // ] +0x00,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, // _ +0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' +0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x38,0x48,0x3C,0x00,0x00, // a +0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0x70,0x00,0x00, // b +0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x40,0x40,0x38,0x00,0x00, // c +0x00,0x00,0x18,0x08,0x08,0x38,0x48,0x48,0x48,0x3C,0x00,0x00, // d +0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x78,0x40,0x38,0x00,0x00, // e +0x00,0x00,0x1C,0x20,0x20,0x78,0x20,0x20,0x20,0x78,0x00,0x00, // f +0x00,0x00,0x00,0x00,0x00,0x3C,0x48,0x30,0x40,0x78,0x44,0x38, // g +0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0xEC,0x00,0x00, // h +0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x70,0x00,0x00, // i +0x00,0x00,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0xE0, // j +0x00,0x00,0xC0,0x40,0x40,0x5C,0x50,0x70,0x48,0xEC,0x00,0x00, // k +0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00, // l +0x00,0x00,0x00,0x00,0x00,0xF0,0xA8,0xA8,0xA8,0xA8,0x00,0x00, // m +0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0xEC,0x00,0x00, // n +0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00, // o +0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0x70,0x40,0xE0, // p +0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x1C, // q +0x00,0x00,0x00,0x00,0x00,0xD8,0x60,0x40,0x40,0xE0,0x00,0x00, // r +0x00,0x00,0x00,0x00,0x00,0x78,0x40,0x30,0x08,0x78,0x00,0x00, // s +0x00,0x00,0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x18,0x00,0x00, // t +0x00,0x00,0x00,0x00,0x00,0xD8,0x48,0x48,0x48,0x3C,0x00,0x00, // u +0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x00,0x00, // v +0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x70,0x50,0x50,0x00,0x00, // w +0x00,0x00,0x00,0x00,0x00,0xD8,0x50,0x20,0x50,0xD8,0x00,0x00, // x +0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x20,0xC0, // y +0x00,0x00,0x00,0x00,0x00,0x78,0x10,0x20,0x20,0x78,0x00,0x00, // z +0x00,0x18,0x10,0x10,0x10,0x20,0x10,0x10,0x10,0x10,0x18,0x00, // { +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, // | +0x00,0x60,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x60,0x00, // } +0x40,0xA4,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ +}; + +// BigFont.c (C)2010 by Henning Karlsen +// Font Size : 16x16 +// Memory usage : 3044 bytes +// # characters : 95 + +fontdatatype BigFont[3044] PROGMEM={ +0x10,0x10,0x20,0x5F, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // +0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00, // ! +0x00,0x00,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x06,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " +0x00,0x00,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x7F,0xFE,0x7F,0xFE,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x7F,0xFE,0x7F,0xFE,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x00,0x00, // # +0x00,0x00,0x02,0x40,0x02,0x40,0x0F,0xF8,0x1F,0xF8,0x1A,0x40,0x1A,0x40,0x1F,0xF0,0x0F,0xF8,0x02,0x58,0x02,0x58,0x1F,0xF8,0x1F,0xF0,0x02,0x40,0x02,0x40,0x00,0x00, // $ +0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x10,0x0E,0x30,0x0E,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x70,0x0C,0x70,0x08,0x70,0x00,0x00,0x00,0x00,0x00,0x00, // % +0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x19,0x80,0x0F,0x00,0x0F,0x08,0x0F,0x98,0x19,0xF8,0x18,0xF0,0x18,0xE0,0x19,0xF0,0x0F,0x98,0x00,0x00,0x00,0x00, // & +0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' +0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xF0,0x00,0x00,0x00,0x00, // ( +0x00,0x00,0x00,0x00,0x0F,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x0F,0x00,0x00,0x00,0x00,0x00, // ) +0x00,0x00,0x00,0x00,0x01,0x80,0x11,0x88,0x09,0x90,0x07,0xE0,0x07,0xE0,0x3F,0xFC,0x3F,0xFC,0x07,0xE0,0x07,0xE0,0x09,0x90,0x11,0x88,0x01,0x80,0x00,0x00,0x00,0x00, // * +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x0F,0xF0,0x0F,0xF0,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x0E,0x00,0x00,0x00, // , +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x1F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00, // , +0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x00,0x0E,0x00,0x1C,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, // / + +0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x78,0x1C,0xF8,0x1C,0xF8,0x1D,0xB8,0x1D,0xB8,0x1F,0x38,0x1F,0x38,0x1E,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // 0 +0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x80,0x1F,0x80,0x1F,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x1F,0xF0,0x00,0x00,0x00,0x00, // 1 +0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x38,0x1C,0x38,0x1F,0xF8,0x00,0x00,0x00,0x00, // 2 +0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x38,0x00,0x38,0x00,0x70,0x03,0xC0,0x03,0xC0,0x00,0x70,0x00,0x38,0x1C,0x38,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // 3 +0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0xE0,0x03,0xE0,0x06,0xE0,0x0C,0xE0,0x18,0xE0,0x1F,0xF8,0x1F,0xF8,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x03,0xF8,0x00,0x00,0x00,0x00, // 4 +0x00,0x00,0x00,0x00,0x1F,0xF8,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xE0,0x1F,0xF0,0x00,0x78,0x00,0x38,0x1C,0x38,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // 5 +0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xF0,0x1F,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // 6 +0x00,0x00,0x00,0x00,0x1F,0xFC,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x1C,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00, // 7 +0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1F,0x38,0x07,0xE0,0x07,0xE0,0x1C,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // 8 +0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1F,0xF8,0x0F,0xF8,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x07,0xC0,0x00,0x00,0x00,0x00, // 9 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ; +0x00,0x00,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x00, // < +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFC,0x3F,0xFC,0x00,0x00,0x00,0x00,0x3F,0xFC,0x3F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = +0x00,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00, // > +0x00,0x00,0x03,0xC0,0x0F,0xF0,0x1E,0x78,0x18,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00, // ? + +0x00,0x00,0x0F,0xF8,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0xFC,0x1C,0xFC,0x1C,0xFC,0x1C,0xFC,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xF0,0x07,0xF8,0x00,0x00, // @ +0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0E,0x70,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1F,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x00,0x00,0x00,0x00, // A +0x00,0x00,0x00,0x00,0x1F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1F,0xF0,0x00,0x00,0x00,0x00, // B +0x00,0x00,0x00,0x00,0x07,0xF0,0x0E,0x38,0x1C,0x38,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x38,0x0E,0x38,0x07,0xF0,0x00,0x00,0x00,0x00, // C +0x00,0x00,0x00,0x00,0x1F,0xE0,0x0E,0x70,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x70,0x1F,0xE0,0x00,0x00,0x00,0x00, // D +0x00,0x00,0x00,0x00,0x1F,0xF8,0x0E,0x18,0x0E,0x08,0x0E,0x00,0x0E,0x30,0x0F,0xF0,0x0F,0xF0,0x0E,0x30,0x0E,0x00,0x0E,0x08,0x0E,0x18,0x1F,0xF8,0x00,0x00,0x00,0x00, // E +0x00,0x00,0x00,0x00,0x1F,0xF8,0x0E,0x18,0x0E,0x08,0x0E,0x00,0x0E,0x30,0x0F,0xF0,0x0F,0xF0,0x0E,0x30,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x00,0x00,0x00,0x00, // F +0x00,0x00,0x00,0x00,0x07,0xF0,0x0E,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0xF8,0x1C,0x38,0x1C,0x38,0x0E,0x38,0x07,0xF8,0x00,0x00,0x00,0x00, // G +0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1F,0xF0,0x1F,0xF0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x00,0x00,0x00,0x00, // H +0x00,0x00,0x00,0x00,0x0F,0xE0,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x0F,0xE0,0x00,0x00,0x00,0x00, // I +0x00,0x00,0x00,0x00,0x01,0xFC,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x38,0x70,0x38,0x70,0x38,0x70,0x38,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // J +0x00,0x00,0x00,0x00,0x1E,0x38,0x0E,0x38,0x0E,0x70,0x0E,0xE0,0x0F,0xC0,0x0F,0x80,0x0F,0x80,0x0F,0xC0,0x0E,0xE0,0x0E,0x70,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // K +0x00,0x00,0x00,0x00,0x1F,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x08,0x0E,0x18,0x0E,0x38,0x1F,0xF8,0x00,0x00,0x00,0x00, // L +0x00,0x00,0x00,0x00,0x1C,0x1C,0x1E,0x3C,0x1F,0x7C,0x1F,0xFC,0x1F,0xFC,0x1D,0xDC,0x1C,0x9C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x00,0x00,0x00, // M +0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1E,0x1C,0x1F,0x1C,0x1F,0x9C,0x1D,0xDC,0x1C,0xFC,0x1C,0x7C,0x1C,0x3C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x00,0x00,0x00, // N +0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0xF0,0x0E,0x38,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x0E,0x38,0x07,0xF0,0x03,0xE0,0x00,0x00,0x00,0x00, // O + +0x00,0x00,0x00,0x00,0x1F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0F,0xF0,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x00,0x00,0x00,0x00, // P +0x00,0x00,0x00,0x00,0x03,0xE0,0x0F,0x78,0x0E,0x38,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x7C,0x1C,0xFC,0x0F,0xF8,0x0F,0xF8,0x00,0x38,0x00,0xFC,0x00,0x00, // Q +0x00,0x00,0x00,0x00,0x1F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0F,0xF0,0x0E,0x70,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // R +0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x00,0x0F,0xE0,0x07,0xF0,0x00,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // S +0x00,0x00,0x00,0x00,0x1F,0xFC,0x19,0xCC,0x11,0xC4,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x07,0xF0,0x00,0x00,0x00,0x00, // T +0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // U +0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x00,0x00,0x00,0x00, // V +0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x0F,0xF8,0x0F,0xF8,0x07,0x70,0x07,0x70,0x00,0x00,0x00,0x00, // W +0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x03,0x80,0x07,0xC0,0x0E,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x00,0x00,0x00,0x00, // X +0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x0F,0xE0,0x00,0x00,0x00,0x00, // Y +0x00,0x00,0x00,0x00,0x1F,0xF8,0x1C,0x38,0x18,0x38,0x10,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x08,0x1C,0x18,0x1C,0x38,0x1F,0xF8,0x00,0x00,0x00,0x00, // Z +0x00,0x00,0x00,0x00,0x07,0xF0,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0xF0,0x00,0x00,0x00,0x00, // [ +0x00,0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x07,0x00,0x00,0x00,0x00, // +0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x07,0xF0,0x00,0x00,0x00,0x00, // ] +0x00,0x00,0x01,0x80,0x03,0xC0,0x07,0xE0,0x0E,0x70,0x1C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x7F,0xFF, // _ + +0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x00,0x70,0x00,0x70,0x0F,0xF0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00, // a +0x00,0x00,0x00,0x00,0x1E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1B,0xF0,0x00,0x00,0x00,0x00, // b +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x00,0x1C,0x00,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // c +0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x70,0x00,0x70,0x00,0x70,0x0F,0xF0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00, // d +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x70,0x1F,0xF0,0x1C,0x00,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // e +0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0x70,0x07,0x70,0x07,0x00,0x07,0x00,0x1F,0xE0,0x1F,0xE0,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00, // f +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xD8,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xF0,0x07,0xF0,0x00,0x70,0x1C,0x70,0x0F,0xE0, // g +0x00,0x00,0x00,0x00,0x1E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0xF0,0x0F,0x38,0x0F,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // h +0x00,0x00,0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x0F,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x0F,0xF8,0x00,0x00,0x00,0x00, // i +0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x00,0x03,0xF0,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x1C,0x70,0x0C,0xF0,0x07,0xE0, // j +0x00,0x00,0x00,0x00,0x1E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x38,0x0E,0x70,0x0E,0xE0,0x0F,0xC0,0x0E,0xE0,0x0E,0x70,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // k +0x00,0x00,0x00,0x00,0x0F,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x0F,0xF8,0x00,0x00,0x00,0x00, // l +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x00,0x00,0x00,0x00, // m +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x00,0x00,0x00,0x00, // n +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // o + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0E,0x00,0x0E,0x00,0x1F,0x00, // p +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xB0,0x38,0xE0,0x38,0xE0,0x38,0xE0,0x38,0xE0,0x38,0xE0,0x1F,0xE0,0x00,0xE0,0x00,0xE0,0x01,0xF0, // q +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xF0,0x0F,0xF8,0x0F,0x38,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x00,0x00,0x00,0x00, // r +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x30,0x1C,0x30,0x0F,0x80,0x03,0xE0,0x18,0x70,0x18,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // s +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x00,0x1F,0xF0,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x70,0x07,0x70,0x03,0xE0,0x00,0x00,0x00,0x00, // t +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00, // u +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x00,0x00,0x00,0x00, // v +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x9C,0x1C,0x9C,0x0F,0xF8,0x07,0x70,0x07,0x70,0x00,0x00,0x00,0x00, // w +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0xE0,0x1C,0xE0,0x0F,0xC0,0x07,0x80,0x07,0x80,0x0F,0xC0,0x1C,0xE0,0x1C,0xE0,0x00,0x00,0x00,0x00, // x +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x07,0xF0,0x03,0xE0,0x00,0xE0,0x01,0xC0,0x1F,0x80, // y +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x18,0xE0,0x11,0xC0,0x03,0x80,0x07,0x00,0x0E,0x20,0x1C,0x60,0x1F,0xE0,0x00,0x00,0x00,0x00, // z +0x00,0x00,0x00,0x00,0x01,0xF8,0x03,0x80,0x03,0x80,0x03,0x80,0x07,0x00,0x1C,0x00,0x1C,0x00,0x07,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0xF8,0x00,0x00,0x00,0x00, // { +0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00, // | +0x00,0x00,0x00,0x00,0x1F,0x80,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0xE0,0x00,0x38,0x00,0x38,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x1F,0x80,0x00,0x00,0x00,0x00, // } +0x00,0x00,0x00,0x00,0x1F,0x1C,0x3B,0x9C,0x39,0xDC,0x38,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ~ +}; + +// SevenSegNumFont.c +// Font Size : 32x50 +// Memory usage : 2004 bytes +// # characters : 10 + +fontdatatype SevenSegNumFont[2004] PROGMEM={ +0x20,0x32,0x30,0x0A, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x0C,0xFF,0xFE,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x38,0x00,0x00,0x18,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x38,0x00,0x00,0x18,0x3E,0x00,0x00,0x78,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x1E,0x00,0x00,0xF0,0x0C,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x00,0xFF,0xFE,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x01,0xFF,0xFE,0x18,0x03,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x27,0xFF,0xFF,0xC0,0x39,0xFF,0xFF,0x00,0x3E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x0C,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x00,0xFF,0xFE,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x01,0xFF,0xFE,0x18,0x03,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x0C,0x00,0x00,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x39,0xFF,0xFE,0x18,0x23,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x0C,0xFF,0xFE,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x39,0xFF,0xFE,0x00,0x23,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 5 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x0C,0xFF,0xFE,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x39,0xFF,0xFE,0x00,0x23,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xE0,0x27,0xFF,0xFF,0xC0,0x39,0xFF,0xFF,0x18,0x3E,0x00,0x00,0x78,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x1E,0x00,0x00,0xF0,0x0C,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x00,0xFF,0xFE,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x0C,0xFF,0xFE,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x39,0xFF,0xFE,0x18,0x23,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x27,0xFF,0xFF,0xC0,0x39,0xFF,0xFF,0x18,0x3E,0x00,0x00,0x78,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x1E,0x00,0x00,0xF0,0x0C,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x0C,0xFF,0xFE,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x39,0xFF,0xFE,0x18,0x23,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 +}; diff --git a/libraries/UTFT/License - CC BY-NC-SA 3.0 - Legal.pdf b/libraries/UTFT/License - CC BY-NC-SA 3.0 - Legal.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed326c9d62012e183e6190ca9bf7bfdaec7ed4ed GIT binary patch literal 150761 zcma&N19&A}vj!U5c6N-3ZQHhO+qP{^Ji)}aZQIU76HanxzVrR(|L=Xid(P?S*}Hpp zuUfTM)mv{@uj);vAR}-tm@&G0_dQku)69W@FE4>_monGb7B^CxYdI^9wfR&j6z{Je1%f|Z`?n4eQ)7D*Qw2jOTj$>zh3#!zZS9-^tn>;_rY4rgF7{5p74h-Wi`p4G zc{;cNm{@*`D$$Es+PIiH(Tmv_x|se~5A>2E+B~A1oD7_dV$6&Tf{aXTEDW4%3}Q^I zVj>LeVhn5|3?h6y%$!2Z%z|vf%*;aULM$vyg3OE@LW~?@f=q&J>?|UJe7f|Kb|$7C z+Q04adlJ8YnAroEnEp~KV`^vaVgX=e;P^8-xBr?nJH3*<{qJ$H{?$bJx3K_h4D>3V z4yN=PN~UJ?>e`F|W&q=Fb2z&=nHt){!&qz^8JQR$85kHD7T>B{uK96g9ZR&hP;yCn|jmlq5sa+=C*;UZ4wF)lme@OQXlfIycj&pzdZyG!^-(@@BEXU0gN0R^#8I2D=WS7Zx1p4dwM$dWcAq>r-?vi?S~Gd z)w)hosp+TPPxnDM(siOcvq=cGUW~D_=6vDLBWkA%4tj?7FW%_8_*76Qrxaki!PbZc zSiGnuWdn=~6Cz<()J`}rNA!nf^iCuTXjcT|wApu7mV{+VF#ykAWd1AtD#{2mS4k8% z_QY@3;k#0Y$c)uUc6F%rd`UCNR@93NK0nDvvu3{DO%J1{js1f){=(DWa2FQ)jX-4= zlfU+Yt}Yg$Zl-oF^dk1g@(!kU^ul7Y^lD81J##j`-`l@{sO(~BXJY7N^50jPIOydm zk*VM2k_{kq?7$n0eRjg`RN5T9qG5lgq7(|}`iUCa&Qj4U0B9MRSs3V*04%>%+lu{{ z{@>qD|2kBq44%K;*e@BQd(RH7(}S(}4)p)osOZ%IEdLI-zo7W{lw?g^3{4DO41Z(w zFMKK(nw!cPdfL0X(97GI{#Ufo|2gRlU}F5M#b3x3{w-o-Z~h;B{zt?L+uOPPwu`g& z??C?@ivZ@o1Od!{1qp!p4}bhV`B$6*nEz4>VE!Zi`y~6Hoi4qwlf8qGy@xgf-R~ZL ze^@zL>3)lIurShbGU?KbJK4KB09ZNxG^UsRO#_DiL*w7f@p~};8oiRKv%Ra6vFYDj zV(+BvU}$Xmhgg&u04#s0|9!{^VEL=_KfL1MBL3TXE`QpH|7r6F{7Qcu`+JtZ >V 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⎻-tUSZ|(H0NjqB5L}S~$db>mU`T|jN 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 Dw3!jg literal 0 HcmV?d00001 diff --git a/libraries/UTFT/License - CC BY-NC-SA 3.0 - Summary.pdf b/libraries/UTFT/License - CC BY-NC-SA 3.0 - Summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b35e677e66c08dbb9caccc1c135051624b16b0d7 GIT binary patch literal 109586 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%0Aw`tglGsl`4d>k#@@?6B) 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 g@OZxgFA`CAsDFt1M#e8bpQYW literal 0 HcmV?d00001 diff --git a/libraries/UTFT/Tools/ImageConverter565.exe b/libraries/UTFT/Tools/ImageConverter565.exe new file mode 100644 index 0000000000000000000000000000000000000000..cca5c396cb15b2e59466329c3e6783d99bbf3131 GIT binary patch literal 212480 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 L=+^QtcLx3+p8a)` literal 0 HcmV?d00001 diff --git a/libraries/UTFT/Tools/ImgConv.exe b/libraries/UTFT/Tools/ImgConv.exe new file mode 100644 index 0000000000000000000000000000000000000000..229ae8ba86c2d069a9957446b207c6ee76847537 GIT binary patch literal 25600 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�+p5t^46$(Q1>LRk&H~BkdcK0g}+`9Giw>#U;zxr!WvNvwJ=&J4G>h#-|>h( z0zB8de^NQT<$9t=r@*rxJ@*>;Ur&JtIj@Z-Tnb^o1|GBZgi9eXNldsDVkh7Joao1_ zlz;vBQ}`iM9sTrsi53KfxF5Ki=&m~Y)hPd$I{Lfxm7v;^Rm=Y0F+ zY2Rj~`TDZ?;wg0sIjF4ectIx@R;&p8jn_uO?Z)oKtG@W)*F*fYldrRhYYoW$hWGdC zF}r$JAp~^4$sMRcCiQ-lUsMIJP->i>MZ=oxS9#C646l6$*+=ld$uLP)={L#_iFe<5 z?COFY8Mo88uVVkIueTfZ_!VPKE`Hs-tor44n$Ql*!~1a$cYc1n1CXE7Oyu7M96xX2 z-;JeEZyVCXQiGp8jAGBp5~|%O$=lyXoK5$UjgNZ8jp>QjOZ%7k^>}Z}?FV+^-09^| z`l=UgYQtWxlYXN71pBgm8tErmX|j#DP7mzJPo76)f6H6^*Q=L-ezxeyea!xX!B^+c zf~bOu8kv;}A%!nKi~=}u;sh|S${+tDX{7MQhfxgvqu0@fYt-D>aE+R1q;|dhM!seY zq+pNt)?YVHw%@kk+VQP#^_54>$Lp`J0%|G3GwUa=_<$bAkXuBz4-9othwaaNWsRbbNQ#u3$P(r zVB@@+JB0nt+67k(Y+kZ@fz3Zs7|IrK{CVwyai_H4l6B3oHCg}QnhgfU(%J=MUh$$* z?hp=cm6nVIzx-H|b4M=9mPWdcEMH)cWQ+NOPN^L1W~4Q+vh6CfKAc}JC8cS-YU&7dKtm(a{A<6^F7nR>JY_gYFs1bN&LUhqg;jZVbmd$NfAoo^yB%aymme z;dcaEtzoBhhFn(!Ty0!6KG@3S#`w(LHs^>_unP>=F36VpibwE2u)PKLSYDkwT)W^P zenaB;N(qytQ%DntzO+I1HA|~T0KuB2K@TCL`uh#|2Wo)>>VJ{EwC)d7zc + +// Include hardware-specific functions for the correct MCU +#if defined(__AVR__) + #include + #include "hardware/avr/HW_AVR.h" + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + #include "hardware/avr/HW_ATmega1280.h" + #elif defined(__AVR_ATmega328P__) + #include "hardware/avr/HW_ATmega328P.h" + #elif defined(__AVR_ATmega32U4__) + #include "hardware/avr/HW_ATmega32U4.h" + #elif defined(__AVR_ATmega168__) + #error "ATmega168 MCUs are not supported because they have too little flash memory!" + #elif defined(__AVR_ATmega1284P__) + #include "hardware/avr/HW_ATmega1284P.h" + #else + #error "Unsupported AVR MCU!" + #endif +#elif defined(__PIC32MX__) + #include "hardware/pic32/HW_PIC32.h" + #if defined(__32MX320F128H__) + #pragma message("Compiling for chipKIT UNO32 (PIC32MX320F128H)") + #include "hardware/pic32/HW_PIC32MX320F128H.h" + #elif defined(__32MX340F512H__) + #pragma message("Compiling for chipKIT uC32 (PIC32MX340F512H)") + #include "hardware/pic32/HW_PIC32MX340F512H.h" + #elif defined(__32MX795F512L__) + #pragma message("Compiling for chipKIT MAX32 (PIC32MX795F512L)") + #include "hardware/pic32/HW_PIC32MX795F512L.h" + #else + #error "Unsupported PIC32 MCU!" + #endif +#elif defined(__arm__) + #include "hardware/arm/HW_ARM.h" + #if defined(__SAM3X8E__) + #pragma message("Compiling for Arduino Due (AT91SAM3X8E)...") + #include "hardware/arm/HW_SAM3X8E.h" + #elif defined(__MK20DX128__) || defined(__MK20DX256__) + #pragma message("Compiling for Teensy 3.x (MK20DX128VLH7 / MK20DX256VLH7)...") + #include "hardware/arm/HW_MX20DX256.h" + #else + #error "Unsupported ARM MCU!" + #endif +#endif +#include "memorysaver.h" + +UTFT::UTFT() +{ +} + +UTFT::UTFT(byte model, int RS, int WR, int CS, int RST, int SER) +{ + word dsx[] = {239, 239, 239, 239, 239, 239, 175, 175, 239, 127, 127, 239, 271, 479, 239, 239, 239, 239, 239, 239, 479, 319, 239, 175, 127, 239, 239, 319, 319, 799, 127}; + word dsy[] = {319, 399, 319, 319, 319, 319, 219, 219, 399, 159, 127, 319, 479, 799, 319, 319, 319, 319, 319, 319, 799, 479, 319, 219, 159, 319, 319, 479, 479, 479, 159}; + byte dtm[] = {16, 16, 16, 8, 8, 16, 8, SERIAL_4PIN, 16, SERIAL_5PIN, SERIAL_5PIN, 16, 16, 16, 8, 16, LATCHED_16, 8, 16, 8, 16, 16, 16, 8, SERIAL_5PIN, SERIAL_5PIN, SERIAL_4PIN, 16, 16, 16, SERIAL_5PIN}; + + disp_x_size = dsx[model]; + disp_y_size = dsy[model]; + display_transfer_mode = dtm[model]; + display_model = model; + + __p1 = RS; + __p2 = WR; + __p3 = CS; + __p4 = RST; + __p5 = SER; + + if (display_transfer_mode == SERIAL_4PIN) + { + display_transfer_mode=1; + display_serial_mode=SERIAL_4PIN; + } + if (display_transfer_mode == SERIAL_5PIN) + { + display_transfer_mode=1; + display_serial_mode=SERIAL_5PIN; + } + + if (display_transfer_mode!=1) + { + _set_direction_registers(display_transfer_mode); + P_RS = portOutputRegister(digitalPinToPort(RS)); + B_RS = digitalPinToBitMask(RS); + P_WR = portOutputRegister(digitalPinToPort(WR)); + B_WR = digitalPinToBitMask(WR); + P_CS = portOutputRegister(digitalPinToPort(CS)); + B_CS = digitalPinToBitMask(CS); + P_RST = portOutputRegister(digitalPinToPort(RST)); + B_RST = digitalPinToBitMask(RST); + if (display_transfer_mode==LATCHED_16) + { + P_ALE = portOutputRegister(digitalPinToPort(SER)); + B_ALE = digitalPinToBitMask(SER); + cbi(P_ALE, B_ALE); + pinMode(8,OUTPUT); + digitalWrite(8, LOW); + } + } + else + { + P_SDA = portOutputRegister(digitalPinToPort(RS)); + B_SDA = digitalPinToBitMask(RS); + P_SCL = portOutputRegister(digitalPinToPort(WR)); + B_SCL = digitalPinToBitMask(WR); + P_CS = portOutputRegister(digitalPinToPort(CS)); + B_CS = digitalPinToBitMask(CS); + if (RST != NOTINUSE) + { + P_RST = portOutputRegister(digitalPinToPort(RST)); + B_RST = digitalPinToBitMask(RST); + } + if (display_serial_mode!=SERIAL_4PIN) + { + P_RS = portOutputRegister(digitalPinToPort(SER)); + B_RS = digitalPinToBitMask(SER); + } + } +} + +void UTFT::LCD_Write_COM(char VL) +{ + if (display_transfer_mode!=1) + { + cbi(P_RS, B_RS); + LCD_Writ_Bus(0x00,VL,display_transfer_mode); + } + else + LCD_Writ_Bus(0x00,VL,display_transfer_mode); +} + +void UTFT::LCD_Write_DATA(char VH,char VL) +{ + if (display_transfer_mode!=1) + { + sbi(P_RS, B_RS); + LCD_Writ_Bus(VH,VL,display_transfer_mode); + } + else + { + LCD_Writ_Bus(0x01,VH,display_transfer_mode); + LCD_Writ_Bus(0x01,VL,display_transfer_mode); + } +} + +void UTFT::LCD_Write_DATA(char VL) +{ + if (display_transfer_mode!=1) + { + sbi(P_RS, B_RS); + LCD_Writ_Bus(0x00,VL,display_transfer_mode); + } + else + LCD_Writ_Bus(0x01,VL,display_transfer_mode); +} + +void UTFT::LCD_Write_COM_DATA(char com1,int dat1) +{ + LCD_Write_COM(com1); + LCD_Write_DATA(dat1>>8,dat1); +} + +void UTFT::InitLCD(byte orientation) +{ + orient=orientation; + _hw_special_init(); + + pinMode(__p1,OUTPUT); + pinMode(__p2,OUTPUT); + pinMode(__p3,OUTPUT); + if (__p4 != NOTINUSE) + pinMode(__p4,OUTPUT); + if ((display_transfer_mode==LATCHED_16) or ((display_transfer_mode==1) and (display_serial_mode==SERIAL_5PIN))) + pinMode(__p5,OUTPUT); + if (display_transfer_mode!=1) + _set_direction_registers(display_transfer_mode); + + sbi(P_RST, B_RST); + delay(5); + cbi(P_RST, B_RST); + delay(15); + sbi(P_RST, B_RST); + delay(15); + + cbi(P_CS, B_CS); + + switch(display_model) + { +#ifndef DISABLE_HX8347A + #include "tft_drivers/hx8347a/initlcd.h" +#endif +#ifndef DISABLE_ILI9327 + #include "tft_drivers/ili9327/initlcd.h" +#endif +#ifndef DISABLE_SSD1289 + #include "tft_drivers/ssd1289/initlcd.h" +#endif +#ifndef DISABLE_ILI9325C + #include "tft_drivers/ili9325c/initlcd.h" +#endif +#ifndef DISABLE_ILI9325D + #include "tft_drivers/ili9325d/default/initlcd.h" +#endif +#ifndef DISABLE_ILI9325D_ALT + #include "tft_drivers/ili9325d/alt/initlcd.h" +#endif +#ifndef DISABLE_HX8340B_8 + #include "tft_drivers/hx8340b/8/initlcd.h" +#endif +#ifndef DISABLE_HX8340B_S + #include "tft_drivers/hx8340b/s/initlcd.h" +#endif +#ifndef DISABLE_ST7735 + #include "tft_drivers/st7735/initlcd.h" +#endif +#ifndef DISABLE_PCF8833 + #include "tft_drivers/pcf8833/initlcd.h" +#endif +#ifndef DISABLE_S1D19122 + #include "tft_drivers/s1d19122/initlcd.h" +#endif +#ifndef DISABLE_HX8352A + #include "tft_drivers/hx8352a/initlcd.h" +#endif +#ifndef DISABLE_SSD1963_480 + #include "tft_drivers/ssd1963/480/initlcd.h" +#endif +#ifndef DISABLE_SSD1963_800 + #include "tft_drivers/ssd1963/800/initlcd.h" +#endif +#ifndef DISABLE_SSD1963_800_ALT + #include "tft_drivers/ssd1963/800alt/initlcd.h" +#endif +#ifndef DISABLE_S6D1121 + #include "tft_drivers/s6d1121/initlcd.h" +#endif +#ifndef DISABLE_ILI9320 + #include "tft_drivers/ili9320/initlcd.h" +#endif +#ifndef DISABLE_ILI9481 + #include "tft_drivers/ili9481/initlcd.h" +#endif +#ifndef DISABLE_S6D0164 + #include "tft_drivers/s6d0164/initlcd.h" +#endif +#ifndef DISABLE_ST7735S + #include "tft_drivers/st7735s/initlcd.h" +#endif +#ifndef DISABLE_ILI9341_S4P + #include "tft_drivers/ili9341/s4p/initlcd.h" +#endif +#ifndef DISABLE_ILI9341_S5P + #include "tft_drivers/ili9341/s5p/initlcd.h" +#endif +#ifndef DISABLE_R61581 + #include "tft_drivers/r61581/initlcd.h" +#endif +#ifndef DISABLE_ILI9486 + #include "tft_drivers/ili9486/initlcd.h" +#endif +#ifndef DISABLE_CPLD + #include "tft_drivers/cpld/initlcd.h" +#endif +#ifndef DISABLE_HX8353C + #include "tft_drivers/hx8353c/initlcd.h" +#endif + } + + sbi (P_CS, B_CS); + + setColor(255, 255, 255); + setBackColor(0, 0, 0); + cfont.font=0; + _transparent = false; +} + +void UTFT::setXY(word x1, word y1, word x2, word y2) +{ + if (orient==LANDSCAPE) + { + swap(word, x1, y1); + swap(word, x2, y2) + y1=disp_y_size-y1; + y2=disp_y_size-y2; + swap(word, y1, y2) + } + + switch(display_model) + { +#ifndef DISABLE_HX8347A + #include "tft_drivers/hx8347a/setxy.h" +#endif +#ifndef DISABLE_HX8352A + #include "tft_drivers/hx8352a/setxy.h" +#endif +#ifndef DISABLE_ILI9327 + #include "tft_drivers/ili9327/setxy.h" +#endif +#ifndef DISABLE_SSD1289 + #include "tft_drivers/ssd1289/setxy.h" +#endif +#ifndef DISABLE_ILI9325C + #include "tft_drivers/ili9325c/setxy.h" +#endif +#ifndef DISABLE_ILI9325D + #include "tft_drivers/ili9325d/default/setxy.h" +#endif +#ifndef DISABLE_ILI9325D_ALT + #include "tft_drivers/ili9325d/alt/setxy.h" +#endif +#ifndef DISABLE_HX8340B_8 + #include "tft_drivers/hx8340b/8/setxy.h" +#endif +#ifndef DISABLE_HX8340B_S + #include "tft_drivers/hx8340b/s/setxy.h" +#endif +#ifndef DISABLE_ST7735 + #include "tft_drivers/st7735/setxy.h" +#endif +#ifndef DISABLE_S1D19122 + #include "tft_drivers/s1d19122/setxy.h" +#endif +#ifndef DISABLE_PCF8833 + #include "tft_drivers/pcf8833/setxy.h" +#endif +#ifndef DISABLE_SSD1963_480 + #include "tft_drivers/ssd1963/480/setxy.h" +#endif +#ifndef DISABLE_SSD1963_800 + #include "tft_drivers/ssd1963/800/setxy.h" +#endif +#ifndef DISABLE_SSD1963_800_ALT + #include "tft_drivers/ssd1963/800alt/setxy.h" +#endif +#ifndef DISABLE_S6D1121 + #include "tft_drivers/s6d1121/setxy.h" +#endif +#ifndef DISABLE_ILI9320 + #include "tft_drivers/ili9320/setxy.h" +#endif +#ifndef DISABLE_ILI9481 + #include "tft_drivers/ili9481/setxy.h" +#endif +#ifndef DISABLE_S6D0164 + #include "tft_drivers/s6d0164/setxy.h" +#endif +#ifndef DISABLE_ST7735S + #include "tft_drivers/st7735s/setxy.h" +#endif +#ifndef DISABLE_ILI9341_S4P + #include "tft_drivers/ili9341/s4p/setxy.h" +#endif +#ifndef DISABLE_ILI9341_S5P + #include "tft_drivers/ili9341/s5p/setxy.h" +#endif +#ifndef DISABLE_R61581 + #include "tft_drivers/r61581/setxy.h" +#endif +#ifndef DISABLE_ILI9486 + #include "tft_drivers/ili9486/setxy.h" +#endif +#ifndef DISABLE_CPLD + #include "tft_drivers/cpld/setxy.h" +#endif +#ifndef DISABLE_HX8353C + #include "tft_drivers/hx8353c/setxy.h" +#endif + } +} + +void UTFT::clrXY() +{ + if (orient==PORTRAIT) + setXY(0,0,disp_x_size,disp_y_size); + else + setXY(0,0,disp_y_size,disp_x_size); +} + +void UTFT::drawRect(int x1, int y1, int x2, int y2) +{ + if (x1>x2) + { + swap(int, x1, x2); + } + if (y1>y2) + { + swap(int, y1, y2); + } + + drawHLine(x1, y1, x2-x1); + drawHLine(x1, y2, x2-x1); + drawVLine(x1, y1, y2-y1); + drawVLine(x2, y1, y2-y1); +} + +void UTFT::drawRoundRect(int x1, int y1, int x2, int y2) +{ + if (x1>x2) + { + swap(int, x1, x2); + } + if (y1>y2) + { + swap(int, y1, y2); + } + if ((x2-x1)>4 && (y2-y1)>4) + { + drawPixel(x1+1,y1+1); + drawPixel(x2-1,y1+1); + drawPixel(x1+1,y2-1); + drawPixel(x2-1,y2-1); + drawHLine(x1+2, y1, x2-x1-4); + drawHLine(x1+2, y2, x2-x1-4); + drawVLine(x1, y1+2, y2-y1-4); + drawVLine(x2, y1+2, y2-y1-4); + } +} + +void UTFT::fillRect(int x1, int y1, int x2, int y2) +{ + if (x1>x2) + { + swap(int, x1, x2); + } + if (y1>y2) + { + swap(int, y1, y2); + } + if (display_transfer_mode==16) + { + cbi(P_CS, B_CS); + setXY(x1, y1, x2, y2); + sbi(P_RS, B_RS); + _fast_fill_16(fch,fcl,((long(x2-x1)+1)*(long(y2-y1)+1))); + sbi(P_CS, B_CS); + } + else if ((display_transfer_mode==8) and (fch==fcl)) + { + cbi(P_CS, B_CS); + setXY(x1, y1, x2, y2); + sbi(P_RS, B_RS); + _fast_fill_8(fch,((long(x2-x1)+1)*(long(y2-y1)+1))); + sbi(P_CS, B_CS); + } + else + { + if (orient==PORTRAIT) + { + for (int i=0; i<((y2-y1)/2)+1; i++) + { + drawHLine(x1, y1+i, x2-x1); + drawHLine(x1, y2-i, x2-x1); + } + } + else + { + for (int i=0; i<((x2-x1)/2)+1; i++) + { + drawVLine(x1+i, y1, y2-y1); + drawVLine(x2-i, y1, y2-y1); + } + } + } +} + +void UTFT::fillRoundRect(int x1, int y1, int x2, int y2) +{ + if (x1>x2) + { + swap(int, x1, x2); + } + if (y1>y2) + { + swap(int, y1, y2); + } + + if ((x2-x1)>4 && (y2-y1)>4) + { + for (int i=0; i<((y2-y1)/2)+1; i++) + { + switch(i) + { + case 0: + drawHLine(x1+2, y1+i, x2-x1-4); + drawHLine(x1+2, y2-i, x2-x1-4); + break; + case 1: + drawHLine(x1+1, y1+i, x2-x1-2); + drawHLine(x1+1, y2-i, x2-x1-2); + break; + default: + drawHLine(x1, y1+i, x2-x1); + drawHLine(x1, y2-i, x2-x1); + } + } + } +} + +void UTFT::drawCircle(int x, int y, int radius) +{ + int f = 1 - radius; + int ddF_x = 1; + int ddF_y = -2 * radius; + int x1 = 0; + int y1 = radius; + + cbi(P_CS, B_CS); + setXY(x, y + radius, x, y + radius); + LCD_Write_DATA(fch,fcl); + setXY(x, y - radius, x, y - radius); + LCD_Write_DATA(fch,fcl); + setXY(x + radius, y, x + radius, y); + LCD_Write_DATA(fch,fcl); + setXY(x - radius, y, x - radius, y); + LCD_Write_DATA(fch,fcl); + + while(x1 < y1) + { + if(f >= 0) + { + y1--; + ddF_y += 2; + f += ddF_y; + } + x1++; + ddF_x += 2; + f += ddF_x; + setXY(x + x1, y + y1, x + x1, y + y1); + LCD_Write_DATA(fch,fcl); + setXY(x - x1, y + y1, x - x1, y + y1); + LCD_Write_DATA(fch,fcl); + setXY(x + x1, y - y1, x + x1, y - y1); + LCD_Write_DATA(fch,fcl); + setXY(x - x1, y - y1, x - x1, y - y1); + LCD_Write_DATA(fch,fcl); + setXY(x + y1, y + x1, x + y1, y + x1); + LCD_Write_DATA(fch,fcl); + setXY(x - y1, y + x1, x - y1, y + x1); + LCD_Write_DATA(fch,fcl); + setXY(x + y1, y - x1, x + y1, y - x1); + LCD_Write_DATA(fch,fcl); + setXY(x - y1, y - x1, x - y1, y - x1); + LCD_Write_DATA(fch,fcl); + } + sbi(P_CS, B_CS); + clrXY(); +} + +void UTFT::fillCircle(int x, int y, int radius) +{ + for(int y1=-radius; y1<=0; y1++) + for(int x1=-radius; x1<=0; x1++) + if(x1*x1+y1*y1 <= radius*radius) + { + drawHLine(x+x1, y+y1, 2*(-x1)); + drawHLine(x+x1, y-y1, 2*(-x1)); + break; + } +} + +void UTFT::clrScr() +{ + long i; + + cbi(P_CS, B_CS); + clrXY(); + if (display_transfer_mode!=1) + sbi(P_RS, B_RS); + if (display_transfer_mode==16) + _fast_fill_16(0,0,((disp_x_size+1)*(disp_y_size+1))); + else if (display_transfer_mode==8) + _fast_fill_8(0,((disp_x_size+1)*(disp_y_size+1))); + else + { + for (i=0; i<((disp_x_size+1)*(disp_y_size+1)); i++) + { + if (display_transfer_mode!=1) + LCD_Writ_Bus(0,0,display_transfer_mode); + else + { + LCD_Writ_Bus(1,0,display_transfer_mode); + LCD_Writ_Bus(1,0,display_transfer_mode); + } + } + } + sbi(P_CS, B_CS); +} + +void UTFT::fillScr(byte r, byte g, byte b) +{ + word color = ((r&248)<<8 | (g&252)<<3 | (b&248)>>3); + fillScr(color); +} + +void UTFT::fillScr(word color) +{ + long i; + char ch, cl; + + ch=byte(color>>8); + cl=byte(color & 0xFF); + + cbi(P_CS, B_CS); + clrXY(); + if (display_transfer_mode!=1) + sbi(P_RS, B_RS); + if (display_transfer_mode==16) + _fast_fill_16(ch,cl,((disp_x_size+1)*(disp_y_size+1))); + else if ((display_transfer_mode==8) and (ch==cl)) + _fast_fill_8(ch,((disp_x_size+1)*(disp_y_size+1))); + else + { + for (i=0; i<((disp_x_size+1)*(disp_y_size+1)); i++) + { + if (display_transfer_mode!=1) + LCD_Writ_Bus(ch,cl,display_transfer_mode); + else + { + LCD_Writ_Bus(1,ch,display_transfer_mode); + LCD_Writ_Bus(1,cl,display_transfer_mode); + } + } + } + sbi(P_CS, B_CS); +} + +void UTFT::setColor(byte r, byte g, byte b) +{ + fch=((r&248)|g>>5); + fcl=((g&28)<<3|b>>3); +} + +void UTFT::setColor(word color) +{ + fch=byte(color>>8); + fcl=byte(color & 0xFF); +} + +word UTFT::getColor() +{ + return (fch<<8) | fcl; +} + +void UTFT::setBackColor(byte r, byte g, byte b) +{ + bch=((r&248)|g>>5); + bcl=((g&28)<<3|b>>3); + _transparent=false; +} + +void UTFT::setBackColor(uint32_t color) +{ + if (color==VGA_TRANSPARENT) + _transparent=true; + else + { + bch=byte(color>>8); + bcl=byte(color & 0xFF); + _transparent=false; + } +} + +word UTFT::getBackColor() +{ + return (bch<<8) | bcl; +} + +void UTFT::setPixel(word color) +{ + LCD_Write_DATA((color>>8),(color&0xFF)); // rrrrrggggggbbbbb +} + +void UTFT::drawPixel(int x, int y) +{ + cbi(P_CS, B_CS); + setXY(x, y, x, y); + setPixel((fch<<8)|fcl); + sbi(P_CS, B_CS); + clrXY(); +} + +void UTFT::drawLine(int x1, int y1, int x2, int y2) +{ + if (y1==y2) + drawHLine(x1, y1, x2-x1); + else if (x1==x2) + drawVLine(x1, y1, y2-y1); + else + { + unsigned int dx = (x2 > x1 ? x2 - x1 : x1 - x2); + short xstep = x2 > x1 ? 1 : -1; + unsigned int dy = (y2 > y1 ? y2 - y1 : y1 - y2); + short ystep = y2 > y1 ? 1 : -1; + int col = x1, row = y1; + + cbi(P_CS, B_CS); + if (dx < dy) + { + int t = - (dy >> 1); + while (true) + { + setXY (col, row, col, row); + LCD_Write_DATA (fch, fcl); + if (row == y2) + return; + row += ystep; + t += dx; + if (t >= 0) + { + col += xstep; + t -= dy; + } + } + } + else + { + int t = - (dx >> 1); + while (true) + { + setXY (col, row, col, row); + LCD_Write_DATA (fch, fcl); + if (col == x2) + return; + col += xstep; + t += dy; + if (t >= 0) + { + row += ystep; + t -= dx; + } + } + } + sbi(P_CS, B_CS); + } + clrXY(); +} + +void UTFT::drawHLine(int x, int y, int l) +{ + if (l<0) + { + l = -l; + x -= l; + } + cbi(P_CS, B_CS); + setXY(x, y, x+l, y); + if (display_transfer_mode == 16) + { + sbi(P_RS, B_RS); + _fast_fill_16(fch,fcl,l); + } + else if ((display_transfer_mode==8) and (fch==fcl)) + { + sbi(P_RS, B_RS); + _fast_fill_8(fch,l); + } + else + { + for (int i=0; i=0; zz--) + { + ch=pgm_read_byte(&cfont.font[temp+zz]); + for(i=0;i<8;i++) + { + if((ch&(1<0) + { + buf[c]=48+(num % 10); + c++; + num=(num-(num % 10))/10; + } + buf[c]=0; + + if (neg) + { + st[0]=45; + } + + if (length>(c+neg)) + { + for (int i=0; i<(length-c-neg); i++) + { + st[i+neg]=filler; + f++; + } + } + + for (int i=0; i5) + dec=5; + + if (num<0) + neg = true; + + _convert_float(st, num, length, dec); + + if (divider != '.') + { + for (unsigned int i=0; i>8,col & 0xff); + } + sbi(P_CS, B_CS); + } + else + { + cbi(P_CS, B_CS); + for (ty=0; ty=0; tx--) + { + col=pgm_read_word(&data[(ty*sx)+tx]); + LCD_Write_DATA(col>>8,col & 0xff); + } + } + sbi(P_CS, B_CS); + } + } + else + { + if (orient==PORTRAIT) + { + cbi(P_CS, B_CS); + for (ty=0; ty>8,col & 0xff); + } + } + sbi(P_CS, B_CS); + } + else + { + cbi(P_CS, B_CS); + for (ty=0; ty=0; tx--) + { + col=pgm_read_word(&data[(ty*sx)+tx]); + for (tsx=0; tsx>8,col & 0xff); + } + } + } + sbi(P_CS, B_CS); + } + } + clrXY(); +} + +void UTFT::drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int deg, int rox, int roy) +{ + unsigned int col; + int tx, ty, newx, newy; + double radian; + radian=deg*0.0175; + + if (deg==0) + drawBitmap(x, y, sx, sy, data); + else + { + cbi(P_CS, B_CS); + for (ty=0; ty>8,col & 0xff); + } + sbi(P_CS, B_CS); + } + clrXY(); +} + +void UTFT::lcdOff() +{ + cbi(P_CS, B_CS); + switch (display_model) + { + case PCF8833: + LCD_Write_COM(0x28); + break; + case CPLD: + LCD_Write_COM_DATA(0x01,0x0000); + LCD_Write_COM(0x0F); + break; + } + sbi(P_CS, B_CS); +} + +void UTFT::lcdOn() +{ + cbi(P_CS, B_CS); + switch (display_model) + { + case PCF8833: + LCD_Write_COM(0x29); + break; + case CPLD: + LCD_Write_COM_DATA(0x01,0x0010); + LCD_Write_COM(0x0F); + break; + } + sbi(P_CS, B_CS); +} + +void UTFT::setContrast(char c) +{ + cbi(P_CS, B_CS); + switch (display_model) + { + case PCF8833: + if (c>64) c=64; + LCD_Write_COM(0x25); + LCD_Write_DATA(c); + break; + } + sbi(P_CS, B_CS); +} + +int UTFT::getDisplayXSize() +{ + if (orient==PORTRAIT) + return disp_x_size+1; + else + return disp_y_size+1; +} + +int UTFT::getDisplayYSize() +{ + if (orient==PORTRAIT) + return disp_y_size+1; + else + return disp_x_size+1; +} + +void UTFT::setBrightness(byte br) +{ + cbi(P_CS, B_CS); + switch (display_model) + { + case CPLD: + if (br>16) br=16; + LCD_Write_COM_DATA(0x01,br); + LCD_Write_COM(0x0F); + break; + } + sbi(P_CS, B_CS); +} + +void UTFT::setDisplayPage(byte page) +{ + cbi(P_CS, B_CS); + switch (display_model) + { + case CPLD: + if (page>7) page=7; + LCD_Write_COM_DATA(0x04,page); + LCD_Write_COM(0x0F); + break; + } + sbi(P_CS, B_CS); +} + +void UTFT::setWritePage(byte page) +{ + cbi(P_CS, B_CS); + switch (display_model) + { + case CPLD: + if (page>7) page=7; + LCD_Write_COM_DATA(0x05,page); + LCD_Write_COM(0x0F); + break; + } + sbi(P_CS, B_CS); +} diff --git a/libraries/UTFT/UTFT.h b/libraries/UTFT/UTFT.h new file mode 100644 index 0000000..c863311 --- /dev/null +++ b/libraries/UTFT/UTFT.h @@ -0,0 +1,275 @@ +/* + UTFT.h - Arduino/chipKit library support for Color TFT LCD Boards + Copyright (C)2010-2014 Henning Karlsen. All right reserved + + This library is the continuation of my ITDB02_Graph, ITDB02_Graph16 + and RGB_GLCD libraries for Arduino and chipKit. As the number of + supported display modules and controllers started to increase I felt + it was time to make a single, universal library as it will be much + easier to maintain in the future. + + Basic functionality of this library was origianlly based on the + demo-code provided by ITead studio (for the ITDB02 modules) and + NKC Electronics (for the RGB GLCD module/shield). + + This library supports a number of 8bit, 16bit and serial graphic + displays, and will work with both Arduino and chipKit boards. For a + full list of tested display modules and controllers, see the + document UTFT_Supported_display_modules_&_controllers.pdf. + + When using 8bit and 16bit display modules there are some + requirements you must adhere to. These requirements can be found + in the document UTFT_Requirements.pdf. + There are no special requirements when using serial displays. + + You can always find the latest version of the library at + http://electronics.henningkarlsen.com/ + + If you make any modifications or improvements to the code, I would + appreciate that you share the code with me so that I might include + it in the next release. I can be contacted through + http://electronics.henningkarlsen.com/contact.php. + + This library is free software; you can redistribute it and/or + modify it under the terms of the CC BY-NC-SA 3.0 license. + Please see the included documents for further information. + + Commercial use of this library requires you to buy a license that + will allow commercial use. This includes using the library, + modified or not, as a tool to sell products. + + The license applies to all part of the library including the + examples and tools supplied with the library. +*/ + +#ifndef UTFT_h +#define UTFT_h + +#define UTFT_VERSION 278 + +#define LEFT 0 +#define RIGHT 9999 +#define CENTER 9998 + +#define PORTRAIT 0 +#define LANDSCAPE 1 + +#define HX8347A 0 +#define ILI9327 1 +#define SSD1289 2 +#define ILI9325C 3 +#define ILI9325D_8 4 +#define ILI9325D_16 5 +#define HX8340B_8 6 +#define HX8340B_S 7 +#define HX8352A 8 +#define ST7735 9 +#define PCF8833 10 +#define S1D19122 11 +#define SSD1963_480 12 +#define SSD1963_800 13 +#define S6D1121_8 14 +#define S6D1121_16 15 +#define SSD1289LATCHED 16 +#define ILI9320_8 17 +#define ILI9320_16 18 +#define SSD1289_8 19 +#define SSD1963_800ALT 20 +#define ILI9481 21 +#define ILI9325D_16ALT 22 +#define S6D0164 23 +#define ST7735S 24 +#define ILI9341_S5P 25 +#define ILI9341_S4P 26 +#define R61581 27 +#define ILI9486 28 +#define CPLD 29 +#define HX8353C 30 + +#define ITDB32 0 // HX8347-A (16bit) +#define ITDB32WC 1 // ILI9327 (16bit) +#define TFT01_32W 1 // ILI9327 (16bit) +#define ITDB32S 2 // SSD1289 (16bit) +#define TFT01_32 2 // SSD1289 (16bit) +#define CTE32 2 // SSD1289 (16bit) +#define GEEE32 2 // SSD1289 (16bit) +#define ITDB24 3 // ILI9325C (8bit) +#define ITDB24D 4 // ILI9325D (8bit) +#define ITDB24DWOT 4 // ILI9325D (8bit) +#define ITDB28 4 // ILI9325D (8bit) +#define TFT01_24_8 4 // ILI9325D (8bit) +#define DMTFT24104 4 // ILI9325D (8bit) +#define DMTFT28103 4 // ILI9325D (8bit) +#define TFT01_24_16 5 // ILI9325D (16bit) +#define ITDB22 6 // HX8340-B (8bit) +#define GEEE22 6 // HX8340-B (8bit) +#define ITDB22SP 7 // HX8340-B (Serial 4Pin) +#define ITDB32WD 8 // HX8352-A (16bit) +#define TFT01_32WD 8 // HX8352-A (16bit) +#define CTE32W 8 // HX8352-A (16bit) +#define ITDB18SP 9 // ST7735 (Serial 5Pin) +#define LPH9135 10 // PCF8833 (Serial 5Pin) +#define ITDB25H 11 // S1D19122 (16bit) +#define ITDB43 12 // SSD1963 (16bit) 480x272 +#define TFT01_43 12 // SSD1963 (16bit) 480x272 +#define ITDB50 13 // SSD1963 (16bit) 800x480 +#define TFT01_50 13 // SSD1963 (16bit) 800x480 +#define CTE50 13 // SSD1963 (16bit) 800x480 +#define EHOUSE50 13 // SSD1963 (16bit) 800x480 +#define ITDB24E_8 14 // S6D1121 (8bit) +#define TFT01_24R2 14 // S6D1121 (8bit) +#define ITDB24E_16 15 // S6D1121 (16bit) +#define INFINIT32 16 // SSD1289 (Latched 16bit) -- Legacy, will be removed later +#define ELEE32_REVA 16 // SSD1289 (Latched 16bit) +#define GEEE24 17 // ILI9320 (8bit) +#define GEEE28 18 // ILI9320 (16bit) +#define ELEE32_REVB 19 // SSD1289 (8bit) +#define TFT01_70 20 // SSD1963 (16bit) 800x480 Alternative Init +#define CTE70 20 // SSD1963 (16bit) 800x480 Alternative Init +#define EHOUSE70 20 // SSD1963 (16bit) 800x480 Alternative Init +#define CTE32HR 21 // ILI9481 (16bit) +#define CTE28 22 // ILI9325D (16bit) Alternative Init +#define TFT01_28 22 // ILI9325D (16bit) Alternative Init +#define CTE22 23 // S6D0164 (8bit) +#define TFT01_22 23 // S6D0164 (8bit) +#define DMTFT22102 23 // S6D0164 (8bit) +#define TFT01_18SP 24 // ST7735S (Serial 5Pin) +#define TFT01_22SP 25 // ILI9341 (Serial 5Pin) +#define DMTFT28105 25 // ILI9341 (Serial 5Pin) +#define MI0283QT9 26 // ILI9341 (Serial 4Pin) +#define CTE35IPS 27 // R61581 (16bit) +#define CTE40 28 // ILI9486 (16bit) +#define EHOUSE50CPLD 29 // CPLD (16bit) +#define CTE50CPLD 29 // CPLD (16bit) +#define CTE70CPLD 29 // CPLD (16bit) +#define DMTFT18101 30 // HX8353C (Serial 5Pin) + + +#define SERIAL_4PIN 4 +#define SERIAL_5PIN 5 +#define LATCHED_16 17 + +#define NOTINUSE 255 + +//********************************* +// COLORS +//********************************* +// VGA color palette +#define VGA_BLACK 0x0000 +#define VGA_WHITE 0xFFFF +#define VGA_RED 0xF800 +#define VGA_GREEN 0x0400 +#define VGA_BLUE 0x001F +#define VGA_SILVER 0xC618 +#define VGA_GRAY 0x8410 +#define VGA_MAROON 0x8000 +#define VGA_YELLOW 0xFFE0 +#define VGA_OLIVE 0x8400 +#define VGA_LIME 0x07E0 +#define VGA_AQUA 0x07FF +#define VGA_TEAL 0x0410 +#define VGA_NAVY 0x0010 +#define VGA_FUCHSIA 0xF81F +#define VGA_PURPLE 0x8010 +#define VGA_TRANSPARENT 0xFFFFFFFF + +#if defined(__AVR__) + #include "Arduino.h" + #include "hardware/avr/HW_AVR_defines.h" +#elif defined(__PIC32MX__) + #include "WProgram.h" + #include "hardware/pic32/HW_PIC32_defines.h" +#elif defined(__arm__) + #include "Arduino.h" + #include "hardware/arm/HW_ARM_defines.h" +#endif + +struct _current_font +{ + uint8_t* font; + uint8_t x_size; + uint8_t y_size; + uint8_t offset; + uint8_t numchars; +}; + +class UTFT +{ + public: + UTFT(); + UTFT(byte model, int RS, int WR, int CS, int RST, int SER=0); + void InitLCD(byte orientation=LANDSCAPE); + void clrScr(); + void drawPixel(int x, int y); + void drawLine(int x1, int y1, int x2, int y2); + void fillScr(byte r, byte g, byte b); + void fillScr(word color); + void drawRect(int x1, int y1, int x2, int y2); + void drawRoundRect(int x1, int y1, int x2, int y2); + void fillRect(int x1, int y1, int x2, int y2); + void fillRoundRect(int x1, int y1, int x2, int y2); + void drawCircle(int x, int y, int radius); + void fillCircle(int x, int y, int radius); + void setColor(byte r, byte g, byte b); + void setColor(word color); + word getColor(); + void setBackColor(byte r, byte g, byte b); + void setBackColor(uint32_t color); + word getBackColor(); + void print(char *st, int x, int y, int deg=0); + void print(String st, int x, int y, int deg=0); + void printNumI(long num, int x, int y, int length=0, char filler=' '); + void printNumF(double num, byte dec, int x, int y, char divider='.', int length=0, char filler=' '); + void setFont(uint8_t* font); + uint8_t* getFont(); + uint8_t getFontXsize(); + uint8_t getFontYsize(); + void drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int scale=1); + void drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int deg, int rox, int roy); + void lcdOff(); + void lcdOn(); + void setContrast(char c); + int getDisplayXSize(); + int getDisplayYSize(); + void setBrightness(byte br); + void setDisplayPage(byte page); + void setWritePage(byte page); + +/* + The functions and variables below should not normally be used. + They have been left publicly available for use in add-on libraries + that might need access to the lower level functions of UTFT. + + Please note that these functions and variables are not documented + and I do not provide support on how to use them. +*/ + byte fch, fcl, bch, bcl; + byte orient; + long disp_x_size, disp_y_size; + byte display_model, display_transfer_mode, display_serial_mode; + regtype *P_RS, *P_WR, *P_CS, *P_RST, *P_SDA, *P_SCL, *P_ALE; + regsize B_RS, B_WR, B_CS, B_RST, B_SDA, B_SCL, B_ALE; + byte __p1, __p2, __p3, __p4, __p5; + _current_font cfont; + boolean _transparent; + + void LCD_Writ_Bus(char VH,char VL, byte mode); + void LCD_Write_COM(char VL); + void LCD_Write_DATA(char VH,char VL); + void LCD_Write_DATA(char VL); + void LCD_Write_COM_DATA(char com1,int dat1); + void _hw_special_init(); + void setPixel(word color); + void drawHLine(int x, int y, int l); + void drawVLine(int x, int y, int l); + void printChar(byte c, int x, int y); + void setXY(word x1, word y1, word x2, word y2); + void clrXY(); + void rotateChar(byte c, int x, int y, int pos, int deg); + void _set_direction_registers(byte mode); + void _fast_fill_16(int ch, int cl, long pix); + void _fast_fill_8(int ch, long pix); + void _convert_float(char *buf, double num, int width, byte prec); +}; + +#endif \ No newline at end of file diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/UTFT_Bitmap.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/UTFT_Bitmap.ino new file mode 100644 index 0000000..1f3ef33 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/UTFT_Bitmap.ino @@ -0,0 +1,66 @@ +// UTFT_Bitmap (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This demo was made to work on the 320x240 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +extern unsigned short info[0x400]; +extern unsigned short icon[0x400]; +extern unsigned short tux[0x400]; + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(255, 255, 255); + myGLCD.print(" *** A 10 by 7 grid of a 32x32 icon *** ", CENTER, 228); + for (int x=0; x<10; x++) + for (int y=0; y<7; y++) + myGLCD.drawBitmap (x*32, y*32, 32, 32, info); + + delay(5000); + + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(255, 255, 255); + myGLCD.print(" Two different icons in scale 1 to 4 ", CENTER, 228); + int x=0; + for (int s=0; s<4; s++) + { + x+=(s*32); + myGLCD.drawBitmap (x, 0, 32, 32, tux, s+1); + } + x=0; + for (int s=4; s>0; s--) + { + myGLCD.drawBitmap (x, 224-(s*32), 32, 32, icon, s); + x+=(s*32); + } + + delay(5000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/icon.c b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/icon.c new file mode 100644 index 0000000..9cb97a1 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/icon.c @@ -0,0 +1,71 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: taskmgr.png +// Time generated: 11.10.2010 22:51:23 +// Size : 2 048 Bytes + +const unsigned short icon[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0xCE79, 0xBDD7, 0xAD75, // 0x0010 (16) +0xAD55, 0xAD75, 0xBDF7, 0xD6BA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC638, 0x9492, 0x8C51, 0x9492, 0xA514, 0xA534, // 0x0030 (48) +0xA534, 0xA534, 0x9CF3, 0x8C71, 0x8430, 0x9CD3, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0x8410, 0x9492, 0xB5B6, 0xC618, 0xBDD7, 0xAD75, 0xA514, // 0x0050 (80) +0xA514, 0xA4F4, 0xAD55, 0xB5B6, 0xBDD7, 0xAD55, 0x8430, 0x8C71, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x9CD3, 0x8430, 0xBDF7, 0xC618, 0xAD75, 0x94F2, 0x8CF1, 0x84B0, 0x8CD1, // 0x0070 (112) +0x9612, 0x8CB1, 0x7C6F, 0x7C8F, 0x8490, 0xA533, 0xBDF7, 0xB596, 0x7BEF, 0xB596, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8430, 0x9CF3, 0xCE39, 0xA514, 0x94B2, 0x9E93, 0x94F2, 0x8CD1, 0x8CB1, 0x9D12, // 0x0090 (144) +0x9F74, 0x9D52, 0x8450, 0x7C8F, 0x73AE, 0x740E, 0x73CE, 0x9CD3, 0xC638, 0x8C51, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x8430, 0xA534, 0xBDF7, 0x8CB1, 0x8C31, 0x9DB3, 0xA735, 0x9D13, 0x8CB1, 0x8C71, 0x9D13, // 0x00B0 (176) +0xB756, 0xA5D4, 0x8C71, 0x8490, 0x8390, 0x7C70, 0x73EE, 0x6B4D, 0x8450, 0xBDF7, 0x8C71, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x94B2, 0x9CF3, 0xBDD7, 0x8490, 0x8CF1, 0x9D72, 0xA694, 0xAE94, 0x9DD3, 0xA593, 0xA553, 0x9592, // 0x00D0 (208) +0x9672, 0x75CE, 0x5BAA, 0x64EB, 0x5D8C, 0x5BCA, 0x4B69, 0x634C, 0x748D, 0x7C4F, 0xBE18, 0x8430, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xC618, 0x8410, 0xBDF7, 0x8410, 0x83F0, 0x94F2, 0x9613, 0x9D13, 0xAE55, 0x9D12, 0x750E, 0x55CB, 0x4BC8, // 0x00F0 (240) +0x4447, 0x3BC6, 0x4B67, 0x44E8, 0x3CE8, 0x3325, 0x20E2, 0x2B45, 0x43E7, 0x3946, 0x732D, 0xC5F8, 0x7BCF, 0xE71C, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xF7BE, 0x7BEF, 0xBDB6, 0x9533, 0x8D71, 0x9552, 0x9E73, 0x9DD3, 0x94B2, 0x6D6D, 0x4BA8, 0x44A8, 0x55EA, 0x5D2A, // 0x0110 (272) +0x43E7, 0x4327, 0x46CA, 0x4B87, 0x42C6, 0x4E0A, 0x4D09, 0x4468, 0x4548, 0x3386, 0x2B25, 0x7C6F, 0xAD35, 0x9492, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFDF, 0xFFFF, 0xBDD7, 0x8C71, 0xAD75, 0x8CF0, 0x8D71, 0x8D51, 0x9DF3, 0x740E, 0x21C4, 0x33E5, 0x558A, 0x554A, 0x650A, 0x566B, // 0x0130 (304) +0x43E7, 0x21C3, 0x3345, 0x2283, 0x1962, 0x3C87, 0x3386, 0x2163, 0x3345, 0x3346, 0x33A6, 0x32C6, 0x9CB3, 0x7BEF, 0xDEDB, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0x8430, 0xAD75, 0x8C31, 0x7C0F, 0x7BCF, 0x83F0, 0x636B, 0x0000, 0x0000, 0x4387, 0x462A, 0x4B27, 0x4B88, 0x4E8B, // 0x0150 (336) +0x42E6, 0x0000, 0x0020, 0x0100, 0x0000, 0x1121, 0x0040, 0x0000, 0x0941, 0x0000, 0x0020, 0x00E0, 0x5AAB, 0x94B2, 0x9CD3, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xE71C, 0x8410, 0xB596, 0x7BEF, 0x7C6F, 0x84B0, 0x5B6B, 0x09E1, 0x0901, 0x1161, 0x3C06, 0x3D89, 0x32C5, 0x43E7, 0x470B, // 0x0170 (368) +0x4BC7, 0x0961, 0x11E2, 0x1282, 0x0961, 0x1262, 0x09E2, 0x0961, 0x12A2, 0x0961, 0x09C2, 0x0A01, 0x29E5, 0xA514, 0x7BEF, 0xFFDF, // 0x0180 (384) +0xFFFF, 0xBDD7, 0x9472, 0xA514, 0x6B4D, 0x7C6F, 0x634C, 0x0040, 0x0981, 0x0060, 0x00E0, 0x11E2, 0x10A1, 0x09C1, 0x19E3, 0x2B25, // 0x0190 (400) +0x22A3, 0x0060, 0x0120, 0x09E1, 0x0060, 0x09E1, 0x0120, 0x0060, 0x0A21, 0x0060, 0x0100, 0x01A0, 0x0040, 0x9CD3, 0x7BEF, 0xDEDB, // 0x01A0 (416) +0xFFFF, 0xA514, 0x9CF3, 0xB596, 0x73AE, 0x7C0F, 0x2945, 0x10A2, 0x2184, 0x18C3, 0x1923, 0x2184, 0x18C3, 0x21A4, 0x2964, 0x2905, // 0x01B0 (432) +0x2A25, 0x2104, 0x2965, 0x2A05, 0x2104, 0x2A05, 0x2985, 0x2104, 0x2A25, 0x2104, 0x2164, 0x29C4, 0x3166, 0xB5B6, 0x8410, 0xC618, // 0x01C0 (448) +0xFFFF, 0x9492, 0xA514, 0xDEDB, 0xC618, 0xA514, 0x8C51, 0x94B2, 0x9CB3, 0x9CF3, 0xA514, 0xA534, 0xAD75, 0xAD75, 0xB596, 0xB5D6, // 0x01D0 (464) +0xBDB7, 0xBDF7, 0xBDF7, 0xBDF7, 0xC618, 0xC5F8, 0xC5F8, 0xBDF7, 0xBDD7, 0xBDD7, 0xB5B6, 0xB596, 0xC638, 0xDEFB, 0x8430, 0xB596, // 0x01E0 (480) +0xFFFF, 0x8C51, 0x9CF3, 0xE73C, 0xDEFB, 0xD69A, 0xD6BA, 0xD6BA, 0xDEDB, 0xDEDB, 0xDEFB, 0xDF1B, 0xE71C, 0xE73C, 0xE73C, 0xE73C, // 0x01F0 (496) +0xEF5D, 0xEF5D, 0xEF5D, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xDEFB, 0xE71C, 0x8C51, 0xAD75, // 0x0200 (512) +0xFFFF, 0x8C71, 0x9CD3, 0xDEFB, 0xAD75, 0x9492, 0x9CD3, 0xA4F3, 0xA514, 0xAD55, 0xAD75, 0xB596, 0xBDB6, 0xBDD7, 0xC5F7, 0xC618, // 0x0210 (528) +0xC638, 0xCE59, 0xCE59, 0xCE79, 0xD679, 0xD679, 0xCE79, 0xCE59, 0xCE59, 0xC638, 0xC618, 0xBDF7, 0xCE79, 0xE71C, 0x8C51, 0xB596, // 0x0220 (544) +0xFFFF, 0x9CD3, 0x9492, 0xAD55, 0x2965, 0x2104, 0x2124, 0x2145, 0x1945, 0x2165, 0x2165, 0x2186, 0x2186, 0x29A6, 0x29A6, 0x31C7, // 0x0230 (560) +0x39C7, 0x31E7, 0x31E7, 0x31E7, 0x3208, 0x3208, 0x31E7, 0x31E7, 0x29E7, 0x31C7, 0x39C7, 0x31A6, 0x4A49, 0xBDF7, 0x8C51, 0xBDF7, // 0x0240 (576) +0xFFFF, 0xB5B6, 0x8430, 0x7BEF, 0x0000, 0x0000, 0x0000, 0x2000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3800, 0x2000, // 0x0250 (592) +0x0000, 0x3000, 0x3800, 0x3000, 0x3800, 0x3800, 0x3800, 0x3000, 0x3800, 0x0800, 0x0000, 0x0000, 0x0000, 0xA514, 0x8430, 0xD6BA, // 0x0260 (608) +0xFFFF, 0xDEDB, 0x7BCF, 0x8430, 0x0020, 0x0000, 0x0000, 0x8000, 0xC800, 0xC000, 0xC800, 0xC820, 0xC820, 0xC820, 0xD020, 0x9800, // 0x0270 (624) +0x0000, 0xB820, 0xD020, 0xD020, 0xD020, 0xD020, 0xD020, 0xC820, 0xD020, 0x4800, 0x0000, 0x0000, 0x2144, 0xAD75, 0x8410, 0xF7BE, // 0x0280 (640) +0xFFFF, 0xFFFF, 0x7BEF, 0x8C71, 0x2945, 0x0000, 0x0000, 0x6800, 0xA800, 0xA800, 0xA800, 0xA800, 0xA800, 0xA800, 0xB000, 0x8000, // 0x0290 (656) +0x0000, 0x9800, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0x4000, 0x0000, 0x0000, 0x632C, 0xA534, 0x94B2, 0xFFFF, // 0x02A0 (672) +0xFFDF, 0xFFFF, 0xAD75, 0x73AE, 0x632C, 0x0000, 0x0000, 0x6920, 0xA9E0, 0xA1C0, 0xA9E0, 0xA9E0, 0xA9E0, 0xA9E0, 0xA9E0, 0x7960, // 0x02B0 (688) +0x0000, 0x99C0, 0xB200, 0xA9E0, 0xB200, 0xB200, 0xB1E0, 0xA9E0, 0xB200, 0x40C0, 0x0000, 0x1082, 0xAD75, 0x8410, 0xD69A, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xF79E, 0x630C, 0x8C51, 0x2965, 0x0000, 0x7400, 0xB620, 0xAE00, 0xB620, 0xB640, 0xB640, 0xB620, 0xB660, 0x84A0, // 0x02D0 (720) +0x0000, 0xA5A0, 0xBE60, 0xB660, 0xBE60, 0xBE60, 0xB660, 0xB640, 0xBE80, 0x4260, 0x0000, 0x6B6D, 0xAD75, 0x8430, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFDF, 0xFFFF, 0xB5B6, 0x632C, 0x8410, 0x0021, 0x7360, 0xBD40, 0xB520, 0xBD40, 0xBD60, 0xBD60, 0xBD40, 0xC580, 0x8C00, // 0x02F0 (752) +0x0000, 0xACE0, 0xC580, 0xC580, 0xC580, 0xC580, 0xC580, 0xBD60, 0xC5A0, 0x39C0, 0x2126, 0xBDF7, 0x73AE, 0xD6BA, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BEF, 0x7BEF, 0x630D, 0x4AE1, 0x6D21, 0x6D01, 0x6D21, 0x6D41, 0x6D41, 0x6D41, 0x6D61, 0x53E1, // 0x0310 (784) +0x0000, 0x64C1, 0x7562, 0x6D62, 0x6D62, 0x6D62, 0x6D62, 0x6D42, 0x6D41, 0x4263, 0xA515, 0x8C51, 0xA534, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x6B4D, 0x8410, 0x636E, 0x04A6, 0x05E5, 0x05C5, 0x0585, 0x0585, 0x0586, 0x05A6, 0x0424, // 0x0330 (816) +0x0000, 0x0505, 0x05C6, 0x05A6, 0x05A6, 0x05C7, 0x0606, 0x0606, 0x1CE9, 0xA535, 0x9492, 0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x6B4D, 0x83EF, 0x9411, 0x3A47, 0x0403, 0x0584, 0x05A4, 0x0585, 0x0585, 0x0404, // 0x0350 (848) +0x0000, 0x04E5, 0x05A5, 0x05A5, 0x05C5, 0x0584, 0x1405, 0x634B, 0xBD76, 0x8C51, 0x8C51, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8410, 0x6B6D, 0x9CB3, 0x7C6F, 0x3CA9, 0x0BE4, 0x0443, 0x0504, 0x03C2, // 0x0370 (880) +0x0000, 0x0483, 0x0504, 0x0444, 0x1426, 0x552D, 0xA554, 0xB576, 0x73CE, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB5B6, 0x6B4D, 0x7BAF, 0x9432, 0x8BD1, 0x6BCE, 0x4C6B, 0x3C09, // 0x0390 (912) +0x3186, 0x3C8A, 0x5C8C, 0x8430, 0xA493, 0xACD4, 0x8410, 0x7BEF, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xAD75, 0x7BEF, 0x73AE, 0x83F0, 0x8C11, 0x9431, // 0x03B0 (944) +0x9492, 0x9452, 0x9432, 0x8430, 0x7BEF, 0x8450, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0xBDD7, 0xA534, 0x94D3, // 0x03D0 (976) +0x94B2, 0x9CF3, 0xA554, 0xC618, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/info.c b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/info.c new file mode 100644 index 0000000..312bee1 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/info.c @@ -0,0 +1,71 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: info.png +// Time generated: 11.10.2010 22:27:55 +// Size : 2 048 Bytes + +const unsigned short info[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF9F, 0xC69D, 0x95BB, 0x7D1A, 0x6CB9, // 0x0030 (48) +0x6499, 0x74F9, 0x8D7A, 0xB63C, 0xE73E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAE1C, 0x4C18, 0x2B56, 0x3397, 0x4C38, 0x64B9, 0x751A, // 0x0050 (80) +0x7D3A, 0x6CD9, 0x5458, 0x3BD7, 0x2B56, 0x3BB7, 0x855A, 0xE77E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA5FB, 0x2B56, 0x2B77, 0x751A, 0xB67C, 0xD73E, 0xE75E, 0xE77E, 0xE77E, // 0x0070 (112) +0xE77E, 0xE77E, 0xE75E, 0xDF3E, 0xC6DD, 0x8D9B, 0x43D7, 0x1B16, 0x74D9, 0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF9F, 0x4C18, 0x1AF6, 0x855A, 0xCEFE, 0xD71E, 0xCEFD, 0xC6DD, 0xC6BD, 0xC6BD, 0xBEBD, // 0x0090 (144) +0xC6BD, 0xBEBD, 0xC6BD, 0xC6DD, 0xC6DD, 0xD71E, 0xD71E, 0xA61C, 0x33B7, 0x2316, 0xBE7C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF3E, 0x2336, 0x3BD7, 0xBE9D, 0xC6DD, 0xBE9D, 0xBE9D, 0xBE9D, 0xBEBD, 0xBE9D, 0xCEFD, 0xEF9F, // 0x00B0 (176) +0xEF9F, 0xD73E, 0xBE9D, 0xBEBD, 0xBE9D, 0xBE9D, 0xB69D, 0xC6BD, 0xCEDD, 0x6CFA, 0x0295, 0x9DBB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xE75E, 0x1AF6, 0x4C58, 0xBEBD, 0xB67D, 0xAE5C, 0xB67D, 0xB67D, 0xB69D, 0xB67D, 0xBEBD, 0xF7DF, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xFFFF, 0xCF1E, 0xB67D, 0xB67D, 0xB67D, 0xB67D, 0xAE5C, 0xAE5C, 0xC6BD, 0x857B, 0x0295, 0xA5DB, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFDF, 0x3BB7, 0x33D8, 0xB67D, 0xA63C, 0xA63C, 0xAE5C, 0xAE5D, 0xAE5D, 0xAE7D, 0xA65D, 0xC6DD, 0xFFFF, 0xFFFF, // 0x00F0 (240) +0xFFDF, 0xFFFF, 0xDF5E, 0xA65D, 0xAE7D, 0xAE5D, 0xAE5D, 0xAE5C, 0xA63C, 0xA61C, 0xB67D, 0x753A, 0x0295, 0xCEBC, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xF7DF, 0xFFFF, 0x957A, 0x12F6, 0x9E1C, 0x9E1C, 0x9E1C, 0x9E1C, 0xA63C, 0xA63C, 0xA63D, 0xA63D, 0xA65D, 0x9DFC, 0xDF3E, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xFFDF, 0xA61C, 0xA65D, 0xA65D, 0xA63D, 0xA63C, 0xA63C, 0x9E1C, 0x9E1C, 0x9DFC, 0xAE3C, 0x3C18, 0x3396, 0xFFDF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xF79F, 0x2336, 0x64DA, 0x9DFC, 0x95DC, 0x95FC, 0x95FC, 0x9E1C, 0x9E1C, 0x9E3D, 0x9E3D, 0x9E3D, 0x9E3D, 0x7D3B, 0xA63C, // 0x0130 (304) +0xB6BD, 0x8DBB, 0x8DFC, 0xA65D, 0x9E3D, 0x9E3D, 0x9E1C, 0x9E1C, 0x95FC, 0x95FC, 0x95DC, 0x95DC, 0x8DBB, 0x0AF6, 0xA5DA, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xA5FB, 0x1337, 0x8DBB, 0x8DBB, 0x8DBC, 0x8DDC, 0x95FC, 0x95FC, 0x961C, 0x961D, 0x963D, 0x9E3D, 0x963D, 0xA67D, 0xB6BD, // 0x0150 (336) +0xB6BD, 0xAE7D, 0x9E3D, 0x9E3D, 0x961D, 0x961D, 0x961C, 0x95FC, 0x95FC, 0x8DDC, 0x8DDC, 0x859B, 0x95DC, 0x3C18, 0x4BD7, 0xFFFF, // 0x0160 (352) +0xFFFF, 0x6499, 0x33F8, 0x8DBB, 0x859B, 0x85BC, 0x85BC, 0x8DDC, 0x8DFC, 0x8DFD, 0x8E1D, 0x961D, 0x961D, 0x9E3D, 0xF7BF, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xA67D, 0x8E1D, 0x961D, 0x8E1D, 0x8DFD, 0x8DFC, 0x8DDC, 0x85BC, 0x85BC, 0x859B, 0x859B, 0x5CDA, 0x2336, 0xE71C, // 0x0180 (384) +0xFFFF, 0x43F8, 0x4C79, 0x859B, 0x7D7B, 0x7D9C, 0x85BC, 0x85DC, 0x85DC, 0x8DFD, 0x8DFD, 0x8E1D, 0x8E1D, 0xA67E, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFFF, 0xBEDE, 0x85FD, 0x8E1D, 0x8DFD, 0x8DFD, 0x85DC, 0x85DC, 0x85BC, 0x7D9C, 0x7D7B, 0x7D7B, 0x753B, 0x1B36, 0xBE5A, // 0x01A0 (416) +0xFFBE, 0x3BF8, 0x3419, 0x6D1B, 0x757B, 0x7D9C, 0x7D9C, 0x7DBC, 0x7DDD, 0x85FD, 0x85FD, 0x861D, 0x861D, 0x9E7E, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xFFFF, 0xB6DE, 0x85FD, 0x8E1D, 0x85FD, 0x85FD, 0x7DDD, 0x7DBC, 0x7D9C, 0x7D9C, 0x757B, 0x6D3B, 0x4C9A, 0x1337, 0xADD9, // 0x01C0 (448) +0xFFBE, 0x4418, 0x23B9, 0x3439, 0x4CBA, 0x653B, 0x759C, 0x7DBD, 0x7DDD, 0x7DFD, 0x861D, 0x861E, 0x861E, 0x9E7E, 0xFFFF, 0xFFFF, // 0x01D0 (464) +0xFFFF, 0xFFFF, 0xB6DE, 0x7E1E, 0x861E, 0x85FD, 0x7DFD, 0x7DDD, 0x7DBD, 0x759C, 0x653B, 0x4CDB, 0x3439, 0x2BF9, 0x1337, 0xA5B9, // 0x01E0 (480) +0xFF9E, 0x4C39, 0x2BF9, 0x345A, 0x3C7A, 0x3C9B, 0x4CFC, 0x5D5C, 0x659D, 0x75DD, 0x7DFE, 0x861E, 0x7E3E, 0x969F, 0xFFFF, 0xFFFF, // 0x01F0 (496) +0xFFFF, 0xFFFF, 0xB6FF, 0x7E1E, 0x863E, 0x7DFE, 0x75DD, 0x6D9D, 0x5D5C, 0x4CFC, 0x3C9B, 0x347A, 0x345A, 0x343A, 0x1B78, 0xA5B9, // 0x0200 (512) +0xF79E, 0x4418, 0x2C3A, 0x3C7A, 0x449B, 0x44DB, 0x4CFC, 0x4D3C, 0x555D, 0x5D7D, 0x65BE, 0x6DFE, 0x6DFF, 0x867F, 0xFFFF, 0xFFFF, // 0x0210 (528) +0xFFFF, 0xFFFF, 0xA6DF, 0x65FF, 0x6DFE, 0x65BE, 0x5D9E, 0x555D, 0x4D3C, 0x4CFC, 0x44DB, 0x44BB, 0x3C7A, 0x345A, 0x1B78, 0xA599, // 0x0220 (544) +0xFFDE, 0x43D8, 0x345A, 0x3C9A, 0x44DB, 0x4CFC, 0x4D3C, 0x555D, 0x5D9D, 0x5DBE, 0x65DE, 0x6DFF, 0x661F, 0x867F, 0xFFFF, 0xFFFF, // 0x0230 (560) +0xFFFF, 0xFFFF, 0xA6DF, 0x65FF, 0x6DFF, 0x65DE, 0x5DBE, 0x5D9D, 0x555D, 0x4D3C, 0x4CFC, 0x44DB, 0x3C7A, 0x3C9B, 0x1B57, 0xADB9, // 0x0240 (576) +0xFFFF, 0x4BD7, 0x2C1A, 0x44DB, 0x44DB, 0x4D1C, 0x555D, 0x5D7D, 0x5DBE, 0x65DE, 0x6E1F, 0x6E3F, 0x765F, 0x96BF, 0xFFFF, 0xFFFF, // 0x0250 (592) +0xFFFF, 0xFFFF, 0xAEFF, 0x6E3F, 0x763F, 0x6E1F, 0x65DE, 0x5DBE, 0x5D7D, 0x555D, 0x4D1C, 0x44DC, 0x3C9B, 0x44DC, 0x1AD5, 0xC639, // 0x0260 (608) +0xFFFF, 0x84D8, 0x1317, 0x5D7D, 0x44DB, 0x553C, 0x557D, 0x5D9E, 0x65DE, 0x65FF, 0x6E3F, 0x7E5F, 0x7E7F, 0x9EDF, 0xFFFF, 0xFFFF, // 0x0270 (624) +0xFFFF, 0xFFFF, 0xB73F, 0x7E7F, 0x7E5F, 0x6E3F, 0x65FF, 0x65DE, 0x5D9E, 0x557D, 0x553C, 0x44DC, 0x4D1C, 0x345B, 0x22B4, 0xE71B, // 0x0280 (640) +0xFFFF, 0xD6BC, 0x0234, 0x4CFC, 0x5D7D, 0x4D3C, 0x5D9D, 0x5DBE, 0x65FF, 0x6E3F, 0x765F, 0x867F, 0x8EBF, 0xA6DF, 0xFFFF, 0xFFFF, // 0x0290 (656) +0xFFFF, 0xFFFF, 0xB71F, 0x8EBF, 0x869F, 0x765F, 0x6E3F, 0x65FF, 0x5DBE, 0x5D7D, 0x553D, 0x4D1C, 0x65BE, 0x0AB7, 0x6C15, 0xFFBE, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0x53B6, 0x0296, 0x75FE, 0x5D9D, 0x557D, 0x65DE, 0x6E1F, 0x763F, 0x7E7F, 0x8EBF, 0x9EFF, 0x96BE, 0xAE3C, 0xE77E, // 0x02B0 (688) +0xEF9E, 0xC69D, 0x967E, 0x9EFF, 0x8EBF, 0x7E7F, 0x763F, 0x6E1F, 0x65DE, 0x5D9E, 0x555D, 0x761E, 0x341A, 0x1294, 0xBE18, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xCE9B, 0x0A13, 0x2378, 0x7E5F, 0x6E1E, 0x5DBE, 0x6E1F, 0x7E5F, 0x869F, 0x96DF, 0x9EFF, 0xAF5F, 0x9E9E, 0x8DFC, // 0x02D0 (720) +0x8E1C, 0x967D, 0xAF3F, 0xA6FF, 0x96DF, 0x869F, 0x7E5F, 0x6E1F, 0x5DBE, 0x65DE, 0x7E5F, 0x4CBB, 0x0AB5, 0x7454, 0xEF5C, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFFF, 0xFFFF, 0x8D17, 0x01D3, 0x23B9, 0x7E3E, 0x8E9F, 0x763F, 0x765F, 0x8E9F, 0x9EDF, 0xA71F, 0xB75F, 0xC7BF, 0xCFDF, // 0x02F0 (752) +0xCFDF, 0xC7BF, 0xB75F, 0xA71F, 0x9EDF, 0x8E9F, 0x765F, 0x6E1F, 0x867F, 0x8E7F, 0x4CBB, 0x1317, 0x4BB4, 0xD679, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFBD, 0x7476, 0x0214, 0x1B78, 0x659D, 0x9EDF, 0x9EFF, 0x96DF, 0x9EFF, 0xAF1F, 0xB75F, 0xC79F, 0xD7DF, // 0x0310 (784) +0xD7DF, 0xC79F, 0xB75F, 0xAF1F, 0x9EDF, 0x96DF, 0x96DF, 0x9EFF, 0x7E1E, 0x3C5A, 0x1B77, 0x43B5, 0xBDD6, 0xF7BE, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77D, 0x7CB6, 0x12B4, 0x1337, 0x449B, 0x7DFD, 0xA6FF, 0xB75F, 0xBF7F, 0xC79F, 0xCFBF, 0xD7FF, // 0x0330 (816) +0xD7FF, 0xCFBF, 0xC79F, 0xBF7F, 0xB77F, 0xAF1F, 0x8E5E, 0x551B, 0x3419, 0x2BD7, 0x5415, 0xB5B6, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79D, 0xA577, 0x3B75, 0x1B36, 0x2BD9, 0x4CBB, 0x759D, 0x965E, 0xAEDF, 0xBF3F, 0xC77F, // 0x0350 (848) +0xC77F, 0xBF3F, 0xB6FF, 0x9E7F, 0x7DDD, 0x5D1C, 0x447A, 0x3C59, 0x4437, 0x7474, 0xC617, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDE, 0xD699, 0x84D5, 0x43D5, 0x33B7, 0x3418, 0x4C7A, 0x5CFC, 0x753D, 0x857E, // 0x0370 (880) +0x859E, 0x755D, 0x653C, 0x5CFB, 0x4CDA, 0x4CB9, 0x5497, 0x6C95, 0xA555, 0xDEDA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79D, 0xCE79, 0x9D56, 0x7495, 0x5C56, 0x4C77, 0x4C97, 0x4CB8, // 0x0390 (912) +0x54D8, 0x5CD8, 0x5CF8, 0x64D7, 0x74D6, 0x8CF5, 0xAD96, 0xD699, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFBE, 0xEF1B, 0xD679, 0xBDF7, 0xAD96, 0xA576, // 0x03B0 (944) +0xA576, 0xAD76, 0xB5B6, 0xC5F7, 0xD679, 0xEF3C, 0xFFDE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFBE, // 0x03D0 (976) +0xF7BE, 0xF7BE, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/tux.c b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/tux.c new file mode 100644 index 0000000..69a04a1 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap/tux.c @@ -0,0 +1,71 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: tux.png +// Time generated: 11.10.2010 22:51:32 +// Size : 2 048 Bytes + +const unsigned short tux[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x9CD3, 0x9CF3, 0xA514, // 0x0010 (16) +0x9CF3, 0x8C51, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x5AEB, 0x7BEF, 0x9CD3, 0x94B2, // 0x0030 (48) +0x94B2, 0x94B2, 0x4228, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x9CF3, 0x18E3, 0x630C, 0x4A49, 0x4A69, // 0x0050 (80) +0x4A69, 0x528A, 0x4A49, 0x0000, 0xC638, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x0000, 0x0020, 0x10A2, 0x1082, // 0x0070 (112) +0x0841, 0x0841, 0x0841, 0x0000, 0x630C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x528A, 0x4228, 0x8410, 0x0000, 0x0861, // 0x0090 (144) +0xAD55, 0xBDD7, 0x10A2, 0x0000, 0x2945, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x5ACB, 0x8C71, 0xE75D, 0x2126, 0x528B, // 0x00B0 (176) +0xE75D, 0xDEDB, 0x7BCF, 0x0000, 0x18E3, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x4A4A, 0x6B2A, 0x8BE7, 0xA48A, // 0x00D0 (208) +0x6B09, 0x4A8A, 0x8431, 0x0000, 0x2104, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6E, 0x5204, 0xDE6A, 0xFFF7, 0xFFF8, // 0x00F0 (240) +0xD5AC, 0xBCAA, 0x5A66, 0x0000, 0x1082, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C10, 0xC540, 0xFFED, 0xFF2C, 0xFEEC, // 0x0110 (272) +0xFECC, 0xFE66, 0x8260, 0x0000, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B3, 0x9C25, 0xFF20, 0xFE40, 0xFDA0, // 0x0130 (304) +0xFCC0, 0xF524, 0x836A, 0x0000, 0x0000, 0x630C, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x630C, 0x94B4, 0xFF13, 0xFD83, 0xF523, // 0x0150 (336) +0xE5CF, 0xF79E, 0xE71D, 0x0861, 0x0000, 0x0861, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0841, 0xD69A, 0xFFFF, 0xFF7D, 0xF77D, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x4A69, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x10A2, 0x8410, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0000, 0x0000, 0x0000, 0x9492, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01A0 (416) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x52AA, 0x0020, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFDF, 0xFFDF, 0xF7BE, 0xFFDF, 0x3186, 0x0000, 0x0020, 0x0841, 0xCE79, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x0000, 0x52AA, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x01D0 (464) +0xFFDF, 0xF7BE, 0xF79E, 0xFFFF, 0x9CF3, 0x0000, 0x0841, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01E0 (480) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x5ACB, 0x0000, 0xBDF7, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFDF, // 0x01F0 (496) +0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0x3186, 0x0000, 0x0861, 0x0000, 0xAD55, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x0861, 0x4A49, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x0210 (528) +0xF7BE, 0xF79E, 0xEF7D, 0xEF5D, 0xFFDF, 0x8410, 0x0000, 0x1082, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0220 (544) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, // 0x0230 (560) +0xF79E, 0xEF7D, 0xEF7D, 0xE73C, 0xF79E, 0xAD55, 0x0861, 0x10A2, 0x0861, 0x0841, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x3185, 0x10A2, 0xE71C, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, // 0x0250 (592) +0xEF7D, 0xEF7D, 0xEF5D, 0xE73C, 0xEF5D, 0xBDF7, 0x18C3, 0x18C3, 0x18C3, 0x0000, 0x8C71, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0260 (608) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0x39E7, 0xF7BE, 0xFFFF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, 0xEF7D, // 0x0270 (624) +0xEF7D, 0xEF5D, 0xE73C, 0xE71C, 0xE71C, 0xC618, 0x18E3, 0x10A2, 0x10A2, 0x0020, 0x6B4D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C51, 0x38E0, 0x4A27, 0xFFFF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, // 0x0290 (656) +0xEF5D, 0xE73C, 0xE71C, 0xDEFB, 0xDF1D, 0xBDF8, 0x39C7, 0x5ACB, 0x528A, 0x10A3, 0x738F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDD6C, 0xFE2B, 0xBC45, 0xA513, 0xFFFF, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF5D, // 0x02B0 (688) +0xE73C, 0xE71C, 0xDEFB, 0xD6DC, 0xDD8E, 0xB3E4, 0x2124, 0x2965, 0x2945, 0x20C1, 0xB511, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77C, 0xE5CF, 0xF60B, 0xFF9B, 0xFF54, 0x8B02, 0x7BF0, 0xFFDF, 0xF79E, 0xEF5D, 0xEF5D, 0xE73C, // 0x02D0 (720) +0xE71C, 0xDEFB, 0xDEDB, 0xCE7A, 0xED89, 0xDDAD, 0x0842, 0x0000, 0x0000, 0xAC69, 0xDD6B, 0xEFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFFF, 0xFFBE, 0xE5CB, 0xEDC9, 0xFE4B, 0xFF14, 0xFEF3, 0xFF35, 0xFE8D, 0x51C1, 0x634E, 0xE73C, 0xEF5D, 0xE73C, 0xE71C, // 0x02F0 (752) +0xDEFB, 0xDEDB, 0xD6DB, 0xCE59, 0xE58B, 0xFF98, 0xBD4F, 0x8B88, 0xCD90, 0xFFB7, 0xCCE8, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xEF3B, 0xF583, 0xFF30, 0xFF11, 0xFECF, 0xFEEF, 0xFECF, 0xFF30, 0xDD46, 0x2903, 0x6B8E, 0xEF7D, 0xE71C, 0xDEFB, // 0x0310 (784) +0xDEDB, 0xD6BA, 0xD69A, 0xCE59, 0xE5AA, 0xFF11, 0xFF53, 0xFF73, 0xFF33, 0xFF12, 0xFE6C, 0xDDAD, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xF79E, 0xEDC5, 0xFECB, 0xFECC, 0xFECC, 0xFEEC, 0xFECB, 0xFECC, 0xFEEA, 0x9BE5, 0x8432, 0xE73C, 0xDEDB, 0xDEDB, // 0x0330 (816) +0xD6BA, 0xD69A, 0xDEDB, 0xA4F3, 0xD547, 0xFF2E, 0xFECD, 0xFECE, 0xFEEE, 0xFEEE, 0xFF10, 0xFEAB, 0xE5A8, 0xEF7D, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xF79E, 0xF603, 0xFEA2, 0xFEC7, 0xFEC7, 0xFEA4, 0xFE81, 0xFE61, 0xFEA4, 0xFE43, 0xDE33, 0xE75E, 0xE71C, 0xDEFB, // 0x0350 (848) +0xDEDB, 0xCE58, 0x8C72, 0x5247, 0xEDE4, 0xFF0A, 0xFECA, 0xFEC9, 0xFE84, 0xFE83, 0xFEE7, 0xFEA3, 0xB443, 0xD69B, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xF75B, 0xFE60, 0xFF00, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xE5C1, 0x9492, 0xA514, 0x9CD3, // 0x0370 (880) +0x8410, 0x630B, 0x4229, 0x6AE8, 0xFE80, 0xFEC1, 0xFEC1, 0xFEA0, 0xFEA0, 0xFEE0, 0xDD80, 0x9BE8, 0xB597, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xF79E, 0xD589, 0xE600, 0xFEA0, 0xFF00, 0xFF40, 0xFF40, 0xFF00, 0xFF00, 0xFF20, 0xFEC0, 0x5267, 0x4229, 0x4A48, // 0x0390 (912) +0x4A49, 0x5289, 0x424A, 0x7B46, 0xFF20, 0xFEE0, 0xFEE0, 0xFF20, 0xFEE0, 0xB4A5, 0x9C92, 0xDEFD, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xE71D, 0xBDB6, 0xB530, 0xBD0B, 0xCD65, 0xEE60, 0xFF40, 0xFFA0, 0xFF80, 0xBD03, 0x8410, 0xA514, 0xA534, // 0x03B0 (944) +0xAD75, 0xB596, 0xA555, 0x9C8F, 0xF6C0, 0xFFA0, 0xFFA0, 0xF6E0, 0xA449, 0xB5B8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7F, 0xD69C, 0xBD95, 0xBD4C, 0xCDC6, 0xB4E8, 0xAD35, 0xF7BF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xF7BF, 0xCDD0, 0xCDC6, 0xCDA7, 0xA48D, 0xCE7B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF1F, 0xB59A, 0xBDDA, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFDF, 0xFFDF, 0xFFFF, 0xEF7F, 0xB59A, 0xAD59, 0xDF1D, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino new file mode 100644 index 0000000..3cc269e --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino @@ -0,0 +1,49 @@ +// UTFT_Bitmap_128x128 (C)2013 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This demo was made to work on the 128x128 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include + +UTFT myGLCD(LPH9135,6,5,2,3,4); // Remember to change the model parameter to suit your display module! + +extern unsigned short icon1[0x400]; +extern unsigned short icon2[0x400]; +extern unsigned short tux[0x1000]; + +void setup() +{ + myGLCD.InitLCD(PORTRAIT); +} + +void loop() +{ +// Draw a 4 by 4 grid of a 32x32 icon. + myGLCD.fillScr(255, 255, 255); + for (int x=0; x<4; x++) + for (int y=0; y<4; y++) + myGLCD.drawBitmap (x*32, y*32, 32, 32, icon1); + + delay(5000); + +// Draw a 64x64 icon in double size. + myGLCD.fillScr(255, 255, 255); + myGLCD.drawBitmap (0, 0, 64, 64, tux, 2); + + delay(5000); + +// Draw a 2 by 2 grid of a 32x32 icon in double size. + myGLCD.fillScr(255, 255, 255); + for (int x=0; x<2; x++) + for (int y=0; y<2; y++) + myGLCD.drawBitmap (x*64, y*64, 32, 32, icon2, 2); + + delay(5000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon1.c b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon1.c new file mode 100644 index 0000000..b9c2c97 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon1.c @@ -0,0 +1,72 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: exit.png +// Time generated: 14.10.2010 21:53:03 +// Dimensions : 32x32 pixels +// Size : 2 048 Bytes + +const unsigned short icon1[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF1C, 0xE618, 0xE638, 0xE638, 0xE638, 0xE659, 0xE659, 0xE659, 0xE659, 0xE659, 0xE679, 0xE679, // 0x0010 (16) +0xE679, 0xE679, 0xE679, 0xE679, 0xEE79, 0xEE9A, 0xEE9A, 0xEE9A, 0xEE9A, 0xEE9A, 0xE638, 0xEEBA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xD555, 0xCCD3, 0xDDB6, 0xDDD7, 0xDDF7, 0xDDF7, 0xDE18, 0xE618, 0xE638, 0xE638, 0xE659, 0xE679, 0xE679, // 0x0030 (48) +0xEE9A, 0xEE9A, 0xEEBA, 0xEEBA, 0xEEBA, 0xEEDB, 0xEEDB, 0xEEFB, 0xEEFB, 0xEEFB, 0xEEFB, 0xE659, 0xD575, 0xF77D, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFDF, 0xFFFF, 0xD534, 0xC471, 0xD575, 0xCCF3, 0xCCD3, 0xCCD3, 0xCCF3, 0xCCF3, 0xD4F3, 0xD514, 0xD514, 0xD514, 0xD534, 0xDD55, // 0x0050 (80) +0xDD55, 0xDD55, 0xDD55, 0xDD75, 0xDD75, 0xDD75, 0xDD96, 0xDD96, 0xDD96, 0xDDB6, 0xDDD7, 0xEE79, 0xEEBA, 0xD534, 0xFFBE, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xEEDB, 0xB38E, 0xC4B2, 0xBC30, 0xC451, 0xC471, 0xC471, 0xCC71, 0xCC92, 0xCC92, 0xCC92, 0xCCB2, 0xD4B2, 0xD4B2, 0xCC71, // 0x0070 (112) +0xCC71, 0xD4D3, 0xD4F3, 0xDCF3, 0xDCF3, 0xDD14, 0xDD14, 0xDD14, 0xDD34, 0xDD34, 0xDD34, 0xDD14, 0xE5D7, 0xDD96, 0xDDF7, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xC4F3, 0xAB2C, 0xC430, 0xC410, 0xC430, 0xC430, 0xC430, 0xCC51, 0xCC51, 0xCC51, 0xCC71, 0xCC71, 0xD471, 0xCC71, 0xD5F7, // 0x0090 (144) +0xD5F7, 0xCC92, 0xDCB2, 0xDCD3, 0xDCD3, 0xDCD3, 0xDCD3, 0xDCF3, 0xDCF3, 0xDD14, 0xDD14, 0xDD34, 0xDD14, 0xDD34, 0xC492, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xB3EF, 0x9A28, 0xC430, 0xBBCF, 0xC3EF, 0xC3EF, 0xC3EF, 0xC410, 0xCC10, 0xCC10, 0xCC30, 0xCC51, 0xCBEF, 0xE638, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xE659, 0xD430, 0xDC92, 0xDC92, 0xDC92, 0xDCB2, 0xDCB2, 0xDCB2, 0xDCD3, 0xDCD3, 0xDCD3, 0xE514, 0xD410, 0xAB0C, 0xF7FF, // 0x00C0 (192) +0xFFFF, 0xABCF, 0x9165, 0xC3EF, 0xBB8E, 0xBBAE, 0xC3AE, 0xC3CF, 0xC3CF, 0xCBCF, 0xCBEF, 0xCC10, 0xCC10, 0xCBAE, 0xEE9A, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xF6DB, 0xD410, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xE492, 0xE492, 0xE492, 0xE4F3, 0xCB2C, 0xA249, 0xF7FF, // 0x00E0 (224) +0xFFFF, 0xABCF, 0x88C3, 0xC3AE, 0xBB4D, 0xBB6D, 0xC36D, 0xC38E, 0xC38E, 0xCBAE, 0xC36D, 0xC34D, 0xCBCF, 0xCB8E, 0xEE59, 0xFFFF, // 0x00F0 (240) +0xFFFF, 0xF6BA, 0xDBCF, 0xD3CF, 0xCBAE, 0xD3CF, 0xE430, 0xE430, 0xE451, 0xE451, 0xE451, 0xE451, 0xECD3, 0xCAAA, 0xA208, 0xF7FF, // 0x0100 (256) +0xFFFF, 0xABCF, 0x8061, 0xBB6D, 0xBB2C, 0xBB2C, 0xC34D, 0xC34D, 0xCB4D, 0xBB0C, 0xC492, 0xCD14, 0xC38E, 0xCB2C, 0xEE59, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xF6BA, 0xD36D, 0xD575, 0xE6DB, 0xDDB6, 0xD3AE, 0xE3EF, 0xE410, 0xE410, 0xE430, 0xE410, 0xECB2, 0xC986, 0xA208, 0xF7FF, // 0x0120 (288) +0xFFFF, 0xB3EF, 0x8041, 0xBB0C, 0xBAEB, 0xBAEB, 0xC30C, 0xC30C, 0xBACB, 0xD5B6, 0xFFFF, 0xFFFF, 0xEE79, 0xCACB, 0xEE59, 0xFFFF, // 0x0130 (304) +0xFFFF, 0xF679, 0xDBEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEEBA, 0xD3CF, 0xE3AE, 0xE3EF, 0xE3CF, 0xEC10, 0xEB6D, 0xC000, 0xA249, 0xF7FF, // 0x0140 (320) +0xFFFF, 0xB3EF, 0x8020, 0xBACB, 0xBAAA, 0xBAAA, 0xC2EB, 0xBA8A, 0xD596, 0xFFFF, 0xFFDF, 0xFFFF, 0xF73C, 0xCAAA, 0xEE38, 0xFFFF, // 0x0150 (336) +0xFFFF, 0xF679, 0xDB4D, 0xFF7D, 0xFFFF, 0xFFDF, 0xFFFF, 0xEEDB, 0xDB6D, 0xEB8E, 0xEBAE, 0xEB8E, 0xE0A2, 0xC800, 0xAA49, 0xF7FF, // 0x0160 (352) +0xFFFF, 0xB3EF, 0x8000, 0xB28A, 0xBA69, 0xBA8A, 0xBA49, 0xCC30, 0xFFFF, 0xFFDF, 0xFFFF, 0xFF5D, 0xDBCF, 0xCA69, 0xEE18, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xF679, 0xDAAA, 0xE3AE, 0xF6BA, 0xFFFF, 0xFFDF, 0xFFFF, 0xE5D7, 0xE30C, 0xEB8E, 0xE0E3, 0xE000, 0xC800, 0xAA49, 0xF7FF, // 0x0180 (384) +0xFFFF, 0xB3EF, 0x8800, 0xB249, 0xBA49, 0xBA49, 0xBA49, 0xEF1C, 0xFFFF, 0xFFFF, 0xFF7D, 0xD32C, 0xCA69, 0xD249, 0xEDF7, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xF659, 0xDAAA, 0xE2CB, 0xE2EB, 0xFEBA, 0xFFFF, 0xFFDF, 0xFFDF, 0xE3CF, 0xE103, 0xE000, 0xE081, 0xD000, 0xAA69, 0xF7FF, // 0x01A0 (416) +0xFFFF, 0xB3EF, 0x8800, 0xB228, 0xBA08, 0xB9A6, 0xCBAE, 0xFFFF, 0xFFDF, 0xFFFF, 0xDC30, 0xC9E7, 0xD28A, 0xCA08, 0xF618, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xF679, 0xDA49, 0xE2CB, 0xE28A, 0xEB6D, 0xFFBE, 0xFFDF, 0xFFFF, 0xEC92, 0xE000, 0xE0A2, 0xE0C2, 0xD040, 0xAA89, 0xF7FF, // 0x01C0 (448) +0xFFFF, 0xB3EF, 0x8800, 0xB1E7, 0xB9E7, 0xB165, 0xDD55, 0xFFFF, 0xFFFF, 0xF71C, 0xCA08, 0xCA08, 0xD228, 0xD1E7, 0xE430, 0xFFDF, // 0x01D0 (464) +0xFFDF, 0xEC51, 0xDA08, 0xE28A, 0xE28A, 0xE228, 0xF618, 0xFFFF, 0xFFFF, 0xF679, 0xE081, 0xE0C2, 0xE903, 0xD081, 0xAA89, 0xF7FF, // 0x01E0 (480) +0xFFFF, 0xBBEF, 0x9000, 0xB1A6, 0xB986, 0xB145, 0xEE38, 0xFFFF, 0xFFFF, 0xED96, 0xC165, 0xC9E7, 0xD1E7, 0xD1E7, 0xD1C7, 0xDACB, // 0x01F0 (496) +0xE2EB, 0xD9E7, 0xE228, 0xE228, 0xEA69, 0xE9E7, 0xF40F, 0xFFFF, 0xFFFF, 0xFF5D, 0xE144, 0xE8E2, 0xE943, 0xD8C1, 0xAA8A, 0xF7FF, // 0x0200 (512) +0xFFFF, 0xBC10, 0x9000, 0xB165, 0xB145, 0xB924, 0xEE9A, 0xFFFF, 0xFFFF, 0xE514, 0xC124, 0xC9A6, 0xD1A6, 0xD1A6, 0xD1C7, 0xD9A6, // 0x0210 (528) +0xD9A6, 0xE1E7, 0xE208, 0xE208, 0xE9A6, 0xE041, 0xEA8A, 0xFFFF, 0xFFFF, 0xFF9E, 0xE9C6, 0xE902, 0xE984, 0xD902, 0xAAAA, 0xF7FF, // 0x0220 (544) +0xFFFF, 0xC410, 0x9000, 0xB124, 0xB124, 0xB0C3, 0xEE18, 0xFFFF, 0xFFFF, 0xE575, 0xC0E3, 0xC986, 0xD165, 0xD165, 0xD986, 0xD9A6, // 0x0230 (560) +0xD9A6, 0xE1A6, 0xE165, 0xE082, 0xE020, 0xE000, 0xEB4C, 0xFFFF, 0xFFFF, 0xFF7D, 0xE9A5, 0xE943, 0xE9A5, 0xD923, 0xAAAA, 0xF7FF, // 0x0240 (576) +0xFFFF, 0xC410, 0x9800, 0xB0E3, 0xB0E3, 0xB061, 0xE4F3, 0xFFFF, 0xFFFF, 0xF6FB, 0xC104, 0xC924, 0xD145, 0xD145, 0xD945, 0xD945, // 0x0250 (592) +0xD8E3, 0xD861, 0xD800, 0xE000, 0xE061, 0xE000, 0xED34, 0xFFFF, 0xFFFF, 0xFE9A, 0xE923, 0xE984, 0xE9C5, 0xE163, 0xAAAA, 0xF7FF, // 0x0260 (608) +0xFFFF, 0xC410, 0xA000, 0xB0A2, 0xB0A2, 0xB041, 0xCACB, 0xFFFF, 0xFFDF, 0xFFFF, 0xD34D, 0xC841, 0xD104, 0xD0A2, 0xD061, 0xD000, // 0x0270 (624) +0xD800, 0xD800, 0xE000, 0xE041, 0xE000, 0xD965, 0xFF9E, 0xFFDF, 0xFFFF, 0xF4D2, 0xE8E2, 0xE9A5, 0xE9E5, 0xE183, 0xAAAA, 0xF7FF, // 0x0280 (640) +0xFFFF, 0xCC10, 0xA000, 0xA861, 0xB061, 0xB061, 0xB882, 0xF6DB, 0xFFFF, 0xFFDF, 0xF75D, 0xC124, 0xC800, 0xD000, 0xD000, 0xD800, // 0x0290 (656) +0xD800, 0xE000, 0xE020, 0xE000, 0xD861, 0xF638, 0xFFFF, 0xFFDF, 0xFFDF, 0xEA68, 0xE943, 0xE9C5, 0xEA06, 0xE1A4, 0xB2CA, 0xF7FF, // 0x02A0 (672) +0xFFFF, 0xCC10, 0xA000, 0xA820, 0xB000, 0xB000, 0xB000, 0xCA49, 0xFFFF, 0xFFDF, 0xFFFF, 0xF71C, 0xCA08, 0xC800, 0xD000, 0xD800, // 0x02B0 (688) +0xD800, 0xD800, 0xD800, 0xD944, 0xEE18, 0xFFFF, 0xFFBE, 0xFFFF, 0xF4F2, 0xE902, 0xE9A5, 0xE9C5, 0xEA06, 0xE9A4, 0xB2CA, 0xF7FF, // 0x02C0 (704) +0xFFFF, 0xD410, 0xA800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xDC10, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xED96, 0xDAEB, 0xD1A6, // 0x02D0 (720) +0xD965, 0xDA69, 0xECD3, 0xFF9E, 0xFFFF, 0xFFBE, 0xFFFF, 0xFE17, 0xE923, 0xE964, 0xE9A5, 0xE9C5, 0xEA26, 0xE9C4, 0xBACA, 0xF7FF, // 0x02E0 (736) +0xF7FF, 0xD410, 0xA800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xB800, 0xE3EF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02F0 (752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF5B6, 0xE923, 0xE923, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xE9C5, 0xBACA, 0xF7FF, // 0x0300 (768) +0xF7FF, 0xDC10, 0xB000, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xD228, 0xF638, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0310 (784) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFEFB, 0xF3AE, 0xE0C1, 0xE903, 0xE964, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xE9E5, 0xC2CA, 0xF7DF, // 0x0320 (800) +0xF7FF, 0xDC51, 0xB800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xC000, 0xC800, 0xD9E7, 0xEC30, 0xF5D7, 0xFE9A, // 0x0330 (816) +0xFEBA, 0xF618, 0xF4D3, 0xEACB, 0xE0E2, 0xE040, 0xE903, 0xE943, 0xE943, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xEA05, 0xC30C, 0xF7DF, // 0x0340 (832) +0xFFFF, 0xD575, 0xD104, 0xA820, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xC000, 0xC820, 0xC800, 0xD000, 0xD000, 0xD800, 0xD800, // 0x0350 (848) +0xE000, 0xE000, 0xE000, 0xE000, 0xE0A1, 0xE0E3, 0xE903, 0xE943, 0xE964, 0xE984, 0xE9C5, 0xE9C5, 0xF226, 0xE227, 0xBC10, 0xF7FF, // 0x0360 (864) +0xFFFF, 0xDF3C, 0xCAAA, 0xD186, 0xB082, 0xB000, 0xB800, 0xB800, 0xB800, 0xC000, 0xC000, 0xC800, 0xC800, 0xD000, 0xD000, 0xD800, // 0x0370 (880) +0xD800, 0xE000, 0xE020, 0xE040, 0xE061, 0xE0A1, 0xE0C2, 0xE102, 0xE123, 0xE943, 0xE984, 0xEA26, 0xFB0A, 0xBA08, 0xCE38, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFDF, 0xBDD7, 0xCA69, 0xE248, 0xD207, 0xD1C6, 0xD1C6, 0xD9C7, 0xD9C7, 0xE1C7, 0xE1C7, 0xE1C7, 0xE9C7, 0xE9C7, 0xE9C7, // 0x0390 (912) +0xF1C6, 0xF1C7, 0xF1E7, 0xF207, 0xF228, 0xF248, 0xF269, 0xF289, 0xF2A9, 0xF2CA, 0xFB0A, 0xF2EA, 0xC207, 0xACB3, 0xF7BE, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xF7BE, 0xBDF7, 0xAB8E, 0xC2EB, 0xC2EB, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xCB0B, 0xCAEB, // 0x03B0 (944) +0xCAEB, 0xCACA, 0xCACA, 0xCAAA, 0xCAAA, 0xCA8A, 0xCA69, 0xC269, 0xC269, 0xC289, 0xBA69, 0xA2CB, 0xAD34, 0xEF7D, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xDF3C, 0xBE39, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, // 0x03D0 (976) +0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xBE38, 0xD71C, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon2.c b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon2.c new file mode 100644 index 0000000..9b843cc --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/icon2.c @@ -0,0 +1,72 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: video.png +// Time generated: 14.10.2010 21:53:17 +// Dimensions : 32x32 pixels +// Size : 2 048 Bytes + +const unsigned short icon2[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE71C, 0xB5B6, 0x94B2, 0x8C71, // 0x0030 (48) +0x9492, 0xA534, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x9CF3, 0x73AE, 0x6B6D, 0x73AE, 0x7BCF, // 0x0050 (80) +0x7BEF, 0x7BCF, 0x7BEF, 0xA534, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC638, 0x7BCF, 0x6B6D, 0x738E, 0x7BCF, 0x8C71, 0x9492, // 0x0070 (112) +0x9492, 0x9492, 0x9492, 0x8C51, 0x8C71, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x738E, 0x738E, 0x73AE, 0x6B4D, 0x8410, 0x9CF3, 0x9CF3, // 0x0090 (144) +0x9CF3, 0x9CF3, 0x9CF3, 0x9CF3, 0x94B2, 0x7BEF, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x738E, 0x7BEF, 0x8410, 0x632C, 0x4A69, 0x9492, 0xAD75, 0xAD55, // 0x00B0 (176) +0xAD55, 0xAD55, 0xAD55, 0xA534, 0xAD55, 0x9492, 0x8430, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDF7, 0x7BCF, 0x8430, 0x7BCF, 0x6B4D, 0x528A, 0x6B6D, 0xB5B6, 0xB5B6, 0xB5B6, // 0x00D0 (208) +0xB5B6, 0xB596, 0xB596, 0xAD75, 0xAD75, 0xAD55, 0x8410, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x7BEF, 0x9CD3, 0xA514, 0x5AEB, 0x630C, 0x6B4D, 0x9492, 0xC638, 0xC618, 0xC618, // 0x00F0 (240) +0xBDF7, 0xBDF7, 0xC618, 0xB5B6, 0xB5B6, 0xB596, 0x9492, 0x8C51, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8C71, 0x94B2, 0xAD55, 0xB5B6, 0x738E, 0x6B4D, 0x632C, 0xB596, 0xD69A, 0xCE59, 0xCE59, // 0x0110 (272) +0xCE79, 0xCE59, 0x6B6D, 0x9492, 0xB5B6, 0xBDF7, 0x9CF3, 0x8430, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB5B6, 0x8C51, 0xAD55, 0xB5B6, 0xCE79, 0x8C51, 0x630C, 0x8C51, 0xCE79, 0xD6BA, 0xD69A, 0xDEDB, // 0x0130 (304) +0xBDD7, 0x8C51, 0x4228, 0x2965, 0xAD55, 0xC638, 0xA534, 0x8430, 0xB5B6, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x8C51, 0xA514, 0xB5B6, 0xC618, 0xD6BA, 0xB5B6, 0xB596, 0xE71C, 0xDEFB, 0xDEFB, 0xE71C, 0xAD55, // 0x0150 (336) +0x738E, 0x7BEF, 0x5AEB, 0x2945, 0xC638, 0xCE59, 0xA534, 0x9492, 0xA534, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x94B2, 0xB5B6, 0xC618, 0xCE79, 0xD6BA, 0xE73C, 0xEF7D, 0xE73C, 0xEF5D, 0xE73C, 0x9CF3, 0x738E, // 0x0170 (368) +0x7BCF, 0x8430, 0x6B6D, 0x2965, 0xB596, 0xD69A, 0xAD55, 0x94B2, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xF79E, 0x9492, 0x9CF3, 0xB5B6, 0xD69A, 0xDEFB, 0xE71C, 0xE73C, 0x6B6D, 0x528A, 0xDEDB, 0xEF5D, 0x7BEF, 0x8430, // 0x0190 (400) +0x7BEF, 0x8C51, 0x7BCF, 0x2104, 0xB596, 0xD6BA, 0xAD55, 0x9CD3, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0xE6FC, // 0x01A0 (416) +0xFFDF, 0xFFFF, 0xCE59, 0x9492, 0x9492, 0x6B4D, 0x7BCF, 0xBDD7, 0xF7BE, 0xA514, 0x4A49, 0x528A, 0xC638, 0xEF7D, 0x7BEF, 0x7BEF, // 0x01B0 (432) +0x7BEF, 0x8430, 0x5AEB, 0x10A2, 0xC618, 0xD69A, 0xAD55, 0x94B2, 0xA514, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE5A, 0x8BF2, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xAD55, 0x94B2, 0x8C51, 0x5AEB, 0x632C, 0xBDD7, 0xE73C, 0x630C, 0x632C, 0xBDF7, 0xFFDF, 0xEF5D, 0xBDD7, 0xB5B6, // 0x01D0 (464) +0xAD75, 0xAD75, 0x8C51, 0x738E, 0xD69A, 0xCE59, 0xB596, 0x8C51, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xCE39, 0x7350, // 0x01E0 (480) +0xFFFF, 0xF79E, 0x94B2, 0x94B2, 0x7BCF, 0x5AEB, 0x738E, 0xD6BA, 0xD69A, 0x2104, 0x6B6D, 0xF79E, 0xF79E, 0xF79E, 0xF7BE, 0xF79E, // 0x01F0 (496) +0xEF7D, 0xEF5D, 0xE73C, 0xE73C, 0xDEFB, 0xBDF7, 0xBDF7, 0x7BEF, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD36, 0x7350, // 0x0200 (512) +0xFFFF, 0xDEDB, 0x8C51, 0x94B2, 0x738E, 0x632C, 0x73AE, 0xCE79, 0xF7BE, 0x7BEF, 0xA514, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0210 (528) +0xE73C, 0xE71C, 0xDEFB, 0xDEDB, 0xDEDB, 0xBDD7, 0xBDF7, 0x73AE, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x9C75, 0x736F, // 0x0220 (544) +0xFFFF, 0xCE59, 0x8430, 0x94B2, 0x6B4D, 0x6B4D, 0xB596, 0xE73C, 0xEF7D, 0xFFFF, 0xFFFF, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0230 (560) +0xE73C, 0xE73C, 0xDEFB, 0xDEFB, 0xD6BA, 0xC618, 0xAD55, 0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x6AEF, 0x9492, // 0x0240 (576) +0xFFFF, 0xBDF7, 0x8430, 0x8C71, 0x6B6D, 0xB596, 0xE71C, 0xE73C, 0xEF5D, 0xE73C, 0xBDF7, 0xCE59, 0xF7BE, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0250 (592) +0xE73C, 0xE71C, 0xDEFB, 0xDEFB, 0xC638, 0xD69A, 0x8410, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x9474, 0x6B0E, 0xCE59, // 0x0260 (608) +0xFFFF, 0xB5B6, 0x8410, 0x9492, 0xBDD7, 0xD6BA, 0xD6BA, 0xE71C, 0xE73C, 0x8C71, 0x6B4D, 0xA514, 0xF7BE, 0xEF5D, 0xEF5D, 0xE73C, // 0x0270 (624) +0xE73C, 0xE71C, 0xDEFB, 0xDEDB, 0xCE59, 0xC618, 0x7BCF, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC5F9, 0x7B51, 0x7BEF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xB596, 0x8C71, 0xAD75, 0xBDF7, 0xCE59, 0xD69A, 0xE71C, 0xCE79, 0x8410, 0x8410, 0x9CD3, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, // 0x0290 (656) +0xE71C, 0xDEFB, 0xDEFB, 0xCE59, 0xDEDB, 0x8C71, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEBB, 0x83B2, 0x630C, 0xE73C, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xB5B6, 0x9492, 0xAD55, 0xBDD7, 0xC638, 0xCE79, 0xDEFB, 0xB596, 0x73AE, 0x8410, 0x8410, 0xDEDB, 0xE73C, 0xE71C, 0xE71C, // 0x02B0 (688) +0xDEFB, 0xDEFB, 0xD6BA, 0xCE59, 0xC618, 0x738E, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x8C14, 0x5ACC, 0xC658, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xC638, 0x8C51, 0xA534, 0xB5B6, 0xBDF7, 0xCE59, 0xD6BA, 0x94B2, 0x738E, 0x8410, 0x8430, 0xCE59, 0xE73C, 0xDEFB, 0xDEFB, // 0x02D0 (720) +0xDEDB, 0xDEFB, 0xBDF7, 0xDEDB, 0x73AE, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x8BD2, 0x5ACC, 0xBDD6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xDEDB, 0x8C51, 0xA514, 0xAD75, 0xBDD7, 0xC638, 0xC618, 0x73AE, 0x7BCF, 0x8410, 0x5ACB, 0x8C51, 0xE73C, 0xDEDB, 0xD6BA, // 0x02F0 (752) +0xDEFB, 0xBDD7, 0xD69A, 0x8C71, 0x8C51, 0xFFFF, 0xFFFF, 0xFFDE, 0xCE5A, 0x7B71, 0x62ED, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xF7BE, 0x94B2, 0x94B2, 0xA534, 0xB596, 0xBDF7, 0xB596, 0x6B6D, 0x4208, 0x2945, 0x18C3, 0x6B6D, 0xDEFB, 0xD69A, 0xDEDB, // 0x0310 (784) +0xB5B6, 0xC618, 0x9CF3, 0x6B4D, 0xFFDE, 0xFFFF, 0xEF5D, 0xAD37, 0x62EE, 0x6B4D, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFDF, 0xFFFF, 0xBDF7, 0x8C51, 0xA514, 0xAD55, 0xB596, 0xBDD7, 0xA514, 0x738E, 0xA514, 0xB5B6, 0xCE59, 0xD69A, 0xDEDB, 0xB596, // 0x0330 (816) +0xBDF7, 0xA534, 0x6B4C, 0xEF5D, 0xF79E, 0xBDB8, 0x7370, 0x5AAC, 0x8C71, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xF79E, 0x94B2, 0x94B2, 0xA534, 0xAD55, 0xB5B6, 0xA534, 0xBDD7, 0xD69A, 0xCE59, 0xCE79, 0xCE59, 0xA534, 0x8430, // 0x0350 (848) +0x738E, 0x3186, 0x7BB0, 0x8C33, 0x7370, 0x62ED, 0x8410, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x8C71, 0x9CD3, 0xAD55, 0xB596, 0xBDD7, 0xBDD7, 0xBDF7, 0xC618, 0xB5B6, 0xA534, 0xA534, 0x632C, // 0x0370 (880) +0x6B6D, 0xB5B6, 0xAD76, 0xAD76, 0xBE17, 0xE71B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x94B2, 0x8C51, 0x94B2, 0xA534, 0xAD55, 0xAD55, 0x9CD3, 0x8C71, 0x73AE, 0x632C, 0xA534, // 0x0390 (912) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xCE59, 0xA514, 0x8430, 0x7BCF, 0x738E, 0x73AE, 0x8410, 0xA534, 0xEF7D, 0xFFFF, // 0x03B0 (944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xE73C, 0xE71C, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/tux.c b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/tux.c new file mode 100644 index 0000000..7fefd80 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Bitmap_128x128/tux.c @@ -0,0 +1,264 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: tux_64x64.png +// Time generated: 14.10.2010 21:56:38 +// Dimensions : 64x64 pixels +// Size : 8 192 Bytes + +const unsigned short tux[0x1000] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE79, 0x9CF3, 0x7BCF, 0x738E, 0x738E, // 0x0020 (32) +0x6B6D, 0x94B2, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0030 (48) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0050 (80) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE79, 0x6B4D, 0x5ACB, 0x8410, 0x9CF3, 0x9CF3, 0x9CF3, // 0x0060 (96) +0x9CD3, 0x73AE, 0x4208, 0x5ACB, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0070 (112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0090 (144) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA514, 0x3186, 0x8C51, 0xBDF7, 0xC618, 0xBDF7, 0xBDF7, 0xBDF7, // 0x00A0 (160) +0xBDF7, 0xC618, 0xBDD7, 0x738E, 0x18C3, 0x8C51, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xBDD7, 0x10A2, 0x8C71, 0x9CF3, 0x8C71, 0x8C71, 0x8C71, 0x8C71, 0x8C71, // 0x00E0 (224) +0x8C71, 0x8C51, 0x8C51, 0x9CF3, 0x73AE, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00F0 (240) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x2945, 0x31A6, 0x7BCF, 0x6B4D, 0x6B6D, 0x6B6D, 0x6B6D, 0x6B6D, 0x6B6D, // 0x0120 (288) +0x6B6D, 0x6B6D, 0x6B6D, 0x6B4D, 0x73AE, 0x2124, 0x0000, 0xAD55, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0130 (304) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0150 (336) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x0000, 0x31A6, 0x52AA, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, // 0x0160 (352) +0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x528A, 0x2104, 0x0000, 0x2965, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C71, 0x0000, 0x1082, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, // 0x01A0 (416) +0x3186, 0x3186, 0x3186, 0x3186, 0x2965, 0x0020, 0x0000, 0x0000, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01D0 (464) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x630C, 0x0000, 0x0000, 0x0861, 0x18C3, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x18C3, // 0x01E0 (480) +0x1082, 0x0841, 0x1082, 0x10A2, 0x0020, 0x0000, 0x0000, 0x0000, 0x528A, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01F0 (496) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0210 (528) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x4A49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0220 (544) +0x0861, 0x3186, 0x18C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0230 (560) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0250 (592) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39C7, 0x0000, 0x3186, 0xAD75, 0x8C51, 0x0841, 0x0000, 0x0000, 0x0000, 0x4208, // 0x0260 (608) +0xD6BA, 0xFFDF, 0xE71C, 0x630C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0270 (624) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0290 (656) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39C7, 0x0000, 0xCE59, 0xFFFF, 0xFFFF, 0x94B2, 0x0000, 0x0000, 0x10A2, 0xE73C, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000, 0x94B2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02B0 (688) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02D0 (720) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2965, 0x18E3, 0xDEDB, 0x7BCF, 0xAD75, 0xEF5D, 0x2944, 0x0000, 0x5ACA, 0xFFFF, // 0x02E0 (736) +0xAD55, 0x94B2, 0xAD55, 0xF7BE, 0x8410, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02F0 (752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0310 (784) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39E7, 0x2945, 0xA514, 0x9CF3, 0x8C71, 0xD6BB, 0x39C9, 0x0000, 0x632E, 0xF7DF, // 0x0320 (800) +0x7BEF, 0xAD54, 0x7BEF, 0xBDF7, 0xB596, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C71, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0330 (816) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0350 (848) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4A49, 0x18C3, 0x9492, 0x39E7, 0x3187, 0xA48F, 0x8323, 0x5A00, 0x93A6, 0xCDD5, // 0x0360 (864) +0x4209, 0x4249, 0x2965, 0x9CD2, 0xB575, 0x0000, 0x0000, 0x0000, 0x0000, 0x9492, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0370 (880) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0390 (912) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x5ACB, 0x0000, 0x9D14, 0x2905, 0x6A40, 0xE643, 0xFFAE, 0xFFF3, 0xFF70, 0xDD86, // 0x03A0 (928) +0x7240, 0x1840, 0x18C3, 0xC65A, 0x73CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03B0 (944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x738E, 0x0000, 0x5A6A, 0xD566, 0xFF66, 0xFFF8, 0xFFFD, 0xFFDC, 0xFFFD, 0xFFFA, // 0x03E0 (992) +0xFF0E, 0xE566, 0xC464, 0xC4CC, 0x2103, 0x0000, 0x0000, 0x0000, 0x0000, 0x6B6D, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0410 (1040) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BEF, 0x0800, 0xB440, 0xFFC6, 0xFFF3, 0xFFB4, 0xFFB2, 0xFF92, 0xFF72, 0xFF53, // 0x0420 (1056) +0xFF55, 0xFF75, 0xFEF0, 0xF542, 0x8240, 0x0000, 0x0000, 0x0000, 0x0000, 0x4228, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0430 (1072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0440 (1088) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0450 (1104) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8432, 0x4140, 0xFFE2, 0xFFEB, 0xFFAC, 0xFF8B, 0xFF4C, 0xFF2C, 0xFEEC, 0xFECB, // 0x0460 (1120) +0xFE6A, 0xFE08, 0xFDA7, 0xFDC3, 0xA320, 0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0470 (1136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0480 (1152) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0490 (1168) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9D14, 0x28A0, 0xF6E0, 0xFFE1, 0xFF43, 0xFF04, 0xFEC4, 0xFE84, 0xFE23, 0xFDE1, // 0x04A0 (1184) +0xFD60, 0xFD20, 0xFD20, 0xFD20, 0x7241, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04B0 (1200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04C0 (1216) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04D0 (1232) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xB5B6, 0x0000, 0xC4A9, 0xFEC0, 0xFF00, 0xFEA0, 0xFE40, 0xFE00, 0xFDA0, 0xFD60, // 0x04E0 (1248) +0xFD40, 0xFD20, 0xEC80, 0xDCC7, 0x8C0F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04F0 (1264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0500 (1280) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0510 (1296) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xAD75, 0x0000, 0xD69B, 0xF631, 0xF5C0, 0xFE80, 0xFE00, 0xFDC0, 0xFD60, 0xFD40, // 0x0520 (1312) +0xFCC0, 0xDC86, 0xCD93, 0xE73D, 0xE71C, 0x0861, 0x0000, 0x0000, 0x0000, 0x0000, 0x0861, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0530 (1328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0540 (1344) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0550 (1360) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x632C, 0x0000, 0xD6BA, 0xFFFF, 0xF5F1, 0xFD40, 0xFD80, 0xFD20, 0xFCE0, 0xECA3, // 0x0560 (1376) +0xDD6F, 0xE6FC, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5ACB, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0570 (1392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0580 (1408) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0590 (1424) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xDEDB, 0x0861, 0x0000, 0xD69A, 0xFFFF, 0xFFFF, 0xFED8, 0xF631, 0xF610, 0xE5F2, 0xE6B9, // 0x05A0 (1440) +0xF7BF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xE71C, 0x10A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05B0 (1456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05C0 (1472) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05D0 (1488) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x39E7, 0x0000, 0x4228, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7FF, 0xF7DF, 0xFFFF, // 0x05E0 (1504) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3186, 0xEF7D, 0xFFFF, 0xFFFF, // 0x05F0 (1520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0600 (1536) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0610 (1552) +0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x738E, 0x0000, 0x18C3, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0620 (1568) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFFF, 0xCE59, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6B4D, 0xFFFF, 0xFFFF, // 0x0630 (1584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0640 (1600) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0650 (1616) +0xFFFF, 0xFFDF, 0xFFFF, 0xA514, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0660 (1632) +0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0x2965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xAD55, 0xFFFF, // 0x0670 (1648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0680 (1664) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0690 (1680) +0xFFDF, 0xFFFF, 0xD69A, 0x0861, 0x0000, 0x2945, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06A0 (1696) +0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xFFFF, 0x7BCF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C3, 0xD6BA, // 0x06B0 (1712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06C0 (1728) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06D0 (1744) +0xFFFF, 0xFFDF, 0x39C7, 0x0000, 0x0000, 0x8430, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06E0 (1760) +0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xFFFF, 0xCE79, 0x0841, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4228, // 0x06F0 (1776) +0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0700 (1792) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x0710 (1808) +0xFFFF, 0x94B2, 0x0000, 0x0020, 0x0020, 0xCE79, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x0720 (1824) +0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xFFDF, 0x4A69, 0x0000, 0x0841, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, // 0x0730 (1840) +0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0740 (1856) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0750 (1872) +0xEF7D, 0x2104, 0x0020, 0x0000, 0x3186, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, // 0x0760 (1888) +0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xFFFF, 0xB5B6, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, // 0x0770 (1904) +0x10A2, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0780 (1920) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x0790 (1936) +0x8C71, 0x0000, 0x0861, 0x0000, 0x7BCF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x07A0 (1952) +0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xFFDF, 0x528A, 0x0000, 0x0841, 0x0020, 0x0020, 0x0020, 0x0020, // 0x07B0 (1968) +0x0000, 0x630C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x07C0 (1984) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, // 0x07D0 (2000) +0x3186, 0x0000, 0x0841, 0x10A2, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x07E0 (2016) +0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF5D, 0xF7BE, 0xBDD7, 0x0841, 0x0861, 0x0841, 0x0841, 0x0841, 0x0020, // 0x07F0 (2032) +0x0020, 0x1082, 0xC638, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0800 (2048) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDD7, // 0x0810 (2064) +0x0020, 0x1082, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, // 0x0820 (2080) +0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF7D, 0x4208, 0x0020, 0x0861, 0x0861, 0x0841, 0x0841, // 0x0830 (2096) +0x0841, 0x0000, 0x630C, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0840 (2112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x6B4D, // 0x0850 (2128) +0x0000, 0x0861, 0x2104, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, // 0x0860 (2144) +0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xE73C, 0xF7BE, 0x8430, 0x0000, 0x1082, 0x0861, 0x0861, 0x0861, // 0x0870 (2160) +0x0861, 0x0020, 0x18C3, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0880 (2176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x2124, // 0x0890 (2192) +0x0861, 0x0020, 0x8410, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, // 0x08A0 (2208) +0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xEF7D, 0xB5B6, 0x0861, 0x1082, 0x1082, 0x0861, 0x0861, // 0x08B0 (2224) +0x0861, 0x0861, 0x0000, 0x8430, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x08C0 (2240) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xA514, 0x0020, // 0x08D0 (2256) +0x10A2, 0x1082, 0xD69A, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x08E0 (2272) +0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xEF5D, 0xCE79, 0x2124, 0x1082, 0x10A2, 0x1082, 0x1082, // 0x08F0 (2288) +0x0861, 0x1082, 0x0000, 0x4208, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0900 (2304) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x4208, 0x0861, // 0x0910 (2320) +0x1082, 0x31A6, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, // 0x0920 (2336) +0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEDB, 0x39C7, 0x1082, 0x10A2, 0x10A2, 0x1082, // 0x0930 (2352) +0x1082, 0x1082, 0x0841, 0x18C3, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0940 (2368) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA534, 0x0841, 0x18C3, // 0x0950 (2384) +0x0841, 0x630C, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, // 0x0960 (2400) +0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xDEFB, 0xE73C, 0x4A49, 0x0861, 0x18C3, 0x10A2, 0x10A2, // 0x0970 (2416) +0x10A2, 0x1082, 0x1082, 0x0841, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0980 (2432) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x3186, 0x1082, 0x18E3, // 0x0990 (2448) +0x0861, 0x94B2, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, // 0x09A0 (2464) +0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEDB, 0xE73C, 0x4A69, 0x1082, 0x18E3, 0x18C3, 0x10A2, // 0x09B0 (2480) +0x10A2, 0x10A2, 0x10A2, 0x0020, 0x73AE, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x09C0 (2496) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0841, 0x18E3, 0x18E3, // 0x09D0 (2512) +0x0861, 0xAD75, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, // 0x09E0 (2528) +0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEDB, 0xE73C, 0x52AA, 0x10A2, 0x2104, 0x18E3, 0x18C3, // 0x09F0 (2544) +0x18C3, 0x18C3, 0x10A2, 0x0841, 0x630C, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A00 (2560) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0861, 0x18E4, 0x18E4, // 0x0A10 (2576) +0x1082, 0xC638, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, // 0x0A20 (2592) +0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xD6BA, 0xE71C, 0x6B4D, 0x10A2, 0x18C3, 0x18C3, 0x10A2, // 0x0A30 (2608) +0x10A2, 0x10A2, 0x18C3, 0x0861, 0x5AEB, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A40 (2624) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8410, 0x0862, 0x3143, 0x2924, // 0x0A50 (2640) +0x0882, 0xBDD7, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0A60 (2656) +0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xE73C, 0x630C, 0x2103, 0x4A69, 0x632C, 0x6B4D, // 0x0A70 (2672) +0x528A, 0x2965, 0x18C3, 0x1081, 0x738E, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A80 (2688) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x7A40, 0xECA0, 0xCC00, // 0x0A90 (2704) +0x3941, 0xA535, 0xFFFF, 0xF7BE, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, // 0x0AA0 (2720) +0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEFB, 0xD6DB, 0xCE38, 0xC618, 0x4A48, 0x4A49, 0x6B6D, 0x6B4D, 0x6B4D, // 0x0AB0 (2736) +0x6B4D, 0x630C, 0x3186, 0x18E4, 0x9492, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0AC0 (2752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xC488, 0xFD41, 0xFE6D, 0xFE6A, // 0x0AD0 (2768) +0xDC60, 0x5A25, 0xB5D8, 0xFFFF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, // 0x0AE0 (2784) +0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xD6BB, 0xBCAB, 0xD462, 0xD462, 0x49E4, 0x10C3, 0x18C3, 0x18C3, 0x18C3, // 0x0AF0 (2800) +0x18C3, 0x18E3, 0x10A3, 0x49C4, 0xB575, 0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B00 (2816) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCD70, 0xECA0, 0xFF14, 0xFF9B, 0xFF7B, // 0x0B10 (2832) +0xFECF, 0xC3A0, 0x3143, 0x9CF3, 0xFFFF, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, // 0x0B20 (2848) +0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEFB, 0xC617, 0xDC60, 0xFD60, 0xFD20, 0x3120, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B30 (2864) +0x0000, 0x0000, 0x3900, 0xE460, 0xB46A, 0xEF9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B40 (2880) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD5F4, 0xDC20, 0xFE8E, 0xFF59, 0xFF36, 0xFF36, // 0x0B50 (2896) +0xFF59, 0xFE6B, 0xA300, 0x18E4, 0x8410, 0xFFBE, 0xF7BE, 0xEF7D, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, // 0x0B60 (2912) +0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEBA, 0xDEFB, 0xC5B5, 0xE4A1, 0xFEF2, 0xF716, 0x3164, 0x18E4, 0x2103, 0x1082, 0x1082, // 0x0B70 (2928) +0x0021, 0x1061, 0xD5D0, 0xFE27, 0xB3E3, 0xCE9B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B80 (2944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77D, 0xE697, 0xDDAF, 0xD4C8, 0xE480, 0xFE29, 0xFF36, 0xFF15, 0xFF35, 0xFF15, // 0x0B90 (2960) +0xFF15, 0xFF36, 0xFDA5, 0x6A42, 0x1905, 0x6B4C, 0xE73C, 0xFFDF, 0xEF5D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, // 0x0BA0 (2976) +0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xDEDB, 0xBDB5, 0xE4C3, 0xFF56, 0xFFDB, 0xAD10, 0x10A2, 0x10C3, 0x18E4, 0x1082, // 0x0BB0 (2992) +0x2922, 0xC5B1, 0xFFDC, 0xFED1, 0xB3A2, 0xBE19, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0BC0 (3008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE6B8, 0xD484, 0xE4C0, 0xF584, 0xFE28, 0xFECF, 0xFF14, 0xFF13, 0xFF13, 0xFF13, 0xFF13, // 0x0BD0 (3024) +0xFF13, 0xFF14, 0xFEF0, 0xDC80, 0x41C5, 0x2945, 0x5269, 0xCE59, 0xF7BE, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, // 0x0BE0 (3040) +0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD69A, 0xD6DB, 0xBD95, 0xE4E2, 0xFF33, 0xFF36, 0xFF97, 0xDDF1, 0x8B66, 0x7AE4, 0x9BC7, // 0x0BF0 (3056) +0xEEB2, 0xFF97, 0xFF37, 0xFEF0, 0xC3E0, 0xB5B7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C00 (3072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD52B, 0xFD60, 0xFECD, 0xFF33, 0xFF13, 0xFF12, 0xFEF1, 0xFEF1, 0xFEF1, 0xFEF1, 0xFEF1, // 0x0C10 (3088) +0xFEF1, 0xFEF1, 0xFF12, 0xFE69, 0x9B41, 0x31A8, 0x31A6, 0x39E7, 0xB5B6, 0xF79E, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, // 0x0C20 (3104) +0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD699, 0xD6BA, 0xBD94, 0xE502, 0xFF12, 0xFF15, 0xFEF4, 0xFF55, 0xFF95, 0xFF54, 0xFF95, // 0x0C30 (3120) +0xFF35, 0xFEF4, 0xFF14, 0xFF14, 0xF5A4, 0xB426, 0xE75E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C40 (3136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD54C, 0xFDA0, 0xFECE, 0xFEF0, 0xFECF, 0xFEEF, 0xFEEF, 0xFEF0, 0xFEEF, 0xFEF0, 0xFEF0, // 0x0C50 (3152) +0xFEF0, 0xFEEF, 0xFEF0, 0xFEEF, 0xF582, 0x6244, 0x39E8, 0x39C6, 0x528A, 0xE71C, 0xE73C, 0xE71C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, // 0x0C60 (3168) +0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE9A, 0xBD94, 0xE522, 0xFF10, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, // 0x0C70 (3184) +0xFEF2, 0xFF12, 0xFEF2, 0xFEF2, 0xFF12, 0xED85, 0xBC68, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C80 (3200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD5B0, 0xF580, 0xFECB, 0xFEEE, 0xFECD, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, // 0x0C90 (3216) +0xFEEE, 0xFEEE, 0xFECD, 0xFECE, 0xFECA, 0xCC60, 0x41C7, 0x39C7, 0x4228, 0xCE79, 0xEF5D, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, // 0x0CA0 (3232) +0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE59, 0xCE9A, 0xBD73, 0xED42, 0xFF0F, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, // 0x0CB0 (3248) +0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFF31, 0xF628, 0xC4A7, 0xDE57, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0CC0 (3264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDE13, 0xF560, 0xFEC9, 0xFECD, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, // 0x0CD0 (3280) +0xFEEC, 0xFEEC, 0xFECC, 0xFECC, 0xFEED, 0xFE44, 0x9323, 0x52CC, 0x73AE, 0xD69A, 0xE73C, 0xDEFB, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, // 0x0CE0 (3296) +0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE59, 0xD69A, 0xB5D8, 0x7B28, 0xF5A2, 0xFF0F, 0xFECE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, // 0x0CF0 (3312) +0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFECD, 0xFF10, 0xFEA9, 0xCC60, 0xD615, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D00 (3328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDE55, 0xED80, 0xFEA4, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFEC9, // 0x0D10 (3344) +0xFEA7, 0xFEA6, 0xFEA8, 0xFEC9, 0xFECB, 0xFEEA, 0xEDA2, 0xB4F0, 0xCE9A, 0xDEFB, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, // 0x0D20 (3360) +0xD6BA, 0xD69A, 0xCE79, 0xCE79, 0xD6BA, 0xB596, 0x4A8B, 0x72A4, 0xFE45, 0xFEEC, 0xFECC, 0xFEEC, 0xFEEC, 0xFEEC, 0xFEEC, 0xFEEC, // 0x0D30 (3376) +0xFEEC, 0xFECB, 0xFECB, 0xFEEC, 0xFEEC, 0xFEEC, 0xFECC, 0xFEA5, 0xFDE0, 0xAC8B, 0xE75E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D40 (3392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE632, 0xF5E0, 0xFE80, 0xFE82, 0xFEC7, 0xFEC8, 0xFEC8, 0xFEC8, 0xFEC7, 0xFEA4, 0xFE61, // 0x0D50 (3408) +0xFE60, 0xFE60, 0xFE60, 0xFE61, 0xFE83, 0xFEA6, 0xFEA3, 0xDD22, 0xD658, 0xE75D, 0xDEDB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, // 0x0D60 (3424) +0xD69A, 0xD69A, 0xD6BA, 0xCE59, 0x9492, 0x5289, 0x39E9, 0x9B84, 0xFEA3, 0xFEEB, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEC8, // 0x0D70 (3440) +0xFE84, 0xFE61, 0xFE61, 0xFEA5, 0xFEC9, 0xFEA7, 0xFEA2, 0xFE80, 0xBC41, 0x8C0F, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D80 (3456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDDCE, 0xFE40, 0xFEA0, 0xFE80, 0xFE80, 0xFEA2, 0xFEA2, 0xFEA2, 0xFEA0, 0xFE80, 0xFE80, // 0x0D90 (3472) +0xFEA0, 0xFEA0, 0xFEA0, 0xFE80, 0xFE80, 0xFE80, 0xFE80, 0xFE80, 0xCCE5, 0xD69A, 0xE73C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, // 0x0DA0 (3488) +0xD69A, 0xBDF7, 0x9CD3, 0x630C, 0x4228, 0x4A69, 0x422A, 0xB423, 0xFEC0, 0xFEA5, 0xFEE7, 0xFEC7, 0xFEC7, 0xFEC6, 0xFEA3, 0xFE80, // 0x0DB0 (3504) +0xFE80, 0xFE80, 0xFE80, 0xFE60, 0xFEA0, 0xFEC0, 0xEDC0, 0xA3A4, 0x732C, 0xAD96, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0DC0 (3520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE5A8, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0DD0 (3536) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xF640, 0x93A8, 0x8C72, 0xA534, 0xAD75, 0xA534, 0x9CF3, 0x8C51, // 0x0DE0 (3552) +0x738E, 0x5ACB, 0x4A49, 0x4A69, 0x528A, 0x4A8A, 0x5249, 0xD502, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC1, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, // 0x0DF0 (3568) +0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFE60, 0xC482, 0x7B09, 0x7BD0, 0xB5B7, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E00 (3584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDD8A, 0xFEC0, 0xFF20, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, // 0x0E10 (3600) +0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEC0, 0xFF20, 0xAC02, 0x4209, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, // 0x0E20 (3616) +0x528A, 0x528A, 0x52AA, 0x52AA, 0x528A, 0x4A8A, 0x5A69, 0xE5C1, 0xFF00, 0xFEC0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, // 0x0E30 (3632) +0xFEC0, 0xFEE0, 0xFF00, 0xE561, 0x9367, 0x736E, 0x9D14, 0xD6BA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E40 (3648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD617, 0xCCC5, 0xF620, 0xFEE0, 0xFF40, 0xFF40, 0xFF40, 0xFF20, 0xFF00, 0xFF00, 0xFF00, // 0x0E50 (3664) +0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF40, 0xB483, 0x4A8B, 0x5ACA, 0x5ACB, 0x5ACB, 0x5ACB, 0x5ACB, // 0x0E60 (3680) +0x5ACB, 0x52AA, 0x52AA, 0x52AA, 0x52AA, 0x4A8A, 0x6289, 0xEE20, 0xFF20, 0xFEE0, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFEE0, // 0x0E70 (3696) +0xFF20, 0xFEC0, 0xBC64, 0x732B, 0x8C72, 0xCE58, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E80 (3712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7E, 0xB576, 0x93EE, 0xA408, 0xC4A5, 0xDD63, 0xF641, 0xFEC0, 0xFF40, 0xFF80, 0xFF60, // 0x0E90 (3728) +0xFF40, 0xFF20, 0xFF20, 0xFF40, 0xFF40, 0xFF40, 0xFF20, 0xFF20, 0xFF80, 0xAC03, 0x4A6B, 0x5ACA, 0x5ACB, 0x5ACB, 0x5AEB, 0x5AEB, // 0x0EA0 (3744) +0x5AEB, 0x630C, 0x630C, 0x630C, 0x5AEB, 0x52CB, 0x5A69, 0xE5E1, 0xFF60, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF60, // 0x0EB0 (3760) +0xF640, 0xA3A7, 0x738F, 0xAD96, 0xE71C, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0EC0 (3776) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0xD6DB, 0xB5B8, 0x9CD4, 0x9431, 0x93EE, 0x9C0A, 0xB467, 0xD544, 0xF660, // 0x0ED0 (3792) +0xFF60, 0xFFA0, 0xFF80, 0xFF60, 0xFF40, 0xFF40, 0xFF60, 0xFFA0, 0xD521, 0x730A, 0x73CF, 0x8C71, 0x9CD3, 0x9CF3, 0xA514, 0xA534, // 0x0EE0 (3808) +0xAD55, 0xB596, 0xB5B6, 0xB596, 0xAD55, 0x9CF3, 0x83F0, 0xCD04, 0xFFA0, 0xFF40, 0xFF40, 0xFF40, 0xFF40, 0xFF40, 0xFFA0, 0xF621, // 0x0EF0 (3824) +0x8B49, 0x8431, 0xCE58, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F00 (3840) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xF79E, 0xE73C, 0xD6BB, 0xBE19, 0xA556, 0x9472, 0x9C0D, // 0x0F10 (3856) +0xB447, 0xDD82, 0xFEE0, 0xFFA0, 0xFFC0, 0xFFC0, 0xFF80, 0xC4C2, 0x730C, 0x9CF4, 0xD69A, 0xEF5D, 0xEF7D, 0xF79E, 0xF79E, 0xF7BE, // 0x0F20 (3872) +0xF7BE, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xEF7D, 0xDF1C, 0xC530, 0xF620, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFF80, 0xE5A2, 0x834A, // 0x0F30 (3888) +0x8C93, 0xDEDA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F40 (3904) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDE, 0xEF7D, 0xD6BB, // 0x0F50 (3920) +0xAD77, 0x9452, 0x9BEB, 0xB466, 0xC524, 0xC543, 0xA3E5, 0x734D, 0xAD76, 0xEF5C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F60 (3936) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF1C, 0xACB0, 0xBCA6, 0xD544, 0xCD64, 0xCD05, 0xAC07, 0x7B6D, 0x9CF4, // 0x0F70 (3952) +0xE6FB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F80 (3968) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F90 (3984) +0xFFDE, 0xE75D, 0xC65A, 0xA536, 0x9493, 0x8C53, 0x94B4, 0xBE18, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FA0 (4000) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xDEFC, 0xAD57, 0x9493, 0x8C73, 0x8C73, 0x94D4, 0xBE18, 0xEF5D, // 0x0FB0 (4016) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FC0 (4032) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FD0 (4048) +0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xEF5C, 0xE73C, 0xEF5C, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FE0 (4064) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xEF5C, 0xE73C, 0xEF5C, 0xEF7D, 0xFFDE, 0xFFFF, // 0x0FF0 (4080) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x1000 (4096) +}; diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino new file mode 100644 index 0000000..8cee78e --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino @@ -0,0 +1,93 @@ +// UTFT_CPLD_PageSwitching (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of page switching on CPLD-based display modules.. +// +// This demo was made for modules with a screen resolution +// of 800x480 pixels. +// +// This program requires the UTFT library. +// +// NOTE: The display will be black for a short while during the start +// + +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(EHOUSE50CPLD,22,23,31,33); + +void setup() +{ + myGLCD.InitLCD(); +} + +void loop() +{ + myGLCD.setBackColor(VGA_TRANSPARENT); + + myGLCD.setBrightness(0); + for (byte pg=0; pg<8; pg++) + { + myGLCD.setWritePage(pg); + myGLCD.clrScr(); + for (int ln=0; ln<480; ln+=2) + { + switch (pg) + { + case 0: + myGLCD.setColor(ln/2, 0, 0); + break; + case 1: + myGLCD.setColor(0, ln/2, 0); + break; + case 2: + myGLCD.setColor(0, 0, ln/2); + break; + case 3: + myGLCD.setColor(ln/4, ln/2, 0); + break; + case 4: + myGLCD.setColor(0, ln/2, ln/2); + break; + case 5: + myGLCD.setColor(ln/2, 0, ln/2); + break; + case 6: + myGLCD.setColor(ln/2, ln/2, 0); + break; + case 7: + myGLCD.setColor(0, ln/2, ln/4); + break; + } + myGLCD.drawLine(0, ln, 799, ln); + myGLCD.drawLine(0, ln+1, 799, ln+1); + } + myGLCD.setColor(VGA_WHITE); + myGLCD.setFont(BigFont); + myGLCD.print("This is page:", CENTER, 200); + myGLCD.setFont(SevenSegNumFont); + myGLCD.printNumI(pg, CENTER, 240); + } + myGLCD.setBrightness(16); + + while(1) + { + for (byte pg=0; pg<8; pg++) + { + myGLCD.setDisplayPage(pg); + delay(500); + } + } +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino new file mode 100644 index 0000000..de371d9 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino @@ -0,0 +1,335 @@ +// UTFT_Demo_128x128_Serial (C)2013 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made to work on the 128x128 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Declare an instance of the class +UTFT myGLCD(LPH9135,6,5,2,3,4); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(PORTRAIT); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + byte buf[126]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + myGLCD.setContrast(64); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0,0,127,12); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0,117,127,127); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255,0,0); + myGLCD.print("Universal TFT", CENTER, 0); + myGLCD.setBackColor(64,64,64); + myGLCD.setColor(255,255,0); + myGLCD.print("H.Karlsen", LEFT, 116); + myGLCD.print("(C)2013", RIGHT, 116); + myGLCD.setColor(0,255,0); + myGLCD.drawRect(0,13,127,116); + +// Draw crosshairs + myGLCD.setColor(0,0,255); + myGLCD.drawLine(63,14,63,115); + myGLCD.drawLine(1,63,126,63); + for (int i=3; i<128; i+=10) + myGLCD.drawLine(i, 61, i, 65); + for (int i=14; i<118; i+=10) + myGLCD.drawLine(61, i, 65, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.setBackColor(0,0,0); + myGLCD.print("Sin", 2, 14); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(sin(((i*2.85)*3.14)/180)*45)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 2, 26); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(cos(((i*2.85)*3.14)/180)*45)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 2, 38); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(tan(((i*2.85)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + myGLCD.setColor(0,0,255); + myGLCD.drawLine(63,14,63,115); + myGLCD.drawLine(1,63,126,63); + +// Draw a moving sinewave + x=1; + for (int i=1; i<3654; i++) + { + x++; + if (x==127) + x=1; + if (i>127) + { + if ((x==63)||(buf[x-1]==63)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=63+(sin(((i*1.3)*3.14)/180)*45); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + delay(1); + } + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(10+(i*10),10+(i*10), 60+(i*10), 60+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(70-(i*10),10+(i*10), 120-(i*10), 60+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(30+(i*10),35+(i*10), 25); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + + // Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=11; i<115; i+=3) + { + myGLCD.drawLine(1, i, i-10, 115); + } + myGLCD.setColor (255,0,0); + for (int i=112; i>14; i-=3) + { + myGLCD.drawLine(126, i, i+14, 14); + } + myGLCD.setColor (0,255,255); + for (int i=115; i>14; i-=3) + { + myGLCD.drawLine(1, i, 116-i, 14); + } + myGLCD.setColor (0,255,255); + for (int i=14; i<115; i+=3) + { + myGLCD.drawLine(126, i, 140-i, 115); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(85); + y=35+random(59); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random lines + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random pixels + for (int i=0; i<5000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(124), 15+random(101)); + } + + delay (2000); + +// Set up the "Finished"-screen + myGLCD.setContrast(0); + myGLCD.fillScr(0,0,255); + myGLCD.setColor(255,0,0); + myGLCD.fillRoundRect(2, 40, 125, 88); + + myGLCD.setColor(255,255,255); + myGLCD.setBackColor(255,0,0); + myGLCD.print("That's it!", CENTER, 46); + myGLCD.print("Restarting in a", CENTER, 66); + myGLCD.print("few seconds...", CENTER, 76); + + myGLCD.setColor(0,0,0); + myGLCD.setBackColor(0,0,255); + myGLCD.print("Runtime: (msecs)", CENTER, 108); + myGLCD.printNumI(millis(), CENTER, 118); + + myGLCD.setContrast(64); + + delay (10000); + +// Fade screen to black + for (int i=64; i>0; i--) + { + myGLCD.setContrast(i); + delay(100); + } +} + + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino new file mode 100644 index 0000000..5ff7106 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino @@ -0,0 +1,328 @@ +// UTFT_Demo_160x128_Serial (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 160x128 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Usage: myGLCD(, SDA, SCL, CS, RST[, RS]); +// +// When using the DM-TFT18-101 and shield from DisplayModule you should use the following: +// UTFT myGLCD(DMTFT18101,2,3,4,6,5); +// +UTFT myGLCD(ITDB18SP,19,18,0,16,17); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[158]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 159, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 114, 159, 127); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("Universal TFT Lib.", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("H.Karlsen", LEFT, 114); + myGLCD.print("(C)2014", RIGHT, 114); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 13, 159, 113); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(79, 14, 79, 113); + myGLCD.drawLine(1, 63, 158, 63); + + for (int i=9; i<150; i+=10) + myGLCD.drawLine(i, 61, i, 65); + for (int i=19; i<110; i+=10) + myGLCD.drawLine(77, i, 81, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(sin(((i*2.27)*3.14)/180)*40)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(cos(((i*2.27)*3.14)/180)*40)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(tan(((i*2.27)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(79, 14, 79, 113); + myGLCD.drawLine(1, 63, 158, 63); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(158*20); i++) + { + x++; + if (x==159) + x=1; + if (i>159) + { + if ((x==79)||(buf[x-1]==63)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=63+(sin(((i*2.5)*3.14)/180)*(40-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(39+(i*10), 23+(i*10), 59+(i*10), 43+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(99-(i*10), 23+(i*10), 119-(i*10), 43+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(49+(i*10),33+(i*10), 15); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=14; i<113; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 112); + } + myGLCD.setColor (255,0,0); + for (int i=112; i>15; i-=5) + { + myGLCD.drawLine(158, i, (i*1.44)-12, 14); + } + myGLCD.setColor (0,255,255); + for (int i=112; i>15; i-=5) + { + myGLCD.drawLine(1, i, 172-(i*1.44), 14); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<112; i+=5) + { + myGLCD.drawLine(158, i, 171-(i*1.44), 112); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(116); + y=35+random(57); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + + for (int i=0; i<5000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(156), 16+random(95)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(10, 17, 149, 72); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 20); + myGLCD.print("Restarting in a", CENTER, 45); + myGLCD.print("few seconds...", CENTER, 57); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 103); + myGLCD.printNumI(millis(), CENTER, 115); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176/UTFT_Demo_220x176.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176/UTFT_Demo_220x176.ino new file mode 100644 index 0000000..b6b3ab2 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176/UTFT_Demo_220x176.ino @@ -0,0 +1,330 @@ +// UTFT_Demo_220x176 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 220x176 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB22,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[218]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 219, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 162, 219, 175); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("** Universal TFT Library **", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("> elec.henningkarlsen.com <", CENTER, 163); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 219, 161); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + + for (int i=9; i<210; i+=10) + myGLCD.drawLine(i, 86, i, 90); + for (int i=19; i<155; i+=10) + myGLCD.drawLine(107, i, 111, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(sin(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(cos(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(tan(((i*1.65)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(218*20); i++) + { + x++; + if (x==219) + x=1; + if (i>219) + { + if ((x==109)||(buf[x-1]==88)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=88+(sin(((i*1.6)*3.14)/180)*(65-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(44+(i*15), 23+(i*15), 88+(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(132-(i*15), 23+(i*15), 172-(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(64+(i*15),43+(i*15), 20); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 160); + } + myGLCD.setColor (255,0,0); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(218, i, (i*1.44)-12, 15); + } + myGLCD.setColor (0,255,255); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(1, i, 232-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(218, i, 231-(i*1.44), 160); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(176); + y=35+random(105); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(216), 16+random(143)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(40, 57, 179, 119); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 62); + myGLCD.print("Restarting in a", CENTER, 88); + myGLCD.print("few seconds...", CENTER, 101); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 146); + myGLCD.printNumI(millis(), CENTER, 161); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino new file mode 100644 index 0000000..7ed75ac --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino @@ -0,0 +1,323 @@ +// UTFT_Demo_220x176_Serial (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for serial modules with a screen resolution +// of 220x176 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Usage: myGLCD(, SDA, SCL, CS, RST[, RS]); +UTFT myGLCD(ITDB22SP,19,18,0,16); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[218]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 219, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 162, 219, 175); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("** Universal TFT Library **", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("> elec.henningkarlsen.com <", CENTER, 163); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 219, 161); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + + for (int i=9; i<210; i+=10) + myGLCD.drawLine(i, 86, i, 90); + for (int i=19; i<155; i+=10) + myGLCD.drawLine(107, i, 111, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(sin(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(cos(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(tan(((i*1.65)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(218*20); i++) + { + x++; + if (x==219) + x=1; + if (i>219) + { + if ((x==109)||(buf[x-1]==88)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=88+(sin(((i*1.6)*3.14)/180)*(65-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(44+(i*15), 23+(i*15), 88+(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(132-(i*15), 23+(i*15), 172-(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(64+(i*15),43+(i*15), 20); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 160); + } + myGLCD.setColor (255,0,0); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(218, i, (i*1.44)-12, 15); + } + myGLCD.setColor (0,255,255); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(1, i, 232-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(218, i, 231-(i*1.44), 160); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,161); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(176); + y=35+random(105); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(216), 16+random(143)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(40, 57, 179, 119); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 62); + myGLCD.print("Restarting in a", CENTER, 88); + myGLCD.print("few seconds...", CENTER, 101); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 146); + myGLCD.printNumI(millis(), CENTER, 161); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240/UTFT_Demo_320x240.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240/UTFT_Demo_320x240.ino new file mode 100644 index 0000000..ce458f3 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240/UTFT_Demo_320x240.ino @@ -0,0 +1,329 @@ +// UTFT_Demo_320x240 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[318]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 319, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 319, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 319, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + for (int i=9; i<310; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(157, i, 161, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(318*20); i++) + { + x++; + if (x==319) + x=1; + if (i>319) + { + if ((x==159)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(70+(i*20), 30+(i*20), 130+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(190-(i*20), 30+(i*20), 250-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(100+(i*20),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(318, i, (i*1.44)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 331-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(318, i, 330-(i*1.44), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(256); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(209); + x2=2+random(316); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(316), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(80, 70, 239, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino new file mode 100644 index 0000000..19da792 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino @@ -0,0 +1,343 @@ +// UTFT_Demo_320x240_Serial (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// +// ******************************************************************** +// * IMPORTANT: Read the comments in the setup() function when * +// * using the DisplayModule DM-TFT28-105. * +// ******************************************************************** +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Usage: myGLCD(, SDA, SCL, CS, RST[, RS]); +//UTFT myGLCD(TFT01_22SP,9,8,12,11,10); // ElecFreaks TFT01-2.2SP +UTFT myGLCD(DMTFT28105,MOSI,SCK,10,NOTINUSE,9); // DisplayModule DM-TFT28-105 + +void setup() +{ +// DisplayModule +// ------------- +// The following 4 lines are needed for the DM-TFT28-105 display +// module to set the SS/CS pins for the other devices connected +// to the Arduino SPI pins. If you are using any other display +// module these lines should be commented out. +// ------------------------------------------------------------- + pinMode(10,OUTPUT); digitalWrite(10,HIGH); // TFT SS/CE + pinMode(8, OUTPUT); digitalWrite(8, HIGH); // SD card SS/CE + pinMode(6, OUTPUT); digitalWrite(6, HIGH); // Flash chip SS/CE + pinMode(4, OUTPUT); digitalWrite(4, HIGH); // Touch controller SS/CE +// ------------------------------------------------------------- + + +// Just get some random numbers + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[318]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 319, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 319, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 319, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + for (int i=9; i<310; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(157, i, 161, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(318*20); i++) + { + x++; + if (x==319) + x=1; + if (i>319) + { + if ((x==159)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(70+(i*20), 30+(i*20), 130+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(190-(i*20), 30+(i*20), 250-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(100+(i*20),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(318, i, (i*1.44)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 331-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(318, i, 330-(i*1.44), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(256); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(209); + x2=2+random(316); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(316), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(80, 70, 239, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_400x240/UTFT_Demo_400x240.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_400x240/UTFT_Demo_400x240.ino new file mode 100644 index 0000000..078902c --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_400x240/UTFT_Demo_400x240.ino @@ -0,0 +1,331 @@ +// UTFT_Demo_400x240 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 400x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32WD,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[398]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 399, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 399, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("*** Universal Color TFT Display Library ***", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("< http://electronics.henningkarlsen.com >", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 399, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(199, 15, 199, 224); + myGLCD.drawLine(1, 119, 398, 119); + for (int i=9; i<390; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(197, i, 201, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<398; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*0.9)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<398; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*0.9)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<398; i++) + { + y=119+(tan(((i*0.9)*3.14)/180)); + if ((y>15) && (y<224)) + myGLCD.drawPixel(i,y); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(199, 15, 199, 224); + myGLCD.drawLine(1, 119, 398, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(398*20); i++) + { + x++; + if (x==399) + x=1; + if (i>399) + { + if ((x==199)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(110+(i*20), 30+(i*20), 170+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(230-(i*20), 30+(i*20), 290-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(110+(i*30),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.77)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(398, i, (i*1.77)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 411-(i*1.77), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(398, i, 410-(i*1.77), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(336); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(207); + x2=2+random(396); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(207); + x2=2+random(396); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(209); + x2=2+random(396); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(396), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(120, 70, 279, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x272/UTFT_Demo_480x272.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x272/UTFT_Demo_480x272.ino new file mode 100644 index 0000000..41c1973 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x272/UTFT_Demo_480x272.ino @@ -0,0 +1,328 @@ +// UTFT_Demo_480x272 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 480x272 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB43,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[478]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 479, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 258, 479, 271); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 259); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 479, 257); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 256); + myGLCD.drawLine(1, 135, 478, 135); + for (int i=9; i<470; i+=10) + myGLCD.drawLine(i, 133, i, 138); + for (int i=15; i<256; i+=10) + myGLCD.drawLine(237, i, 241, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 256); + myGLCD.drawLine(1, 135, 478, 135); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(478*20); i++) + { + x++; + if (x==479) + x=1; + if (i>479) + { + if ((x==239)||(buf[x-1]==135)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=135+(sin(((i*1.65)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(150+(i*20), 46+(i*20), 210+(i*20), 106+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(330-(i*20), 46+(i*20), 270-(i*20), 106+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(180+(i*20),75+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<256; i+=5) + { + myGLCD.drawLine(1, i, (i*1.88)-10, 256); + } + myGLCD.setColor (255,0,0); + for (int i=256; i>15; i-=5) + { + myGLCD.drawLine(478, i, (i*1.88)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=256; i>15; i-=5) + { + myGLCD.drawLine(1, i, 491-(i*1.88), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<256; i+=5) + { + myGLCD.drawLine(478, i, 490-(i*1.88), 256); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some random circles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(416); + y=45+random(178); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some random rectangles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some random rounded rectangles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(476), 16+random(239)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(160, 70, 319, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 243); + myGLCD.printNumI(millis(), CENTER, 258); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x320/UTFT_Demo_480x320.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x320/UTFT_Demo_480x320.ino new file mode 100644 index 0000000..6746a93 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_480x320/UTFT_Demo_480x320.ino @@ -0,0 +1,329 @@ +// UTFT_Demo_480x320 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 480x320 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(CTE32HR,25,26,27,28); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[478]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 479, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 306, 479, 319); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 307); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 479, 305); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 304); + myGLCD.drawLine(1, 159, 478, 159); + for (int i=9; i<470; i+=10) + myGLCD.drawLine(i, 157, i, 161); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(237, i, 241, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 304); + myGLCD.drawLine(1, 159, 478, 159); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(478*15); i++) + { + x++; + if (x==479) + x=1; + if (i>479) + { + if ((x==239)||(buf[x-1]==159)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=159+(sin(((i*0.7)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(150+(i*20), 70+(i*20), 210+(i*20), 130+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(270-(i*20), 70+(i*20), 330-(i*20), 130+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(180+(i*20),100+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<304; i+=5) + { + myGLCD.drawLine(1, i, (i*1.6)-10, 304); + } + myGLCD.setColor (255,0,0); + for (int i=304; i>15; i-=5) + { + myGLCD.drawLine(478, i, (i*1.6)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=304; i>15; i-=5) + { + myGLCD.drawLine(1, i, 491-(i*1.6), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<304; i+=5) + { + myGLCD.drawLine(478, i, 490-(i*1.6), 304); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(416); + y=45+random(226); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(476), 16+random(289)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(160, 70, 319, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 290); + myGLCD.printNumI(millis(), CENTER, 305); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_800x480/UTFT_Demo_800x480.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_800x480/UTFT_Demo_800x480.ino new file mode 100644 index 0000000..293bc00 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Demo_800x480/UTFT_Demo_800x480.ino @@ -0,0 +1,288 @@ +// UTFT_Demo_800x480 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 800x480 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB50,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[798]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 799, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 466, 799, 479); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 467); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 799, 465); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(399, 15, 399, 464); + myGLCD.drawLine(1, 239, 798, 239); + for (int i=9; i<790; i+=10) + myGLCD.drawLine(i, 237, i, 242); + for (int i=19; i<470; i+=10) + myGLCD.drawLine(397, i, 402, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(sin(((i*1.13)*3.14)/180)*200)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(cos(((i*1.13)*3.14)/180)*200)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(tan(((i*0.9)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(399, 15, 399, 464); + myGLCD.drawLine(1, 239, 798, 239); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(798*20); i++) + { + x++; + if (x==799) + x=1; + if (i>799) + { + if ((x==399)||(buf[x-1]==239)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=239+(sin(((i*1.65)*3.14)/180)*(200-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled rectangles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(746); + y=16+random(397); + x2=x+50; + y2=y+50; + myGLCD.fillRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled, rounded rectangles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(746); + y=16+random(397); + x2=x+50; + y2=y+50; + myGLCD.fillRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled circles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=27+random(746); + y=41+random(397); + myGLCD.fillCircle(x, y, 25); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<463; i+=5) + { + myGLCD.drawLine(1, i, (i*1.66)-10, 463); + } + myGLCD.setColor (255,0,0); + for (int i=463; i>15; i-=5) + { + myGLCD.drawLine(798, i, (i*1.66)+30, 15); + } + myGLCD.setColor (0,255,255); + for (int i=463; i>15; i-=5) + { + myGLCD.drawLine(1, i, 770-(i*1.66), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<463; i+=5) + { + myGLCD.drawLine(798, i, 810-(i*1.66), 463); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random circles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(736); + y=45+random(386); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random rectangles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random rounded rectangles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(796), 16+random(447)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(320, 190, 479, 289); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 213); + myGLCD.print("Restarting in a", CENTER, 239); + myGLCD.print("few seconds...", CENTER, 252); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 450); + myGLCD.printNumI(millis(), CENTER, 465); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino new file mode 100644 index 0000000..9f2a83f --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino @@ -0,0 +1,37 @@ +// UTFT_Rotate_Bitmap (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This program requires the UTFT library. +// + +#include + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +extern unsigned short biohazard[0x1000]; + +void setup() +{ + myGLCD.InitLCD(LANDSCAPE); + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(0, 0, 0); +} + +void loop() +{ + for (int i=0; i<360; i+=5) + { + myGLCD.drawBitmap (10, 10, 64, 64, biohazard, i, 32, 32); + } +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/biohazard.c b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/biohazard.c new file mode 100644 index 0000000..ca1348d --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Rotate_Bitmap/biohazard.c @@ -0,0 +1,264 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: biohazard1_L.png +// Time generated: 12.06.2011 00:23:59 +// Dimensions : 64x64 pixels +// Size : 8 192 Bytes + +const unsigned short biohazard[0x1000] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0xC638, 0x9492, 0x6B4D, 0x4228, 0x2945, 0x2124, 0x18C3, 0x1082, // 0x0020 (32) +0x1082, 0x10A2, 0x18C3, 0x2124, 0x2965, 0x4A49, 0x6B6D, 0x9CD3, 0xCE79, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0030 (48) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0050 (80) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xBDD7, 0x6B6D, 0x2965, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0060 (96) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0x31A6, 0x73AE, 0xC618, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0070 (112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0090 (144) +0xFFFF, 0xFFFF, 0xE73C, 0x8C71, 0x3186, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, // 0x00A0 (160) +0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x4207, 0x9CF3, 0xF79E, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00D0 (208) +0xEF7D, 0x8C51, 0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00E0 (224) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x2965, 0x9CD3, // 0x00F0 (240) +0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD75, // 0x0110 (272) +0x2965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0020, 0x2901, 0x5241, 0x7B41, 0x9C02, 0xACA2, 0xBD02, // 0x0120 (288) +0xC521, 0xBD02, 0xACA2, 0x9C22, 0x7B41, 0x5241, 0x2901, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0130 (304) +0x39E7, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xEF5D, 0x630C, 0x0000, // 0x0150 (336) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x41C1, 0x93E1, 0xD5A1, 0xFEA1, 0xFF01, 0xFF20, 0xFF20, 0xFF20, 0xFF00, // 0x0160 (352) +0xFF00, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF01, 0xFEA1, 0xD5A1, 0x93E1, 0x49E1, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0170 (368) +0x0000, 0x0841, 0x7BEF, 0xF7BE, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x2965, 0x0000, 0x0000, // 0x0190 (400) +0x0000, 0x0000, 0x0000, 0x0000, 0x18A0, 0x7B41, 0xD5A1, 0xFF01, 0xFF20, 0xFEE0, 0xFEC0, 0xFEA0, 0xF680, 0xF680, 0xFEA0, 0xFEA0, // 0x01A0 (416) +0xFEA0, 0xFEA0, 0xFEA0, 0xF680, 0xF680, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF01, 0xD5A1, 0x7B41, 0x1880, 0x0000, 0x0000, 0x0000, // 0x01B0 (432) +0x0000, 0x0000, 0x0000, 0x4208, 0xDEDB, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD55, 0x1082, 0x0000, 0x0000, 0x0000, // 0x01D0 (464) +0x0000, 0x0000, 0x0840, 0x7B62, 0xEE41, 0xFF21, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF20, 0xFF20, 0xFEA1, 0xFEC0, // 0x01E0 (480) +0xFEC0, 0xFEC0, 0xFEA1, 0xFF00, 0xFF20, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF21, 0xEE41, 0x7B62, 0x0840, 0x0000, // 0x01F0 (496) +0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0xC618, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0210 (528) +0x0000, 0x5201, 0xDDE1, 0xFF21, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF40, 0xF6A1, 0xB4C1, 0x7322, 0xA441, 0xFEE0, // 0x0220 (544) +0xFEA0, 0xFEE0, 0xA461, 0x7322, 0xACA1, 0xF681, 0xFF40, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF21, 0xDDE2, 0x4A01, // 0x0230 (560) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1082, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x9492, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, // 0x0250 (592) +0x9402, 0xFF01, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xFF01, 0x9401, 0x3961, 0x7341, 0xCD81, 0xF680, 0xFEC0, // 0x0260 (608) +0xFEA0, 0xFEC0, 0xF681, 0xCD81, 0x7B61, 0x3961, 0x8BE1, 0xFEE1, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF01, // 0x0270 (624) +0x9402, 0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xA534, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x20C0, 0xCD61, // 0x0290 (656) +0xFF40, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF01, 0xE621, 0x39A1, 0x20E1, 0xCD81, 0xFF40, 0xFEE0, 0xFEC0, 0xFEC0, // 0x02A0 (672) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEE0, 0xFF41, 0xCDC1, 0x2901, 0x3961, 0xDE01, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEA0, // 0x02B0 (688) +0xFF21, 0xC561, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x1082, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC618, 0x0861, 0x0000, 0x0000, 0x0000, 0x0000, 0x3121, 0xDE01, 0xFF00, // 0x02D0 (720) +0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF01, 0xD5A2, 0x18A0, 0x20E0, 0xF682, 0xFF01, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, // 0x02E0 (736) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xF6A1, 0x2920, 0x1080, 0xCDA2, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x02F0 (752) +0xFE80, 0xFF00, 0xDE01, 0x2921, 0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000, 0x2921, 0xEE41, 0xFF00, 0xFEA0, // 0x0310 (784) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xDE02, 0x18A1, 0x0840, 0xDDE1, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0320 (800) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xE621, 0x0860, 0x1880, 0xD5E2, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0330 (816) +0xFEA0, 0xFEA0, 0xFF00, 0xE641, 0x2921, 0x0000, 0x0000, 0x0000, 0x0000, 0x4208, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x5ACB, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C0, 0xDE21, 0xFF00, 0xFEA0, 0xFEC0, // 0x0350 (848) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC1, 0x39A1, 0x0000, 0x8382, 0xFF21, 0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0360 (864) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFE80, 0xFF20, 0x8BC1, 0x0000, 0x3161, 0xF6A1, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0370 (880) +0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xDE01, 0x18A0, 0x0000, 0x0000, 0x0000, 0x0000, 0x7BCF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA534, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, 0xCD61, 0xFF00, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0390 (912) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x93E1, 0x0000, 0x1060, 0xDE01, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x03A0 (928) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xE621, 0x1080, 0x0000, 0x8BA1, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, // 0x03B0 (944) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xCD61, 0x0820, 0x0000, 0x0000, 0x0000, 0x0021, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x9402, 0xFF41, 0xFE80, 0xFEA0, 0xFEC0, 0xFEC0, // 0x03D0 (976) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xF681, 0x20E0, 0x0000, 0x41A1, 0xFEE1, 0xFEA0, 0xFEA1, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x03E0 (992) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF01, 0x49E1, 0x0000, 0x18A1, 0xEE41, 0xFEC0, 0xFEA0, 0xFEC0, // 0x03F0 (1008) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFE80, 0xFF41, 0x9402, 0x0000, 0x0000, 0x0000, 0x0000, 0x39C7, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BCF, 0x0000, 0x0000, 0x0000, 0x0000, 0x4A01, 0xFF01, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0410 (1040) +0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0xA461, 0x0000, 0x0000, 0x6AC1, 0xFF21, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0420 (1056) +0xFEE0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFE80, 0xFF20, 0x7300, 0x0000, 0x0000, 0x9C21, 0xFF20, 0xFEA0, 0xFEC0, // 0x0430 (1072) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF01, 0x49E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0440 (1088) +0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x10A2, 0x0000, 0x0000, 0x0000, 0x0840, 0xDDE1, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0450 (1104) +0xFEA0, 0xFEA0, 0xFEA0, 0xFF20, 0x6261, 0x0000, 0x0000, 0x7300, 0xFF21, 0xF6A0, 0xFEA0, 0xFEE0, 0xFF20, 0xFF00, 0xFEA1, 0xEE42, // 0x0460 (1120) +0xE602, 0xEE42, 0xFEA1, 0xFF00, 0xFF20, 0xFEE0, 0xFEA0, 0xF681, 0xFF40, 0x8360, 0x0000, 0x0000, 0x5241, 0xFF01, 0xFEA0, 0xFEA0, // 0x0470 (1136) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xDDC1, 0x0840, 0x0000, 0x0000, 0x0000, 0x2945, 0xEF7D, 0xFFFF, 0xFFFF, // 0x0480 (1152) +0xFFFF, 0xFFDF, 0xFFFF, 0x7BEF, 0x0000, 0x0000, 0x0000, 0x0000, 0x7B42, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0490 (1168) +0xFEC0, 0xFEA0, 0xFEC0, 0xFEA0, 0x2900, 0x0000, 0x0000, 0x6AE0, 0xFF21, 0xFEC0, 0xFF01, 0xDE01, 0x9C01, 0x5241, 0x2921, 0x18A1, // 0x04A0 (1184) +0x1061, 0x1881, 0x2921, 0x5241, 0x9C02, 0xDDE1, 0xFF21, 0xFEC0, 0xFF20, 0x7321, 0x0000, 0x0000, 0x20E0, 0xF681, 0xFEC0, 0xFEA0, // 0x04B0 (1200) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x7B41, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFDF, // 0x04C0 (1216) +0xFFDF, 0xFFFF, 0xEF7D, 0x2104, 0x0000, 0x0000, 0x0000, 0x1080, 0xEE41, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x04D0 (1232) +0xFEC0, 0xFEA0, 0xFEC0, 0xEE21, 0x1060, 0x0000, 0x0000, 0x41C1, 0xFF21, 0xDDE1, 0x6AC1, 0x0860, 0x0000, 0x0000, 0x0000, 0x0000, // 0x04E0 (1248) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0860, 0x62C1, 0xDDC1, 0xFF41, 0x49E1, 0x0000, 0x0000, 0x0840, 0xE601, 0xFEE0, 0xFEA0, // 0x04F0 (1264) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xEE41, 0x1080, 0x0000, 0x0000, 0x0000, 0x39C7, 0xF7BE, 0xFFFF, // 0x0500 (1280) +0xFFDF, 0xFFFF, 0xA534, 0x0000, 0x0000, 0x0000, 0x0000, 0x7B21, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0510 (1296) +0xFEA0, 0xFEA0, 0xFEE0, 0xE602, 0x0841, 0x0000, 0x0000, 0x1080, 0xACC2, 0x1060, 0x0000, 0x0000, 0x0000, 0x0020, 0x2920, 0x4A01, // 0x0520 (1312) +0x5241, 0x4A01, 0x3140, 0x0821, 0x0000, 0x0000, 0x0000, 0x0860, 0xACA2, 0x18A0, 0x0000, 0x0000, 0x0820, 0xDDE2, 0xFEE0, 0xFEA0, // 0x0530 (1328) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFE80, 0xFF21, 0x7321, 0x0000, 0x0000, 0x0000, 0x0020, 0xC618, 0xFFFF, // 0x0540 (1344) +0xFFFF, 0xFFFF, 0x52AA, 0x0000, 0x0020, 0x0000, 0x0820, 0xDDA1, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0550 (1360) +0xFEC0, 0xFEA0, 0xFEE0, 0xE621, 0x1060, 0x0000, 0x0000, 0x0000, 0x6AE2, 0x20C1, 0x0000, 0x20E1, 0x8BA2, 0xD5A1, 0xFEA1, 0xFF00, // 0x0560 (1376) +0xFF01, 0xFF00, 0xFEC1, 0xD5C1, 0x8BC2, 0x2901, 0x0000, 0x18A1, 0x7302, 0x0000, 0x0000, 0x0000, 0x0840, 0xDE01, 0xFEE0, 0xFEA0, // 0x0570 (1392) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xD5A1, 0x0020, 0x0000, 0x0000, 0x0000, 0x738E, 0xFFFF, // 0x0580 (1408) +0xFFFF, 0xE71C, 0x18C3, 0x0000, 0x0020, 0x0000, 0x49C1, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0590 (1424) +0xFEA0, 0xFEA0, 0xFEC0, 0xF661, 0x18A0, 0x0000, 0x0000, 0x0000, 0x2101, 0x8363, 0x7321, 0xEE81, 0xFF21, 0xFEE0, 0xFEC0, 0xFEA0, // 0x05A0 (1440) +0xFEA0, 0xFEA0, 0xFEC0, 0xFEE0, 0xFF20, 0xF681, 0x7B41, 0x8362, 0x2921, 0x0000, 0x0000, 0x0000, 0x1080, 0xEE41, 0xFEC0, 0xFEA0, // 0x05B0 (1456) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF01, 0x41C1, 0x0000, 0x0020, 0x0000, 0x3186, 0xF79E, // 0x05C0 (1472) +0xFFFF, 0xAD75, 0x0000, 0x0000, 0x0020, 0x0000, 0x93E1, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, // 0x05D0 (1488) +0xFEC0, 0xFEA0, 0xFEA0, 0xFF41, 0x5221, 0x0000, 0x0000, 0x0000, 0x0000, 0x41C1, 0xFF01, 0xFF00, 0xF660, 0xFEA0, 0xFEA0, 0xFEC0, // 0x05E0 (1504) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xF660, 0xFF00, 0xFF22, 0x49E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x49E1, 0xFF40, 0xFEA0, 0xFEA0, // 0x05F0 (1520) +0xFEA1, 0xFEC0, 0xFEA1, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x93E1, 0x0000, 0x0020, 0x0000, 0x0020, 0xC638, // 0x0600 (1536) +0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0020, 0xD5A1, 0xFF00, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA1, 0xFEA0, // 0x0610 (1552) +0xFEA1, 0xFF20, 0xFEC1, 0xD5C1, 0x5220, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x3981, 0xE622, 0xFF20, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0620 (1568) +0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF21, 0xE621, 0x41C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49E0, 0xCDA2, 0xFEA1, 0xFF20, // 0x0630 (1584) +0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xD5A1, 0x0020, 0x0000, 0x0000, 0x0000, 0x9492, // 0x0640 (1600) +0xFFFF, 0x4A49, 0x0000, 0x0020, 0x0000, 0x2901, 0xFEA1, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, // 0x0650 (1616) +0xFEE1, 0xA461, 0x3981, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1881, 0x93E1, 0xE622, 0xFF01, 0xFF00, // 0x0660 (1632) +0xFEA0, 0xFF00, 0xFF21, 0xEE41, 0x9401, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3141, 0x9C21, // 0x0670 (1648) +0xFEC1, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEA1, 0x2901, 0x0000, 0x0020, 0x0000, 0x632C, // 0x0680 (1664) +0xE71C, 0x2124, 0x0000, 0x0020, 0x0000, 0x5241, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xD5C1, // 0x0690 (1680) +0x41C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1081, 0x4A01, 0xAC81, // 0x06A0 (1696) +0xFF21, 0xB4C1, 0x5221, 0x1081, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x06B0 (1712) +0x3981, 0xCD81, 0xFF21, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF01, 0x5221, 0x0000, 0x0020, 0x0000, 0x4228, // 0x06C0 (1728) +0xBDF7, 0x18C3, 0x0000, 0x0020, 0x0000, 0x7B41, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF20, 0xBD02, 0x1060, // 0x06D0 (1744) +0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5201, // 0x06E0 (1760) +0xFFC0, 0x5A41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, // 0x06F0 (1776) +0x0000, 0x0840, 0xACA1, 0xFF21, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x7B41, 0x0000, 0x0020, 0x0000, 0x2945, // 0x0700 (1792) +0x94B2, 0x0861, 0x0000, 0x0000, 0x0000, 0x9C02, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xBD22, 0x0820, 0x0000, // 0x0710 (1808) +0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1881, 0xAC81, // 0x0720 (1824) +0xFF20, 0xB4A1, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0730 (1840) +0x0020, 0x0000, 0x0000, 0xB4C2, 0xFF00, 0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x9C02, 0x0000, 0x0020, 0x0000, 0x2104, // 0x0740 (1856) +0x73AE, 0x0841, 0x0000, 0x0000, 0x0000, 0xACA2, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xE622, 0x18A1, 0x0000, 0x0000, // 0x0750 (1872) +0x0000, 0x1080, 0x5221, 0x6B03, 0x6AE2, 0x6AE3, 0x4A01, 0x1080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1061, 0xCD82, 0xFF20, // 0x0760 (1888) +0xFE80, 0xFF20, 0xD5C2, 0x1881, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1080, 0x5241, 0x6AE3, 0x6AE2, 0x6AE3, 0x5A62, 0x18C0, // 0x0770 (1904) +0x0000, 0x0000, 0x0000, 0x1060, 0xDDE2, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF20, 0xACA2, 0x0000, 0x0000, 0x0000, 0x10A2, // 0x0780 (1920) +0x52AA, 0x0000, 0x0000, 0x0000, 0x0000, 0xBD02, 0xFF00, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF01, 0x5A61, 0x0000, 0x0000, 0x18A0, // 0x0790 (1936) +0x9401, 0xEE61, 0xFEE2, 0x49E2, 0x18A1, 0x62A1, 0xFF41, 0xE621, 0x8BC2, 0x1880, 0x0000, 0x0820, 0x0000, 0x7B21, 0xFF40, 0xFE80, // 0x07A0 (1952) +0xFEC0, 0xFE80, 0xFF40, 0x8381, 0x0000, 0x0820, 0x0000, 0x1080, 0x8BE2, 0xEE41, 0xFF41, 0x62A2, 0x10A1, 0x3982, 0xFEC2, 0xF6A1, // 0x07B0 (1968) +0xA462, 0x2101, 0x0000, 0x0000, 0x49E1, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xBD02, 0x0000, 0x0000, 0x0000, 0x1082, // 0x07C0 (1984) +0x528A, 0x0000, 0x0000, 0x0000, 0x0000, 0xC521, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xCD41, 0x0000, 0x0000, 0x49C1, 0xE642, // 0x07D0 (2000) +0xFF21, 0xFEE0, 0xEE42, 0x1081, 0x0000, 0x41A0, 0xFEE0, 0xFEC0, 0xFF40, 0xE621, 0x41A1, 0x0000, 0x0000, 0x93E1, 0xFF20, 0xFEA0, // 0x07E0 (2016) +0xFEA0, 0xFEA0, 0xFF20, 0x9C22, 0x0000, 0x0000, 0x3981, 0xDE01, 0xFF21, 0xFEC0, 0xFEE1, 0x49E1, 0x0000, 0x0840, 0xE602, 0xFEC0, // 0x07F0 (2032) +0xFF20, 0xEE81, 0x5A61, 0x0000, 0x0000, 0xBCE1, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xC521, 0x0000, 0x0000, 0x0000, 0x1082, // 0x0800 (2048) +0x52AA, 0x0000, 0x0000, 0x0000, 0x0000, 0xBD02, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF20, 0x6AC1, 0x0000, 0x49E1, 0xFEE2, 0xFEE0, // 0x0810 (2064) +0xFE80, 0xFEC0, 0xF682, 0x20E1, 0x0000, 0x39A0, 0xFEE0, 0xFEA0, 0xFE80, 0xFEE0, 0xF6A2, 0x41A1, 0x3961, 0xDDC1, 0xFF00, 0xFE80, // 0x0820 (2080) +0xFEA0, 0xFEA0, 0xFF00, 0xE601, 0x41C1, 0x3981, 0xF682, 0xFF00, 0xFE80, 0xFEA0, 0xFF00, 0x41C1, 0x0000, 0x20C1, 0xF661, 0xFEC0, // 0x0830 (2096) +0xF6A0, 0xFEC0, 0xFF01, 0x6261, 0x0000, 0x5A41, 0xFF01, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xBD02, 0x0000, 0x0000, 0x0000, 0x1082, // 0x0840 (2112) +0x738E, 0x0841, 0x0000, 0x0000, 0x0000, 0xACA2, 0xFF20, 0xFEA0, 0xFEA0, 0xFEC0, 0xF681, 0x18A0, 0x1080, 0xEE41, 0xFEE0, 0xFEA0, // 0x0850 (2128) +0xFEC0, 0xFEA0, 0xFEE1, 0x3980, 0x0000, 0x20C0, 0xF662, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xF681, 0xFEE1, 0xFF01, 0xDDC1, 0xFF21, // 0x0860 (2144) +0xFF20, 0xFF21, 0xDDC1, 0xFEC1, 0xFF01, 0xF661, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA1, 0x2900, 0x0000, 0x3140, 0xFEA1, 0xFEA0, // 0x0870 (2160) +0xFEA0, 0xFEA0, 0xFEC0, 0xF6A1, 0x2101, 0x0840, 0xEE41, 0xFEE0, 0xFEA0, 0xFEA0, 0xFF20, 0xAC82, 0x0000, 0x0000, 0x0000, 0x10A2, // 0x0880 (2176) +0x9492, 0x0861, 0x0000, 0x0000, 0x0000, 0x9C02, 0xFF20, 0xFEA0, 0xFEA0, 0xFF00, 0xD582, 0x0000, 0x93C1, 0xFF40, 0xFE80, 0xFEC0, // 0x0890 (2192) +0xFEC0, 0xFEA0, 0xFF21, 0x6AC1, 0x0000, 0x0000, 0xCD41, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xDDE1, 0x41A1, 0x0860, 0x6AC1, // 0x08A0 (2208) +0x93E1, 0x6AE1, 0x0841, 0x3161, 0xD5C1, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xCD61, 0x0000, 0x0000, 0x5A81, 0xFF21, 0xFEA0, // 0x08B0 (2224) +0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0xAC81, 0x0000, 0xC521, 0xFF00, 0xFEA0, 0xFEA0, 0xFF20, 0x9C02, 0x0000, 0x0020, 0x0000, 0x2104, // 0x08C0 (2240) +0xB5B6, 0x10A2, 0x0000, 0x0020, 0x0000, 0x7B41, 0xFF20, 0xFEA0, 0xFEA0, 0xFF20, 0xAC80, 0x0820, 0xEE41, 0xFEC0, 0xFEA0, 0xFEC0, // 0x08D0 (2256) +0xFEC0, 0xFEA0, 0xFF00, 0xAC81, 0x0000, 0x0000, 0x7301, 0xFF20, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xD5C1, 0x0000, 0x0000, 0x0000, // 0x08E0 (2272) +0x0000, 0x0000, 0x0000, 0x0000, 0xD561, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF41, 0x7B42, 0x0000, 0x0000, 0xA442, 0xFF21, 0xFEA0, // 0x08F0 (2288) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA1, 0x1080, 0x9C00, 0xFF40, 0xFEA0, 0xFEA0, 0xFF20, 0x7B41, 0x0000, 0x0020, 0x0000, 0x2124, // 0x0900 (2304) +0xDEFB, 0x2104, 0x0000, 0x0020, 0x0000, 0x5221, 0xFF01, 0xFEA0, 0xFEA0, 0xFF40, 0x93C0, 0x3961, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0910 (2320) +0xFEC0, 0xFEA0, 0xFEC0, 0xEE61, 0x1881, 0x0000, 0x1080, 0xEE21, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF01, 0x41C1, 0x0000, 0x0020, // 0x0920 (2336) +0x0000, 0x0020, 0x0000, 0x3961, 0xFEE1, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xEE61, 0x18A1, 0x0000, 0x1060, 0xE621, 0xFEC0, 0xFEA0, // 0x0930 (2352) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x4A01, 0x8361, 0xFF40, 0xFEA0, 0xFEA0, 0xFF01, 0x5221, 0x0000, 0x0020, 0x0000, 0x4208, // 0x0940 (2368) +0xFFDF, 0x4208, 0x0000, 0x0000, 0x0000, 0x2901, 0xFEA1, 0xFEC0, 0xFEA0, 0xFF40, 0x93C0, 0x5A60, 0xFF41, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0950 (2384) +0xFEA0, 0xFEC0, 0xFEA0, 0xFF21, 0x7B41, 0x0000, 0x0000, 0x6281, 0xFF21, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF21, 0x62A1, 0x0000, 0x0000, // 0x0960 (2400) +0x0000, 0x0000, 0x0000, 0x5A41, 0xFF01, 0xFEA0, 0xFEA0, 0xF680, 0xFF41, 0x6AC1, 0x0000, 0x0000, 0x7301, 0xFF21, 0xFEA0, 0xFEA0, // 0x0970 (2416) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF40, 0x6AE1, 0x8361, 0xFF40, 0xFEA0, 0xFEC0, 0xFEA1, 0x2901, 0x0000, 0x0020, 0x0000, 0x630C, // 0x0980 (2432) +0xFFFF, 0x6B6D, 0x0000, 0x0020, 0x0000, 0x0020, 0xD5A1, 0xFF00, 0xFEA0, 0xFF20, 0xA461, 0x6AC0, 0xFF40, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0990 (2448) +0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xEE61, 0x18C0, 0x0000, 0x0000, 0x93E2, 0xFF41, 0xFEA0, 0xFE80, 0xFF20, 0x6AE1, 0x0000, 0x0000, // 0x09A0 (2464) +0x0000, 0x0000, 0x0000, 0x62A1, 0xFF21, 0xFE80, 0xFEA0, 0xFF40, 0x9C22, 0x0000, 0x0000, 0x1881, 0xE641, 0xFEC0, 0xFEC0, 0xFEC0, // 0x09B0 (2480) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF40, 0x7B61, 0x9C00, 0xFF40, 0xFE80, 0xFF00, 0xD581, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, // 0x09C0 (2496) +0xFFFF, 0xA534, 0x0000, 0x0000, 0x0000, 0x0000, 0x93E1, 0xFF20, 0xFE80, 0xFF00, 0xC541, 0x72E1, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, // 0x09D0 (2512) +0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xB4C1, 0x0000, 0x0020, 0x0000, 0x93E1, 0xFF21, 0xFEC0, 0xFF01, 0x5A81, 0x0000, 0x0000, // 0x09E0 (2528) +0x0000, 0x0000, 0x0000, 0x5222, 0xFF01, 0xFEC0, 0xFF21, 0x9C01, 0x0000, 0x0020, 0x0000, 0xAC81, 0xFF01, 0xFEA0, 0xFEA0, 0xFEC0, // 0x09F0 (2544) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x7B40, 0xBD01, 0xFF20, 0xF680, 0xFF20, 0x93C1, 0x0000, 0x0020, 0x0000, 0x0000, 0xBDF7, // 0x0A00 (2560) +0xFFFF, 0xDEDB, 0x1082, 0x0000, 0x0000, 0x0000, 0x41C1, 0xFF01, 0xFEA0, 0xFEC0, 0xF660, 0x6AC2, 0xF6A1, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A10 (2576) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x8BA1, 0x0000, 0x0000, 0x0000, 0x6281, 0xDE21, 0xFF01, 0x3161, 0x0000, 0x0000, // 0x0A20 (2592) +0x0000, 0x0000, 0x0000, 0x2921, 0xFEE1, 0xE641, 0x62A1, 0x0000, 0x0000, 0x0000, 0x8381, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A30 (2608) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC1, 0x6AC2, 0xE621, 0xFEE0, 0xFEA0, 0xFF01, 0x41C1, 0x0000, 0x0020, 0x0000, 0x2124, 0xEF5D, // 0x0A40 (2624) +0xFFFF, 0xFFFF, 0x4A49, 0x0000, 0x0000, 0x0000, 0x0020, 0xD5A1, 0xFEE0, 0xFEA0, 0xFEC0, 0xCD41, 0xF660, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A50 (2640) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF21, 0x8BC1, 0x0000, 0x0000, 0x0000, 0x1060, 0xA442, 0x0860, 0x0000, 0x0000, // 0x0A60 (2656) +0x0000, 0x0000, 0x0000, 0x0820, 0xA442, 0x18A0, 0x0000, 0x0000, 0x0000, 0x8381, 0xFF21, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A70 (2672) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFE80, 0xCD62, 0xFEC0, 0xFEA1, 0xFEE0, 0xD5A1, 0x0020, 0x0000, 0x0000, 0x0000, 0x630C, 0xFFFF, // 0x0A80 (2688) +0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0x0000, 0x0000, 0x0000, 0x7321, 0xFF21, 0xFEA0, 0xFEA0, 0xFEE0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0A90 (2704) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF21, 0xB4C1, 0x20E1, 0x0000, 0x3161, 0x62A2, 0x0000, 0x0000, 0x0000, // 0x0AA0 (2720) +0x0000, 0x0000, 0x0000, 0x0000, 0x5A82, 0x39A1, 0x0000, 0x20C1, 0xAC82, 0xFF21, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0AB0 (2736) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEE0, 0xFEA0, 0xFEA0, 0xFF21, 0x7321, 0x0000, 0x0000, 0x0000, 0x0000, 0xB596, 0xFFFF, // 0x0AC0 (2752) +0xFFDF, 0xFFFF, 0xE73C, 0x18C3, 0x0000, 0x0000, 0x0000, 0x1080, 0xEE41, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA1, 0xFF00, 0xFEE0, 0xFEA0, // 0x0AD0 (2768) +0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xEE41, 0x83C1, 0x8BA3, 0x1081, 0x0000, 0x0000, 0x0000, // 0x0AE0 (2784) +0x0000, 0x0000, 0x0000, 0x0000, 0x1060, 0x8383, 0x83A1, 0xEE41, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, // 0x0AF0 (2800) +0xFEC0, 0xFEA0, 0xFEC0, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xEE21, 0x1080, 0x0000, 0x0000, 0x0000, 0x2945, 0xEF7D, 0xFFFF, // 0x0B00 (2816) +0xFFFF, 0xFFFF, 0xFFFF, 0x6B4D, 0x0000, 0x0000, 0x0000, 0x0000, 0x7B41, 0xFF21, 0xFEA0, 0xFEA0, 0xFF00, 0xB482, 0xD5C1, 0xFF20, // 0x0B10 (2832) +0xFE80, 0xFEA0, 0xFEA0, 0xFEA1, 0xFEA0, 0xFEC0, 0xFEA1, 0xFEA0, 0xF680, 0xFF20, 0xF6A2, 0x3121, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B20 (2848) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20E1, 0xEE62, 0xFF40, 0xF680, 0xFEA0, 0xFEA1, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0B30 (2864) +0xF681, 0xFF20, 0xE601, 0xAC62, 0xFF00, 0xFEA0, 0xFE80, 0xFF21, 0x7B41, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0xFFFF, 0xFFFF, // 0x0B40 (2880) +0xFFFF, 0xFFDF, 0xFFFF, 0xD69A, 0x0841, 0x0000, 0x0000, 0x0000, 0x0840, 0xDDC1, 0xFEE0, 0xFEA0, 0xFEE1, 0xD5A1, 0x5221, 0xBD21, // 0x0B50 (2896) +0xFF41, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA1, 0xFEC0, 0xFF00, 0xFF21, 0xCD61, 0x20E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, // 0x0B60 (2912) +0x7322, 0x0840, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A1, 0xBD22, 0xFF21, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEE0, // 0x0B70 (2928) +0xFF40, 0xC561, 0x5221, 0xCD81, 0xFEE0, 0xFE81, 0xFEE0, 0xDDC1, 0x0840, 0x0000, 0x0000, 0x0000, 0x18E3, 0xE71C, 0xFFFF, 0xFFFF, // 0x0B80 (2944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0000, 0x0000, 0x0000, 0x0000, 0x49E1, 0xFF01, 0xFEA0, 0xFEA0, 0xFF00, 0xDE01, 0x4181, // 0x0B90 (2960) +0x5A81, 0xD581, 0xFEE1, 0xFF20, 0xFF20, 0xFF01, 0xFEC1, 0xD582, 0x6AE1, 0x0020, 0x0000, 0x0020, 0x0000, 0x0000, 0x1060, 0xACA2, // 0x0BA0 (2976) +0xFF61, 0xBD21, 0x18A1, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x62A2, 0xCD62, 0xFEA1, 0xFF01, 0xFF20, 0xFF20, 0xFEE1, 0xD5C1, // 0x0BB0 (2992) +0x62C1, 0x3981, 0xD5C1, 0xFF21, 0xFEA0, 0xFEA0, 0xFF01, 0x49E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0BC0 (3008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x1082, 0x0000, 0x0000, 0x0000, 0x0000, 0x93E2, 0xFF40, 0xFE80, 0xFE80, 0xFEE0, 0xFEC1, // 0x0BD0 (3024) +0x6B01, 0x1061, 0x18C1, 0x4A00, 0x5AA0, 0x5240, 0x3141, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4A01, 0xDDC1, 0xFF20, // 0x0BE0 (3040) +0xFE80, 0xFF00, 0xE602, 0x5A41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2921, 0x5220, 0x5AA0, 0x4A00, 0x20E1, 0x1060, // 0x0BF0 (3056) +0x6AE1, 0xF6A1, 0xFEE0, 0xFEA1, 0xFEA0, 0xFF41, 0x93E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x2124, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C00 (3072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8C71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, 0xCD61, 0xFF00, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0C10 (3088) +0xFF41, 0xDDE1, 0x6B01, 0x18C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A0, 0x5A61, 0xBCE2, 0xFF01, 0xFEE0, 0xFEA0, // 0x0C20 (3104) +0xFEC0, 0xFEA0, 0xFEE0, 0xFF01, 0xC541, 0x6281, 0x20C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C1, 0x6AE1, 0xDDC1, // 0x0C30 (3120) +0xFF41, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF01, 0xC541, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0xA514, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C40 (3136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x4208, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A1, 0xDE01, 0xFF00, 0xFE80, 0xFEC0, // 0x0C50 (3152) +0xFEA0, 0xFEE0, 0xFF20, 0xFEC1, 0xD5A2, 0xAC82, 0x9401, 0x93E1, 0x9C42, 0xC522, 0xEE41, 0xFF01, 0xFF00, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0C60 (3168) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF00, 0xFF21, 0xF661, 0xC542, 0xA462, 0x93E1, 0x9C01, 0xB4A2, 0xD5A1, 0xFEC1, 0xFF20, 0xFEE0, // 0x0C70 (3184) +0xFEA0, 0xFEC0, 0xFE80, 0xFF00, 0xDE01, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C80 (3200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD6BA, 0x10A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x2921, 0xE641, 0xFF00, 0xFE80, // 0x0C90 (3216) +0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0CA0 (3232) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0CB0 (3248) +0xFEA0, 0xFE80, 0xFF00, 0xE641, 0x2901, 0x0000, 0x0000, 0x0000, 0x0000, 0x2124, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0CC0 (3264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD55, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2901, 0xDE01, 0xFF00, // 0x0CD0 (3280) +0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0CE0 (3296) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, // 0x0CF0 (3312) +0xFE80, 0xFF00, 0xDE01, 0x2900, 0x0000, 0x0000, 0x0000, 0x0000, 0x0861, 0xBDD7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D00 (3328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8430, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A1, 0xC561, // 0x0D10 (3344) +0xFF21, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0D20 (3360) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0D30 (3376) +0xFF41, 0xC561, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D40 (3392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, // 0x0D50 (3408) +0x9402, 0xFF01, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0D60 (3424) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF01, // 0x0D70 (3440) +0x9402, 0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D80 (3456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0D90 (3472) +0x0000, 0x4A01, 0xDDC1, 0xFF41, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0DA0 (3488) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF21, 0xD5C1, 0x4A01, // 0x0DB0 (3504) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0DC0 (3520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8430, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0DD0 (3536) +0x0000, 0x0000, 0x0840, 0x7B61, 0xE641, 0xFF21, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0DE0 (3552) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF21, 0xE621, 0x7B42, 0x0840, 0x0000, // 0x0DF0 (3568) +0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0x9492, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E00 (3584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD55, 0x10A2, 0x0000, 0x0000, // 0x0E10 (3600) +0x0000, 0x0000, 0x0000, 0x0000, 0x1880, 0x7B21, 0xD5A1, 0xFF01, 0xFF20, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, // 0x0E20 (3616) +0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF01, 0xD5A1, 0x7321, 0x1880, 0x0000, 0x0000, 0x0000, // 0x0E30 (3632) +0x0000, 0x0000, 0x0000, 0x18E3, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E40 (3648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xD69A, 0x4228, 0x0000, // 0x0E50 (3664) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x41C1, 0x93E1, 0xD5A1, 0xFEA1, 0xFF01, 0xFF20, 0xFF20, 0xFF20, 0xFF00, // 0x0E60 (3680) +0xFF00, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF01, 0xFEA1, 0xD5A1, 0x93E1, 0x41C1, 0x0020, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, // 0x0E70 (3696) +0x0000, 0x0000, 0x528A, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E80 (3712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0x8C71, // 0x0E90 (3728) +0x10A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2901, 0x5221, 0x7B41, 0x9402, 0xAC82, 0xBCE2, // 0x0EA0 (3744) +0xC521, 0xBCE2, 0xAC82, 0x9401, 0x7B41, 0x5221, 0x2901, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0EB0 (3760) +0x18E3, 0x94B2, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0EC0 (3776) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0ED0 (3792) +0xD6BA, 0x632C, 0x0841, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0EE0 (3808) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x10A2, 0x738E, // 0x0EF0 (3824) +0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F00 (3840) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F10 (3856) +0xFFFF, 0xFFFF, 0xCE79, 0x6B4D, 0x18C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, // 0x0F20 (3872) +0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, 0x738E, 0xD69A, 0xFFFF, // 0x0F30 (3888) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F40 (3904) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F50 (3920) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE71C, 0x94B2, 0x4A49, 0x1082, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0F60 (3936) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C3, 0x4A69, 0x9CD3, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F70 (3952) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F80 (3968) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F90 (3984) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0xA534, 0x6B6D, 0x4208, 0x2104, 0x18C3, 0x0861, 0x0841, 0x0000, // 0x0FA0 (4000) +0x0000, 0x0000, 0x0841, 0x0861, 0x18C3, 0x2124, 0x4228, 0x6B6D, 0xA534, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FB0 (4016) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FC0 (4032) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FD0 (4048) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0xB5B6, 0x9492, 0x6B6D, 0x4A49, // 0x0FE0 (4064) +0x4228, 0x4A49, 0x6B6D, 0x8C51, 0xAD75, 0xDEDB, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FF0 (4080) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x1000 (4096) +}; diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino new file mode 100644 index 0000000..3e25649 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino @@ -0,0 +1,52 @@ +// UTFT_Textrotation_Demo (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the textrotation-functions. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(BigFont); +} + +void loop() +{ + myGLCD.print("Text rotation", 0, 0); + myGLCD.setColor(0, 0, 255); + myGLCD.print("0 degrees", 0, 16, 0); + myGLCD.print("90 degrees", 319, 0, 90); + myGLCD.print("180 degrees", 319, 239, 180); + myGLCD.print("270 degrees", 0, 239, 270); + + myGLCD.setFont(SevenSegNumFont); + myGLCD.setColor(0, 255, 0); + myGLCD.print("45", 90, 100, 45); + myGLCD.print("90", 200, 50, 90); + myGLCD.print("180", 300, 200, 180); + + while (true) {}; +} + diff --git a/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_ViewFont/UTFT_ViewFont.ino b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_ViewFont/UTFT_ViewFont.ino new file mode 100644 index 0000000..7a99d20 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (ARM) + Teensy/UTFT_ViewFont/UTFT_ViewFont.ino @@ -0,0 +1,59 @@ +// UTFT_ViewFont (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the included fonts. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +void setup() +{ + myGLCD.InitLCD(); + + myGLCD.clrScr(); +} + +void loop() +{ + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 0); + + myGLCD.setFont(BigFont); + myGLCD.print(" !\"#$%&'()*+,-./", CENTER, 0); + myGLCD.print("0123456789:;<=>?", CENTER, 16); + myGLCD.print("@ABCDEFGHIJKLMNO", CENTER, 32); + myGLCD.print("PQRSTUVWXYZ[\\]^_", CENTER, 48); + myGLCD.print("`abcdefghijklmno", CENTER, 64); + myGLCD.print("pqrstuvwxyz{|}~ ", CENTER, 80); + + myGLCD.setFont(SmallFont); + myGLCD.print(" !\"#$%&'()*+,-./0123456789:;<=>?", CENTER, 120); + myGLCD.print("@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", CENTER, 132); + myGLCD.print("`abcdefghijklmnopqrstuvwxyz{|}~ ", CENTER, 144); + + myGLCD.setFont(SevenSegNumFont); + myGLCD.print("0123456789", CENTER, 190); + + while(1) {}; +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/UTFT_Bitmap.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/UTFT_Bitmap.ino new file mode 100644 index 0000000..3eefe88 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/UTFT_Bitmap.ino @@ -0,0 +1,71 @@ +// UTFT_Bitmap (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This demo was made to work on the 320x240 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +extern unsigned int info[0x400]; +extern unsigned int icon[0x400]; +extern unsigned int tux[0x400]; + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(255, 255, 255); + myGLCD.print(" *** A 10 by 7 grid of a 32x32 icon *** ", CENTER, 228); + for (int x=0; x<10; x++) + for (int y=0; y<7; y++) + myGLCD.drawBitmap (x*32, y*32, 32, 32, info); + + delay(5000); + + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(255, 255, 255); + myGLCD.print(" Two different icons in scale 1 to 4 ", CENTER, 228); + int x=0; + for (int s=0; s<4; s++) + { + x+=(s*32); + myGLCD.drawBitmap (x, 0, 32, 32, tux, s+1); + } + x=0; + for (int s=4; s>0; s--) + { + myGLCD.drawBitmap (x, 224-(s*32), 32, 32, icon, s); + x+=(s*32); + } + + delay(5000); +} diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/icon.c b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/icon.c new file mode 100644 index 0000000..374dd09 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/icon.c @@ -0,0 +1,73 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: taskmgr.png +// Time generated: 11.10.2010 22:51:23 +// Size : 2 048 Bytes + +#include + +const unsigned short icon[0x400] PROGMEM ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0xCE79, 0xBDD7, 0xAD75, // 0x0010 (16) +0xAD55, 0xAD75, 0xBDF7, 0xD6BA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC638, 0x9492, 0x8C51, 0x9492, 0xA514, 0xA534, // 0x0030 (48) +0xA534, 0xA534, 0x9CF3, 0x8C71, 0x8430, 0x9CD3, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0x8410, 0x9492, 0xB5B6, 0xC618, 0xBDD7, 0xAD75, 0xA514, // 0x0050 (80) +0xA514, 0xA4F4, 0xAD55, 0xB5B6, 0xBDD7, 0xAD55, 0x8430, 0x8C71, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x9CD3, 0x8430, 0xBDF7, 0xC618, 0xAD75, 0x94F2, 0x8CF1, 0x84B0, 0x8CD1, // 0x0070 (112) +0x9612, 0x8CB1, 0x7C6F, 0x7C8F, 0x8490, 0xA533, 0xBDF7, 0xB596, 0x7BEF, 0xB596, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8430, 0x9CF3, 0xCE39, 0xA514, 0x94B2, 0x9E93, 0x94F2, 0x8CD1, 0x8CB1, 0x9D12, // 0x0090 (144) +0x9F74, 0x9D52, 0x8450, 0x7C8F, 0x73AE, 0x740E, 0x73CE, 0x9CD3, 0xC638, 0x8C51, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x8430, 0xA534, 0xBDF7, 0x8CB1, 0x8C31, 0x9DB3, 0xA735, 0x9D13, 0x8CB1, 0x8C71, 0x9D13, // 0x00B0 (176) +0xB756, 0xA5D4, 0x8C71, 0x8490, 0x8390, 0x7C70, 0x73EE, 0x6B4D, 0x8450, 0xBDF7, 0x8C71, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x94B2, 0x9CF3, 0xBDD7, 0x8490, 0x8CF1, 0x9D72, 0xA694, 0xAE94, 0x9DD3, 0xA593, 0xA553, 0x9592, // 0x00D0 (208) +0x9672, 0x75CE, 0x5BAA, 0x64EB, 0x5D8C, 0x5BCA, 0x4B69, 0x634C, 0x748D, 0x7C4F, 0xBE18, 0x8430, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xC618, 0x8410, 0xBDF7, 0x8410, 0x83F0, 0x94F2, 0x9613, 0x9D13, 0xAE55, 0x9D12, 0x750E, 0x55CB, 0x4BC8, // 0x00F0 (240) +0x4447, 0x3BC6, 0x4B67, 0x44E8, 0x3CE8, 0x3325, 0x20E2, 0x2B45, 0x43E7, 0x3946, 0x732D, 0xC5F8, 0x7BCF, 0xE71C, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xF7BE, 0x7BEF, 0xBDB6, 0x9533, 0x8D71, 0x9552, 0x9E73, 0x9DD3, 0x94B2, 0x6D6D, 0x4BA8, 0x44A8, 0x55EA, 0x5D2A, // 0x0110 (272) +0x43E7, 0x4327, 0x46CA, 0x4B87, 0x42C6, 0x4E0A, 0x4D09, 0x4468, 0x4548, 0x3386, 0x2B25, 0x7C6F, 0xAD35, 0x9492, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFDF, 0xFFFF, 0xBDD7, 0x8C71, 0xAD75, 0x8CF0, 0x8D71, 0x8D51, 0x9DF3, 0x740E, 0x21C4, 0x33E5, 0x558A, 0x554A, 0x650A, 0x566B, // 0x0130 (304) +0x43E7, 0x21C3, 0x3345, 0x2283, 0x1962, 0x3C87, 0x3386, 0x2163, 0x3345, 0x3346, 0x33A6, 0x32C6, 0x9CB3, 0x7BEF, 0xDEDB, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0x8430, 0xAD75, 0x8C31, 0x7C0F, 0x7BCF, 0x83F0, 0x636B, 0x0000, 0x0000, 0x4387, 0x462A, 0x4B27, 0x4B88, 0x4E8B, // 0x0150 (336) +0x42E6, 0x0000, 0x0020, 0x0100, 0x0000, 0x1121, 0x0040, 0x0000, 0x0941, 0x0000, 0x0020, 0x00E0, 0x5AAB, 0x94B2, 0x9CD3, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xE71C, 0x8410, 0xB596, 0x7BEF, 0x7C6F, 0x84B0, 0x5B6B, 0x09E1, 0x0901, 0x1161, 0x3C06, 0x3D89, 0x32C5, 0x43E7, 0x470B, // 0x0170 (368) +0x4BC7, 0x0961, 0x11E2, 0x1282, 0x0961, 0x1262, 0x09E2, 0x0961, 0x12A2, 0x0961, 0x09C2, 0x0A01, 0x29E5, 0xA514, 0x7BEF, 0xFFDF, // 0x0180 (384) +0xFFFF, 0xBDD7, 0x9472, 0xA514, 0x6B4D, 0x7C6F, 0x634C, 0x0040, 0x0981, 0x0060, 0x00E0, 0x11E2, 0x10A1, 0x09C1, 0x19E3, 0x2B25, // 0x0190 (400) +0x22A3, 0x0060, 0x0120, 0x09E1, 0x0060, 0x09E1, 0x0120, 0x0060, 0x0A21, 0x0060, 0x0100, 0x01A0, 0x0040, 0x9CD3, 0x7BEF, 0xDEDB, // 0x01A0 (416) +0xFFFF, 0xA514, 0x9CF3, 0xB596, 0x73AE, 0x7C0F, 0x2945, 0x10A2, 0x2184, 0x18C3, 0x1923, 0x2184, 0x18C3, 0x21A4, 0x2964, 0x2905, // 0x01B0 (432) +0x2A25, 0x2104, 0x2965, 0x2A05, 0x2104, 0x2A05, 0x2985, 0x2104, 0x2A25, 0x2104, 0x2164, 0x29C4, 0x3166, 0xB5B6, 0x8410, 0xC618, // 0x01C0 (448) +0xFFFF, 0x9492, 0xA514, 0xDEDB, 0xC618, 0xA514, 0x8C51, 0x94B2, 0x9CB3, 0x9CF3, 0xA514, 0xA534, 0xAD75, 0xAD75, 0xB596, 0xB5D6, // 0x01D0 (464) +0xBDB7, 0xBDF7, 0xBDF7, 0xBDF7, 0xC618, 0xC5F8, 0xC5F8, 0xBDF7, 0xBDD7, 0xBDD7, 0xB5B6, 0xB596, 0xC638, 0xDEFB, 0x8430, 0xB596, // 0x01E0 (480) +0xFFFF, 0x8C51, 0x9CF3, 0xE73C, 0xDEFB, 0xD69A, 0xD6BA, 0xD6BA, 0xDEDB, 0xDEDB, 0xDEFB, 0xDF1B, 0xE71C, 0xE73C, 0xE73C, 0xE73C, // 0x01F0 (496) +0xEF5D, 0xEF5D, 0xEF5D, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xDEFB, 0xE71C, 0x8C51, 0xAD75, // 0x0200 (512) +0xFFFF, 0x8C71, 0x9CD3, 0xDEFB, 0xAD75, 0x9492, 0x9CD3, 0xA4F3, 0xA514, 0xAD55, 0xAD75, 0xB596, 0xBDB6, 0xBDD7, 0xC5F7, 0xC618, // 0x0210 (528) +0xC638, 0xCE59, 0xCE59, 0xCE79, 0xD679, 0xD679, 0xCE79, 0xCE59, 0xCE59, 0xC638, 0xC618, 0xBDF7, 0xCE79, 0xE71C, 0x8C51, 0xB596, // 0x0220 (544) +0xFFFF, 0x9CD3, 0x9492, 0xAD55, 0x2965, 0x2104, 0x2124, 0x2145, 0x1945, 0x2165, 0x2165, 0x2186, 0x2186, 0x29A6, 0x29A6, 0x31C7, // 0x0230 (560) +0x39C7, 0x31E7, 0x31E7, 0x31E7, 0x3208, 0x3208, 0x31E7, 0x31E7, 0x29E7, 0x31C7, 0x39C7, 0x31A6, 0x4A49, 0xBDF7, 0x8C51, 0xBDF7, // 0x0240 (576) +0xFFFF, 0xB5B6, 0x8430, 0x7BEF, 0x0000, 0x0000, 0x0000, 0x2000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3800, 0x2000, // 0x0250 (592) +0x0000, 0x3000, 0x3800, 0x3000, 0x3800, 0x3800, 0x3800, 0x3000, 0x3800, 0x0800, 0x0000, 0x0000, 0x0000, 0xA514, 0x8430, 0xD6BA, // 0x0260 (608) +0xFFFF, 0xDEDB, 0x7BCF, 0x8430, 0x0020, 0x0000, 0x0000, 0x8000, 0xC800, 0xC000, 0xC800, 0xC820, 0xC820, 0xC820, 0xD020, 0x9800, // 0x0270 (624) +0x0000, 0xB820, 0xD020, 0xD020, 0xD020, 0xD020, 0xD020, 0xC820, 0xD020, 0x4800, 0x0000, 0x0000, 0x2144, 0xAD75, 0x8410, 0xF7BE, // 0x0280 (640) +0xFFFF, 0xFFFF, 0x7BEF, 0x8C71, 0x2945, 0x0000, 0x0000, 0x6800, 0xA800, 0xA800, 0xA800, 0xA800, 0xA800, 0xA800, 0xB000, 0x8000, // 0x0290 (656) +0x0000, 0x9800, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0x4000, 0x0000, 0x0000, 0x632C, 0xA534, 0x94B2, 0xFFFF, // 0x02A0 (672) +0xFFDF, 0xFFFF, 0xAD75, 0x73AE, 0x632C, 0x0000, 0x0000, 0x6920, 0xA9E0, 0xA1C0, 0xA9E0, 0xA9E0, 0xA9E0, 0xA9E0, 0xA9E0, 0x7960, // 0x02B0 (688) +0x0000, 0x99C0, 0xB200, 0xA9E0, 0xB200, 0xB200, 0xB1E0, 0xA9E0, 0xB200, 0x40C0, 0x0000, 0x1082, 0xAD75, 0x8410, 0xD69A, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xF79E, 0x630C, 0x8C51, 0x2965, 0x0000, 0x7400, 0xB620, 0xAE00, 0xB620, 0xB640, 0xB640, 0xB620, 0xB660, 0x84A0, // 0x02D0 (720) +0x0000, 0xA5A0, 0xBE60, 0xB660, 0xBE60, 0xBE60, 0xB660, 0xB640, 0xBE80, 0x4260, 0x0000, 0x6B6D, 0xAD75, 0x8430, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFDF, 0xFFFF, 0xB5B6, 0x632C, 0x8410, 0x0021, 0x7360, 0xBD40, 0xB520, 0xBD40, 0xBD60, 0xBD60, 0xBD40, 0xC580, 0x8C00, // 0x02F0 (752) +0x0000, 0xACE0, 0xC580, 0xC580, 0xC580, 0xC580, 0xC580, 0xBD60, 0xC5A0, 0x39C0, 0x2126, 0xBDF7, 0x73AE, 0xD6BA, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BEF, 0x7BEF, 0x630D, 0x4AE1, 0x6D21, 0x6D01, 0x6D21, 0x6D41, 0x6D41, 0x6D41, 0x6D61, 0x53E1, // 0x0310 (784) +0x0000, 0x64C1, 0x7562, 0x6D62, 0x6D62, 0x6D62, 0x6D62, 0x6D42, 0x6D41, 0x4263, 0xA515, 0x8C51, 0xA534, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x6B4D, 0x8410, 0x636E, 0x04A6, 0x05E5, 0x05C5, 0x0585, 0x0585, 0x0586, 0x05A6, 0x0424, // 0x0330 (816) +0x0000, 0x0505, 0x05C6, 0x05A6, 0x05A6, 0x05C7, 0x0606, 0x0606, 0x1CE9, 0xA535, 0x9492, 0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x6B4D, 0x83EF, 0x9411, 0x3A47, 0x0403, 0x0584, 0x05A4, 0x0585, 0x0585, 0x0404, // 0x0350 (848) +0x0000, 0x04E5, 0x05A5, 0x05A5, 0x05C5, 0x0584, 0x1405, 0x634B, 0xBD76, 0x8C51, 0x8C51, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8410, 0x6B6D, 0x9CB3, 0x7C6F, 0x3CA9, 0x0BE4, 0x0443, 0x0504, 0x03C2, // 0x0370 (880) +0x0000, 0x0483, 0x0504, 0x0444, 0x1426, 0x552D, 0xA554, 0xB576, 0x73CE, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB5B6, 0x6B4D, 0x7BAF, 0x9432, 0x8BD1, 0x6BCE, 0x4C6B, 0x3C09, // 0x0390 (912) +0x3186, 0x3C8A, 0x5C8C, 0x8430, 0xA493, 0xACD4, 0x8410, 0x7BEF, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xAD75, 0x7BEF, 0x73AE, 0x83F0, 0x8C11, 0x9431, // 0x03B0 (944) +0x9492, 0x9452, 0x9432, 0x8430, 0x7BEF, 0x8450, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0xBDD7, 0xA534, 0x94D3, // 0x03D0 (976) +0x94B2, 0x9CF3, 0xA554, 0xC618, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/info.c b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/info.c new file mode 100644 index 0000000..a0a04ee --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/info.c @@ -0,0 +1,73 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: info.png +// Time generated: 11.10.2010 22:27:55 +// Size : 2 048 Bytes + +#include + +const unsigned short info[0x400] PROGMEM ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF9F, 0xC69D, 0x95BB, 0x7D1A, 0x6CB9, // 0x0030 (48) +0x6499, 0x74F9, 0x8D7A, 0xB63C, 0xE73E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAE1C, 0x4C18, 0x2B56, 0x3397, 0x4C38, 0x64B9, 0x751A, // 0x0050 (80) +0x7D3A, 0x6CD9, 0x5458, 0x3BD7, 0x2B56, 0x3BB7, 0x855A, 0xE77E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA5FB, 0x2B56, 0x2B77, 0x751A, 0xB67C, 0xD73E, 0xE75E, 0xE77E, 0xE77E, // 0x0070 (112) +0xE77E, 0xE77E, 0xE75E, 0xDF3E, 0xC6DD, 0x8D9B, 0x43D7, 0x1B16, 0x74D9, 0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF9F, 0x4C18, 0x1AF6, 0x855A, 0xCEFE, 0xD71E, 0xCEFD, 0xC6DD, 0xC6BD, 0xC6BD, 0xBEBD, // 0x0090 (144) +0xC6BD, 0xBEBD, 0xC6BD, 0xC6DD, 0xC6DD, 0xD71E, 0xD71E, 0xA61C, 0x33B7, 0x2316, 0xBE7C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF3E, 0x2336, 0x3BD7, 0xBE9D, 0xC6DD, 0xBE9D, 0xBE9D, 0xBE9D, 0xBEBD, 0xBE9D, 0xCEFD, 0xEF9F, // 0x00B0 (176) +0xEF9F, 0xD73E, 0xBE9D, 0xBEBD, 0xBE9D, 0xBE9D, 0xB69D, 0xC6BD, 0xCEDD, 0x6CFA, 0x0295, 0x9DBB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xE75E, 0x1AF6, 0x4C58, 0xBEBD, 0xB67D, 0xAE5C, 0xB67D, 0xB67D, 0xB69D, 0xB67D, 0xBEBD, 0xF7DF, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xFFFF, 0xCF1E, 0xB67D, 0xB67D, 0xB67D, 0xB67D, 0xAE5C, 0xAE5C, 0xC6BD, 0x857B, 0x0295, 0xA5DB, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFDF, 0x3BB7, 0x33D8, 0xB67D, 0xA63C, 0xA63C, 0xAE5C, 0xAE5D, 0xAE5D, 0xAE7D, 0xA65D, 0xC6DD, 0xFFFF, 0xFFFF, // 0x00F0 (240) +0xFFDF, 0xFFFF, 0xDF5E, 0xA65D, 0xAE7D, 0xAE5D, 0xAE5D, 0xAE5C, 0xA63C, 0xA61C, 0xB67D, 0x753A, 0x0295, 0xCEBC, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xF7DF, 0xFFFF, 0x957A, 0x12F6, 0x9E1C, 0x9E1C, 0x9E1C, 0x9E1C, 0xA63C, 0xA63C, 0xA63D, 0xA63D, 0xA65D, 0x9DFC, 0xDF3E, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xFFDF, 0xA61C, 0xA65D, 0xA65D, 0xA63D, 0xA63C, 0xA63C, 0x9E1C, 0x9E1C, 0x9DFC, 0xAE3C, 0x3C18, 0x3396, 0xFFDF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xF79F, 0x2336, 0x64DA, 0x9DFC, 0x95DC, 0x95FC, 0x95FC, 0x9E1C, 0x9E1C, 0x9E3D, 0x9E3D, 0x9E3D, 0x9E3D, 0x7D3B, 0xA63C, // 0x0130 (304) +0xB6BD, 0x8DBB, 0x8DFC, 0xA65D, 0x9E3D, 0x9E3D, 0x9E1C, 0x9E1C, 0x95FC, 0x95FC, 0x95DC, 0x95DC, 0x8DBB, 0x0AF6, 0xA5DA, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xA5FB, 0x1337, 0x8DBB, 0x8DBB, 0x8DBC, 0x8DDC, 0x95FC, 0x95FC, 0x961C, 0x961D, 0x963D, 0x9E3D, 0x963D, 0xA67D, 0xB6BD, // 0x0150 (336) +0xB6BD, 0xAE7D, 0x9E3D, 0x9E3D, 0x961D, 0x961D, 0x961C, 0x95FC, 0x95FC, 0x8DDC, 0x8DDC, 0x859B, 0x95DC, 0x3C18, 0x4BD7, 0xFFFF, // 0x0160 (352) +0xFFFF, 0x6499, 0x33F8, 0x8DBB, 0x859B, 0x85BC, 0x85BC, 0x8DDC, 0x8DFC, 0x8DFD, 0x8E1D, 0x961D, 0x961D, 0x9E3D, 0xF7BF, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xA67D, 0x8E1D, 0x961D, 0x8E1D, 0x8DFD, 0x8DFC, 0x8DDC, 0x85BC, 0x85BC, 0x859B, 0x859B, 0x5CDA, 0x2336, 0xE71C, // 0x0180 (384) +0xFFFF, 0x43F8, 0x4C79, 0x859B, 0x7D7B, 0x7D9C, 0x85BC, 0x85DC, 0x85DC, 0x8DFD, 0x8DFD, 0x8E1D, 0x8E1D, 0xA67E, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFFF, 0xBEDE, 0x85FD, 0x8E1D, 0x8DFD, 0x8DFD, 0x85DC, 0x85DC, 0x85BC, 0x7D9C, 0x7D7B, 0x7D7B, 0x753B, 0x1B36, 0xBE5A, // 0x01A0 (416) +0xFFBE, 0x3BF8, 0x3419, 0x6D1B, 0x757B, 0x7D9C, 0x7D9C, 0x7DBC, 0x7DDD, 0x85FD, 0x85FD, 0x861D, 0x861D, 0x9E7E, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xFFFF, 0xB6DE, 0x85FD, 0x8E1D, 0x85FD, 0x85FD, 0x7DDD, 0x7DBC, 0x7D9C, 0x7D9C, 0x757B, 0x6D3B, 0x4C9A, 0x1337, 0xADD9, // 0x01C0 (448) +0xFFBE, 0x4418, 0x23B9, 0x3439, 0x4CBA, 0x653B, 0x759C, 0x7DBD, 0x7DDD, 0x7DFD, 0x861D, 0x861E, 0x861E, 0x9E7E, 0xFFFF, 0xFFFF, // 0x01D0 (464) +0xFFFF, 0xFFFF, 0xB6DE, 0x7E1E, 0x861E, 0x85FD, 0x7DFD, 0x7DDD, 0x7DBD, 0x759C, 0x653B, 0x4CDB, 0x3439, 0x2BF9, 0x1337, 0xA5B9, // 0x01E0 (480) +0xFF9E, 0x4C39, 0x2BF9, 0x345A, 0x3C7A, 0x3C9B, 0x4CFC, 0x5D5C, 0x659D, 0x75DD, 0x7DFE, 0x861E, 0x7E3E, 0x969F, 0xFFFF, 0xFFFF, // 0x01F0 (496) +0xFFFF, 0xFFFF, 0xB6FF, 0x7E1E, 0x863E, 0x7DFE, 0x75DD, 0x6D9D, 0x5D5C, 0x4CFC, 0x3C9B, 0x347A, 0x345A, 0x343A, 0x1B78, 0xA5B9, // 0x0200 (512) +0xF79E, 0x4418, 0x2C3A, 0x3C7A, 0x449B, 0x44DB, 0x4CFC, 0x4D3C, 0x555D, 0x5D7D, 0x65BE, 0x6DFE, 0x6DFF, 0x867F, 0xFFFF, 0xFFFF, // 0x0210 (528) +0xFFFF, 0xFFFF, 0xA6DF, 0x65FF, 0x6DFE, 0x65BE, 0x5D9E, 0x555D, 0x4D3C, 0x4CFC, 0x44DB, 0x44BB, 0x3C7A, 0x345A, 0x1B78, 0xA599, // 0x0220 (544) +0xFFDE, 0x43D8, 0x345A, 0x3C9A, 0x44DB, 0x4CFC, 0x4D3C, 0x555D, 0x5D9D, 0x5DBE, 0x65DE, 0x6DFF, 0x661F, 0x867F, 0xFFFF, 0xFFFF, // 0x0230 (560) +0xFFFF, 0xFFFF, 0xA6DF, 0x65FF, 0x6DFF, 0x65DE, 0x5DBE, 0x5D9D, 0x555D, 0x4D3C, 0x4CFC, 0x44DB, 0x3C7A, 0x3C9B, 0x1B57, 0xADB9, // 0x0240 (576) +0xFFFF, 0x4BD7, 0x2C1A, 0x44DB, 0x44DB, 0x4D1C, 0x555D, 0x5D7D, 0x5DBE, 0x65DE, 0x6E1F, 0x6E3F, 0x765F, 0x96BF, 0xFFFF, 0xFFFF, // 0x0250 (592) +0xFFFF, 0xFFFF, 0xAEFF, 0x6E3F, 0x763F, 0x6E1F, 0x65DE, 0x5DBE, 0x5D7D, 0x555D, 0x4D1C, 0x44DC, 0x3C9B, 0x44DC, 0x1AD5, 0xC639, // 0x0260 (608) +0xFFFF, 0x84D8, 0x1317, 0x5D7D, 0x44DB, 0x553C, 0x557D, 0x5D9E, 0x65DE, 0x65FF, 0x6E3F, 0x7E5F, 0x7E7F, 0x9EDF, 0xFFFF, 0xFFFF, // 0x0270 (624) +0xFFFF, 0xFFFF, 0xB73F, 0x7E7F, 0x7E5F, 0x6E3F, 0x65FF, 0x65DE, 0x5D9E, 0x557D, 0x553C, 0x44DC, 0x4D1C, 0x345B, 0x22B4, 0xE71B, // 0x0280 (640) +0xFFFF, 0xD6BC, 0x0234, 0x4CFC, 0x5D7D, 0x4D3C, 0x5D9D, 0x5DBE, 0x65FF, 0x6E3F, 0x765F, 0x867F, 0x8EBF, 0xA6DF, 0xFFFF, 0xFFFF, // 0x0290 (656) +0xFFFF, 0xFFFF, 0xB71F, 0x8EBF, 0x869F, 0x765F, 0x6E3F, 0x65FF, 0x5DBE, 0x5D7D, 0x553D, 0x4D1C, 0x65BE, 0x0AB7, 0x6C15, 0xFFBE, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0x53B6, 0x0296, 0x75FE, 0x5D9D, 0x557D, 0x65DE, 0x6E1F, 0x763F, 0x7E7F, 0x8EBF, 0x9EFF, 0x96BE, 0xAE3C, 0xE77E, // 0x02B0 (688) +0xEF9E, 0xC69D, 0x967E, 0x9EFF, 0x8EBF, 0x7E7F, 0x763F, 0x6E1F, 0x65DE, 0x5D9E, 0x555D, 0x761E, 0x341A, 0x1294, 0xBE18, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xCE9B, 0x0A13, 0x2378, 0x7E5F, 0x6E1E, 0x5DBE, 0x6E1F, 0x7E5F, 0x869F, 0x96DF, 0x9EFF, 0xAF5F, 0x9E9E, 0x8DFC, // 0x02D0 (720) +0x8E1C, 0x967D, 0xAF3F, 0xA6FF, 0x96DF, 0x869F, 0x7E5F, 0x6E1F, 0x5DBE, 0x65DE, 0x7E5F, 0x4CBB, 0x0AB5, 0x7454, 0xEF5C, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFFF, 0xFFFF, 0x8D17, 0x01D3, 0x23B9, 0x7E3E, 0x8E9F, 0x763F, 0x765F, 0x8E9F, 0x9EDF, 0xA71F, 0xB75F, 0xC7BF, 0xCFDF, // 0x02F0 (752) +0xCFDF, 0xC7BF, 0xB75F, 0xA71F, 0x9EDF, 0x8E9F, 0x765F, 0x6E1F, 0x867F, 0x8E7F, 0x4CBB, 0x1317, 0x4BB4, 0xD679, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFBD, 0x7476, 0x0214, 0x1B78, 0x659D, 0x9EDF, 0x9EFF, 0x96DF, 0x9EFF, 0xAF1F, 0xB75F, 0xC79F, 0xD7DF, // 0x0310 (784) +0xD7DF, 0xC79F, 0xB75F, 0xAF1F, 0x9EDF, 0x96DF, 0x96DF, 0x9EFF, 0x7E1E, 0x3C5A, 0x1B77, 0x43B5, 0xBDD6, 0xF7BE, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77D, 0x7CB6, 0x12B4, 0x1337, 0x449B, 0x7DFD, 0xA6FF, 0xB75F, 0xBF7F, 0xC79F, 0xCFBF, 0xD7FF, // 0x0330 (816) +0xD7FF, 0xCFBF, 0xC79F, 0xBF7F, 0xB77F, 0xAF1F, 0x8E5E, 0x551B, 0x3419, 0x2BD7, 0x5415, 0xB5B6, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79D, 0xA577, 0x3B75, 0x1B36, 0x2BD9, 0x4CBB, 0x759D, 0x965E, 0xAEDF, 0xBF3F, 0xC77F, // 0x0350 (848) +0xC77F, 0xBF3F, 0xB6FF, 0x9E7F, 0x7DDD, 0x5D1C, 0x447A, 0x3C59, 0x4437, 0x7474, 0xC617, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDE, 0xD699, 0x84D5, 0x43D5, 0x33B7, 0x3418, 0x4C7A, 0x5CFC, 0x753D, 0x857E, // 0x0370 (880) +0x859E, 0x755D, 0x653C, 0x5CFB, 0x4CDA, 0x4CB9, 0x5497, 0x6C95, 0xA555, 0xDEDA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79D, 0xCE79, 0x9D56, 0x7495, 0x5C56, 0x4C77, 0x4C97, 0x4CB8, // 0x0390 (912) +0x54D8, 0x5CD8, 0x5CF8, 0x64D7, 0x74D6, 0x8CF5, 0xAD96, 0xD699, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFBE, 0xEF1B, 0xD679, 0xBDF7, 0xAD96, 0xA576, // 0x03B0 (944) +0xA576, 0xAD76, 0xB5B6, 0xC5F7, 0xD679, 0xEF3C, 0xFFDE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFBE, // 0x03D0 (976) +0xF7BE, 0xF7BE, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/tux.c b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/tux.c new file mode 100644 index 0000000..3babe53 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap/tux.c @@ -0,0 +1,73 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: tux.png +// Time generated: 11.10.2010 22:51:32 +// Size : 2 048 Bytes + +#include + +const unsigned short tux[0x400] PROGMEM ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x9CD3, 0x9CF3, 0xA514, // 0x0010 (16) +0x9CF3, 0x8C51, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x5AEB, 0x7BEF, 0x9CD3, 0x94B2, // 0x0030 (48) +0x94B2, 0x94B2, 0x4228, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x9CF3, 0x18E3, 0x630C, 0x4A49, 0x4A69, // 0x0050 (80) +0x4A69, 0x528A, 0x4A49, 0x0000, 0xC638, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x0000, 0x0020, 0x10A2, 0x1082, // 0x0070 (112) +0x0841, 0x0841, 0x0841, 0x0000, 0x630C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x528A, 0x4228, 0x8410, 0x0000, 0x0861, // 0x0090 (144) +0xAD55, 0xBDD7, 0x10A2, 0x0000, 0x2945, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x5ACB, 0x8C71, 0xE75D, 0x2126, 0x528B, // 0x00B0 (176) +0xE75D, 0xDEDB, 0x7BCF, 0x0000, 0x18E3, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x4A4A, 0x6B2A, 0x8BE7, 0xA48A, // 0x00D0 (208) +0x6B09, 0x4A8A, 0x8431, 0x0000, 0x2104, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6E, 0x5204, 0xDE6A, 0xFFF7, 0xFFF8, // 0x00F0 (240) +0xD5AC, 0xBCAA, 0x5A66, 0x0000, 0x1082, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C10, 0xC540, 0xFFED, 0xFF2C, 0xFEEC, // 0x0110 (272) +0xFECC, 0xFE66, 0x8260, 0x0000, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B3, 0x9C25, 0xFF20, 0xFE40, 0xFDA0, // 0x0130 (304) +0xFCC0, 0xF524, 0x836A, 0x0000, 0x0000, 0x630C, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x630C, 0x94B4, 0xFF13, 0xFD83, 0xF523, // 0x0150 (336) +0xE5CF, 0xF79E, 0xE71D, 0x0861, 0x0000, 0x0861, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0841, 0xD69A, 0xFFFF, 0xFF7D, 0xF77D, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x4A69, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x10A2, 0x8410, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0000, 0x0000, 0x0000, 0x9492, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01A0 (416) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x52AA, 0x0020, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFDF, 0xFFDF, 0xF7BE, 0xFFDF, 0x3186, 0x0000, 0x0020, 0x0841, 0xCE79, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x0000, 0x52AA, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x01D0 (464) +0xFFDF, 0xF7BE, 0xF79E, 0xFFFF, 0x9CF3, 0x0000, 0x0841, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01E0 (480) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x5ACB, 0x0000, 0xBDF7, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFDF, // 0x01F0 (496) +0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0x3186, 0x0000, 0x0861, 0x0000, 0xAD55, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x0861, 0x4A49, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x0210 (528) +0xF7BE, 0xF79E, 0xEF7D, 0xEF5D, 0xFFDF, 0x8410, 0x0000, 0x1082, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0220 (544) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, // 0x0230 (560) +0xF79E, 0xEF7D, 0xEF7D, 0xE73C, 0xF79E, 0xAD55, 0x0861, 0x10A2, 0x0861, 0x0841, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x3185, 0x10A2, 0xE71C, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, // 0x0250 (592) +0xEF7D, 0xEF7D, 0xEF5D, 0xE73C, 0xEF5D, 0xBDF7, 0x18C3, 0x18C3, 0x18C3, 0x0000, 0x8C71, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0260 (608) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0x39E7, 0xF7BE, 0xFFFF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, 0xEF7D, // 0x0270 (624) +0xEF7D, 0xEF5D, 0xE73C, 0xE71C, 0xE71C, 0xC618, 0x18E3, 0x10A2, 0x10A2, 0x0020, 0x6B4D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C51, 0x38E0, 0x4A27, 0xFFFF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, // 0x0290 (656) +0xEF5D, 0xE73C, 0xE71C, 0xDEFB, 0xDF1D, 0xBDF8, 0x39C7, 0x5ACB, 0x528A, 0x10A3, 0x738F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDD6C, 0xFE2B, 0xBC45, 0xA513, 0xFFFF, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF5D, // 0x02B0 (688) +0xE73C, 0xE71C, 0xDEFB, 0xD6DC, 0xDD8E, 0xB3E4, 0x2124, 0x2965, 0x2945, 0x20C1, 0xB511, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77C, 0xE5CF, 0xF60B, 0xFF9B, 0xFF54, 0x8B02, 0x7BF0, 0xFFDF, 0xF79E, 0xEF5D, 0xEF5D, 0xE73C, // 0x02D0 (720) +0xE71C, 0xDEFB, 0xDEDB, 0xCE7A, 0xED89, 0xDDAD, 0x0842, 0x0000, 0x0000, 0xAC69, 0xDD6B, 0xEFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFFF, 0xFFBE, 0xE5CB, 0xEDC9, 0xFE4B, 0xFF14, 0xFEF3, 0xFF35, 0xFE8D, 0x51C1, 0x634E, 0xE73C, 0xEF5D, 0xE73C, 0xE71C, // 0x02F0 (752) +0xDEFB, 0xDEDB, 0xD6DB, 0xCE59, 0xE58B, 0xFF98, 0xBD4F, 0x8B88, 0xCD90, 0xFFB7, 0xCCE8, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xEF3B, 0xF583, 0xFF30, 0xFF11, 0xFECF, 0xFEEF, 0xFECF, 0xFF30, 0xDD46, 0x2903, 0x6B8E, 0xEF7D, 0xE71C, 0xDEFB, // 0x0310 (784) +0xDEDB, 0xD6BA, 0xD69A, 0xCE59, 0xE5AA, 0xFF11, 0xFF53, 0xFF73, 0xFF33, 0xFF12, 0xFE6C, 0xDDAD, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xF79E, 0xEDC5, 0xFECB, 0xFECC, 0xFECC, 0xFEEC, 0xFECB, 0xFECC, 0xFEEA, 0x9BE5, 0x8432, 0xE73C, 0xDEDB, 0xDEDB, // 0x0330 (816) +0xD6BA, 0xD69A, 0xDEDB, 0xA4F3, 0xD547, 0xFF2E, 0xFECD, 0xFECE, 0xFEEE, 0xFEEE, 0xFF10, 0xFEAB, 0xE5A8, 0xEF7D, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xF79E, 0xF603, 0xFEA2, 0xFEC7, 0xFEC7, 0xFEA4, 0xFE81, 0xFE61, 0xFEA4, 0xFE43, 0xDE33, 0xE75E, 0xE71C, 0xDEFB, // 0x0350 (848) +0xDEDB, 0xCE58, 0x8C72, 0x5247, 0xEDE4, 0xFF0A, 0xFECA, 0xFEC9, 0xFE84, 0xFE83, 0xFEE7, 0xFEA3, 0xB443, 0xD69B, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xF75B, 0xFE60, 0xFF00, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xE5C1, 0x9492, 0xA514, 0x9CD3, // 0x0370 (880) +0x8410, 0x630B, 0x4229, 0x6AE8, 0xFE80, 0xFEC1, 0xFEC1, 0xFEA0, 0xFEA0, 0xFEE0, 0xDD80, 0x9BE8, 0xB597, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xF79E, 0xD589, 0xE600, 0xFEA0, 0xFF00, 0xFF40, 0xFF40, 0xFF00, 0xFF00, 0xFF20, 0xFEC0, 0x5267, 0x4229, 0x4A48, // 0x0390 (912) +0x4A49, 0x5289, 0x424A, 0x7B46, 0xFF20, 0xFEE0, 0xFEE0, 0xFF20, 0xFEE0, 0xB4A5, 0x9C92, 0xDEFD, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xE71D, 0xBDB6, 0xB530, 0xBD0B, 0xCD65, 0xEE60, 0xFF40, 0xFFA0, 0xFF80, 0xBD03, 0x8410, 0xA514, 0xA534, // 0x03B0 (944) +0xAD75, 0xB596, 0xA555, 0x9C8F, 0xF6C0, 0xFFA0, 0xFFA0, 0xF6E0, 0xA449, 0xB5B8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7F, 0xD69C, 0xBD95, 0xBD4C, 0xCDC6, 0xB4E8, 0xAD35, 0xF7BF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xF7BF, 0xCDD0, 0xCDC6, 0xCDA7, 0xA48D, 0xCE7B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF1F, 0xB59A, 0xBDDA, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFDF, 0xFFDF, 0xFFFF, 0xEF7F, 0xB59A, 0xAD59, 0xDF1D, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino new file mode 100644 index 0000000..1d10e99 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.ino @@ -0,0 +1,50 @@ +// UTFT_Bitmap_128x128 (C)2012 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This demo was made to work on the 128x128 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include +#include + +UTFT myGLCD(LPH9135,6,5,2,3,4); // Remember to change the model parameter to suit your display module! + +extern unsigned int icon1[0x400]; +extern unsigned int icon2[0x400]; +extern unsigned int tux[0x1000]; + +void setup() +{ + myGLCD.InitLCD(PORTRAIT); +} + +void loop() +{ +// Draw a 4 by 4 grid of a 32x32 icon. + myGLCD.fillScr(255, 255, 255); + for (int x=0; x<4; x++) + for (int y=0; y<4; y++) + myGLCD.drawBitmap (x*32, y*32, 32, 32, icon1); + + delay(5000); + +// Draw a 64x64 icon in double size. + myGLCD.fillScr(255, 255, 255); + myGLCD.drawBitmap (0, 0, 64, 64, tux, 2); + + delay(5000); + +// Draw a 2 by 2 grid of a 32x32 icon in double size. + myGLCD.fillScr(255, 255, 255); + for (int x=0; x<2; x++) + for (int y=0; y<2; y++) + myGLCD.drawBitmap (x*64, y*64, 32, 32, icon2, 2); + + delay(5000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon1.c b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon1.c new file mode 100644 index 0000000..e9da278 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon1.c @@ -0,0 +1,74 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: exit.png +// Time generated: 14.10.2010 21:53:03 +// Dimensions : 32x32 pixels +// Size : 2 048 Bytes + +#include + +const unsigned short icon1[0x400] PROGMEM ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF1C, 0xE618, 0xE638, 0xE638, 0xE638, 0xE659, 0xE659, 0xE659, 0xE659, 0xE659, 0xE679, 0xE679, // 0x0010 (16) +0xE679, 0xE679, 0xE679, 0xE679, 0xEE79, 0xEE9A, 0xEE9A, 0xEE9A, 0xEE9A, 0xEE9A, 0xE638, 0xEEBA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xD555, 0xCCD3, 0xDDB6, 0xDDD7, 0xDDF7, 0xDDF7, 0xDE18, 0xE618, 0xE638, 0xE638, 0xE659, 0xE679, 0xE679, // 0x0030 (48) +0xEE9A, 0xEE9A, 0xEEBA, 0xEEBA, 0xEEBA, 0xEEDB, 0xEEDB, 0xEEFB, 0xEEFB, 0xEEFB, 0xEEFB, 0xE659, 0xD575, 0xF77D, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFDF, 0xFFFF, 0xD534, 0xC471, 0xD575, 0xCCF3, 0xCCD3, 0xCCD3, 0xCCF3, 0xCCF3, 0xD4F3, 0xD514, 0xD514, 0xD514, 0xD534, 0xDD55, // 0x0050 (80) +0xDD55, 0xDD55, 0xDD55, 0xDD75, 0xDD75, 0xDD75, 0xDD96, 0xDD96, 0xDD96, 0xDDB6, 0xDDD7, 0xEE79, 0xEEBA, 0xD534, 0xFFBE, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xEEDB, 0xB38E, 0xC4B2, 0xBC30, 0xC451, 0xC471, 0xC471, 0xCC71, 0xCC92, 0xCC92, 0xCC92, 0xCCB2, 0xD4B2, 0xD4B2, 0xCC71, // 0x0070 (112) +0xCC71, 0xD4D3, 0xD4F3, 0xDCF3, 0xDCF3, 0xDD14, 0xDD14, 0xDD14, 0xDD34, 0xDD34, 0xDD34, 0xDD14, 0xE5D7, 0xDD96, 0xDDF7, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xC4F3, 0xAB2C, 0xC430, 0xC410, 0xC430, 0xC430, 0xC430, 0xCC51, 0xCC51, 0xCC51, 0xCC71, 0xCC71, 0xD471, 0xCC71, 0xD5F7, // 0x0090 (144) +0xD5F7, 0xCC92, 0xDCB2, 0xDCD3, 0xDCD3, 0xDCD3, 0xDCD3, 0xDCF3, 0xDCF3, 0xDD14, 0xDD14, 0xDD34, 0xDD14, 0xDD34, 0xC492, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xB3EF, 0x9A28, 0xC430, 0xBBCF, 0xC3EF, 0xC3EF, 0xC3EF, 0xC410, 0xCC10, 0xCC10, 0xCC30, 0xCC51, 0xCBEF, 0xE638, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xE659, 0xD430, 0xDC92, 0xDC92, 0xDC92, 0xDCB2, 0xDCB2, 0xDCB2, 0xDCD3, 0xDCD3, 0xDCD3, 0xE514, 0xD410, 0xAB0C, 0xF7FF, // 0x00C0 (192) +0xFFFF, 0xABCF, 0x9165, 0xC3EF, 0xBB8E, 0xBBAE, 0xC3AE, 0xC3CF, 0xC3CF, 0xCBCF, 0xCBEF, 0xCC10, 0xCC10, 0xCBAE, 0xEE9A, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xF6DB, 0xD410, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xE492, 0xE492, 0xE492, 0xE4F3, 0xCB2C, 0xA249, 0xF7FF, // 0x00E0 (224) +0xFFFF, 0xABCF, 0x88C3, 0xC3AE, 0xBB4D, 0xBB6D, 0xC36D, 0xC38E, 0xC38E, 0xCBAE, 0xC36D, 0xC34D, 0xCBCF, 0xCB8E, 0xEE59, 0xFFFF, // 0x00F0 (240) +0xFFFF, 0xF6BA, 0xDBCF, 0xD3CF, 0xCBAE, 0xD3CF, 0xE430, 0xE430, 0xE451, 0xE451, 0xE451, 0xE451, 0xECD3, 0xCAAA, 0xA208, 0xF7FF, // 0x0100 (256) +0xFFFF, 0xABCF, 0x8061, 0xBB6D, 0xBB2C, 0xBB2C, 0xC34D, 0xC34D, 0xCB4D, 0xBB0C, 0xC492, 0xCD14, 0xC38E, 0xCB2C, 0xEE59, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xF6BA, 0xD36D, 0xD575, 0xE6DB, 0xDDB6, 0xD3AE, 0xE3EF, 0xE410, 0xE410, 0xE430, 0xE410, 0xECB2, 0xC986, 0xA208, 0xF7FF, // 0x0120 (288) +0xFFFF, 0xB3EF, 0x8041, 0xBB0C, 0xBAEB, 0xBAEB, 0xC30C, 0xC30C, 0xBACB, 0xD5B6, 0xFFFF, 0xFFFF, 0xEE79, 0xCACB, 0xEE59, 0xFFFF, // 0x0130 (304) +0xFFFF, 0xF679, 0xDBEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEEBA, 0xD3CF, 0xE3AE, 0xE3EF, 0xE3CF, 0xEC10, 0xEB6D, 0xC000, 0xA249, 0xF7FF, // 0x0140 (320) +0xFFFF, 0xB3EF, 0x8020, 0xBACB, 0xBAAA, 0xBAAA, 0xC2EB, 0xBA8A, 0xD596, 0xFFFF, 0xFFDF, 0xFFFF, 0xF73C, 0xCAAA, 0xEE38, 0xFFFF, // 0x0150 (336) +0xFFFF, 0xF679, 0xDB4D, 0xFF7D, 0xFFFF, 0xFFDF, 0xFFFF, 0xEEDB, 0xDB6D, 0xEB8E, 0xEBAE, 0xEB8E, 0xE0A2, 0xC800, 0xAA49, 0xF7FF, // 0x0160 (352) +0xFFFF, 0xB3EF, 0x8000, 0xB28A, 0xBA69, 0xBA8A, 0xBA49, 0xCC30, 0xFFFF, 0xFFDF, 0xFFFF, 0xFF5D, 0xDBCF, 0xCA69, 0xEE18, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xF679, 0xDAAA, 0xE3AE, 0xF6BA, 0xFFFF, 0xFFDF, 0xFFFF, 0xE5D7, 0xE30C, 0xEB8E, 0xE0E3, 0xE000, 0xC800, 0xAA49, 0xF7FF, // 0x0180 (384) +0xFFFF, 0xB3EF, 0x8800, 0xB249, 0xBA49, 0xBA49, 0xBA49, 0xEF1C, 0xFFFF, 0xFFFF, 0xFF7D, 0xD32C, 0xCA69, 0xD249, 0xEDF7, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xF659, 0xDAAA, 0xE2CB, 0xE2EB, 0xFEBA, 0xFFFF, 0xFFDF, 0xFFDF, 0xE3CF, 0xE103, 0xE000, 0xE081, 0xD000, 0xAA69, 0xF7FF, // 0x01A0 (416) +0xFFFF, 0xB3EF, 0x8800, 0xB228, 0xBA08, 0xB9A6, 0xCBAE, 0xFFFF, 0xFFDF, 0xFFFF, 0xDC30, 0xC9E7, 0xD28A, 0xCA08, 0xF618, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xF679, 0xDA49, 0xE2CB, 0xE28A, 0xEB6D, 0xFFBE, 0xFFDF, 0xFFFF, 0xEC92, 0xE000, 0xE0A2, 0xE0C2, 0xD040, 0xAA89, 0xF7FF, // 0x01C0 (448) +0xFFFF, 0xB3EF, 0x8800, 0xB1E7, 0xB9E7, 0xB165, 0xDD55, 0xFFFF, 0xFFFF, 0xF71C, 0xCA08, 0xCA08, 0xD228, 0xD1E7, 0xE430, 0xFFDF, // 0x01D0 (464) +0xFFDF, 0xEC51, 0xDA08, 0xE28A, 0xE28A, 0xE228, 0xF618, 0xFFFF, 0xFFFF, 0xF679, 0xE081, 0xE0C2, 0xE903, 0xD081, 0xAA89, 0xF7FF, // 0x01E0 (480) +0xFFFF, 0xBBEF, 0x9000, 0xB1A6, 0xB986, 0xB145, 0xEE38, 0xFFFF, 0xFFFF, 0xED96, 0xC165, 0xC9E7, 0xD1E7, 0xD1E7, 0xD1C7, 0xDACB, // 0x01F0 (496) +0xE2EB, 0xD9E7, 0xE228, 0xE228, 0xEA69, 0xE9E7, 0xF40F, 0xFFFF, 0xFFFF, 0xFF5D, 0xE144, 0xE8E2, 0xE943, 0xD8C1, 0xAA8A, 0xF7FF, // 0x0200 (512) +0xFFFF, 0xBC10, 0x9000, 0xB165, 0xB145, 0xB924, 0xEE9A, 0xFFFF, 0xFFFF, 0xE514, 0xC124, 0xC9A6, 0xD1A6, 0xD1A6, 0xD1C7, 0xD9A6, // 0x0210 (528) +0xD9A6, 0xE1E7, 0xE208, 0xE208, 0xE9A6, 0xE041, 0xEA8A, 0xFFFF, 0xFFFF, 0xFF9E, 0xE9C6, 0xE902, 0xE984, 0xD902, 0xAAAA, 0xF7FF, // 0x0220 (544) +0xFFFF, 0xC410, 0x9000, 0xB124, 0xB124, 0xB0C3, 0xEE18, 0xFFFF, 0xFFFF, 0xE575, 0xC0E3, 0xC986, 0xD165, 0xD165, 0xD986, 0xD9A6, // 0x0230 (560) +0xD9A6, 0xE1A6, 0xE165, 0xE082, 0xE020, 0xE000, 0xEB4C, 0xFFFF, 0xFFFF, 0xFF7D, 0xE9A5, 0xE943, 0xE9A5, 0xD923, 0xAAAA, 0xF7FF, // 0x0240 (576) +0xFFFF, 0xC410, 0x9800, 0xB0E3, 0xB0E3, 0xB061, 0xE4F3, 0xFFFF, 0xFFFF, 0xF6FB, 0xC104, 0xC924, 0xD145, 0xD145, 0xD945, 0xD945, // 0x0250 (592) +0xD8E3, 0xD861, 0xD800, 0xE000, 0xE061, 0xE000, 0xED34, 0xFFFF, 0xFFFF, 0xFE9A, 0xE923, 0xE984, 0xE9C5, 0xE163, 0xAAAA, 0xF7FF, // 0x0260 (608) +0xFFFF, 0xC410, 0xA000, 0xB0A2, 0xB0A2, 0xB041, 0xCACB, 0xFFFF, 0xFFDF, 0xFFFF, 0xD34D, 0xC841, 0xD104, 0xD0A2, 0xD061, 0xD000, // 0x0270 (624) +0xD800, 0xD800, 0xE000, 0xE041, 0xE000, 0xD965, 0xFF9E, 0xFFDF, 0xFFFF, 0xF4D2, 0xE8E2, 0xE9A5, 0xE9E5, 0xE183, 0xAAAA, 0xF7FF, // 0x0280 (640) +0xFFFF, 0xCC10, 0xA000, 0xA861, 0xB061, 0xB061, 0xB882, 0xF6DB, 0xFFFF, 0xFFDF, 0xF75D, 0xC124, 0xC800, 0xD000, 0xD000, 0xD800, // 0x0290 (656) +0xD800, 0xE000, 0xE020, 0xE000, 0xD861, 0xF638, 0xFFFF, 0xFFDF, 0xFFDF, 0xEA68, 0xE943, 0xE9C5, 0xEA06, 0xE1A4, 0xB2CA, 0xF7FF, // 0x02A0 (672) +0xFFFF, 0xCC10, 0xA000, 0xA820, 0xB000, 0xB000, 0xB000, 0xCA49, 0xFFFF, 0xFFDF, 0xFFFF, 0xF71C, 0xCA08, 0xC800, 0xD000, 0xD800, // 0x02B0 (688) +0xD800, 0xD800, 0xD800, 0xD944, 0xEE18, 0xFFFF, 0xFFBE, 0xFFFF, 0xF4F2, 0xE902, 0xE9A5, 0xE9C5, 0xEA06, 0xE9A4, 0xB2CA, 0xF7FF, // 0x02C0 (704) +0xFFFF, 0xD410, 0xA800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xDC10, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xED96, 0xDAEB, 0xD1A6, // 0x02D0 (720) +0xD965, 0xDA69, 0xECD3, 0xFF9E, 0xFFFF, 0xFFBE, 0xFFFF, 0xFE17, 0xE923, 0xE964, 0xE9A5, 0xE9C5, 0xEA26, 0xE9C4, 0xBACA, 0xF7FF, // 0x02E0 (736) +0xF7FF, 0xD410, 0xA800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xB800, 0xE3EF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02F0 (752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF5B6, 0xE923, 0xE923, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xE9C5, 0xBACA, 0xF7FF, // 0x0300 (768) +0xF7FF, 0xDC10, 0xB000, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xD228, 0xF638, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0310 (784) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFEFB, 0xF3AE, 0xE0C1, 0xE903, 0xE964, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xE9E5, 0xC2CA, 0xF7DF, // 0x0320 (800) +0xF7FF, 0xDC51, 0xB800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xC000, 0xC800, 0xD9E7, 0xEC30, 0xF5D7, 0xFE9A, // 0x0330 (816) +0xFEBA, 0xF618, 0xF4D3, 0xEACB, 0xE0E2, 0xE040, 0xE903, 0xE943, 0xE943, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xEA05, 0xC30C, 0xF7DF, // 0x0340 (832) +0xFFFF, 0xD575, 0xD104, 0xA820, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xC000, 0xC820, 0xC800, 0xD000, 0xD000, 0xD800, 0xD800, // 0x0350 (848) +0xE000, 0xE000, 0xE000, 0xE000, 0xE0A1, 0xE0E3, 0xE903, 0xE943, 0xE964, 0xE984, 0xE9C5, 0xE9C5, 0xF226, 0xE227, 0xBC10, 0xF7FF, // 0x0360 (864) +0xFFFF, 0xDF3C, 0xCAAA, 0xD186, 0xB082, 0xB000, 0xB800, 0xB800, 0xB800, 0xC000, 0xC000, 0xC800, 0xC800, 0xD000, 0xD000, 0xD800, // 0x0370 (880) +0xD800, 0xE000, 0xE020, 0xE040, 0xE061, 0xE0A1, 0xE0C2, 0xE102, 0xE123, 0xE943, 0xE984, 0xEA26, 0xFB0A, 0xBA08, 0xCE38, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFDF, 0xBDD7, 0xCA69, 0xE248, 0xD207, 0xD1C6, 0xD1C6, 0xD9C7, 0xD9C7, 0xE1C7, 0xE1C7, 0xE1C7, 0xE9C7, 0xE9C7, 0xE9C7, // 0x0390 (912) +0xF1C6, 0xF1C7, 0xF1E7, 0xF207, 0xF228, 0xF248, 0xF269, 0xF289, 0xF2A9, 0xF2CA, 0xFB0A, 0xF2EA, 0xC207, 0xACB3, 0xF7BE, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xF7BE, 0xBDF7, 0xAB8E, 0xC2EB, 0xC2EB, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xCB0B, 0xCAEB, // 0x03B0 (944) +0xCAEB, 0xCACA, 0xCACA, 0xCAAA, 0xCAAA, 0xCA8A, 0xCA69, 0xC269, 0xC269, 0xC289, 0xBA69, 0xA2CB, 0xAD34, 0xEF7D, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xDF3C, 0xBE39, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, // 0x03D0 (976) +0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xBE38, 0xD71C, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon2.c b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon2.c new file mode 100644 index 0000000..3bcc564 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/icon2.c @@ -0,0 +1,74 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: video.png +// Time generated: 14.10.2010 21:53:17 +// Dimensions : 32x32 pixels +// Size : 2 048 Bytes + +#include + +const unsigned short icon2[0x400] PROGMEM ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE71C, 0xB5B6, 0x94B2, 0x8C71, // 0x0030 (48) +0x9492, 0xA534, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x9CF3, 0x73AE, 0x6B6D, 0x73AE, 0x7BCF, // 0x0050 (80) +0x7BEF, 0x7BCF, 0x7BEF, 0xA534, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC638, 0x7BCF, 0x6B6D, 0x738E, 0x7BCF, 0x8C71, 0x9492, // 0x0070 (112) +0x9492, 0x9492, 0x9492, 0x8C51, 0x8C71, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x738E, 0x738E, 0x73AE, 0x6B4D, 0x8410, 0x9CF3, 0x9CF3, // 0x0090 (144) +0x9CF3, 0x9CF3, 0x9CF3, 0x9CF3, 0x94B2, 0x7BEF, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x738E, 0x7BEF, 0x8410, 0x632C, 0x4A69, 0x9492, 0xAD75, 0xAD55, // 0x00B0 (176) +0xAD55, 0xAD55, 0xAD55, 0xA534, 0xAD55, 0x9492, 0x8430, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDF7, 0x7BCF, 0x8430, 0x7BCF, 0x6B4D, 0x528A, 0x6B6D, 0xB5B6, 0xB5B6, 0xB5B6, // 0x00D0 (208) +0xB5B6, 0xB596, 0xB596, 0xAD75, 0xAD75, 0xAD55, 0x8410, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x7BEF, 0x9CD3, 0xA514, 0x5AEB, 0x630C, 0x6B4D, 0x9492, 0xC638, 0xC618, 0xC618, // 0x00F0 (240) +0xBDF7, 0xBDF7, 0xC618, 0xB5B6, 0xB5B6, 0xB596, 0x9492, 0x8C51, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8C71, 0x94B2, 0xAD55, 0xB5B6, 0x738E, 0x6B4D, 0x632C, 0xB596, 0xD69A, 0xCE59, 0xCE59, // 0x0110 (272) +0xCE79, 0xCE59, 0x6B6D, 0x9492, 0xB5B6, 0xBDF7, 0x9CF3, 0x8430, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB5B6, 0x8C51, 0xAD55, 0xB5B6, 0xCE79, 0x8C51, 0x630C, 0x8C51, 0xCE79, 0xD6BA, 0xD69A, 0xDEDB, // 0x0130 (304) +0xBDD7, 0x8C51, 0x4228, 0x2965, 0xAD55, 0xC638, 0xA534, 0x8430, 0xB5B6, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x8C51, 0xA514, 0xB5B6, 0xC618, 0xD6BA, 0xB5B6, 0xB596, 0xE71C, 0xDEFB, 0xDEFB, 0xE71C, 0xAD55, // 0x0150 (336) +0x738E, 0x7BEF, 0x5AEB, 0x2945, 0xC638, 0xCE59, 0xA534, 0x9492, 0xA534, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x94B2, 0xB5B6, 0xC618, 0xCE79, 0xD6BA, 0xE73C, 0xEF7D, 0xE73C, 0xEF5D, 0xE73C, 0x9CF3, 0x738E, // 0x0170 (368) +0x7BCF, 0x8430, 0x6B6D, 0x2965, 0xB596, 0xD69A, 0xAD55, 0x94B2, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xF79E, 0x9492, 0x9CF3, 0xB5B6, 0xD69A, 0xDEFB, 0xE71C, 0xE73C, 0x6B6D, 0x528A, 0xDEDB, 0xEF5D, 0x7BEF, 0x8430, // 0x0190 (400) +0x7BEF, 0x8C51, 0x7BCF, 0x2104, 0xB596, 0xD6BA, 0xAD55, 0x9CD3, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0xE6FC, // 0x01A0 (416) +0xFFDF, 0xFFFF, 0xCE59, 0x9492, 0x9492, 0x6B4D, 0x7BCF, 0xBDD7, 0xF7BE, 0xA514, 0x4A49, 0x528A, 0xC638, 0xEF7D, 0x7BEF, 0x7BEF, // 0x01B0 (432) +0x7BEF, 0x8430, 0x5AEB, 0x10A2, 0xC618, 0xD69A, 0xAD55, 0x94B2, 0xA514, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE5A, 0x8BF2, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xAD55, 0x94B2, 0x8C51, 0x5AEB, 0x632C, 0xBDD7, 0xE73C, 0x630C, 0x632C, 0xBDF7, 0xFFDF, 0xEF5D, 0xBDD7, 0xB5B6, // 0x01D0 (464) +0xAD75, 0xAD75, 0x8C51, 0x738E, 0xD69A, 0xCE59, 0xB596, 0x8C51, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xCE39, 0x7350, // 0x01E0 (480) +0xFFFF, 0xF79E, 0x94B2, 0x94B2, 0x7BCF, 0x5AEB, 0x738E, 0xD6BA, 0xD69A, 0x2104, 0x6B6D, 0xF79E, 0xF79E, 0xF79E, 0xF7BE, 0xF79E, // 0x01F0 (496) +0xEF7D, 0xEF5D, 0xE73C, 0xE73C, 0xDEFB, 0xBDF7, 0xBDF7, 0x7BEF, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD36, 0x7350, // 0x0200 (512) +0xFFFF, 0xDEDB, 0x8C51, 0x94B2, 0x738E, 0x632C, 0x73AE, 0xCE79, 0xF7BE, 0x7BEF, 0xA514, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0210 (528) +0xE73C, 0xE71C, 0xDEFB, 0xDEDB, 0xDEDB, 0xBDD7, 0xBDF7, 0x73AE, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x9C75, 0x736F, // 0x0220 (544) +0xFFFF, 0xCE59, 0x8430, 0x94B2, 0x6B4D, 0x6B4D, 0xB596, 0xE73C, 0xEF7D, 0xFFFF, 0xFFFF, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0230 (560) +0xE73C, 0xE73C, 0xDEFB, 0xDEFB, 0xD6BA, 0xC618, 0xAD55, 0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x6AEF, 0x9492, // 0x0240 (576) +0xFFFF, 0xBDF7, 0x8430, 0x8C71, 0x6B6D, 0xB596, 0xE71C, 0xE73C, 0xEF5D, 0xE73C, 0xBDF7, 0xCE59, 0xF7BE, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0250 (592) +0xE73C, 0xE71C, 0xDEFB, 0xDEFB, 0xC638, 0xD69A, 0x8410, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x9474, 0x6B0E, 0xCE59, // 0x0260 (608) +0xFFFF, 0xB5B6, 0x8410, 0x9492, 0xBDD7, 0xD6BA, 0xD6BA, 0xE71C, 0xE73C, 0x8C71, 0x6B4D, 0xA514, 0xF7BE, 0xEF5D, 0xEF5D, 0xE73C, // 0x0270 (624) +0xE73C, 0xE71C, 0xDEFB, 0xDEDB, 0xCE59, 0xC618, 0x7BCF, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC5F9, 0x7B51, 0x7BEF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xB596, 0x8C71, 0xAD75, 0xBDF7, 0xCE59, 0xD69A, 0xE71C, 0xCE79, 0x8410, 0x8410, 0x9CD3, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, // 0x0290 (656) +0xE71C, 0xDEFB, 0xDEFB, 0xCE59, 0xDEDB, 0x8C71, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEBB, 0x83B2, 0x630C, 0xE73C, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xB5B6, 0x9492, 0xAD55, 0xBDD7, 0xC638, 0xCE79, 0xDEFB, 0xB596, 0x73AE, 0x8410, 0x8410, 0xDEDB, 0xE73C, 0xE71C, 0xE71C, // 0x02B0 (688) +0xDEFB, 0xDEFB, 0xD6BA, 0xCE59, 0xC618, 0x738E, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x8C14, 0x5ACC, 0xC658, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xC638, 0x8C51, 0xA534, 0xB5B6, 0xBDF7, 0xCE59, 0xD6BA, 0x94B2, 0x738E, 0x8410, 0x8430, 0xCE59, 0xE73C, 0xDEFB, 0xDEFB, // 0x02D0 (720) +0xDEDB, 0xDEFB, 0xBDF7, 0xDEDB, 0x73AE, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x8BD2, 0x5ACC, 0xBDD6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xDEDB, 0x8C51, 0xA514, 0xAD75, 0xBDD7, 0xC638, 0xC618, 0x73AE, 0x7BCF, 0x8410, 0x5ACB, 0x8C51, 0xE73C, 0xDEDB, 0xD6BA, // 0x02F0 (752) +0xDEFB, 0xBDD7, 0xD69A, 0x8C71, 0x8C51, 0xFFFF, 0xFFFF, 0xFFDE, 0xCE5A, 0x7B71, 0x62ED, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xF7BE, 0x94B2, 0x94B2, 0xA534, 0xB596, 0xBDF7, 0xB596, 0x6B6D, 0x4208, 0x2945, 0x18C3, 0x6B6D, 0xDEFB, 0xD69A, 0xDEDB, // 0x0310 (784) +0xB5B6, 0xC618, 0x9CF3, 0x6B4D, 0xFFDE, 0xFFFF, 0xEF5D, 0xAD37, 0x62EE, 0x6B4D, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFDF, 0xFFFF, 0xBDF7, 0x8C51, 0xA514, 0xAD55, 0xB596, 0xBDD7, 0xA514, 0x738E, 0xA514, 0xB5B6, 0xCE59, 0xD69A, 0xDEDB, 0xB596, // 0x0330 (816) +0xBDF7, 0xA534, 0x6B4C, 0xEF5D, 0xF79E, 0xBDB8, 0x7370, 0x5AAC, 0x8C71, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xF79E, 0x94B2, 0x94B2, 0xA534, 0xAD55, 0xB5B6, 0xA534, 0xBDD7, 0xD69A, 0xCE59, 0xCE79, 0xCE59, 0xA534, 0x8430, // 0x0350 (848) +0x738E, 0x3186, 0x7BB0, 0x8C33, 0x7370, 0x62ED, 0x8410, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x8C71, 0x9CD3, 0xAD55, 0xB596, 0xBDD7, 0xBDD7, 0xBDF7, 0xC618, 0xB5B6, 0xA534, 0xA534, 0x632C, // 0x0370 (880) +0x6B6D, 0xB5B6, 0xAD76, 0xAD76, 0xBE17, 0xE71B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x94B2, 0x8C51, 0x94B2, 0xA534, 0xAD55, 0xAD55, 0x9CD3, 0x8C71, 0x73AE, 0x632C, 0xA534, // 0x0390 (912) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xCE59, 0xA514, 0x8430, 0x7BCF, 0x738E, 0x73AE, 0x8410, 0xA534, 0xEF7D, 0xFFFF, // 0x03B0 (944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xE73C, 0xE71C, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/tux.c b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/tux.c new file mode 100644 index 0000000..6c2e1e4 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Bitmap_128x128/tux.c @@ -0,0 +1,266 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: tux_64x64.png +// Time generated: 14.10.2010 21:56:38 +// Dimensions : 64x64 pixels +// Size : 8 192 Bytes + +#include + +const unsigned short tux[0x1000] PROGMEM ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE79, 0x9CF3, 0x7BCF, 0x738E, 0x738E, // 0x0020 (32) +0x6B6D, 0x94B2, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0030 (48) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0050 (80) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE79, 0x6B4D, 0x5ACB, 0x8410, 0x9CF3, 0x9CF3, 0x9CF3, // 0x0060 (96) +0x9CD3, 0x73AE, 0x4208, 0x5ACB, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0070 (112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0090 (144) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA514, 0x3186, 0x8C51, 0xBDF7, 0xC618, 0xBDF7, 0xBDF7, 0xBDF7, // 0x00A0 (160) +0xBDF7, 0xC618, 0xBDD7, 0x738E, 0x18C3, 0x8C51, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xBDD7, 0x10A2, 0x8C71, 0x9CF3, 0x8C71, 0x8C71, 0x8C71, 0x8C71, 0x8C71, // 0x00E0 (224) +0x8C71, 0x8C51, 0x8C51, 0x9CF3, 0x73AE, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00F0 (240) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x2945, 0x31A6, 0x7BCF, 0x6B4D, 0x6B6D, 0x6B6D, 0x6B6D, 0x6B6D, 0x6B6D, // 0x0120 (288) +0x6B6D, 0x6B6D, 0x6B6D, 0x6B4D, 0x73AE, 0x2124, 0x0000, 0xAD55, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0130 (304) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0150 (336) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x0000, 0x31A6, 0x52AA, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, // 0x0160 (352) +0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x528A, 0x2104, 0x0000, 0x2965, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C71, 0x0000, 0x1082, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, // 0x01A0 (416) +0x3186, 0x3186, 0x3186, 0x3186, 0x2965, 0x0020, 0x0000, 0x0000, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01D0 (464) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x630C, 0x0000, 0x0000, 0x0861, 0x18C3, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x18C3, // 0x01E0 (480) +0x1082, 0x0841, 0x1082, 0x10A2, 0x0020, 0x0000, 0x0000, 0x0000, 0x528A, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01F0 (496) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0210 (528) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x4A49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0220 (544) +0x0861, 0x3186, 0x18C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0230 (560) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0250 (592) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39C7, 0x0000, 0x3186, 0xAD75, 0x8C51, 0x0841, 0x0000, 0x0000, 0x0000, 0x4208, // 0x0260 (608) +0xD6BA, 0xFFDF, 0xE71C, 0x630C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0270 (624) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0290 (656) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39C7, 0x0000, 0xCE59, 0xFFFF, 0xFFFF, 0x94B2, 0x0000, 0x0000, 0x10A2, 0xE73C, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000, 0x94B2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02B0 (688) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02D0 (720) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2965, 0x18E3, 0xDEDB, 0x7BCF, 0xAD75, 0xEF5D, 0x2944, 0x0000, 0x5ACA, 0xFFFF, // 0x02E0 (736) +0xAD55, 0x94B2, 0xAD55, 0xF7BE, 0x8410, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02F0 (752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0310 (784) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39E7, 0x2945, 0xA514, 0x9CF3, 0x8C71, 0xD6BB, 0x39C9, 0x0000, 0x632E, 0xF7DF, // 0x0320 (800) +0x7BEF, 0xAD54, 0x7BEF, 0xBDF7, 0xB596, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C71, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0330 (816) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0350 (848) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4A49, 0x18C3, 0x9492, 0x39E7, 0x3187, 0xA48F, 0x8323, 0x5A00, 0x93A6, 0xCDD5, // 0x0360 (864) +0x4209, 0x4249, 0x2965, 0x9CD2, 0xB575, 0x0000, 0x0000, 0x0000, 0x0000, 0x9492, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0370 (880) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0390 (912) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x5ACB, 0x0000, 0x9D14, 0x2905, 0x6A40, 0xE643, 0xFFAE, 0xFFF3, 0xFF70, 0xDD86, // 0x03A0 (928) +0x7240, 0x1840, 0x18C3, 0xC65A, 0x73CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03B0 (944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x738E, 0x0000, 0x5A6A, 0xD566, 0xFF66, 0xFFF8, 0xFFFD, 0xFFDC, 0xFFFD, 0xFFFA, // 0x03E0 (992) +0xFF0E, 0xE566, 0xC464, 0xC4CC, 0x2103, 0x0000, 0x0000, 0x0000, 0x0000, 0x6B6D, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0410 (1040) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BEF, 0x0800, 0xB440, 0xFFC6, 0xFFF3, 0xFFB4, 0xFFB2, 0xFF92, 0xFF72, 0xFF53, // 0x0420 (1056) +0xFF55, 0xFF75, 0xFEF0, 0xF542, 0x8240, 0x0000, 0x0000, 0x0000, 0x0000, 0x4228, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0430 (1072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0440 (1088) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0450 (1104) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8432, 0x4140, 0xFFE2, 0xFFEB, 0xFFAC, 0xFF8B, 0xFF4C, 0xFF2C, 0xFEEC, 0xFECB, // 0x0460 (1120) +0xFE6A, 0xFE08, 0xFDA7, 0xFDC3, 0xA320, 0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0470 (1136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0480 (1152) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0490 (1168) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9D14, 0x28A0, 0xF6E0, 0xFFE1, 0xFF43, 0xFF04, 0xFEC4, 0xFE84, 0xFE23, 0xFDE1, // 0x04A0 (1184) +0xFD60, 0xFD20, 0xFD20, 0xFD20, 0x7241, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04B0 (1200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04C0 (1216) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04D0 (1232) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xB5B6, 0x0000, 0xC4A9, 0xFEC0, 0xFF00, 0xFEA0, 0xFE40, 0xFE00, 0xFDA0, 0xFD60, // 0x04E0 (1248) +0xFD40, 0xFD20, 0xEC80, 0xDCC7, 0x8C0F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04F0 (1264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0500 (1280) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0510 (1296) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xAD75, 0x0000, 0xD69B, 0xF631, 0xF5C0, 0xFE80, 0xFE00, 0xFDC0, 0xFD60, 0xFD40, // 0x0520 (1312) +0xFCC0, 0xDC86, 0xCD93, 0xE73D, 0xE71C, 0x0861, 0x0000, 0x0000, 0x0000, 0x0000, 0x0861, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0530 (1328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0540 (1344) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0550 (1360) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x632C, 0x0000, 0xD6BA, 0xFFFF, 0xF5F1, 0xFD40, 0xFD80, 0xFD20, 0xFCE0, 0xECA3, // 0x0560 (1376) +0xDD6F, 0xE6FC, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5ACB, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0570 (1392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0580 (1408) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0590 (1424) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xDEDB, 0x0861, 0x0000, 0xD69A, 0xFFFF, 0xFFFF, 0xFED8, 0xF631, 0xF610, 0xE5F2, 0xE6B9, // 0x05A0 (1440) +0xF7BF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xE71C, 0x10A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05B0 (1456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05C0 (1472) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05D0 (1488) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x39E7, 0x0000, 0x4228, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7FF, 0xF7DF, 0xFFFF, // 0x05E0 (1504) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3186, 0xEF7D, 0xFFFF, 0xFFFF, // 0x05F0 (1520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0600 (1536) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0610 (1552) +0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x738E, 0x0000, 0x18C3, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0620 (1568) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFFF, 0xCE59, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6B4D, 0xFFFF, 0xFFFF, // 0x0630 (1584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0640 (1600) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0650 (1616) +0xFFFF, 0xFFDF, 0xFFFF, 0xA514, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0660 (1632) +0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0x2965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xAD55, 0xFFFF, // 0x0670 (1648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0680 (1664) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0690 (1680) +0xFFDF, 0xFFFF, 0xD69A, 0x0861, 0x0000, 0x2945, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06A0 (1696) +0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xFFFF, 0x7BCF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C3, 0xD6BA, // 0x06B0 (1712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06C0 (1728) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06D0 (1744) +0xFFFF, 0xFFDF, 0x39C7, 0x0000, 0x0000, 0x8430, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06E0 (1760) +0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xFFFF, 0xCE79, 0x0841, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4228, // 0x06F0 (1776) +0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0700 (1792) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x0710 (1808) +0xFFFF, 0x94B2, 0x0000, 0x0020, 0x0020, 0xCE79, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x0720 (1824) +0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xFFDF, 0x4A69, 0x0000, 0x0841, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, // 0x0730 (1840) +0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0740 (1856) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0750 (1872) +0xEF7D, 0x2104, 0x0020, 0x0000, 0x3186, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, // 0x0760 (1888) +0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xFFFF, 0xB5B6, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, // 0x0770 (1904) +0x10A2, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0780 (1920) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x0790 (1936) +0x8C71, 0x0000, 0x0861, 0x0000, 0x7BCF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x07A0 (1952) +0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xFFDF, 0x528A, 0x0000, 0x0841, 0x0020, 0x0020, 0x0020, 0x0020, // 0x07B0 (1968) +0x0000, 0x630C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x07C0 (1984) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, // 0x07D0 (2000) +0x3186, 0x0000, 0x0841, 0x10A2, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x07E0 (2016) +0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF5D, 0xF7BE, 0xBDD7, 0x0841, 0x0861, 0x0841, 0x0841, 0x0841, 0x0020, // 0x07F0 (2032) +0x0020, 0x1082, 0xC638, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0800 (2048) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDD7, // 0x0810 (2064) +0x0020, 0x1082, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, // 0x0820 (2080) +0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF7D, 0x4208, 0x0020, 0x0861, 0x0861, 0x0841, 0x0841, // 0x0830 (2096) +0x0841, 0x0000, 0x630C, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0840 (2112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x6B4D, // 0x0850 (2128) +0x0000, 0x0861, 0x2104, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, // 0x0860 (2144) +0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xE73C, 0xF7BE, 0x8430, 0x0000, 0x1082, 0x0861, 0x0861, 0x0861, // 0x0870 (2160) +0x0861, 0x0020, 0x18C3, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0880 (2176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x2124, // 0x0890 (2192) +0x0861, 0x0020, 0x8410, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, // 0x08A0 (2208) +0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xEF7D, 0xB5B6, 0x0861, 0x1082, 0x1082, 0x0861, 0x0861, // 0x08B0 (2224) +0x0861, 0x0861, 0x0000, 0x8430, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x08C0 (2240) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xA514, 0x0020, // 0x08D0 (2256) +0x10A2, 0x1082, 0xD69A, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x08E0 (2272) +0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xEF5D, 0xCE79, 0x2124, 0x1082, 0x10A2, 0x1082, 0x1082, // 0x08F0 (2288) +0x0861, 0x1082, 0x0000, 0x4208, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0900 (2304) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x4208, 0x0861, // 0x0910 (2320) +0x1082, 0x31A6, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, // 0x0920 (2336) +0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEDB, 0x39C7, 0x1082, 0x10A2, 0x10A2, 0x1082, // 0x0930 (2352) +0x1082, 0x1082, 0x0841, 0x18C3, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0940 (2368) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA534, 0x0841, 0x18C3, // 0x0950 (2384) +0x0841, 0x630C, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, // 0x0960 (2400) +0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xDEFB, 0xE73C, 0x4A49, 0x0861, 0x18C3, 0x10A2, 0x10A2, // 0x0970 (2416) +0x10A2, 0x1082, 0x1082, 0x0841, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0980 (2432) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x3186, 0x1082, 0x18E3, // 0x0990 (2448) +0x0861, 0x94B2, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, // 0x09A0 (2464) +0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEDB, 0xE73C, 0x4A69, 0x1082, 0x18E3, 0x18C3, 0x10A2, // 0x09B0 (2480) +0x10A2, 0x10A2, 0x10A2, 0x0020, 0x73AE, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x09C0 (2496) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0841, 0x18E3, 0x18E3, // 0x09D0 (2512) +0x0861, 0xAD75, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, // 0x09E0 (2528) +0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEDB, 0xE73C, 0x52AA, 0x10A2, 0x2104, 0x18E3, 0x18C3, // 0x09F0 (2544) +0x18C3, 0x18C3, 0x10A2, 0x0841, 0x630C, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A00 (2560) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0861, 0x18E4, 0x18E4, // 0x0A10 (2576) +0x1082, 0xC638, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, // 0x0A20 (2592) +0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xD6BA, 0xE71C, 0x6B4D, 0x10A2, 0x18C3, 0x18C3, 0x10A2, // 0x0A30 (2608) +0x10A2, 0x10A2, 0x18C3, 0x0861, 0x5AEB, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A40 (2624) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8410, 0x0862, 0x3143, 0x2924, // 0x0A50 (2640) +0x0882, 0xBDD7, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0A60 (2656) +0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xE73C, 0x630C, 0x2103, 0x4A69, 0x632C, 0x6B4D, // 0x0A70 (2672) +0x528A, 0x2965, 0x18C3, 0x1081, 0x738E, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A80 (2688) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x7A40, 0xECA0, 0xCC00, // 0x0A90 (2704) +0x3941, 0xA535, 0xFFFF, 0xF7BE, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, // 0x0AA0 (2720) +0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEFB, 0xD6DB, 0xCE38, 0xC618, 0x4A48, 0x4A49, 0x6B6D, 0x6B4D, 0x6B4D, // 0x0AB0 (2736) +0x6B4D, 0x630C, 0x3186, 0x18E4, 0x9492, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0AC0 (2752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xC488, 0xFD41, 0xFE6D, 0xFE6A, // 0x0AD0 (2768) +0xDC60, 0x5A25, 0xB5D8, 0xFFFF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, // 0x0AE0 (2784) +0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xD6BB, 0xBCAB, 0xD462, 0xD462, 0x49E4, 0x10C3, 0x18C3, 0x18C3, 0x18C3, // 0x0AF0 (2800) +0x18C3, 0x18E3, 0x10A3, 0x49C4, 0xB575, 0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B00 (2816) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCD70, 0xECA0, 0xFF14, 0xFF9B, 0xFF7B, // 0x0B10 (2832) +0xFECF, 0xC3A0, 0x3143, 0x9CF3, 0xFFFF, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, // 0x0B20 (2848) +0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEFB, 0xC617, 0xDC60, 0xFD60, 0xFD20, 0x3120, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B30 (2864) +0x0000, 0x0000, 0x3900, 0xE460, 0xB46A, 0xEF9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B40 (2880) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD5F4, 0xDC20, 0xFE8E, 0xFF59, 0xFF36, 0xFF36, // 0x0B50 (2896) +0xFF59, 0xFE6B, 0xA300, 0x18E4, 0x8410, 0xFFBE, 0xF7BE, 0xEF7D, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, // 0x0B60 (2912) +0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEBA, 0xDEFB, 0xC5B5, 0xE4A1, 0xFEF2, 0xF716, 0x3164, 0x18E4, 0x2103, 0x1082, 0x1082, // 0x0B70 (2928) +0x0021, 0x1061, 0xD5D0, 0xFE27, 0xB3E3, 0xCE9B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B80 (2944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77D, 0xE697, 0xDDAF, 0xD4C8, 0xE480, 0xFE29, 0xFF36, 0xFF15, 0xFF35, 0xFF15, // 0x0B90 (2960) +0xFF15, 0xFF36, 0xFDA5, 0x6A42, 0x1905, 0x6B4C, 0xE73C, 0xFFDF, 0xEF5D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, // 0x0BA0 (2976) +0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xDEDB, 0xBDB5, 0xE4C3, 0xFF56, 0xFFDB, 0xAD10, 0x10A2, 0x10C3, 0x18E4, 0x1082, // 0x0BB0 (2992) +0x2922, 0xC5B1, 0xFFDC, 0xFED1, 0xB3A2, 0xBE19, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0BC0 (3008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE6B8, 0xD484, 0xE4C0, 0xF584, 0xFE28, 0xFECF, 0xFF14, 0xFF13, 0xFF13, 0xFF13, 0xFF13, // 0x0BD0 (3024) +0xFF13, 0xFF14, 0xFEF0, 0xDC80, 0x41C5, 0x2945, 0x5269, 0xCE59, 0xF7BE, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, // 0x0BE0 (3040) +0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD69A, 0xD6DB, 0xBD95, 0xE4E2, 0xFF33, 0xFF36, 0xFF97, 0xDDF1, 0x8B66, 0x7AE4, 0x9BC7, // 0x0BF0 (3056) +0xEEB2, 0xFF97, 0xFF37, 0xFEF0, 0xC3E0, 0xB5B7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C00 (3072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD52B, 0xFD60, 0xFECD, 0xFF33, 0xFF13, 0xFF12, 0xFEF1, 0xFEF1, 0xFEF1, 0xFEF1, 0xFEF1, // 0x0C10 (3088) +0xFEF1, 0xFEF1, 0xFF12, 0xFE69, 0x9B41, 0x31A8, 0x31A6, 0x39E7, 0xB5B6, 0xF79E, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, // 0x0C20 (3104) +0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD699, 0xD6BA, 0xBD94, 0xE502, 0xFF12, 0xFF15, 0xFEF4, 0xFF55, 0xFF95, 0xFF54, 0xFF95, // 0x0C30 (3120) +0xFF35, 0xFEF4, 0xFF14, 0xFF14, 0xF5A4, 0xB426, 0xE75E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C40 (3136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD54C, 0xFDA0, 0xFECE, 0xFEF0, 0xFECF, 0xFEEF, 0xFEEF, 0xFEF0, 0xFEEF, 0xFEF0, 0xFEF0, // 0x0C50 (3152) +0xFEF0, 0xFEEF, 0xFEF0, 0xFEEF, 0xF582, 0x6244, 0x39E8, 0x39C6, 0x528A, 0xE71C, 0xE73C, 0xE71C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, // 0x0C60 (3168) +0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE9A, 0xBD94, 0xE522, 0xFF10, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, // 0x0C70 (3184) +0xFEF2, 0xFF12, 0xFEF2, 0xFEF2, 0xFF12, 0xED85, 0xBC68, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C80 (3200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD5B0, 0xF580, 0xFECB, 0xFEEE, 0xFECD, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, // 0x0C90 (3216) +0xFEEE, 0xFEEE, 0xFECD, 0xFECE, 0xFECA, 0xCC60, 0x41C7, 0x39C7, 0x4228, 0xCE79, 0xEF5D, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, // 0x0CA0 (3232) +0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE59, 0xCE9A, 0xBD73, 0xED42, 0xFF0F, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, // 0x0CB0 (3248) +0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFF31, 0xF628, 0xC4A7, 0xDE57, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0CC0 (3264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDE13, 0xF560, 0xFEC9, 0xFECD, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, // 0x0CD0 (3280) +0xFEEC, 0xFEEC, 0xFECC, 0xFECC, 0xFEED, 0xFE44, 0x9323, 0x52CC, 0x73AE, 0xD69A, 0xE73C, 0xDEFB, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, // 0x0CE0 (3296) +0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE59, 0xD69A, 0xB5D8, 0x7B28, 0xF5A2, 0xFF0F, 0xFECE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, // 0x0CF0 (3312) +0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFECD, 0xFF10, 0xFEA9, 0xCC60, 0xD615, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D00 (3328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDE55, 0xED80, 0xFEA4, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFEC9, // 0x0D10 (3344) +0xFEA7, 0xFEA6, 0xFEA8, 0xFEC9, 0xFECB, 0xFEEA, 0xEDA2, 0xB4F0, 0xCE9A, 0xDEFB, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, // 0x0D20 (3360) +0xD6BA, 0xD69A, 0xCE79, 0xCE79, 0xD6BA, 0xB596, 0x4A8B, 0x72A4, 0xFE45, 0xFEEC, 0xFECC, 0xFEEC, 0xFEEC, 0xFEEC, 0xFEEC, 0xFEEC, // 0x0D30 (3376) +0xFEEC, 0xFECB, 0xFECB, 0xFEEC, 0xFEEC, 0xFEEC, 0xFECC, 0xFEA5, 0xFDE0, 0xAC8B, 0xE75E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D40 (3392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE632, 0xF5E0, 0xFE80, 0xFE82, 0xFEC7, 0xFEC8, 0xFEC8, 0xFEC8, 0xFEC7, 0xFEA4, 0xFE61, // 0x0D50 (3408) +0xFE60, 0xFE60, 0xFE60, 0xFE61, 0xFE83, 0xFEA6, 0xFEA3, 0xDD22, 0xD658, 0xE75D, 0xDEDB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, // 0x0D60 (3424) +0xD69A, 0xD69A, 0xD6BA, 0xCE59, 0x9492, 0x5289, 0x39E9, 0x9B84, 0xFEA3, 0xFEEB, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEC8, // 0x0D70 (3440) +0xFE84, 0xFE61, 0xFE61, 0xFEA5, 0xFEC9, 0xFEA7, 0xFEA2, 0xFE80, 0xBC41, 0x8C0F, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D80 (3456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDDCE, 0xFE40, 0xFEA0, 0xFE80, 0xFE80, 0xFEA2, 0xFEA2, 0xFEA2, 0xFEA0, 0xFE80, 0xFE80, // 0x0D90 (3472) +0xFEA0, 0xFEA0, 0xFEA0, 0xFE80, 0xFE80, 0xFE80, 0xFE80, 0xFE80, 0xCCE5, 0xD69A, 0xE73C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, // 0x0DA0 (3488) +0xD69A, 0xBDF7, 0x9CD3, 0x630C, 0x4228, 0x4A69, 0x422A, 0xB423, 0xFEC0, 0xFEA5, 0xFEE7, 0xFEC7, 0xFEC7, 0xFEC6, 0xFEA3, 0xFE80, // 0x0DB0 (3504) +0xFE80, 0xFE80, 0xFE80, 0xFE60, 0xFEA0, 0xFEC0, 0xEDC0, 0xA3A4, 0x732C, 0xAD96, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0DC0 (3520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE5A8, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0DD0 (3536) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xF640, 0x93A8, 0x8C72, 0xA534, 0xAD75, 0xA534, 0x9CF3, 0x8C51, // 0x0DE0 (3552) +0x738E, 0x5ACB, 0x4A49, 0x4A69, 0x528A, 0x4A8A, 0x5249, 0xD502, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC1, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, // 0x0DF0 (3568) +0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFE60, 0xC482, 0x7B09, 0x7BD0, 0xB5B7, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E00 (3584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDD8A, 0xFEC0, 0xFF20, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, // 0x0E10 (3600) +0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEC0, 0xFF20, 0xAC02, 0x4209, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, // 0x0E20 (3616) +0x528A, 0x528A, 0x52AA, 0x52AA, 0x528A, 0x4A8A, 0x5A69, 0xE5C1, 0xFF00, 0xFEC0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, // 0x0E30 (3632) +0xFEC0, 0xFEE0, 0xFF00, 0xE561, 0x9367, 0x736E, 0x9D14, 0xD6BA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E40 (3648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD617, 0xCCC5, 0xF620, 0xFEE0, 0xFF40, 0xFF40, 0xFF40, 0xFF20, 0xFF00, 0xFF00, 0xFF00, // 0x0E50 (3664) +0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF40, 0xB483, 0x4A8B, 0x5ACA, 0x5ACB, 0x5ACB, 0x5ACB, 0x5ACB, // 0x0E60 (3680) +0x5ACB, 0x52AA, 0x52AA, 0x52AA, 0x52AA, 0x4A8A, 0x6289, 0xEE20, 0xFF20, 0xFEE0, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFEE0, // 0x0E70 (3696) +0xFF20, 0xFEC0, 0xBC64, 0x732B, 0x8C72, 0xCE58, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E80 (3712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7E, 0xB576, 0x93EE, 0xA408, 0xC4A5, 0xDD63, 0xF641, 0xFEC0, 0xFF40, 0xFF80, 0xFF60, // 0x0E90 (3728) +0xFF40, 0xFF20, 0xFF20, 0xFF40, 0xFF40, 0xFF40, 0xFF20, 0xFF20, 0xFF80, 0xAC03, 0x4A6B, 0x5ACA, 0x5ACB, 0x5ACB, 0x5AEB, 0x5AEB, // 0x0EA0 (3744) +0x5AEB, 0x630C, 0x630C, 0x630C, 0x5AEB, 0x52CB, 0x5A69, 0xE5E1, 0xFF60, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF60, // 0x0EB0 (3760) +0xF640, 0xA3A7, 0x738F, 0xAD96, 0xE71C, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0EC0 (3776) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0xD6DB, 0xB5B8, 0x9CD4, 0x9431, 0x93EE, 0x9C0A, 0xB467, 0xD544, 0xF660, // 0x0ED0 (3792) +0xFF60, 0xFFA0, 0xFF80, 0xFF60, 0xFF40, 0xFF40, 0xFF60, 0xFFA0, 0xD521, 0x730A, 0x73CF, 0x8C71, 0x9CD3, 0x9CF3, 0xA514, 0xA534, // 0x0EE0 (3808) +0xAD55, 0xB596, 0xB5B6, 0xB596, 0xAD55, 0x9CF3, 0x83F0, 0xCD04, 0xFFA0, 0xFF40, 0xFF40, 0xFF40, 0xFF40, 0xFF40, 0xFFA0, 0xF621, // 0x0EF0 (3824) +0x8B49, 0x8431, 0xCE58, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F00 (3840) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xF79E, 0xE73C, 0xD6BB, 0xBE19, 0xA556, 0x9472, 0x9C0D, // 0x0F10 (3856) +0xB447, 0xDD82, 0xFEE0, 0xFFA0, 0xFFC0, 0xFFC0, 0xFF80, 0xC4C2, 0x730C, 0x9CF4, 0xD69A, 0xEF5D, 0xEF7D, 0xF79E, 0xF79E, 0xF7BE, // 0x0F20 (3872) +0xF7BE, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xEF7D, 0xDF1C, 0xC530, 0xF620, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFF80, 0xE5A2, 0x834A, // 0x0F30 (3888) +0x8C93, 0xDEDA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F40 (3904) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDE, 0xEF7D, 0xD6BB, // 0x0F50 (3920) +0xAD77, 0x9452, 0x9BEB, 0xB466, 0xC524, 0xC543, 0xA3E5, 0x734D, 0xAD76, 0xEF5C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F60 (3936) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF1C, 0xACB0, 0xBCA6, 0xD544, 0xCD64, 0xCD05, 0xAC07, 0x7B6D, 0x9CF4, // 0x0F70 (3952) +0xE6FB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F80 (3968) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F90 (3984) +0xFFDE, 0xE75D, 0xC65A, 0xA536, 0x9493, 0x8C53, 0x94B4, 0xBE18, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FA0 (4000) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xDEFC, 0xAD57, 0x9493, 0x8C73, 0x8C73, 0x94D4, 0xBE18, 0xEF5D, // 0x0FB0 (4016) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FC0 (4032) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FD0 (4048) +0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xEF5C, 0xE73C, 0xEF5C, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FE0 (4064) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xEF5C, 0xE73C, 0xEF5C, 0xEF7D, 0xFFDE, 0xFFFF, // 0x0FF0 (4080) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x1000 (4096) +}; diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino new file mode 100644 index 0000000..b3967a8 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_CPLD_PageSwitching/UTFT_CPLD_PageSwitching.ino @@ -0,0 +1,93 @@ +// UTFT_CPLD_PageSwitching (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of page switching on CPLD-based display modules.. +// +// This demo was made for modules with a screen resolution +// of 800x480 pixels. +// +// This program requires the UTFT library. +// +// NOTE: The display will be black for 10-15 seconds during the start +// + +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(CPLD,38,39,40,41); + +void setup() +{ + myGLCD.InitLCD(); +} + +void loop() +{ + myGLCD.setBackColor(VGA_TRANSPARENT); + + myGLCD.setBrightness(0); + for (byte pg=0; pg<8; pg++) + { + myGLCD.setWritePage(pg); + myGLCD.clrScr(); + for (int ln=0; ln<480; ln+=2) + { + switch (pg) + { + case 0: + myGLCD.setColor(ln/2, 0, 0); + break; + case 1: + myGLCD.setColor(0, ln/2, 0); + break; + case 2: + myGLCD.setColor(0, 0, ln/2); + break; + case 3: + myGLCD.setColor(ln/4, ln/2, 0); + break; + case 4: + myGLCD.setColor(0, ln/2, ln/2); + break; + case 5: + myGLCD.setColor(ln/2, 0, ln/2); + break; + case 6: + myGLCD.setColor(ln/2, ln/2, 0); + break; + case 7: + myGLCD.setColor(0, ln/2, ln/4); + break; + } + myGLCD.drawLine(0, ln, 799, ln); + myGLCD.drawLine(0, ln+1, 799, ln+1); + } + myGLCD.setColor(VGA_WHITE); + myGLCD.setFont(BigFont); + myGLCD.print("This is page:", CENTER, 200); + myGLCD.setFont(SevenSegNumFont); + myGLCD.printNumI(pg, CENTER, 240); + } + myGLCD.setBrightness(16); + + while(1) + { + for (byte pg=0; pg<8; pg++) + { + myGLCD.setDisplayPage(pg); + delay(500); + } + } +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino new file mode 100644 index 0000000..45a97e6 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.ino @@ -0,0 +1,335 @@ +// UTFT_Demo_128x128_Serial (C)2012 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made to work on the 128x128 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Declare an instance of the class +UTFT myGLCD(LPH9135,6,5,2,3,4); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(PORTRAIT); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + byte buf[126]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + myGLCD.setContrast(64); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0,0,127,12); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0,117,127,127); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255,0,0); + myGLCD.print("Universal TFT", CENTER, 0); + myGLCD.setBackColor(64,64,64); + myGLCD.setColor(255,255,0); + myGLCD.print("H.Karlsen", LEFT, 116); + myGLCD.print("(C)2012", RIGHT, 116); + myGLCD.setColor(0,255,0); + myGLCD.drawRect(0,13,127,116); + +// Draw crosshairs + myGLCD.setColor(0,0,255); + myGLCD.drawLine(63,14,63,115); + myGLCD.drawLine(1,63,126,63); + for (int i=3; i<128; i+=10) + myGLCD.drawLine(i, 61, i, 65); + for (int i=14; i<118; i+=10) + myGLCD.drawLine(61, i, 65, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.setBackColor(0,0,0); + myGLCD.print("Sin", 2, 14); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(sin(((i*2.85)*3.14)/180)*45)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 2, 26); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(cos(((i*2.85)*3.14)/180)*45)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 2, 38); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(tan(((i*2.85)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + myGLCD.setColor(0,0,255); + myGLCD.drawLine(63,14,63,115); + myGLCD.drawLine(1,63,126,63); + +// Draw a moving sinewave + x=1; + for (int i=1; i<3654; i++) + { + x++; + if (x==127) + x=1; + if (i>127) + { + if ((x==63)||(buf[x-1]==63)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=63+(sin(((i*1.3)*3.14)/180)*45); + myGLCD.drawPixel(x,y); + buf[x-1]=y; +// delay(3); + } + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(10+(i*10),10+(i*10), 60+(i*10), 60+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(70-(i*10),10+(i*10), 120-(i*10), 60+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(30+(i*10),35+(i*10), 25); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + + // Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=11; i<115; i+=3) + { + myGLCD.drawLine(1, i, i-10, 115); + } + myGLCD.setColor (255,0,0); + for (int i=112; i>14; i-=3) + { + myGLCD.drawLine(126, i, i+14, 14); + } + myGLCD.setColor (0,255,255); + for (int i=115; i>14; i-=3) + { + myGLCD.drawLine(1, i, 116-i, 14); + } + myGLCD.setColor (0,255,255); + for (int i=14; i<115; i+=3) + { + myGLCD.drawLine(126, i, 140-i, 115); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(85); + y=35+random(59); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random lines + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random pixels + for (int i=0; i<5000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(124), 15+random(101)); + } + + delay (2000); + +// Set up the "Finished"-screen + myGLCD.setContrast(0); + myGLCD.fillScr(0,0,255); + myGLCD.setColor(255,0,0); + myGLCD.fillRoundRect(2, 40, 125, 88); + + myGLCD.setColor(255,255,255); + myGLCD.setBackColor(255,0,0); + myGLCD.print("That's it!", CENTER, 46); + myGLCD.print("Restarting in a", CENTER, 66); + myGLCD.print("few seconds...", CENTER, 76); + + myGLCD.setColor(0,0,0); + myGLCD.setBackColor(0,0,255); + myGLCD.print("Runtime: (msecs)", CENTER, 108); + myGLCD.printNumI(millis(), CENTER, 118); + + myGLCD.setContrast(64); + + delay (10000); + +// Fade screen to black + for (int i=64; i>0; i--) + { + myGLCD.setContrast(i); + delay(100); + } +} + + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino new file mode 100644 index 0000000..365b716 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.ino @@ -0,0 +1,328 @@ +// UTFT_Demo_160x128_Serial (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 160x128 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Usage: myGLCD(, SDA, SCL, CS, RST[, RS]); +// +// When using the DM-TFT18-101 and shield from DisplayModule you should use the following: +// UTFT myGLCD(DMTFT18101,2,3,4,6,5); +// +UTFT myGLCD(ITDB18SP,11,10,9,12,8); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[158]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 159, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 114, 159, 127); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("Universal TFT Lib.", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("H.Karlsen", LEFT, 114); + myGLCD.print("(C)2014", RIGHT, 114); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 13, 159, 113); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(79, 14, 79, 113); + myGLCD.drawLine(1, 63, 158, 63); + + for (int i=9; i<150; i+=10) + myGLCD.drawLine(i, 61, i, 65); + for (int i=19; i<110; i+=10) + myGLCD.drawLine(77, i, 81, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(sin(((i*2.27)*3.14)/180)*40)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(cos(((i*2.27)*3.14)/180)*40)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(tan(((i*2.27)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(79, 14, 79, 113); + myGLCD.drawLine(1, 63, 158, 63); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(158*20); i++) + { + x++; + if (x==159) + x=1; + if (i>159) + { + if ((x==79)||(buf[x-1]==63)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=63+(sin(((i*2.5)*3.14)/180)*(40-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(39+(i*10), 23+(i*10), 59+(i*10), 43+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(99-(i*10), 23+(i*10), 119-(i*10), 43+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(49+(i*10),33+(i*10), 15); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=14; i<113; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 112); + } + myGLCD.setColor (255,0,0); + for (int i=112; i>15; i-=5) + { + myGLCD.drawLine(158, i, (i*1.44)-12, 14); + } + myGLCD.setColor (0,255,255); + for (int i=112; i>15; i-=5) + { + myGLCD.drawLine(1, i, 172-(i*1.44), 14); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<112; i+=5) + { + myGLCD.drawLine(158, i, 171-(i*1.44), 112); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(116); + y=35+random(57); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + + for (int i=0; i<5000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(156), 16+random(95)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(10, 17, 149, 72); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 20); + myGLCD.print("Restarting in a", CENTER, 45); + myGLCD.print("few seconds...", CENTER, 57); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 103); + myGLCD.printNumI(millis(), CENTER, 115); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176/UTFT_Demo_220x176.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176/UTFT_Demo_220x176.ino new file mode 100644 index 0000000..50e9c32 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176/UTFT_Demo_220x176.ino @@ -0,0 +1,335 @@ +// UTFT_Demo_220x176 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 220x176 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB22,A5,A4,A3,A2); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[218]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 219, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 162, 219, 175); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("** Universal TFT Library **", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("> elec.henningkarlsen.com <", CENTER, 163); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 219, 161); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + + for (int i=9; i<210; i+=10) + myGLCD.drawLine(i, 86, i, 90); + for (int i=19; i<155; i+=10) + myGLCD.drawLine(107, i, 111, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(sin(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(cos(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(tan(((i*1.65)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(218*20); i++) + { + x++; + if (x==219) + x=1; + if (i>219) + { + if ((x==109)||(buf[x-1]==88)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=88+(sin(((i*1.6)*3.14)/180)*(65-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(44+(i*15), 23+(i*15), 88+(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(132-(i*15), 23+(i*15), 172-(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(64+(i*15),43+(i*15), 20); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 160); + } + myGLCD.setColor (255,0,0); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(218, i, (i*1.44)-12, 15); + } + myGLCD.setColor (0,255,255); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(1, i, 232-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(218, i, 231-(i*1.44), 160); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(176); + y=35+random(105); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(216), 16+random(143)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(40, 57, 179, 119); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 62); + myGLCD.print("Restarting in a", CENTER, 88); + myGLCD.print("few seconds...", CENTER, 101); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 146); + myGLCD.printNumI(millis(), CENTER, 161); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino new file mode 100644 index 0000000..ec66344 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.ino @@ -0,0 +1,322 @@ +// UTFT_Demo_220x176_Serial (C)2012 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for serial modules with a screen resolution +// of 220x176 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +UTFT myGLCD(ITDB22SP,11,10,9,12); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[218]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 219, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 162, 219, 175); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("** Universal TFT Library **", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("> elec.henningkarlsen.com <", CENTER, 163); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 219, 161); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + + for (int i=9; i<210; i+=10) + myGLCD.drawLine(i, 86, i, 90); + for (int i=19; i<155; i+=10) + myGLCD.drawLine(107, i, 111, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(sin(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(cos(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(tan(((i*1.65)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(218*20); i++) + { + x++; + if (x==219) + x=1; + if (i>219) + { + if ((x==109)||(buf[x-1]==88)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=88+(sin(((i*1.6)*3.14)/180)*(65-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(44+(i*15), 23+(i*15), 88+(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(132-(i*15), 23+(i*15), 172-(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(64+(i*15),43+(i*15), 20); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 160); + } + myGLCD.setColor (255,0,0); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(218, i, (i*1.44)-12, 15); + } + myGLCD.setColor (0,255,255); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(1, i, 232-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(218, i, 231-(i*1.44), 160); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,161); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(176); + y=35+random(105); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(216), 16+random(143)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(40, 57, 179, 119); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 62); + myGLCD.print("Restarting in a", CENTER, 88); + myGLCD.print("few seconds...", CENTER, 101); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 146); + myGLCD.printNumI(millis(), CENTER, 161); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240/UTFT_Demo_320x240.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240/UTFT_Demo_320x240.ino new file mode 100644 index 0000000..1e51058 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240/UTFT_Demo_320x240.ino @@ -0,0 +1,334 @@ +// UTFT_Demo_320x240 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[318]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 319, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 319, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 319, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + for (int i=9; i<310; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(157, i, 161, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(318*20); i++) + { + x++; + if (x==319) + x=1; + if (i>319) + { + if ((x==159)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(70+(i*20), 30+(i*20), 130+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(190-(i*20), 30+(i*20), 250-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(100+(i*20),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(318, i, (i*1.44)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 331-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(318, i, 330-(i*1.44), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(256); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(209); + x2=2+random(316); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(316), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(80, 70, 239, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino new file mode 100644 index 0000000..a741524 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.ino @@ -0,0 +1,354 @@ +// UTFT_Demo_320x240_Serial (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for serial modules with a screen +// resolution of 320x240 pixels. +// +// This program requires the UTFT library. +// +// ******************************************************************** +// * IMPORTANT: Read the comments in the setup() function when * +// * using the Watterott MI0283QT9 or the DisplayModule DM-TFT28-105. * +// ******************************************************************** +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Uncomment the line for your display: +//UTFT myGLCD(TFT01_22SP,9,8,12,11,10); // ElecFreaks TFT01-2.2SP +//UTFT myGLCD(MI0283QT9,11,13,7,8); // Watterott MI0283QT9 +UTFT myGLCD(DMTFT28105,MOSI,SCK,10,NOTINUSE,9); // DisplayModule DM-TFT28-105 (Works with both Arduino Uno and Arduino Mega) + +void setup() +{ +// Watterott +// --------- +// The following two lines are needed for the MI0283QT9 display +// module to enable the backlight. If you are using any other +// display module these lines should be commented out. +// ------------------------------------------------------------- +// pinMode(9, OUTPUT); +// digitalWrite(9, HIGH); +// ------------------------------------------------------------- + +// DisplayModule +// ------------- +// The following 4 lines are needed for the DM-TFT28-105 display +// module to set the SS/CS pins for the other devices connected +// to the Arduino SPI pins. If you are using any other display +// module these lines should be commented out. +// ------------------------------------------------------------- + pinMode(10,OUTPUT); digitalWrite(10,HIGH); // TFT SS/CE + pinMode(8, OUTPUT); digitalWrite(8, HIGH); // SD card SS/CE + pinMode(6, OUTPUT); digitalWrite(6, HIGH); // Flash chip SS/CE + pinMode(4, OUTPUT); digitalWrite(4, HIGH); // Touch controller SS/CE +// ------------------------------------------------------------- + + +// Just get some random numbers + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); + +} + +void loop() +{ + int buf[318]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 319, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 319, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 319, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + for (int i=9; i<310; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(157, i, 161, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(318*20); i++) + { + x++; + if (x==319) + x=1; + if (i>319) + { + if ((x==159)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(70+(i*20), 30+(i*20), 130+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(190-(i*20), 30+(i*20), 250-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(100+(i*20),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(318, i, (i*1.44)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 331-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(318, i, 330-(i*1.44), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(256); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(209); + x2=2+random(316); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(316), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(80, 70, 239, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} \ No newline at end of file diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_400x240/UTFT_Demo_400x240.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_400x240/UTFT_Demo_400x240.ino new file mode 100644 index 0000000..93538ce --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_400x240/UTFT_Demo_400x240.ino @@ -0,0 +1,336 @@ +// UTFT_Demo_400x240 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 400x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32WD,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[398]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 399, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 399, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("*** Universal Color TFT Display Library ***", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("< http://electronics.henningkarlsen.com >", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 399, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(199, 15, 199, 224); + myGLCD.drawLine(1, 119, 398, 119); + for (int i=9; i<390; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(197, i, 201, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<398; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*0.9)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<398; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*0.9)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<398; i++) + { + y=119+(tan(((i*0.9)*3.14)/180)); + if ((y>15) && (y<224)) + myGLCD.drawPixel(i,y); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(199, 15, 199, 224); + myGLCD.drawLine(1, 119, 398, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(398*20); i++) + { + x++; + if (x==399) + x=1; + if (i>399) + { + if ((x==199)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(110+(i*20), 30+(i*20), 170+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(230-(i*20), 30+(i*20), 290-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(110+(i*30),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.77)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(398, i, (i*1.77)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 411-(i*1.77), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(398, i, 410-(i*1.77), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(336); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(207); + x2=2+random(396); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(207); + x2=2+random(396); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(209); + x2=2+random(396); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(396), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(120, 70, 279, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x272/UTFT_Demo_480x272.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x272/UTFT_Demo_480x272.ino new file mode 100644 index 0000000..93d8395 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x272/UTFT_Demo_480x272.ino @@ -0,0 +1,333 @@ +// UTFT_Demo_480x272 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 480x272 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB43,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[478]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 479, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 258, 479, 271); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 259); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 479, 257); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 256); + myGLCD.drawLine(1, 135, 478, 135); + for (int i=9; i<470; i+=10) + myGLCD.drawLine(i, 133, i, 138); + for (int i=15; i<256; i+=10) + myGLCD.drawLine(237, i, 241, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 256); + myGLCD.drawLine(1, 135, 478, 135); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(478*20); i++) + { + x++; + if (x==479) + x=1; + if (i>479) + { + if ((x==239)||(buf[x-1]==135)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=135+(sin(((i*1.65)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(150+(i*20), 46+(i*20), 210+(i*20), 106+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(330-(i*20), 46+(i*20), 270-(i*20), 106+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(180+(i*20),75+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<256; i+=5) + { + myGLCD.drawLine(1, i, (i*1.88)-10, 256); + } + myGLCD.setColor (255,0,0); + for (int i=256; i>15; i-=5) + { + myGLCD.drawLine(478, i, (i*1.88)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=256; i>15; i-=5) + { + myGLCD.drawLine(1, i, 491-(i*1.88), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<256; i+=5) + { + myGLCD.drawLine(478, i, 490-(i*1.88), 256); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some random circles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(416); + y=45+random(178); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some random rectangles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + +// Draw some random rounded rectangles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,256); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(476), 16+random(239)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(160, 70, 319, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 243); + myGLCD.printNumI(millis(), CENTER, 258); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x320/UTFT_Demo_480x320.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x320/UTFT_Demo_480x320.ino new file mode 100644 index 0000000..da718c3 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_480x320/UTFT_Demo_480x320.ino @@ -0,0 +1,334 @@ +// UTFT_Demo_480x320 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 480x320 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(CTE32HR,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[478]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 479, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 306, 479, 319); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 307); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 479, 305); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 304); + myGLCD.drawLine(1, 159, 478, 159); + for (int i=9; i<470; i+=10) + myGLCD.drawLine(i, 157, i, 161); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(237, i, 241, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 304); + myGLCD.drawLine(1, 159, 478, 159); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(478*15); i++) + { + x++; + if (x==479) + x=1; + if (i>479) + { + if ((x==239)||(buf[x-1]==159)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=159+(sin(((i*0.7)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(150+(i*20), 70+(i*20), 210+(i*20), 130+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(270-(i*20), 70+(i*20), 330-(i*20), 130+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(180+(i*20),100+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<304; i+=5) + { + myGLCD.drawLine(1, i, (i*1.6)-10, 304); + } + myGLCD.setColor (255,0,0); + for (int i=304; i>15; i-=5) + { + myGLCD.drawLine(478, i, (i*1.6)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=304; i>15; i-=5) + { + myGLCD.drawLine(1, i, 491-(i*1.6), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<304; i+=5) + { + myGLCD.drawLine(478, i, 490-(i*1.6), 304); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(416); + y=45+random(226); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(476), 16+random(289)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(160, 70, 319, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 290); + myGLCD.printNumI(millis(), CENTER, 305); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_800x480/UTFT_Demo_800x480.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_800x480/UTFT_Demo_800x480.ino new file mode 100644 index 0000000..363b71a --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Demo_800x480/UTFT_Demo_800x480.ino @@ -0,0 +1,293 @@ +// UTFT_Demo_800x480 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 800x480 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB50,38,39,40,41); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[798]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 799, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 466, 799, 479); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 467); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 799, 465); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(399, 15, 399, 464); + myGLCD.drawLine(1, 239, 798, 239); + for (int i=9; i<790; i+=10) + myGLCD.drawLine(i, 237, i, 242); + for (int i=19; i<470; i+=10) + myGLCD.drawLine(397, i, 402, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(sin(((i*1.13)*3.14)/180)*200)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(cos(((i*1.13)*3.14)/180)*200)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(tan(((i*0.9)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(399, 15, 399, 464); + myGLCD.drawLine(1, 239, 798, 239); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(798*20); i++) + { + x++; + if (x==799) + x=1; + if (i>799) + { + if ((x==399)||(buf[x-1]==239)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=239+(sin(((i*1.65)*3.14)/180)*(200-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled rectangles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(746); + y=16+random(397); + x2=x+50; + y2=y+50; + myGLCD.fillRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled, rounded rectangles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(746); + y=16+random(397); + x2=x+50; + y2=y+50; + myGLCD.fillRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled circles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=27+random(746); + y=41+random(397); + myGLCD.fillCircle(x, y, 25); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<463; i+=5) + { + myGLCD.drawLine(1, i, (i*1.66)-10, 463); + } + myGLCD.setColor (255,0,0); + for (int i=463; i>15; i-=5) + { + myGLCD.drawLine(798, i, (i*1.66)+30, 15); + } + myGLCD.setColor (0,255,255); + for (int i=463; i>15; i-=5) + { + myGLCD.drawLine(1, i, 770-(i*1.66), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<463; i+=5) + { + myGLCD.drawLine(798, i, 810-(i*1.66), 463); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random circles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(736); + y=45+random(386); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random rectangles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random rounded rectangles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(796), 16+random(447)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(320, 190, 479, 289); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 213); + myGLCD.print("Restarting in a", CENTER, 239); + myGLCD.print("few seconds...", CENTER, 252); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 450); + myGLCD.printNumI(millis(), CENTER, 465); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Leonardo_Demo_320x240/UTFT_Leonardo_Demo_320x240.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Leonardo_Demo_320x240/UTFT_Leonardo_Demo_320x240.ino new file mode 100644 index 0000000..4e8a9d1 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Leonardo_Demo_320x240/UTFT_Leonardo_Demo_320x240.ino @@ -0,0 +1,252 @@ +// UTFT_Leonardo_Demo_320x240 (C)2013 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a reduced demo of how to use some of the functions +// of the library with a supported display modules on an Arduino Leonardo. +// +// It has been reduced in size to fit in the limited flash memory of +// the Leonardo. It has not been tested on all display modules so +// some modules may still produce too large binares. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +UTFT myGLCD(ITDB24E_8,A5,A4,A3,A2); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[318]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 319, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 319, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 319, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + for (int i=9; i<310; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(157, i, 161, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(318*20); i++) + { + x++; + if (x==319) + x=1; + if (i>319) + { + if ((x==159)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(70+(i*20), 30+(i*20), 130+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(190-(i*20), 30+(i*20), 250-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(100+(i*20),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(318, i, (i*1.44)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 331-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(318, i, 330-(i*1.44), 224); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(80, 70, 239, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino new file mode 100644 index 0000000..ccb55f6 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.ino @@ -0,0 +1,43 @@ +// UTFT_Rotate_Bitmap (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This program requires the UTFT library. +// + +#include +#include + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +extern unsigned int tux[0x400]; + +void setup() +{ + myGLCD.InitLCD(LANDSCAPE); + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(0, 0, 0); +} + +void loop() +{ + for (int i=0; i<360; i+=5) + { + myGLCD.drawBitmap (10, 10, 32, 32, tux, i, 16, 16); + } +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/tux.c b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/tux.c new file mode 100644 index 0000000..3babe53 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Rotate_Bitmap/tux.c @@ -0,0 +1,73 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: tux.png +// Time generated: 11.10.2010 22:51:32 +// Size : 2 048 Bytes + +#include + +const unsigned short tux[0x400] PROGMEM ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x9CD3, 0x9CF3, 0xA514, // 0x0010 (16) +0x9CF3, 0x8C51, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x5AEB, 0x7BEF, 0x9CD3, 0x94B2, // 0x0030 (48) +0x94B2, 0x94B2, 0x4228, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x9CF3, 0x18E3, 0x630C, 0x4A49, 0x4A69, // 0x0050 (80) +0x4A69, 0x528A, 0x4A49, 0x0000, 0xC638, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x0000, 0x0020, 0x10A2, 0x1082, // 0x0070 (112) +0x0841, 0x0841, 0x0841, 0x0000, 0x630C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x528A, 0x4228, 0x8410, 0x0000, 0x0861, // 0x0090 (144) +0xAD55, 0xBDD7, 0x10A2, 0x0000, 0x2945, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x5ACB, 0x8C71, 0xE75D, 0x2126, 0x528B, // 0x00B0 (176) +0xE75D, 0xDEDB, 0x7BCF, 0x0000, 0x18E3, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x4A4A, 0x6B2A, 0x8BE7, 0xA48A, // 0x00D0 (208) +0x6B09, 0x4A8A, 0x8431, 0x0000, 0x2104, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6E, 0x5204, 0xDE6A, 0xFFF7, 0xFFF8, // 0x00F0 (240) +0xD5AC, 0xBCAA, 0x5A66, 0x0000, 0x1082, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C10, 0xC540, 0xFFED, 0xFF2C, 0xFEEC, // 0x0110 (272) +0xFECC, 0xFE66, 0x8260, 0x0000, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B3, 0x9C25, 0xFF20, 0xFE40, 0xFDA0, // 0x0130 (304) +0xFCC0, 0xF524, 0x836A, 0x0000, 0x0000, 0x630C, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x630C, 0x94B4, 0xFF13, 0xFD83, 0xF523, // 0x0150 (336) +0xE5CF, 0xF79E, 0xE71D, 0x0861, 0x0000, 0x0861, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0841, 0xD69A, 0xFFFF, 0xFF7D, 0xF77D, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x4A69, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x10A2, 0x8410, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0000, 0x0000, 0x0000, 0x9492, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01A0 (416) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x52AA, 0x0020, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFDF, 0xFFDF, 0xF7BE, 0xFFDF, 0x3186, 0x0000, 0x0020, 0x0841, 0xCE79, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x0000, 0x52AA, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x01D0 (464) +0xFFDF, 0xF7BE, 0xF79E, 0xFFFF, 0x9CF3, 0x0000, 0x0841, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01E0 (480) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x5ACB, 0x0000, 0xBDF7, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFDF, // 0x01F0 (496) +0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0x3186, 0x0000, 0x0861, 0x0000, 0xAD55, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x0861, 0x4A49, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x0210 (528) +0xF7BE, 0xF79E, 0xEF7D, 0xEF5D, 0xFFDF, 0x8410, 0x0000, 0x1082, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0220 (544) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, // 0x0230 (560) +0xF79E, 0xEF7D, 0xEF7D, 0xE73C, 0xF79E, 0xAD55, 0x0861, 0x10A2, 0x0861, 0x0841, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x3185, 0x10A2, 0xE71C, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, // 0x0250 (592) +0xEF7D, 0xEF7D, 0xEF5D, 0xE73C, 0xEF5D, 0xBDF7, 0x18C3, 0x18C3, 0x18C3, 0x0000, 0x8C71, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0260 (608) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0x39E7, 0xF7BE, 0xFFFF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, 0xEF7D, // 0x0270 (624) +0xEF7D, 0xEF5D, 0xE73C, 0xE71C, 0xE71C, 0xC618, 0x18E3, 0x10A2, 0x10A2, 0x0020, 0x6B4D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C51, 0x38E0, 0x4A27, 0xFFFF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, // 0x0290 (656) +0xEF5D, 0xE73C, 0xE71C, 0xDEFB, 0xDF1D, 0xBDF8, 0x39C7, 0x5ACB, 0x528A, 0x10A3, 0x738F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDD6C, 0xFE2B, 0xBC45, 0xA513, 0xFFFF, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF5D, // 0x02B0 (688) +0xE73C, 0xE71C, 0xDEFB, 0xD6DC, 0xDD8E, 0xB3E4, 0x2124, 0x2965, 0x2945, 0x20C1, 0xB511, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77C, 0xE5CF, 0xF60B, 0xFF9B, 0xFF54, 0x8B02, 0x7BF0, 0xFFDF, 0xF79E, 0xEF5D, 0xEF5D, 0xE73C, // 0x02D0 (720) +0xE71C, 0xDEFB, 0xDEDB, 0xCE7A, 0xED89, 0xDDAD, 0x0842, 0x0000, 0x0000, 0xAC69, 0xDD6B, 0xEFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFFF, 0xFFBE, 0xE5CB, 0xEDC9, 0xFE4B, 0xFF14, 0xFEF3, 0xFF35, 0xFE8D, 0x51C1, 0x634E, 0xE73C, 0xEF5D, 0xE73C, 0xE71C, // 0x02F0 (752) +0xDEFB, 0xDEDB, 0xD6DB, 0xCE59, 0xE58B, 0xFF98, 0xBD4F, 0x8B88, 0xCD90, 0xFFB7, 0xCCE8, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xEF3B, 0xF583, 0xFF30, 0xFF11, 0xFECF, 0xFEEF, 0xFECF, 0xFF30, 0xDD46, 0x2903, 0x6B8E, 0xEF7D, 0xE71C, 0xDEFB, // 0x0310 (784) +0xDEDB, 0xD6BA, 0xD69A, 0xCE59, 0xE5AA, 0xFF11, 0xFF53, 0xFF73, 0xFF33, 0xFF12, 0xFE6C, 0xDDAD, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xF79E, 0xEDC5, 0xFECB, 0xFECC, 0xFECC, 0xFEEC, 0xFECB, 0xFECC, 0xFEEA, 0x9BE5, 0x8432, 0xE73C, 0xDEDB, 0xDEDB, // 0x0330 (816) +0xD6BA, 0xD69A, 0xDEDB, 0xA4F3, 0xD547, 0xFF2E, 0xFECD, 0xFECE, 0xFEEE, 0xFEEE, 0xFF10, 0xFEAB, 0xE5A8, 0xEF7D, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xF79E, 0xF603, 0xFEA2, 0xFEC7, 0xFEC7, 0xFEA4, 0xFE81, 0xFE61, 0xFEA4, 0xFE43, 0xDE33, 0xE75E, 0xE71C, 0xDEFB, // 0x0350 (848) +0xDEDB, 0xCE58, 0x8C72, 0x5247, 0xEDE4, 0xFF0A, 0xFECA, 0xFEC9, 0xFE84, 0xFE83, 0xFEE7, 0xFEA3, 0xB443, 0xD69B, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xF75B, 0xFE60, 0xFF00, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xE5C1, 0x9492, 0xA514, 0x9CD3, // 0x0370 (880) +0x8410, 0x630B, 0x4229, 0x6AE8, 0xFE80, 0xFEC1, 0xFEC1, 0xFEA0, 0xFEA0, 0xFEE0, 0xDD80, 0x9BE8, 0xB597, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xF79E, 0xD589, 0xE600, 0xFEA0, 0xFF00, 0xFF40, 0xFF40, 0xFF00, 0xFF00, 0xFF20, 0xFEC0, 0x5267, 0x4229, 0x4A48, // 0x0390 (912) +0x4A49, 0x5289, 0x424A, 0x7B46, 0xFF20, 0xFEE0, 0xFEE0, 0xFF20, 0xFEE0, 0xB4A5, 0x9C92, 0xDEFD, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xE71D, 0xBDB6, 0xB530, 0xBD0B, 0xCD65, 0xEE60, 0xFF40, 0xFFA0, 0xFF80, 0xBD03, 0x8410, 0xA514, 0xA534, // 0x03B0 (944) +0xAD75, 0xB596, 0xA555, 0x9C8F, 0xF6C0, 0xFFA0, 0xFFA0, 0xF6E0, 0xA449, 0xB5B8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7F, 0xD69C, 0xBD95, 0xBD4C, 0xCDC6, 0xB4E8, 0xAD35, 0xF7BF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xF7BF, 0xCDD0, 0xCDC6, 0xCDA7, 0xA48D, 0xCE7B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF1F, 0xB59A, 0xBDDA, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFDF, 0xFFDF, 0xFFFF, 0xEF7F, 0xB59A, 0xAD59, 0xDF1D, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino new file mode 100644 index 0000000..81ce558 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.ino @@ -0,0 +1,57 @@ +// UTFT_Textrotation_Demo (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the textrotation-functions. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(BigFont); +} + +void loop() +{ + myGLCD.print("Text rotation", 0, 0); + myGLCD.setColor(0, 0, 255); + myGLCD.print("0 degrees", 0, 16, 0); + myGLCD.print("90 degrees", 319, 0, 90); + myGLCD.print("180 degrees", 319, 239, 180); + myGLCD.print("270 degrees", 0, 239, 270); + + myGLCD.setFont(SevenSegNumFont); + myGLCD.setColor(0, 255, 0); + myGLCD.print("45", 90, 100, 45); + myGLCD.print("90", 200, 50, 90); + myGLCD.print("180", 300, 200, 180); + + while (true) {}; +} + diff --git a/libraries/UTFT/examples/Arduino (AVR)/UTFT_ViewFont/UTFT_ViewFont.ino b/libraries/UTFT/examples/Arduino (AVR)/UTFT_ViewFont/UTFT_ViewFont.ino new file mode 100644 index 0000000..4a16428 --- /dev/null +++ b/libraries/UTFT/examples/Arduino (AVR)/UTFT_ViewFont/UTFT_ViewFont.ino @@ -0,0 +1,64 @@ +// UTFT_ViewFont (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the included fonts. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// Arduino Uno / 2009: +// ------------------- +// Standard Arduino Uno/2009 shield : ,A5,A4,A3,A2 +// DisplayModule Arduino Uno TFT shield : ,A5,A4,A3,A2 +// +// Arduino Mega: +// ------------------- +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Mega : ,38,39,40,41 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +void setup() +{ + myGLCD.InitLCD(); + + myGLCD.clrScr(); +} + +void loop() +{ + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 0); + + myGLCD.setFont(BigFont); + myGLCD.print(" !\"#$%&'()*+,-./", CENTER, 0); + myGLCD.print("0123456789:;<=>?", CENTER, 16); + myGLCD.print("@ABCDEFGHIJKLMNO", CENTER, 32); + myGLCD.print("PQRSTUVWXYZ[\\]^_", CENTER, 48); + myGLCD.print("`abcdefghijklmno", CENTER, 64); + myGLCD.print("pqrstuvwxyz{|}~ ", CENTER, 80); + + myGLCD.setFont(SmallFont); + myGLCD.print(" !\"#$%&'()*+,-./0123456789:;<=>?", CENTER, 120); + myGLCD.print("@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", CENTER, 132); + myGLCD.print("`abcdefghijklmnopqrstuvwxyz{|}~ ", CENTER, 144); + + myGLCD.setFont(SevenSegNumFont); + myGLCD.print("0123456789", CENTER, 190); + + while(1) {}; +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap/UTFT_Bitmap.pde b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/UTFT_Bitmap.pde new file mode 100644 index 0000000..b28e8fc --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/UTFT_Bitmap.pde @@ -0,0 +1,65 @@ +// UTFT_Bitmap (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This demo was made to work on the 320x240 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,82,83,84,85); + +extern unsigned short info[0x400]; +extern unsigned short icon[0x400]; +extern unsigned short tux[0x400]; + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(255, 255, 255); + myGLCD.print(" *** A 10 by 7 grid of a 32x32 icon *** ", CENTER, 228); + for (int x=0; x<10; x++) + for (int y=0; y<7; y++) + myGLCD.drawBitmap (x*32, y*32, 32, 32, info); + + delay(5000); + + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(255, 255, 255); + myGLCD.print(" Two different icons in scale 1 to 4 ", CENTER, 228); + int x=0; + for (int s=0; s<4; s++) + { + x+=(s*32); + myGLCD.drawBitmap (x, 0, 32, 32, tux, s+1); + } + x=0; + for (int s=4; s>0; s--) + { + myGLCD.drawBitmap (x, 224-(s*32), 32, 32, icon, s); + x+=(s*32); + } + + delay(5000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap/icon.c b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/icon.c new file mode 100644 index 0000000..9cb97a1 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/icon.c @@ -0,0 +1,71 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: taskmgr.png +// Time generated: 11.10.2010 22:51:23 +// Size : 2 048 Bytes + +const unsigned short icon[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0xCE79, 0xBDD7, 0xAD75, // 0x0010 (16) +0xAD55, 0xAD75, 0xBDF7, 0xD6BA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC638, 0x9492, 0x8C51, 0x9492, 0xA514, 0xA534, // 0x0030 (48) +0xA534, 0xA534, 0x9CF3, 0x8C71, 0x8430, 0x9CD3, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0x8410, 0x9492, 0xB5B6, 0xC618, 0xBDD7, 0xAD75, 0xA514, // 0x0050 (80) +0xA514, 0xA4F4, 0xAD55, 0xB5B6, 0xBDD7, 0xAD55, 0x8430, 0x8C71, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x9CD3, 0x8430, 0xBDF7, 0xC618, 0xAD75, 0x94F2, 0x8CF1, 0x84B0, 0x8CD1, // 0x0070 (112) +0x9612, 0x8CB1, 0x7C6F, 0x7C8F, 0x8490, 0xA533, 0xBDF7, 0xB596, 0x7BEF, 0xB596, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8430, 0x9CF3, 0xCE39, 0xA514, 0x94B2, 0x9E93, 0x94F2, 0x8CD1, 0x8CB1, 0x9D12, // 0x0090 (144) +0x9F74, 0x9D52, 0x8450, 0x7C8F, 0x73AE, 0x740E, 0x73CE, 0x9CD3, 0xC638, 0x8C51, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x8430, 0xA534, 0xBDF7, 0x8CB1, 0x8C31, 0x9DB3, 0xA735, 0x9D13, 0x8CB1, 0x8C71, 0x9D13, // 0x00B0 (176) +0xB756, 0xA5D4, 0x8C71, 0x8490, 0x8390, 0x7C70, 0x73EE, 0x6B4D, 0x8450, 0xBDF7, 0x8C71, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x94B2, 0x9CF3, 0xBDD7, 0x8490, 0x8CF1, 0x9D72, 0xA694, 0xAE94, 0x9DD3, 0xA593, 0xA553, 0x9592, // 0x00D0 (208) +0x9672, 0x75CE, 0x5BAA, 0x64EB, 0x5D8C, 0x5BCA, 0x4B69, 0x634C, 0x748D, 0x7C4F, 0xBE18, 0x8430, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xC618, 0x8410, 0xBDF7, 0x8410, 0x83F0, 0x94F2, 0x9613, 0x9D13, 0xAE55, 0x9D12, 0x750E, 0x55CB, 0x4BC8, // 0x00F0 (240) +0x4447, 0x3BC6, 0x4B67, 0x44E8, 0x3CE8, 0x3325, 0x20E2, 0x2B45, 0x43E7, 0x3946, 0x732D, 0xC5F8, 0x7BCF, 0xE71C, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xF7BE, 0x7BEF, 0xBDB6, 0x9533, 0x8D71, 0x9552, 0x9E73, 0x9DD3, 0x94B2, 0x6D6D, 0x4BA8, 0x44A8, 0x55EA, 0x5D2A, // 0x0110 (272) +0x43E7, 0x4327, 0x46CA, 0x4B87, 0x42C6, 0x4E0A, 0x4D09, 0x4468, 0x4548, 0x3386, 0x2B25, 0x7C6F, 0xAD35, 0x9492, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFDF, 0xFFFF, 0xBDD7, 0x8C71, 0xAD75, 0x8CF0, 0x8D71, 0x8D51, 0x9DF3, 0x740E, 0x21C4, 0x33E5, 0x558A, 0x554A, 0x650A, 0x566B, // 0x0130 (304) +0x43E7, 0x21C3, 0x3345, 0x2283, 0x1962, 0x3C87, 0x3386, 0x2163, 0x3345, 0x3346, 0x33A6, 0x32C6, 0x9CB3, 0x7BEF, 0xDEDB, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0x8430, 0xAD75, 0x8C31, 0x7C0F, 0x7BCF, 0x83F0, 0x636B, 0x0000, 0x0000, 0x4387, 0x462A, 0x4B27, 0x4B88, 0x4E8B, // 0x0150 (336) +0x42E6, 0x0000, 0x0020, 0x0100, 0x0000, 0x1121, 0x0040, 0x0000, 0x0941, 0x0000, 0x0020, 0x00E0, 0x5AAB, 0x94B2, 0x9CD3, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xE71C, 0x8410, 0xB596, 0x7BEF, 0x7C6F, 0x84B0, 0x5B6B, 0x09E1, 0x0901, 0x1161, 0x3C06, 0x3D89, 0x32C5, 0x43E7, 0x470B, // 0x0170 (368) +0x4BC7, 0x0961, 0x11E2, 0x1282, 0x0961, 0x1262, 0x09E2, 0x0961, 0x12A2, 0x0961, 0x09C2, 0x0A01, 0x29E5, 0xA514, 0x7BEF, 0xFFDF, // 0x0180 (384) +0xFFFF, 0xBDD7, 0x9472, 0xA514, 0x6B4D, 0x7C6F, 0x634C, 0x0040, 0x0981, 0x0060, 0x00E0, 0x11E2, 0x10A1, 0x09C1, 0x19E3, 0x2B25, // 0x0190 (400) +0x22A3, 0x0060, 0x0120, 0x09E1, 0x0060, 0x09E1, 0x0120, 0x0060, 0x0A21, 0x0060, 0x0100, 0x01A0, 0x0040, 0x9CD3, 0x7BEF, 0xDEDB, // 0x01A0 (416) +0xFFFF, 0xA514, 0x9CF3, 0xB596, 0x73AE, 0x7C0F, 0x2945, 0x10A2, 0x2184, 0x18C3, 0x1923, 0x2184, 0x18C3, 0x21A4, 0x2964, 0x2905, // 0x01B0 (432) +0x2A25, 0x2104, 0x2965, 0x2A05, 0x2104, 0x2A05, 0x2985, 0x2104, 0x2A25, 0x2104, 0x2164, 0x29C4, 0x3166, 0xB5B6, 0x8410, 0xC618, // 0x01C0 (448) +0xFFFF, 0x9492, 0xA514, 0xDEDB, 0xC618, 0xA514, 0x8C51, 0x94B2, 0x9CB3, 0x9CF3, 0xA514, 0xA534, 0xAD75, 0xAD75, 0xB596, 0xB5D6, // 0x01D0 (464) +0xBDB7, 0xBDF7, 0xBDF7, 0xBDF7, 0xC618, 0xC5F8, 0xC5F8, 0xBDF7, 0xBDD7, 0xBDD7, 0xB5B6, 0xB596, 0xC638, 0xDEFB, 0x8430, 0xB596, // 0x01E0 (480) +0xFFFF, 0x8C51, 0x9CF3, 0xE73C, 0xDEFB, 0xD69A, 0xD6BA, 0xD6BA, 0xDEDB, 0xDEDB, 0xDEFB, 0xDF1B, 0xE71C, 0xE73C, 0xE73C, 0xE73C, // 0x01F0 (496) +0xEF5D, 0xEF5D, 0xEF5D, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xDEFB, 0xE71C, 0x8C51, 0xAD75, // 0x0200 (512) +0xFFFF, 0x8C71, 0x9CD3, 0xDEFB, 0xAD75, 0x9492, 0x9CD3, 0xA4F3, 0xA514, 0xAD55, 0xAD75, 0xB596, 0xBDB6, 0xBDD7, 0xC5F7, 0xC618, // 0x0210 (528) +0xC638, 0xCE59, 0xCE59, 0xCE79, 0xD679, 0xD679, 0xCE79, 0xCE59, 0xCE59, 0xC638, 0xC618, 0xBDF7, 0xCE79, 0xE71C, 0x8C51, 0xB596, // 0x0220 (544) +0xFFFF, 0x9CD3, 0x9492, 0xAD55, 0x2965, 0x2104, 0x2124, 0x2145, 0x1945, 0x2165, 0x2165, 0x2186, 0x2186, 0x29A6, 0x29A6, 0x31C7, // 0x0230 (560) +0x39C7, 0x31E7, 0x31E7, 0x31E7, 0x3208, 0x3208, 0x31E7, 0x31E7, 0x29E7, 0x31C7, 0x39C7, 0x31A6, 0x4A49, 0xBDF7, 0x8C51, 0xBDF7, // 0x0240 (576) +0xFFFF, 0xB5B6, 0x8430, 0x7BEF, 0x0000, 0x0000, 0x0000, 0x2000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3800, 0x2000, // 0x0250 (592) +0x0000, 0x3000, 0x3800, 0x3000, 0x3800, 0x3800, 0x3800, 0x3000, 0x3800, 0x0800, 0x0000, 0x0000, 0x0000, 0xA514, 0x8430, 0xD6BA, // 0x0260 (608) +0xFFFF, 0xDEDB, 0x7BCF, 0x8430, 0x0020, 0x0000, 0x0000, 0x8000, 0xC800, 0xC000, 0xC800, 0xC820, 0xC820, 0xC820, 0xD020, 0x9800, // 0x0270 (624) +0x0000, 0xB820, 0xD020, 0xD020, 0xD020, 0xD020, 0xD020, 0xC820, 0xD020, 0x4800, 0x0000, 0x0000, 0x2144, 0xAD75, 0x8410, 0xF7BE, // 0x0280 (640) +0xFFFF, 0xFFFF, 0x7BEF, 0x8C71, 0x2945, 0x0000, 0x0000, 0x6800, 0xA800, 0xA800, 0xA800, 0xA800, 0xA800, 0xA800, 0xB000, 0x8000, // 0x0290 (656) +0x0000, 0x9800, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0xB000, 0x4000, 0x0000, 0x0000, 0x632C, 0xA534, 0x94B2, 0xFFFF, // 0x02A0 (672) +0xFFDF, 0xFFFF, 0xAD75, 0x73AE, 0x632C, 0x0000, 0x0000, 0x6920, 0xA9E0, 0xA1C0, 0xA9E0, 0xA9E0, 0xA9E0, 0xA9E0, 0xA9E0, 0x7960, // 0x02B0 (688) +0x0000, 0x99C0, 0xB200, 0xA9E0, 0xB200, 0xB200, 0xB1E0, 0xA9E0, 0xB200, 0x40C0, 0x0000, 0x1082, 0xAD75, 0x8410, 0xD69A, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xF79E, 0x630C, 0x8C51, 0x2965, 0x0000, 0x7400, 0xB620, 0xAE00, 0xB620, 0xB640, 0xB640, 0xB620, 0xB660, 0x84A0, // 0x02D0 (720) +0x0000, 0xA5A0, 0xBE60, 0xB660, 0xBE60, 0xBE60, 0xB660, 0xB640, 0xBE80, 0x4260, 0x0000, 0x6B6D, 0xAD75, 0x8430, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFDF, 0xFFFF, 0xB5B6, 0x632C, 0x8410, 0x0021, 0x7360, 0xBD40, 0xB520, 0xBD40, 0xBD60, 0xBD60, 0xBD40, 0xC580, 0x8C00, // 0x02F0 (752) +0x0000, 0xACE0, 0xC580, 0xC580, 0xC580, 0xC580, 0xC580, 0xBD60, 0xC5A0, 0x39C0, 0x2126, 0xBDF7, 0x73AE, 0xD6BA, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BEF, 0x7BEF, 0x630D, 0x4AE1, 0x6D21, 0x6D01, 0x6D21, 0x6D41, 0x6D41, 0x6D41, 0x6D61, 0x53E1, // 0x0310 (784) +0x0000, 0x64C1, 0x7562, 0x6D62, 0x6D62, 0x6D62, 0x6D62, 0x6D42, 0x6D41, 0x4263, 0xA515, 0x8C51, 0xA534, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x6B4D, 0x8410, 0x636E, 0x04A6, 0x05E5, 0x05C5, 0x0585, 0x0585, 0x0586, 0x05A6, 0x0424, // 0x0330 (816) +0x0000, 0x0505, 0x05C6, 0x05A6, 0x05A6, 0x05C7, 0x0606, 0x0606, 0x1CE9, 0xA535, 0x9492, 0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x6B4D, 0x83EF, 0x9411, 0x3A47, 0x0403, 0x0584, 0x05A4, 0x0585, 0x0585, 0x0404, // 0x0350 (848) +0x0000, 0x04E5, 0x05A5, 0x05A5, 0x05C5, 0x0584, 0x1405, 0x634B, 0xBD76, 0x8C51, 0x8C51, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8410, 0x6B6D, 0x9CB3, 0x7C6F, 0x3CA9, 0x0BE4, 0x0443, 0x0504, 0x03C2, // 0x0370 (880) +0x0000, 0x0483, 0x0504, 0x0444, 0x1426, 0x552D, 0xA554, 0xB576, 0x73CE, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB5B6, 0x6B4D, 0x7BAF, 0x9432, 0x8BD1, 0x6BCE, 0x4C6B, 0x3C09, // 0x0390 (912) +0x3186, 0x3C8A, 0x5C8C, 0x8430, 0xA493, 0xACD4, 0x8410, 0x7BEF, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xAD75, 0x7BEF, 0x73AE, 0x83F0, 0x8C11, 0x9431, // 0x03B0 (944) +0x9492, 0x9452, 0x9432, 0x8430, 0x7BEF, 0x8450, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0xBDD7, 0xA534, 0x94D3, // 0x03D0 (976) +0x94B2, 0x9CF3, 0xA554, 0xC618, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap/info.c b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/info.c new file mode 100644 index 0000000..312bee1 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/info.c @@ -0,0 +1,71 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: info.png +// Time generated: 11.10.2010 22:27:55 +// Size : 2 048 Bytes + +const unsigned short info[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF9F, 0xC69D, 0x95BB, 0x7D1A, 0x6CB9, // 0x0030 (48) +0x6499, 0x74F9, 0x8D7A, 0xB63C, 0xE73E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAE1C, 0x4C18, 0x2B56, 0x3397, 0x4C38, 0x64B9, 0x751A, // 0x0050 (80) +0x7D3A, 0x6CD9, 0x5458, 0x3BD7, 0x2B56, 0x3BB7, 0x855A, 0xE77E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA5FB, 0x2B56, 0x2B77, 0x751A, 0xB67C, 0xD73E, 0xE75E, 0xE77E, 0xE77E, // 0x0070 (112) +0xE77E, 0xE77E, 0xE75E, 0xDF3E, 0xC6DD, 0x8D9B, 0x43D7, 0x1B16, 0x74D9, 0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF9F, 0x4C18, 0x1AF6, 0x855A, 0xCEFE, 0xD71E, 0xCEFD, 0xC6DD, 0xC6BD, 0xC6BD, 0xBEBD, // 0x0090 (144) +0xC6BD, 0xBEBD, 0xC6BD, 0xC6DD, 0xC6DD, 0xD71E, 0xD71E, 0xA61C, 0x33B7, 0x2316, 0xBE7C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF3E, 0x2336, 0x3BD7, 0xBE9D, 0xC6DD, 0xBE9D, 0xBE9D, 0xBE9D, 0xBEBD, 0xBE9D, 0xCEFD, 0xEF9F, // 0x00B0 (176) +0xEF9F, 0xD73E, 0xBE9D, 0xBEBD, 0xBE9D, 0xBE9D, 0xB69D, 0xC6BD, 0xCEDD, 0x6CFA, 0x0295, 0x9DBB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xE75E, 0x1AF6, 0x4C58, 0xBEBD, 0xB67D, 0xAE5C, 0xB67D, 0xB67D, 0xB69D, 0xB67D, 0xBEBD, 0xF7DF, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xFFFF, 0xCF1E, 0xB67D, 0xB67D, 0xB67D, 0xB67D, 0xAE5C, 0xAE5C, 0xC6BD, 0x857B, 0x0295, 0xA5DB, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFDF, 0x3BB7, 0x33D8, 0xB67D, 0xA63C, 0xA63C, 0xAE5C, 0xAE5D, 0xAE5D, 0xAE7D, 0xA65D, 0xC6DD, 0xFFFF, 0xFFFF, // 0x00F0 (240) +0xFFDF, 0xFFFF, 0xDF5E, 0xA65D, 0xAE7D, 0xAE5D, 0xAE5D, 0xAE5C, 0xA63C, 0xA61C, 0xB67D, 0x753A, 0x0295, 0xCEBC, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xF7DF, 0xFFFF, 0x957A, 0x12F6, 0x9E1C, 0x9E1C, 0x9E1C, 0x9E1C, 0xA63C, 0xA63C, 0xA63D, 0xA63D, 0xA65D, 0x9DFC, 0xDF3E, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xFFDF, 0xA61C, 0xA65D, 0xA65D, 0xA63D, 0xA63C, 0xA63C, 0x9E1C, 0x9E1C, 0x9DFC, 0xAE3C, 0x3C18, 0x3396, 0xFFDF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xF79F, 0x2336, 0x64DA, 0x9DFC, 0x95DC, 0x95FC, 0x95FC, 0x9E1C, 0x9E1C, 0x9E3D, 0x9E3D, 0x9E3D, 0x9E3D, 0x7D3B, 0xA63C, // 0x0130 (304) +0xB6BD, 0x8DBB, 0x8DFC, 0xA65D, 0x9E3D, 0x9E3D, 0x9E1C, 0x9E1C, 0x95FC, 0x95FC, 0x95DC, 0x95DC, 0x8DBB, 0x0AF6, 0xA5DA, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xA5FB, 0x1337, 0x8DBB, 0x8DBB, 0x8DBC, 0x8DDC, 0x95FC, 0x95FC, 0x961C, 0x961D, 0x963D, 0x9E3D, 0x963D, 0xA67D, 0xB6BD, // 0x0150 (336) +0xB6BD, 0xAE7D, 0x9E3D, 0x9E3D, 0x961D, 0x961D, 0x961C, 0x95FC, 0x95FC, 0x8DDC, 0x8DDC, 0x859B, 0x95DC, 0x3C18, 0x4BD7, 0xFFFF, // 0x0160 (352) +0xFFFF, 0x6499, 0x33F8, 0x8DBB, 0x859B, 0x85BC, 0x85BC, 0x8DDC, 0x8DFC, 0x8DFD, 0x8E1D, 0x961D, 0x961D, 0x9E3D, 0xF7BF, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xA67D, 0x8E1D, 0x961D, 0x8E1D, 0x8DFD, 0x8DFC, 0x8DDC, 0x85BC, 0x85BC, 0x859B, 0x859B, 0x5CDA, 0x2336, 0xE71C, // 0x0180 (384) +0xFFFF, 0x43F8, 0x4C79, 0x859B, 0x7D7B, 0x7D9C, 0x85BC, 0x85DC, 0x85DC, 0x8DFD, 0x8DFD, 0x8E1D, 0x8E1D, 0xA67E, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFFF, 0xBEDE, 0x85FD, 0x8E1D, 0x8DFD, 0x8DFD, 0x85DC, 0x85DC, 0x85BC, 0x7D9C, 0x7D7B, 0x7D7B, 0x753B, 0x1B36, 0xBE5A, // 0x01A0 (416) +0xFFBE, 0x3BF8, 0x3419, 0x6D1B, 0x757B, 0x7D9C, 0x7D9C, 0x7DBC, 0x7DDD, 0x85FD, 0x85FD, 0x861D, 0x861D, 0x9E7E, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xFFFF, 0xB6DE, 0x85FD, 0x8E1D, 0x85FD, 0x85FD, 0x7DDD, 0x7DBC, 0x7D9C, 0x7D9C, 0x757B, 0x6D3B, 0x4C9A, 0x1337, 0xADD9, // 0x01C0 (448) +0xFFBE, 0x4418, 0x23B9, 0x3439, 0x4CBA, 0x653B, 0x759C, 0x7DBD, 0x7DDD, 0x7DFD, 0x861D, 0x861E, 0x861E, 0x9E7E, 0xFFFF, 0xFFFF, // 0x01D0 (464) +0xFFFF, 0xFFFF, 0xB6DE, 0x7E1E, 0x861E, 0x85FD, 0x7DFD, 0x7DDD, 0x7DBD, 0x759C, 0x653B, 0x4CDB, 0x3439, 0x2BF9, 0x1337, 0xA5B9, // 0x01E0 (480) +0xFF9E, 0x4C39, 0x2BF9, 0x345A, 0x3C7A, 0x3C9B, 0x4CFC, 0x5D5C, 0x659D, 0x75DD, 0x7DFE, 0x861E, 0x7E3E, 0x969F, 0xFFFF, 0xFFFF, // 0x01F0 (496) +0xFFFF, 0xFFFF, 0xB6FF, 0x7E1E, 0x863E, 0x7DFE, 0x75DD, 0x6D9D, 0x5D5C, 0x4CFC, 0x3C9B, 0x347A, 0x345A, 0x343A, 0x1B78, 0xA5B9, // 0x0200 (512) +0xF79E, 0x4418, 0x2C3A, 0x3C7A, 0x449B, 0x44DB, 0x4CFC, 0x4D3C, 0x555D, 0x5D7D, 0x65BE, 0x6DFE, 0x6DFF, 0x867F, 0xFFFF, 0xFFFF, // 0x0210 (528) +0xFFFF, 0xFFFF, 0xA6DF, 0x65FF, 0x6DFE, 0x65BE, 0x5D9E, 0x555D, 0x4D3C, 0x4CFC, 0x44DB, 0x44BB, 0x3C7A, 0x345A, 0x1B78, 0xA599, // 0x0220 (544) +0xFFDE, 0x43D8, 0x345A, 0x3C9A, 0x44DB, 0x4CFC, 0x4D3C, 0x555D, 0x5D9D, 0x5DBE, 0x65DE, 0x6DFF, 0x661F, 0x867F, 0xFFFF, 0xFFFF, // 0x0230 (560) +0xFFFF, 0xFFFF, 0xA6DF, 0x65FF, 0x6DFF, 0x65DE, 0x5DBE, 0x5D9D, 0x555D, 0x4D3C, 0x4CFC, 0x44DB, 0x3C7A, 0x3C9B, 0x1B57, 0xADB9, // 0x0240 (576) +0xFFFF, 0x4BD7, 0x2C1A, 0x44DB, 0x44DB, 0x4D1C, 0x555D, 0x5D7D, 0x5DBE, 0x65DE, 0x6E1F, 0x6E3F, 0x765F, 0x96BF, 0xFFFF, 0xFFFF, // 0x0250 (592) +0xFFFF, 0xFFFF, 0xAEFF, 0x6E3F, 0x763F, 0x6E1F, 0x65DE, 0x5DBE, 0x5D7D, 0x555D, 0x4D1C, 0x44DC, 0x3C9B, 0x44DC, 0x1AD5, 0xC639, // 0x0260 (608) +0xFFFF, 0x84D8, 0x1317, 0x5D7D, 0x44DB, 0x553C, 0x557D, 0x5D9E, 0x65DE, 0x65FF, 0x6E3F, 0x7E5F, 0x7E7F, 0x9EDF, 0xFFFF, 0xFFFF, // 0x0270 (624) +0xFFFF, 0xFFFF, 0xB73F, 0x7E7F, 0x7E5F, 0x6E3F, 0x65FF, 0x65DE, 0x5D9E, 0x557D, 0x553C, 0x44DC, 0x4D1C, 0x345B, 0x22B4, 0xE71B, // 0x0280 (640) +0xFFFF, 0xD6BC, 0x0234, 0x4CFC, 0x5D7D, 0x4D3C, 0x5D9D, 0x5DBE, 0x65FF, 0x6E3F, 0x765F, 0x867F, 0x8EBF, 0xA6DF, 0xFFFF, 0xFFFF, // 0x0290 (656) +0xFFFF, 0xFFFF, 0xB71F, 0x8EBF, 0x869F, 0x765F, 0x6E3F, 0x65FF, 0x5DBE, 0x5D7D, 0x553D, 0x4D1C, 0x65BE, 0x0AB7, 0x6C15, 0xFFBE, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0x53B6, 0x0296, 0x75FE, 0x5D9D, 0x557D, 0x65DE, 0x6E1F, 0x763F, 0x7E7F, 0x8EBF, 0x9EFF, 0x96BE, 0xAE3C, 0xE77E, // 0x02B0 (688) +0xEF9E, 0xC69D, 0x967E, 0x9EFF, 0x8EBF, 0x7E7F, 0x763F, 0x6E1F, 0x65DE, 0x5D9E, 0x555D, 0x761E, 0x341A, 0x1294, 0xBE18, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xCE9B, 0x0A13, 0x2378, 0x7E5F, 0x6E1E, 0x5DBE, 0x6E1F, 0x7E5F, 0x869F, 0x96DF, 0x9EFF, 0xAF5F, 0x9E9E, 0x8DFC, // 0x02D0 (720) +0x8E1C, 0x967D, 0xAF3F, 0xA6FF, 0x96DF, 0x869F, 0x7E5F, 0x6E1F, 0x5DBE, 0x65DE, 0x7E5F, 0x4CBB, 0x0AB5, 0x7454, 0xEF5C, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFFF, 0xFFFF, 0x8D17, 0x01D3, 0x23B9, 0x7E3E, 0x8E9F, 0x763F, 0x765F, 0x8E9F, 0x9EDF, 0xA71F, 0xB75F, 0xC7BF, 0xCFDF, // 0x02F0 (752) +0xCFDF, 0xC7BF, 0xB75F, 0xA71F, 0x9EDF, 0x8E9F, 0x765F, 0x6E1F, 0x867F, 0x8E7F, 0x4CBB, 0x1317, 0x4BB4, 0xD679, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFBD, 0x7476, 0x0214, 0x1B78, 0x659D, 0x9EDF, 0x9EFF, 0x96DF, 0x9EFF, 0xAF1F, 0xB75F, 0xC79F, 0xD7DF, // 0x0310 (784) +0xD7DF, 0xC79F, 0xB75F, 0xAF1F, 0x9EDF, 0x96DF, 0x96DF, 0x9EFF, 0x7E1E, 0x3C5A, 0x1B77, 0x43B5, 0xBDD6, 0xF7BE, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77D, 0x7CB6, 0x12B4, 0x1337, 0x449B, 0x7DFD, 0xA6FF, 0xB75F, 0xBF7F, 0xC79F, 0xCFBF, 0xD7FF, // 0x0330 (816) +0xD7FF, 0xCFBF, 0xC79F, 0xBF7F, 0xB77F, 0xAF1F, 0x8E5E, 0x551B, 0x3419, 0x2BD7, 0x5415, 0xB5B6, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79D, 0xA577, 0x3B75, 0x1B36, 0x2BD9, 0x4CBB, 0x759D, 0x965E, 0xAEDF, 0xBF3F, 0xC77F, // 0x0350 (848) +0xC77F, 0xBF3F, 0xB6FF, 0x9E7F, 0x7DDD, 0x5D1C, 0x447A, 0x3C59, 0x4437, 0x7474, 0xC617, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDE, 0xD699, 0x84D5, 0x43D5, 0x33B7, 0x3418, 0x4C7A, 0x5CFC, 0x753D, 0x857E, // 0x0370 (880) +0x859E, 0x755D, 0x653C, 0x5CFB, 0x4CDA, 0x4CB9, 0x5497, 0x6C95, 0xA555, 0xDEDA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79D, 0xCE79, 0x9D56, 0x7495, 0x5C56, 0x4C77, 0x4C97, 0x4CB8, // 0x0390 (912) +0x54D8, 0x5CD8, 0x5CF8, 0x64D7, 0x74D6, 0x8CF5, 0xAD96, 0xD699, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFBE, 0xEF1B, 0xD679, 0xBDF7, 0xAD96, 0xA576, // 0x03B0 (944) +0xA576, 0xAD76, 0xB5B6, 0xC5F7, 0xD679, 0xEF3C, 0xFFDE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFBE, // 0x03D0 (976) +0xF7BE, 0xF7BE, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap/tux.c b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/tux.c new file mode 100644 index 0000000..69a04a1 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap/tux.c @@ -0,0 +1,71 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: tux.png +// Time generated: 11.10.2010 22:51:32 +// Size : 2 048 Bytes + +const unsigned short tux[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x9CD3, 0x9CF3, 0xA514, // 0x0010 (16) +0x9CF3, 0x8C51, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x5AEB, 0x7BEF, 0x9CD3, 0x94B2, // 0x0030 (48) +0x94B2, 0x94B2, 0x4228, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x9CF3, 0x18E3, 0x630C, 0x4A49, 0x4A69, // 0x0050 (80) +0x4A69, 0x528A, 0x4A49, 0x0000, 0xC638, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x0000, 0x0020, 0x10A2, 0x1082, // 0x0070 (112) +0x0841, 0x0841, 0x0841, 0x0000, 0x630C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x528A, 0x4228, 0x8410, 0x0000, 0x0861, // 0x0090 (144) +0xAD55, 0xBDD7, 0x10A2, 0x0000, 0x2945, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x5ACB, 0x8C71, 0xE75D, 0x2126, 0x528B, // 0x00B0 (176) +0xE75D, 0xDEDB, 0x7BCF, 0x0000, 0x18E3, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6D, 0x4A4A, 0x6B2A, 0x8BE7, 0xA48A, // 0x00D0 (208) +0x6B09, 0x4A8A, 0x8431, 0x0000, 0x2104, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x6B6E, 0x5204, 0xDE6A, 0xFFF7, 0xFFF8, // 0x00F0 (240) +0xD5AC, 0xBCAA, 0x5A66, 0x0000, 0x1082, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C10, 0xC540, 0xFFED, 0xFF2C, 0xFEEC, // 0x0110 (272) +0xFECC, 0xFE66, 0x8260, 0x0000, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B3, 0x9C25, 0xFF20, 0xFE40, 0xFDA0, // 0x0130 (304) +0xFCC0, 0xF524, 0x836A, 0x0000, 0x0000, 0x630C, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x630C, 0x94B4, 0xFF13, 0xFD83, 0xF523, // 0x0150 (336) +0xE5CF, 0xF79E, 0xE71D, 0x0861, 0x0000, 0x0861, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0841, 0xD69A, 0xFFFF, 0xFF7D, 0xF77D, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x4A69, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x10A2, 0x8410, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFDF, 0xFFFF, 0xCE59, 0x0000, 0x0000, 0x0000, 0x9492, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01A0 (416) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x52AA, 0x0020, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFDF, 0xFFDF, 0xF7BE, 0xFFDF, 0x3186, 0x0000, 0x0020, 0x0841, 0xCE79, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x0000, 0x52AA, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x01D0 (464) +0xFFDF, 0xF7BE, 0xF79E, 0xFFFF, 0x9CF3, 0x0000, 0x0841, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01E0 (480) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x5ACB, 0x0000, 0xBDF7, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFDF, // 0x01F0 (496) +0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0x3186, 0x0000, 0x0861, 0x0000, 0xAD55, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x0861, 0x4A49, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x0210 (528) +0xF7BE, 0xF79E, 0xEF7D, 0xEF5D, 0xFFDF, 0x8410, 0x0000, 0x1082, 0x0000, 0x39E7, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0220 (544) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0xB596, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, // 0x0230 (560) +0xF79E, 0xEF7D, 0xEF7D, 0xE73C, 0xF79E, 0xAD55, 0x0861, 0x10A2, 0x0861, 0x0841, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x3185, 0x10A2, 0xE71C, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, // 0x0250 (592) +0xEF7D, 0xEF7D, 0xEF5D, 0xE73C, 0xEF5D, 0xBDF7, 0x18C3, 0x18C3, 0x18C3, 0x0000, 0x8C71, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0260 (608) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0x39E7, 0xF7BE, 0xFFFF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF79E, 0xEF7D, // 0x0270 (624) +0xEF7D, 0xEF5D, 0xE73C, 0xE71C, 0xE71C, 0xC618, 0x18E3, 0x10A2, 0x10A2, 0x0020, 0x6B4D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C51, 0x38E0, 0x4A27, 0xFFFF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, // 0x0290 (656) +0xEF5D, 0xE73C, 0xE71C, 0xDEFB, 0xDF1D, 0xBDF8, 0x39C7, 0x5ACB, 0x528A, 0x10A3, 0x738F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDD6C, 0xFE2B, 0xBC45, 0xA513, 0xFFFF, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF5D, // 0x02B0 (688) +0xE73C, 0xE71C, 0xDEFB, 0xD6DC, 0xDD8E, 0xB3E4, 0x2124, 0x2965, 0x2945, 0x20C1, 0xB511, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77C, 0xE5CF, 0xF60B, 0xFF9B, 0xFF54, 0x8B02, 0x7BF0, 0xFFDF, 0xF79E, 0xEF5D, 0xEF5D, 0xE73C, // 0x02D0 (720) +0xE71C, 0xDEFB, 0xDEDB, 0xCE7A, 0xED89, 0xDDAD, 0x0842, 0x0000, 0x0000, 0xAC69, 0xDD6B, 0xEFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xFFFF, 0xFFBE, 0xE5CB, 0xEDC9, 0xFE4B, 0xFF14, 0xFEF3, 0xFF35, 0xFE8D, 0x51C1, 0x634E, 0xE73C, 0xEF5D, 0xE73C, 0xE71C, // 0x02F0 (752) +0xDEFB, 0xDEDB, 0xD6DB, 0xCE59, 0xE58B, 0xFF98, 0xBD4F, 0x8B88, 0xCD90, 0xFFB7, 0xCCE8, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xEF3B, 0xF583, 0xFF30, 0xFF11, 0xFECF, 0xFEEF, 0xFECF, 0xFF30, 0xDD46, 0x2903, 0x6B8E, 0xEF7D, 0xE71C, 0xDEFB, // 0x0310 (784) +0xDEDB, 0xD6BA, 0xD69A, 0xCE59, 0xE5AA, 0xFF11, 0xFF53, 0xFF73, 0xFF33, 0xFF12, 0xFE6C, 0xDDAD, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFFF, 0xFFFF, 0xF79E, 0xEDC5, 0xFECB, 0xFECC, 0xFECC, 0xFEEC, 0xFECB, 0xFECC, 0xFEEA, 0x9BE5, 0x8432, 0xE73C, 0xDEDB, 0xDEDB, // 0x0330 (816) +0xD6BA, 0xD69A, 0xDEDB, 0xA4F3, 0xD547, 0xFF2E, 0xFECD, 0xFECE, 0xFEEE, 0xFEEE, 0xFF10, 0xFEAB, 0xE5A8, 0xEF7D, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xF79E, 0xF603, 0xFEA2, 0xFEC7, 0xFEC7, 0xFEA4, 0xFE81, 0xFE61, 0xFEA4, 0xFE43, 0xDE33, 0xE75E, 0xE71C, 0xDEFB, // 0x0350 (848) +0xDEDB, 0xCE58, 0x8C72, 0x5247, 0xEDE4, 0xFF0A, 0xFECA, 0xFEC9, 0xFE84, 0xFE83, 0xFEE7, 0xFEA3, 0xB443, 0xD69B, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xF75B, 0xFE60, 0xFF00, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xE5C1, 0x9492, 0xA514, 0x9CD3, // 0x0370 (880) +0x8410, 0x630B, 0x4229, 0x6AE8, 0xFE80, 0xFEC1, 0xFEC1, 0xFEA0, 0xFEA0, 0xFEE0, 0xDD80, 0x9BE8, 0xB597, 0xFFDF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xF79E, 0xD589, 0xE600, 0xFEA0, 0xFF00, 0xFF40, 0xFF40, 0xFF00, 0xFF00, 0xFF20, 0xFEC0, 0x5267, 0x4229, 0x4A48, // 0x0390 (912) +0x4A49, 0x5289, 0x424A, 0x7B46, 0xFF20, 0xFEE0, 0xFEE0, 0xFF20, 0xFEE0, 0xB4A5, 0x9C92, 0xDEFD, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xE71D, 0xBDB6, 0xB530, 0xBD0B, 0xCD65, 0xEE60, 0xFF40, 0xFFA0, 0xFF80, 0xBD03, 0x8410, 0xA514, 0xA534, // 0x03B0 (944) +0xAD75, 0xB596, 0xA555, 0x9C8F, 0xF6C0, 0xFFA0, 0xFFA0, 0xF6E0, 0xA449, 0xB5B8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7F, 0xD69C, 0xBD95, 0xBD4C, 0xCDC6, 0xB4E8, 0xAD35, 0xF7BF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xF7BF, 0xCDD0, 0xCDC6, 0xCDA7, 0xA48D, 0xCE7B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF1F, 0xB59A, 0xBDDA, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFDF, 0xFFDF, 0xFFFF, 0xEF7F, 0xB59A, 0xAD59, 0xDF1D, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.pde b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.pde new file mode 100644 index 0000000..85f0573 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/UTFT_Bitmap_128x128.pde @@ -0,0 +1,49 @@ +// UTFT_Bitmap_128x128 (C)2012 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This demo was made to work on the 128x128 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include + +UTFT myGLCD(LPH9135,6,5,2,3,4); // Remember to change the model parameter to suit your display module! + +extern unsigned short icon1[0x400]; +extern unsigned short icon2[0x400]; +extern unsigned short tux[0x1000]; + +void setup() +{ + myGLCD.InitLCD(PORTRAIT); +} + +void loop() +{ +// Draw a 4 by 4 grid of a 32x32 icon. + myGLCD.fillScr(255, 255, 255); + for (int x=0; x<4; x++) + for (int y=0; y<4; y++) + myGLCD.drawBitmap (x*32, y*32, 32, 32, icon1); + + delay(5000); + +// Draw a 64x64 icon in double size. + myGLCD.fillScr(255, 255, 255); + myGLCD.drawBitmap (0, 0, 64, 64, tux, 2); + + delay(5000); + +// Draw a 2 by 2 grid of a 32x32 icon in double size. + myGLCD.fillScr(255, 255, 255); + for (int x=0; x<2; x++) + for (int y=0; y<2; y++) + myGLCD.drawBitmap (x*64, y*64, 32, 32, icon2, 2); + + delay(5000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon1.c b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon1.c new file mode 100644 index 0000000..b9c2c97 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon1.c @@ -0,0 +1,72 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: exit.png +// Time generated: 14.10.2010 21:53:03 +// Dimensions : 32x32 pixels +// Size : 2 048 Bytes + +const unsigned short icon1[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF1C, 0xE618, 0xE638, 0xE638, 0xE638, 0xE659, 0xE659, 0xE659, 0xE659, 0xE659, 0xE679, 0xE679, // 0x0010 (16) +0xE679, 0xE679, 0xE679, 0xE679, 0xEE79, 0xEE9A, 0xEE9A, 0xEE9A, 0xEE9A, 0xEE9A, 0xE638, 0xEEBA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xD555, 0xCCD3, 0xDDB6, 0xDDD7, 0xDDF7, 0xDDF7, 0xDE18, 0xE618, 0xE638, 0xE638, 0xE659, 0xE679, 0xE679, // 0x0030 (48) +0xEE9A, 0xEE9A, 0xEEBA, 0xEEBA, 0xEEBA, 0xEEDB, 0xEEDB, 0xEEFB, 0xEEFB, 0xEEFB, 0xEEFB, 0xE659, 0xD575, 0xF77D, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFDF, 0xFFFF, 0xD534, 0xC471, 0xD575, 0xCCF3, 0xCCD3, 0xCCD3, 0xCCF3, 0xCCF3, 0xD4F3, 0xD514, 0xD514, 0xD514, 0xD534, 0xDD55, // 0x0050 (80) +0xDD55, 0xDD55, 0xDD55, 0xDD75, 0xDD75, 0xDD75, 0xDD96, 0xDD96, 0xDD96, 0xDDB6, 0xDDD7, 0xEE79, 0xEEBA, 0xD534, 0xFFBE, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xEEDB, 0xB38E, 0xC4B2, 0xBC30, 0xC451, 0xC471, 0xC471, 0xCC71, 0xCC92, 0xCC92, 0xCC92, 0xCCB2, 0xD4B2, 0xD4B2, 0xCC71, // 0x0070 (112) +0xCC71, 0xD4D3, 0xD4F3, 0xDCF3, 0xDCF3, 0xDD14, 0xDD14, 0xDD14, 0xDD34, 0xDD34, 0xDD34, 0xDD14, 0xE5D7, 0xDD96, 0xDDF7, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xC4F3, 0xAB2C, 0xC430, 0xC410, 0xC430, 0xC430, 0xC430, 0xCC51, 0xCC51, 0xCC51, 0xCC71, 0xCC71, 0xD471, 0xCC71, 0xD5F7, // 0x0090 (144) +0xD5F7, 0xCC92, 0xDCB2, 0xDCD3, 0xDCD3, 0xDCD3, 0xDCD3, 0xDCF3, 0xDCF3, 0xDD14, 0xDD14, 0xDD34, 0xDD14, 0xDD34, 0xC492, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xB3EF, 0x9A28, 0xC430, 0xBBCF, 0xC3EF, 0xC3EF, 0xC3EF, 0xC410, 0xCC10, 0xCC10, 0xCC30, 0xCC51, 0xCBEF, 0xE638, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xE659, 0xD430, 0xDC92, 0xDC92, 0xDC92, 0xDCB2, 0xDCB2, 0xDCB2, 0xDCD3, 0xDCD3, 0xDCD3, 0xE514, 0xD410, 0xAB0C, 0xF7FF, // 0x00C0 (192) +0xFFFF, 0xABCF, 0x9165, 0xC3EF, 0xBB8E, 0xBBAE, 0xC3AE, 0xC3CF, 0xC3CF, 0xCBCF, 0xCBEF, 0xCC10, 0xCC10, 0xCBAE, 0xEE9A, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xF6DB, 0xD410, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xDC71, 0xE492, 0xE492, 0xE492, 0xE4F3, 0xCB2C, 0xA249, 0xF7FF, // 0x00E0 (224) +0xFFFF, 0xABCF, 0x88C3, 0xC3AE, 0xBB4D, 0xBB6D, 0xC36D, 0xC38E, 0xC38E, 0xCBAE, 0xC36D, 0xC34D, 0xCBCF, 0xCB8E, 0xEE59, 0xFFFF, // 0x00F0 (240) +0xFFFF, 0xF6BA, 0xDBCF, 0xD3CF, 0xCBAE, 0xD3CF, 0xE430, 0xE430, 0xE451, 0xE451, 0xE451, 0xE451, 0xECD3, 0xCAAA, 0xA208, 0xF7FF, // 0x0100 (256) +0xFFFF, 0xABCF, 0x8061, 0xBB6D, 0xBB2C, 0xBB2C, 0xC34D, 0xC34D, 0xCB4D, 0xBB0C, 0xC492, 0xCD14, 0xC38E, 0xCB2C, 0xEE59, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xF6BA, 0xD36D, 0xD575, 0xE6DB, 0xDDB6, 0xD3AE, 0xE3EF, 0xE410, 0xE410, 0xE430, 0xE410, 0xECB2, 0xC986, 0xA208, 0xF7FF, // 0x0120 (288) +0xFFFF, 0xB3EF, 0x8041, 0xBB0C, 0xBAEB, 0xBAEB, 0xC30C, 0xC30C, 0xBACB, 0xD5B6, 0xFFFF, 0xFFFF, 0xEE79, 0xCACB, 0xEE59, 0xFFFF, // 0x0130 (304) +0xFFFF, 0xF679, 0xDBEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEEBA, 0xD3CF, 0xE3AE, 0xE3EF, 0xE3CF, 0xEC10, 0xEB6D, 0xC000, 0xA249, 0xF7FF, // 0x0140 (320) +0xFFFF, 0xB3EF, 0x8020, 0xBACB, 0xBAAA, 0xBAAA, 0xC2EB, 0xBA8A, 0xD596, 0xFFFF, 0xFFDF, 0xFFFF, 0xF73C, 0xCAAA, 0xEE38, 0xFFFF, // 0x0150 (336) +0xFFFF, 0xF679, 0xDB4D, 0xFF7D, 0xFFFF, 0xFFDF, 0xFFFF, 0xEEDB, 0xDB6D, 0xEB8E, 0xEBAE, 0xEB8E, 0xE0A2, 0xC800, 0xAA49, 0xF7FF, // 0x0160 (352) +0xFFFF, 0xB3EF, 0x8000, 0xB28A, 0xBA69, 0xBA8A, 0xBA49, 0xCC30, 0xFFFF, 0xFFDF, 0xFFFF, 0xFF5D, 0xDBCF, 0xCA69, 0xEE18, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xF679, 0xDAAA, 0xE3AE, 0xF6BA, 0xFFFF, 0xFFDF, 0xFFFF, 0xE5D7, 0xE30C, 0xEB8E, 0xE0E3, 0xE000, 0xC800, 0xAA49, 0xF7FF, // 0x0180 (384) +0xFFFF, 0xB3EF, 0x8800, 0xB249, 0xBA49, 0xBA49, 0xBA49, 0xEF1C, 0xFFFF, 0xFFFF, 0xFF7D, 0xD32C, 0xCA69, 0xD249, 0xEDF7, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xF659, 0xDAAA, 0xE2CB, 0xE2EB, 0xFEBA, 0xFFFF, 0xFFDF, 0xFFDF, 0xE3CF, 0xE103, 0xE000, 0xE081, 0xD000, 0xAA69, 0xF7FF, // 0x01A0 (416) +0xFFFF, 0xB3EF, 0x8800, 0xB228, 0xBA08, 0xB9A6, 0xCBAE, 0xFFFF, 0xFFDF, 0xFFFF, 0xDC30, 0xC9E7, 0xD28A, 0xCA08, 0xF618, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xF679, 0xDA49, 0xE2CB, 0xE28A, 0xEB6D, 0xFFBE, 0xFFDF, 0xFFFF, 0xEC92, 0xE000, 0xE0A2, 0xE0C2, 0xD040, 0xAA89, 0xF7FF, // 0x01C0 (448) +0xFFFF, 0xB3EF, 0x8800, 0xB1E7, 0xB9E7, 0xB165, 0xDD55, 0xFFFF, 0xFFFF, 0xF71C, 0xCA08, 0xCA08, 0xD228, 0xD1E7, 0xE430, 0xFFDF, // 0x01D0 (464) +0xFFDF, 0xEC51, 0xDA08, 0xE28A, 0xE28A, 0xE228, 0xF618, 0xFFFF, 0xFFFF, 0xF679, 0xE081, 0xE0C2, 0xE903, 0xD081, 0xAA89, 0xF7FF, // 0x01E0 (480) +0xFFFF, 0xBBEF, 0x9000, 0xB1A6, 0xB986, 0xB145, 0xEE38, 0xFFFF, 0xFFFF, 0xED96, 0xC165, 0xC9E7, 0xD1E7, 0xD1E7, 0xD1C7, 0xDACB, // 0x01F0 (496) +0xE2EB, 0xD9E7, 0xE228, 0xE228, 0xEA69, 0xE9E7, 0xF40F, 0xFFFF, 0xFFFF, 0xFF5D, 0xE144, 0xE8E2, 0xE943, 0xD8C1, 0xAA8A, 0xF7FF, // 0x0200 (512) +0xFFFF, 0xBC10, 0x9000, 0xB165, 0xB145, 0xB924, 0xEE9A, 0xFFFF, 0xFFFF, 0xE514, 0xC124, 0xC9A6, 0xD1A6, 0xD1A6, 0xD1C7, 0xD9A6, // 0x0210 (528) +0xD9A6, 0xE1E7, 0xE208, 0xE208, 0xE9A6, 0xE041, 0xEA8A, 0xFFFF, 0xFFFF, 0xFF9E, 0xE9C6, 0xE902, 0xE984, 0xD902, 0xAAAA, 0xF7FF, // 0x0220 (544) +0xFFFF, 0xC410, 0x9000, 0xB124, 0xB124, 0xB0C3, 0xEE18, 0xFFFF, 0xFFFF, 0xE575, 0xC0E3, 0xC986, 0xD165, 0xD165, 0xD986, 0xD9A6, // 0x0230 (560) +0xD9A6, 0xE1A6, 0xE165, 0xE082, 0xE020, 0xE000, 0xEB4C, 0xFFFF, 0xFFFF, 0xFF7D, 0xE9A5, 0xE943, 0xE9A5, 0xD923, 0xAAAA, 0xF7FF, // 0x0240 (576) +0xFFFF, 0xC410, 0x9800, 0xB0E3, 0xB0E3, 0xB061, 0xE4F3, 0xFFFF, 0xFFFF, 0xF6FB, 0xC104, 0xC924, 0xD145, 0xD145, 0xD945, 0xD945, // 0x0250 (592) +0xD8E3, 0xD861, 0xD800, 0xE000, 0xE061, 0xE000, 0xED34, 0xFFFF, 0xFFFF, 0xFE9A, 0xE923, 0xE984, 0xE9C5, 0xE163, 0xAAAA, 0xF7FF, // 0x0260 (608) +0xFFFF, 0xC410, 0xA000, 0xB0A2, 0xB0A2, 0xB041, 0xCACB, 0xFFFF, 0xFFDF, 0xFFFF, 0xD34D, 0xC841, 0xD104, 0xD0A2, 0xD061, 0xD000, // 0x0270 (624) +0xD800, 0xD800, 0xE000, 0xE041, 0xE000, 0xD965, 0xFF9E, 0xFFDF, 0xFFFF, 0xF4D2, 0xE8E2, 0xE9A5, 0xE9E5, 0xE183, 0xAAAA, 0xF7FF, // 0x0280 (640) +0xFFFF, 0xCC10, 0xA000, 0xA861, 0xB061, 0xB061, 0xB882, 0xF6DB, 0xFFFF, 0xFFDF, 0xF75D, 0xC124, 0xC800, 0xD000, 0xD000, 0xD800, // 0x0290 (656) +0xD800, 0xE000, 0xE020, 0xE000, 0xD861, 0xF638, 0xFFFF, 0xFFDF, 0xFFDF, 0xEA68, 0xE943, 0xE9C5, 0xEA06, 0xE1A4, 0xB2CA, 0xF7FF, // 0x02A0 (672) +0xFFFF, 0xCC10, 0xA000, 0xA820, 0xB000, 0xB000, 0xB000, 0xCA49, 0xFFFF, 0xFFDF, 0xFFFF, 0xF71C, 0xCA08, 0xC800, 0xD000, 0xD800, // 0x02B0 (688) +0xD800, 0xD800, 0xD800, 0xD944, 0xEE18, 0xFFFF, 0xFFBE, 0xFFFF, 0xF4F2, 0xE902, 0xE9A5, 0xE9C5, 0xEA06, 0xE9A4, 0xB2CA, 0xF7FF, // 0x02C0 (704) +0xFFFF, 0xD410, 0xA800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xDC10, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xED96, 0xDAEB, 0xD1A6, // 0x02D0 (720) +0xD965, 0xDA69, 0xECD3, 0xFF9E, 0xFFFF, 0xFFBE, 0xFFFF, 0xFE17, 0xE923, 0xE964, 0xE9A5, 0xE9C5, 0xEA26, 0xE9C4, 0xBACA, 0xF7FF, // 0x02E0 (736) +0xF7FF, 0xD410, 0xA800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xB800, 0xE3EF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02F0 (752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF5B6, 0xE923, 0xE923, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xE9C5, 0xBACA, 0xF7FF, // 0x0300 (768) +0xF7FF, 0xDC10, 0xB000, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xD228, 0xF638, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0310 (784) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFEFB, 0xF3AE, 0xE0C1, 0xE903, 0xE964, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xE9E5, 0xC2CA, 0xF7DF, // 0x0320 (800) +0xF7FF, 0xDC51, 0xB800, 0xA800, 0xB000, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xC000, 0xC800, 0xD9E7, 0xEC30, 0xF5D7, 0xFE9A, // 0x0330 (816) +0xFEBA, 0xF618, 0xF4D3, 0xEACB, 0xE0E2, 0xE040, 0xE903, 0xE943, 0xE943, 0xE984, 0xE9A5, 0xE9E5, 0xEA26, 0xEA05, 0xC30C, 0xF7DF, // 0x0340 (832) +0xFFFF, 0xD575, 0xD104, 0xA820, 0xB000, 0xB800, 0xB800, 0xC000, 0xC000, 0xC000, 0xC820, 0xC800, 0xD000, 0xD000, 0xD800, 0xD800, // 0x0350 (848) +0xE000, 0xE000, 0xE000, 0xE000, 0xE0A1, 0xE0E3, 0xE903, 0xE943, 0xE964, 0xE984, 0xE9C5, 0xE9C5, 0xF226, 0xE227, 0xBC10, 0xF7FF, // 0x0360 (864) +0xFFFF, 0xDF3C, 0xCAAA, 0xD186, 0xB082, 0xB000, 0xB800, 0xB800, 0xB800, 0xC000, 0xC000, 0xC800, 0xC800, 0xD000, 0xD000, 0xD800, // 0x0370 (880) +0xD800, 0xE000, 0xE020, 0xE040, 0xE061, 0xE0A1, 0xE0C2, 0xE102, 0xE123, 0xE943, 0xE984, 0xEA26, 0xFB0A, 0xBA08, 0xCE38, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFDF, 0xBDD7, 0xCA69, 0xE248, 0xD207, 0xD1C6, 0xD1C6, 0xD9C7, 0xD9C7, 0xE1C7, 0xE1C7, 0xE1C7, 0xE9C7, 0xE9C7, 0xE9C7, // 0x0390 (912) +0xF1C6, 0xF1C7, 0xF1E7, 0xF207, 0xF228, 0xF248, 0xF269, 0xF289, 0xF2A9, 0xF2CA, 0xFB0A, 0xF2EA, 0xC207, 0xACB3, 0xF7BE, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xF7BE, 0xBDF7, 0xAB8E, 0xC2EB, 0xC2EB, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xC30B, 0xCB0B, 0xCAEB, // 0x03B0 (944) +0xCAEB, 0xCACA, 0xCACA, 0xCAAA, 0xCAAA, 0xCA8A, 0xCA69, 0xC269, 0xC269, 0xC289, 0xBA69, 0xA2CB, 0xAD34, 0xEF7D, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xDF3C, 0xBE39, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, // 0x03D0 (976) +0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xB5F7, 0xBE38, 0xD71C, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon2.c b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon2.c new file mode 100644 index 0000000..9b843cc --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/icon2.c @@ -0,0 +1,72 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: video.png +// Time generated: 14.10.2010 21:53:17 +// Dimensions : 32x32 pixels +// Size : 2 048 Bytes + +const unsigned short icon2[0x400] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE71C, 0xB5B6, 0x94B2, 0x8C71, // 0x0030 (48) +0x9492, 0xA534, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x9CF3, 0x73AE, 0x6B6D, 0x73AE, 0x7BCF, // 0x0050 (80) +0x7BEF, 0x7BCF, 0x7BEF, 0xA534, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0060 (96) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC638, 0x7BCF, 0x6B6D, 0x738E, 0x7BCF, 0x8C71, 0x9492, // 0x0070 (112) +0x9492, 0x9492, 0x9492, 0x8C51, 0x8C71, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x738E, 0x738E, 0x73AE, 0x6B4D, 0x8410, 0x9CF3, 0x9CF3, // 0x0090 (144) +0x9CF3, 0x9CF3, 0x9CF3, 0x9CF3, 0x94B2, 0x7BEF, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00A0 (160) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x738E, 0x7BEF, 0x8410, 0x632C, 0x4A69, 0x9492, 0xAD75, 0xAD55, // 0x00B0 (176) +0xAD55, 0xAD55, 0xAD55, 0xA534, 0xAD55, 0x9492, 0x8430, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDF7, 0x7BCF, 0x8430, 0x7BCF, 0x6B4D, 0x528A, 0x6B6D, 0xB5B6, 0xB5B6, 0xB5B6, // 0x00D0 (208) +0xB5B6, 0xB596, 0xB596, 0xAD75, 0xAD75, 0xAD55, 0x8410, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00E0 (224) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x7BEF, 0x9CD3, 0xA514, 0x5AEB, 0x630C, 0x6B4D, 0x9492, 0xC638, 0xC618, 0xC618, // 0x00F0 (240) +0xBDF7, 0xBDF7, 0xC618, 0xB5B6, 0xB5B6, 0xB596, 0x9492, 0x8C51, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x8C71, 0x94B2, 0xAD55, 0xB5B6, 0x738E, 0x6B4D, 0x632C, 0xB596, 0xD69A, 0xCE59, 0xCE59, // 0x0110 (272) +0xCE79, 0xCE59, 0x6B6D, 0x9492, 0xB5B6, 0xBDF7, 0x9CF3, 0x8430, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0120 (288) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB5B6, 0x8C51, 0xAD55, 0xB5B6, 0xCE79, 0x8C51, 0x630C, 0x8C51, 0xCE79, 0xD6BA, 0xD69A, 0xDEDB, // 0x0130 (304) +0xBDD7, 0x8C51, 0x4228, 0x2965, 0xAD55, 0xC638, 0xA534, 0x8430, 0xB5B6, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x8C51, 0xA514, 0xB5B6, 0xC618, 0xD6BA, 0xB5B6, 0xB596, 0xE71C, 0xDEFB, 0xDEFB, 0xE71C, 0xAD55, // 0x0150 (336) +0x738E, 0x7BEF, 0x5AEB, 0x2945, 0xC638, 0xCE59, 0xA534, 0x9492, 0xA534, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0160 (352) +0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x94B2, 0xB5B6, 0xC618, 0xCE79, 0xD6BA, 0xE73C, 0xEF7D, 0xE73C, 0xEF5D, 0xE73C, 0x9CF3, 0x738E, // 0x0170 (368) +0x7BCF, 0x8430, 0x6B6D, 0x2965, 0xB596, 0xD69A, 0xAD55, 0x94B2, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xF79E, 0x9492, 0x9CF3, 0xB5B6, 0xD69A, 0xDEFB, 0xE71C, 0xE73C, 0x6B6D, 0x528A, 0xDEDB, 0xEF5D, 0x7BEF, 0x8430, // 0x0190 (400) +0x7BEF, 0x8C51, 0x7BCF, 0x2104, 0xB596, 0xD6BA, 0xAD55, 0x9CD3, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0xE6FC, // 0x01A0 (416) +0xFFDF, 0xFFFF, 0xCE59, 0x9492, 0x9492, 0x6B4D, 0x7BCF, 0xBDD7, 0xF7BE, 0xA514, 0x4A49, 0x528A, 0xC638, 0xEF7D, 0x7BEF, 0x7BEF, // 0x01B0 (432) +0x7BEF, 0x8430, 0x5AEB, 0x10A2, 0xC618, 0xD69A, 0xAD55, 0x94B2, 0xA514, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE5A, 0x8BF2, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xAD55, 0x94B2, 0x8C51, 0x5AEB, 0x632C, 0xBDD7, 0xE73C, 0x630C, 0x632C, 0xBDF7, 0xFFDF, 0xEF5D, 0xBDD7, 0xB5B6, // 0x01D0 (464) +0xAD75, 0xAD75, 0x8C51, 0x738E, 0xD69A, 0xCE59, 0xB596, 0x8C51, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xCE39, 0x7350, // 0x01E0 (480) +0xFFFF, 0xF79E, 0x94B2, 0x94B2, 0x7BCF, 0x5AEB, 0x738E, 0xD6BA, 0xD69A, 0x2104, 0x6B6D, 0xF79E, 0xF79E, 0xF79E, 0xF7BE, 0xF79E, // 0x01F0 (496) +0xEF7D, 0xEF5D, 0xE73C, 0xE73C, 0xDEFB, 0xBDF7, 0xBDF7, 0x7BEF, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD36, 0x7350, // 0x0200 (512) +0xFFFF, 0xDEDB, 0x8C51, 0x94B2, 0x738E, 0x632C, 0x73AE, 0xCE79, 0xF7BE, 0x7BEF, 0xA514, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0210 (528) +0xE73C, 0xE71C, 0xDEFB, 0xDEDB, 0xDEDB, 0xBDD7, 0xBDF7, 0x73AE, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x9C75, 0x736F, // 0x0220 (544) +0xFFFF, 0xCE59, 0x8430, 0x94B2, 0x6B4D, 0x6B4D, 0xB596, 0xE73C, 0xEF7D, 0xFFFF, 0xFFFF, 0xF7BE, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0230 (560) +0xE73C, 0xE73C, 0xDEFB, 0xDEFB, 0xD6BA, 0xC618, 0xAD55, 0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x6AEF, 0x9492, // 0x0240 (576) +0xFFFF, 0xBDF7, 0x8430, 0x8C71, 0x6B6D, 0xB596, 0xE71C, 0xE73C, 0xEF5D, 0xE73C, 0xBDF7, 0xCE59, 0xF7BE, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0250 (592) +0xE73C, 0xE71C, 0xDEFB, 0xDEFB, 0xC638, 0xD69A, 0x8410, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x9474, 0x6B0E, 0xCE59, // 0x0260 (608) +0xFFFF, 0xB5B6, 0x8410, 0x9492, 0xBDD7, 0xD6BA, 0xD6BA, 0xE71C, 0xE73C, 0x8C71, 0x6B4D, 0xA514, 0xF7BE, 0xEF5D, 0xEF5D, 0xE73C, // 0x0270 (624) +0xE73C, 0xE71C, 0xDEFB, 0xDEDB, 0xCE59, 0xC618, 0x7BCF, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC5F9, 0x7B51, 0x7BEF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xB596, 0x8C71, 0xAD75, 0xBDF7, 0xCE59, 0xD69A, 0xE71C, 0xCE79, 0x8410, 0x8410, 0x9CD3, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, // 0x0290 (656) +0xE71C, 0xDEFB, 0xDEFB, 0xCE59, 0xDEDB, 0x8C71, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEBB, 0x83B2, 0x630C, 0xE73C, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xB5B6, 0x9492, 0xAD55, 0xBDD7, 0xC638, 0xCE79, 0xDEFB, 0xB596, 0x73AE, 0x8410, 0x8410, 0xDEDB, 0xE73C, 0xE71C, 0xE71C, // 0x02B0 (688) +0xDEFB, 0xDEFB, 0xD6BA, 0xCE59, 0xC618, 0x738E, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x8C14, 0x5ACC, 0xC658, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xC638, 0x8C51, 0xA534, 0xB5B6, 0xBDF7, 0xCE59, 0xD6BA, 0x94B2, 0x738E, 0x8410, 0x8430, 0xCE59, 0xE73C, 0xDEFB, 0xDEFB, // 0x02D0 (720) +0xDEDB, 0xDEFB, 0xBDF7, 0xDEDB, 0x73AE, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x8BD2, 0x5ACC, 0xBDD6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02E0 (736) +0xFFFF, 0xDEDB, 0x8C51, 0xA514, 0xAD75, 0xBDD7, 0xC638, 0xC618, 0x73AE, 0x7BCF, 0x8410, 0x5ACB, 0x8C51, 0xE73C, 0xDEDB, 0xD6BA, // 0x02F0 (752) +0xDEFB, 0xBDD7, 0xD69A, 0x8C71, 0x8C51, 0xFFFF, 0xFFFF, 0xFFDE, 0xCE5A, 0x7B71, 0x62ED, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xF7BE, 0x94B2, 0x94B2, 0xA534, 0xB596, 0xBDF7, 0xB596, 0x6B6D, 0x4208, 0x2945, 0x18C3, 0x6B6D, 0xDEFB, 0xD69A, 0xDEDB, // 0x0310 (784) +0xB5B6, 0xC618, 0x9CF3, 0x6B4D, 0xFFDE, 0xFFFF, 0xEF5D, 0xAD37, 0x62EE, 0x6B4D, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0320 (800) +0xFFDF, 0xFFFF, 0xBDF7, 0x8C51, 0xA514, 0xAD55, 0xB596, 0xBDD7, 0xA514, 0x738E, 0xA514, 0xB5B6, 0xCE59, 0xD69A, 0xDEDB, 0xB596, // 0x0330 (816) +0xBDF7, 0xA534, 0x6B4C, 0xEF5D, 0xF79E, 0xBDB8, 0x7370, 0x5AAC, 0x8C71, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xF79E, 0x94B2, 0x94B2, 0xA534, 0xAD55, 0xB5B6, 0xA534, 0xBDD7, 0xD69A, 0xCE59, 0xCE79, 0xCE59, 0xA534, 0x8430, // 0x0350 (848) +0x738E, 0x3186, 0x7BB0, 0x8C33, 0x7370, 0x62ED, 0x8410, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0360 (864) +0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x8C71, 0x9CD3, 0xAD55, 0xB596, 0xBDD7, 0xBDD7, 0xBDF7, 0xC618, 0xB5B6, 0xA534, 0xA534, 0x632C, // 0x0370 (880) +0x6B6D, 0xB5B6, 0xAD76, 0xAD76, 0xBE17, 0xE71B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x94B2, 0x8C51, 0x94B2, 0xA534, 0xAD55, 0xAD55, 0x9CD3, 0x8C71, 0x73AE, 0x632C, 0xA534, // 0x0390 (912) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xCE59, 0xA514, 0x8430, 0x7BCF, 0x738E, 0x73AE, 0x8410, 0xA534, 0xEF7D, 0xFFFF, // 0x03B0 (944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xE73C, 0xE71C, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03E0 (992) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +}; diff --git a/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/tux.c b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/tux.c new file mode 100644 index 0000000..7fefd80 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Bitmap_128x128/tux.c @@ -0,0 +1,264 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: tux_64x64.png +// Time generated: 14.10.2010 21:56:38 +// Dimensions : 64x64 pixels +// Size : 8 192 Bytes + +const unsigned short tux[0x1000] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE79, 0x9CF3, 0x7BCF, 0x738E, 0x738E, // 0x0020 (32) +0x6B6D, 0x94B2, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0030 (48) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0050 (80) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE79, 0x6B4D, 0x5ACB, 0x8410, 0x9CF3, 0x9CF3, 0x9CF3, // 0x0060 (96) +0x9CD3, 0x73AE, 0x4208, 0x5ACB, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0070 (112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0090 (144) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA514, 0x3186, 0x8C51, 0xBDF7, 0xC618, 0xBDF7, 0xBDF7, 0xBDF7, // 0x00A0 (160) +0xBDF7, 0xC618, 0xBDD7, 0x738E, 0x18C3, 0x8C51, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00D0 (208) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xBDD7, 0x10A2, 0x8C71, 0x9CF3, 0x8C71, 0x8C71, 0x8C71, 0x8C71, 0x8C71, // 0x00E0 (224) +0x8C71, 0x8C51, 0x8C51, 0x9CF3, 0x73AE, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00F0 (240) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0110 (272) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x2945, 0x31A6, 0x7BCF, 0x6B4D, 0x6B6D, 0x6B6D, 0x6B6D, 0x6B6D, 0x6B6D, // 0x0120 (288) +0x6B6D, 0x6B6D, 0x6B6D, 0x6B4D, 0x73AE, 0x2124, 0x0000, 0xAD55, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0130 (304) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0150 (336) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x0000, 0x31A6, 0x52AA, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, // 0x0160 (352) +0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x528A, 0x2104, 0x0000, 0x2965, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0170 (368) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0190 (400) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8C71, 0x0000, 0x1082, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, // 0x01A0 (416) +0x3186, 0x3186, 0x3186, 0x3186, 0x2965, 0x0020, 0x0000, 0x0000, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01B0 (432) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01D0 (464) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x630C, 0x0000, 0x0000, 0x0861, 0x18C3, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x18C3, // 0x01E0 (480) +0x1082, 0x0841, 0x1082, 0x10A2, 0x0020, 0x0000, 0x0000, 0x0000, 0x528A, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01F0 (496) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0210 (528) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x4A49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0220 (544) +0x0861, 0x3186, 0x18C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0230 (560) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0250 (592) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39C7, 0x0000, 0x3186, 0xAD75, 0x8C51, 0x0841, 0x0000, 0x0000, 0x0000, 0x4208, // 0x0260 (608) +0xD6BA, 0xFFDF, 0xE71C, 0x630C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0270 (624) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0290 (656) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39C7, 0x0000, 0xCE59, 0xFFFF, 0xFFFF, 0x94B2, 0x0000, 0x0000, 0x10A2, 0xE73C, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000, 0x94B2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02B0 (688) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02D0 (720) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2965, 0x18E3, 0xDEDB, 0x7BCF, 0xAD75, 0xEF5D, 0x2944, 0x0000, 0x5ACA, 0xFFFF, // 0x02E0 (736) +0xAD55, 0x94B2, 0xAD55, 0xF7BE, 0x8410, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02F0 (752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0310 (784) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39E7, 0x2945, 0xA514, 0x9CF3, 0x8C71, 0xD6BB, 0x39C9, 0x0000, 0x632E, 0xF7DF, // 0x0320 (800) +0x7BEF, 0xAD54, 0x7BEF, 0xBDF7, 0xB596, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C71, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0330 (816) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0350 (848) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4A49, 0x18C3, 0x9492, 0x39E7, 0x3187, 0xA48F, 0x8323, 0x5A00, 0x93A6, 0xCDD5, // 0x0360 (864) +0x4209, 0x4249, 0x2965, 0x9CD2, 0xB575, 0x0000, 0x0000, 0x0000, 0x0000, 0x9492, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0370 (880) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0390 (912) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x5ACB, 0x0000, 0x9D14, 0x2905, 0x6A40, 0xE643, 0xFFAE, 0xFFF3, 0xFF70, 0xDD86, // 0x03A0 (928) +0x7240, 0x1840, 0x18C3, 0xC65A, 0x73CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03B0 (944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03D0 (976) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x738E, 0x0000, 0x5A6A, 0xD566, 0xFF66, 0xFFF8, 0xFFFD, 0xFFDC, 0xFFFD, 0xFFFA, // 0x03E0 (992) +0xFF0E, 0xE566, 0xC464, 0xC4CC, 0x2103, 0x0000, 0x0000, 0x0000, 0x0000, 0x6B6D, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03F0 (1008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0410 (1040) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BEF, 0x0800, 0xB440, 0xFFC6, 0xFFF3, 0xFFB4, 0xFFB2, 0xFF92, 0xFF72, 0xFF53, // 0x0420 (1056) +0xFF55, 0xFF75, 0xFEF0, 0xF542, 0x8240, 0x0000, 0x0000, 0x0000, 0x0000, 0x4228, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0430 (1072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0440 (1088) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0450 (1104) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8432, 0x4140, 0xFFE2, 0xFFEB, 0xFFAC, 0xFF8B, 0xFF4C, 0xFF2C, 0xFEEC, 0xFECB, // 0x0460 (1120) +0xFE6A, 0xFE08, 0xFDA7, 0xFDC3, 0xA320, 0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0xD69A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0470 (1136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0480 (1152) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0490 (1168) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9D14, 0x28A0, 0xF6E0, 0xFFE1, 0xFF43, 0xFF04, 0xFEC4, 0xFE84, 0xFE23, 0xFDE1, // 0x04A0 (1184) +0xFD60, 0xFD20, 0xFD20, 0xFD20, 0x7241, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CF3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04B0 (1200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04C0 (1216) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04D0 (1232) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xB5B6, 0x0000, 0xC4A9, 0xFEC0, 0xFF00, 0xFEA0, 0xFE40, 0xFE00, 0xFDA0, 0xFD60, // 0x04E0 (1248) +0xFD40, 0xFD20, 0xEC80, 0xDCC7, 0x8C0F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x04F0 (1264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0500 (1280) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0510 (1296) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xAD75, 0x0000, 0xD69B, 0xF631, 0xF5C0, 0xFE80, 0xFE00, 0xFDC0, 0xFD60, 0xFD40, // 0x0520 (1312) +0xFCC0, 0xDC86, 0xCD93, 0xE73D, 0xE71C, 0x0861, 0x0000, 0x0000, 0x0000, 0x0000, 0x0861, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0530 (1328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0540 (1344) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0550 (1360) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x632C, 0x0000, 0xD6BA, 0xFFFF, 0xF5F1, 0xFD40, 0xFD80, 0xFD20, 0xFCE0, 0xECA3, // 0x0560 (1376) +0xDD6F, 0xE6FC, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5ACB, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0570 (1392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0580 (1408) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0590 (1424) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xDEDB, 0x0861, 0x0000, 0xD69A, 0xFFFF, 0xFFFF, 0xFED8, 0xF631, 0xF610, 0xE5F2, 0xE6B9, // 0x05A0 (1440) +0xF7BF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xE71C, 0x10A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0xB5B6, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05B0 (1456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05C0 (1472) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x05D0 (1488) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x39E7, 0x0000, 0x4228, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7FF, 0xF7DF, 0xFFFF, // 0x05E0 (1504) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3186, 0xEF7D, 0xFFFF, 0xFFFF, // 0x05F0 (1520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0600 (1536) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0610 (1552) +0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x738E, 0x0000, 0x18C3, 0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0620 (1568) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFFF, 0xCE59, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6B4D, 0xFFFF, 0xFFFF, // 0x0630 (1584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0640 (1600) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0650 (1616) +0xFFFF, 0xFFDF, 0xFFFF, 0xA514, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0660 (1632) +0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0x2965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xAD55, 0xFFFF, // 0x0670 (1648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0680 (1664) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0690 (1680) +0xFFDF, 0xFFFF, 0xD69A, 0x0861, 0x0000, 0x2945, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06A0 (1696) +0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xFFFF, 0x7BCF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C3, 0xD6BA, // 0x06B0 (1712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06C0 (1728) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06D0 (1744) +0xFFFF, 0xFFDF, 0x39C7, 0x0000, 0x0000, 0x8430, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x06E0 (1760) +0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xFFFF, 0xCE79, 0x0841, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4228, // 0x06F0 (1776) +0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0700 (1792) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x0710 (1808) +0xFFFF, 0x94B2, 0x0000, 0x0020, 0x0020, 0xCE79, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, // 0x0720 (1824) +0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xFFDF, 0x4A69, 0x0000, 0x0841, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, // 0x0730 (1840) +0x8C71, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0740 (1856) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0750 (1872) +0xEF7D, 0x2104, 0x0020, 0x0000, 0x3186, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, // 0x0760 (1888) +0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xFFFF, 0xB5B6, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, // 0x0770 (1904) +0x10A2, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0780 (1920) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x0790 (1936) +0x8C71, 0x0000, 0x0861, 0x0000, 0x7BCF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x07A0 (1952) +0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xFFDF, 0x528A, 0x0000, 0x0841, 0x0020, 0x0020, 0x0020, 0x0020, // 0x07B0 (1968) +0x0000, 0x630C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x07C0 (1984) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, // 0x07D0 (2000) +0x3186, 0x0000, 0x0841, 0x10A2, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, // 0x07E0 (2016) +0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF5D, 0xF7BE, 0xBDD7, 0x0841, 0x0861, 0x0841, 0x0841, 0x0841, 0x0020, // 0x07F0 (2032) +0x0020, 0x1082, 0xC638, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0800 (2048) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDD7, // 0x0810 (2064) +0x0020, 0x1082, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, // 0x0820 (2080) +0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF7D, 0x4208, 0x0020, 0x0861, 0x0861, 0x0841, 0x0841, // 0x0830 (2096) +0x0841, 0x0000, 0x630C, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0840 (2112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x6B4D, // 0x0850 (2128) +0x0000, 0x0861, 0x2104, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, // 0x0860 (2144) +0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xE73C, 0xF7BE, 0x8430, 0x0000, 0x1082, 0x0861, 0x0861, 0x0861, // 0x0870 (2160) +0x0861, 0x0020, 0x18C3, 0xCE79, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0880 (2176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x2124, // 0x0890 (2192) +0x0861, 0x0020, 0x8410, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, // 0x08A0 (2208) +0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xEF7D, 0xB5B6, 0x0861, 0x1082, 0x1082, 0x0861, 0x0861, // 0x08B0 (2224) +0x0861, 0x0861, 0x0000, 0x8430, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x08C0 (2240) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xA514, 0x0020, // 0x08D0 (2256) +0x10A2, 0x1082, 0xD69A, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x08E0 (2272) +0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xEF5D, 0xCE79, 0x2124, 0x1082, 0x10A2, 0x1082, 0x1082, // 0x08F0 (2288) +0x0861, 0x1082, 0x0000, 0x4208, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0900 (2304) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x4208, 0x0861, // 0x0910 (2320) +0x1082, 0x31A6, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, // 0x0920 (2336) +0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEDB, 0x39C7, 0x1082, 0x10A2, 0x10A2, 0x1082, // 0x0930 (2352) +0x1082, 0x1082, 0x0841, 0x18C3, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0940 (2368) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA534, 0x0841, 0x18C3, // 0x0950 (2384) +0x0841, 0x630C, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, // 0x0960 (2400) +0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xDEFB, 0xE73C, 0x4A49, 0x0861, 0x18C3, 0x10A2, 0x10A2, // 0x0970 (2416) +0x10A2, 0x1082, 0x1082, 0x0841, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0980 (2432) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0x3186, 0x1082, 0x18E3, // 0x0990 (2448) +0x0861, 0x94B2, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, // 0x09A0 (2464) +0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEDB, 0xE73C, 0x4A69, 0x1082, 0x18E3, 0x18C3, 0x10A2, // 0x09B0 (2480) +0x10A2, 0x10A2, 0x10A2, 0x0020, 0x73AE, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x09C0 (2496) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0841, 0x18E3, 0x18E3, // 0x09D0 (2512) +0x0861, 0xAD75, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, // 0x09E0 (2528) +0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEDB, 0xE73C, 0x52AA, 0x10A2, 0x2104, 0x18E3, 0x18C3, // 0x09F0 (2544) +0x18C3, 0x18C3, 0x10A2, 0x0841, 0x630C, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A00 (2560) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0861, 0x18E4, 0x18E4, // 0x0A10 (2576) +0x1082, 0xC638, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, // 0x0A20 (2592) +0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xD6BA, 0xE71C, 0x6B4D, 0x10A2, 0x18C3, 0x18C3, 0x10A2, // 0x0A30 (2608) +0x10A2, 0x10A2, 0x18C3, 0x0861, 0x5AEB, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A40 (2624) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8410, 0x0862, 0x3143, 0x2924, // 0x0A50 (2640) +0x0882, 0xBDD7, 0xFFFF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, // 0x0A60 (2656) +0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xE73C, 0x630C, 0x2103, 0x4A69, 0x632C, 0x6B4D, // 0x0A70 (2672) +0x528A, 0x2965, 0x18C3, 0x1081, 0x738E, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0A80 (2688) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB596, 0x7A40, 0xECA0, 0xCC00, // 0x0A90 (2704) +0x3941, 0xA535, 0xFFFF, 0xF7BE, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, // 0x0AA0 (2720) +0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEFB, 0xD6DB, 0xCE38, 0xC618, 0x4A48, 0x4A49, 0x6B6D, 0x6B4D, 0x6B4D, // 0x0AB0 (2736) +0x6B4D, 0x630C, 0x3186, 0x18E4, 0x9492, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0AC0 (2752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xC488, 0xFD41, 0xFE6D, 0xFE6A, // 0x0AD0 (2768) +0xDC60, 0x5A25, 0xB5D8, 0xFFFF, 0xF7BE, 0xF7BE, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, // 0x0AE0 (2784) +0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xD6BB, 0xBCAB, 0xD462, 0xD462, 0x49E4, 0x10C3, 0x18C3, 0x18C3, 0x18C3, // 0x0AF0 (2800) +0x18C3, 0x18E3, 0x10A3, 0x49C4, 0xB575, 0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B00 (2816) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCD70, 0xECA0, 0xFF14, 0xFF9B, 0xFF7B, // 0x0B10 (2832) +0xFECF, 0xC3A0, 0x3143, 0x9CF3, 0xFFFF, 0xF7BE, 0xF79E, 0xF79E, 0xF79E, 0xEF7D, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, // 0x0B20 (2848) +0xE73C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEFB, 0xC617, 0xDC60, 0xFD60, 0xFD20, 0x3120, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B30 (2864) +0x0000, 0x0000, 0x3900, 0xE460, 0xB46A, 0xEF9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B40 (2880) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD5F4, 0xDC20, 0xFE8E, 0xFF59, 0xFF36, 0xFF36, // 0x0B50 (2896) +0xFF59, 0xFE6B, 0xA300, 0x18E4, 0x8410, 0xFFBE, 0xF7BE, 0xEF7D, 0xF79E, 0xEF7D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, // 0x0B60 (2912) +0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEBA, 0xDEFB, 0xC5B5, 0xE4A1, 0xFEF2, 0xF716, 0x3164, 0x18E4, 0x2103, 0x1082, 0x1082, // 0x0B70 (2928) +0x0021, 0x1061, 0xD5D0, 0xFE27, 0xB3E3, 0xCE9B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0B80 (2944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF77D, 0xE697, 0xDDAF, 0xD4C8, 0xE480, 0xFE29, 0xFF36, 0xFF15, 0xFF35, 0xFF15, // 0x0B90 (2960) +0xFF15, 0xFF36, 0xFDA5, 0x6A42, 0x1905, 0x6B4C, 0xE73C, 0xFFDF, 0xEF5D, 0xEF7D, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, // 0x0BA0 (2976) +0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xDEDB, 0xBDB5, 0xE4C3, 0xFF56, 0xFFDB, 0xAD10, 0x10A2, 0x10C3, 0x18E4, 0x1082, // 0x0BB0 (2992) +0x2922, 0xC5B1, 0xFFDC, 0xFED1, 0xB3A2, 0xBE19, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0BC0 (3008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE6B8, 0xD484, 0xE4C0, 0xF584, 0xFE28, 0xFECF, 0xFF14, 0xFF13, 0xFF13, 0xFF13, 0xFF13, // 0x0BD0 (3024) +0xFF13, 0xFF14, 0xFEF0, 0xDC80, 0x41C5, 0x2945, 0x5269, 0xCE59, 0xF7BE, 0xEF5D, 0xEF5D, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, // 0x0BE0 (3040) +0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD69A, 0xD6DB, 0xBD95, 0xE4E2, 0xFF33, 0xFF36, 0xFF97, 0xDDF1, 0x8B66, 0x7AE4, 0x9BC7, // 0x0BF0 (3056) +0xEEB2, 0xFF97, 0xFF37, 0xFEF0, 0xC3E0, 0xB5B7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C00 (3072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD52B, 0xFD60, 0xFECD, 0xFF33, 0xFF13, 0xFF12, 0xFEF1, 0xFEF1, 0xFEF1, 0xFEF1, 0xFEF1, // 0x0C10 (3088) +0xFEF1, 0xFEF1, 0xFF12, 0xFE69, 0x9B41, 0x31A8, 0x31A6, 0x39E7, 0xB5B6, 0xF79E, 0xE73C, 0xE73C, 0xE73C, 0xE71C, 0xE71C, 0xDEFB, // 0x0C20 (3104) +0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD699, 0xD6BA, 0xBD94, 0xE502, 0xFF12, 0xFF15, 0xFEF4, 0xFF55, 0xFF95, 0xFF54, 0xFF95, // 0x0C30 (3120) +0xFF35, 0xFEF4, 0xFF14, 0xFF14, 0xF5A4, 0xB426, 0xE75E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C40 (3136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD54C, 0xFDA0, 0xFECE, 0xFEF0, 0xFECF, 0xFEEF, 0xFEEF, 0xFEF0, 0xFEEF, 0xFEF0, 0xFEF0, // 0x0C50 (3152) +0xFEF0, 0xFEEF, 0xFEF0, 0xFEEF, 0xF582, 0x6244, 0x39E8, 0x39C6, 0x528A, 0xE71C, 0xE73C, 0xE71C, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, // 0x0C60 (3168) +0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE9A, 0xBD94, 0xE522, 0xFF10, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, 0xFEF2, // 0x0C70 (3184) +0xFEF2, 0xFF12, 0xFEF2, 0xFEF2, 0xFF12, 0xED85, 0xBC68, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C80 (3200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD5B0, 0xF580, 0xFECB, 0xFEEE, 0xFECD, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, // 0x0C90 (3216) +0xFEEE, 0xFEEE, 0xFECD, 0xFECE, 0xFECA, 0xCC60, 0x41C7, 0x39C7, 0x4228, 0xCE79, 0xEF5D, 0xE71C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, // 0x0CA0 (3232) +0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE59, 0xCE9A, 0xBD73, 0xED42, 0xFF0F, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, // 0x0CB0 (3248) +0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFEF0, 0xFF31, 0xF628, 0xC4A7, 0xDE57, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0CC0 (3264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDE13, 0xF560, 0xFEC9, 0xFECD, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, 0xFECC, // 0x0CD0 (3280) +0xFEEC, 0xFEEC, 0xFECC, 0xFECC, 0xFEED, 0xFE44, 0x9323, 0x52CC, 0x73AE, 0xD69A, 0xE73C, 0xDEFB, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, // 0x0CE0 (3296) +0xD6BA, 0xD6BA, 0xD69A, 0xCE79, 0xCE59, 0xD69A, 0xB5D8, 0x7B28, 0xF5A2, 0xFF0F, 0xFECE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, // 0x0CF0 (3312) +0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFEEE, 0xFECD, 0xFF10, 0xFEA9, 0xCC60, 0xD615, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D00 (3328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDE55, 0xED80, 0xFEA4, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFECA, 0xFEC9, // 0x0D10 (3344) +0xFEA7, 0xFEA6, 0xFEA8, 0xFEC9, 0xFECB, 0xFEEA, 0xEDA2, 0xB4F0, 0xCE9A, 0xDEFB, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, 0xD6BA, // 0x0D20 (3360) +0xD6BA, 0xD69A, 0xCE79, 0xCE79, 0xD6BA, 0xB596, 0x4A8B, 0x72A4, 0xFE45, 0xFEEC, 0xFECC, 0xFEEC, 0xFEEC, 0xFEEC, 0xFEEC, 0xFEEC, // 0x0D30 (3376) +0xFEEC, 0xFECB, 0xFECB, 0xFEEC, 0xFEEC, 0xFEEC, 0xFECC, 0xFEA5, 0xFDE0, 0xAC8B, 0xE75E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D40 (3392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE632, 0xF5E0, 0xFE80, 0xFE82, 0xFEC7, 0xFEC8, 0xFEC8, 0xFEC8, 0xFEC7, 0xFEA4, 0xFE61, // 0x0D50 (3408) +0xFE60, 0xFE60, 0xFE60, 0xFE61, 0xFE83, 0xFEA6, 0xFEA3, 0xDD22, 0xD658, 0xE75D, 0xDEDB, 0xDEDB, 0xDEDB, 0xD6BA, 0xD6BA, 0xD69A, // 0x0D60 (3424) +0xD69A, 0xD69A, 0xD6BA, 0xCE59, 0x9492, 0x5289, 0x39E9, 0x9B84, 0xFEA3, 0xFEEB, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEEA, 0xFEC8, // 0x0D70 (3440) +0xFE84, 0xFE61, 0xFE61, 0xFEA5, 0xFEC9, 0xFEA7, 0xFEA2, 0xFE80, 0xBC41, 0x8C0F, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D80 (3456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDDCE, 0xFE40, 0xFEA0, 0xFE80, 0xFE80, 0xFEA2, 0xFEA2, 0xFEA2, 0xFEA0, 0xFE80, 0xFE80, // 0x0D90 (3472) +0xFEA0, 0xFEA0, 0xFEA0, 0xFE80, 0xFE80, 0xFE80, 0xFE80, 0xFE80, 0xCCE5, 0xD69A, 0xE73C, 0xE71C, 0xDEFB, 0xDEFB, 0xDEDB, 0xDEDB, // 0x0DA0 (3488) +0xD69A, 0xBDF7, 0x9CD3, 0x630C, 0x4228, 0x4A69, 0x422A, 0xB423, 0xFEC0, 0xFEA5, 0xFEE7, 0xFEC7, 0xFEC7, 0xFEC6, 0xFEA3, 0xFE80, // 0x0DB0 (3504) +0xFE80, 0xFE80, 0xFE80, 0xFE60, 0xFEA0, 0xFEC0, 0xEDC0, 0xA3A4, 0x732C, 0xAD96, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0DC0 (3520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE5A8, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0DD0 (3536) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xF640, 0x93A8, 0x8C72, 0xA534, 0xAD75, 0xA534, 0x9CF3, 0x8C51, // 0x0DE0 (3552) +0x738E, 0x5ACB, 0x4A49, 0x4A69, 0x528A, 0x4A8A, 0x5249, 0xD502, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC1, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, // 0x0DF0 (3568) +0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFE60, 0xC482, 0x7B09, 0x7BD0, 0xB5B7, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E00 (3584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDD8A, 0xFEC0, 0xFF20, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, // 0x0E10 (3600) +0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEC0, 0xFF20, 0xAC02, 0x4209, 0x4A69, 0x4A69, 0x4A69, 0x4A69, 0x4A69, // 0x0E20 (3616) +0x528A, 0x528A, 0x52AA, 0x52AA, 0x528A, 0x4A8A, 0x5A69, 0xE5C1, 0xFF00, 0xFEC0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, 0xFEE0, // 0x0E30 (3632) +0xFEC0, 0xFEE0, 0xFF00, 0xE561, 0x9367, 0x736E, 0x9D14, 0xD6BA, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E40 (3648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD617, 0xCCC5, 0xF620, 0xFEE0, 0xFF40, 0xFF40, 0xFF40, 0xFF20, 0xFF00, 0xFF00, 0xFF00, // 0x0E50 (3664) +0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF40, 0xB483, 0x4A8B, 0x5ACA, 0x5ACB, 0x5ACB, 0x5ACB, 0x5ACB, // 0x0E60 (3680) +0x5ACB, 0x52AA, 0x52AA, 0x52AA, 0x52AA, 0x4A8A, 0x6289, 0xEE20, 0xFF20, 0xFEE0, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFEE0, // 0x0E70 (3696) +0xFF20, 0xFEC0, 0xBC64, 0x732B, 0x8C72, 0xCE58, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E80 (3712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7E, 0xB576, 0x93EE, 0xA408, 0xC4A5, 0xDD63, 0xF641, 0xFEC0, 0xFF40, 0xFF80, 0xFF60, // 0x0E90 (3728) +0xFF40, 0xFF20, 0xFF20, 0xFF40, 0xFF40, 0xFF40, 0xFF20, 0xFF20, 0xFF80, 0xAC03, 0x4A6B, 0x5ACA, 0x5ACB, 0x5ACB, 0x5AEB, 0x5AEB, // 0x0EA0 (3744) +0x5AEB, 0x630C, 0x630C, 0x630C, 0x5AEB, 0x52CB, 0x5A69, 0xE5E1, 0xFF60, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF60, // 0x0EB0 (3760) +0xF640, 0xA3A7, 0x738F, 0xAD96, 0xE71C, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0EC0 (3776) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0xD6DB, 0xB5B8, 0x9CD4, 0x9431, 0x93EE, 0x9C0A, 0xB467, 0xD544, 0xF660, // 0x0ED0 (3792) +0xFF60, 0xFFA0, 0xFF80, 0xFF60, 0xFF40, 0xFF40, 0xFF60, 0xFFA0, 0xD521, 0x730A, 0x73CF, 0x8C71, 0x9CD3, 0x9CF3, 0xA514, 0xA534, // 0x0EE0 (3808) +0xAD55, 0xB596, 0xB5B6, 0xB596, 0xAD55, 0x9CF3, 0x83F0, 0xCD04, 0xFFA0, 0xFF40, 0xFF40, 0xFF40, 0xFF40, 0xFF40, 0xFFA0, 0xF621, // 0x0EF0 (3824) +0x8B49, 0x8431, 0xCE58, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F00 (3840) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xF79E, 0xE73C, 0xD6BB, 0xBE19, 0xA556, 0x9472, 0x9C0D, // 0x0F10 (3856) +0xB447, 0xDD82, 0xFEE0, 0xFFA0, 0xFFC0, 0xFFC0, 0xFF80, 0xC4C2, 0x730C, 0x9CF4, 0xD69A, 0xEF5D, 0xEF7D, 0xF79E, 0xF79E, 0xF7BE, // 0x0F20 (3872) +0xF7BE, 0xFFDF, 0xFFDF, 0xF7BE, 0xF7BE, 0xEF7D, 0xDF1C, 0xC530, 0xF620, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFF80, 0xE5A2, 0x834A, // 0x0F30 (3888) +0x8C93, 0xDEDA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F40 (3904) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDE, 0xEF7D, 0xD6BB, // 0x0F50 (3920) +0xAD77, 0x9452, 0x9BEB, 0xB466, 0xC524, 0xC543, 0xA3E5, 0x734D, 0xAD76, 0xEF5C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F60 (3936) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF1C, 0xACB0, 0xBCA6, 0xD544, 0xCD64, 0xCD05, 0xAC07, 0x7B6D, 0x9CF4, // 0x0F70 (3952) +0xE6FB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F80 (3968) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F90 (3984) +0xFFDE, 0xE75D, 0xC65A, 0xA536, 0x9493, 0x8C53, 0x94B4, 0xBE18, 0xEF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FA0 (4000) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xDEFC, 0xAD57, 0x9493, 0x8C73, 0x8C73, 0x94D4, 0xBE18, 0xEF5D, // 0x0FB0 (4016) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FC0 (4032) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FD0 (4048) +0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xEF5C, 0xE73C, 0xEF5C, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FE0 (4064) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xEF5C, 0xE73C, 0xEF5C, 0xEF7D, 0xFFDE, 0xFFFF, // 0x0FF0 (4080) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x1000 (4096) +}; diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.pde new file mode 100644 index 0000000..45a97e6 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_128x128_Serial/UTFT_Demo_128x128_Serial.pde @@ -0,0 +1,335 @@ +// UTFT_Demo_128x128_Serial (C)2012 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made to work on the 128x128 modules. +// Any other size displays may cause strange behaviour. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Declare an instance of the class +UTFT myGLCD(LPH9135,6,5,2,3,4); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(PORTRAIT); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + byte buf[126]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + myGLCD.setContrast(64); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0,0,127,12); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0,117,127,127); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255,0,0); + myGLCD.print("Universal TFT", CENTER, 0); + myGLCD.setBackColor(64,64,64); + myGLCD.setColor(255,255,0); + myGLCD.print("H.Karlsen", LEFT, 116); + myGLCD.print("(C)2012", RIGHT, 116); + myGLCD.setColor(0,255,0); + myGLCD.drawRect(0,13,127,116); + +// Draw crosshairs + myGLCD.setColor(0,0,255); + myGLCD.drawLine(63,14,63,115); + myGLCD.drawLine(1,63,126,63); + for (int i=3; i<128; i+=10) + myGLCD.drawLine(i, 61, i, 65); + for (int i=14; i<118; i+=10) + myGLCD.drawLine(61, i, 65, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.setBackColor(0,0,0); + myGLCD.print("Sin", 2, 14); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(sin(((i*2.85)*3.14)/180)*45)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 2, 26); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(cos(((i*2.85)*3.14)/180)*45)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 2, 38); + for (int i=1; i<126; i++) + { + myGLCD.drawPixel(i,63+(tan(((i*2.85)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + myGLCD.setColor(0,0,255); + myGLCD.drawLine(63,14,63,115); + myGLCD.drawLine(1,63,126,63); + +// Draw a moving sinewave + x=1; + for (int i=1; i<3654; i++) + { + x++; + if (x==127) + x=1; + if (i>127) + { + if ((x==63)||(buf[x-1]==63)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=63+(sin(((i*1.3)*3.14)/180)*45); + myGLCD.drawPixel(x,y); + buf[x-1]=y; +// delay(3); + } + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(10+(i*10),10+(i*10), 60+(i*10), 60+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(70-(i*10),10+(i*10), 120-(i*10), 60+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(30+(i*10),35+(i*10), 25); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + + // Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=11; i<115; i+=3) + { + myGLCD.drawLine(1, i, i-10, 115); + } + myGLCD.setColor (255,0,0); + for (int i=112; i>14; i-=3) + { + myGLCD.drawLine(126, i, i+14, 14); + } + myGLCD.setColor (0,255,255); + for (int i=115; i>14; i-=3) + { + myGLCD.drawLine(1, i, 116-i, 14); + } + myGLCD.setColor (0,255,255); + for (int i=14; i<115; i+=3) + { + myGLCD.drawLine(126, i, 140-i, 115); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(85); + y=35+random(59); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random lines + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(124); + y=15+random(101); + x2=2+random(124); + y2=15+random(101); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,126,115); + +// Draw some random pixels + for (int i=0; i<5000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(124), 15+random(101)); + } + + delay (2000); + +// Set up the "Finished"-screen + myGLCD.setContrast(0); + myGLCD.fillScr(0,0,255); + myGLCD.setColor(255,0,0); + myGLCD.fillRoundRect(2, 40, 125, 88); + + myGLCD.setColor(255,255,255); + myGLCD.setBackColor(255,0,0); + myGLCD.print("That's it!", CENTER, 46); + myGLCD.print("Restarting in a", CENTER, 66); + myGLCD.print("few seconds...", CENTER, 76); + + myGLCD.setColor(0,0,0); + myGLCD.setBackColor(0,0,255); + myGLCD.print("Runtime: (msecs)", CENTER, 108); + myGLCD.printNumI(millis(), CENTER, 118); + + myGLCD.setContrast(64); + + delay (10000); + +// Fade screen to black + for (int i=64; i>0; i--) + { + myGLCD.setContrast(i); + delay(100); + } +} + + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.pde new file mode 100644 index 0000000..365b716 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_160x128_Serial/UTFT_Demo_160x128_Serial.pde @@ -0,0 +1,328 @@ +// UTFT_Demo_160x128_Serial (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 160x128 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Usage: myGLCD(, SDA, SCL, CS, RST[, RS]); +// +// When using the DM-TFT18-101 and shield from DisplayModule you should use the following: +// UTFT myGLCD(DMTFT18101,2,3,4,6,5); +// +UTFT myGLCD(ITDB18SP,11,10,9,12,8); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[158]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 159, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 114, 159, 127); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("Universal TFT Lib.", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("H.Karlsen", LEFT, 114); + myGLCD.print("(C)2014", RIGHT, 114); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 13, 159, 113); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(79, 14, 79, 113); + myGLCD.drawLine(1, 63, 158, 63); + + for (int i=9; i<150; i+=10) + myGLCD.drawLine(i, 61, i, 65); + for (int i=19; i<110; i+=10) + myGLCD.drawLine(77, i, 81, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(sin(((i*2.27)*3.14)/180)*40)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(cos(((i*2.27)*3.14)/180)*40)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<158; i++) + { + myGLCD.drawPixel(i,63+(tan(((i*2.27)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(79, 14, 79, 113); + myGLCD.drawLine(1, 63, 158, 63); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(158*20); i++) + { + x++; + if (x==159) + x=1; + if (i>159) + { + if ((x==79)||(buf[x-1]==63)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=63+(sin(((i*2.5)*3.14)/180)*(40-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(39+(i*10), 23+(i*10), 59+(i*10), 43+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(99-(i*10), 23+(i*10), 119-(i*10), 43+(i*10)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(49+(i*10),33+(i*10), 15); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=14; i<113; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 112); + } + myGLCD.setColor (255,0,0); + for (int i=112; i>15; i-=5) + { + myGLCD.drawLine(158, i, (i*1.44)-12, 14); + } + myGLCD.setColor (0,255,255); + for (int i=112; i>15; i-=5) + { + myGLCD.drawLine(1, i, 172-(i*1.44), 14); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<112; i+=5) + { + myGLCD.drawLine(158, i, 171-(i*1.44), 112); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(116); + y=35+random(57); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(156); + y=16+random(95); + x2=2+random(156); + y2=16+random(95); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,14,158,113); + + for (int i=0; i<5000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(156), 16+random(95)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(10, 17, 149, 72); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 20); + myGLCD.print("Restarting in a", CENTER, 45); + myGLCD.print("few seconds...", CENTER, 57); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 103); + myGLCD.printNumI(millis(), CENTER, 115); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_220x176/UTFT_Demo_220x176.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_220x176/UTFT_Demo_220x176.pde new file mode 100644 index 0000000..d82506e --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_220x176/UTFT_Demo_220x176.pde @@ -0,0 +1,329 @@ +// UTFT_Demo_220x176 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 220x176 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB22,82,83,84,85); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[218]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 219, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 162, 219, 175); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("** Universal TFT Library **", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("> elec.henningkarlsen.com <", CENTER, 163); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 219, 161); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + + for (int i=9; i<210; i+=10) + myGLCD.drawLine(i, 86, i, 90); + for (int i=19; i<155; i+=10) + myGLCD.drawLine(107, i, 111, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(sin(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(cos(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(tan(((i*1.65)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(218*20); i++) + { + x++; + if (x==219) + x=1; + if (i>219) + { + if ((x==109)||(buf[x-1]==88)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=88+(sin(((i*1.6)*3.14)/180)*(65-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(44+(i*15), 23+(i*15), 88+(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(132-(i*15), 23+(i*15), 172-(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(64+(i*15),43+(i*15), 20); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 160); + } + myGLCD.setColor (255,0,0); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(218, i, (i*1.44)-12, 15); + } + myGLCD.setColor (0,255,255); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(1, i, 232-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(218, i, 231-(i*1.44), 160); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(176); + y=35+random(105); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(216), 16+random(143)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(40, 57, 179, 119); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 62); + myGLCD.print("Restarting in a", CENTER, 88); + myGLCD.print("few seconds...", CENTER, 101); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 146); + myGLCD.printNumI(millis(), CENTER, 161); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.pde new file mode 100644 index 0000000..ec66344 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_220x176_Serial/UTFT_Demo_220x176_Serial.pde @@ -0,0 +1,322 @@ +// UTFT_Demo_220x176_Serial (C)2012 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for serial modules with a screen resolution +// of 220x176 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +UTFT myGLCD(ITDB22SP,11,10,9,12); // Remember to change the model parameter to suit your display module! + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[218]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 219, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 162, 219, 175); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("** Universal TFT Library **", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("> elec.henningkarlsen.com <", CENTER, 163); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 219, 161); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + + for (int i=9; i<210; i+=10) + myGLCD.drawLine(i, 86, i, 90); + for (int i=19; i<155; i+=10) + myGLCD.drawLine(107, i, 111, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(sin(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(cos(((i*1.65)*3.14)/180)*70)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<218; i++) + { + myGLCD.drawPixel(i,88+(tan(((i*1.65)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(109, 15, 109, 160); + myGLCD.drawLine(1, 88, 218, 88); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(218*20); i++) + { + x++; + if (x==219) + x=1; + if (i>219) + { + if ((x==109)||(buf[x-1]==88)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=88+(sin(((i*1.6)*3.14)/180)*(65-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(44+(i*15), 23+(i*15), 88+(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(132-(i*15), 23+(i*15), 172-(i*15), 63+(i*15)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(64+(i*15),43+(i*15), 20); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 160); + } + myGLCD.setColor (255,0,0); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(218, i, (i*1.44)-12, 15); + } + myGLCD.setColor (0,255,255); + for (int i=160; i>15; i-=5) + { + myGLCD.drawLine(1, i, 232-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<160; i+=5) + { + myGLCD.drawLine(218, i, 231-(i*1.44), 160); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,161); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=22+random(176); + y=35+random(105); + r=random(20); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(216); + y=16+random(143); + x2=2+random(216); + y2=16+random(143); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,218,160); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(216), 16+random(143)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(40, 57, 179, 119); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 62); + myGLCD.print("Restarting in a", CENTER, 88); + myGLCD.print("few seconds...", CENTER, 101); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 146); + myGLCD.printNumI(millis(), CENTER, 161); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_320x240/UTFT_Demo_320x240.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_320x240/UTFT_Demo_320x240.pde new file mode 100644 index 0000000..d849855 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_320x240/UTFT_Demo_320x240.pde @@ -0,0 +1,328 @@ +// UTFT_Demo_320x240 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,82,83,84,85); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[318]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 319, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 319, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 319, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + for (int i=9; i<310; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(157, i, 161, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(318*20); i++) + { + x++; + if (x==319) + x=1; + if (i>319) + { + if ((x==159)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(70+(i*20), 30+(i*20), 130+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(190-(i*20), 30+(i*20), 250-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(100+(i*20),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(318, i, (i*1.44)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 331-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(318, i, 330-(i*1.44), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(256); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(209); + x2=2+random(316); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(316), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(80, 70, 239, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.pde new file mode 100644 index 0000000..8342994 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_320x240_Serial/UTFT_Demo_320x240_Serial.pde @@ -0,0 +1,323 @@ +// UTFT_Demo_320x240_Serial (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Usage: myGLCD(, SDA, SCL, CS, RST[, RS]); +UTFT myGLCD(TFT01_22SP,9,8,12,11,10); // Remember to change the model parameter to suit your display module! + +void setup() +{ +// Just get some random numbers + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[318]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 319, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 319, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 319, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + for (int i=9; i<310; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(157, i, 161, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<318; i++) + { + myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(159, 15, 159, 224); + myGLCD.drawLine(1, 119, 318, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(318*20); i++) + { + x++; + if (x==319) + x=1; + if (i>319) + { + if ((x==159)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(70+(i*20), 30+(i*20), 130+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(190-(i*20), 30+(i*20), 250-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(100+(i*20),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.44)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(318, i, (i*1.44)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 331-(i*1.44), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(318, i, 330-(i*1.44), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(256); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(207); + x2=2+random(316); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(316); + y=16+random(209); + x2=2+random(316); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,318,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(316), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(80, 70, 239, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_400x240/UTFT_Demo_400x240.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_400x240/UTFT_Demo_400x240.pde new file mode 100644 index 0000000..0745538 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_400x240/UTFT_Demo_400x240.pde @@ -0,0 +1,330 @@ +// UTFT_Demo_400x240 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 400x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32WD,82,83,84,85); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[398]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 399, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 226, 399, 239); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("*** Universal Color TFT Display Library ***", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("< http://electronics.henningkarlsen.com >", CENTER, 227); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 399, 225); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(199, 15, 199, 224); + myGLCD.drawLine(1, 119, 398, 119); + for (int i=9; i<390; i+=10) + myGLCD.drawLine(i, 117, i, 121); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(197, i, 201, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<398; i++) + { + myGLCD.drawPixel(i,119+(sin(((i*0.9)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<398; i++) + { + myGLCD.drawPixel(i,119+(cos(((i*0.9)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<398; i++) + { + y=119+(tan(((i*0.9)*3.14)/180)); + if ((y>15) && (y<224)) + myGLCD.drawPixel(i,y); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(199, 15, 199, 224); + myGLCD.drawLine(1, 119, 398, 119); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(398*20); i++) + { + x++; + if (x==399) + x=1; + if (i>399) + { + if ((x==199)||(buf[x-1]==119)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=119+(sin(((i)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(110+(i*20), 30+(i*20), 170+(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(230-(i*20), 30+(i*20), 290-(i*20), 90+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(110+(i*30),60+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(1, i, (i*1.77)-10, 224); + } + myGLCD.setColor (255,0,0); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(398, i, (i*1.77)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=224; i>15; i-=5) + { + myGLCD.drawLine(1, i, 411-(i*1.77), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<224; i+=5) + { + myGLCD.drawLine(398, i, 410-(i*1.77), 224); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(336); + y=45+random(146); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(207); + x2=2+random(396); + y2=16+random(207); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(207); + x2=2+random(396); + y2=16+random(207); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(396); + y=16+random(209); + x2=2+random(396); + y2=16+random(209); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,398,224); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(396), 16+random(209)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(120, 70, 279, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 210); + myGLCD.printNumI(millis(), CENTER, 225); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_480x272/UTFT_Demo_480x272.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_480x272/UTFT_Demo_480x272.pde new file mode 100644 index 0000000..ae2b2f6 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_480x272/UTFT_Demo_480x272.pde @@ -0,0 +1,327 @@ +// UTFT_Demo_480x272 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 480x272 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB43,82,83,84,85); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[478]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 479, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 258, 479, 271); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 259); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 479, 257); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 256); + myGLCD.drawLine(1, 135, 478, 135); + for (int i=9; i<470; i+=10) + myGLCD.drawLine(i, 133, i, 138); + for (int i=15; i<256; i+=10) + myGLCD.drawLine(237, i, 241, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,135+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 256); + myGLCD.drawLine(1, 135, 478, 135); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(478*20); i++) + { + x++; + if (x==479) + x=1; + if (i>479) + { + if ((x==239)||(buf[x-1]==135)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=135+(sin(((i*1.65)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(150+(i*20), 46+(i*20), 210+(i*20), 106+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(330-(i*20), 46+(i*20), 270-(i*20), 106+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(180+(i*20),75+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<256; i+=5) + { + myGLCD.drawLine(1, i, (i*1.88)-10, 256); + } + myGLCD.setColor (255,0,0); + for (int i=256; i>15; i-=5) + { + myGLCD.drawLine(478, i, (i*1.88)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=256; i>15; i-=5) + { + myGLCD.drawLine(1, i, 491-(i*1.88), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<256; i+=5) + { + myGLCD.drawLine(478, i, 490-(i*1.88), 256); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + +// Draw some random circles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(416); + y=45+random(178); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + +// Draw some random rectangles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + +// Draw some random rounded rectangles + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + + for (int i=0; i<150; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(239); + x2=2+random(476); + y2=16+random(239); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,257); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(476), 16+random(239)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(160, 70, 319, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 243); + myGLCD.printNumI(millis(), CENTER, 258); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_480x320/UTFT_Demo_480x320.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_480x320/UTFT_Demo_480x320.pde new file mode 100644 index 0000000..8d3401c --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_480x320/UTFT_Demo_480x320.pde @@ -0,0 +1,328 @@ +// UTFT_Demo_480x320 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 480x320 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(CTE32HR,82,83,84,85); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[478]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 479, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 306, 479, 319); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 307); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 479, 305); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 304); + myGLCD.drawLine(1, 159, 478, 159); + for (int i=9; i<470; i+=10) + myGLCD.drawLine(i, 157, i, 161); + for (int i=19; i<220; i+=10) + myGLCD.drawLine(237, i, 241, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(sin(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(cos(((i*1.13)*3.14)/180)*95)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<478; i++) + { + myGLCD.drawPixel(i,159+(tan(((i*1.13)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(239, 15, 239, 304); + myGLCD.drawLine(1, 159, 478, 159); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(478*15); i++) + { + x++; + if (x==479) + x=1; + if (i>479) + { + if ((x==239)||(buf[x-1]==159)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=159+(sin(((i*0.7)*3.14)/180)*(90-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRect(150+(i*20), 70+(i*20), 210+(i*20), 130+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled, rounded rectangles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillRoundRect(270-(i*20), 70+(i*20), 330-(i*20), 130+(i*20)); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some filled circles + for (int i=1; i<6; i++) + { + switch (i) + { + case 1: + myGLCD.setColor(255,0,255); + break; + case 2: + myGLCD.setColor(255,0,0); + break; + case 3: + myGLCD.setColor(0,255,0); + break; + case 4: + myGLCD.setColor(0,0,255); + break; + case 5: + myGLCD.setColor(255,255,0); + break; + } + myGLCD.fillCircle(180+(i*20),100+(i*20), 30); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<304; i+=5) + { + myGLCD.drawLine(1, i, (i*1.6)-10, 304); + } + myGLCD.setColor (255,0,0); + for (int i=304; i>15; i-=5) + { + myGLCD.drawLine(478, i, (i*1.6)-11, 15); + } + myGLCD.setColor (0,255,255); + for (int i=304; i>15; i-=5) + { + myGLCD.drawLine(1, i, 491-(i*1.6), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<304; i+=5) + { + myGLCD.drawLine(478, i, 490-(i*1.6), 304); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random circles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(416); + y=45+random(226); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + +// Draw some random rounded rectangles + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + + for (int i=0; i<100; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(476); + y=16+random(289); + x2=2+random(476); + y2=16+random(289); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,478,304); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(476), 16+random(289)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(160, 70, 319, 169); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 93); + myGLCD.print("Restarting in a", CENTER, 119); + myGLCD.print("few seconds...", CENTER, 132); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 290); + myGLCD.printNumI(millis(), CENTER, 305); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Demo_800x480/UTFT_Demo_800x480.pde b/libraries/UTFT/examples/chipKit/UTFT_Demo_800x480/UTFT_Demo_800x480.pde new file mode 100644 index 0000000..e12bf71 --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Demo_800x480/UTFT_Demo_800x480.pde @@ -0,0 +1,287 @@ +// UTFT_Demo_800x480 (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of how to use most of the functions +// of the library with a supported display modules. +// +// This demo was made for modules with a screen resolution +// of 800x480 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB50,82,83,84,85); + +void setup() +{ + randomSeed(analogRead(0)); + +// Setup the LCD + myGLCD.InitLCD(); + myGLCD.setFont(SmallFont); +} + +void loop() +{ + int buf[798]; + int x, x2; + int y, y2; + int r; + +// Clear the screen and draw the frame + myGLCD.clrScr(); + + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, 799, 13); + myGLCD.setColor(64, 64, 64); + myGLCD.fillRect(0, 466, 799, 479); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("* Universal Color TFT Display Library *", CENTER, 1); + myGLCD.setBackColor(64, 64, 64); + myGLCD.setColor(255,255,0); + myGLCD.print("", CENTER, 467); + + myGLCD.setColor(0, 0, 255); + myGLCD.drawRect(0, 14, 799, 465); + +// Draw crosshairs + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(399, 15, 399, 464); + myGLCD.drawLine(1, 239, 798, 239); + for (int i=9; i<790; i+=10) + myGLCD.drawLine(i, 237, i, 242); + for (int i=19; i<470; i+=10) + myGLCD.drawLine(397, i, 402, i); + +// Draw sin-, cos- and tan-lines + myGLCD.setColor(0,255,255); + myGLCD.print("Sin", 5, 15); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(sin(((i*1.13)*3.14)/180)*200)); + } + + myGLCD.setColor(255,0,0); + myGLCD.print("Cos", 5, 27); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(cos(((i*1.13)*3.14)/180)*200)); + } + + myGLCD.setColor(255,255,0); + myGLCD.print("Tan", 5, 39); + for (int i=1; i<798; i++) + { + myGLCD.drawPixel(i,239+(tan(((i*0.9)*3.14)/180))); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + myGLCD.setColor(0, 0, 255); + myGLCD.setBackColor(0, 0, 0); + myGLCD.drawLine(399, 15, 399, 464); + myGLCD.drawLine(1, 239, 798, 239); + +// Draw a moving sinewave + x=1; + for (int i=1; i<(798*20); i++) + { + x++; + if (x==799) + x=1; + if (i>799) + { + if ((x==399)||(buf[x-1]==239)) + myGLCD.setColor(0,0,255); + else + myGLCD.setColor(0,0,0); + myGLCD.drawPixel(x,buf[x-1]); + } + myGLCD.setColor(0,255,255); + y=239+(sin(((i*1.65)*3.14)/180)*(200-(i / 100))); + myGLCD.drawPixel(x,y); + buf[x-1]=y; + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled rectangles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(746); + y=16+random(397); + x2=x+50; + y2=y+50; + myGLCD.fillRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled, rounded rectangles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(746); + y=16+random(397); + x2=x+50; + y2=y+50; + myGLCD.fillRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random filled circles + for (int i=0; i<50; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=27+random(746); + y=41+random(397); + myGLCD.fillCircle(x, y, 25); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some lines in a pattern + myGLCD.setColor (255,0,0); + for (int i=15; i<463; i+=5) + { + myGLCD.drawLine(1, i, (i*1.66)-10, 463); + } + myGLCD.setColor (255,0,0); + for (int i=463; i>15; i-=5) + { + myGLCD.drawLine(798, i, (i*1.66)+30, 15); + } + myGLCD.setColor (0,255,255); + for (int i=463; i>15; i-=5) + { + myGLCD.drawLine(1, i, 770-(i*1.66), 15); + } + myGLCD.setColor (0,255,255); + for (int i=15; i<463; i+=5) + { + myGLCD.drawLine(798, i, 810-(i*1.66), 463); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random circles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=32+random(736); + y=45+random(386); + r=random(30); + myGLCD.drawCircle(x, y, r); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random rectangles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + +// Draw some random rounded rectangles + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawRoundRect(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + + for (int i=0; i<250; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + x=2+random(796); + y=16+random(447); + x2=2+random(796); + y2=16+random(447); + myGLCD.drawLine(x, y, x2, y2); + } + + delay(2000); + + myGLCD.setColor(0,0,0); + myGLCD.fillRect(1,15,798,464); + + for (int i=0; i<10000; i++) + { + myGLCD.setColor(random(255), random(255), random(255)); + myGLCD.drawPixel(2+random(796), 16+random(447)); + } + + delay(2000); + + myGLCD.fillScr(0, 0, 255); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRoundRect(320, 190, 479, 289); + + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("That's it!", CENTER, 213); + myGLCD.print("Restarting in a", CENTER, 239); + myGLCD.print("few seconds...", CENTER, 252); + + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 255); + myGLCD.print("Runtime: (msecs)", CENTER, 450); + myGLCD.printNumI(millis(), CENTER, 465); + + delay (10000); +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.pde b/libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.pde new file mode 100644 index 0000000..0d3453a --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/UTFT_Rotate_Bitmap.pde @@ -0,0 +1,36 @@ +// UTFT_Rotate_Bitmap (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the drawBitmap()-function. +// +// This program requires the UTFT library. +// + +#include + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,82,83,84,85); + +extern unsigned short biohazard[0x1000]; + +void setup() +{ + myGLCD.InitLCD(LANDSCAPE); + myGLCD.fillScr(255, 255, 255); + myGLCD.setColor(0, 0, 0); +} + +void loop() +{ + for (int i=0; i<360; i+=5) + { + myGLCD.drawBitmap (10, 10, 64, 64, biohazard, i, 32, 32); + } +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/biohazard.c b/libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/biohazard.c new file mode 100644 index 0000000..ca1348d --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Rotate_Bitmap/biohazard.c @@ -0,0 +1,264 @@ +// Generated by : ImageConverter 565 v1.0 +// Generated from: biohazard1_L.png +// Time generated: 12.06.2011 00:23:59 +// Dimensions : 64x64 pixels +// Size : 8 192 Bytes + +const unsigned short biohazard[0x1000] ={ +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7D, 0xC638, 0x9492, 0x6B4D, 0x4228, 0x2945, 0x2124, 0x18C3, 0x1082, // 0x0020 (32) +0x1082, 0x10A2, 0x18C3, 0x2124, 0x2965, 0x4A49, 0x6B6D, 0x9CD3, 0xCE79, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0030 (48) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0040 (64) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0050 (80) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0xBDD7, 0x6B6D, 0x2965, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0060 (96) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0x31A6, 0x73AE, 0xC618, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0070 (112) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0080 (128) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0090 (144) +0xFFFF, 0xFFFF, 0xE73C, 0x8C71, 0x3186, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, // 0x00A0 (160) +0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x4207, 0x9CF3, 0xF79E, 0xFFFF, // 0x00B0 (176) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00C0 (192) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x00D0 (208) +0xEF7D, 0x8C51, 0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00E0 (224) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x2965, 0x9CD3, // 0x00F0 (240) +0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0100 (256) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD75, // 0x0110 (272) +0x2965, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0020, 0x2901, 0x5241, 0x7B41, 0x9C02, 0xACA2, 0xBD02, // 0x0120 (288) +0xC521, 0xBD02, 0xACA2, 0x9C22, 0x7B41, 0x5241, 0x2901, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0130 (304) +0x39E7, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0140 (320) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xEF5D, 0x630C, 0x0000, // 0x0150 (336) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x41C1, 0x93E1, 0xD5A1, 0xFEA1, 0xFF01, 0xFF20, 0xFF20, 0xFF20, 0xFF00, // 0x0160 (352) +0xFF00, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF01, 0xFEA1, 0xD5A1, 0x93E1, 0x49E1, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0170 (368) +0x0000, 0x0841, 0x7BEF, 0xF7BE, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0180 (384) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xC638, 0x2965, 0x0000, 0x0000, // 0x0190 (400) +0x0000, 0x0000, 0x0000, 0x0000, 0x18A0, 0x7B41, 0xD5A1, 0xFF01, 0xFF20, 0xFEE0, 0xFEC0, 0xFEA0, 0xF680, 0xF680, 0xFEA0, 0xFEA0, // 0x01A0 (416) +0xFEA0, 0xFEA0, 0xFEA0, 0xF680, 0xF680, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF01, 0xD5A1, 0x7B41, 0x1880, 0x0000, 0x0000, 0x0000, // 0x01B0 (432) +0x0000, 0x0000, 0x0000, 0x4208, 0xDEDB, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x01C0 (448) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD55, 0x1082, 0x0000, 0x0000, 0x0000, // 0x01D0 (464) +0x0000, 0x0000, 0x0840, 0x7B62, 0xEE41, 0xFF21, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF20, 0xFF20, 0xFEA1, 0xFEC0, // 0x01E0 (480) +0xFEC0, 0xFEC0, 0xFEA1, 0xFF00, 0xFF20, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF21, 0xEE41, 0x7B62, 0x0840, 0x0000, // 0x01F0 (496) +0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0xC618, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0200 (512) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x94B2, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0210 (528) +0x0000, 0x5201, 0xDDE1, 0xFF21, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF40, 0xF6A1, 0xB4C1, 0x7322, 0xA441, 0xFEE0, // 0x0220 (544) +0xFEA0, 0xFEE0, 0xA461, 0x7322, 0xACA1, 0xF681, 0xFF40, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF21, 0xDDE2, 0x4A01, // 0x0230 (560) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1082, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0240 (576) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x9492, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, // 0x0250 (592) +0x9402, 0xFF01, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xFF01, 0x9401, 0x3961, 0x7341, 0xCD81, 0xF680, 0xFEC0, // 0x0260 (608) +0xFEA0, 0xFEC0, 0xF681, 0xCD81, 0x7B61, 0x3961, 0x8BE1, 0xFEE1, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF01, // 0x0270 (624) +0x9402, 0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0xB596, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0280 (640) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xA534, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x20C0, 0xCD61, // 0x0290 (656) +0xFF40, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF01, 0xE621, 0x39A1, 0x20E1, 0xCD81, 0xFF40, 0xFEE0, 0xFEC0, 0xFEC0, // 0x02A0 (672) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEE0, 0xFF41, 0xCDC1, 0x2901, 0x3961, 0xDE01, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEA0, // 0x02B0 (688) +0xFF21, 0xC561, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x1082, 0xC618, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02C0 (704) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC618, 0x0861, 0x0000, 0x0000, 0x0000, 0x0000, 0x3121, 0xDE01, 0xFF00, // 0x02D0 (720) +0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF01, 0xD5A2, 0x18A0, 0x20E0, 0xF682, 0xFF01, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, // 0x02E0 (736) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xF6A1, 0x2920, 0x1080, 0xCDA2, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x02F0 (752) +0xFE80, 0xFF00, 0xDE01, 0x2921, 0x0000, 0x0000, 0x0000, 0x0000, 0x18E3, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73C, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000, 0x2921, 0xEE41, 0xFF00, 0xFEA0, // 0x0310 (784) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xDE02, 0x18A1, 0x0840, 0xDDE1, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0320 (800) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xE621, 0x0860, 0x1880, 0xD5E2, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0330 (816) +0xFEA0, 0xFEA0, 0xFF00, 0xE641, 0x2921, 0x0000, 0x0000, 0x0000, 0x0000, 0x4208, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x5ACB, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C0, 0xDE21, 0xFF00, 0xFEA0, 0xFEC0, // 0x0350 (848) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC1, 0x39A1, 0x0000, 0x8382, 0xFF21, 0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0360 (864) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFE80, 0xFF20, 0x8BC1, 0x0000, 0x3161, 0xF6A1, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0370 (880) +0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xDE01, 0x18A0, 0x0000, 0x0000, 0x0000, 0x0000, 0x7BCF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0380 (896) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA534, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, 0xCD61, 0xFF00, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0390 (912) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x93E1, 0x0000, 0x1060, 0xDE01, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x03A0 (928) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xE621, 0x1080, 0x0000, 0x8BA1, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, // 0x03B0 (944) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xCD61, 0x0820, 0x0000, 0x0000, 0x0000, 0x0021, 0xBDF7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x03C0 (960) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x2104, 0x0000, 0x0000, 0x0000, 0x0000, 0x9402, 0xFF41, 0xFE80, 0xFEA0, 0xFEC0, 0xFEC0, // 0x03D0 (976) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xF681, 0x20E0, 0x0000, 0x41A1, 0xFEE1, 0xFEA0, 0xFEA1, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x03E0 (992) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF01, 0x49E1, 0x0000, 0x18A1, 0xEE41, 0xFEC0, 0xFEA0, 0xFEC0, // 0x03F0 (1008) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFE80, 0xFF41, 0x9402, 0x0000, 0x0000, 0x0000, 0x0000, 0x39C7, 0xF7BE, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0400 (1024) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BCF, 0x0000, 0x0000, 0x0000, 0x0000, 0x4A01, 0xFF01, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0410 (1040) +0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0xA461, 0x0000, 0x0000, 0x6AC1, 0xFF21, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0420 (1056) +0xFEE0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFE80, 0xFF20, 0x7300, 0x0000, 0x0000, 0x9C21, 0xFF20, 0xFEA0, 0xFEC0, // 0x0430 (1072) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF01, 0x49E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0440 (1088) +0xFFFF, 0xFFFF, 0xFFFF, 0xDEFB, 0x10A2, 0x0000, 0x0000, 0x0000, 0x0840, 0xDDE1, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0450 (1104) +0xFEA0, 0xFEA0, 0xFEA0, 0xFF20, 0x6261, 0x0000, 0x0000, 0x7300, 0xFF21, 0xF6A0, 0xFEA0, 0xFEE0, 0xFF20, 0xFF00, 0xFEA1, 0xEE42, // 0x0460 (1120) +0xE602, 0xEE42, 0xFEA1, 0xFF00, 0xFF20, 0xFEE0, 0xFEA0, 0xF681, 0xFF40, 0x8360, 0x0000, 0x0000, 0x5241, 0xFF01, 0xFEA0, 0xFEA0, // 0x0470 (1136) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xDDC1, 0x0840, 0x0000, 0x0000, 0x0000, 0x2945, 0xEF7D, 0xFFFF, 0xFFFF, // 0x0480 (1152) +0xFFFF, 0xFFDF, 0xFFFF, 0x7BEF, 0x0000, 0x0000, 0x0000, 0x0000, 0x7B42, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0490 (1168) +0xFEC0, 0xFEA0, 0xFEC0, 0xFEA0, 0x2900, 0x0000, 0x0000, 0x6AE0, 0xFF21, 0xFEC0, 0xFF01, 0xDE01, 0x9C01, 0x5241, 0x2921, 0x18A1, // 0x04A0 (1184) +0x1061, 0x1881, 0x2921, 0x5241, 0x9C02, 0xDDE1, 0xFF21, 0xFEC0, 0xFF20, 0x7321, 0x0000, 0x0000, 0x20E0, 0xF681, 0xFEC0, 0xFEA0, // 0x04B0 (1200) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x7B41, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFDF, // 0x04C0 (1216) +0xFFDF, 0xFFFF, 0xEF7D, 0x2104, 0x0000, 0x0000, 0x0000, 0x1080, 0xEE41, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x04D0 (1232) +0xFEC0, 0xFEA0, 0xFEC0, 0xEE21, 0x1060, 0x0000, 0x0000, 0x41C1, 0xFF21, 0xDDE1, 0x6AC1, 0x0860, 0x0000, 0x0000, 0x0000, 0x0000, // 0x04E0 (1248) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0860, 0x62C1, 0xDDC1, 0xFF41, 0x49E1, 0x0000, 0x0000, 0x0840, 0xE601, 0xFEE0, 0xFEA0, // 0x04F0 (1264) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xEE41, 0x1080, 0x0000, 0x0000, 0x0000, 0x39C7, 0xF7BE, 0xFFFF, // 0x0500 (1280) +0xFFDF, 0xFFFF, 0xA534, 0x0000, 0x0000, 0x0000, 0x0000, 0x7B21, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0510 (1296) +0xFEA0, 0xFEA0, 0xFEE0, 0xE602, 0x0841, 0x0000, 0x0000, 0x1080, 0xACC2, 0x1060, 0x0000, 0x0000, 0x0000, 0x0020, 0x2920, 0x4A01, // 0x0520 (1312) +0x5241, 0x4A01, 0x3140, 0x0821, 0x0000, 0x0000, 0x0000, 0x0860, 0xACA2, 0x18A0, 0x0000, 0x0000, 0x0820, 0xDDE2, 0xFEE0, 0xFEA0, // 0x0530 (1328) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFE80, 0xFF21, 0x7321, 0x0000, 0x0000, 0x0000, 0x0020, 0xC618, 0xFFFF, // 0x0540 (1344) +0xFFFF, 0xFFFF, 0x52AA, 0x0000, 0x0020, 0x0000, 0x0820, 0xDDA1, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0550 (1360) +0xFEC0, 0xFEA0, 0xFEE0, 0xE621, 0x1060, 0x0000, 0x0000, 0x0000, 0x6AE2, 0x20C1, 0x0000, 0x20E1, 0x8BA2, 0xD5A1, 0xFEA1, 0xFF00, // 0x0560 (1376) +0xFF01, 0xFF00, 0xFEC1, 0xD5C1, 0x8BC2, 0x2901, 0x0000, 0x18A1, 0x7302, 0x0000, 0x0000, 0x0000, 0x0840, 0xDE01, 0xFEE0, 0xFEA0, // 0x0570 (1392) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xD5A1, 0x0020, 0x0000, 0x0000, 0x0000, 0x738E, 0xFFFF, // 0x0580 (1408) +0xFFFF, 0xE71C, 0x18C3, 0x0000, 0x0020, 0x0000, 0x49C1, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0590 (1424) +0xFEA0, 0xFEA0, 0xFEC0, 0xF661, 0x18A0, 0x0000, 0x0000, 0x0000, 0x2101, 0x8363, 0x7321, 0xEE81, 0xFF21, 0xFEE0, 0xFEC0, 0xFEA0, // 0x05A0 (1440) +0xFEA0, 0xFEA0, 0xFEC0, 0xFEE0, 0xFF20, 0xF681, 0x7B41, 0x8362, 0x2921, 0x0000, 0x0000, 0x0000, 0x1080, 0xEE41, 0xFEC0, 0xFEA0, // 0x05B0 (1456) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF01, 0x41C1, 0x0000, 0x0020, 0x0000, 0x3186, 0xF79E, // 0x05C0 (1472) +0xFFFF, 0xAD75, 0x0000, 0x0000, 0x0020, 0x0000, 0x93E1, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, // 0x05D0 (1488) +0xFEC0, 0xFEA0, 0xFEA0, 0xFF41, 0x5221, 0x0000, 0x0000, 0x0000, 0x0000, 0x41C1, 0xFF01, 0xFF00, 0xF660, 0xFEA0, 0xFEA0, 0xFEC0, // 0x05E0 (1504) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xF660, 0xFF00, 0xFF22, 0x49E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x49E1, 0xFF40, 0xFEA0, 0xFEA0, // 0x05F0 (1520) +0xFEA1, 0xFEC0, 0xFEA1, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x93E1, 0x0000, 0x0020, 0x0000, 0x0020, 0xC638, // 0x0600 (1536) +0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0020, 0xD5A1, 0xFF00, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA1, 0xFEA0, // 0x0610 (1552) +0xFEA1, 0xFF20, 0xFEC1, 0xD5C1, 0x5220, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x3981, 0xE622, 0xFF20, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0620 (1568) +0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF21, 0xE621, 0x41C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49E0, 0xCDA2, 0xFEA1, 0xFF20, // 0x0630 (1584) +0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xD5A1, 0x0020, 0x0000, 0x0000, 0x0000, 0x9492, // 0x0640 (1600) +0xFFFF, 0x4A49, 0x0000, 0x0020, 0x0000, 0x2901, 0xFEA1, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, // 0x0650 (1616) +0xFEE1, 0xA461, 0x3981, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1881, 0x93E1, 0xE622, 0xFF01, 0xFF00, // 0x0660 (1632) +0xFEA0, 0xFF00, 0xFF21, 0xEE41, 0x9401, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3141, 0x9C21, // 0x0670 (1648) +0xFEC1, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEA1, 0x2901, 0x0000, 0x0020, 0x0000, 0x632C, // 0x0680 (1664) +0xE71C, 0x2124, 0x0000, 0x0020, 0x0000, 0x5241, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xD5C1, // 0x0690 (1680) +0x41C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1081, 0x4A01, 0xAC81, // 0x06A0 (1696) +0xFF21, 0xB4C1, 0x5221, 0x1081, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x06B0 (1712) +0x3981, 0xCD81, 0xFF21, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF01, 0x5221, 0x0000, 0x0020, 0x0000, 0x4228, // 0x06C0 (1728) +0xBDF7, 0x18C3, 0x0000, 0x0020, 0x0000, 0x7B41, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF20, 0xBD02, 0x1060, // 0x06D0 (1744) +0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5201, // 0x06E0 (1760) +0xFFC0, 0x5A41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, // 0x06F0 (1776) +0x0000, 0x0840, 0xACA1, 0xFF21, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x7B41, 0x0000, 0x0020, 0x0000, 0x2945, // 0x0700 (1792) +0x94B2, 0x0861, 0x0000, 0x0000, 0x0000, 0x9C02, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xBD22, 0x0820, 0x0000, // 0x0710 (1808) +0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1881, 0xAC81, // 0x0720 (1824) +0xFF20, 0xB4A1, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0730 (1840) +0x0020, 0x0000, 0x0000, 0xB4C2, 0xFF00, 0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x9C02, 0x0000, 0x0020, 0x0000, 0x2104, // 0x0740 (1856) +0x73AE, 0x0841, 0x0000, 0x0000, 0x0000, 0xACA2, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xE622, 0x18A1, 0x0000, 0x0000, // 0x0750 (1872) +0x0000, 0x1080, 0x5221, 0x6B03, 0x6AE2, 0x6AE3, 0x4A01, 0x1080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1061, 0xCD82, 0xFF20, // 0x0760 (1888) +0xFE80, 0xFF20, 0xD5C2, 0x1881, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1080, 0x5241, 0x6AE3, 0x6AE2, 0x6AE3, 0x5A62, 0x18C0, // 0x0770 (1904) +0x0000, 0x0000, 0x0000, 0x1060, 0xDDE2, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF20, 0xACA2, 0x0000, 0x0000, 0x0000, 0x10A2, // 0x0780 (1920) +0x52AA, 0x0000, 0x0000, 0x0000, 0x0000, 0xBD02, 0xFF00, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF01, 0x5A61, 0x0000, 0x0000, 0x18A0, // 0x0790 (1936) +0x9401, 0xEE61, 0xFEE2, 0x49E2, 0x18A1, 0x62A1, 0xFF41, 0xE621, 0x8BC2, 0x1880, 0x0000, 0x0820, 0x0000, 0x7B21, 0xFF40, 0xFE80, // 0x07A0 (1952) +0xFEC0, 0xFE80, 0xFF40, 0x8381, 0x0000, 0x0820, 0x0000, 0x1080, 0x8BE2, 0xEE41, 0xFF41, 0x62A2, 0x10A1, 0x3982, 0xFEC2, 0xF6A1, // 0x07B0 (1968) +0xA462, 0x2101, 0x0000, 0x0000, 0x49E1, 0xFF01, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF00, 0xBD02, 0x0000, 0x0000, 0x0000, 0x1082, // 0x07C0 (1984) +0x528A, 0x0000, 0x0000, 0x0000, 0x0000, 0xC521, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xCD41, 0x0000, 0x0000, 0x49C1, 0xE642, // 0x07D0 (2000) +0xFF21, 0xFEE0, 0xEE42, 0x1081, 0x0000, 0x41A0, 0xFEE0, 0xFEC0, 0xFF40, 0xE621, 0x41A1, 0x0000, 0x0000, 0x93E1, 0xFF20, 0xFEA0, // 0x07E0 (2016) +0xFEA0, 0xFEA0, 0xFF20, 0x9C22, 0x0000, 0x0000, 0x3981, 0xDE01, 0xFF21, 0xFEC0, 0xFEE1, 0x49E1, 0x0000, 0x0840, 0xE602, 0xFEC0, // 0x07F0 (2032) +0xFF20, 0xEE81, 0x5A61, 0x0000, 0x0000, 0xBCE1, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xC521, 0x0000, 0x0000, 0x0000, 0x1082, // 0x0800 (2048) +0x52AA, 0x0000, 0x0000, 0x0000, 0x0000, 0xBD02, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF20, 0x6AC1, 0x0000, 0x49E1, 0xFEE2, 0xFEE0, // 0x0810 (2064) +0xFE80, 0xFEC0, 0xF682, 0x20E1, 0x0000, 0x39A0, 0xFEE0, 0xFEA0, 0xFE80, 0xFEE0, 0xF6A2, 0x41A1, 0x3961, 0xDDC1, 0xFF00, 0xFE80, // 0x0820 (2080) +0xFEA0, 0xFEA0, 0xFF00, 0xE601, 0x41C1, 0x3981, 0xF682, 0xFF00, 0xFE80, 0xFEA0, 0xFF00, 0x41C1, 0x0000, 0x20C1, 0xF661, 0xFEC0, // 0x0830 (2096) +0xF6A0, 0xFEC0, 0xFF01, 0x6261, 0x0000, 0x5A41, 0xFF01, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xBD02, 0x0000, 0x0000, 0x0000, 0x1082, // 0x0840 (2112) +0x738E, 0x0841, 0x0000, 0x0000, 0x0000, 0xACA2, 0xFF20, 0xFEA0, 0xFEA0, 0xFEC0, 0xF681, 0x18A0, 0x1080, 0xEE41, 0xFEE0, 0xFEA0, // 0x0850 (2128) +0xFEC0, 0xFEA0, 0xFEE1, 0x3980, 0x0000, 0x20C0, 0xF662, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEE0, 0xF681, 0xFEE1, 0xFF01, 0xDDC1, 0xFF21, // 0x0860 (2144) +0xFF20, 0xFF21, 0xDDC1, 0xFEC1, 0xFF01, 0xF661, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEA1, 0x2900, 0x0000, 0x3140, 0xFEA1, 0xFEA0, // 0x0870 (2160) +0xFEA0, 0xFEA0, 0xFEC0, 0xF6A1, 0x2101, 0x0840, 0xEE41, 0xFEE0, 0xFEA0, 0xFEA0, 0xFF20, 0xAC82, 0x0000, 0x0000, 0x0000, 0x10A2, // 0x0880 (2176) +0x9492, 0x0861, 0x0000, 0x0000, 0x0000, 0x9C02, 0xFF20, 0xFEA0, 0xFEA0, 0xFF00, 0xD582, 0x0000, 0x93C1, 0xFF40, 0xFE80, 0xFEC0, // 0x0890 (2192) +0xFEC0, 0xFEA0, 0xFF21, 0x6AC1, 0x0000, 0x0000, 0xCD41, 0xFF00, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xDDE1, 0x41A1, 0x0860, 0x6AC1, // 0x08A0 (2208) +0x93E1, 0x6AE1, 0x0841, 0x3161, 0xD5C1, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF00, 0xCD61, 0x0000, 0x0000, 0x5A81, 0xFF21, 0xFEA0, // 0x08B0 (2224) +0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0xAC81, 0x0000, 0xC521, 0xFF00, 0xFEA0, 0xFEA0, 0xFF20, 0x9C02, 0x0000, 0x0020, 0x0000, 0x2104, // 0x08C0 (2240) +0xB5B6, 0x10A2, 0x0000, 0x0020, 0x0000, 0x7B41, 0xFF20, 0xFEA0, 0xFEA0, 0xFF20, 0xAC80, 0x0820, 0xEE41, 0xFEC0, 0xFEA0, 0xFEC0, // 0x08D0 (2256) +0xFEC0, 0xFEA0, 0xFF00, 0xAC81, 0x0000, 0x0000, 0x7301, 0xFF20, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEE0, 0xD5C1, 0x0000, 0x0000, 0x0000, // 0x08E0 (2272) +0x0000, 0x0000, 0x0000, 0x0000, 0xD561, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF41, 0x7B42, 0x0000, 0x0000, 0xA442, 0xFF21, 0xFEA0, // 0x08F0 (2288) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA1, 0x1080, 0x9C00, 0xFF40, 0xFEA0, 0xFEA0, 0xFF20, 0x7B41, 0x0000, 0x0020, 0x0000, 0x2124, // 0x0900 (2304) +0xDEFB, 0x2104, 0x0000, 0x0020, 0x0000, 0x5221, 0xFF01, 0xFEA0, 0xFEA0, 0xFF40, 0x93C0, 0x3961, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0910 (2320) +0xFEC0, 0xFEA0, 0xFEC0, 0xEE61, 0x1881, 0x0000, 0x1080, 0xEE21, 0xFEE0, 0xFEA0, 0xFEC0, 0xFEA0, 0xFF01, 0x41C1, 0x0000, 0x0020, // 0x0920 (2336) +0x0000, 0x0020, 0x0000, 0x3961, 0xFEE1, 0xFEA0, 0xFEC0, 0xFEA0, 0xFEC0, 0xEE61, 0x18A1, 0x0000, 0x1060, 0xE621, 0xFEC0, 0xFEA0, // 0x0930 (2352) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x4A01, 0x8361, 0xFF40, 0xFEA0, 0xFEA0, 0xFF01, 0x5221, 0x0000, 0x0020, 0x0000, 0x4208, // 0x0940 (2368) +0xFFDF, 0x4208, 0x0000, 0x0000, 0x0000, 0x2901, 0xFEA1, 0xFEC0, 0xFEA0, 0xFF40, 0x93C0, 0x5A60, 0xFF41, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0950 (2384) +0xFEA0, 0xFEC0, 0xFEA0, 0xFF21, 0x7B41, 0x0000, 0x0000, 0x6281, 0xFF21, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF21, 0x62A1, 0x0000, 0x0000, // 0x0960 (2400) +0x0000, 0x0000, 0x0000, 0x5A41, 0xFF01, 0xFEA0, 0xFEA0, 0xF680, 0xFF41, 0x6AC1, 0x0000, 0x0000, 0x7301, 0xFF21, 0xFEA0, 0xFEA0, // 0x0970 (2416) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF40, 0x6AE1, 0x8361, 0xFF40, 0xFEA0, 0xFEC0, 0xFEA1, 0x2901, 0x0000, 0x0020, 0x0000, 0x630C, // 0x0980 (2432) +0xFFFF, 0x6B6D, 0x0000, 0x0020, 0x0000, 0x0020, 0xD5A1, 0xFF00, 0xFEA0, 0xFF20, 0xA461, 0x6AC0, 0xFF40, 0xFEA0, 0xFEC0, 0xFEC0, // 0x0990 (2448) +0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xEE61, 0x18C0, 0x0000, 0x0000, 0x93E2, 0xFF41, 0xFEA0, 0xFE80, 0xFF20, 0x6AE1, 0x0000, 0x0000, // 0x09A0 (2464) +0x0000, 0x0000, 0x0000, 0x62A1, 0xFF21, 0xFE80, 0xFEA0, 0xFF40, 0x9C22, 0x0000, 0x0000, 0x1881, 0xE641, 0xFEC0, 0xFEC0, 0xFEC0, // 0x09B0 (2480) +0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF40, 0x7B61, 0x9C00, 0xFF40, 0xFE80, 0xFF00, 0xD581, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, // 0x09C0 (2496) +0xFFFF, 0xA534, 0x0000, 0x0000, 0x0000, 0x0000, 0x93E1, 0xFF20, 0xFE80, 0xFF00, 0xC541, 0x72E1, 0xFF20, 0xFEA0, 0xFEC0, 0xFEC0, // 0x09D0 (2512) +0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xB4C1, 0x0000, 0x0020, 0x0000, 0x93E1, 0xFF21, 0xFEC0, 0xFF01, 0x5A81, 0x0000, 0x0000, // 0x09E0 (2528) +0x0000, 0x0000, 0x0000, 0x5222, 0xFF01, 0xFEC0, 0xFF21, 0x9C01, 0x0000, 0x0020, 0x0000, 0xAC81, 0xFF01, 0xFEA0, 0xFEA0, 0xFEC0, // 0x09F0 (2544) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF20, 0x7B40, 0xBD01, 0xFF20, 0xF680, 0xFF20, 0x93C1, 0x0000, 0x0020, 0x0000, 0x0000, 0xBDF7, // 0x0A00 (2560) +0xFFFF, 0xDEDB, 0x1082, 0x0000, 0x0000, 0x0000, 0x41C1, 0xFF01, 0xFEA0, 0xFEC0, 0xF660, 0x6AC2, 0xF6A1, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A10 (2576) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFF21, 0x8BA1, 0x0000, 0x0000, 0x0000, 0x6281, 0xDE21, 0xFF01, 0x3161, 0x0000, 0x0000, // 0x0A20 (2592) +0x0000, 0x0000, 0x0000, 0x2921, 0xFEE1, 0xE641, 0x62A1, 0x0000, 0x0000, 0x0000, 0x8381, 0xFF21, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A30 (2608) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEC1, 0x6AC2, 0xE621, 0xFEE0, 0xFEA0, 0xFF01, 0x41C1, 0x0000, 0x0020, 0x0000, 0x2124, 0xEF5D, // 0x0A40 (2624) +0xFFFF, 0xFFFF, 0x4A49, 0x0000, 0x0000, 0x0000, 0x0020, 0xD5A1, 0xFEE0, 0xFEA0, 0xFEC0, 0xCD41, 0xF660, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A50 (2640) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF21, 0x8BC1, 0x0000, 0x0000, 0x0000, 0x1060, 0xA442, 0x0860, 0x0000, 0x0000, // 0x0A60 (2656) +0x0000, 0x0000, 0x0000, 0x0820, 0xA442, 0x18A0, 0x0000, 0x0000, 0x0000, 0x8381, 0xFF21, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0A70 (2672) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFE80, 0xCD62, 0xFEC0, 0xFEA1, 0xFEE0, 0xD5A1, 0x0020, 0x0000, 0x0000, 0x0000, 0x630C, 0xFFFF, // 0x0A80 (2688) +0xFFDF, 0xFFFF, 0x94B2, 0x0000, 0x0000, 0x0000, 0x0000, 0x7321, 0xFF21, 0xFEA0, 0xFEA0, 0xFEE0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0A90 (2704) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF21, 0xB4C1, 0x20E1, 0x0000, 0x3161, 0x62A2, 0x0000, 0x0000, 0x0000, // 0x0AA0 (2720) +0x0000, 0x0000, 0x0000, 0x0000, 0x5A82, 0x39A1, 0x0000, 0x20C1, 0xAC82, 0xFF21, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0AB0 (2736) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEC0, 0xFEE0, 0xFEA0, 0xFEA0, 0xFF21, 0x7321, 0x0000, 0x0000, 0x0000, 0x0000, 0xB596, 0xFFFF, // 0x0AC0 (2752) +0xFFDF, 0xFFFF, 0xE73C, 0x18C3, 0x0000, 0x0000, 0x0000, 0x1080, 0xEE41, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA1, 0xFF00, 0xFEE0, 0xFEA0, // 0x0AD0 (2768) +0xFEC0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFF00, 0xEE41, 0x83C1, 0x8BA3, 0x1081, 0x0000, 0x0000, 0x0000, // 0x0AE0 (2784) +0x0000, 0x0000, 0x0000, 0x0000, 0x1060, 0x8383, 0x83A1, 0xEE41, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, // 0x0AF0 (2800) +0xFEC0, 0xFEA0, 0xFEC0, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xEE21, 0x1080, 0x0000, 0x0000, 0x0000, 0x2945, 0xEF7D, 0xFFFF, // 0x0B00 (2816) +0xFFFF, 0xFFFF, 0xFFFF, 0x6B4D, 0x0000, 0x0000, 0x0000, 0x0000, 0x7B41, 0xFF21, 0xFEA0, 0xFEA0, 0xFF00, 0xB482, 0xD5C1, 0xFF20, // 0x0B10 (2832) +0xFE80, 0xFEA0, 0xFEA0, 0xFEA1, 0xFEA0, 0xFEC0, 0xFEA1, 0xFEA0, 0xF680, 0xFF20, 0xF6A2, 0x3121, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0B20 (2848) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20E1, 0xEE62, 0xFF40, 0xF680, 0xFEA0, 0xFEA1, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0B30 (2864) +0xF681, 0xFF20, 0xE601, 0xAC62, 0xFF00, 0xFEA0, 0xFE80, 0xFF21, 0x7B41, 0x0000, 0x0000, 0x0000, 0x0000, 0x8410, 0xFFFF, 0xFFFF, // 0x0B40 (2880) +0xFFFF, 0xFFDF, 0xFFFF, 0xD69A, 0x0841, 0x0000, 0x0000, 0x0000, 0x0840, 0xDDC1, 0xFEE0, 0xFEA0, 0xFEE1, 0xD5A1, 0x5221, 0xBD21, // 0x0B50 (2896) +0xFF41, 0xFF00, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA1, 0xFEC0, 0xFF00, 0xFF21, 0xCD61, 0x20E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, // 0x0B60 (2912) +0x7322, 0x0840, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A1, 0xBD22, 0xFF21, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEE0, // 0x0B70 (2928) +0xFF40, 0xC561, 0x5221, 0xCD81, 0xFEE0, 0xFE81, 0xFEE0, 0xDDC1, 0x0840, 0x0000, 0x0000, 0x0000, 0x18E3, 0xE71C, 0xFFFF, 0xFFFF, // 0x0B80 (2944) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x632C, 0x0000, 0x0000, 0x0000, 0x0000, 0x49E1, 0xFF01, 0xFEA0, 0xFEA0, 0xFF00, 0xDE01, 0x4181, // 0x0B90 (2960) +0x5A81, 0xD581, 0xFEE1, 0xFF20, 0xFF20, 0xFF01, 0xFEC1, 0xD582, 0x6AE1, 0x0020, 0x0000, 0x0020, 0x0000, 0x0000, 0x1060, 0xACA2, // 0x0BA0 (2976) +0xFF61, 0xBD21, 0x18A1, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x62A2, 0xCD62, 0xFEA1, 0xFF01, 0xFF20, 0xFF20, 0xFEE1, 0xD5C1, // 0x0BB0 (2992) +0x62C1, 0x3981, 0xD5C1, 0xFF21, 0xFEA0, 0xFEA0, 0xFF01, 0x49E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x7BEF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0BC0 (3008) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0x1082, 0x0000, 0x0000, 0x0000, 0x0000, 0x93E2, 0xFF40, 0xFE80, 0xFE80, 0xFEE0, 0xFEC1, // 0x0BD0 (3024) +0x6B01, 0x1061, 0x18C1, 0x4A00, 0x5AA0, 0x5240, 0x3141, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4A01, 0xDDC1, 0xFF20, // 0x0BE0 (3040) +0xFE80, 0xFF00, 0xE602, 0x5A41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2921, 0x5220, 0x5AA0, 0x4A00, 0x20E1, 0x1060, // 0x0BF0 (3056) +0x6AE1, 0xF6A1, 0xFEE0, 0xFEA1, 0xFEA0, 0xFF41, 0x93E1, 0x0000, 0x0000, 0x0000, 0x0000, 0x2124, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C00 (3072) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8C71, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, 0xCD61, 0xFF00, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0C10 (3088) +0xFF41, 0xDDE1, 0x6B01, 0x18C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A0, 0x5A61, 0xBCE2, 0xFF01, 0xFEE0, 0xFEA0, // 0x0C20 (3104) +0xFEC0, 0xFEA0, 0xFEE0, 0xFF01, 0xC541, 0x6281, 0x20C1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C1, 0x6AE1, 0xDDC1, // 0x0C30 (3120) +0xFF41, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF01, 0xC541, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0xA514, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C40 (3136) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x4208, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A1, 0xDE01, 0xFF00, 0xFE80, 0xFEC0, // 0x0C50 (3152) +0xFEA0, 0xFEE0, 0xFF20, 0xFEC1, 0xD5A2, 0xAC82, 0x9401, 0x93E1, 0x9C42, 0xC522, 0xEE41, 0xFF01, 0xFF00, 0xFEA0, 0xFEA0, 0xFEC0, // 0x0C60 (3168) +0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFF00, 0xFF21, 0xF661, 0xC542, 0xA462, 0x93E1, 0x9C01, 0xB4A2, 0xD5A1, 0xFEC1, 0xFF20, 0xFEE0, // 0x0C70 (3184) +0xFEA0, 0xFEC0, 0xFE80, 0xFF00, 0xDE01, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x52AA, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0C80 (3200) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD6BA, 0x10A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x2921, 0xE641, 0xFF00, 0xFE80, // 0x0C90 (3216) +0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0CA0 (3232) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF20, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0CB0 (3248) +0xFEA0, 0xFE80, 0xFF00, 0xE641, 0x2901, 0x0000, 0x0000, 0x0000, 0x0000, 0x2124, 0xE71C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0CC0 (3264) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD55, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2901, 0xDE01, 0xFF00, // 0x0CD0 (3280) +0xFE80, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0CE0 (3296) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEA0, // 0x0CF0 (3312) +0xFE80, 0xFF00, 0xDE01, 0x2900, 0x0000, 0x0000, 0x0000, 0x0000, 0x0861, 0xBDD7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D00 (3328) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0x8430, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18A1, 0xC561, // 0x0D10 (3344) +0xFF21, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0D20 (3360) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, // 0x0D30 (3376) +0xFF41, 0xC561, 0x18A1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CD3, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D40 (3392) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, // 0x0D50 (3408) +0x9402, 0xFF01, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0D60 (3424) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF01, // 0x0D70 (3440) +0x9402, 0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0D80 (3456) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x73AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0D90 (3472) +0x0000, 0x4A01, 0xDDC1, 0xFF41, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0DA0 (3488) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF21, 0xD5C1, 0x4A01, // 0x0DB0 (3504) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C51, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0DC0 (3520) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8430, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0DD0 (3536) +0x0000, 0x0000, 0x0840, 0x7B61, 0xE641, 0xFF21, 0xFEE0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, // 0x0DE0 (3552) +0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEE0, 0xFF21, 0xE621, 0x7B42, 0x0840, 0x0000, // 0x0DF0 (3568) +0x0000, 0x0000, 0x0000, 0x0000, 0x0841, 0x9492, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E00 (3584) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD55, 0x10A2, 0x0000, 0x0000, // 0x0E10 (3600) +0x0000, 0x0000, 0x0000, 0x0000, 0x1880, 0x7B21, 0xD5A1, 0xFF01, 0xFF20, 0xFF00, 0xFEC0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, // 0x0E20 (3616) +0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEA0, 0xFEC0, 0xFF00, 0xFF20, 0xFF01, 0xD5A1, 0x7321, 0x1880, 0x0000, 0x0000, 0x0000, // 0x0E30 (3632) +0x0000, 0x0000, 0x0000, 0x18E3, 0xAD75, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E40 (3648) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xD69A, 0x4228, 0x0000, // 0x0E50 (3664) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x41C1, 0x93E1, 0xD5A1, 0xFEA1, 0xFF01, 0xFF20, 0xFF20, 0xFF20, 0xFF00, // 0x0E60 (3680) +0xFF00, 0xFF00, 0xFF20, 0xFF20, 0xFF20, 0xFF01, 0xFEA1, 0xD5A1, 0x93E1, 0x41C1, 0x0020, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, // 0x0E70 (3696) +0x0000, 0x0000, 0x528A, 0xD6BA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0E80 (3712) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0x8C71, // 0x0E90 (3728) +0x10A2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2901, 0x5221, 0x7B41, 0x9402, 0xAC82, 0xBCE2, // 0x0EA0 (3744) +0xC521, 0xBCE2, 0xAC82, 0x9401, 0x7B41, 0x5221, 0x2901, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0EB0 (3760) +0x18E3, 0x94B2, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0EC0 (3776) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0ED0 (3792) +0xD6BA, 0x632C, 0x0841, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0EE0 (3808) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x10A2, 0x738E, // 0x0EF0 (3824) +0xDEFB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F00 (3840) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F10 (3856) +0xFFFF, 0xFFFF, 0xCE79, 0x6B4D, 0x18C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, // 0x0F20 (3872) +0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2104, 0x738E, 0xD69A, 0xFFFF, // 0x0F30 (3888) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F40 (3904) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F50 (3920) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE71C, 0x94B2, 0x4A49, 0x1082, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0F60 (3936) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C3, 0x4A69, 0x9CD3, 0xE73C, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F70 (3952) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F80 (3968) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0F90 (3984) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0xA534, 0x6B6D, 0x4208, 0x2104, 0x18C3, 0x0861, 0x0841, 0x0000, // 0x0FA0 (4000) +0x0000, 0x0000, 0x0841, 0x0861, 0x18C3, 0x2124, 0x4228, 0x6B6D, 0xA534, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FB0 (4016) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FC0 (4032) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FD0 (4048) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDB, 0xB5B6, 0x9492, 0x6B6D, 0x4A49, // 0x0FE0 (4064) +0x4228, 0x4A49, 0x6B6D, 0x8C51, 0xAD75, 0xDEDB, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0FF0 (4080) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x1000 (4096) +}; diff --git a/libraries/UTFT/examples/chipKit/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.pde b/libraries/UTFT/examples/chipKit/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.pde new file mode 100644 index 0000000..f9db69a --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_Textrotation_Demo/UTFT_Textrotation_Demo.pde @@ -0,0 +1,51 @@ +// UTFT_Textrotation_Demo (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the textrotation-functions. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,82,83,84,85); + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(BigFont); +} + +void loop() +{ + myGLCD.print("Text rotation", 0, 0); + myGLCD.setColor(0, 0, 255); + myGLCD.print("0 degrees", 0, 16, 0); + myGLCD.print("90 degrees", 319, 0, 90); + myGLCD.print("180 degrees", 319, 239, 180); + myGLCD.print("270 degrees", 0, 239, 270); + + myGLCD.setFont(SevenSegNumFont); + myGLCD.setColor(0, 255, 0); + myGLCD.print("45", 90, 100, 45); + myGLCD.print("90", 200, 50, 90); + myGLCD.print("180", 300, 200, 180); + + while (true) {}; +} + diff --git a/libraries/UTFT/examples/chipKit/UTFT_ViewFont/UTFT_ViewFont.pde b/libraries/UTFT/examples/chipKit/UTFT_ViewFont/UTFT_ViewFont.pde new file mode 100644 index 0000000..bd9fa5f --- /dev/null +++ b/libraries/UTFT/examples/chipKit/UTFT_ViewFont/UTFT_ViewFont.pde @@ -0,0 +1,58 @@ +// UTFT_ViewFont (C)2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a demo of the included fonts. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels. +// +// This program requires the UTFT library. +// + +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; +extern uint8_t BigFont[]; +extern uint8_t SevenSegNumFont[]; + +// Set the pins to the correct ones for your development shield +// ------------------------------------------------------------ +// My chipKit Uno32/uC32 shield : ,38,39,40,41 +// My chipKit Max32 shield : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,82,83,84,85); + +void setup() +{ + myGLCD.InitLCD(); + + myGLCD.clrScr(); +} + +void loop() +{ + myGLCD.setColor(0, 255, 0); + myGLCD.setBackColor(0, 0, 0); + + myGLCD.setFont(BigFont); + myGLCD.print(" !\"#$%&'()*+,-./", CENTER, 0); + myGLCD.print("0123456789:;<=>?", CENTER, 16); + myGLCD.print("@ABCDEFGHIJKLMNO", CENTER, 32); + myGLCD.print("PQRSTUVWXYZ[\\]^_", CENTER, 48); + myGLCD.print("`abcdefghijklmno", CENTER, 64); + myGLCD.print("pqrstuvwxyz{|}~ ", CENTER, 80); + + myGLCD.setFont(SmallFont); + myGLCD.print(" !\"#$%&'()*+,-./0123456789:;<=>?", CENTER, 120); + myGLCD.print("@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", CENTER, 132); + myGLCD.print("`abcdefghijklmnopqrstuvwxyz{|}~ ", CENTER, 144); + + myGLCD.setFont(SevenSegNumFont); + myGLCD.print("0123456789", CENTER, 190); + + while(1) {}; +} + diff --git a/libraries/UTFT/hardware/arm/HW_ARM.h b/libraries/UTFT/hardware/arm/HW_ARM.h new file mode 100644 index 0000000..c71a5ff --- /dev/null +++ b/libraries/UTFT/hardware/arm/HW_ARM.h @@ -0,0 +1,7 @@ +void UTFT::_convert_float(char *buf, double num, int width, byte prec) +{ + char format[10]; + + sprintf(format, "%%%i.%if", width, prec); + sprintf(buf, format, num); +} diff --git a/libraries/UTFT/hardware/arm/HW_ARM_defines.h b/libraries/UTFT/hardware/arm/HW_ARM_defines.h new file mode 100644 index 0000000..2881e17 --- /dev/null +++ b/libraries/UTFT/hardware/arm/HW_ARM_defines.h @@ -0,0 +1,40 @@ +// CTE TFT LCD/SD Shield for Arduino Due +// ------------------------------------- +// Uncomment the following line if you are using this shield +//#define CTE_DUE_SHIELD 1 +// +// For this shield: RS=25, WR=26, CS=27, RST=28 +//******************************************************************** + +// ElecHouse TFT LCD/SD Shield for Arduino Due +// ------------------------------------- +// Uncomment the following line if you are using this shield +//#define EHOUSE_DUE_SHIELD 1 +// +// For this shield: RS=22, WR=23, CS=31, RST=33 +//******************************************************************** + +// *** Hardwarespecific defines *** +#define cbi(reg, bitmask) *reg &= ~bitmask +#define sbi(reg, bitmask) *reg |= bitmask +#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask); +#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask); + +#define cport(port, data) port &= data +#define sport(port, data) port |= data + +#define swap(type, i, j) {type t = i; i = j; j = t;} + +#define fontbyte(x) cfont.font[x] + +#define pgm_read_word(data) *data +#define pgm_read_byte(data) *data +#define bitmapdatatype unsigned short* + +#if defined(TEENSYDUINO) && TEENSYDUINO >= 117 + #define regtype volatile uint8_t + #define regsize uint8_t +#else + #define regtype volatile uint32_t + #define regsize uint32_t +#endif diff --git a/libraries/UTFT/hardware/arm/HW_MX20DX256.h b/libraries/UTFT/hardware/arm/HW_MX20DX256.h new file mode 100644 index 0000000..93df980 --- /dev/null +++ b/libraries/UTFT/hardware/arm/HW_MX20DX256.h @@ -0,0 +1,188 @@ +/** + * + * This file is a modified version of the HW_Teensy3.h created by Paul Stoffregen. + * + * Teensy 3.x pin definitions created by Dawnmist + * http://forum.pjrc.com/threads/18002-Teensy-3-0-driving-an-SSD1289-with-utft?p=34719&viewfull=1#post34719 + * + * This file only supports the B and D ports as defined by Dawnmist for 8-bit and 16-bit display modules. + * Serial display modules are also supported. + * + * NOTE: This file has only been tested on a Teensy 3.1 + * +**/ + +// *** Hardware specific functions *** +void UTFT::_hw_special_init() +{ +} + +void UTFT::LCD_Writ_Bus(char VH,char VL, byte mode) +{ + switch (mode) + { + case 1: + if (display_serial_mode==SERIAL_4PIN) + { + if (VH==1) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + } + else + { + if (VH==1) + sbi(P_RS, B_RS); + else + cbi(P_RS, B_RS); + } + + if (VL & 0x80) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + if (VL & 0x40) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + if (VL & 0x20) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + if (VL & 0x10) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + if (VL & 0x08) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + if (VL & 0x04) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + if (VL & 0x02) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + if (VL & 0x01) + sbi(P_SDA, B_SDA); + else + cbi(P_SDA, B_SDA); + pulse_low(P_SCL, B_SCL); + break; + case 8: + *(volatile uint8_t *)(&GPIOD_PDOR) = VH; + pulse_low(P_WR, B_WR); + *(volatile uint8_t *)(&GPIOD_PDOR) = VL; + pulse_low(P_WR, B_WR); + break; + case 16: + *(volatile uint8_t *)(&GPIOD_PDOR) = VH; + GPIOB_PCOR = 0x000F000F; // clear data lines B0-3,B16-19 + GPIOB_PSOR = (0x0F & VL) | ((VL >> 4) << 16); // set data lines 0-3,16-19 if set in cl + pulse_low(P_WR, B_WR); + break; + } +} + +void UTFT::_set_direction_registers(byte mode) +{ + GPIOD_PDDR |= 0xFF; + PORTD_PCR0 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTD_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTD_PCR2 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTD_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTD_PCR4 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTD_PCR5 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTD_PCR6 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTD_PCR7 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + + if (mode == 16) + { + GPIOB_PDDR |= 0x000F000F; + PORTB_PCR0 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTB_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTB_PCR2 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTB_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTB_PCR16 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTB_PCR17 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTB_PCR18 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + PORTB_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + } +} +void UTFT::_fast_fill_16(int ch, int cl, long pix) +{ + long blocks; + + *(volatile uint8_t *)(&GPIOD_PDOR) = ch; + GPIOB_PCOR = 0x000F000F; // clear data lines B0-3,B16-19 + GPIOB_PSOR = (0x0F & cl) | ((cl >> 4) << 16); // set data lines 0-3,16-19 if set in cl + + blocks = pix/16; + for (int i=0; i>3) | ((VH & 0x80)>>1); + pulse_low(P_WR, B_WR); + + REG_PIOA_CODR=0x0000C000; + REG_PIOD_CODR=0x0000064F; + REG_PIOA_SODR=(VL & 0x06)<<13; + (VL & 0x01) ? REG_PIOB_SODR = 0x4000000 : REG_PIOB_CODR = 0x4000000; + REG_PIOD_SODR=((VL & 0x78)>>3) | ((VL & 0x80)>>1); + pulse_low(P_WR, B_WR); +#endif + break; + case 16: +#if defined(CTE_DUE_SHIELD) + REG_PIOC_CODR=0xFF1FE; + REG_PIOC_SODR=(VL<<1) & 0x1FE; + REG_PIOC_SODR=(VH<<12) & 0xFF000; +#elif defined(EHOUSE_DUE_SHIELD) + PIOC->PIO_ODSR = ((PIOC->PIO_ODSR&(~0x000FF3FC)) | ((((uint32_t)VL)<<2) | (((uint32_t)VH)<<12))); +#else + REG_PIOA_CODR=0x0000C080; + REG_PIOC_CODR=0x0000003E; + REG_PIOD_CODR=0x0000064F; + REG_PIOA_SODR=((VH & 0x06)<<13) | ((VL & 0x40)<<1); + (VH & 0x01) ? REG_PIOB_SODR = 0x4000000 : REG_PIOB_CODR = 0x4000000; + REG_PIOC_SODR=((VL & 0x01)<<5) | ((VL & 0x02)<<3) | ((VL & 0x04)<<1) | ((VL & 0x08)>>1) | ((VL & 0x10)>>3); + REG_PIOD_SODR=((VH & 0x78)>>3) | ((VH & 0x80)>>1) | ((VL & 0x20)<<5) | ((VL & 0x80)<<2); +#endif + pulse_low(P_WR, B_WR); + break; + case LATCHED_16: + asm("nop"); // Mode is unsupported + break; + } +} + +void UTFT::_set_direction_registers(byte mode) +{ + if (mode!=LATCHED_16) + { +#if defined(CTE_DUE_SHIELD) + if (mode==16) + { + REG_PIOC_OER=0x000FF1FE; + } + else + REG_PIOC_OER=0x000FF000; +#elif defined(EHOUSE_DUE_SHIELD) + if (mode==16) + { + REG_PIOC_OER=0x000FF3FC; + REG_PIOC_OWER=0x000FF3FC; + } + else + REG_PIOC_OER=0x000FF000; +#else + REG_PIOA_OER=0x0000c000; //PA14,PA15 enable + REG_PIOB_OER=0x04000000; //PB26 enable + REG_PIOD_OER=0x0000064f; //PD0-3,PD6,PD9-10 enable + if (mode==16) + { + REG_PIOA_OER=0x00000080; //PA7 enable + REG_PIOC_OER=0x0000003e; //PC1 - PC5 enable + } +#endif + } + else + { + asm("nop"); // Mode is unsupported + } +} + +void UTFT::_fast_fill_16(int ch, int cl, long pix) +{ + long blocks; + +#if defined(CTE_DUE_SHIELD) + REG_PIOC_CODR=0xFF1FE; + REG_PIOC_SODR=(cl<<1) & 0x1FE; + REG_PIOC_SODR=(ch<<12) & 0xFF000; +#elif defined(EHOUSE_DUE_SHIELD) + PIOC->PIO_ODSR = ((PIOC->PIO_ODSR&(~0x000FF3FC)) | ((((uint32_t)cl)<<2) | (((uint32_t)ch)<<12))); +#else + REG_PIOA_CODR=0x0000C080; + REG_PIOC_CODR=0x0000003E; + REG_PIOD_CODR=0x0000064F; + REG_PIOA_SODR=((ch & 0x06)<<13) | ((cl & 0x40)<<1); + (ch & 0x01) ? REG_PIOB_SODR = 0x4000000 : REG_PIOB_CODR = 0x4000000; + REG_PIOC_SODR=((cl & 0x01)<<5) | ((cl & 0x02)<<3) | ((cl & 0x04)<<1) | ((cl & 0x08)>>1) | ((cl & 0x10)>>3); + REG_PIOD_SODR=((ch & 0x78)>>3) | ((ch & 0x80)>>1) | ((cl & 0x20)<<5) | ((cl & 0x80)<<2); +#endif + + blocks = pix/16; + for (int i=0; i>3) | ((ch & 0x80)>>1); +#endif + + blocks = pix/16; + for (int i=0; i>3; + PORTE &= ~0x3B; + PORTE |= (VH & 0x03) + ((VH & 0x0C)<<2) + ((VH & 0x20)>>2); + pulse_low(P_WR, B_WR); + PORTG &= ~0x20; + PORTG |= (VL & 0x10)<<1; + PORTH &= ~0x18; + PORTH |= (VL & 0xC0)>>3; + PORTE &= ~0x3B; + PORTE |= (VL & 0x03) + ((VL & 0x0C)<<2) + ((VL & 0x20)>>2); + pulse_low(P_WR, B_WR); +#else + PORTA = VH; + pulse_low(P_WR, B_WR); + PORTA = VL; + pulse_low(P_WR, B_WR); +#endif + break; + case 16: + PORTA = VH; + PORTC = VL; + pulse_low(P_WR, B_WR); + break; + case LATCHED_16: + PORTG &= ~0x20; + PORTG |= (VH & 0x10)<<1; + PORTH &= ~0x18; + PORTH |= (VH & 0xC0)>>3; + PORTE &= ~0x3B; + PORTE |= (VH & 0x03) + ((VH & 0x0C)<<2) + ((VH & 0x20)>>2); + cbi(P_ALE, B_ALE); + pulse_high(P_ALE, B_ALE); + cbi(P_CS, B_CS); + PORTG &= ~0x20; + PORTG |= (VL & 0x10)<<1; + PORTH &= ~0x18; + PORTH |= (VL & 0xC0)>>3; + PORTE &= ~0x3B; + PORTE |= (VL & 0x03) + ((VL & 0x0C)<<2) + ((VL & 0x20)>>2); + pulse_low(P_WR, B_WR); + sbi(P_CS, B_CS); + break; + } +} + +void UTFT::_set_direction_registers(byte mode) +{ +#if defined(USE_UNO_SHIELD_ON_MEGA) + DDRH = 0x18; + DDRG = 0x20; + DDRE = 0x3B; +#else + if (mode!=LATCHED_16) + { + DDRA = 0xFF; + if (mode==16) + DDRC = 0xFF; + } + else + { + DDRH = 0x18; + DDRG = 0x20; + DDRE = 0x3B; + } +#endif +} + +void UTFT::_fast_fill_16(int ch, int cl, long pix) +{ +#if defined(USE_UNO_SHIELD_ON_MEGA) + if (ch==cl) + _fast_fill_8(ch, pix); + else + { + for (int i=0; i>3; + PORTE &= ~0x3B; + PORTE |= (ch & 0x03) + ((ch & 0x0C)<<2) + ((ch & 0x20)>>2); + pulse_low(P_WR, B_WR); + PORTG &= ~0x20; + PORTG |= (cl & 0x10)<<1; + PORTH &= ~0x18; + PORTH |= (cl & 0xC0)>>3; + PORTE &= ~0x3B; + PORTE |= (cl & 0x03) + ((cl & 0x0C)<<2) + ((cl & 0x20)>>2); + pulse_low(P_WR, B_WR); + } + } +#else + long blocks; + + PORTA = ch; + PORTC = cl; + + blocks = pix/16; + for (int i=0; i>3; + PORTE &= ~0x3B; + PORTE |= (ch & 0x03) + ((ch & 0x0C)<<2) + ((ch & 0x20)>>2); +#else + PORTA = ch; +#endif + + blocks = pix/16; + for (int i=0; i>4); + pulse_low(P_WR, B_WR); + cport (PORTD, 0xF0); + sport (PORTD, (VL & 0x0F)); + cport (PORTB, 0xF0); + sport (PORTB, (VL & 0xF0)>>4); + pulse_low(P_WR, B_WR); + break; + case 16: + cport (PORTD, 0x90); + sport (PORTD, (VH & 0x0F) | ((VL & 0x03)<<5)); + PORTB = ((VH & 0xF0)>>4) | ((VL & 0x3C)<<2); + cport (PORTA, 0x3F); + sport (PORTA, ((VL & 0x40)<<1) | ((VL & 0x80)>>1)); + pulse_low(P_WR, B_WR); + break; + case LATCHED_16: + cport (PORTD, 0xF0); + sport (PORTD, (VH & 0x0F)); + cport (PORTB, 0xF0); + sport (PORTB, (VH & 0xF0)>>4); + cbi(P_ALE, B_ALE); + pulse_high(P_ALE, B_ALE); + cbi(P_CS, B_CS); + cport (PORTD, 0xF0); + sport (PORTD, (VL & 0x0F)); + cport (PORTB, 0xF0); + sport (PORTB, (VL & 0xF0)>>4); + pulse_low(P_WR, B_WR); + sbi(P_CS, B_CS); + break; + } +} + +void UTFT::_set_direction_registers(byte mode) +{ + DDRB |= 0x0F; + DDRD |= 0x0F; + if (mode==16) + { + DDRB = 0xFF; + DDRD |= 0x6F; + DDRA |= 0xC0; + } + +} + +void UTFT::_fast_fill_16(int ch, int cl, long pix) +{ + long blocks; + + cport (PORTD, 0x90); + sport (PORTD, (ch & 0x0F) | ((cl & 0x03)<<5)); + PORTB = ((ch & 0xF0)>>4) | ((cl & 0x3C)<<2); + cport (PORTA, 0x3F); + sport (PORTA, ((cl & 0x40)<<1) | ((cl & 0x80)>>1)); + + blocks = pix/16; + for (int i=0; i>4); + + blocks = pix/16; + for (int i=0; i>6) & 0x03); + PORTB = VL & 0x3F; + pulse_low(P_WR, B_WR); + break; + case LATCHED_16: + PORTD = VH; + cbi(P_ALE, B_ALE); + pulse_high(P_ALE, B_ALE); + cbi(P_CS, B_CS); + PORTD = VL; + pulse_low(P_WR, B_WR); + sbi(P_CS, B_CS); + break; + } +} + +void UTFT::_set_direction_registers(byte mode) +{ + DDRD = 0xFF; + if (mode==16) + { + DDRB |= 0x3F; + DDRC |= 0x03; + } + +} + +void UTFT::_fast_fill_16(int ch, int cl, long pix) +{ + long blocks; + + PORTD = ch; + cport(PORTC, 0xFC); + sport(PORTC, (cl>>6) & 0x03); + PORTB = cl & 0x3F; + + blocks = pix/16; + for (int i=0; i>3) + ((VH & 0x04)>>1) + ((VH & 0x03)<<2); + PORTE += ((VH & 0x80)>>1); + pulse_low(P_WR, B_WR); + + cport(PORTC, 0xBF); + cport(PORTD, 0x60); + cport(PORTE, 0xBF); + PORTC += ((VL & 0x20)<<1); + PORTD += ((VL & 0x40)<<1) + (VL & 0x10) + ((VL & 0x08)>>3) + ((VL & 0x04)>>1) + ((VL & 0x03)<<2); + PORTE += ((VL & 0x80)>>1); + pulse_low(P_WR, B_WR); + break; + case 16: + cport(PORTB, 0x0F); + cport(PORTC, 0x3F); + cport(PORTD, 0x20); + cport(PORTE, 0xBF); + cport(PORTF, 0x3F); + + PORTB |= ((VL & 0x0F)<<4); + PORTC |= ((VL & 0x20)<<2) + ((VH & 0x20)<<1); + PORTD |= ((VH & 0x40)<<1) + (VH & 0x10) + ((VH & 0x08)>>3) + ((VH & 0x04)>>1) + ((VH & 0x03)<<2) + ((VL & 0x10)<<2); + PORTE |= ((VH & 0x80)>>1); + PORTF |= ((VL & 0x80)>>1) + ((VL & 0x40)<<1); + + pulse_low(P_WR, B_WR); + break; + case LATCHED_16: + cport(PORTC, 0xBF); + cport(PORTD, 0x60); + cport(PORTE, 0xBF); + PORTC += ((VH & 0x20)<<1); + PORTD += ((VH & 0x40)<<1) + (VH & 0x10) + ((VH & 0x08)>>3) + ((VH & 0x04)>>1) + ((VH & 0x03)<<2); + PORTE += ((VH & 0x80)>>1); + cbi(P_ALE, B_ALE); + pulse_high(P_ALE, B_ALE); + cbi(P_CS, B_CS); + cport(PORTC, 0xBF); + cport(PORTD, 0x60); + cport(PORTE, 0xBF); + PORTC += ((VL & 0x20)<<1); + PORTD += ((VL & 0x40)<<1) + (VL & 0x10) + ((VL & 0x08)>>3) + ((VL & 0x04)>>1) + ((VL & 0x03)<<2); + PORTE += ((VL & 0x80)>>1); + pulse_low(P_WR, B_WR); + sbi(P_CS, B_CS); + break; + } +} + +void UTFT::_set_direction_registers(byte mode) +{ + switch (mode) + { + case 8: + case LATCHED_16: + DDRC |= 0x40; + DDRD |= 0x9F; + DDRE |= 0x40; + break; + case 16: + DDRB |= 0xF0; + DDRC |= 0xC0; + DDRD |= 0xDF; + DDRE |= 0x40; + DDRF |= 0xC0; + break; + } +} + +void UTFT::_fast_fill_16(int ch, int cl, long pix) +{ + long blocks; + + cport(PORTB, 0x0F); + cport(PORTC, 0x3F); + cport(PORTD, 0x20); + cport(PORTE, 0xBF); + cport(PORTF, 0x3F); + + PORTB |= ((cl & 0x0F)<<4); + PORTC |= ((cl & 0x20)<<2) + ((ch & 0x20)<<1); + PORTD |= ((ch & 0x40)<<1) + (ch & 0x10) + ((ch & 0x08)>>3) + ((ch & 0x04)>>1) + ((ch & 0x03)<<2) + ((cl & 0x10)<<2); + PORTE |= ((ch & 0x80)>>1); + PORTF |= ((cl & 0x80)>>1) + ((cl & 0x40)<<1); + + blocks = pix/16; + for (int i=0; i>3) + ((ch & 0x04)>>1) + ((ch & 0x03)<<2); + PORTE |= ((ch & 0x80)>>1); + + blocks = pix/16; + for (int i=0; i>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/hx8347a/initlcd.h b/libraries/UTFT/tft_drivers/hx8347a/initlcd.h new file mode 100644 index 0000000..76bf08e --- /dev/null +++ b/libraries/UTFT/tft_drivers/hx8347a/initlcd.h @@ -0,0 +1,88 @@ +case HX8347A: + LCD_Write_COM_DATA(0x46,0x00A4); + LCD_Write_COM_DATA(0x47,0x0053); + LCD_Write_COM_DATA(0x48,0x0000); + LCD_Write_COM_DATA(0x49,0x0044); + LCD_Write_COM_DATA(0x4a,0x0004); + LCD_Write_COM_DATA(0x4b,0x0067); + LCD_Write_COM_DATA(0x4c,0x0033); + LCD_Write_COM_DATA(0x4d,0x0077); + LCD_Write_COM_DATA(0x4e,0x0012); + LCD_Write_COM_DATA(0x4f,0x004C); + LCD_Write_COM_DATA(0x50,0x0046); + LCD_Write_COM_DATA(0x51,0x0044); + + //240x320 window setting + LCD_Write_COM_DATA(0x02,0x0000); // Column address start2 + LCD_Write_COM_DATA(0x03,0x0000); // Column address start1 + LCD_Write_COM_DATA(0x04,0x0000); // Column address end2 + LCD_Write_COM_DATA(0x05,0x00ef); // Column address end1 + LCD_Write_COM_DATA(0x06,0x0000); // Row address start2 + LCD_Write_COM_DATA(0x07,0x0000); // Row address start1 + LCD_Write_COM_DATA(0x08,0x0001); // Row address end2 + LCD_Write_COM_DATA(0x09,0x003f); // Row address end1 + + // Display Setting + LCD_Write_COM_DATA(0x01,0x0006); // IDMON=0, INVON=1, NORON=1, PTLON=0 + LCD_Write_COM_DATA(0x16,0x00C8); // MY=0, MX=0, MV=0, ML=1, BGR=0, TEON=0 0048 + LCD_Write_COM_DATA(0x23,0x0095); // N_DC=1001 0101 + LCD_Write_COM_DATA(0x24,0x0095); // PI_DC=1001 0101 + LCD_Write_COM_DATA(0x25,0x00FF); // I_DC=1111 1111 + + LCD_Write_COM_DATA(0x27,0x0002); // N_BP=0000 0010 + LCD_Write_COM_DATA(0x28,0x0002); // N_FP=0000 0010 + LCD_Write_COM_DATA(0x29,0x0002); // PI_BP=0000 0010 + LCD_Write_COM_DATA(0x2a,0x0002); // PI_FP=0000 0010 + LCD_Write_COM_DATA(0x2C,0x0002); // I_BP=0000 0010 + LCD_Write_COM_DATA(0x2d,0x0002); // I_FP=0000 0010 + + LCD_Write_COM_DATA(0x3a,0x0001); // N_RTN=0000, N_NW=001 0001 + LCD_Write_COM_DATA(0x3b,0x0000); // P_RTN=0000, P_NW=001 + LCD_Write_COM_DATA(0x3c,0x00f0); // I_RTN=1111, I_NW=000 + LCD_Write_COM_DATA(0x3d,0x0000); // DIV=00 + delay(1); + LCD_Write_COM_DATA(0x35,0x0038); // EQS=38h + LCD_Write_COM_DATA(0x36,0x0078); // EQP=78h + LCD_Write_COM_DATA(0x3E,0x0038); // SON=38h + LCD_Write_COM_DATA(0x40,0x000F); // GDON=0Fh + LCD_Write_COM_DATA(0x41,0x00F0); // GDOFF + + // Power Supply Setting + LCD_Write_COM_DATA(0x19,0x0049); // CADJ=0100, CUADJ=100, OSD_EN=1 ,60Hz + LCD_Write_COM_DATA(0x93,0x000F); // RADJ=1111, 100% + delay(1); + LCD_Write_COM_DATA(0x20,0x0040); // BT=0100 + LCD_Write_COM_DATA(0x1D,0x0007); // VC1=111 0007 + LCD_Write_COM_DATA(0x1E,0x0000); // VC3=000 + LCD_Write_COM_DATA(0x1F,0x0004); // VRH=0011 + + //VCOM SETTING + LCD_Write_COM_DATA(0x44,0x004D); // VCM=101 0000 4D + LCD_Write_COM_DATA(0x45,0x000E); // VDV=1 0001 0011 + delay(1); + LCD_Write_COM_DATA(0x1C,0x0004); // AP=100 + delay(2); + + LCD_Write_COM_DATA(0x1B,0x0018); // GASENB=0, PON=0, DK=1, XDK=0, VLCD_TRI=0, STB=0 + delay(1); + LCD_Write_COM_DATA(0x1B,0x0010); // GASENB=0, PON=1, DK=0, XDK=0, VLCD_TRI=0, STB=0 + delay(1); + LCD_Write_COM_DATA(0x43,0x0080); //set VCOMG=1 + delay(2); + + // Display ON Setting + LCD_Write_COM_DATA(0x90,0x007F); // SAP=0111 1111 + LCD_Write_COM_DATA(0x26,0x0004); //GON=0, DTE=0, D=01 + delay(1); + LCD_Write_COM_DATA(0x26,0x0024); //GON=1, DTE=0, D=01 + LCD_Write_COM_DATA(0x26,0x002C); //GON=1, DTE=0, D=11 + delay(1); + LCD_Write_COM_DATA(0x26,0x003C); //GON=1, DTE=1, D=11 + + // INTERNAL REGISTER SETTING + LCD_Write_COM_DATA(0x57,0x0002); // TEST_Mode=1: into TEST mode + LCD_Write_COM_DATA(0x95,0x0001); // SET DISPLAY CLOCK AND PUMPING CLOCK TO SYNCHRONIZE + LCD_Write_COM_DATA(0x57,0x0000); // TEST_Mode=0: exit TEST mode + //LCD_Write_COM_DATA(0x21,0x0000); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/hx8347a/setxy.h b/libraries/UTFT/tft_drivers/hx8347a/setxy.h new file mode 100644 index 0000000..bf82d6b --- /dev/null +++ b/libraries/UTFT/tft_drivers/hx8347a/setxy.h @@ -0,0 +1,11 @@ +case HX8347A: + LCD_Write_COM_DATA(0x02,x1>>8); + LCD_Write_COM_DATA(0x03,x1); + LCD_Write_COM_DATA(0x04,x2>>8); + LCD_Write_COM_DATA(0x05,x2); + LCD_Write_COM_DATA(0x06,y1>>8); + LCD_Write_COM_DATA(0x07,y1); + LCD_Write_COM_DATA(0x08,y2>>8); + LCD_Write_COM_DATA(0x09,y2); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/hx8352a/initlcd.h b/libraries/UTFT/tft_drivers/hx8352a/initlcd.h new file mode 100644 index 0000000..5645bbe --- /dev/null +++ b/libraries/UTFT/tft_drivers/hx8352a/initlcd.h @@ -0,0 +1,131 @@ +case HX8352A: + LCD_Write_COM(0x83); + LCD_Write_DATA(0x02); //TESTM=1 + + LCD_Write_COM(0x85); + LCD_Write_DATA(0x03); //VDC_SEL=011 + LCD_Write_COM(0x8B); + LCD_Write_DATA(0x01); + LCD_Write_COM(0x8C); + LCD_Write_DATA(0x93); //STBA[7]=1,STBA[5:4]=01,STBA[1:0]=11 + + LCD_Write_COM(0x91); + LCD_Write_DATA(0x01); //DCDC_SYNC=1 + + LCD_Write_COM(0x83); + LCD_Write_DATA(0x00); //TESTM=0 + //Gamma Setting + + LCD_Write_COM(0x3E); + LCD_Write_DATA(0xB0); + LCD_Write_COM(0x3F); + LCD_Write_DATA(0x03); + LCD_Write_COM(0x40); + LCD_Write_DATA(0x10); + LCD_Write_COM(0x41); + LCD_Write_DATA(0x56); + LCD_Write_COM(0x42); + LCD_Write_DATA(0x13); + LCD_Write_COM(0x43); + LCD_Write_DATA(0x46); + LCD_Write_COM(0x44); + LCD_Write_DATA(0x23); + LCD_Write_COM(0x45); + LCD_Write_DATA(0x76); + LCD_Write_COM(0x46); + LCD_Write_DATA(0x00); + LCD_Write_COM(0x47); + LCD_Write_DATA(0x5E); + LCD_Write_COM(0x48); + LCD_Write_DATA(0x4F); + LCD_Write_COM(0x49); + LCD_Write_DATA(0x40); + //**********Power On sequence************ + + LCD_Write_COM(0x17); + LCD_Write_DATA(0x91); + + LCD_Write_COM(0x2B); + LCD_Write_DATA(0xF9); + delay(10); + + LCD_Write_COM(0x1B); + LCD_Write_DATA(0x14); + + LCD_Write_COM(0x1A); + LCD_Write_DATA(0x11); + + LCD_Write_COM(0x1C); + LCD_Write_DATA(0x06); + + LCD_Write_COM(0x1F); + LCD_Write_DATA(0x42); + delay(20); + + LCD_Write_COM(0x19); + LCD_Write_DATA(0x0A); + + LCD_Write_COM(0x19); + LCD_Write_DATA(0x1A); + delay(40); + + + LCD_Write_COM(0x19); + LCD_Write_DATA(0x12); + delay(40); + + LCD_Write_COM(0x1E); + LCD_Write_DATA(0x27); + delay(100); + + + //**********DISPLAY ON SETTING*********** + + LCD_Write_COM(0x24); + LCD_Write_DATA(0x60); + + LCD_Write_COM(0x3D); + LCD_Write_DATA(0x40); + + LCD_Write_COM(0x34); + LCD_Write_DATA(0x38); + + LCD_Write_COM(0x35); + LCD_Write_DATA(0x38); + + LCD_Write_COM(0x24); + LCD_Write_DATA(0x38); + delay(40); + + LCD_Write_COM(0x24); + LCD_Write_DATA(0x3C); + + LCD_Write_COM(0x16); + LCD_Write_DATA(0x1C); + + LCD_Write_COM(0x01); + LCD_Write_DATA(0x06); + + LCD_Write_COM(0x55); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0x02); + LCD_Write_DATA(0x00); + LCD_Write_COM(0x03); + LCD_Write_DATA(0x00); + LCD_Write_COM(0x04); + LCD_Write_DATA(0x00); + LCD_Write_COM(0x05); + LCD_Write_DATA(0xef); + + LCD_Write_COM(0x06); + LCD_Write_DATA(0x00); + LCD_Write_COM(0x07); + LCD_Write_DATA(0x00); + LCD_Write_COM(0x08); + LCD_Write_DATA(0x01); + LCD_Write_COM(0x09); + LCD_Write_DATA(0x8f); + + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/hx8352a/setxy.h b/libraries/UTFT/tft_drivers/hx8352a/setxy.h new file mode 100644 index 0000000..225fe65 --- /dev/null +++ b/libraries/UTFT/tft_drivers/hx8352a/setxy.h @@ -0,0 +1,11 @@ +case HX8352A: + LCD_Write_COM_DATA(0x02,x1>>8); + LCD_Write_COM_DATA(0x03,x1); + LCD_Write_COM_DATA(0x04,x2>>8); + LCD_Write_COM_DATA(0x05,x2); + LCD_Write_COM_DATA(0x06,y1>>8); + LCD_Write_COM_DATA(0x07,y1); + LCD_Write_COM_DATA(0x08,y2>>8); + LCD_Write_COM_DATA(0x09,y2); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/hx8353c/initlcd.h b/libraries/UTFT/tft_drivers/hx8353c/initlcd.h new file mode 100644 index 0000000..70b6f29 --- /dev/null +++ b/libraries/UTFT/tft_drivers/hx8353c/initlcd.h @@ -0,0 +1,69 @@ +case HX8353C: + LCD_Write_COM(0xB9);//SETEXTC + LCD_Write_DATA(0xFF); + LCD_Write_DATA(0x83); + LCD_Write_DATA(0x53); + + LCD_Write_COM(0xB0);//RADJ + LCD_Write_DATA(0x3C); + LCD_Write_DATA(0x01); + + LCD_Write_COM(0xB6);//VCOM + LCD_Write_DATA(0x94); + LCD_Write_DATA(0x6C); + LCD_Write_DATA(0x50); + + LCD_Write_COM(0xB1);//PWR + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x1B); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x77); + LCD_Write_DATA(0x89); + + LCD_Write_COM(0xE0); //Gamma setting for tpo Panel + LCD_Write_DATA(0x50); + LCD_Write_DATA(0x77); + LCD_Write_DATA(0x40); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0xBF); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x73); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x72); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0xB0); + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x0F); + + LCD_Write_COM(0x3A); + LCD_Write_DATA(0x05); //05 + LCD_Write_COM(0x36); + LCD_Write_DATA(0xC0); //83 //0B + + LCD_Write_COM(0x11); // SLPOUT + delay(150); + + LCD_Write_COM(0x29); // display on + + delay(150); + LCD_Write_COM(0x2D); //Look up table + + for(int j=0;j<32;j++) + { LCD_Write_DATA(2*j); } //Red + for(int j=0;j<64;j++) + { LCD_Write_DATA(1*j); } //Green + for(int j=0;j<32;j++) + { LCD_Write_DATA(2*j); } //Blue + + LCD_Write_COM(0x2c); + delay(150); + break; diff --git a/libraries/UTFT/tft_drivers/hx8353c/setxy.h b/libraries/UTFT/tft_drivers/hx8353c/setxy.h new file mode 100644 index 0000000..a654657 --- /dev/null +++ b/libraries/UTFT/tft_drivers/hx8353c/setxy.h @@ -0,0 +1,13 @@ +case HX8353C: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/ili9320/initlcd.h b/libraries/UTFT/tft_drivers/ili9320/initlcd.h new file mode 100644 index 0000000..a49f118 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9320/initlcd.h @@ -0,0 +1,67 @@ +case ILI9320_8: +case ILI9320_16: + LCD_Write_COM_DATA(0xe5, 0x8000); + LCD_Write_COM_DATA(0x00, 0x0001); + LCD_Write_COM_DATA(0x01, 0x0100); + LCD_Write_COM_DATA(0x02, 0x0700); + LCD_Write_COM_DATA(0x03, 0x1030); + LCD_Write_COM_DATA(0x04, 0x0000); + LCD_Write_COM_DATA(0x08, 0x0202); + LCD_Write_COM_DATA(0x09, 0x0000); + LCD_Write_COM_DATA(0x0A, 0x0000); + LCD_Write_COM_DATA(0x0C, 0x0000); + LCD_Write_COM_DATA(0x0D, 0x0000); + LCD_Write_COM_DATA(0x0F, 0x0000); + //-----Power On sequence----------------------- + LCD_Write_COM_DATA(0x10, 0x0000); + LCD_Write_COM_DATA(0x11, 0x0007); + LCD_Write_COM_DATA(0x12, 0x0000); + LCD_Write_COM_DATA(0x13, 0x0000); + delay(50); + LCD_Write_COM_DATA(0x10, 0x17B0); + LCD_Write_COM_DATA(0x11, 0x0007); + delay(10); + LCD_Write_COM_DATA(0x12, 0x013A); + delay(10); + LCD_Write_COM_DATA(0x13, 0x1A00); + LCD_Write_COM_DATA(0x29, 0x000c); + delay(10); + //-----Gamma control----------------------- + LCD_Write_COM_DATA(0x30, 0x0000); + LCD_Write_COM_DATA(0x31, 0x0505); + LCD_Write_COM_DATA(0x32, 0x0004); + LCD_Write_COM_DATA(0x35, 0x0006); + LCD_Write_COM_DATA(0x36, 0x0707); + LCD_Write_COM_DATA(0x37, 0x0105); + LCD_Write_COM_DATA(0x38, 0x0002); + LCD_Write_COM_DATA(0x39, 0x0707); + LCD_Write_COM_DATA(0x3C, 0x0704); + LCD_Write_COM_DATA(0x3D, 0x0807); + //-----Set RAM area----------------------- + LCD_Write_COM_DATA(0x50, 0x0000); + LCD_Write_COM_DATA(0x51, 0x00EF); + LCD_Write_COM_DATA(0x52, 0x0000); + LCD_Write_COM_DATA(0x53, 0x013F); + LCD_Write_COM_DATA(0x60, 0x2700); + LCD_Write_COM_DATA(0x61, 0x0001); + LCD_Write_COM_DATA(0x6A, 0x0000); + LCD_Write_COM_DATA(0x21, 0x0000); + LCD_Write_COM_DATA(0x20, 0x0000); + //-----Partial Display Control------------ + LCD_Write_COM_DATA(0x80, 0x0000); + LCD_Write_COM_DATA(0x81, 0x0000); + LCD_Write_COM_DATA(0x82, 0x0000); + LCD_Write_COM_DATA(0x83, 0x0000); + LCD_Write_COM_DATA(0x84, 0x0000); + LCD_Write_COM_DATA(0x85, 0x0000); + //-----Panel Control---------------------- + LCD_Write_COM_DATA(0x90, 0x0010); + LCD_Write_COM_DATA(0x92, 0x0000); + LCD_Write_COM_DATA(0x93, 0x0003); + LCD_Write_COM_DATA(0x95, 0x0110); + LCD_Write_COM_DATA(0x97, 0x0000); + LCD_Write_COM_DATA(0x98, 0x0000); + //-----Display on----------------------- + LCD_Write_COM_DATA(0x07, 0x0173); + delay(50); + break; diff --git a/libraries/UTFT/tft_drivers/ili9320/setxy.h b/libraries/UTFT/tft_drivers/ili9320/setxy.h new file mode 100644 index 0000000..d54564f --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9320/setxy.h @@ -0,0 +1,10 @@ +case ILI9320_8: +case ILI9320_16: + LCD_Write_COM_DATA(0x20,x1); + LCD_Write_COM_DATA(0x21,y1); + LCD_Write_COM_DATA(0x50,x1); + LCD_Write_COM_DATA(0x52,y1); + LCD_Write_COM_DATA(0x51,x2); + LCD_Write_COM_DATA(0x53,y2); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/ili9325c/initlcd.h b/libraries/UTFT/tft_drivers/ili9325c/initlcd.h new file mode 100644 index 0000000..23fba46 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9325c/initlcd.h @@ -0,0 +1,61 @@ +case ILI9325C: + LCD_Write_COM_DATA(0xE5, 0x78F0); // set SRAM internal timing + LCD_Write_COM_DATA(0x01, 0x0100); // set Driver Output Control + LCD_Write_COM_DATA(0x02, 0x0700); // set 1 line inversion + LCD_Write_COM_DATA(0x03, 0x1030); // set GRAM write direction and BGR=1. + LCD_Write_COM_DATA(0x04, 0x0000); // Resize register + LCD_Write_COM_DATA(0x08, 0x0207); // set the back porch and front porch + LCD_Write_COM_DATA(0x09, 0x0000); // set non-display area refresh cycle ISC[3:0] + LCD_Write_COM_DATA(0x0A, 0x0000); // FMARK function + LCD_Write_COM_DATA(0x0C, 0x0000); // RGB interface setting + LCD_Write_COM_DATA(0x0D, 0x0000); // Frame marker Position + LCD_Write_COM_DATA(0x0F, 0x0000); // RGB interface polarity + //*************Power On sequence ****************// + LCD_Write_COM_DATA(0x10, 0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB + LCD_Write_COM_DATA(0x11, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0] + LCD_Write_COM_DATA(0x12, 0x0000); // VREG1OUT voltage + LCD_Write_COM_DATA(0x13, 0x0000); // VDV[4:0] for VCOM amplitude + LCD_Write_COM_DATA(0x07, 0x0001); + delay(200); // Dis-charge capacitor power voltage + LCD_Write_COM_DATA(0x10, 0x1090); // SAP, BT[3:0], AP, DSTB, SLP, STB + LCD_Write_COM_DATA(0x11, 0x0227); // Set DC1[2:0], DC0[2:0], VC[2:0] + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x12, 0x001F); // 0012 + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x13, 0x1500); // VDV[4:0] for VCOM amplitude + LCD_Write_COM_DATA(0x29, 0x0027); // 04 VCM[5:0] for VCOMH + LCD_Write_COM_DATA(0x2B, 0x000D); // Set Frame Rate + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x20, 0x0000); // GRAM horizontal Address + LCD_Write_COM_DATA(0x21, 0x0000); // GRAM Vertical Address + // ----------- Adjust the Gamma Curve ----------// + LCD_Write_COM_DATA(0x30, 0x0000); + LCD_Write_COM_DATA(0x31, 0x0707); + LCD_Write_COM_DATA(0x32, 0x0307); + LCD_Write_COM_DATA(0x35, 0x0200); + LCD_Write_COM_DATA(0x36, 0x0008); + LCD_Write_COM_DATA(0x37, 0x0004); + LCD_Write_COM_DATA(0x38, 0x0000); + LCD_Write_COM_DATA(0x39, 0x0707); + LCD_Write_COM_DATA(0x3C, 0x0002); + LCD_Write_COM_DATA(0x3D, 0x1D04); + //------------------ Set GRAM area ---------------// + LCD_Write_COM_DATA(0x50, 0x0000); // Horizontal GRAM Start Address + LCD_Write_COM_DATA(0x51, 0x00EF); // Horizontal GRAM End Address + LCD_Write_COM_DATA(0x52, 0x0000); // Vertical GRAM Start Address + LCD_Write_COM_DATA(0x53, 0x013F); // Vertical GRAM Start Address + LCD_Write_COM_DATA(0x60, 0xA700); // Gate Scan Line + LCD_Write_COM_DATA(0x61, 0x0001); // NDL,VLE, REV + LCD_Write_COM_DATA(0x6A, 0x0000); // set scrolling line + //-------------- Partial Display Control ---------// + LCD_Write_COM_DATA(0x80, 0x0000); + LCD_Write_COM_DATA(0x81, 0x0000); + LCD_Write_COM_DATA(0x82, 0x0000); + LCD_Write_COM_DATA(0x83, 0x0000); + LCD_Write_COM_DATA(0x84, 0x0000); + LCD_Write_COM_DATA(0x85, 0x0000); + //-------------- Panel Control -------------------// + LCD_Write_COM_DATA(0x90, 0x0010); + LCD_Write_COM_DATA(0x92, 0x0600); + LCD_Write_COM_DATA(0x07, 0x0133); // 262K color and display ON + break; diff --git a/libraries/UTFT/tft_drivers/ili9325c/setxy.h b/libraries/UTFT/tft_drivers/ili9325c/setxy.h new file mode 100644 index 0000000..6e7428d --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9325c/setxy.h @@ -0,0 +1,9 @@ +case ILI9325C: + LCD_Write_COM_DATA(0x20,x1); + LCD_Write_COM_DATA(0x21,y1); + LCD_Write_COM_DATA(0x50,x1); + LCD_Write_COM_DATA(0x52,y1); + LCD_Write_COM_DATA(0x51,x2); + LCD_Write_COM_DATA(0x53,y2); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/ili9325d/alt/initlcd.h b/libraries/UTFT/tft_drivers/ili9325d/alt/initlcd.h new file mode 100644 index 0000000..fa52c8d --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9325d/alt/initlcd.h @@ -0,0 +1,61 @@ +case ILI9325D_16ALT: + LCD_Write_COM_DATA(0xE5, 0x78F0); // set SRAM internal timing + LCD_Write_COM_DATA(0x01, 0x0100); // set Driver Output Control + LCD_Write_COM_DATA(0x02, 0x0700); // set 1 line inversion + LCD_Write_COM_DATA(0x03, 0x1030); // set GRAM write direction and BGR=1. + LCD_Write_COM_DATA(0x04, 0x0000); // Resize register + LCD_Write_COM_DATA(0x08, 0x0207); // set the back porch and front porch + LCD_Write_COM_DATA(0x09, 0x0000); // set non-display area refresh cycle ISC[3:0] + LCD_Write_COM_DATA(0x0A, 0x0000); // FMARK function + LCD_Write_COM_DATA(0x0C, 0x0000); // RGB interface setting + LCD_Write_COM_DATA(0x0D, 0x0000); // Frame marker Position + LCD_Write_COM_DATA(0x0F, 0x0000); // RGB interface polarity + //*************Power On sequence ****************// + LCD_Write_COM_DATA(0x10, 0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB + LCD_Write_COM_DATA(0x11, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0] + LCD_Write_COM_DATA(0x12, 0x0000); // VREG1OUT voltage + LCD_Write_COM_DATA(0x13, 0x0000); // VDV[4:0] for VCOM amplitude + LCD_Write_COM_DATA(0x07, 0x0001); + delay(200); // Dis-charge capacitor power voltage + LCD_Write_COM_DATA(0x10, 0x1590); // SAP, BT[3:0], AP, DSTB, SLP, STB + LCD_Write_COM_DATA(0x11, 0x0227); // Set DC1[2:0], DC0[2:0], VC[2:0] + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x12, 0x009C); // 0012 + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x13, 0x1900); // VDV[4:0] for VCOM amplitude + LCD_Write_COM_DATA(0x29, 0x0023); // 04 VCM[5:0] for VCOMH + LCD_Write_COM_DATA(0x2B, 0x000E); // Set Frame Rate + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x20, 0x0000); // GRAM horizontal Address + LCD_Write_COM_DATA(0x21, 0x0000); // GRAM Vertical Address + // ----------- Adjust the Gamma Curve ----------// + LCD_Write_COM_DATA(0x30, 0x0000); + LCD_Write_COM_DATA(0x31, 0x0404); + LCD_Write_COM_DATA(0x32, 0x0003); + LCD_Write_COM_DATA(0x35, 0x0405); + LCD_Write_COM_DATA(0x36, 0x0808); + LCD_Write_COM_DATA(0x37, 0x0407); + LCD_Write_COM_DATA(0x38, 0x0303); + LCD_Write_COM_DATA(0x39, 0x0707); + LCD_Write_COM_DATA(0x3C, 0x0504); + LCD_Write_COM_DATA(0x3D, 0x0808); + //------------------ Set GRAM area ---------------// + LCD_Write_COM_DATA(0x50, 0x0000); // Horizontal GRAM Start Address + LCD_Write_COM_DATA(0x51, 0x00EF); // Horizontal GRAM End Address + LCD_Write_COM_DATA(0x52, 0x0000); // Vertical GRAM Start Address + LCD_Write_COM_DATA(0x53, 0x013F); // Vertical GRAM Start Address + LCD_Write_COM_DATA(0x60, 0xA700); // Gate Scan Line + LCD_Write_COM_DATA(0x61, 0x0001); // NDL,VLE, REV + LCD_Write_COM_DATA(0x6A, 0x0000); // set scrolling line + //-------------- Partial Display Control ---------// + LCD_Write_COM_DATA(0x80, 0x0000); + LCD_Write_COM_DATA(0x81, 0x0000); + LCD_Write_COM_DATA(0x82, 0x0000); + LCD_Write_COM_DATA(0x83, 0x0000); + LCD_Write_COM_DATA(0x84, 0x0000); + LCD_Write_COM_DATA(0x85, 0x0000); + //-------------- Panel Control -------------------// + LCD_Write_COM_DATA(0x90, 0x0010); + LCD_Write_COM_DATA(0x92, 0x0000); + LCD_Write_COM_DATA(0x07, 0x0133); // 262K color and display ON + break; diff --git a/libraries/UTFT/tft_drivers/ili9325d/alt/setxy.h b/libraries/UTFT/tft_drivers/ili9325d/alt/setxy.h new file mode 100644 index 0000000..95361e0 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9325d/alt/setxy.h @@ -0,0 +1,9 @@ +case ILI9325D_16ALT: + LCD_Write_COM_DATA(0x20,x1); + LCD_Write_COM_DATA(0x21,y1); + LCD_Write_COM_DATA(0x50,x1); + LCD_Write_COM_DATA(0x52,y1); + LCD_Write_COM_DATA(0x51,x2); + LCD_Write_COM_DATA(0x53,y2); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/ili9325d/default/initlcd.h b/libraries/UTFT/tft_drivers/ili9325d/default/initlcd.h new file mode 100644 index 0000000..6ecb6e2 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9325d/default/initlcd.h @@ -0,0 +1,62 @@ +case ILI9325D_8: +case ILI9325D_16: + LCD_Write_COM_DATA(0xE5, 0x78F0); // set SRAM internal timing + LCD_Write_COM_DATA(0x01, 0x0100); // set Driver Output Control + LCD_Write_COM_DATA(0x02, 0x0200); // set 1 line inversion + LCD_Write_COM_DATA(0x03, 0x1030); // set GRAM write direction and BGR=1. + LCD_Write_COM_DATA(0x04, 0x0000); // Resize register + LCD_Write_COM_DATA(0x08, 0x0207); // set the back porch and front porch + LCD_Write_COM_DATA(0x09, 0x0000); // set non-display area refresh cycle ISC[3:0] + LCD_Write_COM_DATA(0x0A, 0x0000); // FMARK function + LCD_Write_COM_DATA(0x0C, 0x0000); // RGB interface setting + LCD_Write_COM_DATA(0x0D, 0x0000); // Frame marker Position + LCD_Write_COM_DATA(0x0F, 0x0000); // RGB interface polarity + //*************Power On sequence ****************// + LCD_Write_COM_DATA(0x10, 0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB + LCD_Write_COM_DATA(0x11, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0] + LCD_Write_COM_DATA(0x12, 0x0000); // VREG1OUT voltage + LCD_Write_COM_DATA(0x13, 0x0000); // VDV[4:0] for VCOM amplitude + LCD_Write_COM_DATA(0x07, 0x0001); + delay(200); // Dis-charge capacitor power voltage + LCD_Write_COM_DATA(0x10, 0x1690); // SAP, BT[3:0], AP, DSTB, SLP, STB + LCD_Write_COM_DATA(0x11, 0x0227); // Set DC1[2:0], DC0[2:0], VC[2:0] + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x12, 0x000D); // 0012 + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x13, 0x1200); // VDV[4:0] for VCOM amplitude + LCD_Write_COM_DATA(0x29, 0x000A); // 04 VCM[5:0] for VCOMH + LCD_Write_COM_DATA(0x2B, 0x000D); // Set Frame Rate + delay(50); // Delay 50ms + LCD_Write_COM_DATA(0x20, 0x0000); // GRAM horizontal Address + LCD_Write_COM_DATA(0x21, 0x0000); // GRAM Vertical Address + // ----------- Adjust the Gamma Curve ----------// + LCD_Write_COM_DATA(0x30, 0x0000); + LCD_Write_COM_DATA(0x31, 0x0404); + LCD_Write_COM_DATA(0x32, 0x0003); + LCD_Write_COM_DATA(0x35, 0x0405); + LCD_Write_COM_DATA(0x36, 0x0808); + LCD_Write_COM_DATA(0x37, 0x0407); + LCD_Write_COM_DATA(0x38, 0x0303); + LCD_Write_COM_DATA(0x39, 0x0707); + LCD_Write_COM_DATA(0x3C, 0x0504); + LCD_Write_COM_DATA(0x3D, 0x0808); + //------------------ Set GRAM area ---------------// + LCD_Write_COM_DATA(0x50, 0x0000); // Horizontal GRAM Start Address + LCD_Write_COM_DATA(0x51, 0x00EF); // Horizontal GRAM End Address + LCD_Write_COM_DATA(0x52, 0x0000); // Vertical GRAM Start Address + LCD_Write_COM_DATA(0x53, 0x013F); // Vertical GRAM Start Address + LCD_Write_COM_DATA(0x60, 0xA700); // Gate Scan Line + LCD_Write_COM_DATA(0x61, 0x0001); // NDL,VLE, REV + LCD_Write_COM_DATA(0x6A, 0x0000); // set scrolling line + //-------------- Partial Display Control ---------// + LCD_Write_COM_DATA(0x80, 0x0000); + LCD_Write_COM_DATA(0x81, 0x0000); + LCD_Write_COM_DATA(0x82, 0x0000); + LCD_Write_COM_DATA(0x83, 0x0000); + LCD_Write_COM_DATA(0x84, 0x0000); + LCD_Write_COM_DATA(0x85, 0x0000); + //-------------- Panel Control -------------------// + LCD_Write_COM_DATA(0x90, 0x0010); + LCD_Write_COM_DATA(0x92, 0x0000); + LCD_Write_COM_DATA(0x07, 0x0133); // 262K color and display ON + break; diff --git a/libraries/UTFT/tft_drivers/ili9325d/default/setxy.h b/libraries/UTFT/tft_drivers/ili9325d/default/setxy.h new file mode 100644 index 0000000..f5fdd94 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9325d/default/setxy.h @@ -0,0 +1,10 @@ +case ILI9325D_8: +case ILI9325D_16: + LCD_Write_COM_DATA(0x20,x1); + LCD_Write_COM_DATA(0x21,y1); + LCD_Write_COM_DATA(0x50,x1); + LCD_Write_COM_DATA(0x52,y1); + LCD_Write_COM_DATA(0x51,x2); + LCD_Write_COM_DATA(0x53,y2); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/ili9327/initlcd.h b/libraries/UTFT/tft_drivers/ili9327/initlcd.h new file mode 100644 index 0000000..451806b --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9327/initlcd.h @@ -0,0 +1,63 @@ +case ILI9327: + LCD_Write_COM(0xE9); + LCD_Write_DATA(0x00,0x20); + LCD_Write_COM(0x11); //Exit Sleep + delay(100); + LCD_Write_COM(0xD1); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x71); + LCD_Write_DATA(0x00,0x19); + LCD_Write_COM(0xD0); + LCD_Write_DATA(0x00,0x07); + LCD_Write_DATA(0x00,0x01); + LCD_Write_DATA(0x00,0x08); + LCD_Write_COM(0x36); + LCD_Write_DATA(0x00,0x48); + LCD_Write_COM(0x3A); + LCD_Write_DATA(0x00,0x05); + LCD_Write_COM(0xC1); + LCD_Write_DATA(0x00,0x10); + LCD_Write_DATA(0x00,0x10); + LCD_Write_DATA(0x00,0x02); + LCD_Write_DATA(0x00,0x02); + LCD_Write_COM(0xC0); //Set Default Gamma + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x35); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x01); + LCD_Write_DATA(0x00,0x02); + LCD_Write_COM(0xC5); //Set frame rate + LCD_Write_DATA(0x00,0x04); + LCD_Write_COM(0xD2); //power setting + LCD_Write_DATA(0x00,0x01); + LCD_Write_DATA(0x00,0x44); + LCD_Write_COM(0xC8); //Set Gamma + LCD_Write_DATA(0x00,0x04); + LCD_Write_DATA(0x00,0x67); + LCD_Write_DATA(0x00,0x35); + LCD_Write_DATA(0x00,0x04); + LCD_Write_DATA(0x00,0x08); + LCD_Write_DATA(0x00,0x06); + LCD_Write_DATA(0x00,0x24); + LCD_Write_DATA(0x00,0x01); + LCD_Write_DATA(0x00,0x37); + LCD_Write_DATA(0x00,0x40); + LCD_Write_DATA(0x00,0x03); + LCD_Write_DATA(0x00,0x10); + LCD_Write_DATA(0x00,0x08); + LCD_Write_DATA(0x00,0x80); + LCD_Write_DATA(0x00,0x00); + LCD_Write_COM(0x2A); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0xeF); + LCD_Write_COM(0x2B); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x00); + LCD_Write_DATA(0x00,0x01); + LCD_Write_DATA(0x00,0x8F); + LCD_Write_COM(0x29); //display on + LCD_Write_COM(0x2C); //display on + break; diff --git a/libraries/UTFT/tft_drivers/ili9327/setxy.h b/libraries/UTFT/tft_drivers/ili9327/setxy.h new file mode 100644 index 0000000..6390c65 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9327/setxy.h @@ -0,0 +1,13 @@ +case ILI9327: + LCD_Write_COM(0x2a); + LCD_Write_DATA(0x00,x1>>8); + LCD_Write_DATA(0x00,x1); + LCD_Write_DATA(0x00,x2>>8); + LCD_Write_DATA(0x00,x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(0x00,y1>>8); + LCD_Write_DATA(0x00,y1); + LCD_Write_DATA(0x00,y2>>8); + LCD_Write_DATA(0x00,y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/ili9341/s4p/initlcd.h b/libraries/UTFT/tft_drivers/ili9341/s4p/initlcd.h new file mode 100644 index 0000000..0a5a082 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9341/s4p/initlcd.h @@ -0,0 +1,58 @@ +case ILI9341_S4P: + LCD_Write_COM(0x11);//sleep out + delay(20); + //LCD_Write_COM(0x01); //reset + //delay(15); + LCD_Write_COM(0x28); //display off + delay(5); + LCD_Write_COM(0xCF); //power control b + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x83); //83 81 AA + LCD_Write_DATA(0x30); + LCD_Write_COM(0xED); //power on seq control + LCD_Write_DATA(0x64); //64 67 + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x12); + LCD_Write_DATA(0x81); + LCD_Write_COM(0xE8); //timing control a + LCD_Write_DATA(0x85); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x79); //79 78 + LCD_Write_COM(0xCB); //power control a + LCD_Write_DATA(0x39); + LCD_Write_DATA(0X2C); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x34); + LCD_Write_DATA(0x02); + LCD_Write_COM(0xF7); //pump ratio control + LCD_Write_DATA(0x20); + LCD_Write_COM(0xEA); //timing control b + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_COM(0xC0); //power control 2 + LCD_Write_DATA(0x26); //26 25 + LCD_Write_COM(0xC1); //power control 2 + LCD_Write_DATA(0x11); + LCD_Write_COM(0xC5); //vcom control 1 + LCD_Write_DATA(0x35); + LCD_Write_DATA(0x3E); + LCD_Write_COM(0xC7); //vcom control 2 + LCD_Write_DATA(0xBE); //BE 94 + LCD_Write_COM(0xB1); //frame control + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x1B); //1B 70 + LCD_Write_COM(0xB6); //display control + LCD_Write_DATA(0x0A); + LCD_Write_DATA(0x82); + LCD_Write_DATA(0x27); + LCD_Write_DATA(0x00); + LCD_Write_COM(0xB7); //emtry mode + LCD_Write_DATA(0x07); + LCD_Write_COM(0x3A); //pixel format + LCD_Write_DATA(0x55); //16bit + LCD_Write_COM(0x36); //mem access + LCD_Write_DATA((1<<3)|(1<<6)); + //LCD_Write_DATA((1<<3)|(1<<7)); //rotate 180 + LCD_Write_COM(0x29); //display on + delay(5); + break; diff --git a/libraries/UTFT/tft_drivers/ili9341/s4p/setxy.h b/libraries/UTFT/tft_drivers/ili9341/s4p/setxy.h new file mode 100644 index 0000000..08ac212 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9341/s4p/setxy.h @@ -0,0 +1,13 @@ +case ILI9341_S4P: + LCD_Write_COM(0x2A); //column + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2B); //page + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2C); //write + break; diff --git a/libraries/UTFT/tft_drivers/ili9341/s5p/initlcd.h b/libraries/UTFT/tft_drivers/ili9341/s5p/initlcd.h new file mode 100644 index 0000000..7afa6f6 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9341/s5p/initlcd.h @@ -0,0 +1,105 @@ +case ILI9341_S5P: + LCD_Write_COM(0xCB); + LCD_Write_DATA(0x39); + LCD_Write_DATA(0x2C); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x34); + LCD_Write_DATA(0x02); + + LCD_Write_COM(0xCF); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0XC1); + LCD_Write_DATA(0X30); + + LCD_Write_COM(0xE8); + LCD_Write_DATA(0x85); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x78); + + LCD_Write_COM(0xEA); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xED); + LCD_Write_DATA(0x64); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0X12); + LCD_Write_DATA(0X81); + + LCD_Write_COM(0xF7); + LCD_Write_DATA(0x20); + + LCD_Write_COM(0xC0); //Power control + LCD_Write_DATA(0x23); //VRH[5:0] + + LCD_Write_COM(0xC1); //Power control + LCD_Write_DATA(0x10); //SAP[2:0];BT[3:0] + + LCD_Write_COM(0xC5); //VCM control + LCD_Write_DATA(0x3e); //Contrast + LCD_Write_DATA(0x28); + + LCD_Write_COM(0xC7); //VCM control2 + LCD_Write_DATA(0x86); //-- + + LCD_Write_COM(0x36); // Memory Access Control + LCD_Write_DATA(0x48); + + LCD_Write_COM(0x3A); + LCD_Write_DATA(0x55); + + LCD_Write_COM(0xB1); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x18); + + LCD_Write_COM(0xB6); // Display Function Control + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x82); + LCD_Write_DATA(0x27); +/* + LCD_Write_COM(0xF2); // 3Gamma Function Disable + LCD_Write_DATA(0x00); + + LCD_Write_COM(0x26); //Gamma curve selected + LCD_Write_DATA(0x01); + + LCD_Write_COM(0xE0); //Set Gamma + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x31); + LCD_Write_DATA(0x2B); + LCD_Write_DATA(0x0C); + LCD_Write_DATA(0x0E); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x4E); + LCD_Write_DATA(0xF1); + LCD_Write_DATA(0x37); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x0E); + LCD_Write_DATA(0x09); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0XE1); //Set Gamma + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x0E); + LCD_Write_DATA(0x14); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x11); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x31); + LCD_Write_DATA(0xC1); + LCD_Write_DATA(0x48); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x0C); + LCD_Write_DATA(0x31); + LCD_Write_DATA(0x36); + LCD_Write_DATA(0x0F); +*/ + LCD_Write_COM(0x11); //Exit Sleep + delay(120); + + LCD_Write_COM(0x29); //Display on + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/ili9341/s5p/setxy.h b/libraries/UTFT/tft_drivers/ili9341/s5p/setxy.h new file mode 100644 index 0000000..965f21d --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9341/s5p/setxy.h @@ -0,0 +1,13 @@ +case ILI9341_S5P: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/ili9481/initlcd.h b/libraries/UTFT/tft_drivers/ili9481/initlcd.h new file mode 100644 index 0000000..74260ed --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9481/initlcd.h @@ -0,0 +1,62 @@ +case ILI9481: + LCD_Write_COM(0x11); + delay(20); + LCD_Write_COM(0xD0); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x42); + LCD_Write_DATA(0x18); + + LCD_Write_COM(0xD1); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x10); + + LCD_Write_COM(0xD2); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x02); + + LCD_Write_COM(0xC0); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x3B); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x11); + + LCD_Write_COM(0xC5); + LCD_Write_DATA(0x03); + + LCD_Write_COM(0xC8); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x32); + LCD_Write_DATA(0x36); + LCD_Write_DATA(0x45); + LCD_Write_DATA(0x06); + LCD_Write_DATA(0x16); + LCD_Write_DATA(0x37); + LCD_Write_DATA(0x75); + LCD_Write_DATA(0x77); + LCD_Write_DATA(0x54); + LCD_Write_DATA(0x0C); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0x36); + LCD_Write_DATA(0x0A); + + + LCD_Write_COM(0x3A); + LCD_Write_DATA(0x55); + + LCD_Write_COM(0x2A); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x3F); + + LCD_Write_COM(0x2B); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0xE0); + delay(120); + LCD_Write_COM(0x29); + break; diff --git a/libraries/UTFT/tft_drivers/ili9481/setxy.h b/libraries/UTFT/tft_drivers/ili9481/setxy.h new file mode 100644 index 0000000..e3e7ce2 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9481/setxy.h @@ -0,0 +1,13 @@ +case ILI9481: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/ili9486/initlcd.h b/libraries/UTFT/tft_drivers/ili9486/initlcd.h new file mode 100644 index 0000000..b67b0ed --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9486/initlcd.h @@ -0,0 +1,105 @@ +case ILI9486: + LCD_Write_COM(0x11); // Sleep OUT + delay(50); + + LCD_Write_COM(0xF2); // ????? + LCD_Write_DATA(0x1C); + LCD_Write_DATA(0xA3); + LCD_Write_DATA(0x32); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0xb2); + LCD_Write_DATA(0x12); + LCD_Write_DATA(0xFF); + LCD_Write_DATA(0x12); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xF1); // ????? + LCD_Write_DATA(0x36); + LCD_Write_DATA(0xA4); + + LCD_Write_COM(0xF8); // ????? + LCD_Write_DATA(0x21); + LCD_Write_DATA(0x04); + + LCD_Write_COM(0xF9); // ????? + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x08); + + LCD_Write_COM(0xC0); // Power Control 1 + LCD_Write_DATA(0x0d); + LCD_Write_DATA(0x0d); + + LCD_Write_COM(0xC1); // Power Control 2 + LCD_Write_DATA(0x43); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xC2); // Power Control 3 + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xC5); // VCOM Control + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x48); + + LCD_Write_COM(0xB6); // Display Function Control + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x22); // 0x42 = Rotate display 180 deg. + LCD_Write_DATA(0x3B); + + LCD_Write_COM(0xE0); // PGAMCTRL (Positive Gamma Control) + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x24); + LCD_Write_DATA(0x1c); + LCD_Write_DATA(0x0a); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x43); + LCD_Write_DATA(0x88); + LCD_Write_DATA(0x32); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x06); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xE1); // NGAMCTRL (Negative Gamma Control) + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x38); + LCD_Write_DATA(0x30); + LCD_Write_DATA(0x09); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x4e); + LCD_Write_DATA(0x77); + LCD_Write_DATA(0x3c); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x23); + LCD_Write_DATA(0x1b); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0x20); // Display Inversion OFF + LCD_Write_DATA(0x00);//C8 + + LCD_Write_COM(0x36); // Memory Access Control + LCD_Write_DATA(0x0A); + + LCD_Write_COM(0x3A); // Interface Pixel Format + LCD_Write_DATA(0x55); + + LCD_Write_COM(0x2A); // Column Addess Set + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0xDF); + + LCD_Write_COM(0x002B); // Page Address Set + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x3f); + delay(50); + LCD_Write_COM(0x0029); // Display ON + LCD_Write_COM(0x002C); // Memory Write + break; diff --git a/libraries/UTFT/tft_drivers/ili9486/setxy.h b/libraries/UTFT/tft_drivers/ili9486/setxy.h new file mode 100644 index 0000000..df5beb3 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ili9486/setxy.h @@ -0,0 +1,13 @@ +case ILI9486: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/pcf8833/initlcd.h b/libraries/UTFT/tft_drivers/pcf8833/initlcd.h new file mode 100644 index 0000000..685f855 --- /dev/null +++ b/libraries/UTFT/tft_drivers/pcf8833/initlcd.h @@ -0,0 +1,30 @@ +case PCF8833: + LCD_Write_COM(0x01); + LCD_Write_COM(0x25); + LCD_Write_DATA(0x40); + LCD_Write_COM(0x11); + delay(10); + LCD_Write_COM(0x20); + LCD_Write_COM(0x38); + LCD_Write_COM(0x29); + LCD_Write_COM(0x13); + LCD_Write_COM(0x36); + LCD_Write_DATA(0x60); + LCD_Write_COM(0x3A); + LCD_Write_DATA(0x05); + LCD_Write_COM(0x2A); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x7F); + LCD_Write_COM(0xB4); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x0b); + LCD_Write_DATA(0x0e); + LCD_Write_COM(0xBA); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x0D); + LCD_Write_COM(0x2B); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x7F); + LCD_Write_COM(0x2C); + break; diff --git a/libraries/UTFT/tft_drivers/pcf8833/setxy.h b/libraries/UTFT/tft_drivers/pcf8833/setxy.h new file mode 100644 index 0000000..34dd38c --- /dev/null +++ b/libraries/UTFT/tft_drivers/pcf8833/setxy.h @@ -0,0 +1,9 @@ +case PCF8833: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/r61581/initlcd.h b/libraries/UTFT/tft_drivers/r61581/initlcd.h new file mode 100644 index 0000000..6208485 --- /dev/null +++ b/libraries/UTFT/tft_drivers/r61581/initlcd.h @@ -0,0 +1,110 @@ +case R61581: + LCD_Write_COM(0xB0); + LCD_Write_DATA(0x1E); + + LCD_Write_COM(0xB0); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xB3); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x10); + + LCD_Write_COM(0xB4); + LCD_Write_DATA(0x00);//0X10 + +// LCD_Write_COM(0xB9); //PWM Settings for Brightness Control +// LCD_Write_DATA(0x01);// Disabled by default. +// LCD_Write_DATA(0xFF); //0xFF = Max brightness +// LCD_Write_DATA(0xFF); +// LCD_Write_DATA(0x18); + + LCD_Write_COM(0xC0); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x3B);// + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x00);//NW + LCD_Write_DATA(0x43); + + LCD_Write_COM(0xC1); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x15);//CLOCK + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x08); + + LCD_Write_COM(0xC4); + LCD_Write_DATA(0x15); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x01); + + LCD_Write_COM(0xC6); + LCD_Write_DATA(0x02); + + LCD_Write_COM(0xC8); + LCD_Write_DATA(0x0c); + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x0A);//0X12 + LCD_Write_DATA(0x6B);//0x7D + LCD_Write_DATA(0x04); + LCD_Write_DATA(0x06);//0x08 + LCD_Write_DATA(0x15);//0x0A + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x60);//0x23 + + LCD_Write_COM(0x36); + LCD_Write_DATA(0x0A); + + LCD_Write_COM(0x0C); + LCD_Write_DATA(0x55); + + LCD_Write_COM(0x3A); + LCD_Write_DATA(0x55); + + LCD_Write_COM(0x38); + + LCD_Write_COM(0xD0); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x07);//VCI1 + LCD_Write_DATA(0x14);//VRH 0x1D + LCD_Write_DATA(0xA2);//BT 0x06 + + LCD_Write_COM(0xD1); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x5A);//VCM 0x5A + LCD_Write_DATA(0x10);//VDV + + LCD_Write_COM(0xD2); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x04);//0x24 + LCD_Write_DATA(0x04); + + LCD_Write_COM(0x11); + delay(150); + + LCD_Write_COM(0x2A); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0xDF);//320 + + LCD_Write_COM(0x2B); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x3F);//480 + + + delay(100); + + LCD_Write_COM(0x29); + delay(30); + + LCD_Write_COM(0x2C); + delay(30); + break; diff --git a/libraries/UTFT/tft_drivers/r61581/setxy.h b/libraries/UTFT/tft_drivers/r61581/setxy.h new file mode 100644 index 0000000..29f356b --- /dev/null +++ b/libraries/UTFT/tft_drivers/r61581/setxy.h @@ -0,0 +1,13 @@ +case R61581: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/s1d19122/initlcd.h b/libraries/UTFT/tft_drivers/s1d19122/initlcd.h new file mode 100644 index 0000000..33f2c65 --- /dev/null +++ b/libraries/UTFT/tft_drivers/s1d19122/initlcd.h @@ -0,0 +1,183 @@ +case S1D19122: + //************* Start Initial Sequence **********// + + int i,R,G,B; + LCD_Write_COM(0x11); + LCD_Write_COM(0x13); + LCD_Write_COM(0x29); + + //-------------- Display Control ---------// + LCD_Write_COM(0xB0); + + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0xF0); + LCD_Write_DATA(0x0A); + LCD_Write_DATA(0x41); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x0A); + LCD_Write_DATA(0x30); + LCD_Write_DATA(0x31); + LCD_Write_DATA(0x36); + LCD_Write_DATA(0x37); + LCD_Write_DATA(0x40); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x3F); + LCD_Write_DATA(0x40); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x81); + LCD_Write_DATA(0x04); + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x64); + + // ----------- Gamma Curve Set3 Postive----------// + LCD_Write_COM(0xFC); + + LCD_Write_DATA(0x88); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x42); + LCD_Write_DATA(0x42); + LCD_Write_DATA(0x22); + LCD_Write_DATA(0x11); + LCD_Write_DATA(0x11); + LCD_Write_DATA(0x22); + LCD_Write_DATA(0x99); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0xBB); + LCD_Write_DATA(0xBB); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0x33); + LCD_Write_DATA(0x33); + LCD_Write_DATA(0x11); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0xC0); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + + // ----------- Gamma Curve Set3 Negative----------// + LCD_Write_COM(0xFD); + + LCD_Write_DATA(0x88); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x42); + LCD_Write_DATA(0x42); + LCD_Write_DATA(0x22); + LCD_Write_DATA(0x11); + LCD_Write_DATA(0x11); + LCD_Write_DATA(0x22); + LCD_Write_DATA(0x99); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0xBB); + LCD_Write_DATA(0xBB); + LCD_Write_DATA(0xAA); + LCD_Write_DATA(0x33); + LCD_Write_DATA(0x33); + LCD_Write_DATA(0x11); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x03); + + // ----------- EVRSER Regulator Voltage Setting---------// + LCD_Write_COM(0xBE); + + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x15); + LCD_Write_DATA(0x16); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x09); + LCD_Write_DATA(0x15); + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + + // -----------Module Definiton Setting---------// + LCD_Write_COM(0xC0); + + LCD_Write_DATA(0x0E); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + + // -----------PWRDEF Power Ability Ddfinition----------// + LCD_Write_COM(0xC1); + + LCD_Write_DATA(0x2F); + LCD_Write_DATA(0x23); + LCD_Write_DATA(0xB4); + LCD_Write_DATA(0xFF); + LCD_Write_DATA(0x24); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x20); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x20); + LCD_Write_DATA(0x20); + LCD_Write_DATA(0x00); + + // -----------Other Setting----------// + LCD_Write_COM(0xC2); + LCD_Write_DATA(0x03); + LCD_Write_COM(0x26); + LCD_Write_DATA(0x08); + LCD_Write_COM(0x35); + + LCD_Write_COM(0x36); + LCD_Write_DATA(0x64); + LCD_Write_COM(0x3A); + LCD_Write_DATA(0x05); + LCD_Write_COM(0x2A); + LCD_Write_DATA(0x01,0x3f); + LCD_Write_COM(0x2B); + LCD_Write_DATA(0xEF); + LCD_Write_COM(0x2c); + + // -----------RGB Setting----------// + LCD_Write_COM(0x2D); + R=0; + G=0; + B=0; + + for(i=0;i<32;i++) + { + LCD_Write_DATA(R); + R=R+2; + } + for(i=0;i<64;i++) + { + LCD_Write_DATA(G); + G=G+1; + } + for(i=0;i<32;i++) + { + LCD_Write_DATA(B); + B=B+2; + } + break; diff --git a/libraries/UTFT/tft_drivers/s1d19122/setxy.h b/libraries/UTFT/tft_drivers/s1d19122/setxy.h new file mode 100644 index 0000000..d88c733 --- /dev/null +++ b/libraries/UTFT/tft_drivers/s1d19122/setxy.h @@ -0,0 +1,13 @@ +case S1D19122: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/s6d0164/initlcd.h b/libraries/UTFT/tft_drivers/s6d0164/initlcd.h new file mode 100644 index 0000000..7b2716b --- /dev/null +++ b/libraries/UTFT/tft_drivers/s6d0164/initlcd.h @@ -0,0 +1,44 @@ +case S6D0164: + LCD_Write_COM_DATA(0x11,0x001A); + LCD_Write_COM_DATA(0x12,0x3121); + LCD_Write_COM_DATA(0x13,0x006C); + LCD_Write_COM_DATA(0x14,0x4249); + + LCD_Write_COM_DATA(0x10,0x0800); + delay(10); + LCD_Write_COM_DATA(0x11,0x011A); + delay(10); + LCD_Write_COM_DATA(0x11,0x031A); + delay(10); + LCD_Write_COM_DATA(0x11,0x071A); + delay(10); + LCD_Write_COM_DATA(0x11,0x0F1A); + delay(10); + LCD_Write_COM_DATA(0x11,0x0F3A); + delay(30); + + LCD_Write_COM_DATA(0x01,0x011C); + LCD_Write_COM_DATA(0x02,0x0100); + LCD_Write_COM_DATA(0x03,0x1030); + LCD_Write_COM_DATA(0x07,0x0000); + LCD_Write_COM_DATA(0x08,0x0808); + LCD_Write_COM_DATA(0x0B,0x1100); + LCD_Write_COM_DATA(0x0C,0x0000); + + LCD_Write_COM_DATA(0x0F,0x1401); + LCD_Write_COM_DATA(0x15,0x0000); + LCD_Write_COM_DATA(0x20,0x0000); + LCD_Write_COM_DATA(0x21,0x0000); + + + LCD_Write_COM_DATA(0x36,0x00AF); + LCD_Write_COM_DATA(0x37,0x0000); + LCD_Write_COM_DATA(0x38,0x00DB); + LCD_Write_COM_DATA(0x39,0x0000); + + LCD_Write_COM_DATA(0x0F,0x0B01); + LCD_Write_COM_DATA(0x07,0x0016); + LCD_Write_COM_DATA(0x07,0x0017); + + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/s6d0164/setxy.h b/libraries/UTFT/tft_drivers/s6d0164/setxy.h new file mode 100644 index 0000000..6e5d5e9 --- /dev/null +++ b/libraries/UTFT/tft_drivers/s6d0164/setxy.h @@ -0,0 +1,9 @@ +case S6D0164: + LCD_Write_COM_DATA(0x36,x2); + LCD_Write_COM_DATA(0x37,x1); + LCD_Write_COM_DATA(0x38,y2); + LCD_Write_COM_DATA(0x39,y1); + LCD_Write_COM_DATA(0x20,x1); + LCD_Write_COM_DATA(0x21,y1); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/s6d1121/initlcd.h b/libraries/UTFT/tft_drivers/s6d1121/initlcd.h new file mode 100644 index 0000000..c8d80e6 --- /dev/null +++ b/libraries/UTFT/tft_drivers/s6d1121/initlcd.h @@ -0,0 +1,47 @@ +case S6D1121_8: +case S6D1121_16: + LCD_Write_COM_DATA(0x11,0x2004); + LCD_Write_COM_DATA(0x13,0xCC00); + LCD_Write_COM_DATA(0x15,0x2600); + LCD_Write_COM_DATA(0x14,0x252A); + LCD_Write_COM_DATA(0x12,0x0033); + LCD_Write_COM_DATA(0x13,0xCC04); + LCD_Write_COM_DATA(0x13,0xCC06); + LCD_Write_COM_DATA(0x13,0xCC4F); + LCD_Write_COM_DATA(0x13,0x674F); + LCD_Write_COM_DATA(0x11,0x2003); + LCD_Write_COM_DATA(0x30,0x2609); + LCD_Write_COM_DATA(0x31,0x242C); + LCD_Write_COM_DATA(0x32,0x1F23); + LCD_Write_COM_DATA(0x33,0x2425); + LCD_Write_COM_DATA(0x34,0x2226); + LCD_Write_COM_DATA(0x35,0x2523); + LCD_Write_COM_DATA(0x36,0x1C1A); + LCD_Write_COM_DATA(0x37,0x131D); + LCD_Write_COM_DATA(0x38,0x0B11); + LCD_Write_COM_DATA(0x39,0x1210); + LCD_Write_COM_DATA(0x3A,0x1315); + LCD_Write_COM_DATA(0x3B,0x3619); + LCD_Write_COM_DATA(0x3C,0x0D00); + LCD_Write_COM_DATA(0x3D,0x000D); + LCD_Write_COM_DATA(0x16,0x0007); + LCD_Write_COM_DATA(0x02,0x0013); + LCD_Write_COM_DATA(0x03,0x0003); + LCD_Write_COM_DATA(0x01,0x0127); + LCD_Write_COM_DATA(0x08,0x0303); + LCD_Write_COM_DATA(0x0A,0x000B); + LCD_Write_COM_DATA(0x0B,0x0003); + LCD_Write_COM_DATA(0x0C,0x0000); + LCD_Write_COM_DATA(0x41,0x0000); + LCD_Write_COM_DATA(0x50,0x0000); + LCD_Write_COM_DATA(0x60,0x0005); + LCD_Write_COM_DATA(0x70,0x000B); + LCD_Write_COM_DATA(0x71,0x0000); + LCD_Write_COM_DATA(0x78,0x0000); + LCD_Write_COM_DATA(0x7A,0x0000); + LCD_Write_COM_DATA(0x79,0x0007); + LCD_Write_COM_DATA(0x07,0x0051); + LCD_Write_COM_DATA(0x07,0x0053); + LCD_Write_COM_DATA(0x79,0x0000); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/s6d1121/setxy.h b/libraries/UTFT/tft_drivers/s6d1121/setxy.h new file mode 100644 index 0000000..c2f5a1f --- /dev/null +++ b/libraries/UTFT/tft_drivers/s6d1121/setxy.h @@ -0,0 +1,9 @@ +case S6D1121_8: +case S6D1121_16: + LCD_Write_COM_DATA(0x46,(x2 << 8) | x1); + LCD_Write_COM_DATA(0x47,y2); + LCD_Write_COM_DATA(0x48,y1); + LCD_Write_COM_DATA(0x20,x1); + LCD_Write_COM_DATA(0x21,y1); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1289/initlcd.h b/libraries/UTFT/tft_drivers/ssd1289/initlcd.h new file mode 100644 index 0000000..0d63d92 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1289/initlcd.h @@ -0,0 +1,46 @@ +case SSD1289: +case SSD1289_8: +case SSD1289LATCHED: + LCD_Write_COM_DATA(0x00,0x0001); + LCD_Write_COM_DATA(0x03,0xA8A4); + LCD_Write_COM_DATA(0x0C,0x0000); + LCD_Write_COM_DATA(0x0D,0x080C); + LCD_Write_COM_DATA(0x0E,0x2B00); + LCD_Write_COM_DATA(0x1E,0x00B7); + LCD_Write_COM_DATA(0x01,0x2B3F); + LCD_Write_COM_DATA(0x02,0x0600); + LCD_Write_COM_DATA(0x10,0x0000); + LCD_Write_COM_DATA(0x11,0x6070); + LCD_Write_COM_DATA(0x05,0x0000); + LCD_Write_COM_DATA(0x06,0x0000); + LCD_Write_COM_DATA(0x16,0xEF1C); + LCD_Write_COM_DATA(0x17,0x0003); + LCD_Write_COM_DATA(0x07,0x0233); + LCD_Write_COM_DATA(0x0B,0x0000); + LCD_Write_COM_DATA(0x0F,0x0000); + LCD_Write_COM_DATA(0x41,0x0000); + LCD_Write_COM_DATA(0x42,0x0000); + LCD_Write_COM_DATA(0x48,0x0000); + LCD_Write_COM_DATA(0x49,0x013F); + LCD_Write_COM_DATA(0x4A,0x0000); + LCD_Write_COM_DATA(0x4B,0x0000); + LCD_Write_COM_DATA(0x44,0xEF00); + LCD_Write_COM_DATA(0x45,0x0000); + LCD_Write_COM_DATA(0x46,0x013F); + LCD_Write_COM_DATA(0x30,0x0707); + LCD_Write_COM_DATA(0x31,0x0204); + LCD_Write_COM_DATA(0x32,0x0204); + LCD_Write_COM_DATA(0x33,0x0502); + LCD_Write_COM_DATA(0x34,0x0507); + LCD_Write_COM_DATA(0x35,0x0204); + LCD_Write_COM_DATA(0x36,0x0204); + LCD_Write_COM_DATA(0x37,0x0502); + LCD_Write_COM_DATA(0x3A,0x0302); + LCD_Write_COM_DATA(0x3B,0x0302); + LCD_Write_COM_DATA(0x23,0x0000); + LCD_Write_COM_DATA(0x24,0x0000); + LCD_Write_COM_DATA(0x25,0x8000); + LCD_Write_COM_DATA(0x4f,0x0000); + LCD_Write_COM_DATA(0x4e,0x0000); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1289/setxy.h b/libraries/UTFT/tft_drivers/ssd1289/setxy.h new file mode 100644 index 0000000..28b0efd --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1289/setxy.h @@ -0,0 +1,10 @@ +case SSD1289: +case SSD1289_8: +case SSD1289LATCHED: + LCD_Write_COM_DATA(0x44,(x2<<8)+x1); + LCD_Write_COM_DATA(0x45,y1); + LCD_Write_COM_DATA(0x46,y2); + LCD_Write_COM_DATA(0x4e,x1); + LCD_Write_COM_DATA(0x4f,y1); + LCD_Write_COM(0x22); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1963/480/initlcd.h b/libraries/UTFT/tft_drivers/ssd1963/480/initlcd.h new file mode 100644 index 0000000..a051795 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1963/480/initlcd.h @@ -0,0 +1,78 @@ +case SSD1963_480: + LCD_Write_COM(0xE2); //PLL multiplier, set PLL clock to 120M + LCD_Write_DATA(0x23); //N=0x36 for 6.5M, 0x23 for 10M crystal + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x54); + LCD_Write_COM(0xE0); // PLL enable + LCD_Write_DATA(0x01); + delay(10); + LCD_Write_COM(0xE0); + LCD_Write_DATA(0x03); + delay(10); + LCD_Write_COM(0x01); // software reset + delay(100); + LCD_Write_COM(0xE6); //PLL setting for PCLK, depends on resolution + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x1F); + LCD_Write_DATA(0xFF); + + LCD_Write_COM(0xB0); //LCD SPECIFICATION + LCD_Write_DATA(0x20); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); //Set HDP 479 + LCD_Write_DATA(0xDF); + LCD_Write_DATA(0x01); //Set VDP 271 + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xB4); //HSYNC + LCD_Write_DATA(0x02); //Set HT 531 + LCD_Write_DATA(0x13); + LCD_Write_DATA(0x00); //Set HPS 8 + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x2B); //Set HPW 43 + LCD_Write_DATA(0x00); //Set LPS 2 + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xB6); //VSYNC + LCD_Write_DATA(0x01); //Set VT 288 + LCD_Write_DATA(0x20); + LCD_Write_DATA(0x00); //Set VPS 4 + LCD_Write_DATA(0x04); + LCD_Write_DATA(0x0c); //Set VPW 12 + LCD_Write_DATA(0x00); //Set FPS 2 + LCD_Write_DATA(0x02); + + LCD_Write_COM(0xBA); + LCD_Write_DATA(0x0F); //GPIO[3:0] out 1 + + LCD_Write_COM(0xB8); + LCD_Write_DATA(0x07); //GPIO3=input, GPIO[2:0]=output + LCD_Write_DATA(0x01); //GPIO0 normal + + LCD_Write_COM(0x36); //rotation + LCD_Write_DATA(0x22); + + LCD_Write_COM(0xF0); //pixel data interface + LCD_Write_DATA(0x03); + + + delay(1); + + setXY(0, 0, 479, 271); + LCD_Write_COM(0x29); //display on + + LCD_Write_COM(0xBE); //set PWM for B/L + LCD_Write_DATA(0x06); + LCD_Write_DATA(0xf0); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0xf0); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xd0); + LCD_Write_DATA(0x0d); + + LCD_Write_COM(0x2C); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1963/480/setxy.h b/libraries/UTFT/tft_drivers/ssd1963/480/setxy.h new file mode 100644 index 0000000..e2b9297 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1963/480/setxy.h @@ -0,0 +1,15 @@ +case SSD1963_480: + swap(word, x1, y1); + swap(word, x2, y2); + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1963/800/initlcd.h b/libraries/UTFT/tft_drivers/ssd1963/800/initlcd.h new file mode 100644 index 0000000..722286d --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1963/800/initlcd.h @@ -0,0 +1,78 @@ +case SSD1963_800: + LCD_Write_COM(0xE2); //PLL multiplier, set PLL clock to 120M + LCD_Write_DATA(0x1E); //N=0x36 for 6.5M, 0x23 for 10M crystal + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x54); + LCD_Write_COM(0xE0); // PLL enable + LCD_Write_DATA(0x01); + delay(10); + LCD_Write_COM(0xE0); + LCD_Write_DATA(0x03); + delay(10); + LCD_Write_COM(0x01); // software reset + delay(100); + LCD_Write_COM(0xE6); //PLL setting for PCLK, depends on resolution + LCD_Write_DATA(0x03); + LCD_Write_DATA(0xFF); + LCD_Write_DATA(0xFF); + + LCD_Write_COM(0xB0); //LCD SPECIFICATION + LCD_Write_DATA(0x24); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x03); //Set HDP 799 + LCD_Write_DATA(0x1F); + LCD_Write_DATA(0x01); //Set VDP 479 + LCD_Write_DATA(0xDF); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xB4); //HSYNC + LCD_Write_DATA(0x03); //Set HT 928 + LCD_Write_DATA(0xA0); + LCD_Write_DATA(0x00); //Set HPS 46 + LCD_Write_DATA(0x2E); + LCD_Write_DATA(0x30); //Set HPW 48 + LCD_Write_DATA(0x00); //Set LPS 15 + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xB6); //VSYNC + LCD_Write_DATA(0x02); //Set VT 525 + LCD_Write_DATA(0x0D); + LCD_Write_DATA(0x00); //Set VPS 16 + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x10); //Set VPW 16 + LCD_Write_DATA(0x00); //Set FPS 8 + LCD_Write_DATA(0x08); + + LCD_Write_COM(0xBA); + LCD_Write_DATA(0x0F); //GPIO[3:0] out 1 + + LCD_Write_COM(0xB8); + LCD_Write_DATA(0x07); //GPIO3=input, GPIO[2:0]=output + LCD_Write_DATA(0x01); //GPIO0 normal + + LCD_Write_COM(0x36); //rotation + LCD_Write_DATA(0x22); + + LCD_Write_COM(0xF0); //pixel data interface + LCD_Write_DATA(0x03); + + + delay(1); + + setXY(0, 0, 799, 479); + LCD_Write_COM(0x29); //display on + + LCD_Write_COM(0xBE); //set PWM for B/L + LCD_Write_DATA(0x06); + LCD_Write_DATA(0xf0); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0xf0); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xd0); + LCD_Write_DATA(0x0d); + + LCD_Write_COM(0x2C); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1963/800/setxy.h b/libraries/UTFT/tft_drivers/ssd1963/800/setxy.h new file mode 100644 index 0000000..1b2fed7 --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1963/800/setxy.h @@ -0,0 +1,15 @@ +case SSD1963_800: + swap(word, x1, y1); + swap(word, x2, y2); + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1963/800alt/initlcd.h b/libraries/UTFT/tft_drivers/ssd1963/800alt/initlcd.h new file mode 100644 index 0000000..a0cbecc --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1963/800alt/initlcd.h @@ -0,0 +1,78 @@ +case SSD1963_800ALT: + LCD_Write_COM(0xE2); //PLL multiplier, set PLL clock to 120M + LCD_Write_DATA(0x23); //N=0x36 for 6.5M, 0x23 for 10M crystal + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x04); + LCD_Write_COM(0xE0); // PLL enable + LCD_Write_DATA(0x01); + delay(10); + LCD_Write_COM(0xE0); + LCD_Write_DATA(0x03); + delay(10); + LCD_Write_COM(0x01); // software reset + delay(100); + LCD_Write_COM(0xE6); //PLL setting for PCLK, depends on resolution + LCD_Write_DATA(0x04); + LCD_Write_DATA(0x93); + LCD_Write_DATA(0xE0); + + LCD_Write_COM(0xB0); //LCD SPECIFICATION + LCD_Write_DATA(0x00); // 0x24 + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x03); //Set HDP 799 + LCD_Write_DATA(0x1F); + LCD_Write_DATA(0x01); //Set VDP 479 + LCD_Write_DATA(0xDF); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xB4); //HSYNC + LCD_Write_DATA(0x03); //Set HT 928 + LCD_Write_DATA(0xA0); + LCD_Write_DATA(0x00); //Set HPS 46 + LCD_Write_DATA(0x2E); + LCD_Write_DATA(0x30); //Set HPW 48 + LCD_Write_DATA(0x00); //Set LPS 15 + LCD_Write_DATA(0x0F); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xB6); //VSYNC + LCD_Write_DATA(0x02); //Set VT 525 + LCD_Write_DATA(0x0D); + LCD_Write_DATA(0x00); //Set VPS 16 + LCD_Write_DATA(0x10); + LCD_Write_DATA(0x10); //Set VPW 16 + LCD_Write_DATA(0x00); //Set FPS 8 + LCD_Write_DATA(0x08); + + LCD_Write_COM(0xBA); + LCD_Write_DATA(0x05); //GPIO[3:0] out 1 + + LCD_Write_COM(0xB8); + LCD_Write_DATA(0x07); //GPIO3=input, GPIO[2:0]=output + LCD_Write_DATA(0x01); //GPIO0 normal + + LCD_Write_COM(0x36); //rotation + LCD_Write_DATA(0x22); // -- Set to 0x21 to rotate 180 degrees + + LCD_Write_COM(0xF0); //pixel data interface + LCD_Write_DATA(0x03); + + + delay(10); + + setXY(0, 0, 799, 479); + LCD_Write_COM(0x29); //display on + + LCD_Write_COM(0xBE); //set PWM for B/L + LCD_Write_DATA(0x06); + LCD_Write_DATA(0xF0); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0xF0); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + + LCD_Write_COM(0xD0); + LCD_Write_DATA(0x0D); + + LCD_Write_COM(0x2C); + break; diff --git a/libraries/UTFT/tft_drivers/ssd1963/800alt/setxy.h b/libraries/UTFT/tft_drivers/ssd1963/800alt/setxy.h new file mode 100644 index 0000000..7e6a81d --- /dev/null +++ b/libraries/UTFT/tft_drivers/ssd1963/800alt/setxy.h @@ -0,0 +1,15 @@ +case SSD1963_800ALT: + swap(word, x1, y1); + swap(word, x2, y2); + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/st7735/initlcd.h b/libraries/UTFT/tft_drivers/st7735/initlcd.h new file mode 100644 index 0000000..63439c7 --- /dev/null +++ b/libraries/UTFT/tft_drivers/st7735/initlcd.h @@ -0,0 +1,104 @@ +case ST7735: + LCD_Write_COM(0x11);//Sleep exit + delay(12); + + //ST7735R Frame Rate + LCD_Write_COM(0xB1); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x2C); + LCD_Write_DATA(0x2D); + LCD_Write_COM(0xB2); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x2C); + LCD_Write_DATA(0x2D); + LCD_Write_COM(0xB3); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x2C); + LCD_Write_DATA(0x2D); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x2C); + LCD_Write_DATA(0x2D); + + LCD_Write_COM(0xB4); //Column inversion + LCD_Write_DATA(0x07); + + //ST7735R Power Sequence + LCD_Write_COM(0xC0); + LCD_Write_DATA(0xA2); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x84); + LCD_Write_COM(0xC1); + LCD_Write_DATA(0xC5); + LCD_Write_COM(0xC2); + LCD_Write_DATA(0x0A); + LCD_Write_DATA(0x00); + LCD_Write_COM(0xC3); + LCD_Write_DATA(0x8A); + LCD_Write_DATA(0x2A); + LCD_Write_COM(0xC4); + LCD_Write_DATA(0x8A); + LCD_Write_DATA(0xEE); + + LCD_Write_COM(0xC5); //VCOM + LCD_Write_DATA(0x0E); + + LCD_Write_COM(0x36); //MX, MY, RGB mode + LCD_Write_DATA(0xC8); + + //ST7735R Gamma Sequence + LCD_Write_COM(0xe0); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x1a); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x18); + LCD_Write_DATA(0x2f); + LCD_Write_DATA(0x28); + LCD_Write_DATA(0x20); + LCD_Write_DATA(0x22); + LCD_Write_DATA(0x1f); + LCD_Write_DATA(0x1b); + LCD_Write_DATA(0x23); + LCD_Write_DATA(0x37); + LCD_Write_DATA(0x00); + + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x02); + LCD_Write_DATA(0x10); + LCD_Write_COM(0xe1); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x1b); + LCD_Write_DATA(0x0f); + LCD_Write_DATA(0x17); + LCD_Write_DATA(0x33); + LCD_Write_DATA(0x2c); + LCD_Write_DATA(0x29); + LCD_Write_DATA(0x2e); + LCD_Write_DATA(0x30); + LCD_Write_DATA(0x30); + LCD_Write_DATA(0x39); + LCD_Write_DATA(0x3f); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x10); + + LCD_Write_COM(0x2a); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x7f); + LCD_Write_COM(0x2b); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x9f); + + LCD_Write_COM(0xF0); //Enable test command + LCD_Write_DATA(0x01); + LCD_Write_COM(0xF6); //Disable ram power save mode + LCD_Write_DATA(0x00); + + LCD_Write_COM(0x3A); //65k mode + LCD_Write_DATA(0x05); + LCD_Write_COM(0x29);//Display on + break; diff --git a/libraries/UTFT/tft_drivers/st7735/setxy.h b/libraries/UTFT/tft_drivers/st7735/setxy.h new file mode 100644 index 0000000..ff38181 --- /dev/null +++ b/libraries/UTFT/tft_drivers/st7735/setxy.h @@ -0,0 +1,13 @@ +case ST7735: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/tft_drivers/st7735s/initlcd.h b/libraries/UTFT/tft_drivers/st7735s/initlcd.h new file mode 100644 index 0000000..d28296d --- /dev/null +++ b/libraries/UTFT/tft_drivers/st7735s/initlcd.h @@ -0,0 +1,98 @@ +case ST7735S: + LCD_Write_COM(0x11);//Sleep exit + delay(120); + + //ST7735R Frame Rate + LCD_Write_COM(0xB1); + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x3C); + LCD_Write_DATA(0x3C); + LCD_Write_COM(0xB2); + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x3C); + LCD_Write_DATA(0x3C); + LCD_Write_COM(0xB3); + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x3C); + LCD_Write_DATA(0x3C); + LCD_Write_DATA(0x05); + LCD_Write_DATA(0x3C); + LCD_Write_DATA(0x3C); + + LCD_Write_COM(0xB4); //Column inversion + LCD_Write_DATA(0x03); + + //ST7735R Power Sequence + LCD_Write_COM(0xC0); + LCD_Write_DATA(0x28); + LCD_Write_DATA(0x08); + LCD_Write_DATA(0x04); + LCD_Write_COM(0xC1); + LCD_Write_DATA(0xC0); + LCD_Write_COM(0xC2); + LCD_Write_DATA(0x0D); + LCD_Write_DATA(0x00); + LCD_Write_COM(0xC3); + LCD_Write_DATA(0x8D); + LCD_Write_DATA(0x2A); + LCD_Write_COM(0xC4); + LCD_Write_DATA(0x8D); + LCD_Write_DATA(0xEE); + + LCD_Write_COM(0xC5); //VCOM + LCD_Write_DATA(0x1A); + + LCD_Write_COM(0x36); //MX, MY, RGB mode + LCD_Write_DATA(0xC0); + + //ST7735R Gamma Sequence + LCD_Write_COM(0xE0); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x22); + LCD_Write_DATA(0x07); + LCD_Write_DATA(0x0A); + LCD_Write_DATA(0x2E); + LCD_Write_DATA(0x30); + LCD_Write_DATA(0x25); + LCD_Write_DATA(0x2A); + LCD_Write_DATA(0x28); + LCD_Write_DATA(0x26); + LCD_Write_DATA(0x2E); + LCD_Write_DATA(0x3A); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x03); + LCD_Write_DATA(0x13); + LCD_Write_COM(0xE1); + LCD_Write_DATA(0x04); + LCD_Write_DATA(0x16); + LCD_Write_DATA(0x06); + LCD_Write_DATA(0x0D); + LCD_Write_DATA(0x2D); + LCD_Write_DATA(0x26); + LCD_Write_DATA(0x23); + LCD_Write_DATA(0x27); + LCD_Write_DATA(0x27); + LCD_Write_DATA(0x25); + LCD_Write_DATA(0x2D); + LCD_Write_DATA(0x3B); + LCD_Write_DATA(0x00); + LCD_Write_DATA(0x01); + LCD_Write_DATA(0x04); + LCD_Write_DATA(0x13); + + //LCD_Write_COM(0x2A); + //LCD_Write_DATA(0x00); + //LCD_Write_DATA(0x00); + //LCD_Write_DATA(0x00); + //LCD_Write_DATA(0x7F); + //LCD_Write_COM(0x2B); + //LCD_Write_DATA(0x00); + //LCD_Write_DATA(0x00); + //LCD_Write_DATA(0x00); + //LCD_Write_DATA(0x9F); + + LCD_Write_COM(0x3A); //65k mode + LCD_Write_DATA(0x05); + LCD_Write_COM(0x29);//Display on + break; diff --git a/libraries/UTFT/tft_drivers/st7735s/setxy.h b/libraries/UTFT/tft_drivers/st7735s/setxy.h new file mode 100644 index 0000000..b7a1c64 --- /dev/null +++ b/libraries/UTFT/tft_drivers/st7735s/setxy.h @@ -0,0 +1,13 @@ +case ST7735S: + LCD_Write_COM(0x2a); + LCD_Write_DATA(x1>>8); + LCD_Write_DATA(x1); + LCD_Write_DATA(x2>>8); + LCD_Write_DATA(x2); + LCD_Write_COM(0x2b); + LCD_Write_DATA(y1>>8); + LCD_Write_DATA(y1); + LCD_Write_DATA(y2>>8); + LCD_Write_DATA(y2); + LCD_Write_COM(0x2c); + break; diff --git a/libraries/UTFT/version.txt b/libraries/UTFT/version.txt new file mode 100644 index 0000000..cbef4b4 --- /dev/null +++ b/libraries/UTFT/version.txt @@ -0,0 +1,65 @@ +Version: + 1.0 12 Feb 2012 - initial release + 1.1 09 Apr 2012 - added support for more display modules + added support for String objects to print() + fixed a bug in printNumF() + added optional minimum length and filler character to pintNumI() and printNumF() + added option to disable unneeded controller chip code to minimize memory use + 1.2 14 Apr 2012 - added support for more display modules + added getDisplayXSize() and getDisplayYSize() + 1.3 03 Jun 2012 - added support for more display modules + fixed a bug in the ITDB02-25H init + 2.0 21 Jan 2013 - added support for Arduino Due and Arduino Leonardo + added support for the "AquaLEDSource All in One Super Screw Shield" on chipKit Max32 + added support for more display modules + fixed a bug in printNumF() + optimized drawLine() + optimized 16bit data transfer + optimized some 8bit data transfer + added option to use pre-defined RGB565 values with setColor(), setBackColor() and fillScr() + added functions getColor(), getBackColor(), getFont(), getFontXsize() and getFontYsize() + added 16 VGA standard colors as pre-defined color literal + rearranged the manual to keep related functions grouped together + 2.01 05 Feb 2013 - fixed a bug that only shows up on linux-based systems + 2.1 29 Mar 2013 - added support for Electronics Lees 3.2" display shield Rev B on Arduinos + fixed a bug that only shows up on some linux-based systems + added built-in support for using display shields designed for Arduino Uno on Arduino Mega + changed license to CC BY-NC-SA 3.0 + 2.2 01 May 2013 - added support for ElecFreaks TFT01-5.0 and TFT01-7.0 + added support for chipKit uC32 + restructured files slightly + 2.3 08 May 2013 - added support for transparent text background + fixed a bug in printNumF() + 2.4 11 May 2013 - added basic support for multiple display modules from Coldtears + 2.41 12 May 2013 - made some changes to facilitate the use of add-on libraries + 2.42 17 Jun 2013 - fixed a small bug in drawBitmap() + fixed a bug in the 16-bit Arduino Due driver + 2.5 25 Jul 2013 - fixed a bug where some lines were 1 pixel too short + fixed a bug in the init code for 7" modules that were only visible in portrait mode + added basic support for more display modules from Coldtears + updated ImageConverter565 to v2.0 + added ImgConv v1.0 - Command line image converter + added manual for image converters + fixed some omissions in memorysaver.h + 2.51 02 Aug 2013 - updated ImageConverter565 to v2.1 + fixed a typo in the tools manual name + 2.6 07 Sep 2013 - added support for 4 more ElecFreaks display modules + added support for Watterott electronics MI0283QT-9A display module + fixed a bug in the "Arduino (ARM)/UTFT_Demo_480x272" example + 2.7 03 Nov 2013 - added support Bobuino (ATmega1284P) + optimized Arduino Due driver slightly + 2.71 06 Dec 2013 - added support for ElecFreaks TFT01-4.3 + added support for Coldtears 3.5" and 4.0" modules + minor changes to the library constructor + removed unused variables + 2.72 12 Dec 2013 - added support for ElecFreaks TFT-2.4 v1.2 + 2.73 16 Feb 2014 - added support for Teensy 3.x Boards + added support for three display modules from ElecHouse + minor bugfixes + added three new functions for CPLD-based displays + 2.74 20 Feb 2014 - fixed a bug in the serial driver + 2.75 28 Mar 2014 - added support for Coldtears 5" and 7" CPLD modules + 2.76 04 May 2014 - added support for several display modules from DisplayModule + 2.77 24 May 2014 - fixed a bug with the ElecHouse 7" display and shield combination + 2.78 08 Sep 2014 - fixed compatibility-issues with Arduino 1.5.7 + diff --git a/libraries/UTFT_Buttons/License - CC BY-NC-SA 3.0 - Legal.pdf b/libraries/UTFT_Buttons/License - CC BY-NC-SA 3.0 - Legal.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed326c9d62012e183e6190ca9bf7bfdaec7ed4ed GIT binary patch literal 150761 zcma&N19&A}vj!U5c6N-3ZQHhO+qP{^Ji)}aZQIU76HanxzVrR(|L=Xid(P?S*}Hpp zuUfTM)mv{@uj);vAR}-tm@&G0_dQku)69W@FE4>_monGb7B^CxYdI^9wfR&j6z{Je1%f|Z`?n4eQ)7D*Qw2jOTj$>zh3#!zZS9-^tn>;_rY4rgF7{5p74h-Wi`p4G zc{;cNm{@*`D$$Es+PIiH(Tmv_x|se~5A>2E+B~A1oD7_dV$6&Tf{aXTEDW4%3}Q^I zVj>LeVhn5|3?h6y%$!2Z%z|vf%*;aULM$vyg3OE@LW~?@f=q&J>?|UJe7f|Kb|$7C z+Q04adlJ8YnAroEnEp~KV`^vaVgX=e;P^8-xBr?nJH3*<{qJ$H{?$bJx3K_h4D>3V z4yN=PN~UJ?>e`F|W&q=Fb2z&=nHt){!&qz^8JQR$85kHD7T>B{uK96g9ZR&hP;yCn|jmlq5sa+=C*;UZ4wF)lme@OQXlfIycj&pzdZyG!^-(@@BEXU0gN0R^#8I2D=WS7Zx1p4dwM$dWcAq>r-?vi?S~Gd z)w)hosp+TPPxnDM(siOcvq=cGUW~D_=6vDLBWkA%4tj?7FW%_8_*76Qrxaki!PbZc zSiGnuWdn=~6Cz<()J`}rNA!nf^iCuTXjcT|wApu7mV{+VF#ykAWd1AtD#{2mS4k8% z_QY@3;k#0Y$c)uUc6F%rd`UCNR@93NK0nDvvu3{DO%J1{js1f){=(DWa2FQ)jX-4= zlfU+Yt}Yg$Zl-oF^dk1g@(!kU^ul7Y^lD81J##j`-`l@{sO(~BXJY7N^50jPIOydm zk*VM2k_{kq?7$n0eRjg`RN5T9qG5lgq7(|}`iUCa&Qj4U0B9MRSs3V*04%>%+lu{{ z{@>qD|2kBq44%K;*e@BQd(RH7(}S(}4)p)osOZ%IEdLI-zo7W{lw?g^3{4DO41Z(w zFMKK(nw!cPdfL0X(97GI{#Ufo|2gRlU}F5M#b3x3{w-o-Z~h;B{zt?L+uOPPwu`g& z??C?@ivZ@o1Od!{1qp!p4}bhV`B$6*nEz4>VE!Zi`y~6Hoi4qwlf8qGy@xgf-R~ZL ze^@zL>3)lIurShbGU?KbJK4KB09ZNxG^UsRO#_DiL*w7f@p~};8oiRKv%Ra6vFYDj zV(+BvU}$Xmhgg&u04#s0|9!{^VEL=_KfL1MBL3TXE`QpH|7r6F{7Qcu`+JtZ >V z9^T)UQDOW|Zhs9*MTH5#`d=1RQDFwK{?+ksAq{yWD^ue?a+0>c`}(WJUocU!|Dyx& zH!=J%_mYiCi-w#tygc}5HvvI5777fx!Z#8^E-Y_bz*)Or`|(TO$GFBgAhfDm4o(bAg(@#$^oPw%hsO} z*_m=rt%CrMpAIWUwFIK=E&O~>CE(xh(Ja_)yd0H8o9GB{4K}wc-MV)>z#&2&P8<76 z)~eSNv&8_zuBcbVn{AYvx%?aM9dUT0pIY;~#7lCbiwe9~VES893a*>PpDTJu%f=qm z#IDFvw6=}mNkh5>r|WRu!tM|lc?{Rvo>HqPjb)6HBCd*@pYN{wlp-kbr)LT0upJ7v zrlYJ)+l?ELiVWw5PHiCsDHmZm)rN2dcQKB269KuxN|VkuRI@p!-pc3{vSSORS%xom z2wxdnT(R=IqSo`HFG1WlPk69XTgTX1I}3_CRZYdzt{A&X0~W*f`vNY4m|~X7#jw9D z8f!L8l3w9<^G16%LeDT#%b6 zWWMN&F*Xw5$8hz8FkKJLOdahVGf$L{4#&=*!sY41*W8O7Oin;?+m9TXji|@NC6ERT z(*eiieQ~ze8#~oU?QTs9ZAj(!vcLQIL6RGYXm3CyxbO`;Cx(rs`duY4OOiJJRI*BH z#R$qwvpgBo^-D^p4B&`9j^G>z566~$(PA!oZA6yk4(?4!A_zicVLo0xDb{`&8`s;3 zdbWdbo_VmD=edZ)t0=UduuE+LQ?etj`9?adcSDi6mnxkBQ-;GgGVTKI!&K+)#51|p zr!`r^71o;JyW+?O1zQs~QCHA#0lC{#_tygt*{Z%RQmxhTdr777mL9x1u$ynfT|mY# z@R>orGL&V{-e8qAQi@rpT%V%@MUTu;h9EAdb!(XOO)Gp)@;DIq%GAiog{D+nx<4WX zoBhe%cje}+T%ggwG=uq6)awL~LA+0gDN3$?^6F{Bwcpxkdie|KLs;z%<64z- z=!I$q)~_jv=5}7`CT5{_XcI!nZ>4pwbGZbp#G*Kgr_BkY7K^n+)P-kq58qlc!h*Fi z&P4!hE+4oz6*~cL(c!j95F$!|k1Z{eQVW-h@2;*b1Ct*>pSz7Rl6*=GvJ1=QVjGpZ z;-L(Qpz&`P&oar&2v>^-^sId3RX9z|Bl|**5|%@pgCjyXUXP8&-~Z{h`iEct|2ggN z?17bq{olletRYfb1-GbQNaQC>fgZDa72ly;DGxM_c?_N{wl-UdB=8t=jA=rwE8{!Y z$!^!eOi98azAi=}Hmy5woIU2}L9{&7pTP0Rf*`dV^8SNnwN@F30;JD+k%F$Tqf_u(1}(4j}2!c zjgRwP#IzeWiFwoZInOVvq%_;ZH|c}u38FRbEPEn*MB*Yie64enuKaADid2LkL+Cwo z$eyp?`o8n|H0sxe8pbHZSIVO7#gdTPIu5H?$Hbw!!58ip@uPpk%$m{CSI^afY!m7< zvKcth*ce_npz@w|E>8Kma(BafLPBLtE+Lq>n_n9#hS$p)txA}`iENm^S+hd}{INXm zkLEV{$WFtIHl|x4!F=Q6)08^uC3cN#_w3d0TLUTz8Bdm9%ntJYrP6;FNhqR6-Fb9X zE+AVnz=B0DzwN4CALr}QVz{8FU2xz<)Sh@^Ve4Q53(XQ?GF|%}9mVZJ!{Q|R5$GCc z&&)lto-5WAj+jJ z>Q!zYRoJJNQGfICJD_6UJpC*%D&a4?F9qe0Q^E!f&-@!eDvx#27Ypf70<>#U-DWtf zssk_vR5Gg{0&}zz454JR!Xschge#DvHIYM%;B_ex6p)y=$Q#nENP_wqy9Pk`<(D!+ z77UbrMFSYSmaYM$v8%K^7UyPh?q)*nS@?ZVjZ&71#1r;u4`*t)fq`^M6@&Fs6mkx8yV z^2a-12qgS*OV;K~=*TeJHUf%itw}Bf`G)cR335N}Ems+hir5K65fNmwk)0Pq#j~h9+KtJjbSVHj1ba@LF zr>4Cec$z?y;1CJg0P|+#I_x|q&=L`2JbAhlcj{^VnT5Qp@Z-c0Z(wp{1twWt$?--t z5PW<*u=@IuWYbYP;z#hR1=IN~^PJ2DWXDJzc}L1sPcksZ0V^CwIn^FSpq);6-x7Mc z_3$sG0mVFbEET%LN^ROEJa%a0y7wL5C55c4`o?ViD1TKKk|`a>AwjKx4EPkJEodLki3IMgg(s)C=r$0t7j@sS?2WC`u$}w~ z*|gJiy-JajF^Y42l>>w~OBNuOD0NY(>9%I=CIZuFVWsU6Z}k1t3V+3ikI2Hs(-h=) zI(?tmwX=ed)n4Uz`j=CRxQ1zy4e8ywiv~7<3BX=5W>X^!mq& z>3y06cbg;MPIgyzFPDv|;oQeKGT&sBYUWU;2j{{M0gY9)nL34zQ;#n21y>k34VT2e z)eaf|4XE&40mJ48Ocx?5PVCvwMX*O8H@;d(XVDOQ#i*DR;BzW=XW-^v#sqPujgH0l z#BENyCBoSXneThZmfY<)a<{$?*nE{er$;v^iY3qbPK&oZX|DK17^NQI4|#6MX4_Rj zG%`Bu>VnIcGlF)P6C8QPJ$g3Kw*^QnRo84*BDkh*$Ki*i^)Lbw9eqj66#~*EDiB!6 ztMUruPzDW?>$+2&KrZgB1>Pd}n4LzA3D*Q9`U*~wu)`(j~2_dr zlu&*~{lYQD*+kFreXI@9?QK9gfwulB3|Xy81eYHx!1VEA4y13zbTo3SP+KJx*0p%9 zYKTE}A?@D{5gY9{EbN8PSeUWaos+>ZD!mkQp`P8ZB@fB%`S$KA)Zd?xb1Z>0Az0A> z?teFs7bDAks6P+(<7Xn$C6>hyH*%qan>jh`r#dc$4;kb?VfD|G{Qr(smftHN|GKBL zWwjc}iNzh{3$A4Khvu_MbZ=TyPB4?}lDj|>a%kzsbllhKEt9Ds&BvMx(5k(@*>Czn zJs%u19jktU*p$Mwe3?Qdhs?!kwW%A+jOuAUPKE=b2W_ujFJb}Qf# zyFH5$vYB`~Q~^`k$QBJAYRK)9SJ!4X%B>(h zGQ&h84j3}(S69ftkFf1+e|h~rFx<;;5G*HPJnU5O(`Vaqp#BpQY$+#XjD*|!lqb=b zDMrk2@kW>H*NP*e?BL*&WhYe5QxvwC8@Qng)RwS3pYFyFol#Z)IzA~@WSyg|)*B-T@j?F3=&PTn4B867;L-GyLpPUOT*qJdRH{>~u*2v~pg*O`WP(D5Oiz{lztr%s zNd$HDiJ#3G> zPI|p_n4ap*CL0sXJB>vt4UTR!N6vHW6~cUNK(Or$aS&a;1?*Iy;5hJN@5$^SZFl74 zqLDZ`CqJ*QK?~r8TuU${6&UVVbb;=3$tNqpvh|tW<96*$N+M*Rw_Gvh{kZ2K*e5k{ zYda)w(A(lbJahd-`Z=q@i<2fLBsU?8pid{TNz3S`vV}#Qd=pu&$k+!)YDIbos{_qO7827 zi7u=vYgh#dl3pLj6%?WV@#%JYAD#$jaX`r<8m3?yoKSTF{xZh<{l~4x385pNDaCt# zusqg|(t0v;L(nnH&{imnVE!f~e|jL-~wlGYT3Fl^vlQBVb5(2>OHmRzakTPF%%NJi^-*?E8g`jr5?jHL`b;(ZK{eH;U3Zpu8F!UIqQf>I?XoSpz zXvgiW`(^6L;Nxw3`C8B-hUOj-Sp`gEEi;aWv)1_{r&b%dxsl@luTkpfJ!ggW@KPR0 z+J3q3N4l|7LFfsmjsgt8%)|wAoE4+lz-(`EEy=$cIMKKgBcB3kf@}i%L4A++s@~Tn zXoQo!Rs$Wrpv&XlTMutKcf7~aL;+70&`{dwewQbdrK)__E8UT>zTQPHe<^KABVMUD zdm`o8vynYe3-P^sum6^=x~wa;mN)uO2>r8C`oFU+`|m2qzt~ns-V0V+CzbiuVN3Mc zv%YgOE6RnT6UD0l6YCL_NaQlp2=e$_8P75iE3mBmy2{bdgb!K}<|gY*8(b;9M8)2$UK$%SGd)J5>FZf#%JO~7 z43gZ=F1^>sO=n_eNLTR_pT;S^tM`Fmr{#TqIgIRv2Cj}qIe;$bY$(IEtZsk>RVG-# ztwWh&}aXZDpgvoRSuJ3Jts?nsP zG9L_#$|Z^VOZ=UCjIbzr-XfEEsaPI zwN4yd11_vR__1?5m`nO?yMqR&?vEXzvQYykpK^Y}0^SpI} zissGl?}#; zmP>u2uQ&v4d>wEM5j6nzj=B)5X>Zk0|sGTB33on48ggB9Yj39;9F8KdrB61^bU z{JuN3kI<)l{N&9$_;4ZV5{i~z=&x-ifH5Lti@mvE>}T>H3m`k|zOFz&iWrAUZCy}I z_elv_n?7)cHs1dz)LLPQL@>1^X1*%7{mGi0h($P6;}E^`H+i^IKnXs~@})iRRtkaXOju4nQQW4F%{wik+ z`Gf~Q2xDy%I5Ye0$tE#D&ADpiwz>BjHRMRXuqXc$nsj7{XGDHGc?XjUt zl3y0pt7)bfO{y-*Ra-3=f;^+^Jj`>LvWsF{+x)Q3t&!70$HkgG<4_$ZdzfTl|Ah1Z zD3tvV`3A>-6ij~+v*a6VZ#6>pAkZHs)joe`@a*KU*qzu2yzI6KM&>8MW<&-e7KG3{ z{6w=W1asmxuAdiM)u9ixR0-Z3Xkn5!5ld_>*7MwFYk zK_?Nm5nWy?GSjOkxDtF10xPes@G^}AaU4+6`T3b1@^jn<%RKrKUjI4dtNt=%kck~; zt{YP27ue$2cP0&Al;EP!j-v$ngMfa#1FbnSE(noK}($|_)V81 zUMA@uCZ^l1pGd08!0V#iMlK7=tq59vs&k-SuTD8EK>bvkTI$NBmsz&LWK5(Q!_ZRE z^*!Phg1d5_C2_36Wh=1kT6hQiF0Iu%$-h8Bl^U#3jZ+HZ>A4$y?RJF>X(U!#aE7D7 zn7&WUV~kB$?TW^yH$?3O$2$BH#ck(m7Vz_1u~JptK?x+xlpm|Y=+Bta(wF!})0S#n z(rK=oc7A~rE1qw0pj0GhGW&7w=9w~G2sJKIs3$Bh;3Fy@g0AF4*`(CKG)T9yxES1y zuo`kj?JX)jFMs+VyQ%Ez!ZEs{*&EBE%%RQ~9U5V6kA5ck#h+Sgxe(4opM|v%B_=bH zB1*_-PCtZ`P$?%{#5da=zrG}G#Vj6>UIoK-cEb9TlRWu`DF$9N?OQ0VB1OznDf}Ch z1GWFGCV4%aG>}pOt;jYxyX`ozYfQ%yV?mpkKd!Gs20(aRlaig=y(_s;P8!4U+S|zN ziQj_RjcLvOvF6f}Uv<)m=bzyIKi4k*POq7n{$qKKU`DSgvuA@IQR)81tpTe2vugsB zEe*66vuCW^qidqQUs_XN?qO5Y{suR8x0o-kTm7A^8mj4GIMMcMRq0kzQD%}iM#C8|fOZH%t%D1QGK?SbK^3$9i@-wb_NF zU%W#cuo*7u*@iVzBt4Zn0MZc0Vw@b8mQaYeHK6aPE})pU+a7>Wj>(mblyr5Hj2&O7 z%QJeLcr}geE|)sH@C@FI*S*dXg=c2L1eW*RxARtga{KT?K zFP&LG#_ZR?yO_r%0jf@&H>o=jZ}!FBrfdLOv^b^%V3GhfDnDcq+xikW!tR4xg1k~f zJ$|g6bdM^y#H8jctV6-JF{m*ND4DI~{Ccz!H9aP~+;T@Bx%$nO>@q4HF^G)zKY8Q- zRCQruWcyP;{&zZQLyx>#i#B-tm9C;HOwCQOsky2I|8>cY0h3iA=ZNC{4z>gDpDgr$Di<&_u&^-yU2kUuurn|-G5_0I8omAr%8{^a z>7qj&Poy~3zt&bstUdXh#WEcF%tkJSILWj#6}+<-KN_L*6FEcORHby8ltOr4+zR#D z6rk4=hEF!7^gxGkeDSND)rr7OI!31A{9EVk89^~!+`AU%B5&wIBd!fi5|DjL-UkT_ zV<57=G3=>`%Lafk=E&NJnd;(RLC^R0oa3^wS7AyfX;;K$Y_FI#tPTT=tk<1J>1P)$<($7f&x|mbiV8rH63?h#?t)a z4p?7Ij`cmD>ojTB=pFq^EKb2@Y?iQ^Gw)X<$NV%Tcl$@|i3BiCSv7SZrzLw|F*^fx z9V7wv(fINuj5EU?DDB8ER0v`@Xu?fSg{ei`^F9r9R`r%ib@=IpuS2;oHw^KuqIX9e z7ciRHJ>tEEtQ=Rz`W&l!FGT3rHm;_m0F%qQ@||aFJOuaEL=8u!**Uua?9N|a61vLc zQT8D9py(hrUg8Bb3Ox=ay$1Gd2yWRQ6 zG*~vHY$SyyaFSbO3O~#4ftVKW4r;X#}~G z&*`b!YbYV!7Pemmd66TR%u`FdB@$(b4iq6$9WBP&y)a%}b3_G^I{{&-j&W;_x)R-? z_}x#p!{b_#llB?K8nQ=x%MEDh{v4o}@8+o4lc|gK3?u^x-l!o8i z+p{oUFF){r{>qQ3I419I=xi8ahZ27J(!ATzPaj`#oWQz4RT6#jZBwYa0Uru}gN9iF zc4?V2|L|+_%(gKW_v!2ME39xx_*r7 zWBM@fIZm#_Qdn2Dv@|^FIa*&>>o!$270w6=nU2f)YK||G8pFu|@8cGb5NxGgQ}vc@EZ#I;P{`OLe0R;ph-K^h`3=3+hVHbXrI_o4U?U3CtcdaBs@MfPZP$^1TNamRt|A(s3t+wAC=R#S#(PSz6|Jt50Mmipi+GzyWFTn@r7laMpQPp zE!Kb#R=bPLK=gW+QoxVIt~pT(AoMthn?BgmgTt3hdC$ zOf_!?CA5wOgZ!tOhcBf=9s(rL?eDgDoAV^;Nc!~=F=O-r>X`J(G!q1`TQBUEOg}yu zmrE$68cVky(1E^=g!OraFC|}$BOH7<&L8tVvD}>Wk~SH=8+^~#b^E5B`cZ~ly7$UZ z_~K&`Y|5r*+cv~<_5>GNa^c2PqfHG_aA1^vVoR=SmR{+5icT%cjPyhn8UJc--->6P z1Bpck)O~Cu-G$T4eK(AkBuNMzt8><$_)`%ML%nc=5m5k;a@`!I6w!uL#t z)U#&1+M8fzM{W>&ouVCS~$>oV=Q zd)k_eG8bcJ@GCZv?r~g84(J|i+L?E z{o}!H_L@bCAp&i0G+X?$ik+k;>zVy2rOUSkMxl_irapMGiCS z8@(Y4Sead|O*513QRac9tEuVv1o|BHB8W^qtT9K+uKCb6RqyS!W}dvx=TI8(ZAgp! z>cxTxNPABe$u1&@A7-E^*x=(b7DUymp;;g0*X2C4zu(~K1A7*Y_KvrvXjj=f_6 z@jlCeVi6sywH{vD&W1G1w*Uap39kZs8-9XuCaHA)+fI!hI3A&HuKSO399X9 z1e7>l_oYY-z{^sk2SF-m{Dd0VSH$|xXW}R8sma4kt%`)v<$wZWhXwbK6xb{dKJmidBFH_vtSX}kJIOYtbDIkbo{ zlqwaQUU9S8gq%@#jqQ1rYB}umQwA0I4<$9Rl)(p)uD-{P^S1KSp26l$BPsAC6XVlE z2?qf<7HDg9tY;NW)h^m`8-ldEkPf6+e58uOJ$x&F&N7L0_B!A%d^$@sAcoKAM_Hwn zI`FdRPjNsSK}q#TboCV@SF_A{tk>v!g?8Pi9GNuPn@X=UwzI9ldR?);o54&<&!9n? zAO+|twalB9K^a2Ljr$^=%WnaMse_gG4#b!qiT+hLeJqAY+|>Bv6JZ*o1r`5u?G-PmLHM?`OhEz-yzPdq4iz_149=xC>n(#S<-(lQh&d!(Sh4kuY;cK#x_XL<(l4vF+q~7p2)rd7JBw zQDLGPkSOZ)7*+!cl+Ujk>mF0)5|c?&@*W`mSw|=z0S_G@k zYQmS|-e+oFRHovZo7EOPPzvpy8r`1fOh)g)k2l#by$h#P&p_%)^;3)WLEzi6-`vTW z_`&oP)1;@E6}k>iNxi1F#EWT|4Sj_~&@nwQ)Tnn^`Ci-&^7B=H<`|MZ?|7=oIW7?XRvs^bptK9p$}5f}nXq!OTjMGhamy7iMF@NuZr~ zElft=J??Z>~Y*-4yqAI0W?GKNaazA6f~aXBjLiistEBDOUqC+>OLfUhPVH*+5cvfco5mRCG1Zi=iL0DW z3*u=<*6pLe6=e3CGJB)8cDj^**om!>i@;mUm)sp8p7 zRWbI%nmndq&8E7+AL_vQvR@M--?p8^U4JlCk*FJ@!{n^>#Ib0O2XoiNCkRJCPeeA1 zg3V-1)CmH-%IV7ENHe3@$o0sA5lgRMyx#?i_tBljqBQxga5ez`TN{2*M`tMV9d0~` z?}z3w%#)bFCm~n#ox`nNdfayn6_tsu=^Zw%iBrmnc=!t;5l;A_UfE2zckCZ~ySrg# z+d+{TZ7KmV*^nPB^u~*n(sex=;uc(d0ZgGHM&*j zcH+Y1oc6>$viSTu9y06`LcsyK7I4BVInQa((ol=aa+K4-6uBc>2w#d`{m%d)3R4(k zF+4!9TAjASlT%*3*0;{UEha<5*iEOcf_5f(1Yt1B8X^bu&Z@IX5nW+f@#XH^aRkb& zc(o{^tz&71X4GrxPh~RsOeY&J7%kLb+6M1+ET0o^9YZw{8~84FUiQelNV8b}i&g#) z?E=C^cM_&?I-_nzy#r{q(>`;hs)H*U{hLtDtd_{LxY#Omqst09@lvRGjfcg zKW)M947e03MGY@ykXlyJPqtW>^`ehe4lva{SePm(KPbCI4&5Jl5^?`>BVI`j9Xk`b z+(79;5XseJsK$3rG65k-E#jPOK|Z@30hTFyJm6lW(Z|Z|(rQQ_LfLc;Eau{7!iEv9 z@-_GQ`W>`hUDVC`RvMt$)!89Zg`+^syCqy5j|lYjYTeks-W2)$i^nexGjS-v`n~md zF)9qe#uVM`f`I0f{Wm&*3^yvj&W_1DEwM7<8RyfN{fv=PRAi0=P$?3rDTw>Fr$VpqrM>u;Xu1@)ZJH<@83YIG|ypOrXJ3;9{4Ne zll_5?)cHjTG8x96@R4YBzuIFeowNAVcE=`LbGYO?zd_|1fGp47I6#vv z5@DJ2M5@PpS?Lu_)+R2(ZpuUV{5nu#Rq-Y1YWXXBhkZB`Z2M0`as)Q@H-#zges7wU zlLTMC8(}g%7q?^A7H`CIP6%t=Fcj zTSZ;{@0)im5{br_%THJv$<__*58LS9$G!0dUL+S0MX9U<3a+joLmnFjRY7$NJa;(! zo`nLgvg1|Uk(Ijo??~yj#$K zs2ZqZmI{S_b!$@I-XFQrr>aAkf8X;d0nOdtI|r0fnMIv(X7aSJz5aUq&_BY21ESvM zsD>6cyGjMC3T>IHeq!^xdhpOzAeof;T* z@rt+o1R5C;Xq=ZG{X z35__5xg+TJA>~W{$=6SL&6lr{9tmR%R1&H#mv;&ebR0*QYxay`vSF8pzlKN@={+qt zGRy1_arb4rn}pfFd7`4j6SSUJs zj47JDk>HX2Szg-TS9s9BzL#Da6qf?TqWZXICxEY|#_J<=L|{#^W^Sb4jc$KZ@_?O?KdSPOYY*PBTlILDdwC z?#BcyqYXM{WP}R5rC=U*&lnsi=qZM%U(XC_W4VdOcgbzjHN2%MInf3zJDra@WS%h% zfKXt%jq7s^t^sXRHJ;;lDp4rR>J!WmeZ=!u{$nx~*Df-IRc4B3%*}l*@r1?k-Js5s zeLIwFuy@T@?A-klYmX-5bV~jfr&oPMcdYx0sL(_e>53nOZ0KPj6k$eY4?minxSgPP zw~a9y+~U)M%kL?|8-BTqjdRE98k7Hf5Ar3PGOT z48@J9D$D=M_vXnH4HY+Rq(A-~S#%NdONYH?&1`+@JUH^%wW_BE7ovF;rSk$4F z;}s4nlzLgK53%5!JsrxeB=s#_gtQ^`tkm##Y;J`@IoDBF)TSEL7jEr)Kj>HNczk(j z)nAx)f@1Laa+Jr%T6v|aP`Wz~YAY({0-2SH;sWy?A0`=sw7}p*j#WOjWyiYjr&4~I zkwI?-$P1E;zb+LGR=t5o7iUKA+vqc7UPS2?j+}CBtpcPkVWWi-tRX6KA$VL{gnp6< zuuAU0o2qnb>*9G@2GGW90y7J~X8|2%SXv8NfS7WrOIBvBViSi#&u4Fqe11kPq?zoz z{!-4=x+!KuCDpxhZhciNzjvy6f#!8c?*T_VHSXeL2mzsGqtNk?Of{kY`ooExDIxI! zL{Ou9dc!V2Mo-3?4r1sInyYqqfXI|k%ep6_|3S6+YWSxlj$U6i8Pi2FQVD#vb02Uy zA2v9BVSj?5?@3dzb;tC*MuvX8I9ubS2lM3Fm4C%LjHTVRjO7}^=hQ%JbcT0 zD*#)lK`RmZ!}!;Nxpit}l60T7yktgG+MzAGO|Ah?`hXi&MH`hakhu5CPw?&8dE`#mu|+D-|0 z$j1(}->^O{f+E6I%Jb=0(M5(X|?lhFJ-|nFpN6bX#e4 z0XExTk#9sP&4-$XH4=W?%t!U&)kmqKX2glq+OAt{6`t_Im&>sZ4Z&h6HpCz83YMN9 zTkFO7)3uH7QW*l9E;TCfP=vqDZy6}8^U_J{A;2dGdGz=H@RqyjAwXs06vI}olexTJ z7;J$!!6IvmglG#9woJHQbY>6Ilf;)hy)s1 zpfkX^H;^mVCpjv#BKKTcytT!NzUkrio%VpctU^FMCf11U_v5Hx(=*0%c51DHU$)UR zQG!a=LL6Fi5L}UrH?sS`D^0+~F~yb%JpgflubwdKPB4=5TWq8D;zdWA*XPL_LGUDhvY? z!;BehL#qJW*>zKWp&i~}>d>dBD`=g4UM!WhURS?icrI4*pL5sT+*JsEu94;1OKm5V z#pY_2V(xE*9db(4ETB&n^wlwky4eG(d;|~?=OWn ztpyE>84Lr%Y@cr^rcv*N$FYBP;sgVtk~Nd>SU2`1G`4JRTao9;g!7A9;xzB+et?!M zqsJjTa-5d8_ES&Xyq1hkL661mnMqT@&|7G1Y^U1GBk1(*`37#!@UbLGOy;<<+rp#d{xzR79vfd2E8ZN6jvlIP+ zDe77${EaYjTrEjg;7YK8_dU@}8Sy0KF+$iv5U&)tG}H=}Tg!M>Fo3t-)!WaMqA4CJ^eN4> zyIs5vMtQe>(RvWOKMeB72OL$@9tar@Vlgs_1`H|&f>59ZOAc9W{ZjAUij;QAoQ1f^ z`~L1?9IR*%d2I+AYzSFQe?3LjFK&AVE1qbFa}<@>TguO0h2iZl6QaSQHq{%~7mN4Bd#$xOyI)@f_j3;#Oeu7|?jBs2F zM#_vau4v<+G@lbU0VI!|EERlrZ00b_S`u}{j^RfXI|?oA4k(YPo%Ec*19V z9JNu2d-?nGev7NK`)-s3x^^xU`^~bqsm`cn=@~c31I1Z7$&xAv<~EF=Q&++YGM$r# zWaA^dPD0UW6BtcK*Cb(8gFRGI(LAAW?Vu)sT)wK?vDv#0Mbzisxvvk6~ zu*(2$XhKOMfei5Ex%z6WWLyI ze&AlnaGvcsYHfaVf_(&xdS;N<(xQM*Q%E|VGG4Ca4xB+Qt;xS+r7Xz=pm!sk0j7ZL z?5)2a+Z?rc>P8~q(6I_{r{B4r9u8Xll1d0!Ov2@@YH%3PMDv{Q+e^h=Eecf;XjBO) zaZ|HPX=NE8$}(o+FMGEHDgn`$3{{jUCUXoZv8?8`o-FGl;@49Tb<^jZv|r2%#M=a5a^Kcij^CMt81@+ z>S#4tR!X#VNSYdkU|Kr={{SgK*1vTTJ9NvR6jrMU-`!J$fe>sM&;!)m5 z2^rWC=33kaJpo`tm!qxml<#|V(H)ke9}^CwPM7L5L>c95@B;~) zxFDG@N8(uLim#I8B6Fq*%+D_mWdd#~VA{iE_bXxEesN6o4~uMg=Ga%3O9W!5tdo|J zEORQG!yWG)k$<^oQN6)ZpR!_LvGSS-;AjfdmbB}H4M*J0rAQ}eP8^>hO6ng$&|tu` za5a-N?6)B?Cd|((jRGq63WS(c`m+k)cryB>H5%8zwJ&zBQWr}HTQl&}Bt))}%NaR} zooa_q0#x4A@BZQWXUc4Dan+SI2`cJD=*Wj+`DycnRSqvbUxPu z?C4_dX$VG>>p(}X?eQiQUf}y+@y};&u)X~MI?uMYw4S`18MzDZK7D7rkA5Z|%6q7v zVjwon&Gy_k5&vsN!1o_X2vm8xTBbRBOhnHhwXM>AUo8mBJO#P*1+lZW7{F?ZmiqJi z)J#m!2+K{Z^7Z1GcM%N&So5re&JhdGao?jM#e}YuZa($l@>ywEfNBoalfs4B|1*@a zArL}4)UYaXh{Xs21Ej-wRVibS>^;($Mo}guTK!6%MxfD`4i&l%y|+TnoJLRwOXcIy z_`x}T2oTaxy4T34&zh0!N$B2As3e;Q(3*s%+BLz$R-Ur64u`!DL<1Ham~tl4pm6)rXd17aD6`lR{EM`s zrOAex?xobsNO^NgiaI4daW=6CH_`gM3~siFdYS~B%3lST4;7a<5>Hy$a4Pu1kQYU| z!7?t<**JQypQxE5(D-v6?!qSws1{u{WtbP$ho;cAcZyKPuL3tj-a8KT?Z96J<+bPS z)(a@b$n@PEX_g(+$pB}cz%g{{wFMLFtBj+BL=js2^;uWT6xb$NxSb5)H=W}nMPTp2 z8mLRpukqcW5o$WNt-6eS*?jHh^8RnV#F1t#NLbJ1}+ROaG=*Fe+^h$R2syoVfkG{4xG zd_@IMYOJs7=5ENwFfo$?;{tP5Dhm4R79SdO!`;Rf0scjYOQ^YYp1&L4{dC+fupyPw z{^!%)l}_Z`EHk;<_D4x3ik{AdA|vQjlHp3IpA)&rO4p)cH3TVsr81#zbK8Q5Y={XX zb!0rW0=WZ@r)c~w$O5mk20XKWyx778Q(Xs0ZIUSMNZ6orCVP=O5VhV5`1p!XpkZ9# z;tT3nejW1OqjskCj!K8&L=i_j7?YK3(#e^YVKSB~ds*T;eI$3ww>|=clRL>Oz=Rfa zkn{I4B*ZfPTbX2Sf-b5V4J<#?orH9gtfZyP+@*OLg|NIyMpc1?S>9;*?3Q!jJyRS6UB~DQ)c1RmO8*&^)Iz!%-1sqAHiR6$0#u!5@Fuv)i*Rj=_2b08ueg zsFt5is2^oR7)O>cQrq3hKc)ZSc=TTz&knyampAtNv5$1}jTP#d65?>=)@_fD)=icE zE2hLZUI$^Q2~$&#Ph`VaFK3wS1PEF}S7GuMYy*3UE{)};fhp{sJ{R23G6Smlf+qMi ztcw_r3=xhBZgL10w|$P9-6J9Z(b>|Jlq-Up_2Ek)0bVNayiteuR=08Sq2q7DBbayU z-kVYf#<*;*SRS!b6dasghzkv1T3t>(c<=~w=XjU*s9^%KJoUH4O=R|YnU02iL{*IK z;TH>qVOHKgjKdo{B^|0F;(85WR9p@>Xw~-@@?Hi0_tG#Obky$MCK=_h*#jx!F-ks) zIVHwh|C>glY^@c0Fu3{VqYP%RZB}D?r_T&b5ZC1BS%*8F_D@L_shP(sDa!Rb`uP~^ zRd}SUoMoSw`$4ex$&|>+|GYoOX+>F$hIZ25JOY|5E$noKRi!VW^hswUBCo?-#+=+E*=Q*<2&9!V)1dHjHpo(#aR3TKn!Z* zAsdnY*Ok{rrYiO7?d!WRFO@ZElULWlvl6+vu`2JenSL{!zskM+SIcPBp<86YhI%L8 zULn;dqGJ+@05ld-_2|Cms_Qs-(zc$+lB+ss@v8Ey1>*(qeP<#bP{mdc3C?6ejC@4h zC$IK;AIrkGkX|OU*Cp67nCCFJrAY~UU2)62xo3W~uC3b2!n(V?j1c{ckua5)d7uhr zTBA$NZXeP+3*EIi_wop>J;4fZFh6H$kn!>eS@@s&<}8X{ut4=uKx^<)1=^j<eE=`J zJctn2sr(`^kl~c2nAa}R%^9?WRun*@m(@C^jQ|kycP~HbXOs&FSXdtj&tpV;ud5L|I7>OLTq<5iDO6CsdRJo!_5(z&0DpEGiVj|3 z+$L72>vUQU5#^%ykLI?+(d8d zV>~dWk^eyKA|4QnbmADHfW0jxW@M`pe8GAJG)r4lxMI(agf_3CMcmYps<_bAa7?793ylM z@XiXK-ugmpxYQHYs*ejpF!?uJ5)+!A{!MaP=M`!_J!<{e5!HKo<=R=n;iW4br71;h z$*PwhW9#3yINGiTBI_i6gd$S5Wje>MT9E&eL)hVNZmy@r?y)Wu99N08nAF1g#B(N2 z4$PM3uSon(O+4d=Erdl8$hO~ZvBLj=s}+!c>&U#z)h>KSS^$eL$hNdNg;)USQLm|i zpsBT6%*VVpYMW4mEJcDJKoSm0Mk%4kmmahkoIoKPRw>RN7W!c#jJ`@lj}|0APVIy- z;Gji);j5y8&UC<&%nP#>u4bzN4kxCu6Oou=Ye`@EXM+W{o2~DLBUgK%n-hrG`RV?s ztYBYws5Ua!gJMCt;&IY-gs>jU>2!XBehh67}82TS|?*q*};+Umqo^^EMpCIT}2 zWcUvDDo(5xj{pXvc_1EB+>Ck9OoEc&_ORG+L<~(*yXbA{A8Neu#nV3_D7hO_Pz*Lta zZOCG6&rOlYYRF2F5cR5qn(ZE&mWuG4V8%!LuaB^fSt#H74y*>JzW6p4iEQynfI_ra z&<6jAC~JQ%+)VMDjqTD;=KywWzAoaX24^KeEtrU6TGUo690CcF`xAwtTe0Olt0IfM-u{^(sC*ek6;*89v1RoNSO=40=ZOoxX4{)m2Q0sWj$P+ z2`F&C1@ULbpnW|5@RC>qabM68gi%LC<0;*4#hNUi;geq^0R9DnS}*|up{cnxXTU)P zoW6Gd884G|Neis%2LKsW?lb`OGd(k3L#gjbJgS32099_o0-c8=E*&Nx(~W!?0tY&! zStAA3W?DKrpst9o-4N7IYD|69Cc1w0w-j71)5J8Gk~`~yyGiB$;c$S1>yx3I7Bp)2}>?fX{x-MoPz{QemX@p@8mO#+vX2e$eMKmNRcim0u71Q{iCwJ=stfCMJ#2wPHE;kn@Xep2XDq)r(M*S2e6doGi%*$35vru8 zyWITY%fR`nb(Ezrx0cr`>k5buec-0*E2Q%Rw+Ox8&NW=P&S#u!UW6sctnrS)Xk-FK zyu^xogSbd6#FJ3g_{aUD%5ZyCR|;xNyE)xkFY|bcYG7084+u`Z?2AgC$-Rhg5Qoly zPOsozHN*QSm|T9i~AQ=vDj2XQu};)hK&mnBeqAs&1_Z&I$KC~USKL&kZ^^Yipc5_gdV zXGYf+9u4=qT6!cU123>r{y15s{wI$X>%Ldu!JurjAa7VcBb6O$_S2vxOJ3+q{+4{5 z0gn4m8iQkl9bK`Bd40M1V^!NkWCV`75#7t1R@j2HIo7!}6fu2-WXsxEDMzbtuRPf= zvesFVoZ1%tm#bdCuW$L#*dX3wR*Mq#N-xG&Ryd|#w6MA^^j&5bv3Iu92#7BIFP(;i z-Wpf!#=R)5QKA_=8!orfJ=MJ4;c}I^DQ4c(Bs8cDm^yP)*rayuFfKhv3c4;6x>o;h z-Vijg*pzOcX#u33R6FK`Lu{GL_-8{jwA18XR$GTUc&I?!$n|y^d51i5nq#2e0a2m# zKOATJqaGV(IcZpf-^C-akwLY0n`*PA-f95t`Mx>hQalPK7#XDc;b+~N1;lze6eDl2 z$*yAhY*G=)!B!B7@aM^8VS~dgtib=Pf3T)PDguTiiV6(f<9OtZ2|%XVe>+e`5%t)Q zh$cdJY)a|zrL{mnicNGs#qkiDpu#UJDE5)}Zd-x$%#p;(Yhz)76AxB0n2>${JIdKf zO@y$LW{IMzI!$?+J=uZYJm$b@^nZLg#EfB!=aXx!F8};`fBRC`o|)Ez&wUf(t}!Ar z*dyf9h0+g2FToGB5}oB2RG^a1hy885aoGnsF>0@XEqL6npW*ipkn+^|dvdxpH=b<3 z7FwB2(me17BWgM^3R4dddLZ>!FW+CvU;^X~uC=!5;H4!<^2MK8yOXY>KvUwGF0dhR zM}|*zo~#B1l93?cLI}HXX?<3ArbC};4v$rQ39d=z8LmPV$XMYs|0N8`IsaxprK8qk zMn3kr7rs_4bQx_Sy zWzBS@C2Sr}gYOS(Ef+>>Sy>n_WVk#k=$l?Fm^5jL{e~0Dd8)1fh z72-$$l&qo`^`{x);SY~ix}=&vQMV-ZcvDyWtBv;|N-Ts4d3$fMT0iC1(w{;KF5@*av4A{m{wL+$iRzCx+L7yr}@txA1iozWjb$_NXKaGtpZDA znP5lvCqwps@)5IrEcqvzVzMv%BQRtqKLxFuXE{H?+PJq;XPy$F&uOBQ#vI)MHnE%Z z{(xWVD<1qO+9B$VrQK6PT~6U^|M<%xnksGcVG~gg-6>O(eAw>Up804TF#Rzzlzw*p zw~BF|0^De7tMdBx>>tVjf4F*h--&C?ot=>7+wFM05y^pv5sJE@qBmZZ{kysVYZ4VS z%(_f`+IDCTS(Ope{>P`wIUHoKI9)<3Xtu`n z{IIF6tn%Dt==1ni)D$kQP1e3=(+xM!n#y)a6Gqh8T*SeWhY8kw1Wu*|(<_Ja~GiLxc;^|)rO!9A?8gYPH3V7=dW=FC;!J{nGWp&oy2uI7GkRvBDk zdh|o)pDHe-p?EB)nIz!ME_}xLC8}_&RcoC6mLkQhHlv?WxvTYfuND)Aj3J3+mQ6TJ z5E-lp%mf`9uBMpiG~?@m#|UwR_}&2~2u)u%qk7W>QoV(=K*+oN0GCSO^MvQt=M?}P z)>1#6w%-Ql!)PRue^foG$c1x;vCh=coF2MD^d&$4g{^O2c<_+#a`itBOxTyl(To)! zHBoogm$NuAhV$vuOme$`6>{dEhh1A28Z#LJuOj+@C_9LmlSM%4$r9TiE;1Gx$j+Jg z4#@%;*8aSt-oultQNO29v*}9=;6n^q(3Lg*n)(BkU4HE7PG_p+;aJy)I7E{OMpSyCDe>$m=B;bU}xatSFB)&>1G1k{+h~E`2Ii*}kqY`x? zI@wH6+(6<%S1eC}i!$%c{0BJwMjBlqyKg#>NLyq2nZ&*{^-zQ@`<~Rrv#k)D^5#}I z{vN$<^zJ0PFHmxPc@REruHfyU3KZ4wan_~)nrWi<4aHrPpn{rt7Zz~lUiaZr!F{8 z^}Z+{2h#-(^c35x=yNiBAanchUPBUs2wJ*T7pC$YdtRG-f*laPz%btTJFw8T67X^G zGl2q8@R8(Hw})(OSB^<=Jyw0>(pSO>q@Xk-M+L)$5(3GhAKc}sG;6?YUs+U3ynhH5 zY(h1{Mf9mxf{slcd6@6U5^xpdb2qZd4tR)4i;BM zsV80Af30F5mF(jJV63iJDxHn)X22?fSK7eIbAEH(3t!p5-jTkrzEz4+=I&PR1w&?9 z>PeayUB>%pb{m$1tc=@YtS|oh$HjZ$Ogn^ncfX#A1kL6Zz+ew)z>s$)_TE9Qke}TWXug#Ibh(eJw!*g};Crcl;Za0+4p>jh4AA=<5*5@*c@Dq%8NJi1 zxOp)T77uSd|32*7Psk#IYNj#upqprUd|#nUoRxAB%+hBu0tnPVHok|)MZ_A^fo2=+ z$3l#9G7cT@hS|J;8Q*K0W}yM=&e$ieOdu$}hnC9;h7GO|h_SSS)1D7t3{;Ruu@DQT z&I(Lzx=ReNrs|SMw4fOZq2U&1XdFF^6h$Q5W3*&SrOJs=>Y0&iCH%X*?jE)mcv_0e zF27hO0fOsn$VE=MHj?`=KA0f65`XHU`cEL4y|4p%<4&mn@VEl{(Yw}KmW^r!Q@H#l zqC2io`l$Lgv=K2*a^AnGfayUmq1k^a-VfvpMfq8yAXl)-@i#wH7e?96qMyndevgb9 z2|T%jp@;_0^WaT9h$QYjOps#p^Z(Cpb>Yf#_iqca(BQ=+x!+ zVS=EaJds@ZG%&}pT@9=OH<#9&4)&0|#owx`i$5!0wBlj`-QMq8xL~+Y&QV1=u#;1b znky0mE8CJMM|a1Xc6IDA^DG%qkwJm4M{Iz1;RnncPS*aye1T@zrWoU*Rut8=3F8^@ zIF~jiDSLcDhBNk@lN99ak}borLk`&uk&agh2WC&u!JO1 zE~g6e&ss%2?r32~0{Uh0J9QTP!*(w5ZCZf~us<6H*&(%WK>=ZRV>VhX!u2lw2LqSK zbaeCLjv?0iQ0n}Y1_zAh*-?hq%z|luReMtJZAPSMtBC5-d^ttCeX?C9mJdVDEN-g3UZFbis zbI(|9plgGCm5B<6O2uk)xA;_fcxkf^L6j(xpUHD8#Vl3%aL3%`FY~miWutX-M+26h z+>ZqCd?-QNOBwQe_1!ePiLDJc=I`UcPr`E}=L@SJVgo3I z@QF<0(_rd%cyro0@=UeeS^vmTN7wmUKEF20%H-8c+vI`k^g^M?0-&iJF+F?3%Jt6> zOk?}O%yo|S)bF>sM+Dn@42Fdza~4~3akR@{uN~hB2)KHbJ1NeVeP#E3?C7O-U zElvRNsW49K^FUu?)C9DIFc*qqrV(XS(!XaU2ZmKY;m6B|e(lfP3CJcvMtGrX_Z~U> zE$DP)UPU)j?%p!v7TftqfL!9`K51``aF4g$oJK}_Po40j_};@BPT)B#o#_iOUSl&f zve(rJiTVCH6W^^rYREd}?KX4RP}m1wQv#i4 z@o?K`Q=|`vv6*>3d+P<>&#I$rbFgvmO^Uuj1VT%`RFcx3nCxmqnSV)byT#qcLFz?* zYJT278*JB(OZ;u)tXt-FTtcFUBa(rrVY_JJew2HL4*@QH$Of!rXl?OqeooMdi_(=( z^*I={*Ol@Y$aEOGif5jw0Ty@XBp5moW(tS!DGielgS$baS1`#2b(ISBF!ffVS}K0$ z;`GME91Z6Squv;CO(?~pn3c&QWMtLl=rG+9HNW1HGEP#h?pc=$xnFi0Wm60W4nY#7 z+JD$Pz00ftiU29{CB?YVQ0kh%Jz6@i5zzt^n(KBVCZj6^NV z8|ktrvKK?ojuHhPUI2F{Rg4U*+L@d3J-Xa~X_*d@kzkj2mxZ4 zt?jq>FLSn*Po*FRMbiS@p)dC7FJi|X8l#JF3g;$nqaEGe0E;Pd-Ke`C&<9qIYt*sI zvKMf22V%k3^MKpFzmCdE#OVPW!ifYZ;R0HKQhrodO9#2R0YZ|*R4?;FCU_BjC;73^ z@{K@t)hjto)`)Fi_yK$U)DY$X^tlfc_ME&ylIC8Qop1}ay+lFT1GOoTt`HzSKfnLL z*ckgmWnh^r%9Ks{b)&QP#mGjKl-B{huF0t&^JmWvw1JK6CWm@w==vPtA4g1ES|+DlbssSKG1h$Yz#9jwKpwYVzR^*Jj+69d;lL z-FaW@DIxidtS)qy7W$Do^k>AcC2izWOCR~;z1g?02~8mPz4vjKs&^~(_U+QdK}PdD zxX$ZwnmL%I+8okCTMJ~g&z z-kRd>VBy+eQU|u=xviwMjH9FO$64ArXRmY}TH6%Y;w=#D{7fsN&cxCbMFBY(uoPeY zw#$Fa@x?l`Cs{oKn@1d5O zJpF|_iHf)MaZ>G{74~DcF~*=+m6}s?^?a4!wSlR=8&{dc-5dh)=8w#RF_i^fshoCP z`W&nN&A!Tq#ghUbLQK`|gMUn5drG;pyq=3}Gy{Z|xGH!N)ApW*vxf6{95DlHJt(@# zY9xhekx|1)vxwQ{L=)H`HV5qjd=WK?j-|Ta3bQ=gmgku0sNmJG&9#Mu_{ra~zk1fu zB0?e8W$qf#9{9b|0zRbvY5C$Dtgb_)2PkyyrdLQel=79{K)MzGm!*>ka&b*o;0Ws^cx3hesWKU!1YHqg791=Qq$RV0I8OTBFL zBaO5gC|GM!s4GsSzGN-jdeHe0|Zp??&5j~L$2cI@C9IW4Fl1c=G974tgV&4 z*ON%NN~+QvZm71bNAbbd-zbieE6GqWWd;$ z%<==Zhqnmjz5gvOj6G$TW`4c;OP>?9xBQ{?R zN)@9NHie-aX>`6#H9@zfq`iyLr*KRb_xxJg4dMHy9vhpSbP~Bq0L12apin}ifVb)B z1D!H9wjUsma7!fLWYC|gh;QsnfclZGPe!BxHFI>(Kf_Ln=ix=$rC_vFt!??x_SZJF z&jQln>#l|rm;G$}jFURBy`h5iOZ282DC2A%SJ_d*6yR~c*XEUY&{+B3h(6x8U-4UoiltGpX|C>I*r-h0XN{5eCHW|Cjy0mWv<}3%9@t2rW~ak!!Ivr~8z=R**Hd&t6@2*i@cRjq%;(*m z{~3{`A^&Hx+lh?Ad<-aC({i-b zww^yh9HGBa=B(}RP0>)Er!p-@%ahI)OSQ{3n^*H4)Uee_L!0!Tz;6GVQue4i#W|ma z!#Xf|J)yGj?2b`D?1`em8cajE#4Hrdeae`0%!&lCq%VIvMG!Fu-iRTmhfk1q5AN^4 z`Q|hah9%@)k*VDj5S4nY2U9}e%VFgAB>Q$-ZZ~dIg-fIfrQRt}%<=f9HHxz^?IY2IB-deC((Kv;WeyyV$I&xRUY=X~@Mp#C zk$bw3&>wC?S);eJ0Ion#1@di+nepuDjkCH%<+cSUuCvA*+72eIUuJ(CZLl zj#-1o=?211onS$~T9(wPVk-5b!+~V`iE|{A4gn>WQeR#GE?xpQVJbD%DM#)g-65dV zcSkyd5;>Y}fH244k{1s->)ct5OaU{Vb(s9+HQ z!-!#)9g8fDXi-K^Iv07WCQqW$697CkJf42hRj?K{wn)vwB+p)z6tC`82x}m{BodYH zm1?)2V{8^lq{}HZ)^)|#b$Oq9a|!}YWixHRXJ$Pm;^xVL1(akGtArE{yF+>VW5omYEr;UQe{t>B=hY!7P}>sd;KYXU$L_vUSj%^)a?* zwC#rs`E6=Gr-a-kQloUrj}5tPINvjPBXgZughQhJt(kE7pJ%lV1zvCbLCBd*d6m&i1A}LS%eaQo&EOlOx2ZwBcqiYJ@)TngCHg z{WMoAx+|gyFWzalxFh(a2WoZVtLZ1J0wEYqvxf4f=uSrI9`#n*q&Z9hdz_ z7I&oWx08wsw5qioJzt$J;qg(FJjW8}U+w85A0BhykJdzWRA-`6H;T(cvO)w$jxCgB z+y3Zz3#@=c&nC)JizL8@X?d<9<=l1^uV=npkqb|Hhn=+oeM4`9f1pKQd~KJkE&#fr z_VE4fJM$N@LZNp_Q_nt#>QWVQk{NH9rC0XYw_h2|tRr;wt)%1GBB*!n>^eI`PV*sS zJHhJQHk;S5ulX0o)w@D&3|5nR{Dz}oG7hbT$M6WaduG%O-;Z-~({#}HuICnPCexsGOx6gPpz~?;>tJrKAOF8zH24!syTmJH3P7nGL>_kW{x{= zy*u-ko1lt!cpFkKam@zU6R!lsZgtmaPtVJghpJ0(bu)bM^J$)a-k;3DlZ-NFd+b93 zY0p*&C52U;P!vsr?E?_G5!SHHrv=Z=AA?rEbR z0|vvR3^`40t6g{ zhtg+TIbzR&$g`q(gGgiJV6`Hm>nb<^UjY2?i9RUD@?mIE@DzQ;7KTk8Ql9Y+wXZbS zph=}G2E8pLszd?~?|sd#x)262sipl+;oN$9Md7OmIw3xxjUa(Ff|{fVT@L+~fOO@< zOo|WQ-@uH+Zx+^2$DH^sti;dWT9N1$z}sUZO{)xD)$x@YqdP5NCAwg`LJmdS5T~Oo z{e^~I|075bLe2)S7tbj3TY4>v)fn_S!fP|i8Cy&KBB0yHddprLKj(@hs24kS>0Bo9 zQal=s2;tym&+^Bn@4}r-68p7762I zP=3`T#dNhljhHAM#ur+R%HS6-dEZ(l_?yqjyowv0d*9pGyI6`%O$}x7RA@>e2eCY> z@}1tuAfCvRKJ3R-tZaR}bBQ;|qKBV%Kj1$FW-gz)%c*BjA-YO4t0cPI#%;u5fIiC# zhx#6<9HMkhDVDP&rIJduHadmc-X&okrXQ_MxhlI;IQ7cx z=I-Q^(9M2c-3wu#)Mly_Zsr=;#PE;#-A8x=7oLYbxol6KE&h7da}BwP-80jCFz z#9_p+%};dI(-8I*&d~rmVm#>P-KH9W%)nI^uRF6yRhh-k`km;j8gL(MR6g867o@$@ zrE`?tK6~dk77>=#pdF_sW-#{CtNoEzM22tB2>SaBPh@6ww1#8tN?3bLRT12$IRpyn z#PIk{jn?eR+~pW$`3U;0=%vN*rvZhx@l|zLW5qPf(D-vYV+SV*qZsG@yx@ZS-|7H4 zT=eR3Qy2+-r3NglH;bB;Z`um?%@~R%%4u-*R3FU zdvpNiOL2OK_Rm>sbq42%07iz#48V^dSM`Jm(xv%JYkDZxTmpL0d@Oy%#ZTk~MCh)N zP+!o8Cyo;y=OAvN!_ShP*<@=f23v7UOS(iSUJi3MXEBbzSf{1{>CcFberS4$MT+Q5 zy1pgwm>JG(=;&Q{;1WcfPe$`zONk6t>3DzhM662PK5RaQw6)~*-UJ&9Ejl{622;nw z7}B>ejyS(u2kr-2;$#Q_BfaG(`))yt4TsTZfLTIM#{i#JWt= z5PBwcf;#LV63MkOzFXXV&)o)6kwcfKWm)tsrZUdGyxO5szXAN7T5hrk#xDAs({ja9 zxRUYy!0)y{+?(*+ktc-dsq?fYUqm)ql?UuSru7{RC`oBDuA(e1_w`vm0^@*YiZB;4 zECfuTAc`MVkQc!LZdacB;sx69y%qx^m+G60eye;MMEhIh zk=8WUh^#Mnp;(O3f~JG5l);63uY9BlYb!zP(&B#sv z(eGy}H?pH~Kc>#jCsQ<2ZRoZTrnk4mDL^rI1J7+t@B++Lsqx=PnH#$^ zOE;jR+3@6IIPxUFwODu)4GiS)Cz8jA_HO4-I){9o9Ga1Oh16I7XLdh+Eq?QEY^Yu~q0NjJp!jXN`FC4OFdCcUV!;jBlG z)%~#d%OuKuxtTyHg!DuJ+4dx+3>eDu9%8#tL~pN*qdzGK(=;>r$w8ReWQKlM)3~qvxgrK*2Jq4=%FMKn$^%32CB)eN16N7K zJl+9|utMKLvhjDieDG(GVGH!+$yQ}jRm8;BOV5Go4nP_4F|g7birV)`G4P#6KkHejCR;#rdc?MSV&54u#1EX1o6KSm@U`-><4^H+N~SX zQPT?hyMiG4*rKLMicd*JD0eiStq$3_^R*>?5s1}$`=$cH%-DYYp_^9IdI|MJ3w9iz zOBZlLD8LvBZAN0y9Jy;ru{a2Oeksv&et|3@vH{s;?N0z3wHqnO)4iuCZxFyG!k-dE zh^)IbzW2q2MiPJ;T&x`KVkB1V_4X)I_;`~>qlAY3oNVXSu1pZ^*4g8&%`A;6> ztwrKsHEt>qc&XH2<;0OgNBFaO2c6>$)1$nk78$)0r~+A&>}6L+dH;v~(<{l^hheEV z7F03*k9!dpg2iFatPRjZdi-cCIDYSP-GH;d&bM@KbPT=+2%dA*NaQZR`H^n?%ULpo zo!4uzPRkHB87_xp^ZQ(A#HF#@ifbpfzOMF!>e3zQFQ`LRBU;WZTF0Hh+s%@S6s@Jn z7>Uj9TY|2`NMrVnRLzi*ZIy?Z(F#t3WBV6Wv*06pc}<`O-EPgLhvy@GCxa>s+Fz!YDx$vwgy!B^+kkg&Zrx~-oZkp| zr(LF|GN%h!BMQryeZYzMHT2uz7*%`uG&3+vT2~6^Ik27Map%Zs2xAzWYLi0R_Q#Bq zep0JjN9DF`7=CMik)8NLz>J9fN`GLKj@UBzNJr3vShoq(W=OtHbjo{mM_A zcatv%=R*W zSmL&%Adr~RN^5RWBw#L}ZjOh^!BMpm#YCqHla`PsQs90zj)KUlONjtE;bokQ4_o@x z+!zWX;|x_KU6-{lp)C2V19q>+pMfW;Z`@mUPmBNJ7nGX~CDEL&tG*p=9muYgg=DK= z4%|;rckDh`9W9+lq?KW^TER-&n#Z9{hfL{431UMOq-;W#laeB9wtj%(Pq3ix_Z;fH z&E&cb;}%s@WnSZyd?)=tuS}hoTh>_`>+hzq7Qw;jlg-jUHByJO5qg2>c3p_Q%fc=z)Bx)ONlQfqiv-rUmjm-KrkZ3Fe(W4sY6#sIOCH=p z6P=LCETXm-T$chnOoauo`BD44T&`C#l;p7kyG4Iu%wFz=9B1$}X{(?_V&N*Fps!^C z@QW53L{*;pEGjXFW7s)(h~u=Du%00Gm^8#l)Q4AzZ#|QM>p%zxhEZnGiP*3%18c`=E%XNbk=Z|lj|c% ze8po*un4D>F(4lXlpF-y_x;zauxZ}8dmu}j05 z&r=Pi+<>Ue8AZ*@Hemu*%6i6*@-z22cNxsfZw-FfSEUpZYXpa4-C7v3IyL%`Ot332 z(?$iuNvb3Jk*%{J*vyVFBcdm`_dYa1e1;1!LdM@B)tqx*ww?e}sZf}O{6p^@jvLe1RO8@fx4=f7@@ zsSwR$j*LFMyp=ms=rXy0Epob4-kis}KOY>qFq1kD_YHG(E9ELP|8weNxn62L$ee46 z=j_Hp+^8n9LQ$WERh=k$CjF%f$r7%!0~0l;#1{y~Ys=n17EtCHH`2WaF{h~j9tEQ+ z$)2v@xAimMF>;5jSp=eAs_&JDvA|H)_a;`X+4?y4ILq`%09*|E6AO5N$WU_}gp;$^ z;Ev>0SRVE3WsiC$LDGf%>%m;We^Fx1x~>W_4Oqh6stIE@fwFuXVBIn3Rj?yQe_Xsn z+KI$2E<3@!Fpd2Dlcm^^@Q?W|437V!H#F%7@Gn9`*NHG{DYro`3ZkVkI*1g1KT{7h zG`Ut1SZ*?9&*n~yZJN{$OPib?t17I-Y_=h#0Y;I^>z3p+4k|r|EIKETiCwVE>9~Ol zxMK#++W)mALS#B3OjoZ24Oi5pN>I}r`r-;q*FNXB^cR7uY4=aN28Df9xP-c<13&6t z169u&85f{Ka(~8FVK!E&wTm262|6}oUVl=l3Vw$+RXKtAN|B)US6)p zkodufr<>(!Jn}+mSU;Rv0Xw(AFwT64UpA_vnqoI zU)-I01u%6i_4lgg#*&iQck)Wu;$>Fwq z8s7`13CVPpn=6Lnp(eEY6=Y)PQ0^C=;&4|Y^EA{2BV5ZhZ~Q=Al?%k-Ur9DMclvNr zy@Rb}4OO!tB;a3*N@X<4yR|x=Jlous_o^Pe%0OIz?RpXq44gUO`?VojfKUf>Tq@8% z>4Ddv%b@y<)B+C<(XK$`8$N?@aGPg%W~y&(z|8FD=H;9oHPzL*4=h3t0g+t|9a*yR zhuqpoe`@(XOAo8V({?-AZm{1_R9`M>bKAGh=G8=rssk#K;N;fK$IGE~zq2YZJM|65 z#aEVL0Ef$N2@VPdCk-lEWRCB2YX?f`p@QLs*EGgUz;Y!8P?fNUK!$ok9hMUW5cM-<|8EmK3dhqmDzjZXy zXI680(Q^Bf`arbAvdHLPJjuspO-st;xnlvUO0Mb;_p#^3VQ4A&~_tQ9Y znVSn8`{nbRv~2h(h#>lYK1`z8xiqiF<^3n9cQ1{HM6g-LBQS-{4u*C)a(7^<#WE$9 zSd+dF#`70U=PTjpBPuPH?nOHhZhH6PhHYwjmnrp>Zo4|6wY;(#&zC1IV}t58WD;hVj1=B1J`HB)%k5;i#$0#}CUX*n6Q zZ;LyVp6RCudw(3Y+dj`!O5SvP49cs1HLxoL^2@|mHn;9TNo^&{NsdLKiz^MomLLOh z0-y%gtlf3CH|-b^!(I>`eM^Z&Bn@YVtk*4^+`wI?_SEXP^WEJEBPVyTJbhVv3fz)K zKzScy5k!toGcCg}YJUtVpuH|Zi*_|*y>`iIE=FIN*xj8owUDHyj*DE@A#W zqi%kKh|SKfdAj2I7Uil#*zw`RI3R`&<-xmns51qv%$M9@N~s(pv20G_{8E<@K9-pY zsW0wmTxfwK7Jz-_E_K%32_22005eEA-BROwjY(S{BTmFJ-Gv4X7h-WCA6)oW z{0ZmPXA1Kawg)|B;!rUFb3ly09wWceAMKF+nQ+q<+_(X(#(2onmE=|S>qgL06Hb9# z^~K-)_6_wr?8>i|H3_-$#VkhV0_M@*E;U;v&MrgYiWL*;*oz2}+@LCqdg{ghAsO;e zF7KpsA_*)Lr0lPz)pL`zNEWz^JFn}&O80I7^`0ocQ485bW- zRUrsy%oMw^yiYkvL>WQkdv~9}#KmaWdp5<5qB|M_^DGsbPp}-z{g>Mowe>p@%Ql=EbGt!yh+EH*8{amDDKTG zSm!^XU}SOCoAwEA9?aGmX=t&JApAar!|-ODTg44Q1n!9L>2P7d(53=Vt#wgYgm|ILUy~6cQ)~ zP5Y)R4#Y*NiqxVdBIU+dD;vWC{1e;3>GAgbYW8RXxdC{2bqB2RzCgMri z25RkBl7E=|k2J<8|GeokTmS67BwBwyr(JO~GQ4>G%`7LfvWEl)D960hM1D#sD7}&ZDTISSrJ>fyFG>UZ(7V_*_hr@%V{UUr@=wyx`I3c z0cy1?G>CegYDo?W*eR~eKA}3cbHozK2~mB_;o^`6QRwIo^$M)!Iai}krm4-qc_|vU z51yLYfG$ePhP$pP-!#-ZOK*#wCU!7N2u>`dmPGmd9@53q^sdn=rnH1urC6QfjH-Bdu^AHsk*7cuiCmXs zZEvLa62QW}#`+|oAcNNs{h^DCkJ2WH-Gg+bmL8YJoJO%j+~=Ii(L zomT|U>n1OCLHBJ+{!KueR@>jLX!AAO=Akukk`Hs@9XO#dTqXzhX5SB6D5XI`S>)ZR zZ2EmCF`Xe&wuCnE@uUh7UvO+tqQ!umh@0g@v#+?JPI%`ewcVk(E{-(F6S09EtTzx- z;&8|7KoRTo%xaq3>pquxvG71mQWkliGmZGDnl}fH9N4p{3i3z??nRbeUUi1$sREtcHn9 zU14YRR{gzjCjp=V6r1EN2(@ZY_2FLv@KIwSP!XV7a!eqa*spf;KDOS z7zgMLqk1d;!)(yur-#8t%ZCTMbYxw>uK|<#5_Md1?W@f?g&Yqw&+a3v1&w_XCP5_M zdIsKky{X~zPUN_mg_E7Ud=we1# zXar*!8_y=B3iu-UNJEmPSnwh{Zvkdm8;7VKH#Otba|(8Hybg1q43GC(M>h4iBqFaF zQh(p=@nCyQ&a?>VVnKDTVw^_!70RYP+JwtTlG)eoxx?Fyc@iwf7MY`u=m|9yEuYXq z^me~gt>6Oq+H{(v>qfBJ5?KcUPs+*~Yks!8_3IYT{PLHH(W42Y-BgxD_;*?tHsZUu}>F*xtXb%fs3JK+OiYXP| zXQJFvII2)Mbg;mqvFVADt2x=pG+aqAcHs2Wn6O5L_rAexpeN@`IH;||j|RZoF7KrQ zdG-u9qo57CT+%}bVkemcbQ)!}r-K1{1)#G4g8mX*FA?dPQF~Jpq)Pgda zk+1G3XF8H8$m4OSw^T)Tw=}W4T1<-d5DYUKy|xMFA#lbhKx;N}uv&+)#OsaO^`_h! zexj$;XN|UuejIJKIk@rV7{=Fq>@Jge3kcc?>n_={PQ0#i&7 zmEFSS@r1K$M0E`aeVI#anZfCCH(l-dz2MG(sIl3&A_l{NytyKaTjLDuJeVp9X zij?wpz*m#EAq5*Gg*lv1P5%*y34hkCj}eb|$uK`f==9H0$9L)1-qX3hoXJ|{B=!rU z8qTg19K@%^d&&TnMh`?B3t0V;>4qdPNV_eu)We2*3y@`pz-i9*K{HVGw z8>)a*l#17if{Y_~ad}7`NlbV!UwQAeMQK2hIY|S z>X(udUnx=Z{ZF=`09pACpp-w{qYP#s&%V&NptBY{1ZLru$G4T4oXA;;%tF`eWF1W9 ztou4LR!L>VY%V~(s0sMYUttW%&3bk~bQw`nABVk>t~$d`S{n6qN*yDe5H2W1L3-3P z%R_Fz9{kyOzG7U=0a2juq1D94B3^TOjifVIY`6dfmblUD-%(E#62n7D68iXH{I)TxZ z@2*qP-y?4h-q69yXM<&k#mLoC#9C}%YC0tB$6w6atLnGXe$FFO#qkhqT}-2TO>uqP z+6l#H0db3p4&LdNw(v4;&U&pw1YL z8aXG)D-l7cV+8wX=$ap$Q{;N=nyaDbl!d)YfQu!_a$EPY#E)QI{Hz59oZ3Q%Dh#hq zaymqy9K+w5uK85@BshC_t=2X@e5MD&;iTddf_n4G z@tkH#{_avFMHa{%{?pj-P5Ljc!{N9OFAdgE(~g9(oJXPKy;E^W%$;KoN7Pp$^8jH%z5ak zwD5?4coqqIn>%PBOXIgWt>PVPn*T~$Ayw5j9}bJbUJe+TQ)?R{Z*S-|Ix*}XeVRcw zWO+-U9M-M5O=y2_hHNT3WXj(I!wEIbvKS1*Eau9X?aS$0P_8nB*tnsZL%^B_H$Ura z37Pd2Q4BenWmsdK8N|)hAH6$Q!d9k+#xjO&Q4st`BC+P)GlCGqP3{SL&F?KJ`Ex&G z&`K0xVU1lL^PxWtah$=9vJS|vZ}1uehfR$pvgR&B{(xbc00V?9qHA~EO}iz%#Uzjj zBQ(ShJ1nxx(slz*@Hl4KG~9X6ZU+4^=QIfJ@JvX-i-mUH zFgXgC1P?JRNhW}9PcZByt$2v!(lf9V4r9 zdyKt$^8i~P6O;)Ed;)^F7sM6R{=rp9T|i|)rx4Um8R~P&vN@RT=a@jFBPW?%Dyju1thC56ZdFHGzpg`O;Dp_?h3SSZN~Tt=C&NS@k(3s?A{5qRR@399U* zu9jVgY&Wix%mgrT*jD8!+6GTfxuJ@x3i9Pdh8Qk(rcJD}S!YP%5tP&_%0@2}DeLhs zjkNYFP4cNIF}yFp{*pHh747cWSI#y1_2aA5TSj9`(fOE6qytbkJ;c|fLj*xuqrszH z<7VCi==XDwF4K#T)2q6VPY;n!H^zOM6l+`rT2w<;t>%tGlDX4(^R5;P)cGYHju`CC3ttQ$Q8@Fz#z2~_Zl#xoHy6&gdfPp0a{R939_C5PlSCS7W;^zP?9CaJP9F-E z1Ivvd7S3cWWX+9;L6Xvx6Yf)cfR@}agyMUyZ?Q_&Ui5>giEr5%{E$LT_E7=BtAX|7 z)WoufZ=)aMhC^e^+Cfz`oE%AQO;f))4bP(N)}O_x^Rl@%v1Vy(Ie}LpZTo}HD#0nJ zluW7pNwFR^rZYn~6X!Vo!rAn9P0KB%FRA5O+*u#yzs?zPjs5Sf)#(q+FA*$>TT4JU z^5$H>QDCT)|u*^H?2vmy+r=Aoa93yF@0_2n*vT#4Q4%K z#+r6{l<(6`rrse}Ejay87!&u&hf6yXbiW)|M(=L`C*>YF@p1p(_St;kTRcMRyP2z{ zrelX86CZs<-cj;$UzWw!m355kvsNN?9R&TBl97x1;&|q77E3VF58u@pCYO>(|5h}G zsYt%rI*QWvU(*mQ^VDMi?)BNyoDyna7VN5)VvZ@D9FfSzh0gO7t`BLJN?;tI**X-t zY30+rPWS)i%68F9OjY!)(3G_}pI21(sr&Y@~CDYiqL_*a|IfSb{ z)LLEe^(Je%ILRA8USlE}qM_XK_w8ALUGl!zgtY$XEyLBRx+0co!o@O|~o8A21_px)(Gkl2Ps?{r4v{ov9 z;F%K-(1)XdThhj%5S_RaZ9zrx1w3NZx)ROLFIIV6rk6Fc0?gBZL1!T`qWqMWsg(mj zH~y)zbWG+In37A|4f)$9z-zoX%#rBQP}XSljLkAZ_c6zx%p+-AGD}c53;u6-tr_}1QO5GE%yO}N-lnGWsSitphH(RJzmfnZkV<%5BPy* z+7>AIaL~;Ocn=Wz^A9ItCYwH@~vX=dk_4E48-UmjoGY zCBq{c(OyYRY|ozM&A1g1nz{di2Kq;YfsO$IZ1m=8MLrS&PxPdMM&@c7m8+eMmw+_b ztMzxG`yP#012lX{xyB0{;eEPwYO#{S4P+pP)dNS+6p8omDgdV6@r5TCVdVZOJ1WUR zRXI`(;|P94yd826=;@BNz@lJ)^RRejG=RxU^~4u98j;d-N;AINJk~O_kKe}kf&fzE zunc1FH(l=!N6Nj=;(s2B@i;*qbS0O;KlQcSp>HXj5rM9JXgC#l5y6hsd}|!4#|l@( z&@==Z6cH~txGIv(d&B!CsSMEw7ukB(CS7g+dc0^0W*BC7)XLjhm%9Nc*!cX-qZ^e5 zm6pset`rth{mxA$wbdOw$kX9%f})-Rr2z-#2V^MyvxQmqqZ}%T&s^Zl-AgepNh3Q= zRsc-4VBz_uLe=n$W5r@AXyzb_GArnm#Cpw`R}hp)_Pn~9Z`iO@0_8FDFnCLGfu~KV zE2A%^=vr_ZXzj|096`~}9rFWEY7LP$rt{Ql;X-VhordIXrV$jBcLmY#qH5+nL@mm4 z_7re%{958)NMiE~p12~4Ep!(=N{wF=fZ&5Ht0~~!zvIBV`1udmDt;YHjp7z+Bg=%! zn1fo-f?|4O%o_6knVcTq(U6T3BYH7uhG{+H(<*6h9PLST`V1(mv<{)iH+=aj8nFP13W_ZddDt1rD*&fxEJ`4H|0+460opL!&f5ynokH zoArYcfk8#gW@0Okv@I(wLn>#uz{;30LCV)us6UfunM^4F)_4eGcQez7OnKglaR~IE zmM7&ThX|NeSFfB=5t%(Zk}95fXj}XOIb{>T^Wawh{QQL?+~)yQz{?V6 z!uoebg>8qobK=t;XiS1=eh>P$Ici~H-4DfBTTQX+VUUJ6&7y#EF7Z(?c4?5axX?~VRU6gWn*t-WiL!+ZfA68ATl*M zH#sj%Wo~D5XfYr*GC46hK0b4Fa%Ev{4GM0@FVUnd6#VV_x(BUKmJTh%6Hsez(TEi` zaLE)LZs5{sgqc+zcY4A;dL9Ztet`O^qUSB8j|wb|Cfk!4nUG=`ulTn*+STxqMzGQH z*%Dyb(1@O2RhT6P%lJB?-+tSBg7GwfEKjipK=8aarmlSY?d zM(dLY@FPsV`vC@xT5nlYI$lmWiA%p$P$^JsZL_wK)dgNJ%@{?VorADn#L2t-d58$4 zjdeBuOBWz}j4KiaO^QtnyUpnv};_xcpz^UYSD+U zey0GmY@+dbtpAS*i^e3Z(6$o3dWd`GdZh0UDaZa-zgQN*S<;^)V9pm!uZ1~BJsHke z%*}E0jg01MgJMTywS#N{Sj6h{F7KM*I^ z`h=*a`eYWLV<0E*-2IVd0T`S~)$Nf%F@95g4~Y8_2n=%Y&K9E^gp_Y#LOR)B*FP?@ z%koYd_GV4@>V0sb1&Id574RhsHD{ZD21l4XN9${OntG_=+f;u)2}yRhsR8!GzW#1- zvM-Q(aU@K`_5F z4(vhMlI6y+;lR#O0>SYnw1R65- zEf!b4SnP!+}68gu29RBgL9R1t?AR&oZ9Psqyfi9gTCN9$d`{lhPQ zFHgvJSH-Rl3AM<2Gr3J&RhHeaq@D*ypyS=k8*)+|*T?Q459daN^H`mI

Rn6`l46&bP_^ddtbBJ;&unCladhMx@JPxZybYV(bIbtQopS`5 z>#EqyV?oMOz1Pm2CNVL}vSnBV^GcNI8t-}W{%)_R-8s5SFLKKiw*?O%GG|;W>`jQv z;YIK}W$ymT(9m*g^!5mY#}&OWO_j*!{Z(+Zk1ucwT?vL`pm{Yaz5a5PjxQ&kAwefMU+D-`lYD=OF2) zGt=TXR`VDX{(g+$rRopdUeVVJV$>1y?!af3;xtbV{Ra)Qo^T5j15O>?Y}>5@l`=$(S}X+j!sZu(2tu(%XqJo-3+$ zYwUqenB6uZ!13s!RwdmeNdD-CnPuWkj*;Ru2G#4Dgn{!O)`%Ka8YD*2oP@FCe=YVy z7H^ooazNtUixF{Frf3-6Bh-5)1;UlnokA}NXR;Xkq?wLl1x^d1|3wQ$HStOFgY6Z& zMW=<{&Yn16nW%vi^Q(iHp(fMGbWDg1#P6SKs%9IA2Ym&!L81MDWuQzg{rsJa_9GZ6 zLji0gZZ`ytOIAtB6AoNcDiH5ue@i3hqz4B21S>EW+G3No)X9+dTX-0;+MDb! zD>9SBpy618)wkR!_=cUVv*6&g9(4#X|Iy2V0F95C?ye4KV(NhW-|~V_M+ZY$IqOT# zGN(vTYN7bZ$=>)-5AhH3x$9&Q=FK+*e{(~4it5^K$XIzghJ9Zz)+MISZ_4Xi;BxT+ zjk^DLt_%yc0UTuC37UT=QmVct=no;F85(oBr@RP@F2Z+zXJRjQp{N+Qswo%THVvoz zATMu8QGh3{*QYzG5e()cCVO5&s4~dnv~`X8aHwRU(<|7Czk(|;?qFYGQoC(9g@x$~ zj%m~IeS>PAHmOLSAyxZ8-@mbll7xgfAoxKAHCos#S(9#+3DFs~GEG`e<6X5||9B5X z>ua9OEtS|&mRvPVH@49oxUInW)2;@Tx8g{`!7c881#(=1>!uq5qAVc z-G95T8ld4b623%y<~G#3?(s_IEvNEoqOQ`|QXJqKkWzvR{g~lV2&W~cCKHy!JUYja z3`vdMz4f@(^WY9Gyd&+ixzFW&G!Q^sXB6)iz9t;$n&oD#-z0)P1WbM;-N%#$U zq_&{Z9=n$YmNK1v;t~$Lad=IvH_IQtvv{ZV*f^Xh=k0vtE<-i;T8r6Yv3ap=JC}ja z9owN$nx*oKHvybxI|w;r`5vg0d^CfPQzzi{s&layt`8>{z7%b5^4mIZC^Y{uOgc%bu=eJ|6Av@f4muVS{Y;1%L z0*M$5R}%xDQVstkQdpI2LKW6!FsWUtkLYO-UUWx95ZsNO$_uz0%vZm zJZhNr8br+uwNYp0{2o$?O3jNPZLzx#0VnQw);u^hwiI~Rtb*7laz%qloPc-$oZA|D z?#Ub7P^eSpjJp)1-uo(U$dl9ceAqN%SitofN{q=&W&-cF%`;!u;Hh||XZA9loz0(F zg1ht5fV&(WDT=S-F;FRQUs$@@&v$NO%}qfVoQ{p;d9JF7c{qH$RS^wd_G3!L>_tmP$BJ2E{Hnlwl-1<&_k;VYJ$8VWa$@36*dp73Kf2@`{wpZO zv5opJz2M&aH~jc&zO{}(!ILlmX$|JDLjPq`Gs5GF>2SqO11ce6=f)stFr(G9+5)z% zKDX4RBAM0^N}Z%tbWNaVu1lM3`nLy(sj|SG6sEo_?g>3aJ;z=T&Cg%jRq8J7! zfx;Z`k^9XM9&iH@APJX2RO%eoE_YRw%2a=-VT7SCS`_~2{B%~Le_WLMAfw>qE zX#`pBF$&B#)sKxjqwfSDoz#!Q>K4CfLuQ3d9kAZ*M!M*(nyvYd+~Js{;gpNMIinoTf1 zYC~Sv#K>Gw9=%H=vNF*kJkWnDQ?0%QHFy6wNf39Vmsk?21vyOEGj2j?<-4AjzUEYG4>hKKtawAGFGcLU4(T)AUWB}0I%tjO)pP0 z;h#i6DQUq2VHr2pxS&FM9M4Q(RX6e@4LADkPz7ES^>Cxg%wywv6NM74GO8r4=wxCb zi?wYn!mZR{s$?z+64qjwTn}YPjDKjAA_IauADm;Qn7U`w9nnc$oxFk zgVX8M6xVb~!3LGIYNYou#*7(Q64+*hIIA9cLh>gw(fH~o)8NyXDXAJ2Dkn)RRyCQ& zKbUM)I2{PoH@wSfjF2Lu$j1StgXyznWa5S{8M2@& zNiU}aSQ5yrduFC_!JrcCLN5 zVD=f=mogRi=7{Q}KlQZ8%KvFlB3B8dA+eR}FyQ=9T}iU?ja!aEZ4swVTy(?NC)=4o zpkj#EzZ*WC{JDPDBkb;yeejESid3Fs5f8}>Icm^|1}N*VknoZ-_vy>rbuM{b7!4x_ zyR_+&l&(Dkfk5G4V)#gbLGYMgj{?+dZK9wtio?TEl%+Ek8w>O;4!3x^7Hthkcrzr! zaEE5en&Bq|JVin3LBo9ovo*Gn2G%kLD1virg3P zgaF3WUwGntUy42>KJHE@CXo*aC+s!tA54`ZhB>NdC83Epg9mf=%+eWM3ioDGX$y#4 zMHhMiEqy!9Z^H)#4p?sq{6~XCT*&Hc-1ehd9wYyVLYqun4tj~y;x?k#6{+<1AMW%% zo>@|2=Z{GV?MlOuDvh#ikKc4D@<(5)~6=M<8fAJm_al^2;HjS@mVQ13qopXS43( z_lK_&&f&UGs)p^1?&}`1OwtNml5AX+w1=16iUhXlx}hfCBeIU#<^_U~oj?kRzG%Zt zIdkoKrfb; zWiWu`6b*PM`Wgoc9{4A5rU&dRT_d5_y)I&DLdqro!`|4J3IVizVP2A&*iI{Gi8>6D z0rwwo%iEC3jcrJ`N6(}GOG_zKLpmYK%4ZNRc9O&ND5Hsi;{RWn4v}J$W2I%I`WJ*P zP6~1A@l#r90*`!cm^ypi+_Vrx@QiQ@<_7k<9ZTX_rck3k-r4sQC+KxaO>~?#k3mo` zzz$yBG}>_v-liRUdwJ(8VxG@QRT0b?nyE-UHGN6Wsi#6(*h?ZH6&R>NV@hDr?^KjG zs*Pqq5-U?{+B_dXrWL2L<;+;Z>3bbqdF|I-0i=rVU4cbD7;nK4TjTbg=7$4IT6?$b zN9!sC!dGv%g$Trna~_nrGibQ>GpLW)L!=F9El>VwzOcLLJTdF;abGtTNEkRHMqdy{Er+aW?*bXIVh<)DFsqWy+0ZCQQ zxmmS37g4pmceubps$~onu7sL^=R!huhg<$NM&N6mAeq}yf8Yn#$veUOb6LINbD~;n zuQpu!-i;8ucPfMJhn~Hd&FfYGc}|Fz5ONVkY^p6*8pUMJp@b;PC8Hr(>em3Mu}Z=2 zy;kgtgfv?}kql4M`$zK#1#NlVWuAB@=!&2$cQsf^`Ja<;sRS+sqV>JB)>_CL4lf7` z5_rA&+VkBvA!O#;{$j(bxwazT*gKH~@B<(_Nq}785}+^gkEjOL#Nf<(wG>j8W#$WW zT35M3pt{B}`zqrO({)F0`6X`FL`6`QJ!EWyoPm9+3`BAD3MHYyCU<};EV?%mU_}Ya zO11boBuxdl6Q&YiC69n&41|haj8B0x-jfKPn2*@aAKw41JBy5ZH%s z(4!`6bZZ}bLn&@Er|`a*$VWtTvdO4XBu->JE$|Z_?$CT^jB_EwDY|;3iy8iOLiR5h z-|8LnJuzw%)*LtiR!q$(7)s#S$PV#hp&GSqnQ)AuG7i5@ra-Y(aC#p z|$gZIz%VW(Et~2dY9=RbX4hW4P8OGPwK!)wpWC>shU?) z#I<`+qT{n#UL9}|q`iGz5KvO8leEN)DZ%0Ug9D?QZszfgnclEyvoofM4Qqv^e$`qJ zJ!aU&l8vo-C_ld;1;*D^xSC3N%A;-0AI%@VC};cNKli649(9qEPoWt*nV)7goD)({ zi8Z4zqfKlm&wyz9EvFTkrfD~j8D^L+{!$M&LnrZNVXjRD)eo448zK~axRd>0C`z` zxh_?UM3VijK2Wo?7&TiLhv&tA`x4{G5h!J(Ezx$W(W!ZBoBoL!aJ#}fA=ND{IIHb( zt$nAlyp)yHr?uFC66_cXYLI5eX zD!(*XTSVO(ye4L3GEE&Nso@16r*X7G`4fgz&TsX^QZ67 z!lvlI8JW?U37Wr9e^<-b_!2l);ZN*9ki< zj1uR$<7TtU>7?fRF*JwTjti6sOo#s7iJvFAi+IlPzjHlfha!3(;d<)Y3=jQHSnd znnKXgil!5N^Rsy{x?jNu1jZb`RlZw}2iK?`qVu`nCMH*&2w&8Ild`d?hP=kF7v##y$m z;MWL?#D9Z#nBdF5ID-B&biVzBMCZ7Njpj`+xWk z5^<&!NlfUt?6(4aw{k0oqR3RE5U#v%=9^p3++4^)u1V99=i(u28b(elc;u6L*W=ep zj$t0m0A!8J{JVG$){I{&q)b!Xa{+ z^S*R2i}lQ%w;jSOH9H_)irHK+6oiRjhF$oX)5gH1{A~yKN*n+O8WAV0N(a=XeX2hE zQN}ic@c2mqI)53Kv2wU&{S8{5zgbHb?6b1&CuB&zP8@pKMip3xt5%7TYY}UeYA=y5 zT{?w_RpzKbsL5%6O67_8YmXbJK|dg4q(txm_zt%YOLusUkIxDfV*#!f+**1SZ%sH9R@sUv6d2*0)9Egg;YG<-0|E$_Td~>F!0XP!*2d$ zvI|OrZZJ&uTO6fBBSg+O8egYIdiL?4)|=!qxa4tgB&;6nT*F^Yd9aHr_w};p*6pWco4J&)lj9b9k6HeB$XT?_{JI$`$sedz-3mrnr}v4dFMR_Lu#B6HY5Qir#cgT9lJUNtsT zL%htdmZw7|^?Xo8EQ5Yh3vw@BbE=k}D}s0Z65g}#FFYBHj^7Xr1AaR90DhmFb%x!O z22@^4EYnI;*41ZA?12?nd*FXZjheL1wyE2YWw()xqbW5SLB9OqbSd(+4Iudc@WYx71U#wM7&6>A&S#lPLKlQz! zbLLV}HWfS%cffCk^Hnnv7o0y6-6nELK(zl^mi|hUkCM<~`!6si;RnP-_(C!0+_R72 zb8`CCL&>*C%{&~+u=IyQZ>IK+^5f+Bl@jhVc&zBAnyXdHckRoURn>d<6fJ!jY35Ug zvefp8x%heNxV1Q=(kDPj-O^ZwYl{WK!op7p97~;XIHU3|lO&YSdKxAT&C}?NyD)D0 zajx8_BZ=bZZQm~F7(>ioXk6f+b{M?}I>&SmMeo!4XtrEB)X%}xBpVo=J;iuNK!W@)D*y?abTfV0<4iY5u`M9X+--n%C ziAGr{V~Yzr(5pvP`~!6Piuu40IL11wNyr*sSY8Mox=Qz9FTn;w{DegI4X~`d76e>suJxYpnr?J zni4JD^osOy3q!Rw7qmO2?sY2FH&e?bI)_?OH$q7f$sFATG=Arwy{x#wtIp^Q|2BZ5 zNa4X}gv0aL^eS3|WS@%y%?G2+4e&U4MIgL&knDnug4w&k28}y{Ksa3Ub8N(V^g~N*JVms{6vo90p|Rv z7u>i(_PMBW&8%|0WT7zg%ay&m>(-J(UU7?+NgDb;_Z!E3Q{z%hQ~2cxaFDld06Nzv zrAu741?V`i(~!Sj+mv6S>eA9!j+0IRd=3rMUjwusFqYG>D5}N;m6$XKr(=QRY)Ar3 zd;Z52Nf41#w7bXbRAFR(y5J=}2tl4!&(u+xP z{9t*Bo3&d+j`OZUDQ#Wt|A;}J9~85#E}JvuVt+hm;c}`}{ARSWn@J2R%h`j4HrV7+ zFy6F#&lOPc!6sQhU~T#i#< ztC}6FFAb!0jJ=?J9)gU(yM421HNODmV=ZCH)WkiCy(^8n z(oQNXoqrRA*;do06yq4;!}@o)5yuEYKlqbfqD9u7Dqs@PxPHzYzo%x{fZmgInih&N z>_hmQO1*5wO2OGZbebSY^P$?r^G$FG4y^UpRK(dWmw}-^?Z|Rhfl||&l;+ijs8;zw zqK3iM-|ADGdnKyp6&;8)xY~JAt>+x+APr%i38#0mvDlS~TD$Qa#0EYuc_lx*LR>r7 z%cPuBd}nbF=va7wD8{*DGiO#tvp4cwJ&XKXoO8*a82IUXWB$+dZqE-cJvNEJV!4VG*tz z9nvCwa)%K(LJ@ZxlIFxLM{389yp3L&jlCcpc?r0J(N9bx@;BeNrDIv!#jJ{Id@970 z40l#uPI^wdv}10f8v}%KMUCWNAUJc5o8pq$9W(M#MF_^un?KRfJ_w3#76J+P)%`Hg zR)iM!Bc05dxZ-^Yu4yvN0qjUF+pRjU|=!#9?9~PRe-@LuzesS+wy@%&eEZ} zTbD>KlIt*Reu>+WxvT)9(>p6F198a?q{t}F~;Dj&;chIGZ9BU$DQi+!l-5oRN<^OxY7~$#qd~N=2|e@E0ICKvRytd z<@s~4s4=jcHXjKE`FVlEphA_+YI{$6<)L!ekik}IJU0alB2^N=Lrz9cy=|>Qg!}Wx zX?g~&NMv;ew-ukzL9fVxLUXAsu~m77N)L~d+q%H}d&ou!-sAr{7y2ApmZwA`gi;7W zRj*XGXh6dNp18a0eYCTM9UvCO#gg)oj8yMuPE#=eDrq(=*8{I6KyOO_K%wW**mWMO zXpm(cBKcW^!9j@DAqASnwd>#4JMOe}RB^4QMhngn)^I zp8E%@-2Fn|hb10YvfH$xN@=o_{Uy5ifRjatL6^{1m%CE~_>O*;G zL6o4NSNuNuFQ5(-1U63Lra9oBpVG)5!cNg~DP%|3L8V3^_a+QRr%5kb@gVTm?`QrB z&&&4OWia4g6z-p7%5U>j>29eQt36aZ>%w|)Qz}V1havt;y z5$@dnA%V=zniuRqnxvRrn}f7=+ZRgS?Nj#)F&yJI zJ++BompW+VUyGv(r_+ku$5jhN%&jGMB`#^l~rEk9Is>7K8Cg|5x2zVs2Q@l|XI?FK(5 zjn7x++`@1afb-=#>XgwZ>r1X@4ZHw&Hb{d>eKs+H0lf zn!`v2PTGn=u7nL=t1yWNDB`yN-Q#t!)Vn}cc^#ux8k`dwl+2`k1ATAoQCV9EmRfeX zauN|6?OTs~N7wRs$3Kk|GZLM|g9%EqqKChB$Ccnx!GA_Krq_>e=yY&viy~n5RE>C@ z8+Knl^li?#-$&GN4ApQ{2|dCnp`4dX%rz6#X*_&?K7LUO6FD5ZIpA<#9^-zcg)I#% zjScc>Z9CnCXoqSi|5x$Hb%46o2 z=B=X%SLsJ|X5^{;5*Oy}OXp*)@UibT5?)Ip+w_<9q8nbL{=k*o1$YrW!%MF;Dv+@Z z07{b)Ei#{5d6|eQe9Jqzu*%tDFiRNv6uRGpS;5-od3<8%h#j$uefG-fTaK_DC#l$Z z>rg6$K`qX};3xvf#r7Pvdv{P5Dh*OV&Bd?hdpK8xnEkLP)N$7>x0fC5t%4+CXERPa z@DB=#<7^Fvsdw~NA+WVd;txMAVnalButK?DeQ}}>%wd-)c~3yxc3E*I)%g8A` zHT_M7-FT?MoWO_t-?7V`p7Iiu^R3~4xaadcCWaBjEu_~_aVf2#T~WhAI8?aARx+#} z7yJb)Ntu_Pu@t)l1WwEEdi@ktdVp(+&RooZn24Q~YAvHyl&*4z{(~%*hlY&yw;1hP zh^cEdnpS-F@sy91$K1U$c6`Z@ZW|9)z`VJQ9H&4x3A#kY@I71R+-x49u zEugN*!*y7Vt2DJzq&DDEbO@bPp)DtSz-H_w}0T1RV3(QPI+c493?%8L+=1K|I%y6z#V zMkya%cp{L&lJ%Fp92p1tElEo{$1ODHys-BWueN|XiQ*tTukPCB-2 z+qP{dUu@g9I<{@I<2iS8GZ*tG>Zz)|*LwXkn~IPNnuC5TitRkvV5=58Y_>p(f}NGn zO#E-Y>isBl{-2g|5&_UALB)zF?0Nsi`OgD zjhXB{-qVam^YDD&x}CKUh_X1DX|aGLbXe;444HeU6R>Q2dR+l69n#e>7iB7aC{AZM z@BJCLw-`8(C0>xI_eP+-HQ{S(tAzBkFXSb5&VBE0^^%~1me5Ohqkd1?p@`tkS;;R3MdqKW9dQOeR?;zl(Ayud?Qy06$l6@)0-Z9{2iM3mH0=n7f zW~obKID71$FPtdT>Q1JFZ2Gb)&no_w>Z*n0h{W)d#5PL5Eewmvtu~TEwV%;|hX1u! zTEVJDLVd9%xgxb?QI)wr`MmlXI~c)E*NJcH{N9XrTL+9Oe!+V`C#4z48}0zT`|)g} zbi6?&9YW25W2cbBK!0{z`tveCCZroLv(=e5vUzc?u-nX&raz~WOd&|#_ zynUQ9ZXHdzCaqUE<$N%QS8K9_QDS}^Ix%EUBgKirO3w_Z2Sv0~@%TKbrp$k97{jfZ zE;BLtg07nrZ-^S|TSgzbC(4>Hy-CEJAed6|(;t6X@S+{BVge#No+^@B;bkQCe+X$^ zZKVlnowTVs4{JM?TD1P+KzseLAKH<->-+W&Z%W9Sir|WLB;C5|x76!K4nDyC3TS?j zo5n(+)(gF?_D_7OV6Yr)i5A66AgwQIYi2XbuDrHV}m64pupi9o)2tEO3*Jv zC#f3Dm#WmLn3WOuZ`9{6HffnU@$GcHF^*tl$o0yXJ=Ckj8D?z*?+-!nzNrv-B4-wxMMTLIt|lrO_EOZ`_N^*xGDJpyogwJqT5+B#3gJmUAsQDwUw+Gy9NcjuKg$_ zQo*C(belbz(V1e!E9cRhL8WqKNS7}8=i^-3jd+!8q9By0_|^!qtr>TmjTnT?Psjns z;$3Wz^7!kw&ZF@XQ=WfJiX%j?R&84!y8N`Q#MEIJn~={~yQkPNPBMXe)I^a8B5>X* zrzp17L|~GY!!V&-=C|mPE(V3f$xGe`b7T|RR;-2dOqYH{s2fjYJCQ*k?E{VNV6%(s zU*(Ewz*K@hMw0t%%eVp@ce&NrfM0)5DnKzZSrY5}Nz-rKZ>c!Ew~=7c`4%a==f&Gx zl{RIM)TfM#hNm~1H*Zv`6ABG>Z6V;6-i33i|DjH@ah$|v?a$Sh$;>HjxrMX zA_G2C&NlPyM6F8pzZ{xuvRINEW!KK-v*GhVf71mCC3afyCpg^uw+%>h!RRyU^;X!y z3{J1=dTKu8mxAKTXEf^}QsZ9%v;yUcoMMpv7SE`ph`Uu#7tUl**2rU!$@!>b($rDG z-qKA`a`GdL_o%*yQQ#58Ly*_7*mKo|w9>|o3hY9jT87|!9P+ZmOrw`Y31+&7wP$3! zj3W#**{|h7!CLwY`ac3BKjeirt}>7h zFw`hhXw`X%H_P-c-GU+_vuu-Kjh|;&hCh7JZOO#)B`Z zW&1IUt8t<0ypq#td6I~q^N<_^abM))nK%Ev_-%I;@MxuWBnCM^@cDo0hE-IbJd>#E zW!otDrt9VS0gq(MF}%OiG)~&nhTEQ(i%30MM3gJdrJBM{_D&a)yuZ;Dsz2T#2pc2+ zLA^|}@X$mw9`4@YWaub?&>?jVby>f0sLJRHE<)}m;@&*H8cjqU5>54Bf|wYaCHF}Z z*S88nv`0c#t;0P_y8ou2KO%WHac4)TkQgc^_2DNWl)-RpHw0qPvUni=gu5T(AiU&{ znL5zn+OQDIgspoQ8)nbo$39wb_~XM=Fz1KN6Yr2ME?1^<5k>I13y@Oyz@P2 zYQ$Ofl`5mx#f;@E58|8oAm~uSbk|p@>l@?M4H2b@sHSo;&!dq5$D03|LT{rL5R;UC*P^at63ZQb*Gm}TqwVS(SUwhCC-4z`J-j0ywzyB(ygMSg zHsD&0Gb#Rog@V!Vze}8^9{ogO^J{CAl!|2pnSD9e2pgb>Xx<@~3*Y@^s=~?*pK+MS zyRno9Gl%_o{zEzMCa zd-Y>?73egLekCsY17O?4AZ!@>B83lvz9$GpEV8e$&2ECR{aH>Sn|0noGOy{7$d<|Z z8BjY?W5tloVZUS&7wu!Zd6eSB>YAWM)X*C0uV#T{bou|O;Eoci!fZv;EycX4LRc0n=lyi1a(6Tm7-tH&?r}o3$Dg1{2S@6djR>N%KE%fJ_NW2j(HN%5uQOm%5FdBxlb&2LKjVBLSFxKunJaAdX@&vNqzS;CSdCN^VhCZZX0+M0=XnbAttk3 zfEMk)JOcWdsJoVzttci{ZkxnBeiZ(t3mBPc1UI*ZYbPwKkG@?n4Ok9HNFbTJ|61`R zVV(j495iTas1TvY8L$=5V_-C7DcPY;AIz}P=o`8$mC#(b*+L)3mOpUmzV)CGnE^e1 zCJ+ONkd(I-ZhWJBW#15k)}sjKUuqd{x+>BNo~|bo8z8~$XZ=Mm`WS@-O=b~uXMdN# zNmj(sJaj=}dr{<(zsBjoOl(&;IPD#VM=}NR5@Dx3tXsA6wDr}ck9ew=UupxLe@TI!5K=KPR2!;Y4E#BJp2asYt;yg9Z zP8~b}Wd+Dg4YXU$K3y@o=BhlKj1aPY*iug~5TKS_q#d?LkK(64EXVYO-}z!_pv7J> zDv@L$_)PiKZ+of&AWB2s&xR5YG3Or}=)n9SJ=R=Y+4~v!4MBp%l4_ou&hJ z19^}xJeB=svqiEYK^MLszcU}>GGZ=D7%f{+b0bfr4+DAkpgpx3m|8jou!HnQt>u6T z=;!fJ*dL)+q*$C$yMKaGy=H?=%-L;gQUh5$v~jH`FIXeq|Gux-ZjEi{i zT34%QSzjY(^6g)`8|VY01fIx_fvl~0w4xHy>wak-YPz@rVh_D8>>F;ux)(wO@;gPl zHxpBY6}uKPzmvMonnQ3yfyJ?!UtIA0Kz_cvQrki`O$O3pbt58+COABl!ULedd%gAA z3&RkBn^w<93DGkOX}oG!rf1IncUM-xQ5DqT#Rl6bTo{(@ugiBPb&hW^5X-v!EERiO04x~|Syl5=_oaR&2az)8YnA7ZDTw9QqAH3@*3bVFW0rQo&7_xtIpZwPJzC)`fBBCfxO%AU~#^_Esb6hK$`~Za(X71 zxGu#>_5<(l2yIUO-tZxeFA}AOl)=ROMObI`6o zfKQU%dmIfiPbd&hQ*ObLgI+sa-+yU{G3*fx^h!gSU~cE3FCf+x5wgjo6Zs;=ZEO!Y zlC&5xnxt2C#Iuk+{)qPH);i8h(H)uJWRDI4q1Q<(sN~JwRLR`=-yi6jI3QgX`CG+* zVN!+Vm6l{Z6w)>H*6)=n;G2s^h}h*w6^;0pu*O?G^s~s`-$CgCcb&SxDN2l%m+fxb!PF2i0-!6&VHx1+`GCWGf(Wn++ z<9(Zd0$Q`f`46ReJx}LrqCeBFb^z^JLFi(Hi!7#zfi5=GIBcUthh&D-B1Mj8bV5_m zNl9VPPR~L5UN?8j_lRzp_C}@GY%C zma@(aoD4EQMVS7IZc=caMiI0y5089UgBWyARKGx&?!ORieo~ zn(-|Et4S00^oJ}(JbeLr)Siwx3SMd*Zb1jWAESW`ky%PW(g0 z{>FU0%YBFj9h8$AxlVlE3U|zro63=!Zu6tQhFlH5%I80vIm&7|%pg2LQNcHuar(+g z_<~5`5z6T{|wsQIYA) zFkJUp9MjnYanoW?)ayhnmcAyW7)%~Jp*)M*jfSKOK)7&|onsWiDuX|`MNOh&MSN06 zh?x%B(;_z=MT011`QW{J66J{f?^e}-%HiaZ5_c6tr6Cy!`8vsO6X8Yr2rNR3%;%tF z$Fj1FSt8i(;bCvCXAn($x|apn^Ank+P93VZi^h=~1&=)w(AdN+HA1D(!ruT}p31ti=%U&Q|*WUU5`6kkXK<`)6I!|XsvvIBF^b8n)w)79r51zsaGOC;1dMke( zR-IP_hv{`fVE3DKqb)m0lI+EHY5;_jYem!?H2y(BDttMtTz4)Fz1tA)_$b1_<7u{Y z{cr0*#x3~3B}gb~AJh_V)P$zIB?hC5*K!mZVBW(7WMA+n3YY{H)(D*u_2E&DO68^K zs`o_}7^{De`=}B1>PGNF-Nb3oK}N+I`-VYH^ObCcdU~m2l7w$9uc9}f(4UXDr)Jk} zwshY_FsQY>D+_NhjycMs3?nzVY)VYU?itP!@TBB)kKT2)rGu69RWQ?SXN?X@r9fb= zK;uWB6?@eNTqgMGNtK^L!PDshb0g+RHN>xP%j||_?GXul3bNVr9 zw(2%ay2uPC+(FX(u>ozX%V0_hb832&kz-$Z`HZ>hiaMoZEB&CY&J(+D7vZTaBmzkC z1u|D^5Qe(1p)~mEK}0gUvn%vtfv=gE_kCX5j7gL4O?k-3I<~ck7IW%>22-TE;|@vC zz^Tch)tIJ^$IOrLZ`+|cbcW^h{-lw#(RMKy9n9cI(56t zeC}X5`?dcVGe|f}t)amg^d57n5B(bmsWMh+AkX1oN(``XAEg$)@B&5hP4ns?=EKj5 z$N4Aw9!#Nw%>;Ih$>g(po3ZOa&y=AyV{ApH$*j#EwWedx7wOd;Tw4B&a=a@eA-X8atz39KZTcY$MXnKv^X(hNZd!^saebzZP z&~3C~qRJALI87AKpem1shJ?hO(Mmt+M@&I9N_Nne8lmGLViy_wOSzadC1m0GPnLvg zb+TSOnIFAIyLOXO!=z)`wZGemJp#PQc4hR748{?a`B@ncG48dyO1k0r?!MJ_2fYzu zlp0lFKnlmHGm5R+a3s;F>)*lQdESi+QTUJ!o4A{%cm|w3qu$@T+zZa6~W$Y*EEYvoxLldg%lhrApIWnqeTX z4@=Lx$JxD9EK?Qc-w2?Y&Tu+Sc%%{t@c8MrEO=O!Cv=@9vgh2)od>7*VB84SJSgxc zWv^W-yRvS)g4$YZN^GWUpkQjSY4BC`IkeN+TE4Z}f*+7%J-SO$_=+l2op(X>sr1MxqPf-WgFMlVgx0cILSBpO!UyV0mWCN4wPPM;qsu;ft*BjDv2fW%eq z_U}IYm|wkam=l=%DN6lHaEOyPfX3Ca!fe2XM31j}uUs$G-#=&%jY)S0SUtok8KEG0 zzA$8X<^5}H*^cM)R+?>ey>|gTYkNjg$F#PWbZ8{wUHpBTIwhndlipQyEX5n>TqNiY zs8w>}x(u&Jz|p$Gb54PMcJ?yjrw$Xjv443D;&33+#n5V>Re;tmXZhXXyB@PER&uGK zdMm6kjms})WdxJXe~Qk&roJ{pn3!leqsXup*W0FSZz9;{*+0ATI9mdz+JP4sGF3*0 zpN(%XTdhTdT82TdVRzeN7 zsPpH_b?ckEt}ACglf8F6U?Fm|xO)MaVicP7nRxVqZa}xT*+}{#k0iG#(&^<)ruIl2 z(H0#BdGIH-|5!>FP4{+01$V%Ns@mch@FMbLZQs)PD|8;n)Kh3{Qf+SY*X3_{;hv< z`cTpA&qf_bUk1V`bdz*L(<{Ai=^}K2Xm(H?03{~NU|aW=MDo%Mi1<rXx)jV)7+H%_qgjiav^a_?u*)&3oU--z z>UZ{PEBup-EpuP(`{lL6%yOQ@%rT)XntnDsP@Xb~P0oM9d67mnK^F|KK1OuCIY?!~ zHPaNt-A?KL1AJUfsB;;X@T$)MFGGS_hbK(;lCzt(hzM8j3V{Ivvgf5>bD`+Zt|1o@ zu&(S^)aRkiomZgsBrIiLQ$JCeWECZjjC;O1y(eKYZOq9x^s*f~oU?M*Mf0kbzrAl0 zUcV=l5at!4fBr~egH+cEDy}-?p^1i+%spFRMzdu+ZV@vtKe=P8=7S`9IA!oYJysC) z9^{!4F*Th4!$ddcqau5+Llnc2CI)QU7boj_Xx}iK$X9165r^w{uNZtQ6zTXRdmuCI z=89=J}a4W|6Xw&SMLaehX=jEk7sUs4M%~LwXE8xoIN_J>izrm+sC1QjGn(R4Av* zL)VX4zzmWano=p7 zz`r}c5#%_f{W%j-V6QWbGqH7VV%<7xE@X{!NS80a$>BBth~Fg=Z)08*W0z^9lMeF& zK1u8DYmq-@$8Cjm&&PPC!3#jC+-{YF*z^Rm2%`dGb&<>1OB+@VewV)(IMrqWL=2kc}6g zQJ_914FJ|_Si9`>u_rGhJ70Wx=~S13xni(jk!7CtuwRfgV65%>vF% z+J`dyn^4-K=v>jPT4G8%T&3=wPl7f5#u=d3EKHcpG5@2jMe)Tsgtv+mDWv|*V|jPG%>?>dTr{_d37XgOAB1#E5gvwt7X!Ey8kdgdvKERhhn@765vr!CGD8r#>%11w8Tv`592E=mPG z$qeYs@*8rJm4pfYd_Wlc6#8_6PGa>pP~{)fLv?L3J0zfk&PgqMRCFT4^QS0hgIWlx12&_2=KXk}!nmk127rTto$0cNl}lbaan`kS$Ugb1WC)O#M3Z z1AR^^F})#Evvb&%DHO^`-N)Ok$q-QGDu1YYT{$whD`&GIHq zp|iLmxSSdw64*_wMu>Tpv%GsxbAPX~Nfm@8rcoY+RW4q zN_0>2{WyRh1K79)X9!&KlC9qvVxMHkFUEqchA}=}ngS-*Hg^mLIE-?N@Q;E^OB8%Z z<~FLjTMD81aQkjmpZN_RCbhyE3k;o3PgZa9=qdiig8qJ<3nr+Y#?PZh?2Wr&imBUj z%KMTHa3d2SWO=Z@a0GTgn9hOXFda&AJ*sazm!K*T1!C#Qe)!&0e<_4nJI1gw2_e-R zR-vo7M5!@l8V8l{yLI9eEc<>z) zTJ?2j21E?{a9maqM~}R#gyA{(DrfCbk=pbJ3MA&6x+qvlubX!Z{Bj$q2ykt`3766dQxdIKsKEJt(G-By927+Yn8=i*-j?Gd95PrHYqI-*Pzu{3W7&F4JXm&*`ut<^cLA=N ztzh21ymKBD^F;8~IrRkyVv&|}v$Qo~7{KnaGQzS0CFL};Ly_#}5Uw9&8&!x!n zED}{UW2fV9Q$v=@QGazPWs%{4@ACE1O0=4Z5X-H7hv&biU`5~DdLGOfH1?JzvBF}= zLqm%p8b4D@QRhq$hbM-r{%N1o9@Cu`Sa63fJU*Oc9n5p0&lutiN`_SRh ze@Hi&BR#h_yg?cb?D#hIt38jb=}sD458vAJEpOj9BptpAx6qA%{TM_nMd|GDe=1Vv z2aTR{Y7GO7%OD@>ECbYkE|}dqpBLqbSDJg%UHIapb0}nY0xr1St#tDTHNP?Go-D!e z<6wgvvF2$0bYp8R2#DvfdthybHmeoDSqmpzUW-YIdDL>Afh|)A8j*svqtC~}y5nwJ zPqms?Ec$o-cpcL5(cz1HLM^*nkd`mJ6+G7~LJO3krKjo?agO>)vs7~ah&7y|lRs5^ z(*k+sIw|W`r~}*d_C8W1$wk;Y+Q7i6Z)qc{@o{X!XF}Yb2I0`(T~`mg(Khgxvp;kb z%C%*r8vT)%L6%OrX7D7=N~JS8<)>i-@364t2s~w^o~46TLI!F%Jqjju#$~=r)ICr6 z`jKp+|5C`rDqmfi47d3m+Ndkhk&5KGDUjtCAFPkTMGR{l`LSDfd=!?=`cY2cK!u!a zR7YBsDg%-xlD07VP`+EwvgWCkB0MqOGB-^q+;Q%{s}KJG3I^NRrR3wUEw6l6U93yF zIC0_B4HyXQKrNIy3uTGVysXYG1$TOwRKY)@$j-TPp%JX;c#Ln2fKs)&gzBlLCcs%1 zyy<|MY!EO$rK^su8{>zS3~0X*=WB9IL|#=q?=Fpb(jN({T;`kZU zrIwkS3UNE=qoM4=obq^qhX{j*OzdW*3pYT|ECJb+#13oB1(i}AMR!yCYSvU&z+qv7 zAv<=XtrHbdQbZP-OuQX8u26JyNGBx&MvJDS*!n&XQ&?c{qQV@RrqxnU`RL^a(o$Qk z>_+zMzpkk0fZ*aMKI*pqmAq=12)d1Mt!Gd!|6P?qocPXfjd%e(k4Ke2lB&BvymP>3 zn1}=u!9j%g7cntfTU3$t7k-B;|>b_rEn)RthBwCbKBS1Zzvx5P) zY}4K#QdZdeDqv452hHXt?hHcv1+{*F9I42gsUyTz7nnIN|2Vkrm%7yqFI*c<${NKX zp`P)LIxV>*a$#bT{XdvIZ@53PON#VhFB~V$Uov;3*_H7Rf226gE}rsd39Qy%wXBEv zH@nB~qX(#DZaHOo85V4$s_ufgX~1ijlA3GlT_s~j+}z3M`jjM_o3|DG5rQlTB73Pa^ExO!BG6UpLiX?+T3Ua1 zAl{&YgNkM{xB0J`h&n$!4>RTq{=dUwEhWmmemCZ5vuP4m-a7r z3iNV?V>tKromXSEpv2y0VRa0)O|h3UmC~9{xUh;*Sb@JcsV2m2ZL^aYYon-L8P=P? zf8x`O+P_njmBg52Om4b*{fjMU~H?f32)?QAYDIqeza{k_($vvP*dGL-IYv= zA?8!UtkBrJDQuG7R%B#mf{VnZ!4my&+~e?fb5HqZbj%7l2>R&l6dsQXh6UqoJXRnk zms~*zo=~z4DG{k`&;AoUwb}YFDrY-0tf@tQ4+XGng6F)+6oz)*ynE#k`D?lLHv_fT zG6u!xtKo$=;-cAu%1mXQ$PvV2EN(RhrqOYVs9SbJbr8?+H4ML2_02y6)Kx)ok60!F zGk4gu;icp-u>$BGuIEgJ#F0&ly}@PP{O0OI@`r`%j1Mie2*QpGv2hqGeJGBr#q}OI z8hEah!po)hy|~ZsL%gbz4V>q{B~=q*KhyJe-wr&n)H@j z;(d}>QkCeWC31b)d|LrfpdGjT+31^ySr_ii*6)=9>e@uMjd{A+Ir(`MNtU+M1;^jU z6ke*z*Y{o;TcwaD0$4DUSKtT?97Tz+a!p~KJPpJx|9@X*gOY*?kAE`qt-M{&p&_!O z68tPW(5KC)rI#~64>xfXkQ_O!Fq0@slzC_u zSR4tEU2{FfIJVwICsPgpFY$@A>>e1t8}Mi$SDD3! zz2Bt^|M#b+NmdFRNd`oyH^#ZYF|M+9UFq8HgVca1L=@|Re8j)7Gvuwwwt#Z>U8$voQWeqbv4ckgYzqFPM!p+CIFU*MBM@W5xjn${ao2JFNV z8I-c5x^yaDxms`)EY2CT55K5b+0_w=p*?Yq79i{@ZMAwDgv_L`^r30waR9&q)}_+w zpuy_b#bl%_Ru$rDY7HpZOOO5UFU2zB8Ohe}HTDTwb&r50Z6;$F!R-!93R7#Cep)d< zdtU`gi+F!EUYf_hL@ZS5ROXK6Fmq4MSQH8X*O3;w0iGjPHceuBSJg4lp$3cWD$S33 zdJs5FSbRxw!0qG48-o^>@940a+KwE62qa1;t<0wAhpbA0OjY&v_r;^!ctRLaYfT|$ z3pQ=D%w|Sx$>}!KhnIsuv27yT=da0W@-%Ph+)aHdL?s7%2+~_4E~h~+)Abd`ZdFEF z>)RJ%*fhTPEgB#+oi(E83CgjHoKJQJb7&x!{!+$3IiW*U%QUGY6k*ECR-DvUUMF`) zEqtQcWg9cl+Q^Pvj2FTt!yXHgk5^D6elyBnWzO#A`ltPg05qmo@!+ym7X4qTZS8+& z#)h{GYdJne#eWl-E$pZLvwU7%7`C!8V8LO<>Pi?Gkjl|K{<}-~YC4mRgU~&>n6B4g zJrXuFR8*6%=YB$5KLf9^ULxWg^+TBbKU;+OZzQ>k*l!#4IPZxpSI1DXI8u$Ss$7rz z*PJN|yRzQ@J!%**NrhT$MoYkwMqC=gb3ESyBcdB>-*pm7e=;&bO@$i;?iFL(vY1hD zn=_~!7NjwrIVRdbAoPZaBC9it(eu zfi7y$`kp6%*vRlsNn%Bb^?t36>@l*gkFE`4uK$Y9!eh3TFp7SS2Hr%K7&>kF@Y(dXewiGq$2Zu|`y4q!X zsPI)#@-h3NZ=59<-c>|>%&OcuYSv9aO*+Ze5VnUj<-&x)Mk7VIS#hz`$9H>cvFssW z(B79f2;VRZiXYdy94G)EzX8EXnw5T#^f#PQWGtF|HI`eEA%-?<y6QX05}1VIrPKJ_nw91)!m}^qRr^XuoZtPLsv6Lq$Uv{U zYeL9a_B2t5??ggrgcZ#d%nRF5(51c|BHDx7Eq9I~McBdr`MnlrLg07pz8|*N{koEZOpMF55rHAsX&b@nlT)`v6e{h5_Nj&vB z;AE_`De)5k@u~*Y*YqSe%UJla8+i;gQK(PrCw@30jMfaAXL3cQYt4DV4`Hk}f0JsK zF_q!KG$e{<+l<4^Gfc~h8o6XKqq5_rEV>J~Vo1`yt%?rXZ*aQnt&QqYFD|)rk`&`g z>CQ_D@?XXR_O`d2BhwxHwny*esw~EKfNL!_C9jEs&}wezP3a$KSKa}(d4(?V+v}ul zCmz7B#GT0=)`MAtQLphgg1>imWH6Bi2=& zk}l%(Fc|+EhV0!~)$8>S^AQ3?J9gK|zoIfkL5q@G40N`qPAk@YM0#1FkLd?$)La~) zS?R)|sG_lSnqV*gN#QxjgQ!iAtxtnOgO#^`?K$RZX@Md3cxCRdJUv+a2Qm_hS-jCu zJYl>frP~WA(&jDTs!y&F6g=g+f(!rUnsk?w4@aN<0m4QTQSG;4Tm7TVsqI+6A~QVC zY|}~+PBX7&<@z4p6LytP2XTUQ#tm~$qx>4=TK;}rvV>8Ucc?RYkY?6>gTwv zAC{^=1YQx&A4On;X?XK*4h#PkC6k>p`a3H#B8V!{)g>Sre;UM*Of!1oFKr8*>UJg} zDzkF)kq}x<*Qm}G9!hacIkfpG#3qy%B-CN>H_qWcd7zH!8f&L`oy#kE8&wp`>wc?X zcFNA!3`*4Rq627+0Q%S`9K%W%+A5$AxIvS%AAsVYE5grXK$d#R5~E7jNvzi1C3U}X z^sikVi9y0IEAOTC@TEA19c|xpHG^Gwn48JGuoQjEj?4E3WUXI_T{0m==}8 z16c8lPsi~R=sWPRdDwbUL{XAGto&s3qJymuLA(qq5rB(Wsd$uSMr`=c~FDp-}R7Pp{%Ug;K6)A$Gy1N_2_ND5c? zi@N5SLsOO)R1Hi<(XukJljfS4zSnCznMw%MCL3!-Y5dPn(!a3aIhzISS8)ZY_AbU0 zHIzY0$hyGH(a9zsbl^b6c>M?9);yyx8`eL#n~pgyz}w?p zYcXE{`^N)G{kB%|DNi^>jf(dq_{|y{eeeige-bZ2pvU@A-}pwX!Kpx8e6p}Y!q3pai1J0jIqfl0IAO$(2iqQIF#A3@(jNAgAAc+8l=MGK@j+ zzd4)bM-C31X9Wdz0;=)lh(2l3AUt#`SAOO4bv6g>tqDBLx%iJP!8VC`=Q88?=!Uin zE`pIv&kUu9Ws1{lQz%getJsVm^}ncW$fe#%?{GNUy2DLJ3_7FGTAwI6{?qT~cQR*Z zq%Lq4%7IFJ3nz5K3KnN(&UFb8fxW!8CimBYAN@hPH85d98P_%WgLR}gO@6j-arka= zY0IN$)45@m-lLI5bvD@Sk(Bh z3495MVTfMAwz*cQv6_v~Mjc~11i^1;)@dkT<>z=Pq0L7t?l(z3D7qS?n98h2m8E!( zyTWZ*?teu*m@SnRBNV2{w#h0rTF)w#g+ZN0HmR4m97Uhrl6mGbmKo=vK_uJh_&#r} z6H3fOe~ZCKClNvLzcfIaK#K^oF80y(HndbPNIq7$-WdU2D#j`6Z`@ca8)*|>P?+NS z{5sh-dVvlTg$>lE*aAdp@iE;Ba2S8K?iETLasy)eK)-NHVZ;2Is5^_bfLnu;!maWf zmbJ#>ByQu|SG&4R;?FBw6>(n_si#$`Z0nN;t*evH?N30&dMo)WxJ`N`)&5WsHRhO#dEwg)bDFwXGAt3XIYNtB7I`p&1E*5=8sIw{4!E21JANtg^gz;|A?5Xk1G7A~o=QrOErZBYK{Lfq9mQr z^8zp0yL9hl`i_Cdw*QVzgA}-Bif3B_+F1HNtSBcEN|4`g{2z+4Onw6iv@Dy3e03u8 zCUNW|UxMo&Jr8Y}xl51yWC&>+>QQ&&Mg z`^*nWgwvF-l6@z?_q8J9V3FDVnLcQ}j_!;5kOvO%?1!}+XayO1V8o%zEokOj)g?>` zP#7_r%t2%2KgMk7>#h0dc=$&-)1IRjtAHieeV5alJ|B8hQzHQ9fL) zJkSv6edOMyvM>ZUCSofqDTO#vsZSv-?@sya4$4 z^ZrDZhKFhmAK5oVDufl~xsMrsL3hcF_?q#rEOn?r?wu^E-8SW(98z1zmaX8K6h>|0 z?wdo*{{^}*|NlT2PIg9lBG&&^TpsQ&t4BL{o=(S5jf~!MA|<5LTwFNS>z< z`5~nv16B=D9eE$^Wz(=~m?m^wRmGQRO;1Y{5T+hPRKP7VBhb2u*etUHvizZQR#0ZS zr7^9kaI=A@5MV)JzNl`Cv;u)9e3S9qp07=;7j(+DA74dy(D*pCLO@tofA-R(Ce2B7 zq!d4D9(a@%1lqV*Z$ng7fNf{17lx~}-lmUNl7^C|F#NxCfV+h9!~+hWpaJ1NWYp*i znaLL0*G@M{j1a=AVYy3W?j)<9DO7kkbzx9UOhMH$mvB82=}gpna&XO&8ZW*g%S4J3 zGhq|qM0Wa9{0cJWVK!ufh;cA|FZ+Lb14I=fQ*X6ZiEKC7LaOY-!s;hOU=?ZBB;ov~ zPC~_YcWZAtNtp7#tpkIZ1nFt&_hRrhO6pACU=N0N-Q%uyZ{anq8{grb7lwc5NQW*r zp;jH`U}PDneXx$>;c+iwA90J+8L>pk~3Gahky~*>{*6 z%<@GAY_mw9xsGx=IJ)+h7+G1(phZRsxr4?_hj<8Ao0pG-Y?*0tOeShFyP zl%!ym;fGE@m6;e~5w2OxmkGZ3gxg{5e)3$Bfwr$(CZQHhO+nG0Q+qPM6)IF&|{Y0#@BF>JDO-g;p%4LYt;l7?Z z!kX8{=IA(wh69XqvO*&^i4%DK$qHiKY8rO%Z@=wF>;x@?{S;HD2Oj=5BqSmUK!Co@ z4Z9jcEiIcPrd@3pl7LjVb3H{ZmwheIs)%Vb1`_i?O3IPotP-tpl^fmxyz)n?p6F1W z^t-oxr13d_*GRH1EPIPT{m3~XL%-(X*^+oY16xS$v`Xcley9kYZUG?Eh>g#bx?t|H zw`PCmkU79gK8pE&XW(qkJ@l>QjDFby{h%)Gb|k7^C7o_RO|$&wHa4qmIo5T+ZUNFP z5oC(y>3Bnl8gr-+C}!|BEa0fkg_yk#TE~CCPocY-*7&dcLMCVXCH%cx)sF;oU* z1urqZ!peBeicV;xFejR5C&>>{d6*2{>V%9wF*oFT1~E8Lls9^^Y|qd?NmlCX{mbs6 zmH4Qa$tpCh{psRE~l&A3QcU$_Sfu|FKBvfY2v@q+W2==$j5bRscHvU@_UpHtlZKwjcT z#0em=94AFTtTz^^XOkpbp2l)^<|*S)BP_1+5ol!<=rYQ~q+n-SheJwEI@F zu$bp8n`t#HwW9J1h~gxHk*sKS@$4UziagFr$lPDv3ky0ptK8(gF48 z=T8OuCO0#AfHeL?zQ_k8qeP`C?}YaX?)@C_dDhn-OjpiucART@s&N&P~@z-h&M=meHuydxk z_nLp@sD?+m8dcdkjT#xrr*NOVKmYWG6Oxz&5#9h^*`Be)#wvVz?1FdwX%@w){Fsk} zF|KXf8e`#Y+EI6xb;Cq$oMaPMpS7CYnc)$)%CIv53v1rjcX=Z(t++b8S4M4)wUnk( z3=5Ne05a>-t;r>m7h7s%X>Q=lTAg$e(`{Mw%w2`spx}5eL`_kbu;0T>d|4-VQ)}YxtvVK=!Q`F6d0!KS&SBRbsUNB%dfp^D+oFo^u0n z9NpF>>U>!-3AE}BgK<%@Rq!&HLmrEo)A_x;^Ae>JNA5-JA=W9EZS0jYo^u+9e_b=> z0OBhCUj2Mt&gj3Hh!EOgyT;yix&(ACu$(%H{A$`aE)&srE8`B$!iO5x2e137AmLe3 z-fg>E=fc^uGuQCU!XsH^4C|Jq=9aAacO~`b?dB?>ZM~y1#ecP@8+x>U9Cph&{xoZU zPuss;tJe;mBby^D%sd;!*6Eu#DN5$bZHSY!E2@YT$5}6q{6SoXXgkSf;CaRut!}6RN_w**M?4Fl{-2zv4Gq{;;0V>bDxlc$&)C9^7S;+|7iPa=T+V3dT$w9EfFef z70(BvCtgL9#1)+6c_6-%qg@zCdL~h zW(&+)oa5W`Y{mXY#qCdx2#X19&8+CpNizb19P4a2BYTOec9l8N9EXmJ8+4`}C#z=Y zIL$}7&!bL4V=H6s(@0vW_Ot+<+JTz~tq7+^Qp@3o6aL8evaL@t$nt;Y)>PK>{N6Pw z`DB;y027%#uHU}*jn3q&=htw@rj2QRp+P~f8B51T*$VbKyYEaiQJ}=AdwrvP32*a> zTn;ORd(>eqR{8y(?N)N-tx8*Z>F+t>75 za0+910Qcq^C?8oFsMNTk3U&I7HVnuUO4|d%zWhcA^{(Jscys=5$&%^+k}MfHI5?R9 zpDK`rlarO>|A$N|e1X^*%r~RkPvcrN>k(b+Sg0h`D;~f~OJDIQF2zG@V{0Z=FmUxx za{C01B4RD66!sV`p#p8~L+TRr={+D%FP<-lb;cS8?s{nq;(ld1$A9jXMp!~#{yTr; z^`kB>ZpSydkzpR6j736fxqwRoJY1+GsD!h`cU-^Gz5R4&ksi^#Y$|1cNiARjjV~Qw z9n1L8yIK&PdwMjp#%;;&6s3ZiitDt8hvA;xfV@OAZZpxqLkzQyvQJQXz(9^xD`>z$ zt$P?)kA}C77W>5OJf@$4kby!V$rELvf-*=YWMGP(HSejS$g&6~c>NzKk4H|h>9H&{ zIj&4J225uMv=zmfu|k<+jK^xjX2>IFj#iGoa#!`pV)x)hThVON|9Q8`MQ#M22<=r> z=wbZrCc3D8)gk#*fq@|sl1|&5?Zvt;P}?%PGUPj2viWdeA?~o4am&>-Hio19aNkC# za*N&Cc;``v=`Bw$QD6Dd5{ww@Dn{z5H&bw+QJQxwtbHK^V8ikgQFqqXwWJbL0fwqVB z`$%*rtNg(-BT1F>{hRAx=m1>jna@1MRj>ZL@%jxBc6+=BxdgnV=`RxW<*#jg!&>%% z6)OV_KX>|($=wKN7K|?DlYeAEuvDUnj@@#j{8}>O*(wW%v48#NHio@d=|%(At9*$9 zSi!7o22>48%OFKtgUEuQCPx_y}9UQJGn2E-;10`Ym zQ0zvGYI`n#<>IPOZUq7i1~xAUSz2mP>3HzuiG746^Cw#|Z; zI-@zFQ4<@E`VXyxFx`~_4$@PE2!HhIhbq5RstDtYFwa+sjca#8a332@0TepMoQlb^ zYBR+6oAaGC_t}^GPjyyI!xM~9nqQ{~PIdPW3GW)62XdvCdqY)!_Pw0U-a= z&n-bMmp|_!3UI4^`WpTYw986NgUX;F{dd_>5x&t&JHbkmKm4mFQlhJ!dHL6#?dy)H zbxau4V&bxe`-`flnCu(@D;;fm9H2ef5`&OC)M3vunsfbkl^IJ9b$8hFBi3nU5s^r0 zT4UK~+O_);k?P7KO*)#0;9dWFbh{N8q~A}cC*8<4b-79+GeV~SHGXF-uIZG|T9hhA zZd@KZ-HT-ABhlbbn!(rW%j{=;t8Fg8dC(6nW~M2cV!3CbLy+97#M*L06>Ojd%&`L; zgP9U9hJF-ksGr~nzN7v>J*dCC@VmS%di`^zgFrbcI(rE`cbp=;SW5tj?i_*eOUmc< zB@gBCwk?U0Fk|(a_leZVaBLzaS*?qjD(%t91C)1rf6B#=C^nHY_Y0rvwgF9ZQVd*b zL8`eL@g#Cl{Q}Qa$RE2iG&OI|6MuD)l>E^Lo~RL(ZI(p%G{~#=q;;EOnD*>U8RhZ@Ucmdc*&KrNHPV+8+_aPq;|(o;fldr_R$_v>%8lk+-D zX4a>8t<jG%Oe(l=ge(`~m-PpmRzj*Dt1INy0E`mzc^vlxkI8AQLc)~G>4 zF|GD1n43$e$X_VIt}AXUld)}}D_rWCiFZnwTg>}Fj|c|lxa2o9IEYd?Q@?R?R7~gD z&_LQwe}BNhg*z6U?8r!S*^cjSMZ(h_wGB&`caj4lTHMdAeyT{(zzjCYGlQm@iUV_W5L zw%^xilmPjAfE|{|un-CXWRgbayn(&=6p;@1;p zz%SY{^91NoQ4sWN#R+y<90hRm(6kYDhtEMcAOJA^s?-jLV-(XQDOq;ic-L>z^CRGP z`f*a8eA;t(iGuC5A-bpGfSa7&M#`1{1Z;XlQBUC6y9kUH+nak z>#>N1E!el!yedr}SQI5P#%;RJMYI1=_nhJem7{&?p?+4G$Wx1!Ts0S0?SS~7Q#7fx zy&urgO9o}RESY})Olo;fc^cj!~RJSbR(5vMpadT4(uIB5b zN4}{Sn|VFq?0&SpkEwl2o)Zt2w}}Ok&`ymfH{P{#4E&3cF42z7uwh1MFBpj(ksladWF_2 z!qf*gi}dAxO4Kd^?)A!g%|gL=ueE^FT4R$_fy^CVCE6jm5vhG(8;YVGDAJC8nS>sO?xEH1feO5+eQx(iV{Ou zM>wuIpQt=d!_PCx@9>E?ItQu+3Fb6{F7=`ZcafQ&DlGQ6;A>-U(p>jf8l0+G)+&i->_`c1x~NuZnES#BIxmh$Hk8G?B_hB*g(T z0BAXI27o-l>j!zw^dWajv!fMe>e@L|N!veE`fa{B&mIJFbdrgi0{XR)+w*U1!&BlF zO?asB{(k4lD-+hpe$%~r+#;Kp-EO+#VO;DWlFSD@uYdUd#l#ng!nGW6g#npD-Y;y0BxgKiG5-gB<+tP1|%OGoga=4xouroCN0c#ohi^{%=@Rn0jR=7qjmZ0IftSiUhpv7_lu(L zp7>ox&3JAYiEVDm zNUwZF@-28=FLMTPQ;$3)W#55CDxwvj`w5U#$^#rl0K|6o&UdP*H6liiw&ZT@sNRcX z$UB1}rXcX^F0&TzKwv~zaiF21WVk9Gz!4oI%!|JsMKbH!{@QSdKb%029>fG{?*rh& zVu-BDF*$qR_DsFBjj&(4Os8o-e`vm*qMYVo&^dGTcxarTRmUe-fEbta!M#KAfAuKaYKUO z20t30tpC$U3>^4(RHt8n$z_LZcV!{hTuO1+MJbDf8LcLgZn#yga$X!}i?|cSW9Ffq zvFNG24GcxN?Je|L<7d2!jgidD<8<6Tr!fq*fyPpjco0F7cy2GYgog)G2&NL@*%hGp z8=#C6%4bC7pH-!`8?4bXCL2A7>1?9x+9B}s{@Nk1)S63F!PJ*L&&xL zsHy(zW`#P%1#OyJap5Ig`#J!{h+ZknO$*b4A%jb$)zrdt70i$z~ETtE5($`%(Vb>R5^~$aO2}$ zjwKjX97mVsM=ykBu(;l7@ktfhPwP=x0G-LJx!aXssZ-m@oOzjz^*%TKN+!q+ zlm?euJ3&U{Jd9i!GnXiCgefSspjuAu@sDpKSDb`HlI*&g z5nA~$f}LKbw&hUI5{vZ*V*Gjd5qHj7fYQfr6Ws~>qLluZ#66{b`17S27^*oE{1mJO zv6ek*c1d?K-8C-?QcNjvKvi)H`54F{+3k|9ApaI6K*4M`h%? z55@JjNk{mQ7Mzr!+yCxrFTCvm%k(vO{b>W0yKClcpX~RNt!&xF^A3II%Q9#hAs-H@ z>!R){LaK!pPR2m?i~e78vYyGYuC9?9=Ncf|D{@Ws^AuDsW$xmS*lR zEj)v4FT*GNWd-*Wsp8j;cNjK;lRR{Tu2&cWrPPtH`ab)hT7s+{rq_P)aocczpzG|> zz4lhPvay3HgWkh_03;pQ-5dYe4Vm6bPP4yhYYasdArgT5>~e6>z&{pQCwlsZQgjfM zM@1Gouub;x2J{i;_E{675cix+kX_v937%(y&Jfx*s`3I}=xc~gHVy!oF%TI?&NRik z*!E!cr{XFSgdNZzTyQV!WQ$;_;-Z|>lH>|g#ndo1B*!S&B9W;9wLyqVj8UP)(w2NB z_}NyDu=I?9dl4q#XA@6D>we@F>|5rnkG|DjbxTOwwFok3%hU2UE@BU&a4gKif`pE{ z{FP^sXxmd(j_z&A8$`i{?dQN@TEsQWQS6F!Qx+_L6vKX;n8P?s``zN;H$E8U@JVfE z4q1~vfuSEIg$*A7-&VRkvn}1q^(*^|k@3y)o)Svrm67sD)uW~NlE#jh7>?Y!zR74x z@HAJJvgLO4(B$@dvS^v#Dyq4Ve(y4;Ksa2=chB;)hf~3>E_T)(i4CY>a>ozbV5E&0 zi%bZgOa69Fqc_r0;f@c)sY_ybq_;P4Y#VSQliGZ|1A&u%yuUq!fnIFwc{0m-8_oJ! zAaMtKJ7LfO#S|~{X^=AfBatl&^77aXt!We0ROZvU-5|oM${62Qe*gJ;C!P7>Lte|B z-z28j5w440U}mE;w#+Q&7Y%w-g<#o+cq_sH{$06}7EopdOI7MCv!mrKPqJ$?gI=^; zR1VDk?Tl&Oka`6q?fuv-_9*;^bgM;En-oRqATiZbfvhNJ3ObNe@XPwDM50H*2?Wey zpY_k61?j+9*E6TC{+m{dWX>%3pdX5L>EkyZ>3alN)_bZS_xmz`8634pcC5h zjI$iGXw8+@9}-cIX#YsCo+}iHYP=#I(nW-dAwV6Vi)t*qS7&o&L5%rn3#j6kHA_N4e?H7AV_;EkcyOPGxy zHu(*gOZzAI^E07VclJ2-*;dNh4>ie>^Uvt%^CX?u;hs8DKWlFSYyCW4m9>)HTz-%T z(E#;lS)j(F#=0UFiRlY46mmIN4fq= zUHb#TRZAIqsiDFo3uV1}>80e?B9o2#zbCFrJFxS1I8R#L6Jq-r+p-6#>dN#L1?4d- z-jd#a2AW3z9abWQ0u>K*n4{s};&de3h?fkN6Q;#)Z|=^TE#`y)aPF%#;iR}Sx|YlW zB=K(^okb6s{`z?y(c!xn4;+Z`cV3)Dz<>pg?tOgi+fiS^Y$^yg!vQ(+Eiv_+G2xqC zhF0_Oze0tZwYywOM!THSgpxKfFOF@o*igd;Qk`)Sbq?I0=`CBlB+Nc*5iGxGh;azv z^vg3=SeooB?mR6*Ekfr?*(&FLne`>B2@pl9OQ3l$_1UuxO4c)h1UX<;3)@F{Wsu2Z z>6^E4ky*M_+H^)Cb1Me=ho{pMe<;3l6Lc(pDFVNY%!f;j)OY27q=qYVDhRqfyg?R) zYM%hsHL_`Q-E^Xc1%X|?IN+6BbELjHf!ojkI0i55+9z_pk^Y3u#RC(rb9CyUE6qmLUBsdqM`KPT=T>N%vT$pg_f}^&Go$n@pzw0uS)fVL zf!9$<=_`X0A@o&M33YKdxCq%%Pn}iN2&vWbUEu=h9dL?Y3M~lOLIN?UWl)dkz6K%! ztKes@!cL5ml4rnBJnD@4wVva6Ab_r?DC>`5aCgUudJfuNZrNYl8u7M;(~>R2{yl3t zLE<@(0-O%&j~LSJl0!U`u2hT6`J-uTclp5H_551mT&;o;VtIN}&tqpIJLcOl%X^NK zU|8pg06>Bv9d8K_%Qlp&1T{xZ5@r*pYPDi8rD!SySiMk$qj7V!+56QzUj}u;4*y$( zbj=y0iaD?!!_jdd=ShRK+cM*R$?mO0F`hA#719nxLw`>P%&@138P!>dG*^AO#=-`= z=*4CE6vqE0H-H}*dK8_SE8A}5uf7yn$wId}lCc%?FNfuy#HYnpFl%|yqSC~Om)4uh z*`3JkB1hwr|xVi^NqN%B9>FA@cq$dxm#zW0qp0R`M!5z{hsn@DvT8mhY88diGvkX*^ z?BVSK$EX@9mR5(sujD-S?o_$s!20Upe$*ZzZjCSRy4I^wKa-~@o%9f3=r&1-WC;`3 z6;;2XWI~^C^qQitE#ky0E%`OwcZ#39QeHt5B3{2mUF4>UK@k)#%epIEgj!OK6`O{1 zl6B2~@Av~_v4}hDVM_rxIxNpJl$}cxPw4bV7Vrr}*>!T{9th|6FcXj1zD)r>;N60* z@F}hcY8P>j^6{nYNh7;a-dC!IXCqRswBqRIiT#>S78|j==|*qW{*1&ZsEKbUB3~Au z_@>a6(eC$?ZV{DBb!P8;!wyesfTzP!Q|LDsM4Mlc!Ge7CfK@yChE`YvW!;SVD6u@? zr|JWR3^Wbx-VS_Yr)YiSOsz>`V{;7*+;1-C#4v+)W4ad79vuZMc9AEexZ)Ss*!)Ux zl%;`4$MbKcBO=Qcd_Q+%9*T}eeo($}J@liRQ{PTFx@p#bRokuKRZ z6rpg--F)&JivVEx9HLVfu>7uta1rCJxOgRnW_4~ zy=iKav_-D9Md_m}RE)`+Erp6zy(#@elt}MQ0-To#Cl;Wa)|&#MC+5BSFCVSl0+nHO zFcOcf56 zm9f0>P0gBigRlk!tC;C#`O86!w|A9ZMCv$F|B~_|yBdR76VqQ$r$Fc!$)RZJGl$qhEc(ZCg>Dv$M+if=$yVbPBri-i<@VMBCj9Z0@<@EKg^gSL$Xe88ND= zySwE9YGVyTdb;vcIvy*JT)q`x8@aTtt%AkFEO5?41QQ8^=1IhRJg3D-@+_f@-FueS z>)|2V%r@k3Wx%5(YYVVX4GqgT+CQOyaP13nw5R9s&zf!Rko3A~QOBa3kgGQaqip=1 zy((d*Bsmq5Xw%*AD2H z2vNqq&O%|!JIqs%po(%W5MF0_Abs=osK4-ir(Q~GP$xYhb2jZ)#V0P~*(z8wc9M&a z>gvz{M%1hSQe~3Vn}Jd*y;^&^Ma8>@&*b6b=^6m~yUOA6rlp<0c2wFuW^Y5Tu>R2) zCKXTtBJ)tT`^Q~j{wGSrDCG-#3rrE`X%HQ$s90qx{g$*n*vl@p2s}bW+LGV7dz(gJ zp0&`vFwAS44hq2?!hC3@9tg3+NrQUWg34xPTcgREtLeJQvuJ6%g$iorwEJoWpVH{( zjPlx}CeB02tBx^;Ur)qPX_(%BZh(|=eVUE568e{&?>}L9ubc*MW8c>?h^hbT&)`y+ zVaome?}0x1Ys4$L9-vV}w-Zf<%)D8#Jek0!znrLN3rRRxfj1ikNa4?-DY&;!&S0{p z8c@@stS0DJT+C;TukmI2vTfeUC0X2;c43b&J6O7OH2`&0`M5rYY_OAy_wm)i&>x0_ zBzt&Jy*9`$s{taUazf?SFQrztQ1!Zi(HBxl#g?Tgk%bgqNC6s6D5VhbMB>U$ep5tt zAdXgWlSuEmxC=-mq~KLM;i7Ab6&|M za8(AMQ3Sn1t0VY@!a^tg!M|YNdA(8u2%_@IU6hlvLekh>dEJ((Vr+;}VA&VkcF!^n zM4r+1p0pGF-(DQG;F^DSJrF~n4m(3#pdSm}oZs6a()}_4YvrC&{_H^eM8gW8N`w#; zqTwx))vXwl(Y{zcAEsNAX!)NvY)p|{rZm-Ud8!x0>Z}wg6DF<5oDGDlBTVwXI8}Yp znL$tHrX@T%wl};;p%L69X;hp~F%<7vtdxq3`rX&pvc#b0=R9EuWL z0Mk`{pt#T`0+08O`$VLzJ=3lSDb5O!(mXawb~d+2@~cXOV+o1WM|REUz#naW2~hXv z1KcL&HQEDZ9l>o0-_O^(m>lesX3|Z$h;)21uxhT*=$&Wr6r2`6QsR~KsaIXco%CzE z>~O(!5<>Pc2u0A3Bt`Jve}sKfUfu%|H2vIs|M%S#*u_hK;Z-2yaRgDn9!?QGfNHNqz1G^8ij?_ctT_fN zjfmt=q7r4l?c?OsDZN7Muh7rGo`ww%Vvc+^bI3j2T;;Q*IKnY=AbI^Nr z{mhBY93T}Bx)r(>H*3|`uv_Dfmru?5BJFwk;4`7u^EZQJKS{D zUxT8kz2PxJf|rXQr*z8f7wicCoCUgxbyCWd5gspR9d}mCVHO*bDV-34xC4p1bb~go z?YNojz^Q}+Pf-HerCW96f}}G&t42S`3aor0;4iMykVs9hN9`19QKGI z?3EfG6)4YK>xBUrFVXZpP5>NQ?;k86#X|=0KqtBFl*-Pi22uuRT9L}p)MecUY$ic@ zviSk?S)P2X*_U2zw<9*{+@e0?&fGXJ=#ru;jH7Y1`>IWjq|_WgQzNi#%ISB^HTSd& zeS_X6SQfZ^hLUQ4qZmIG6!E4p%Qs`DuXVqHH%iqQj{gEC+zx5vH|Fp{IKqLbYk-l| zi_kL|e#%(5mnN4OC=gQMcTC5zGsTo%WhAw%ngx`Qr1jP#=Pj?yt(z~Pkn(Kz%MpQ` zltcA+ig^Pg8nuk;*CwixHkM>K!^Zet+nQu^oWXuT%i+%I$$)P4_nyY!Tn9G9H-LQq3Y*k zEfFXep=k^lB&gB6UdD>?Y5Wc063D>0Oq3t=l(Z+?0J2NDdDHlRPS0NGvhV1J)>g8k z)1#b4Rv7$RYZOSbI>FyU^9ECSb2|@r4{BK4&5Z0XIqRHV0t6_mUPEQ=KLvIy@6XPs zCg{VdUFveGR{^aE7K>!ZT$FI(ot`yDefyo6nPe@40iwO1t8>m(W@R4Ld@;b7hLXm4 z#%cPtM``rPpJ`0-D*8w1K#JJP9uS0!EY^KYQO9R(Ry?Gk=H!{KloUM)7Xn10JQrGS}M`sCSCcW*sl1v}@P9Fkn!qCu&<^Zaf1? zaMN}rX*{igZ+o9Pbecktz2O}m3+Qs9j00QIB5%#ZVNJ}-vY^hvcpL9wXSm$2l!CTI z75oz=BUyp4?5ND{lC{e^H(4{lw+U3qEL(L}dEi@WN9OHLhg#-DdTDVn^f@9JkA$eU zT)1L}43{bO2<1WhnXj5m>+JjFjk4#HtUULNXVX0(7(yQ|$EO5DZEWHo7aXjP*GM}naWayS1I zx5~Y=ttt^G(g{t4EKCu6S-W}9hk7pmv86o1@rj`;=&L~Yu0XKTU|<(khd9Hw$y;=^ zE9j@G4nf+#n6@wE>mlyqQ(VVmYw`EM$|rfHC?YGXn&%c-)4?5ju>=CFpbRZ+6R91i zeXhfGzMJ)*uD$kduBB!4jEafR=uONo%@T;iJ#Lw(sBOYIsHrF};-QH~g1TLtu(YR7 zmIK#MnT=0pZa<{Pr+5kDRI}0APw6Sl77ZQ{xOr}=c@;;GwKBUBvH2JN5ym?&Cgk-u z*zBPP;w9-kFv=S=7l?D)Wvp(CN4LToiVQlM`1*7Mp;k_1x`+jF_#DpPQ3 zm1kD!{BRNDG*;zrnlRV@N8`wZMmAN{9qyXdt`m$Bv|YqQE~&xsnR8{^Lzk4+CU2Sv zJXx}N|5GcRq}Q&@aT6()QUg_^@P)Xz*HeVf7nl18GtK~a^#y_j*Xe=#Pdhva%n=gk zJyurOxASMZKSRjEW+oEB3MV|-gt17ExtKz^&8RY6fd0Eqt?-~JLzmK>Mh$WtwNKhF z`dyrglQVUqQRKnoAbv7jQh5lGwxq@Sdz|PqxAb@n7;+zPLW!D2?LNI5Gg4_w0cs6X zDJSJZc5N8@c|J{xwtWR-pu|yhAj?EdMqwHwW|~nET!-FmTy52DvN^K5bh-|noL)rpw&t=#rs`RK|?<_`JQpk~0Yr=DwDuqT~CeZO>tnW-c@X;W~S@mS}%_#dHQ z1R>Ui%z25X25FhcmuM|rd4ns$Z~sVo@j5>t-F6XjWLxlf1ne@n$q-5&^7p7(TC3z> zc5h%vtzdwN#&)e3#%0^iMn z?;)wJ2B#AR=kDc4l$z0euPDmjdu+WiHAysiM?@Q0W{NiKgjO+^t=A2r1Dy+@%8+9b zq&VQUdcUYjZd+BJ2tNRIE`}th9H{OVez9qaeXGC+8IoeWlxS)ST^Jxa;AdccSW`*M zpgsOp1kQ{W^;4Ar2rOvpwH0N&qPrm^(sb~ogCah8HphPk1ZDxBt~wK7ebAd|g4*9j9?5bV z#@`Dtf;ZQ*O>ja^vi=V@^^7WrZV#%=)M#a#a)+~Cm$@!puL}n2+92~UWgT2HNzwVZ z*D+~9J!{-SIMP=a7$w*Hw{E#5wyP+at_a_m=%KKbecvdA1f_bHNxM4uW5+H#m6spdvJ6u(*^vS|tb zUy(`fQHHrum!$n2whiN)-;k+;K;|+1R9Uj4Zaw?;4ckd)54=9Th0CXqbAKvWC69Se z91hpJ#z$xhpp(0_mh;gPgKDKceB;;Vg9<)reS5%#?4V|c;_l(ww5DB(?q2}+){)jg zw>jwqw@BCdsiFl>@Gtb;@N%J8IqWLqjKr`Ndg7khER9GKXviAb?mBXL&#=ifeEiIR zoer|wn;)4{5)6wAcU|#tOF?G2J=!SQE$mW&AK0=Xz@{3?7N{HLhu2aO92>#DruGKQ z&Y``f3zs&SvZBFP@iry+?dVQL#z(w{%s_8F; ztzz{F|Kbh@<+7m0rU?@<0GghnxFk^3(@&8OL(3b*i39)Sii{#>ZW{WUO3ei7s375$ zJZ&ozqJs9(THAEikHg}vL({QmJ=lI+U7X&OJPqYQ;qOb0m;uQ)jY0r4sOqBF@ zJi6eX&a=Fh7+yD@t-Vtkad?alU-l>?Z?`X7hqZ$fFmQG+KI9dgGP$*~tm&b^8!GXJ z`LAysD~`B{Mn(Jqbc#|azK`w(#G<7fejKEWUD2T>vry2q*&#N{6F!>J4|?dYJq z@@2{QD&+9EVx*7nqs84?Bg%FzTK_{+J7AqKTJp_Wy#)NZA9>Bc56IV%!op8|E)4yE zvpgBY#Pgf}(q?ibbV~>$Y1Cq6>`u6E+$wOgo7c5+W9wfnQvRBET)G@aEy;S$fntgL zo=6NtL=Jvo`-^Y0ztLLPOGyDQz4Y~5l-;?&h#9yCvEiRw!VfkdJ2lJ^YN+0rdbJmE z*XSuce6|FdyMy)BfuEY9wach69wC{0bp3|1MA8wWJCa`RDDLY|lG6x@u*QmIm!RrU zI@O)NZOAQvj4Y*Kuy{rct%R;)v+-k6Vr&y{;i9PtHY?T8TOFWz5ccHoh5YTdV;~tu zfJD|3qanmt&b3BL>NQ9^k`g5cs5uq4VXA=pgl$gL{zlHbBlrUK(XhlKI&EIAv}CM! zURIKo#w#W6A|W>2;aRy##L7XnJ%&+0|-{f;N2J~yo zqfxI;e}@EK*hW~lfNLfVob-co&mJNmpieCx|N1Ni;{-)3b%4sBg6wPn9hSZI80nZ6 zGWJ@|HoBGsWXw+U*|HS^C;O$Lz*HQ1a`$ng${Maba6^3313$zU+zl2aG2F7RH~##O zu^*lt!>BG-BgcFpL9R#j&BLC?V7S6kNFzMa^tC-^xX7B|>JS#tWhS$w63E!G!qh+1 zYhHn)9S+>i&&JIa(#ZyO2t!vutSoDMhIEqIinBBL$ALRogp2WH#3U95Z4P3&jNO>3 zi?FCP@ZHp`A!?1Q-_-b5IxV7fva?>)B`VQ-V#PG{`|z&>M&(v0Z379G=&Z z_`aR1^t1#p7W!bgWqOrt4@(FAGd@Y{$>oR1kkORo9ea(cKGL#_tH4c*gOu^5mlz%m zZ2cP0j9C6-)5_g~yr~;R=zVyy()`co`|b_^^5^}9#7lY}ANn)AIHTE}$vszGH5uR> zNUpOdpGbWsU`(RLONZn8YPLi?X`Ll>L%p9%?WErzylOa&adk*@oJo4Ko)y{Rs5t-v z&0r+rmukeu6EJ@tq>XGh-YF z*}F8si-j`C_)FoCQsI}Y1l!k-hTQ^ zg^oNlPU1i3$$#&y#Ekq^40qJEe|2;J6tPnWy;yEdc`*g(2NY&Jr=im>10)d3X020M zw*P%AqI+bB;$eFEJ0=9ai*FS<~{CBmY{KX77kZ8GxQJkv5p1%X=neuC{IjdDO#i)iBD{)W_^WpJ>5*@;dJzW)eS135 zx^f0Q=Qp;R08Qzl87KcTPA!yX>OK~;pV=x_iNTM8^3ut%KN+Dsn1vSHdWDZrB;tlQ zO2p_6i=m@?hl(`J*_6HKcL8vxW0*P?U%9Hk2A8;2ijb_gm=ICU5m>-BCI7m$S1pY4 z2Ln7%$2cyQ(k`oAs(^|h>0F4s8A!f68At!iMW$TT9A--o`&C(Y#ugaeky)B&<^hrQ zYiW9JcLKg9EOR{Sq$F;Cp}C3`Y>XascXfXJCUwnvj}&|G>g*+bKJ7- zndfaMLC?dbh0n`KA(oisx!>FchJTuXXnI&~Y1hf4`^{MRyOPE0J0 zl!6^RImQH-D7$Nb_j@xyPny73#f&U?FlJ_|A2F)sPhW9%TlklRX;jey+bK(&jZgoJeTf^6R@$m!7^)$= zZ4a45$UzDtNV6Y5#dnRG2Zw0uwic1a`Y0d0>#@VWY1q#4%Zy#2Bw4JCll;glPx(U6bY>DydUDdxJH?wz!{s z0?KEK*H7Cn_D+i;gHm;a_aGImZ3}LC3zsXdC-L%1NF`^q{U_!RZ(mqED%A1LnYi{) z`bB~ND0jJBKS-Wb(OMlrtTn(|c5Nj(NV%Rx*D9{jw!eOH%k5>6UHD`_1}0sXUTp1L zmRpjQZP!3e5JJTGx6V)+&OnA?Sq!Z8`H!G++R%Y>7y{6}k;iwXzTRG+DjKyX);m}J zl@c~p`^Pj!LA6g^IW+u&!-?7+%FBR|xy&g7bCK9+))1rY7lU6H(oY>kRXx+o9;BwQ zy>fLKpPO}#N8KXtHs_c>NrNgEfx!=Cu0$T(;L2iYXbWG%Zeu%Uiur0kM7JR7w5OM@iCaU-;35cw z6R4I-2C1~d1AjlUj{Hy@WeqwT;J1MDy8z|FC#j*YjUtOR+^FPue;})mmHScAfb+BQ zLkcrI`#D=6-XkiKl6UFNWf5Gi5MQuTc@zMQq-iOo?YTIu0Evo~V)|aK7&iJJAoTp> zhM-_>3U*G3%Wsv}`-TqoEw{A0L~Eh^bIq&1Mtc6?xaAL^m_`rr@|4riYmqNH&oVoq3$CD zBX5yn?bSXPXD5dZe8M+F{gKI&zDpdvJvtvzW4rr|%w7xoVNxYtiL-}r3w?Z~SH7%v zAP375TG`EZUS``G_qi{48f624Yo+UT+jPytn=KQ>L2f@6nz?!`IfaI#8QF4gfBfFT z0KPcuu34$#yf_fp!g`+v=k^fC6@b}p6r|`2T~S_sR253KUJ?{UU3i}+-n;=wcJvty zym#jN=qTbV$&n4e3cXPPVJ0aX%-mM;kF1awQ>LnO}W?*s<>Q;PvS!i|^X*lR(caeet0$W5NcM}5>6~)Cv(RkwEe(R6hB<_+25jcWt>?Mz zKWvXa+wK?M{8HZeuX^ii;8&pzE0r{)dT%ozNAEie3PBgY+tGzT^vkM=p}u2h5vx*!iaI8r%!R!6DBly4U8_p7(P;9?s6Y zo^|9|hQk~DYV(3_%)(-6MC^urgJS|p@S>x&oDQv%H+9>B)amvRGmWd)j|mO-l)w!4 zNYvRjs$2C0uVF(R*pmZ3YG@<8EzuA|^2kE<6vr>bAI6y?Ka!O#0Wn8guA1&_;xL0u zI!=rRT}H50fBm)=Pu%-nOh8xTo02P7@lx+$=E3ji0iuU+yhL0Be!)JIxIIWa4%v8A zMn6mb7`u+zHTFK<_G)!L|GQ&LEzfuoGQ_+{-oF@hhJWYo?vNezS-K)az$bF|Pft-h zOWu_u$pU5qn2RL4PVSx72V1g#|4o-Yt8!u6hFYF?>i4KK7im5c2uO+XK$2Z&4c9gG zc4=KQbU1pAP8!1X5TMyCG|5hUXuowhRGN;Q%*4+#u1}z{EP%D}?!y0|J0;po?X|)4Ei)p zBt3{&u?xl<&s7)aR&u6wZ=j5iz(n3)?M+7*mjmKBrG92s$WHE<36};CHzaN5y@*!K z02Uqu4=<4N3-tR@s)#+PdAaRj^jn}9TbJ!YPjsF6u4ni3EUfP&u9`ozxexRXKZ`vv?|K*#?GdCujStmM&#LQ7&?79e7H$uMNPd)x+?xm_1H16VGv>F}!Q`7SbMMxK%~IM7T)?jL zf+kiC$T%e?T~3_0HYy-OZ5JVBUL?RddV`$$G0Rn>mC{a|>EgDm?+yB#CGw z2`Yu{BM*i1@0Jgh-)iyI1_&dg1&s$Z!Q(Xqf1X3Egs@-es($PsnDn;k*Y_iR?9Cn4 z6B>Py_?FZMp^+|~x(Zp8BZIPt{np{QWZm#Qiy1BsvaRC!MTMiQOc4evf)u%rqdqN* z5pqa}&;PRR#SShfiYQ|4W)Q=$h)#g`K$sH$jjpLrK#n7RW5u!txkOSs3< zF!FhWyZ$pC6t8o(&F+T|FC&WdhiP6KhBwXlof2c#^i!~xNd>WwSXvb#EXzD(LxkB( z?S1!Ceh(kd4HD_@_4I{=tr$_-vt}?6fT%t^Ie)^~0&y)C(T=&{xnA2~4tQcR9~5ci z(#$af!XG!+Dp13w2e2VdODp{!%FZc96d*vhV_SD@+qP}nwr$(CZQHhO-?2S=H~aGT zXJ4}KuRpr`qdMuNJ5{IVTm9BbmP;p&c^ruh-RCnP%2{2x)NKk#epbVph-V+@}94++^LaU(FE@+@R-%W=1d*ww5gzB@|28zc7*+x*e{MTk*Jx5ZnGvE)Su zu(mjA>>^jrD3|T7e}T{Gc<7_Dl2ego?5e3E=-Dv~-|gJ+M1Gf_-Ez-#XEE)F6#vyO zMcLKk_Yo4=)c{o`YF23~`5q($7-U1R8Oi%I>alZ3Jl}AtQfF(~t4dz(s)+i-H}Uqx zLyZ&yr-zfYDUXM{ULGZz=Bzy$XPA9zXX(% zo^cV7lNpDAev6n9>dz0?kqc~#$UJ6R(EQ(TzwuaRdf> znwc3Rxlec1wk^*`Gh%n~Wda~7vh!^u8>SfUiz;obj&w}${9Rbk($a@fh_(+q(_*I0 z1)y8YOaweK_Yy{0-96aPy2QKdTY^m2-+Ojn8=CUb)SsY%Vnx8r;y;azcX!Mu_ojBn zQE{x(+ZxDyK9(aiOf$)}ly21XkD-@D8pW9>rI8MG^0TwEt}(e?m`H)^p~H%oW^|_A z@$%ytfrmZFam=K)9#Xl%$bR!;tRoyw1Nwxf(-V?L7zvC~!K}iSLL@p&4^6>OK6@SM zEVE1m6w~ z)PM5dF+Q>>nOy4xZgi-|hz7T#<5Z5ZS<{Z$iB%!FUD^LelIkW1wF)5>>c45YzX}p0#e6G zisBgUMVYQlleA?Qf~D)Yht*#(fQsl5R6lIDI(O3?i3!eXNtIt$@I;QgBm=Y18`5>Q zRdqEU&Q?|~TG$f*<1uzl#@--T^2XW44`)}88pOsnesS(@28|RM_{95h@<2c^^vk!8JC1o zoR1{Z^-qIPiBu`RmqGDUJ53)e>gE8i8ADh{he9){RplMkQ}V%Zi)3mG<#G$B6+OY; z@CL${Bc%O4KA8vBhpu4VFKxVm0s{6@hSa7D$rxNhDj29-x%mlnMG8!*QBNd<7tig8 zdvS-iJA9#sayhGH`khMgaEWgL=L`WlsxDKl$Hc{9R_z6f^F@OR$xsjc$g>i444KF6 zz)9_zKYSbDsoHZx?m$vKs6Ur6DORQQ%f<4L#rTML@<+m_-WFZs~@PpcU)RR${*2AAfbg(!C+G`Yx3V_fZIJh z{AY4#jlUl+{3saxTnGdy!re~(qfL=rpo=@4MiZM_Tj1Q*7 z8EKNghuly74t>9V=2QrK?r8p36)v}vgRo03oO#Gg3w$UmEyr>R&tjdv#3YLhzL(LOi2a)~mZqDl{6aQC>b zUBNAGMEZC2%lv2+tz3< zebJTM;S}{2hJ+f2%q_X;iU~wPS|QaM8ycxW5fU(=A#~)<+CQHWV5y@}j8l!e2`+YQ zT$n~lMZ`wI4gBY?AB!$_*+Tir1?pSivlNXhKzI2T&0|GL=*rVhXQE1A#K3Au47IYzt1k?m38~=ObiW_cSp1k z0)j2867v~rZ7{sXh5|#fIb2g?9}~hzwqx$Q`yO>E8FCS_ZD274deem9CU@(}6MFwr zyLq-aBINdlWu+Kq)IQ1BX70z zTgIgF|4WdhD{G6dLQ|dI+H~7SF?CR^T21nYl_13`d|27k+uo}U|EGMT~0To-1NfQqy>V9T=LrD zN`vEM$U9YOQTrrmdzllfLo*Twn1?z$9+>)BlbA{J?d2rI$RBh@t;i!`QRMIU zN~t2r*DfS_y%%%mU6bnijjzZu-NYqm-&o%nK$>pvu0`Dgr!*+)K*8E(p8^#w2$X=yeQy4bLs zfCPs6>>)Cmm{C(qtr&qahXYOtcPc;vbm`oGw(sof$6Ov#J zH+J^0=N#?HL0ls*-Da&=0%hpkR)ev36Ger z54BHTp$9DVd?JU#@7IRy?w$vX0v;WNEN>L^tmvtSWV~Tm;x2~qne56{3{M`#L&92g z8r?k-S|p5xq^R?!Bw#O$;I5J;s!dPl7bOS@N4oU6&@;ZmDdhS%KyZ4MNmOrPhm;d} z@o3M%PS~DairNF46$3Zvx+0cHxROxA?idI>2TIIhw*w1txwJ|HOHTgQQgY8t=h)gV zv>v$>?$rj12Km4PQI>_mjppBi;6S5r)+a!zT#&p#?~r<7KXHT~4pXcp1p$O@qS}lo z(G=%*?p(d!a_TbFzNK_2kk_u?q|$*PEC^TyI3RwCtU&9}Diiw09!1z5Jl!=)JMJ1owOD)=z1 zs~N9M^1Pz5x%$zEM{&d$?i`En=IIm5jN;_U1jqG`Lf?J(wVI6Z)YTE0Y}#32wFM~X zt`;oIQ9skSKRG-Q2~vQ*C-uPxF5E@KM0t69x-lf`!{vSoF)G$ky$K&aI<8=S-P z=xT=C@`HQ#zs865h-3mY8UBFien4+)?roK?dOI4;$f>lLLPCwEa)N{4JEi%(L|W&4 z|(kkUQA~pJl=Dq`?JKh5>5RIAmzMQy?KbdV`M*I>ajWb6H`sTvdE}{6 zKj5O9MV;l;4u57~+~unQ)^?6c_69~KbiyXC7Dgswjs_n8hDLVACh`W3Hcs5! zbpNkqPWTM}x!%Rb)(M}Dg`Ss}PSnEM*~F1f)Y`z=z{`0~-@Mbvh*%LuU_r6FLbS12Ypk<^LS2%Nbgl7&+6aSr|K;|JSxo&WWJgq($Kh%c@Nbs+sus5q3+TOwN?hhPa9dLhX`03PW0 z4=9t%e`)8fBwNSA1ovyYE7GVOX=QE9Ki8w5Z_;R&Ys_?pHj6?m$o?n2S^k%L<1@4W zo2mG}(~OCMjgjO3swQLLWQEWCp9ib>|0$sW#PT=gKEc(1YW{n(jh0j?VuoMg(m;T3}g_z&Jm+K+P`1IAi{4;k(5-1sq#N`V$3q5 z(T!w$lm#X$J3Bh<%t9bU2ac#p&U6xbmWeH<1g;>4Ev2Rda^7$P{PnAlNHoy$S-c_u zCNGf0voe>+W$1OvAtWJSJSVDg=(I%856&^fn_OSOX&bb3U@+S9)#ccsZmecsYuWD( zb13FHE$cjiT;bP(8zxUiK$^#Fwfaf(HmhA z&PCvsLx2`iwJvVknhD$v#t80NDoIU-yeqZ06&lkz-33zB)UB}*o_se7XZAeV-)VYp z056~XPsGgma@M6_AZ4_$vbtEUnZ$yrl}*wdNV>VV4pWANwGx>~UoYKW(QJ3$⎻-tUSZ|(H0NjqB5L}S~$db>mU`T|jN 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 Dw3!jg literal 0 HcmV?d00001 diff --git a/libraries/UTFT_Buttons/License - CC BY-NC-SA 3.0 - Summary.pdf b/libraries/UTFT_Buttons/License - CC BY-NC-SA 3.0 - Summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b35e677e66c08dbb9caccc1c135051624b16b0d7 GIT binary patch literal 109586 zcma&N1y~&0vM7wZyEC}U;1b+DxVyW%YjAfbxI4ie0zm`8-JJlz^(TApbI<00LN;nRWU35l!t(enSHM z9|s~F8{5B;h?*MPo0xtybh34RM=4@&<7#W?3}9#a=wxbQY3yR}1OT$|^D~Lr89RA8 zxB$4`XDTs?TiUpoIx&gc7`mAL34lpTRQm&m5DOPEyhZl}kG+>v#>oWljuhN7t6B$PaP1-U@8w`+4)fc?-r<}&hCoT=1FgGB;*!72^ zY)%6Kg#wYV!)-)_d)L%o6#k_%XBR^!7Y`>>GekIML^uixF$Hl%xZiq2gyZLVYFKGd}nUn#nT>ln8XT_nG?nX7_Ds7UbOfa0j^B7}4YB%BP$x9nH1*=99 zww;6Nea2AzsP|*lA zuaK*Yg_xVEoePtwy|IFWsU4GuxEzxj%m47i!T)~z%LJ8O4DCz|olO4cDhn5r0yQe_ z)Au9;C>=Y2<7@_!sOOlknOf4kb>R3m5VVrXLMVh8~KVVoZg z%}r$uJ?&jxm=x?x|8z5^-zVRF?T;J&uv(G#2{!iT{{{$T{+pES?Ofi);;ap1`90%Z z&wu{>cINkge}Dl1|L_(7@OKz_Klz8d0)T%wh%S?elf8qmy@xh4<2%^*4?8zIBP$Dl ziw(%g&7#XB;biaX0O0u3#pT}J-|+u&^Lxa2C+08Wl}w%OU7d_g{|X`YPRb63#-_jH zi83>Q?N0_plz{-YKYdw5nFYZ1CmIoDRsh?d{wt!)24MfquhRQ8b^!aIf)i2Z0I>hT z@cUU#0Q(fe+9cfS_5baHli z*DLe?SUM{w_j~wfVf!=Sy%YUz#{YKoi7BF(dr$jOf73ln{pYyKT5v6-_2PQWC|m>- zve+9kXmIp54w4SRIF90?LuscHa9cPK!&pJ~)5Ruep5{ITvz1tn(Y-U}bmbITRFgf0 zG90CoUhYK#9cj6`cqIw{7kK_ekg(38uWQ4%HTI{AmT809Iu<;F$CQJy?a_V^Of^bb z-L^@rC%Dr+Jh9VX?;TU0^OGJ54d-2A<8 z2;B|QQtk{HDzqn1|2l%N$3SeKN}6L|ytX>lCkp&?=vp75O?!1hOq`Y^6815^z!Ss)q_v zgD<-+A0cPBA`?onKqv2RWlEjjo?a8CkewH4TI>x2*LtfdQ7#`uUCCS3& zY@+=l2Y-G$mW9$NYAT$DYxyPd+H~|etl9#d42U9<#+2>`4y1hk1l&|1oNiC7xi2i1 z+QJd1fwXIS*m9TAPD?+ghIgP0GWlNov_2ne5S6CDU6<>?8X;JLwpKh@^_qlCM)9yT3*gt0C%*E3eeeNL}SO&|I*gDE0^ z^xF&thzP7s$xM#EZ`B0jibuwt7pmD8-Z}Ew?#ZI0|x>aAbzq-k*4{qULqtFj;TdvHHry&{s62 z^lPVi*DvF8UrYQ0uu9})sPL-Toi)}X0!#5VXId4bKZXnSoFnm-Gd`21d`l`8t;`*g zoFygAI;5RI__&S}+6{6L_QOGQ8O~+1BSDpVD3kV82@2uN$m@t85^~`FxMoLXf=v5I zpyFr58I(=uMtcz6=Z!eUgR`a^E6vX>1|)nEZ&B+yqPBP}2+|^gs0;mwhmjWqn?Sx| zL(!auVn@zSDh%HkID5LH*fbYymDw|^sH>(HNDpSJ98UwJ&3)OAusL-%Z&>z8=1&V& z^1;$p6P^Oh?MN@%J7NZbStdAI&M|b>_s?rT$`$wONSpC@!nacyw(Vk-UR=Vh365&d zkcqYh%nT7Zt?5y)(axVuJQu6;R2w{`30sc%nS4Q*FQpOq%&QVj&liOVXBm5iuMT_h z&TL{gjw-?%RS5wdKK)Ij2Lq|A>ZaQLjZ%-4lBaYx1DnmtX3FUcz!KloaiWH95Ytt; zoW~-Q%g7&i^cP8uTi>Nb%zDVv4DeI}NqXRhW`)Lo>GwkdWodB^Xtq8=f#6H!M-7V=^C=QTv86?t|k zFHnZmW_y^Dx!6FL$l=e+chgYxKJ=UC@nVG$hdmdOVX8omCbJ#bX}2O(*V|0SyW3-O zRNF7Mho3Pb0i9y6H)z!FNK;= z3BEsyk#%j@AwlF*i%M+~WC@=nE6f8Il2-H4$MTa;rZ*qv!WFDZFJ5(1C}yb1cNBy75Nn>gYG|^ zUqqpF)r*GqTYiVYQkyUS+*&XTaSg|oh4&aZ=H*daNs@=*M(0*qYFRi}l$<^g*L4m3 zYMx5reMr&TvEgD?bCa0Ox1?NDD{trb^_6*7{fac2fZ1m%T@ib2JM!{nAvc&jb^VL} zWA~u_<6}3a6Hxb)tex}hfXW(qBFXnUKQVJD$pLQyC#C+VT|-q=@$wNaW1hOW7}qCz57V2y>b9~d(c8I{_N)T1J4$C3 zcZFx{5nbP&H73qU9+9x=3T;Ed>#=BRIqV})sJ!C}3L6WwL@=cS^AK%R>5xPRMoV#R zBvwB^mJ#_F&1dx69r$8~g1tyV?Iltm-GEj}B8eOu9A}SxAU-2$aMc8JuzeV}RY)5x z6CL>~!i}A{si&yjsTjJNR4gVKoT_|I6=mdZs=fNFBw$l-Bh(Sq&z@dv*erqA8`_iE ztz&C7>WTk_Q$*Gq=#`SjND*=vD8p~6pKF$&M@azLw*;AX7@f=82uT<{*`;L!d130) zinMAeoK(JhwMbS|WAabd{X3KSkJio3`JSQw%eoug!DqF_>||g%!pdY@X4mB=%8;ju zk5VANEUh_x$StuE&1v*#ml90kRrc$j;ighgGJ>R*c1YE;|LCV_z5PW!g$bn>2KZ6I zJu}3qW520u{cE0)?Huy!FADdxa;#E&!MRDFecv$-PAs40&RYToarX{aM#OC9h6EjX2O^Pkiub~@&7ytbS2qTIEQj2W{ba4e8m>6NHpZ^=1iOjBCFrjR8zLi1au+XO`(3hHeaSQfcT)&*;iNCRcPPnApk$ObS|`@CHo z<2ZOmX@w^WbNxA2K5ErU8m+*?4t5P(LnoqEctc^}vqVBV4p(w!i~-IYjTM)gG>o4LI*yjTEYJ`_+HXN-I}d=+s zm`5K+Q5ACs(a6z}NPqeFhg}s8#iA<35*77_7?wq*ogb9e({Y_es7)d>+>1iqnmxtmROz>)h;Yh&Qwsu%yT0RC5uWoG@i z72-VKoP5`2T{Kr;`i^s#LW3J<^t^H+ZP{Z?WgXm!J};XapJ_PI&n#L@X{;!V+eV2;8<;f2Ej7w5tXD~? zCq5w)0D;oadF}$MZN?A>W4NZlTBJPCMIj%yrrLO_$X3{y5-G)RGusba(nRFf9+CZ4yb z6yV3HL)a>m#DWU;jirs^g=u`0m-64T9Q(RUMlAu6(K!-8I28%XWo!MSMN8*a404!bzd|(&xBrZkCuO z$<1suf1gX)!#=0^MFLLZ))G>zN|i zT0wyvoRxm%@oB#vFa$O2E-lJ}keYD{7KfeF*W-SvHsBf4{?u7btWx(fy?V+=GwUn4 z_Apxtbzvk$iHAdHo@x)<8h{*`=|E(_MHzW>#0>-$KU_o>vVlW^ORN(4S<+nye9KTj z3n`lfrzr+>2q7q#akbe9Ou`muc?xlgP9KO?Xm!7?L_0 zaNY{_Jqq<3)sZajeARD_sN%M?tx^p`{agpDV^2`RkUdT}PBUw;GYfynBK#wK>e`=7Y+UAyQP9QE! zOTT^EnBFm8_QO!!H-TS4w6UkV;&uA|NpH9kZBvpATXMQ!BSZHiu}#~Q|BOQMA;dwi znfgfE_MNoWOnR3b5;j1OeV!D@DxVOX)@>l>axr7-WpZ|TG$zMP2%Cy*)QZ8YlfaQc z_S)+p#Oa2}gr@w!R$-f(Q9TyvUSD$17*$YdbFASA-uWfCD>nXR3B?^;KNP`X4{qf) zI(`xBPGez6x-x6G$1=Wf#2+oyVqd+{K$(rceDU*n+U*Qd=#C^Z+cYh&VX`riNK0KdyT|Iq>1x&M|Yh-1&E1-GD;D5STLU1T4F zzqq&Y*CV(&``21zNXui}8skcqk-uaJ{y<9bWVYR41dX=2?@$2^_p*h`i@YPj&a2JN zYEhki5vj$}o|MV5bOv*vhPr5P_n*uQ z+@jU|z7bR5@quYQO_K1wH0NjcSNPpT@{AL@yyqX7Oi2B@{-vzhzFm65^N{tb%nFRn z%3Nr{%#*f*-Fz}i;x#cST^$o%P|Zrx-x{A!wRoJRuI6_*d@c2VU9RV|uh#FL4^mfb z3gfzj2?GuzmJ5X=LF$w}3>=ZtN$)j#6jCO41%;y_n2158uERQQW|R%CK&j-3n(VZb_(ErTd3HP)>01=lf*o z%`kMVjfSM5Aj&l8Szj$>+CJE==pKdlD9^5^`b-3S<rV&zLs+Tboy=2^I1$2WEX$K{ncIcX2MW{ zU%MFbF`m`X8TZTrA@m}S`&Iy{eco}#vJdGiqc^=~Qf*PRerNC08H9t+a@9lKk={VE z?V-zJ#I8&!p3~z$S?1r`EB|}$z|IN$cWCbP!H{AhTNi9nN_T8L!Vy%9*C(Id(h*ZH zb!EB*cV0TG6wA%6P6h#qtVlW+moYh=epbk!`Bhoc>A^6X$IngzA2h)$n5V%XYUZXJ zvP=6sWjOR=Buy-HcZX>Z_ye1lR_VW38VIfO6>uQ8 z3P4`UI;4(xUE|c?@epyQt4}%9bE}O6$wmYt+%;=k@jIM-#WrFlz-u1L?MBUD(&rD| zE31Uwi0`c`3rE17o-GK472(4__oj|B&ma9|?9@$((~~Vqml`fJk0fQ|>;09w+%3MG zE@YdIaACIb>;-q@Nq;iW^O$+7nKb!cHL+KX{2Wv$&Ci|)&k>Gc)H+wi)T6O`wu*#A zCps=WELj%MPh!0eW0573#PAXJ2wO|A^5zL;pFf6ym2+sqSRk$#7~&x?9fTL%SH{## zeaLIvCOF{r$uikV1F5^kR$gybd#}D~>~ij(%5Nwz%Vs?vwOLh__ zZ?$16RU|b!&k^mY^e*HcdwrW<^PI2tfbo03>Hli%{85qr&!Lg)Zv}$H_&cNGw;7=U z_HBIpcxoa6QyF*q#d9KEG(=Y(_vLIz1&(jsdul$Fz;2wjDDEYU7MS#L+aMR51#8ju zsToor@40ZdlFwQ=SgZ4R0tlxIEL6WJwto*DPFn~+m*f8UGv8RorQNhHbZe^P5m*#d z_!NVjjF}?G{w8FyN45niHHHi@nKXs+TJ;#XV|(WoQLJo1KU4Ozy3wk9>d8Zdkm8{y zWh;+dt79{mV$?wZ39FLfep}H>gvuxX!+j>Dw``P$z`bq<89Y#tGO-&Xe2)I74w5HA z9Jw}NLbLU1F)9+OL8V2dRv8;OR!u3jMp85!$t4&OrFf zRd8DVIK!|((Fe}1mrZ|`75l8Cft1B)$YsVxkcdX4JY`kkiBaBgY5Z0A+`@RmsG z`#Eh=P$zA-PjX7}>>v0H2_Kzcy5eUS`{~y|0d5keR2OHcXlq#U+_H#1|Ken}`C+Mq{S$w7b;f}iFGafz7C+c6(k?b)k55v>Wobpyr=~W_}PlRf6I6tO$bjTeN zR^xak_fOXNyN&Umtr7UQaQKl3H&^h1WB&5|LjC{;iyX}MSkZ+)ZWTvb#N+2OMk;dR z?niZj=8%i08Y~mi3?p_-m2&0>4~j&Dg*gEd$a3R!^@@{ng@AK+_1wZ3bNI(=jGEmw z)+8K&&Ie7+36vUSf(j{X>_rjTBhO4{7?TPLpIlI_6`X)libzY*w#dr)RhXX#F>GeF zvX}OUQlp8i73e7ZD?KHj{p*6g+K4|(;1^BQV!q)Nh2xm>kJomuANzB)!F=(P+PL6h z?SnYzfyoetRu-1xpTIx%9t^WIB)3ru=fHSc=`M;aib3zZGvMZFz8v?G1@nU2_NLRu zdVL-=*zs-%X>XQ_Vlw@?Re*BE9T~NK=iQ!MBh`6U2w;XaT4=eCRia*Y_ey2suSS#d z-$ZeMhHMU{<^t2eXmjZey^X#|&f~!GQnR5v?54bPtxq96pE$esbHGUOjll+2E)Lz48;7`pw!rkl+CGa=W%X2deBRFs zld`?bOpGs&p?8bbmjlh~ccKC)xGqaG~2Vz;`5#$*Y5uhJh_W~Avi{CPP* z?!9_GT-)ejoBR((#PYWu<^TRnWdU;h-mLKN=PLA6lqBUI_5(A_k++03a5mgXccoJ7 z;ug@BDQL;p*x8fOzd!9l{n4C0DUr8xG6qsA4-jn`r@HGd{dub7AyBp1W@hFFsdYax^c#ylR<7E%L)mOW z4E}YoZ5~Nu_sO=Y$~&DxY14a(Olf6-?<5ym(g8<)v|-b@9g z5|}xtd65SVM!VBwJ@k!9CKp-}2iII}Se#`o$T_lVFyh)|f}%?$nB|qqwB-nIPo4vY z`Z#C>Pbg->h1f)PJLeiYFAl!?H1#hhNOh#Tc18{sl0GdVsNERli?_O1^GPeSi6!#5 z&IFAG?CWINpKV4o*ad`^vouXev$?c{)#eQg{l+`{N)uK~GQM3qb~iDcbZi;ok-DM7 z8}qYvl=qTrhn@nOOX8nr-3h){hHc`F+px`+2eL*DIx4kq1lT zxy3+=g%prIFpSqZM6FTE;|Hk;iCW0{6t8h)TbI$vP33iX% z(?lDm9p9(uKw^MiIG4Ybc@$TXmOGl;WAM$*|;7g58CHHmhq9Y(fcBLQSRO(2|@~*}4Pm#2aROJ3)yz zolFjKbU!Q4Y1`1G2#>gr4$$2n!sZtQLvT_OQ=fEZd(*@b=nY&i?>?+*NY`TE1m%Xr zl3GGjxpdf}-<3+sHdudp#SWH&P0sp&jv8$7)r-kggbyTg#J8|EP@2QTs;4=iIp9Ms zizjGKFWPg{z8aRgWF|$&j8M{?U7aAXy#fx=0%#I=47S}BN&-9+_ zv3^9@Q?On5{hzOIJk;EuaW-wuX|u6-jML-=gYf&+E-Okj%`z(Titc@KA8!z&2pSe4 zrDKB!WQ*xjc}97v2%=~0bQ{0^)TIEkACWnUwpmDq&z)`n-&iE2ynh-4mJhH|MTM**T^U)7$MlV!u+$UEx&deQvqBCUnPz?p*r5v$Hq?VV~MxBzq z)KX;0G;@cBJ#WjW7>+cSNl}?ozR<1)u&GqB^Dm8Q8bN-IsO;xh@+~H97*6xhT8F0v z{T!b>sO)fC9923;!Rf}G6g~RaTyy)$62GnPUuZ#_>QBs!_ zeeI^G#82chlSB7#snlI7+v%r(c@q}X#UMWj@71fYA+z#agK*T46V_B)`>E;3MkS`i zKq#_9E>#|g_zyB0-x#b>3&?15g*WK_W-+M1QXXmIGrlPnnC_7EPoVSlifjQZ)O~y- zI^B0SCgFYdrd@~PEgTJCsmNj9Mp)) zal{smHMidn6+?kboN-aviwtP3A!dtigc!TWCRR}JzG1zyV*>DA2Cf~6rEgc^UuRH9 z?F|AOa*lJ*hIE@XP%kQfv5+?-XD*)#vMVFhE0d_YZ%2O7iQdFz+?_^WyUX%1j|V(C z)TD!yjM=wJFN={WDr`ar#!8RHp^4H>5skIE^T^aJW^*nwc@fU85;4C_1v5KFkbLTn z5lC{AozKz%!xo&ot&6kboa!wS}k2nZ3hx*rB?HhYL})R zM^&b1oJ|!G^PmOCZB;D77FCF&O9qv9yvVm2)h;-uq)M_e-Uk=y=I-!iYI7x|iu_UYM;42wpZ0nwC4D$oyB0++?|RWpu*aSunJ!DA+nL62*I8ZrqIX`zSQU$;f7-> zT*N^=6#x4RU4X6R1ec+3?AIS(nOZ7A@xZb^@aY8KnmO8Auzo-O9`*pWd6a7PdAh3! z%{S4sjxZ)L=*HbWqfh!*#(MLjgQiQcEOMFsy$t_7VDU@a2TI=s_?92NItOw4+|#%_}smQiK9?GxelDWmwFiI89u8# zRzTb+uRsX3RbmWqX&|*vzM@1CMGU$wF)SXD4;oNeiHxl_FwZN$=6hide&fXp@u^ms zDhf-uMQ-?{r*jyd%4POxmC#!pR~-=Tf^2K{#U9Lf$-FKi0w;~{pEAqe+syvs0`5Jt zWc&YTmMO!6G}cJs0UDWJ#lw$6UtLL#*lTz{(H9B*y!^nnO;ZPWLgAF7Ds@B+P;!v3 zLC4IgDV{gRCJQ($$Jj)jx;&b$)}h+M2I>5PQ=_L|b2?=2Tm2~Q`7v>0s}eszsT4#H zA1iLT+ODThwz@GusH86;H;7CjP*mu)fG8^A1D0ACc-OG z(T>xvo#hYdD`K&5UxrIl4@c%FPdyK-h&2oSaN~MB%I<@QK3Q`{ep~!jtXJ+JW+f+c z9w&Prl&V<;zA!vQI4dt@$lkprX5u8dZgku^*OdPWH8q61J)U#GpD-Cz3lvGw>7MSF z+PGAHn6chfi^{A5=8zZ|oR`&bZCY`gn6mdKR>uf^teZ!G#HSHyIG5{uCJX__QViuq zm*6BViIITGq^*FCq*cUWHJiMIjS;sCtXCS@W#52D!gvGX2s)6+@n3=#Jw4xzAL0jN zT~3pE^0V#lk@hsEEt_0F)65@UhSjHsnR}~$JgE8hrA^r3>g8JaGc=!c2(_i&*_cE> zKeAL-1^nl!Utc0Z^!u4$vjNO7$CiS?kA0)Hl22Q=cP*gwXt~gDtpyY`b|K@8jx`++ zU*X=6dDGy*MGx(m?_5DANZmbmwCL&d?siH_UvV8Ur0WdSGipFVMb@%nZV`x)LS|V7 zulgCohm#78G@?lTI?;Vd0t+CyCk*!ro@aDzhGfHa`yk(p0VF5UK7z78L#7N+fE9sp zHf9^B5dvyKtf{y>iT?gC!mGtnuiD}h&8J;I0(^yAmB-{(fswn&vA5Z&JW4uQa{%|e zP^A@ZSdDp=OEOB8WEpCk)CG1?JKWmmu*r1@=pUeJp}!`U;*coW$d1UR4`@*r9{Zx>7XgWe|1 zXS)jCmQqD>#EgKPsfZZ3<{RWdo$_UrGyJ7kl8Nt7i`@r55h(lhFKX71{6aX_pg_rd z?qx#29t7CY-L8|*c~-OKnquZy=w(A^Zha*H-UEvU$| zJew{Xz>TX40Z3z_*@@mFjO*26LQLB|%yAxLnv;usS~B-5PpygP@Ejs#+`V$+ zrA9C)7m%f7+r_{$buPedw7L)aNtz8SiuATMCWwD=Y`Y=w)ytt|HGTNUm+&8M z!Ys+b?w!g%^@k2bOnle90qcj-77u=>I4*Q?iP2R9L`)7ZN1Sx#nHD~Q%z_Eh^jKen zIVCQ%v@(cOWFX zgm-84nOSl?F7#{SThsV~0wg9R*C(enmV6kmWl_fFV={P&_Cavp&e0=J5u9dZp^!bR z$}k&_?E+Zy!VI($kN;$iESyPlSI1f9@QKk&sA+xGFsXQDzpseH> zJ$*<})jiVD=-G5O`Bi3JQTL4r%aS|0=f`D{50D@G+h(4WW;!NxJ~_ew`=d-AYqB~4+( zxGSq=*xmlCj+j+wauG))^lAhs&~uL~dI4SCPNOh0`kdn0`)TU%mG_J z-EtuOO4=NqmX}Dw>z}kuvD#Q2*5XR%fc%1Omn14&TB&6Qd8mEfF{v<>DMV;rDr#7=V-{;gESfKwfvJ8!@P=@SC+5RWLbW0$~uY(aG7%*5=E}}5-j=cDp_UW%0d?aob7$? za-z3goAyPxvG@e7cpz-qajJ>>FZ$0~5;MH!^$1}q!`xi=xnzbu+KcNo^m?kZt_mRH zh-#<_224SdAFvOc)+o-t+%(^tKRzry`d#CS$gNF~+9|Wd<1C(4Eq3(?)uv%QK;**n z>yz8AGcF3MTq$Pp-87WJFVHwO*W)l%$%J)`Ef&=j4ASiNzifQ0Rtu<=;Q8tA)nuti zcT-|-nVumbDZV|vSLk-k3JUM>Drn(ZXXMEz1F}GH=|_qGj7H&%yritP(<>Lu*3Zaj zs7n_Pn;B|zXQ|F=gpJQ!8vaukJRyd+@WFIW<^d-BIOmR@zq6yK^=G4gdvL20=AtLZRqQ$>n>)9APU*yG7hqsx%r9askb|GcY zBoZb<35lPsoX?&xF~_v}mVT&K0}~UiN#*>6=tR^^lCIFL7(x!env!JnFkPPF#m@l$ za~dz&l*U=-Bo+;}t6CCf2c5cH$EqNc@0~E_dLO#JC{;T>VLr)dM7xQOSd@f`#UyExqNp~)IPV9_XciuSDEies6}c$9jwscg zhPJ5JYudZ~)t6&_|JT660AIlYf791S6sXeE9|_~9j3ORG9rhc&c^+Cp7LEvy$udD} z8W|-LR?4ojL5yHf%X(7=pNx7MS}2(?vQ}yCG5eQ(WlPslv96-iejY%pg$OVrzG{sN z>fr68Sp8%=TRUdbFG@Kq0`D=YLsSVF#N5);y_)k$pcZ^ZS~!;J)sFf@6i60*M+B&F zVJ((pE4ArC(Ud1$A)GxJn1I_NX353}@eUO{OESy^NRnmKFTtJ}288}q=jb~H4AZg# z#}*MPE?oYQJ$yV}tUFF_`Uso2NV#wKtmXm9hV%y+ZDi%~cv3}`k zp!+6je0M<`pV6UK{lO2YMc(khC7|cv6YMF9IXQ4~Xi%0Aw`tglGsl`4d>k#@@?6B) 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 g@OZxgFA`CAsDFt1M#e8bpQYW literal 0 HcmV?d00001 diff --git a/libraries/UTFT_Buttons/UTFT_Buttons.cpp b/libraries/UTFT_Buttons/UTFT_Buttons.cpp new file mode 100644 index 0000000..11345e1 --- /dev/null +++ b/libraries/UTFT_Buttons/UTFT_Buttons.cpp @@ -0,0 +1,269 @@ +/* + UTFT_Buttons.cpp - Add-on Library for UTFT: Buttons + Copyright (C)2013 Henning Karlsen. All right reserved + + This library adds simple but easy to use buttons to extend the use + of the UTFT and UTouch libraries. + + You can always find the latest version of the library at + http://electronics.henningkarlsen.com/ + + If you make any modifications or improvements to the code, I would + appreciate that you share the code with me so that I might include + it in the next release. I can be contacted through + http://electronics.henningkarlsen.com/contact.php. + + This library is free software; you can redistribute it and/or + modify it under the terms of the CC BY-NC-SA 3.0 license. + Please see the included documents for further information. +*/ + +#include "UTFT_Buttons.h" +#include +#include + +UTFT_Buttons::UTFT_Buttons(UTFT *ptrUTFT, UTouch *ptrUTouch) +{ + _UTFT = ptrUTFT; + _UTouch = ptrUTouch; + deleteAllButtons(); + _color_text = VGA_WHITE; + _color_text_inactive = VGA_GRAY; + _color_background = VGA_BLUE; + _color_border = VGA_WHITE; + _color_hilite = VGA_RED; + _font_text = NULL; + _font_symbol = NULL; +} + +int UTFT_Buttons::addButton(uint16_t x, uint16_t y, uint16_t width, uint16_t height, char *label, uint16_t flags) +{ + int btcnt = 0; + + while (((buttons[btcnt].flags & BUTTON_UNUSED) == 0) and (btcntgetFont();; + word _current_color = _UTFT->getColor(); + word _current_back = _UTFT->getBackColor(); + + if (buttons[buttonID].flags & BUTTON_BITMAP) + { + _UTFT->drawBitmap(buttons[buttonID].pos_x, buttons[buttonID].pos_y, buttons[buttonID].width, buttons[buttonID].height, buttons[buttonID].data); + if (!(buttons[buttonID].flags & BUTTON_NO_BORDER)) + { + if ((buttons[buttonID].flags & BUTTON_DISABLED)) + _UTFT->setColor(_color_text_inactive); + else + _UTFT->setColor(_color_border); + _UTFT->drawRect(buttons[buttonID].pos_x, buttons[buttonID].pos_y, buttons[buttonID].pos_x+buttons[buttonID].width, buttons[buttonID].pos_y+buttons[buttonID].height); + } + } + else + { + _UTFT->setColor(_color_background); + _UTFT->fillRoundRect(buttons[buttonID].pos_x, buttons[buttonID].pos_y, buttons[buttonID].pos_x+buttons[buttonID].width, buttons[buttonID].pos_y+buttons[buttonID].height); + _UTFT->setColor(_color_border); + _UTFT->drawRoundRect(buttons[buttonID].pos_x, buttons[buttonID].pos_y, buttons[buttonID].pos_x+buttons[buttonID].width, buttons[buttonID].pos_y+buttons[buttonID].height); + if (buttons[buttonID].flags & BUTTON_DISABLED) + _UTFT->setColor(_color_text_inactive); + else + _UTFT->setColor(_color_text); + if (buttons[buttonID].flags & BUTTON_SYMBOL) + { + _UTFT->setFont(_font_symbol); + text_x = (buttons[buttonID].width/2) - (_UTFT->getFontXsize()/2) + buttons[buttonID].pos_x; + text_y = (buttons[buttonID].height/2) - (_UTFT->getFontYsize()/2) + buttons[buttonID].pos_y; + } + else + { + _UTFT->setFont(_font_text); + text_x = ((buttons[buttonID].width/2) - ((strlen(buttons[buttonID].label) * _UTFT->getFontXsize())/2)) + buttons[buttonID].pos_x; + text_y = (buttons[buttonID].height/2) - (_UTFT->getFontYsize()/2) + buttons[buttonID].pos_y; + } + _UTFT->setBackColor(_color_background); + _UTFT->print(buttons[buttonID].label, text_x, text_y); + if ((buttons[buttonID].flags & BUTTON_SYMBOL) and (buttons[buttonID].flags & BUTTON_SYMBOL_REP_3X)) + { + _UTFT->print(buttons[buttonID].label, text_x-_UTFT->getFontXsize(), text_y); + _UTFT->print(buttons[buttonID].label, text_x+_UTFT->getFontXsize(), text_y); + } + } + _UTFT->setFont(_font_current); + _UTFT->setColor(_current_color); + _UTFT->setBackColor(_current_back); +} + +void UTFT_Buttons::enableButton(int buttonID, boolean redraw) +{ + if (!(buttons[buttonID].flags & BUTTON_UNUSED)) + { + buttons[buttonID].flags = buttons[buttonID].flags & ~BUTTON_DISABLED; + if (redraw) + drawButton(buttonID); + } +} + +void UTFT_Buttons::disableButton(int buttonID, boolean redraw) +{ + if (!(buttons[buttonID].flags & BUTTON_UNUSED)) + { + buttons[buttonID].flags = buttons[buttonID].flags | BUTTON_DISABLED; + if (redraw) + drawButton(buttonID); + } +} + +void UTFT_Buttons::relabelButton(int buttonID, char *label, boolean redraw) +{ + if (!(buttons[buttonID].flags & BUTTON_UNUSED)) + { + buttons[buttonID].label = label; + if (redraw) + drawButton(buttonID); + } +} + +boolean UTFT_Buttons::buttonEnabled(int buttonID) +{ + return !(buttons[buttonID].flags & BUTTON_DISABLED); +} + +void UTFT_Buttons::deleteButton(int buttonID) +{ + if (!(buttons[buttonID].flags & BUTTON_UNUSED)) + buttons[buttonID].flags = BUTTON_UNUSED; +} + +void UTFT_Buttons::deleteAllButtons() +{ + for (int i=0;idataAvailable() == true) + { + _UTouch->read(); + int result = -1; + int touch_x = _UTouch->getX(); + int touch_y = _UTouch->getY(); + word _current_color = _UTFT->getColor(); + + for (int i=0;i= (int)buttons[i].pos_x) and (touch_x <= (int)(buttons[i].pos_x + buttons[i].width)) and (touch_y >= (int)buttons[i].pos_y) and (touch_y <= (int)(buttons[i].pos_y + buttons[i].height))) + result = i; + } + } + if (result != -1) + { + if (!(buttons[result].flags & BUTTON_NO_BORDER)) + { + _UTFT->setColor(_color_hilite); + if (buttons[result].flags & BUTTON_BITMAP) + _UTFT->drawRect(buttons[result].pos_x, buttons[result].pos_y, buttons[result].pos_x+buttons[result].width, buttons[result].pos_y+buttons[result].height); + else + _UTFT->drawRoundRect(buttons[result].pos_x, buttons[result].pos_y, buttons[result].pos_x+buttons[result].width, buttons[result].pos_y+buttons[result].height); + } + } + + while (_UTouch->dataAvailable() == true) {}; + + if (result != -1) + { + if (!(buttons[result].flags & BUTTON_NO_BORDER)) + { + _UTFT->setColor(_color_border); + if (buttons[result].flags & BUTTON_BITMAP) + _UTFT->drawRect(buttons[result].pos_x, buttons[result].pos_y, buttons[result].pos_x+buttons[result].width, buttons[result].pos_y+buttons[result].height); + else + _UTFT->drawRoundRect(buttons[result].pos_x, buttons[result].pos_y, buttons[result].pos_x+buttons[result].width, buttons[result].pos_y+buttons[result].height); + } + } + + _UTFT->setColor(_current_color); + return result; + } + else + return -1; +} + +void UTFT_Buttons::setTextFont(uint8_t* font) +{ + _font_text = font; +} + +void UTFT_Buttons::setSymbolFont(uint8_t* font) +{ + _font_symbol = font; +} + +void UTFT_Buttons::setButtonColors(word atxt, word iatxt, word brd, word brdhi, word back) +{ + _color_text = atxt; + _color_text_inactive = iatxt; + _color_background = back; + _color_border = brd; + _color_hilite = brdhi; +} diff --git a/libraries/UTFT_Buttons/UTFT_Buttons.h b/libraries/UTFT_Buttons/UTFT_Buttons.h new file mode 100644 index 0000000..678c847 --- /dev/null +++ b/libraries/UTFT_Buttons/UTFT_Buttons.h @@ -0,0 +1,84 @@ +/* + UTFT_Buttons.h - Add-on Library for UTFT: Buttons + Copyright (C)2013 Henning Karlsen. All right reserved + + This library adds simple but easy to use buttons to extend the use + of the UTFT and UTouch libraries. + + You can always find the latest version of the library at + http://electronics.henningkarlsen.com/ + + If you make any modifications or improvements to the code, I would + appreciate that you share the code with me so that I might include + it in the next release. I can be contacted through + http://electronics.henningkarlsen.com/contact.php. + + This library is free software; you can redistribute it and/or + modify it under the terms of the CC BY-NC-SA 3.0 license. + Please see the included documents for further information. +*/ + +#ifndef UTFT_Buttons_h +#define UTFT_Buttons_h + +#if defined(__AVR__) + #include "Arduino.h" +#elif defined(__PIC32MX__) + #include "WProgram.h" +#elif defined(__arm__) + #include "Arduino.h" +#endif + +#include +#include +#if ((!defined(UTFT_VERSION)) || (UTFT_VERSION<241)) + #error : You will need UTFT v2.41 or higher to use this add-on library... +#endif + +#define MAX_BUTTONS 20 // Maximum number of buttons available at one time + +// Define presets for button status +#define BUTTON_DISABLED 0x0001 +#define BUTTON_SYMBOL 0x0002 +#define BUTTON_SYMBOL_REP_3X 0x0004 +#define BUTTON_BITMAP 0x0008 +#define BUTTON_NO_BORDER 0x0010 +#define BUTTON_UNUSED 0x8000 + +typedef struct +{ + uint16_t pos_x, pos_y, width, height; + uint16_t flags; + char *label; + bitmapdatatype data; +} button_type; + +class UTFT_Buttons +{ + public: + UTFT_Buttons(UTFT *ptrUTFT, UTouch *ptrUTouch); + + int addButton(uint16_t x, uint16_t y, uint16_t width, uint16_t height, char *label, uint16_t flags=0); + int addButton(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bitmapdatatype data, uint16_t flags=0); + void drawButtons(); + void drawButton(int buttonID); + void enableButton(int buttonID, boolean redraw=false); + void disableButton(int buttonID, boolean redraw=false); + void relabelButton(int buttonID, char *label, boolean redraw=false); + boolean buttonEnabled(int buttonID); + void deleteButton(int buttonID); + void deleteAllButtons(); + int checkButtons(); + void setTextFont(uint8_t* font); + void setSymbolFont(uint8_t* font); + void setButtonColors(word atxt, word iatxt, word brd, word brdhi, word back); + + protected: + UTFT *_UTFT; + UTouch *_UTouch; + button_type buttons[MAX_BUTTONS]; + word _color_text, _color_text_inactive, _color_background, _color_border, _color_hilite; + uint8_t *_font_text, *_font_symbol; +}; + +#endif diff --git a/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/UTFT_Buttons_Bitmap_Demo.ino b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/UTFT_Buttons_Bitmap_Demo.ino new file mode 100644 index 0000000..f778f0d --- /dev/null +++ b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/UTFT_Buttons_Bitmap_Demo.ino @@ -0,0 +1,130 @@ +// UTFT_Buttons_Bitmap_Demo (C)2013 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// A small demo to demonstrate the use of some of the +// functions of the UTFT_Buttons add-on library. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels, but should work on larger screens as +// well. +// +// This demo will not work on Arduino 2009/Uno/Leonardo +// due to the size of the images. +// +// This program requires both the UTFT and UTouch libraries +// in addition to the UTFT_Buttons add-on library. +// + +// This code block is only needed to support multiple +// MCU architectures in a single sketch. +#if defined(__AVR__) + #define imagedatatype unsigned int +#elif defined(__PIC32MX__) + #define imagedatatype unsigned short +#elif defined(__arm__) + #define imagedatatype unsigned short +#endif +// End of multi-architecture block + +#include +#include +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; + +// Declare which bitmaps we will be using +extern imagedatatype cat[]; +extern imagedatatype dog[]; +extern imagedatatype bird[]; +extern imagedatatype monkey[]; + +// Set up UTFT... +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino 2009/Uno/Leonardo shield : NOT SUPPORTED DUE TO LACK OF MEMORY +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Standard chipKit Uno32/uC32 : ,34,35,36,37 +// Standard chipKit Max32 : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +// Set up UTouch... +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino 2009/Uno/Leonardo shield : NOT SUPPORTED DUE TO LACK OF MEMORY +// Standard Arduino Mega/Due shield : 6,5,4,3,2 +// CTE TFT LCD/SD Shield for Arduino Due : 6,5,4,3,2 +// Standard chipKit Uno32/uC32 : 20,21,22,23,24 +// Standard chipKit Max32 : 62,63,64,65,66 +// AquaLEDSource All in One Super Screw Shield : 62,63,64,65,66 +UTouch myTouch(6,5,4,3,2); + +// Finally we set up UTFT_Buttons :) +UTFT_Buttons myButtons(&myGLCD, &myTouch); + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(BigFont); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_MEDIUM); + + myButtons.setTextFont(BigFont); +} + +void loop() +{ + int but1, but2, but3, but4, but5, pressed_button; + + but1 = myButtons.addButton( 10, 10, 80, 60, cat); + but2 = myButtons.addButton( 120, 10, 80, 60, dog); + but3 = myButtons.addButton( 10, 80, 80, 60, bird); + but4 = myButtons.addButton( 120, 80, 80, 60, monkey, BUTTON_NO_BORDER); + but5 = myButtons.addButton( 10, 150, 190, 30, "Disable Dog"); + myButtons.drawButtons(); + + myGLCD.print("You pressed:", 10, 200); + myGLCD.setColor(VGA_BLACK); + myGLCD.setBackColor(VGA_WHITE); + myGLCD.print("None ", 10, 220); + + while(1) + { + if (myTouch.dataAvailable() == true) + { + pressed_button = myButtons.checkButtons(); + + if (pressed_button==but5) + if (myButtons.buttonEnabled(but2)) + { + myButtons.disableButton(but2); + myButtons.relabelButton(but5, "Enable Dog", true); + myButtons.drawButton(but2); + } + else + { + myButtons.enableButton(but2); + myButtons.relabelButton(but5, "Disable Dog", true); + myButtons.drawButton(but2); + } + + if (pressed_button==but1) + myGLCD.print("Cat ", 10, 220); + if (pressed_button==but2) + myGLCD.print("Dog ", 10, 220); + if (pressed_button==but3) + myGLCD.print("Bird ", 10, 220); + if (pressed_button==but4) + myGLCD.print("Monkey ", 10, 220); + if (pressed_button==-1) + myGLCD.print("None ", 10, 220); + } + } +} + diff --git a/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/bird.c b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/bird.c new file mode 100644 index 0000000..ec21c18 --- /dev/null +++ b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/bird.c @@ -0,0 +1,314 @@ +// Generated by : ImageConverter 565 v1.2 +// Dimensions : 80x60 pixels +// Size : 9 600 Bytes + +#if defined(__AVR__) + #include +#elif defined(__PIC32MX__) + #define PROGMEM +#elif defined(__arm__) + #define PROGMEM +#endif + +const unsigned short bird[0x12C0] PROGMEM ={ +0x71A0, 0x6980, 0x7A20, 0xAB61, 0xDC82, 0xECC1, 0xF4C0, 0xECE1, 0xED03, 0xD4C5, 0x9BA5, 0x7AC2, 0x9320, 0xBC22, 0xC421, 0xBBE0, // 0x0010 (16) +0xB3E0, 0xA3A1, 0x7A81, 0x5180, 0x4140, 0x51A1, 0x6A82, 0x8303, 0x7281, 0x61A0, 0x5980, 0x5961, 0x5101, 0x5901, 0x5921, 0x6140, // 0x0020 (32) +0x69E0, 0x92E1, 0xAB42, 0xAB00, 0xAB60, 0xBBE3, 0xAB62, 0x8A40, 0x8A20, 0xB382, 0xE504, 0xF583, 0xF561, 0xD4A0, 0xABA0, 0xA361, // 0x0030 (48) +0xBBA1, 0xC381, 0xB320, 0xA320, 0x9B41, 0x8B01, 0x82E1, 0x7AA2, 0x7264, 0x6A43, 0x6A20, 0x82A0, 0xAB80, 0xBBE1, 0xAB61, 0x8A80, // 0x0040 (64) +0x71E0, 0x61C1, 0x6A01, 0x7262, 0x6A81, 0x62C1, 0x62E1, 0x6B02, 0x7322, 0x6B22, 0x62C1, 0x5260, 0x4A61, 0x4A62, 0x4A42, 0x4A02, // 0x0050 (80) +0x6160, 0x6160, 0x71E0, 0x9B21, 0xD441, 0xE4A1, 0xECC1, 0xE4C2, 0xE4E3, 0xD4C5, 0xAC06, 0x8B23, 0xA381, 0xC442, 0xC421, 0xBBA0, // 0x0060 (96) +0xBB80, 0xAB40, 0x7AA1, 0x51C0, 0x3140, 0x4161, 0x5A21, 0x7262, 0x7241, 0x61A0, 0x5940, 0x5120, 0x48E0, 0x48E0, 0x5120, 0x61A0, // 0x0070 (112) +0x7A60, 0x9B20, 0xAB41, 0x9AE0, 0xAB60, 0xC443, 0xB3E2, 0x8AC0, 0x92A0, 0xBBC2, 0xE503, 0xF563, 0xE541, 0xCC80, 0x9BA0, 0x9B60, // 0x0080 (128) +0xAB80, 0xB380, 0xAB40, 0x9B21, 0x8B01, 0x82E1, 0x7AC2, 0x7AC3, 0x7263, 0x7262, 0x7240, 0x8AA0, 0xB360, 0xCC22, 0xCC02, 0xB341, // 0x0090 (144) +0x9A40, 0x89A0, 0x79C0, 0x71E0, 0x6241, 0x62A1, 0x6301, 0x6321, 0x6B41, 0x6B41, 0x6301, 0x5281, 0x4241, 0x4A43, 0x4A24, 0x4A04, // 0x00A0 (160) +0x59A1, 0x59A1, 0x6A00, 0x9301, 0xC421, 0xD481, 0xD461, 0xD462, 0xD4A4, 0xCCC5, 0xB445, 0x9B62, 0xABA1, 0xC483, 0xC441, 0xA360, // 0x00B0 (176) +0x92C0, 0x9B01, 0x82E2, 0x5A20, 0x3980, 0x3961, 0x49C3, 0x5A05, 0x6A24, 0x61E2, 0x59A2, 0x5141, 0x4920, 0x4920, 0x5160, 0x69C0, // 0x00C0 (192) +0x8AA0, 0x9B20, 0x9B00, 0x92A0, 0xAB80, 0xC483, 0xB423, 0x9320, 0x8AE0, 0xB3C2, 0xDCE3, 0xE523, 0xD4E2, 0xB441, 0x8BA0, 0x8340, // 0x00D0 (208) +0xA380, 0xB3C1, 0xB3C2, 0x9B42, 0x82E1, 0x72A2, 0x7AC2, 0x7AE3, 0x7AA3, 0x7A82, 0x7A81, 0x8AA0, 0xAB20, 0xD401, 0xDC61, 0xD3C0, // 0x00E0 (224) +0xC280, 0xA9A0, 0x9140, 0x8180, 0x71E1, 0x6A81, 0x62E1, 0x6320, 0x6320, 0x6B41, 0x6302, 0x5261, 0x4201, 0x4A03, 0x4A25, 0x4A05, // 0x00F0 (240) +0x59E3, 0x59C2, 0x61E1, 0x82A1, 0xABC1, 0xBC01, 0xBBE1, 0xBBE3, 0xC424, 0xC465, 0xBC25, 0xA361, 0xA360, 0xBC44, 0xB422, 0x8B00, // 0x0100 (256) +0x7280, 0x7282, 0x7A83, 0x61E3, 0x5162, 0x4121, 0x4160, 0x51E2, 0x6221, 0x6A02, 0x61A2, 0x5122, 0x4902, 0x5101, 0x5980, 0x7200, // 0x0110 (272) +0x8A81, 0x9281, 0x8A60, 0x92A0, 0xB3C1, 0xC483, 0xAC03, 0x8B21, 0x8AE0, 0xABC3, 0xD4A4, 0xDCC4, 0xBC43, 0x9381, 0x7B21, 0x7B00, // 0x0120 (288) +0x9340, 0xABC1, 0xB3E2, 0x9B41, 0x7AA1, 0x6A82, 0x72A3, 0x7AC4, 0x7AA3, 0x7A82, 0x7A81, 0x8280, 0x9AC0, 0xBBA1, 0xDC42, 0xDBC1, // 0x0130 (304) +0xCA80, 0xB180, 0x9900, 0x9141, 0x89C2, 0x7A42, 0x6AA0, 0x62A0, 0x6300, 0x6301, 0x62C2, 0x5242, 0x49E2, 0x4A03, 0x5A24, 0x5A25, // 0x0140 (320) +0x59E1, 0x51A0, 0x59C0, 0x7280, 0x9B60, 0xA3A0, 0xAB81, 0xABA3, 0xABC4, 0xABE4, 0xAC04, 0xA382, 0x9321, 0x9BA3, 0x9362, 0x6A80, // 0x0150 (336) +0x51C0, 0x5A01, 0x6222, 0x59E3, 0x49A2, 0x3121, 0x3141, 0x5203, 0x6284, 0x6223, 0x51C2, 0x4181, 0x4981, 0x4960, 0x5940, 0x79A1, // 0x0160 (352) +0x81E1, 0x8A21, 0x8A40, 0x9AE0, 0xBC01, 0xBC42, 0x9BA2, 0x8B21, 0x9322, 0xB3E4, 0xD4A4, 0xCC83, 0xAC02, 0x8B41, 0x7AC2, 0x7281, // 0x0170 (368) +0x82C0, 0xA360, 0xB3C1, 0x9B40, 0x7AA0, 0x7261, 0x7A83, 0x82C4, 0x8283, 0x7A62, 0x7281, 0x7AA1, 0x8AA0, 0xA321, 0xC3A2, 0xCB82, // 0x0180 (384) +0xB261, 0xA160, 0xA100, 0xA121, 0x99A2, 0x9222, 0x8261, 0x6A60, 0x62A1, 0x5A82, 0x5242, 0x5202, 0x5202, 0x6202, 0x6A23, 0x7223, // 0x0190 (400) +0x69E0, 0x61E0, 0x6A40, 0x7AE0, 0x8B81, 0x9380, 0x9B61, 0xA383, 0x9B63, 0x9323, 0x9B63, 0x9363, 0x82E1, 0x7281, 0x6241, 0x51E0, // 0x01A0 (416) +0x41C0, 0x39A1, 0x4A03, 0x49E4, 0x39A3, 0x4289, 0x5452, 0x5538, 0x4D9C, 0x3CF9, 0x3C33, 0x3B4D, 0x4286, 0x41A1, 0x4140, 0x5960, // 0x01B0 (432) +0x71C0, 0x9261, 0x9AE0, 0xAB40, 0xBC01, 0xB401, 0x9361, 0x8302, 0x9364, 0xAC25, 0xC483, 0xC4A2, 0xBC62, 0xABC2, 0x9342, 0x82A1, // 0x01C0 (448) +0x8AA0, 0x9B20, 0xB381, 0x9B20, 0x7A80, 0x7260, 0x8282, 0x8AC4, 0x8A83, 0x8262, 0x7281, 0x7A81, 0x7A80, 0x92C0, 0xB322, 0xBB22, // 0x01D0 (464) +0xAA41, 0x9980, 0xA121, 0xA942, 0xA982, 0xA202, 0x8A41, 0x7241, 0x6A42, 0x5A22, 0x51E2, 0x5A02, 0x6A22, 0x7242, 0x8221, 0x8A22, // 0x01E0 (480) +0x8A80, 0x92C0, 0x8B60, 0x93C1, 0x8BA0, 0x8B60, 0x9B60, 0xABC3, 0x9383, 0x7AC1, 0x7AC2, 0x7AE3, 0x6A81, 0x5200, 0x49A1, 0x4182, // 0x01F0 (496) +0x3962, 0x39A3, 0x3182, 0x3248, 0x4C55, 0x3D1C, 0x149E, 0x047F, 0x0C5D, 0x043C, 0x04BE, 0x153E, 0x255D, 0x3497, 0x4B0B, 0x51C2, // 0x0200 (512) +0x82A2, 0xA342, 0xB361, 0xAB60, 0xABA1, 0x9B41, 0x7AC2, 0x72A3, 0x8B66, 0x9BE6, 0xA403, 0xB422, 0xC463, 0xC463, 0xB402, 0xA361, // 0x0210 (528) +0x9B20, 0xA361, 0xB382, 0x9AE0, 0x7A40, 0x7A20, 0x8280, 0x9AE2, 0x9AC2, 0x9281, 0x7A61, 0x7A81, 0x7A80, 0x8AA0, 0xAAE2, 0xBB02, // 0x0220 (544) +0xB281, 0xA9E0, 0xB182, 0xB162, 0xA982, 0xA203, 0x8A42, 0x7221, 0x6222, 0x5A22, 0x6202, 0x6A21, 0x7A61, 0x8A61, 0x9241, 0x9221, // 0x0230 (560) +0xB360, 0xB3E1, 0xB462, 0xA441, 0x83A0, 0x8360, 0xA3E1, 0xBC64, 0xA3E4, 0x7AE1, 0x6A61, 0x6A82, 0x5A41, 0x49E1, 0x4182, 0x4163, // 0x0240 (576) +0x4142, 0x3143, 0x322A, 0x43B5, 0x2C3B, 0x0BDC, 0x03BD, 0x039D, 0x03BC, 0x03DC, 0x0C3E, 0x043E, 0x0C7E, 0x253F, 0x359D, 0x5515, // 0x0250 (592) +0x8C29, 0xBC25, 0xB3A2, 0xA300, 0x9302, 0x7A62, 0x6A02, 0x6A64, 0x8368, 0x8BA7, 0x8343, 0x9341, 0xB3E2, 0xC443, 0xC462, 0xB401, // 0x0260 (608) +0xB3E2, 0xB3C3, 0xBBA3, 0xA2E1, 0x7A20, 0x7A20, 0x92A0, 0xAB42, 0xBB63, 0xB323, 0x8AC2, 0x7A61, 0x7A60, 0x8A80, 0xAAC1, 0xC302, // 0x0270 (624) +0xCB02, 0xC261, 0xC1C2, 0xB162, 0xA181, 0x99E2, 0x8242, 0x6A22, 0x5A22, 0x6243, 0x6A62, 0x7A61, 0x8A80, 0x9281, 0x9A42, 0x9A02, // 0x0280 (640) +0xCC40, 0xD4A1, 0xBC61, 0x9BC0, 0x8380, 0x8380, 0xAC41, 0xD505, 0xC4A3, 0x9361, 0x6261, 0x5A22, 0x6222, 0x59E2, 0x49C3, 0x41E3, // 0x0290 (656) +0x39A0, 0x2A06, 0x33F7, 0x139B, 0x02FA, 0x0B1B, 0x0ADB, 0x0AFB, 0x0AD9, 0x02D9, 0x0B9C, 0x03DC, 0x047C, 0x04BC, 0x04BF, 0x155F, // 0x02A0 (672) +0x2DDE, 0x5DD9, 0x7C8F, 0x7B25, 0x7261, 0x6A20, 0x51E2, 0x62A4, 0x8BA6, 0x9BE6, 0x93A4, 0x8B41, 0x9B80, 0xB3E0, 0xB402, 0xABE3, // 0x02B0 (688) +0xA3C4, 0xABE5, 0xA3A3, 0x92E0, 0x8220, 0x8A00, 0xAAE0, 0xCBE2, 0xD442, 0xB3A1, 0x8B00, 0x82E1, 0x92E1, 0xA301, 0xAB01, 0xC321, // 0x02C0 (704) +0xCB62, 0xCB02, 0xC262, 0xA9C1, 0x99C1, 0x91C2, 0x79E3, 0x69C2, 0x71E1, 0x7A41, 0x82A0, 0x8280, 0x8A80, 0x92A2, 0x9261, 0x8A00, // 0x02D0 (720) +0xDCA0, 0xD4A1, 0xAC00, 0x8B60, 0x7B20, 0x7B40, 0xAC21, 0xDD45, 0xD504, 0xA381, 0x7281, 0x6A63, 0x6A43, 0x6243, 0x6264, 0x4A04, // 0x02E0 (736) +0x4226, 0x53B1, 0x2359, 0x029A, 0x0258, 0x0216, 0x0215, 0x0215, 0x0277, 0x02B8, 0x031B, 0x0B9D, 0x039C, 0x041D, 0x0C5D, 0x045C, // 0x02F0 (752) +0x0CBD, 0x151D, 0x2DBC, 0x4DB8, 0x53AB, 0x4203, 0x4A24, 0x7B06, 0xAC07, 0xC465, 0xBC41, 0xB420, 0xA3E1, 0x9BC2, 0x9BC3, 0x9342, // 0x0300 (768) +0x9343, 0x9B43, 0x9321, 0x8AA0, 0x7A40, 0x8A60, 0xB360, 0xD442, 0xDC82, 0xBBC0, 0x9B20, 0x9B21, 0xB3A2, 0xBBA2, 0xBB61, 0xBB40, // 0x0310 (784) +0xCB80, 0xCB61, 0xC301, 0xB261, 0xA201, 0x89E2, 0x71E2, 0x69C2, 0x71E1, 0x8262, 0x82C0, 0x7AA0, 0x7A60, 0x8261, 0x8A21, 0x81C0, // 0x0320 (800) +0xE4C1, 0xCC61, 0x9360, 0x72C0, 0x6AC0, 0x7B00, 0xAC00, 0xDD24, 0xDD04, 0xB3E1, 0x8B01, 0x7AC3, 0x7AA4, 0x7AA4, 0x7284, 0x6286, // 0x0330 (816) +0x532C, 0x4BD4, 0x12B7, 0x0237, 0x0192, 0x0191, 0x01B2, 0x0214, 0x0296, 0x1319, 0x0B19, 0x0B7A, 0x0B7A, 0x0B9A, 0x039A, 0x03FB, // 0x0340 (832) +0x047D, 0x04FE, 0x04FD, 0x157D, 0x3E1E, 0x4D16, 0x5329, 0x9386, 0xCC66, 0xDCA4, 0xD4A1, 0xD4C0, 0xC460, 0xB3E0, 0xA3A1, 0x9301, // 0x0350 (848) +0x8AC2, 0x8AE2, 0x9301, 0x82A0, 0x7A60, 0x92E0, 0xC401, 0xDC81, 0xDC81, 0xBBA0, 0xA300, 0xAB40, 0xC422, 0xD422, 0xC381, 0xBB20, // 0x0360 (864) +0xC380, 0xCBA0, 0xCBA2, 0xBB42, 0xAAE1, 0x9A81, 0x8241, 0x7201, 0x7A21, 0x8282, 0x7AC1, 0x72A0, 0x7260, 0x7240, 0x7A21, 0x79E0, // 0x0370 (880) +0xE482, 0xBBE1, 0x7AC0, 0x5A40, 0x6260, 0x7AE0, 0xABC0, 0xD4C3, 0xDCE3, 0xBC01, 0x9B41, 0x8AE2, 0x8B04, 0x82E4, 0x7263, 0x6286, // 0x0380 (896) +0x5B6E, 0x2AD1, 0x0A33, 0x01D3, 0x0191, 0x012F, 0x0191, 0x01B2, 0x1235, 0x0235, 0x0298, 0x02F9, 0x033B, 0x03DD, 0x03FD, 0x041D, // 0x0390 (912) +0x0C7C, 0x049C, 0x049D, 0x04FE, 0x0D5E, 0x35BD, 0x5599, 0x7CD0, 0xC4C7, 0xDC61, 0xE4A1, 0xED01, 0xE4E0, 0xCC60, 0xABC0, 0x9320, // 0x03A0 (928) +0x8AC2, 0x9B03, 0xA363, 0xA321, 0x9AE0, 0xAB60, 0xD460, 0xE4C0, 0xD460, 0xB360, 0x9AC0, 0xA320, 0xC401, 0xCC01, 0xBB41, 0xB2E0, // 0x03B0 (944) +0xBB21, 0xC381, 0xC3C2, 0xC3C1, 0xBBC1, 0xB3A1, 0x9B41, 0x92E1, 0x82A1, 0x82A1, 0x72C1, 0x6AC1, 0x6AA0, 0x6A80, 0x7280, 0x7A60, // 0x03C0 (960) +0xD442, 0xAB40, 0x6A40, 0x51E0, 0x6240, 0x72A0, 0x9B40, 0xC422, 0xD4A3, 0xC422, 0x9B21, 0x8AE2, 0x82E3, 0x7AC4, 0x7AE4, 0x5A64, // 0x03D0 (976) +0x7C2E, 0x5BF0, 0x018A, 0x012B, 0x00C9, 0x00C8, 0x00E6, 0x1168, 0x0149, 0x01CE, 0x02B5, 0x0319, 0x039B, 0x0C5D, 0x0C7C, 0x043B, // 0x03E0 (992) +0x047C, 0x049D, 0x049D, 0x049D, 0x0CDD, 0x049B, 0x0C9A, 0x55DA, 0x8D6F, 0xB4C7, 0xDCA2, 0xF4C2, 0xECC2, 0xD482, 0xAC22, 0x9361, // 0x03F0 (1008) +0x92E2, 0xAB43, 0xC3E3, 0xCBE2, 0xC3A0, 0xCBE0, 0xE480, 0xECC0, 0xD460, 0xB380, 0x92C0, 0x9AE0, 0xB380, 0xC381, 0xB300, 0xB2C1, // 0x0400 (1024) +0xBAC2, 0xC343, 0xC3A2, 0xBBC1, 0xC401, 0xCC41, 0xBC21, 0xABC1, 0x9B40, 0x8300, 0x7300, 0x6B00, 0x6AE0, 0x6AA0, 0x6AC0, 0x72E1, // 0x0410 (1040) +0xCC02, 0xA300, 0x7220, 0x61E0, 0x6240, 0x6A40, 0x8280, 0xAB81, 0xC423, 0xAB60, 0x92E1, 0x8AA2, 0x9345, 0x7AE5, 0x6285, 0x8C0D, // 0x0420 (1056) +0xAD75, 0x530D, 0x0083, 0x0042, 0x1083, 0x1082, 0x18E2, 0x0061, 0x00E6, 0x124F, 0x0AF6, 0x039B, 0x0BFC, 0x03FC, 0x03FB, 0x0C1B, // 0x0430 (1072) +0x0C3B, 0x0C7C, 0x047B, 0x049C, 0x0C9B, 0x1CFC, 0x153D, 0x1D1B, 0x3D7A, 0x7574, 0xACE9, 0xDCC4, 0xF4C2, 0xEC61, 0xCC62, 0xAB80, // 0x0440 (1088) +0xA301, 0xB382, 0xD403, 0xE442, 0xE441, 0xEC81, 0xF4C0, 0xECC1, 0xDC81, 0xB3C0, 0x9B00, 0x92C0, 0xA300, 0xB321, 0xB2E1, 0xB2C1, // 0x0450 (1104) +0xBB23, 0xC3A4, 0xC3C2, 0xBBA0, 0xC3E1, 0xD462, 0xD482, 0xC441, 0xABE0, 0x9BA0, 0x8B80, 0x83A0, 0x8360, 0x7300, 0x72E0, 0x6AC1, // 0x0460 (1120) +0xCC22, 0xB380, 0x8AA0, 0x7220, 0x6A20, 0x6A00, 0x7A20, 0xA301, 0xAB61, 0xA301, 0x8A81, 0x8AA3, 0x8283, 0x7AC6, 0x840D, 0x8450, // 0x0470 (1136) +0x52AB, 0x7C30, 0x846F, 0x4AC8, 0x10C0, 0x10E2, 0x0904, 0x0147, 0x11ED, 0x0A71, 0x02F4, 0x03B8, 0x03D9, 0x0378, 0x0BFA, 0x0C1A, // 0x0480 (1152) +0x147B, 0x0C5A, 0x0C7A, 0x0C5A, 0x0439, 0x047A, 0x0499, 0x0CBA, 0x1CDA, 0x455B, 0x5D97, 0x9591, 0xD527, 0xECA1, 0xDC82, 0xC3E1, // 0x0490 (1168) +0xBBC1, 0xCC02, 0xDC42, 0xEC82, 0xECA1, 0xEC81, 0xECA1, 0xECC1, 0xE4A1, 0xCC40, 0xB3A0, 0xA300, 0xAAE0, 0xB2E1, 0xB2C2, 0xBB23, // 0x04A0 (1184) +0xC3C4, 0xCC45, 0xCC83, 0xC401, 0xCBC1, 0xD422, 0xD482, 0xCC82, 0xBC40, 0xAC00, 0x9BE0, 0xA400, 0xA3E0, 0x9BA0, 0x8341, 0x72E0, // 0x04B0 (1200) +0xDC82, 0xCC21, 0xAB40, 0x8240, 0x6A00, 0x6A00, 0x8240, 0xA302, 0xAB63, 0x92A0, 0x8A42, 0x8243, 0x8A84, 0x8308, 0x73AD, 0x7C72, // 0x04C0 (1216) +0x9D35, 0x9534, 0x9574, 0x7450, 0x0966, 0x0168, 0x01CD, 0x0251, 0x0274, 0x0AF6, 0x0B98, 0x0399, 0x141C, 0x039A, 0x03FA, 0x0C7C, // 0x04D0 (1232) +0x047C, 0x049C, 0x04BD, 0x049C, 0x047A, 0x14DB, 0x14DC, 0x0C9A, 0x14B9, 0x253A, 0x3D9C, 0x55BA, 0x7DB6, 0x9D4F, 0xCCC5, 0xE481, // 0x04E0 (1248) +0xDC82, 0xDC82, 0xECA2, 0xECA2, 0xE4A1, 0xE461, 0xE461, 0xECA1, 0xECC1, 0xE4A0, 0xD440, 0xBB80, 0xBB00, 0xBAE2, 0xB303, 0xBB84, // 0x04F0 (1264) +0xC405, 0xD4C6, 0xDD25, 0xD482, 0xCC01, 0xD401, 0xD461, 0xD482, 0xC462, 0xB401, 0xABC1, 0xABC1, 0xBC02, 0xBC22, 0x9BC1, 0x8340, // 0x0500 (1280) +0xE4A1, 0xDC61, 0xBBC1, 0x92C0, 0x71E0, 0x71E0, 0x9260, 0xAB02, 0xAB42, 0x9AE0, 0x9280, 0x9AA0, 0x92C2, 0x8AA3, 0x82A6, 0x72C9, // 0x0510 (1296) +0x5ACA, 0x21A6, 0x2186, 0x1188, 0x016B, 0x01F1, 0x0A98, 0x0AFB, 0x0B39, 0x0B59, 0x0B98, 0x0398, 0x0376, 0x043A, 0x047B, 0x0CBC, // 0x0520 (1312) +0x0C59, 0x0BF7, 0x03F7, 0x0438, 0x047A, 0x0CBA, 0x14FA, 0x1498, 0x24D7, 0x34F8, 0x3D3B, 0x4DBD, 0x457B, 0x54D4, 0xA50E, 0xD4E8, // 0x0530 (1328) +0xDCE3, 0xE4C1, 0xECE3, 0xEC82, 0xE481, 0xDC60, 0xDC60, 0xE4C0, 0xE4C0, 0xE4A1, 0xE461, 0xD401, 0xB340, 0xA321, 0xB364, 0xABA4, // 0x0540 (1344) +0xA404, 0xC4C5, 0xE505, 0xE4C3, 0xD440, 0xC400, 0xCC41, 0xD483, 0xD483, 0xCC63, 0xAC03, 0x9381, 0x9BA2, 0xB463, 0xBC42, 0xABC0, // 0x0550 (1360) +0xE4A1, 0xDCA2, 0xBC23, 0x92E1, 0x7200, 0x71E0, 0x9260, 0xAB01, 0xAB21, 0xA2E0, 0xAAE0, 0xB300, 0xB322, 0xAB23, 0x9AE4, 0x7A85, // 0x0560 (1376) +0x6B29, 0x29E6, 0x0127, 0x09CD, 0x0A31, 0x0213, 0x0276, 0x0B18, 0x0337, 0x0378, 0x0378, 0x0399, 0x0BFA, 0x145B, 0x0C7A, 0x14BB, // 0x0570 (1392) +0x0C37, 0x0C58, 0x0479, 0x0CFB, 0x253C, 0x24DB, 0x24FA, 0x2D1B, 0x2D1A, 0x2CFA, 0x2CFA, 0x355A, 0x45BA, 0x3557, 0x3D55, 0x6D50, // 0x0580 (1408) +0xB4E6, 0xDCC2, 0xE4C3, 0xECC3, 0xDC21, 0xE421, 0xEC61, 0xE460, 0xDCA1, 0xDC60, 0xDC00, 0xD3C0, 0xBB61, 0xAB63, 0x9BC4, 0x8B83, // 0x0590 (1424) +0x8B42, 0xB404, 0xDCE4, 0xE503, 0xCC81, 0xBBE0, 0xBC00, 0xCC83, 0xD4A3, 0xD483, 0xBC42, 0x9B80, 0x9320, 0xA3A2, 0xBC22, 0xC421, // 0x05A0 (1440) +0xDC81, 0xD4A3, 0xB403, 0x8AC0, 0x61C0, 0x69C0, 0x9260, 0xAAE1, 0xAAE0, 0xB300, 0xC320, 0xC340, 0xCBA1, 0xD3E3, 0xC384, 0x9AC3, // 0x05B0 (1456) +0x7B28, 0x4AAB, 0x018C, 0x01F2, 0x0A54, 0x0255, 0x02B7, 0x0B38, 0x0BF8, 0x03B7, 0x0BF9, 0x0C1B, 0x0C3B, 0x147C, 0x14DB, 0x14BA, // 0x05C0 (1472) +0x0C9B, 0x14DC, 0x0CDC, 0x1CDC, 0x34DC, 0x3CBB, 0x34BB, 0x3CDB, 0x5D1B, 0x5CFA, 0x4CD8, 0x3435, 0x3455, 0x34B6, 0x1497, 0x3CB4, // 0x05D0 (1488) +0x948A, 0xC444, 0xE483, 0xE482, 0xDC62, 0xCBE0, 0xDC01, 0xEC61, 0xEC60, 0xE420, 0xCBC0, 0xBB81, 0xBB80, 0xB3C2, 0x9BE4, 0x8322, // 0x05E0 (1504) +0x7AC2, 0xA383, 0xCCA3, 0xDD23, 0xC4A1, 0xA3A0, 0xA3A0, 0xBC22, 0xCCA2, 0xD4A2, 0xCC83, 0xB3C1, 0x9AE0, 0xA301, 0xBBA1, 0xCC43, // 0x05F0 (1520) +0xD461, 0xCC42, 0xA3A1, 0x7240, 0x5980, 0x69C0, 0x9260, 0xAAC0, 0xAAE0, 0xBB20, 0xC340, 0xCB40, 0xCB80, 0xDC22, 0xDC03, 0xB344, // 0x0600 (1536) +0x8B6A, 0x6370, 0x1231, 0x0255, 0x0275, 0x0296, 0x0339, 0x0BDA, 0x0C9C, 0x045A, 0x0C79, 0x0C79, 0x0438, 0x0479, 0x0CDA, 0x0499, // 0x0610 (1552) +0x0CDB, 0x0C9A, 0x0C99, 0x1CBA, 0x1C99, 0x1458, 0x0C99, 0x24F9, 0x3CF8, 0x44B6, 0x2C56, 0x2416, 0x2C77, 0x2477, 0x1437, 0x4519, // 0x0620 (1568) +0x7D75, 0x9CCD, 0xC485, 0xE4C3, 0xD441, 0xC3E0, 0xD3E1, 0xE462, 0xE4A1, 0xDC60, 0xCBC0, 0xBB21, 0xB321, 0xBBA4, 0xB3E3, 0x9B41, // 0x0630 (1584) +0x8AC1, 0x9B42, 0xBC42, 0xC4E2, 0xA461, 0x8360, 0x8320, 0x9B82, 0xBC02, 0xCC43, 0xCC63, 0xC402, 0xAB21, 0xA2C0, 0xB320, 0xC3C2, // 0x0640 (1600) +0xDC61, 0xCC21, 0x9B61, 0x7240, 0x59A0, 0x7200, 0x9AA0, 0xB300, 0xBB60, 0xC360, 0xCB60, 0xC340, 0xC360, 0xD401, 0xDC23, 0xB3A5, // 0x0650 (1616) +0x83ED, 0x5414, 0x1336, 0x0317, 0x0338, 0x0BDA, 0x0C7D, 0x0CBD, 0x04DC, 0x04DC, 0x0C7A, 0x0438, 0x0417, 0x0458, 0x0479, 0x0459, // 0x0660 (1632) +0x0477, 0x0CB9, 0x0CBB, 0x047B, 0x045A, 0x0459, 0x0478, 0x0477, 0x0496, 0x0CB7, 0x1C57, 0x2416, 0x4D19, 0x44F8, 0x2477, 0x24D9, // 0x0670 (1648) +0x255B, 0x5DB7, 0xB4C8, 0xDCA2, 0xCC22, 0xB3A1, 0xC402, 0xD462, 0xD4E2, 0xDCA2, 0xD3A2, 0xC2C1, 0xBAA2, 0xC323, 0xC3C2, 0xB3A0, // 0x0680 (1664) +0x9B20, 0x9341, 0x9BA0, 0xA401, 0x8BA0, 0x6B00, 0x6AC0, 0x82E2, 0x9B43, 0xB384, 0xC404, 0xCC04, 0xBB82, 0xAAE0, 0xAAE0, 0xB342, // 0x0690 (1680) +0xDC61, 0xCC21, 0x9B61, 0x7240, 0x61C0, 0x7220, 0xAAE0, 0xCBA1, 0xD3C1, 0xD3C0, 0xD3A1, 0xC360, 0xC3A0, 0xD402, 0xD403, 0xA3A6, // 0x06A0 (1696) +0x6C4F, 0x3C76, 0x1419, 0x03FB, 0x043C, 0x151F, 0x0D5F, 0x051E, 0x04FC, 0x04DC, 0x14BC, 0x0C19, 0x03D7, 0x1439, 0x0C18, 0x03D6, // 0x06B0 (1712) +0x03B5, 0x03B6, 0x03BA, 0x03DB, 0x0C3B, 0x041A, 0x03D8, 0x0C59, 0x049A, 0x0C37, 0x2C15, 0x2B72, 0x43F3, 0x3BF3, 0x3475, 0x1435, // 0x06C0 (1728) +0x0499, 0x3559, 0x8DD3, 0xACEA, 0xBC44, 0xC3E2, 0xC423, 0xCC64, 0xDCA3, 0xE483, 0xD3E3, 0xC322, 0xBAA0, 0xBAE0, 0xC3A1, 0xC3E1, // 0x06D0 (1744) +0xA3A0, 0x9340, 0x8B00, 0x8320, 0x7300, 0x62A0, 0x6A80, 0x7281, 0x8282, 0x92C2, 0xAB63, 0xC3C3, 0xC3A2, 0xB320, 0xAAC0, 0xAB01, // 0x06E0 (1760) +0xDC41, 0xC3E1, 0x9320, 0x7260, 0x6200, 0x7A40, 0xB320, 0xE402, 0xE400, 0xDBE0, 0xCB80, 0xC360, 0xCBC0, 0xD422, 0xCBE2, 0x9B85, // 0x06F0 (1776) +0x6450, 0x23F6, 0x0C1A, 0x049D, 0x04FF, 0x055F, 0x051D, 0x0D3E, 0x0D1C, 0x0CDC, 0x1CFE, 0x043B, 0x03D8, 0x0C38, 0x0BF7, 0x0374, // 0x0700 (1792) +0x0332, 0x0B73, 0x1375, 0x0B34, 0x0B54, 0x1374, 0x0B53, 0x0B54, 0x03B6, 0x13D5, 0x3475, 0x23D3, 0x0B94, 0x1C36, 0x34B7, 0x23F3, // 0x0710 (1808) +0x022C, 0x130F, 0x3D78, 0x7657, 0x9C47, 0xBBA2, 0xC3E4, 0xD446, 0xD485, 0xDC84, 0xD442, 0xCBC1, 0xBB21, 0xBB00, 0xC381, 0xC401, // 0x0720 (1824) +0xB401, 0x9B60, 0x8B00, 0x82C0, 0x72A0, 0x6AA0, 0x7AC0, 0x82C1, 0x8261, 0x8A61, 0x9AC0, 0xB342, 0xC381, 0xBB20, 0xAAA0, 0xA281, // 0x0730 (1840) +0xCC00, 0xB380, 0x8B00, 0x7280, 0x6A20, 0x8260, 0xBB40, 0xEC21, 0xEC61, 0xE400, 0xD380, 0xCB60, 0xD3E1, 0xDC43, 0xCBE2, 0x9B65, // 0x0740 (1856) +0x63F2, 0x2BD7, 0x13FA, 0x047C, 0x053E, 0x055F, 0x051E, 0x0D1E, 0x0CDD, 0x14FE, 0x1D5F, 0x045B, 0x0479, 0x0C99, 0x0417, 0x0BF6, // 0x0750 (1872) +0x0352, 0x0373, 0x03D4, 0x0372, 0x02CD, 0x0AAC, 0x1AED, 0x1B0E, 0x0B11, 0x0B52, 0x13B0, 0x1BF2, 0x03B4, 0x13F5, 0x2370, 0x4BD1, // 0x0760 (1888) +0x534F, 0x4B4F, 0x33AF, 0x6DB6, 0xA615, 0x8C4A, 0xAC25, 0xCC85, 0xD484, 0xD463, 0xCC61, 0xCC41, 0xBBC2, 0xBB41, 0xC381, 0xCC02, // 0x0770 (1904) +0xC421, 0xABA0, 0x9321, 0x8AC1, 0x7AA0, 0x7AC0, 0x8B41, 0x9B63, 0x9B42, 0x92E1, 0x92C0, 0xAB21, 0xC362, 0xC322, 0xAAA1, 0xA261, // 0x0780 (1920) +0xA382, 0x9AE0, 0x9280, 0x8A60, 0x7260, 0x8280, 0xAB60, 0xDC21, 0xF442, 0xEBE0, 0xCB80, 0xC3A0, 0xD400, 0xDC62, 0xD423, 0x9BA6, // 0x0790 (1936) +0x5C52, 0x1BF7, 0x0419, 0x151E, 0x0D1D, 0x0D3D, 0x0D1E, 0x0D3E, 0x04DD, 0x0CFD, 0x155D, 0x0439, 0x03B7, 0x13B8, 0x0B77, 0x1398, // 0x07A0 (1952) +0x1396, 0x0B12, 0x1331, 0x024C, 0x1A6B, 0x120A, 0x1A6D, 0x1AD0, 0x0AD1, 0x0B53, 0x0353, 0x0393, 0x0331, 0x02CE, 0x230F, 0x4B6F, // 0x07B0 (1968) +0x6BCE, 0x8C4F, 0x7BED, 0x4B2B, 0x5D77, 0x9EDB, 0x9CCC, 0xBCA7, 0xC4A4, 0xBC62, 0xBC61, 0xCC82, 0xCC41, 0xCBC1, 0xCBA1, 0xD3E2, // 0x07C0 (1984) +0xD422, 0xC3E1, 0xA360, 0x8B00, 0x82A0, 0x8AA0, 0xA300, 0xBB82, 0xCBC2, 0xC3C2, 0xAB40, 0xA320, 0xB3A1, 0xBBA2, 0xBB22, 0xB2A1, // 0x07D0 (2000) +0x92E0, 0x9AE0, 0x9AE0, 0x92A0, 0x7240, 0x7240, 0xA320, 0xD401, 0xEC61, 0xE400, 0xC380, 0xBB80, 0xCBE1, 0xDC63, 0xD443, 0x9B84, // 0x07E0 (2016) +0x63AB, 0x3C32, 0x0C79, 0x0D3F, 0x0D1E, 0x0D1E, 0x049C, 0x049C, 0x0CBD, 0x14FD, 0x151E, 0x047B, 0x03F8, 0x0316, 0x0B58, 0x0293, // 0x07F0 (2032) +0x022F, 0x01CB, 0x0A2B, 0x01A9, 0x026C, 0x02CE, 0x0310, 0x0B52, 0x0B73, 0x0353, 0x03B4, 0x0BB3, 0x1330, 0x01EB, 0x02AD, 0x2B8F, // 0x0800 (2048) +0x19C6, 0x0903, 0x0082, 0x0083, 0x0925, 0x53D0, 0x8DFA, 0x84D1, 0xB446, 0xBBC0, 0xAC40, 0xB4E2, 0xB4C3, 0xBC63, 0xC402, 0xCBE1, // 0x0810 (2064) +0xD441, 0xCC21, 0xB3C1, 0x9B00, 0x8280, 0x8260, 0x92C0, 0xB381, 0xCC22, 0xD462, 0xC3E2, 0xAB60, 0xAB61, 0xBBC3, 0xC3E3, 0xBB61, // 0x0820 (2080) +0xA300, 0xAB80, 0xB382, 0x92E1, 0x7220, 0x7220, 0xA320, 0xD421, 0xEC81, 0xDC20, 0xBB80, 0xAB20, 0xBB81, 0xCC03, 0xCC03, 0xA362, // 0x0830 (2096) +0x6B23, 0x540C, 0x2CF9, 0x0D1E, 0x04BD, 0x04BD, 0x0CDE, 0x0C7D, 0x045C, 0x14BD, 0x0CDD, 0x043A, 0x0335, 0x1397, 0x0295, 0x0274, // 0x0840 (2112) +0x0272, 0x0291, 0x02D2, 0x0312, 0x0B72, 0x1BF3, 0x0B71, 0x1392, 0x0BB2, 0x022C, 0x026E, 0x1352, 0x0BB5, 0x0395, 0x0373, 0x13B3, // 0x0850 (2128) +0x1B2F, 0x01A8, 0x1987, 0x2987, 0x2147, 0x0907, 0x2330, 0x7DD6, 0x94CB, 0x9C03, 0xB444, 0xC463, 0xCCC1, 0xC4A0, 0xBC20, 0xBBC0, // 0x0860 (2144) +0xD440, 0xDC62, 0xD421, 0xAB60, 0x8AA0, 0x7A60, 0x8280, 0x9301, 0xB3C0, 0xD462, 0xD462, 0xBBA0, 0x9B00, 0xAB42, 0xBC02, 0xBC02, // 0x0870 (2160) +0xBBE0, 0xC442, 0xBBE3, 0x92C0, 0x6A00, 0x7A40, 0xAB40, 0xD421, 0xE481, 0xDC20, 0xBB80, 0xAB00, 0xB301, 0xC342, 0xC362, 0xB321, // 0x0880 (2176) +0x8AC1, 0x6348, 0x3CD7, 0x0C9B, 0x045A, 0x043A, 0x0C7D, 0x0C7D, 0x14DE, 0x043B, 0x0CBC, 0x0419, 0x0292, 0x12F4, 0x0AD4, 0x02D5, // 0x0890 (2192) +0x0316, 0x0377, 0x0B55, 0x1334, 0x1B32, 0x128E, 0x228C, 0x0187, 0x126A, 0x234F, 0x0AAF, 0x026F, 0x0313, 0x03D6, 0x03B6, 0x13B6, // 0x08A0 (2208) +0x2C14, 0x2B4F, 0x2A08, 0x5B0C, 0x6BAE, 0x6BCE, 0x5BED, 0x8552, 0x9E16, 0x950F, 0xBCC5, 0xDD02, 0xDD01, 0xD481, 0xBC00, 0xBBC0, // 0x08B0 (2224) +0xD400, 0xE482, 0xE461, 0xC3A0, 0x9B00, 0x8280, 0x7241, 0x7A60, 0x9B20, 0xC401, 0xDCA2, 0xC422, 0x9B00, 0x8AA0, 0x9B80, 0xB443, // 0x08C0 (2240) +0xD4A1, 0xD4C3, 0xB403, 0x8AC0, 0x7A40, 0x92E0, 0xBBC1, 0xDC61, 0xE481, 0xDC40, 0xCBA1, 0xBB20, 0xBAC0, 0xBAC1, 0xC2C1, 0xBAC1, // 0x08D0 (2256) +0xAAC3, 0x7AE8, 0x4434, 0x1458, 0x1459, 0x03F8, 0x0377, 0x03FA, 0x0C7B, 0x14BC, 0x0459, 0x1459, 0x0AF3, 0x022F, 0x12F1, 0x12F1, // 0x08E0 (2272) +0x128F, 0x0A6E, 0x0A6D, 0x0A0C, 0x11CB, 0x0948, 0x0986, 0x2A29, 0x10E5, 0x2A2A, 0x1B6F, 0x0330, 0x028F, 0x0AF2, 0x0BB4, 0x0BB4, // 0x08F0 (2288) +0x13D4, 0x0ACE, 0x0165, 0x1123, 0x10C1, 0x2122, 0x39C4, 0x1184, 0x1B8F, 0x7617, 0xBDCD, 0xCD25, 0xBD01, 0xC4E1, 0xC402, 0xCBA2, // 0x0900 (2304) +0xDC22, 0xE482, 0xE481, 0xCBE0, 0xAB40, 0x92E0, 0x7A82, 0x7A41, 0x8AC0, 0xAB81, 0xCC42, 0xCC22, 0xA321, 0x7200, 0x7A60, 0x9BA3, // 0x0910 (2320) +0xDD02, 0xD4C3, 0xABE2, 0x8AC0, 0x8AC0, 0xAB81, 0xD442, 0xE4A2, 0xEC81, 0xDC40, 0xD3E0, 0xCB60, 0xC321, 0xC2C1, 0xBA60, 0xBA61, // 0x0920 (2336) +0xC2C3, 0x9B07, 0x63D0, 0x3415, 0x0BF7, 0x0C18, 0x0335, 0x0376, 0x0395, 0x0C18, 0x0479, 0x0C79, 0x1BD7, 0x024F, 0x020B, 0x1A6B, // 0x0930 (2352) +0x0965, 0x19C6, 0x32CC, 0x228B, 0x01E7, 0x22CB, 0x19C8, 0x0926, 0x2ACB, 0x0186, 0x0126, 0x2AEE, 0x1371, 0x0352, 0x03B4, 0x03B4, // 0x0940 (2368) +0x0BD4, 0x0B11, 0x1ACE, 0x32AD, 0x19C8, 0x1125, 0x08A1, 0x00C2, 0x00C5, 0x1AEE, 0x55B8, 0x7E34, 0xBD47, 0xD4A0, 0xD480, 0xCC40, // 0x0950 (2384) +0xDC41, 0xDC62, 0xDC82, 0xCC20, 0xB3A0, 0xAB61, 0x9B22, 0x92E2, 0x8AC0, 0x9B01, 0xABA2, 0xBBE3, 0xAB43, 0x7A20, 0x69E0, 0x82C3, // 0x0960 (2400) +0xDCE1, 0xCC81, 0xA381, 0x8AE0, 0x9B41, 0xC402, 0xDC61, 0xECA1, 0xE480, 0xDC40, 0xD400, 0xCBC0, 0xCB80, 0xC300, 0xBA81, 0xBA82, // 0x0970 (2416) +0xC302, 0xAB45, 0x8369, 0x5BD0, 0x1374, 0x03D7, 0x03B7, 0x0B96, 0x0334, 0x0B96, 0x0418, 0x0C59, 0x1458, 0x1393, 0x0126, 0x11C8, // 0x0980 (2432) +0x1A29, 0x0145, 0x1A28, 0x4BAE, 0x334D, 0x22CC, 0x2B2C, 0x0A07, 0x09E7, 0x436E, 0x1A09, 0x11E9, 0x1ACC, 0x130E, 0x1392, 0x1372, // 0x0990 (2448) +0x3B70, 0x4370, 0x3391, 0x232F, 0x338F, 0x3B6E, 0x4B2D, 0x3209, 0x2166, 0x0107, 0x0395, 0x355A, 0x7615, 0x9D8C, 0xC4C4, 0xD460, // 0x09A0 (2464) +0xD461, 0xCC41, 0xCC61, 0xC441, 0xC401, 0xC422, 0xC443, 0xBBE3, 0x9301, 0x82A0, 0x8280, 0x9AE2, 0x9AE2, 0x8220, 0x69A0, 0x7202, // 0x09B0 (2480) +0xDCA0, 0xC440, 0xA361, 0x9321, 0xB3C2, 0xD483, 0xE4A1, 0xE480, 0xE460, 0xDC40, 0xD420, 0xCBE0, 0xC3A0, 0xC340, 0xB2A2, 0xBAE3, // 0x09C0 (2496) +0xCBC3, 0xBBC4, 0x9B04, 0x7B6B, 0x2BD3, 0x0376, 0x03B8, 0x13F9, 0x0B36, 0x0B35, 0x0BF7, 0x03F7, 0x03D5, 0x2436, 0x22EE, 0x00C5, // 0x09D0 (2512) +0x01A8, 0x1A6B, 0x11A7, 0x1986, 0x530C, 0x63CE, 0x43AE, 0x43CE, 0x1269, 0x1A69, 0x53AE, 0x3AAA, 0x31E7, 0x3A08, 0x3289, 0x42C9, // 0x09E0 (2528) +0x6B48, 0x7348, 0x7B48, 0x6B4A, 0x434D, 0x2B4E, 0x3390, 0x22AC, 0x1165, 0x0965, 0x024B, 0x1C16, 0x149B, 0x34D9, 0x84EF, 0xB4C8, // 0x09F0 (2544) +0xCCA3, 0xC420, 0xBC21, 0xBC42, 0xC442, 0xDCA3, 0xE504, 0xD4C3, 0xABE3, 0x82A0, 0x7200, 0x7A21, 0x8A41, 0x8200, 0x69A0, 0x69E2, // 0x0A00 (2560) +0xD4A1, 0xC420, 0xB380, 0xBBA0, 0xD462, 0xDCA3, 0xD461, 0xD440, 0xD480, 0xD4A1, 0xCC21, 0xBBA0, 0xBB81, 0xB341, 0xB321, 0xC3A3, // 0x0A10 (2576) +0xE484, 0xDC43, 0xC382, 0x8AE4, 0x5B6C, 0x3392, 0x0354, 0x0BD7, 0x0355, 0x0334, 0x0395, 0x0BD6, 0x03B6, 0x0BF7, 0x1BF6, 0x026F, // 0x0A20 (2592) +0x00A5, 0x00A3, 0x0965, 0x0123, 0x1103, 0x4AA9, 0x5B4C, 0x530B, 0x3A68, 0x3A47, 0x3A06, 0x39C5, 0x39C4, 0x4205, 0x4245, 0x4246, // 0x0A30 (2608) +0x52A8, 0x62E9, 0x6AE8, 0x7309, 0x7B28, 0x6AE8, 0x3A68, 0x2A8A, 0x126B, 0x0168, 0x0128, 0x23B4, 0x0C18, 0x0419, 0x14DB, 0x3CF7, // 0x0A40 (2624) +0x8D0E, 0xAC67, 0xA3C1, 0xB3A0, 0xC421, 0xD4C2, 0xE543, 0xE524, 0xC442, 0x9B40, 0x7220, 0x61E0, 0x7221, 0x71E1, 0x61C0, 0x6A01, // 0x0A50 (2640) +0xC440, 0xBC00, 0xBBE0, 0xCC41, 0xDCC3, 0xD482, 0xC3E0, 0xBBC0, 0xD480, 0xDCA1, 0xC421, 0xAB60, 0xAB40, 0xAB61, 0xBBC2, 0xD463, // 0x0A60 (2656) +0xF503, 0xF503, 0xCBE3, 0xA344, 0x72C5, 0x532B, 0x1B51, 0x0334, 0x0B34, 0x02F4, 0x0397, 0x0375, 0x0BD5, 0x13F6, 0x0395, 0x1374, // 0x0A70 (2672) +0x1AD0, 0x0169, 0x00A2, 0x00A1, 0x08A0, 0x3184, 0x41C6, 0x41C7, 0x3165, 0x3185, 0x52C9, 0x52A8, 0x3A05, 0x39C4, 0x5205, 0x49E5, // 0x0A80 (2688) +0x4A47, 0x4A67, 0x5289, 0x5ACA, 0x5AC9, 0x62C9, 0x6B09, 0x41E5, 0x18E2, 0x1145, 0x016A, 0x12F3, 0x0BD9, 0x03DA, 0x03DA, 0x14BC, // 0x0A90 (2704) +0x24BA, 0x5D58, 0x6C6C, 0x6B22, 0x9360, 0xC482, 0xE503, 0xE503, 0xD4C3, 0xABA1, 0x7AC1, 0x6A61, 0x6221, 0x6201, 0x5A02, 0x51E2, // 0x0AA0 (2720) +0xB400, 0xB3C0, 0xCC20, 0xDCC2, 0xE502, 0xCC61, 0xB3C0, 0xB3A0, 0xCC60, 0xD481, 0xC401, 0xA320, 0x9B40, 0xB3C1, 0xCC62, 0xED23, // 0x0AB0 (2736) +0xFDA2, 0xFD82, 0xDC62, 0xB321, 0x8240, 0x5245, 0x2B4F, 0x0B12, 0x0A70, 0x0A71, 0x1334, 0x0B54, 0x0393, 0x13F5, 0x0332, 0x0353, // 0x0AC0 (2752) +0x1BD5, 0x0AF0, 0x01A8, 0x0924, 0x1102, 0x08C1, 0x2165, 0x2986, 0x2144, 0x1924, 0x3ACA, 0x3B0B, 0x32CA, 0x2A48, 0x4227, 0x4206, // 0x0AD0 (2768) +0x4226, 0x39E5, 0x4205, 0x4226, 0x3A06, 0x31C5, 0x4205, 0x4A87, 0x39E5, 0x29A6, 0x0107, 0x09ED, 0x0270, 0x02B3, 0x0B56, 0x03B7, // 0x0AE0 (2784) +0x14DB, 0x2D1A, 0x54D5, 0x642D, 0x73A5, 0xA422, 0xD4C2, 0xECC1, 0xE481, 0xCBE0, 0x9B00, 0x7A80, 0x7A60, 0x6A21, 0x61E1, 0x59E2, // 0x0AF0 (2800) +0xA360, 0xAB80, 0xCC20, 0xE4C2, 0xDCE2, 0xC440, 0xB3C0, 0xBBE0, 0xD460, 0xDC81, 0xC3E0, 0xAB40, 0xABA0, 0xC441, 0xDCC1, 0xF562, // 0x0B00 (2816) +0xFDE2, 0xF5A2, 0xE4A2, 0xB361, 0x7A61, 0x4A03, 0x434C, 0x336F, 0x1AAE, 0x0A2E, 0x01ED, 0x024E, 0x028F, 0x02D0, 0x026D, 0x0B30, // 0x0B10 (2832) +0x0BD3, 0x0351, 0x026D, 0x0168, 0x09C9, 0x09A8, 0x0125, 0x0145, 0x1164, 0x19A5, 0x32EA, 0x3B4C, 0x330C, 0x2A8A, 0x3227, 0x3A27, // 0x0B20 (2848) +0x4228, 0x4A29, 0x4207, 0x4A07, 0x5248, 0x4207, 0x2122, 0x2102, 0x31C5, 0x3A49, 0x0106, 0x0169, 0x09ED, 0x020F, 0x0271, 0x0335, // 0x0B30 (2864) +0x03B9, 0x0CBD, 0x1D3C, 0x34F8, 0x4412, 0x638C, 0x9BE7, 0xCC85, 0xDCE2, 0xCC60, 0xABA0, 0x8B00, 0x72A0, 0x6260, 0x5A60, 0x6260, // 0x0B40 (2880) +0x9300, 0xA360, 0xCC21, 0xDCA2, 0xD4A1, 0xCC40, 0xBC00, 0xC421, 0xDC81, 0xE481, 0xD400, 0xC3E0, 0xCC40, 0xDCC1, 0xED00, 0xFD41, // 0x0B50 (2896) +0xFDC2, 0xF583, 0xD4A3, 0xABC3, 0x72A3, 0x5203, 0x5A85, 0x5B29, 0x2B0C, 0x026C, 0x026D, 0x022D, 0x022D, 0x020C, 0x128D, 0x028D, // 0x0B60 (2912) +0x0B4F, 0x0B70, 0x024D, 0x026F, 0x0290, 0x0A8F, 0x022B, 0x0A09, 0x0965, 0x0944, 0x19E5, 0x3247, 0x3A88, 0x42A9, 0x4AA9, 0x3A27, // 0x0B70 (2928) +0x31E6, 0x3A48, 0x3A28, 0x4268, 0x4227, 0x52A8, 0x5AE8, 0x3A05, 0x29C4, 0x2184, 0x0903, 0x1165, 0x0965, 0x11E6, 0x1A06, 0x1A26, // 0x0B80 (2944) +0x330C, 0x2370, 0x0C78, 0x151C, 0x2D1A, 0x2C14, 0x332E, 0x4ACA, 0x83EA, 0xA468, 0xAC03, 0x9320, 0x7AC0, 0x6A80, 0x5A80, 0x5AA0, // 0x0B90 (2960) +0x9B20, 0xB3A1, 0xCC21, 0xD461, 0xD460, 0xCC40, 0xC420, 0xCC41, 0xE481, 0xDC60, 0xD420, 0xD440, 0xE4C1, 0xE4E1, 0xECE0, 0xFD20, // 0x0BA0 (2976) +0xFD62, 0xED22, 0xD482, 0xABA2, 0x82E2, 0x6A21, 0x6200, 0x6283, 0x4B08, 0x3B4B, 0x12ED, 0x020C, 0x026E, 0x0A8E, 0x0A4C, 0x0A2A, // 0x0BB0 (2992) +0x12AC, 0x0A6C, 0x020C, 0x0A8F, 0x0290, 0x0AD1, 0x0AB0, 0x0A6E, 0x09EB, 0x0188, 0x0125, 0x0924, 0x19A6, 0x21E7, 0x326A, 0x2A28, // 0x0BC0 (3008) +0x3227, 0x3A47, 0x3A07, 0x3A07, 0x5227, 0x49E6, 0x5227, 0x5A68, 0x5227, 0x5205, 0x6A44, 0x9B66, 0xAB63, 0xB381, 0xBBC0, 0xC401, // 0x0BD0 (3024) +0xBBA2, 0x8B22, 0x4B23, 0x2B46, 0x33AB, 0x5471, 0x5454, 0x4392, 0x330D, 0x4B2B, 0x8389, 0x9387, 0x7AC3, 0x7240, 0x7280, 0x6AA0, // 0x0BE0 (3040) +0xB380, 0xBBE1, 0xCC21, 0xCC00, 0xCC20, 0xD440, 0xCC20, 0xD440, 0xDC80, 0xD460, 0xD440, 0xD480, 0xDCC0, 0xDCA0, 0xDCA0, 0xE4E1, // 0x0BF0 (3056) +0xED02, 0xE4C2, 0xD441, 0xAB41, 0x8AE3, 0x7262, 0x7242, 0x7283, 0x72C3, 0x7346, 0x5349, 0x2ACA, 0x024A, 0x020B, 0x01C8, 0x0A09, // 0x0C00 (3072) +0x0A2A, 0x126B, 0x0A6B, 0x0A6C, 0x0A6C, 0x020C, 0x0A6D, 0x01EB, 0x01EA, 0x09C9, 0x0187, 0x00E4, 0x00C3, 0x00E2, 0x1984, 0x2A06, // 0x0C10 (3088) +0x2A67, 0x11E6, 0x2A48, 0x3248, 0x3228, 0x3207, 0x3A27, 0x4247, 0x4226, 0x49E4, 0x59A1, 0x92A3, 0xBB82, 0xBB40, 0xCBC0, 0xCC02, // 0x0C20 (3104) +0xB3A2, 0x9301, 0x7260, 0x6200, 0x6A00, 0x7260, 0x8305, 0x942C, 0x742F, 0x4B2C, 0x3AA8, 0x5349, 0x73EA, 0x6B05, 0x5A60, 0x6A80, // 0x0C30 (3120) +0xC3E0, 0xD442, 0xD441, 0xCC20, 0xD460, 0xDC80, 0xDC60, 0xDC61, 0xD480, 0xD460, 0xCC60, 0xD480, 0xD4A0, 0xCC40, 0xC420, 0xD480, // 0x0C40 (3136) +0xE4C0, 0xDC81, 0xB3A1, 0x9323, 0x72A3, 0x7284, 0x7A84, 0x92E4, 0xAB64, 0xABA5, 0x8B43, 0x5AE4, 0x2AC8, 0x0A69, 0x0209, 0x01E9, // 0x0C50 (3152) +0x022B, 0x028C, 0x0AAC, 0x0A6A, 0x1A4A, 0x1A29, 0x0186, 0x09C6, 0x0183, 0x0963, 0x1123, 0x18E2, 0x20E0, 0x6283, 0x8B22, 0x9300, // 0x0C60 (3168) +0x8AE2, 0x82C3, 0x5A23, 0x4A46, 0x3269, 0x2A49, 0x3206, 0x31C4, 0x3A26, 0x4206, 0x41C5, 0x4983, 0x8A63, 0xAAA2, 0xBB43, 0xC3A4, // 0x0C70 (3184) +0xA381, 0x82C0, 0x8240, 0x8202, 0x79A0, 0x81E0, 0x9AA0, 0xAB81, 0xAC25, 0xA468, 0x7388, 0x52E7, 0x6326, 0x62C4, 0x6220, 0x6A40, // 0x0C80 (3200) +0xD460, 0xDCA0, 0xDCC0, 0xDCC0, 0xE4A0, 0xF4C1, 0xECE1, 0xE4A0, 0xDC80, 0xD440, 0xDC60, 0xDC81, 0xD4A0, 0xC420, 0xC3E0, 0xCC60, // 0x0C90 (3216) +0xD4C2, 0xC442, 0xA341, 0x8280, 0x7A62, 0x82C3, 0xA363, 0xB3C3, 0xC403, 0xC444, 0xB3C3, 0x7AC2, 0x10A0, 0x00E2, 0x09A6, 0x1A8A, // 0x0CA0 (3232) +0x1A69, 0x1248, 0x0A27, 0x01C6, 0x01C7, 0x01C7, 0x01A7, 0x19E7, 0x21C5, 0x1943, 0x08C2, 0x10C2, 0x2941, 0x7B67, 0x93A2, 0x9B20, // 0x0CB0 (3248) +0x92A0, 0x9A80, 0x9A82, 0x8A83, 0x6A63, 0x5223, 0x39E3, 0x29A2, 0x19A3, 0x2183, 0x31A6, 0x3965, 0x4103, 0x69E3, 0xA303, 0xBB63, // 0x0CC0 (3264) +0xAB03, 0x9A62, 0x9242, 0x9222, 0x8200, 0x8A20, 0x9AE0, 0xAB60, 0xBBE1, 0xBBE1, 0xABC1, 0x8B41, 0x6AE1, 0x6AC3, 0x6AA3, 0x6243, // 0x0CD0 (3280) +0xDCA0, 0xE4E0, 0xE500, 0xE500, 0xF500, 0xFD01, 0xF501, 0xECE0, 0xE480, 0xDC60, 0xDC80, 0xE4A0, 0xDCE1, 0xD4A0, 0xD460, 0xDCA0, // 0x0CE0 (3296) +0xDCC0, 0xBC00, 0x9B01, 0x7A41, 0x7A62, 0x9B43, 0xC423, 0xDCA2, 0xD481, 0xD4A4, 0xC488, 0x51A0, 0x0840, 0x0081, 0x0081, 0x0903, // 0x0CF0 (3312) +0x29E6, 0x21E6, 0x2227, 0x09A5, 0x0144, 0x01E6, 0x01A5, 0x01C5, 0x1206, 0x09A5, 0x00E3, 0x1944, 0x2921, 0x59E1, 0x9300, 0xA300, // 0x0D00 (3328) +0xAB00, 0xA281, 0x9A21, 0x9A43, 0x9284, 0x8AC5, 0x7AC4, 0x6A83, 0x6283, 0x5A63, 0x5A64, 0x5225, 0x41A3, 0x4161, 0x6A41, 0xA365, // 0x0D10 (3344) +0xA303, 0x9A83, 0x9A62, 0x9242, 0x9261, 0x9AC1, 0xB381, 0xC401, 0xC3E0, 0xAB80, 0x9320, 0x7AA0, 0x6260, 0x6282, 0x6AA3, 0x6A83, // 0x0D20 (3360) +0xDCE0, 0xE500, 0xE520, 0xED00, 0xF520, 0xFD00, 0xF500, 0xF4E0, 0xE4A0, 0xE480, 0xDC80, 0xE4C0, 0xE501, 0xE521, 0xDCE0, 0xE500, // 0x0D30 (3376) +0xDCC1, 0xBBC0, 0x8AC2, 0x6A21, 0x7AA1, 0xABA3, 0xDCA2, 0xF522, 0xED23, 0xC484, 0x6202, 0x41C5, 0x2965, 0x3A08, 0x4208, 0x1081, // 0x0D40 (3392) +0x0060, 0x1901, 0x3960, 0x8387, 0x6AC3, 0x6B24, 0x52A3, 0x3A22, 0x42A6, 0x1100, 0x3941, 0x7223, 0x7200, 0x8A80, 0x9B20, 0xC402, // 0x0D50 (3408) +0xC3A2, 0xAAE1, 0x9A41, 0x9282, 0x8AE3, 0x8B24, 0x8B03, 0x8AC1, 0x9280, 0x8A40, 0x8A01, 0x8A23, 0x8244, 0x6A03, 0x7262, 0x9344, // 0x0D60 (3424) +0xAB84, 0xAB03, 0x9A82, 0x9241, 0x9260, 0xAB21, 0xC3E1, 0xD462, 0xCC41, 0xAB80, 0x8AC0, 0x6A40, 0x5A00, 0x5A00, 0x6220, 0x6A40, // 0x0D70 (3440) +0xDCE0, 0xE520, 0xE500, 0xECE0, 0xF520, 0xFD00, 0xF4E0, 0xF4E0, 0xECC0, 0xE480, 0xD460, 0xD480, 0xE4E0, 0xED21, 0xED20, 0xE501, // 0x0D80 (3456) +0xDC82, 0xB381, 0x8282, 0x7221, 0x82C1, 0xB403, 0xE4E3, 0xF544, 0xED87, 0x6220, 0x6B2A, 0x8451, 0x3A69, 0x5B2D, 0x7C10, 0x5ACB, // 0x0D90 (3472) +0x18A3, 0x1020, 0x38E0, 0x9B86, 0xA363, 0xB381, 0xD440, 0xE4E3, 0xBC44, 0x48E0, 0x9AA1, 0x9220, 0x89C0, 0xA2A1, 0xC3C1, 0xD463, // 0x0DA0 (3488) +0xC3E2, 0xAB20, 0x9AA1, 0x9AE2, 0x9B43, 0x9B43, 0x9B02, 0x9AC1, 0xA2C1, 0xA260, 0xA200, 0x99E0, 0x9A01, 0xA282, 0xB303, 0xC3A3, // 0x0DB0 (3504) +0xC423, 0xBBC2, 0xA2C1, 0x8A00, 0x9220, 0xA2A1, 0xB361, 0xC3E2, 0xC422, 0xB3A1, 0x8B01, 0x7260, 0x6220, 0x6A40, 0x72A0, 0x7AA0, // 0x0DC0 (3520) +0xDCE0, 0xE500, 0xED00, 0xECE0, 0xF520, 0xFD20, 0xF4E0, 0xECE0, 0xE4C0, 0xDC80, 0xCC20, 0xCC20, 0xDC80, 0xECE0, 0xED00, 0xECE1, // 0x0DD0 (3536) +0xDC21, 0xBB41, 0x9261, 0x8A21, 0x9AC1, 0xC3E3, 0xED03, 0xF545, 0xD4E7, 0x6A82, 0xA553, 0x7C31, 0x636D, 0x740F, 0x73EF, 0x6B6D, // 0x0DE0 (3552) +0x2143, 0x1080, 0x5243, 0x6A62, 0x6A21, 0x92E2, 0xC380, 0xE4A5, 0x8240, 0x79E0, 0xAB23, 0x9220, 0x9240, 0xAB01, 0xD420, 0xDC40, // 0x0DF0 (3568) +0xC380, 0xAAA0, 0xAA60, 0xBB03, 0xC3A4, 0xBBA4, 0xB342, 0xAAE1, 0xAAA0, 0xAA60, 0xAA60, 0xAA81, 0xAAC1, 0xAB00, 0xBB60, 0xCC21, // 0x0E00 (3584) +0xDCC1, 0xC440, 0xA320, 0x9220, 0x91E1, 0x9A22, 0xA282, 0xB302, 0xAB61, 0x9B41, 0x82E0, 0x6A60, 0x6220, 0x6A60, 0x7AE0, 0x8B20, // 0x0E10 (3600) +0xDCC0, 0xE500, 0xED00, 0xED00, 0xF520, 0xF540, 0xECE0, 0xE4C0, 0xDCA0, 0xD460, 0xBC00, 0xBC00, 0xD460, 0xE4A1, 0xECE0, 0xECC1, // 0x0E20 (3616) +0xE420, 0xCB20, 0xB221, 0xA1E1, 0xAA61, 0xD3A2, 0xF4E2, 0xF543, 0xE506, 0x8B24, 0xAD32, 0x8431, 0x7BEF, 0x94B1, 0x8CB0, 0x6BCD, // 0x0E30 (3632) +0x31C7, 0x1903, 0x4A24, 0x49C2, 0x49A0, 0x6A41, 0x9B42, 0xB3C4, 0x5920, 0xAB65, 0x9AC1, 0x9A60, 0x9A80, 0xB342, 0xC3E1, 0xCBC1, // 0x0E40 (3648) +0xB2C0, 0xA240, 0xAA20, 0xC323, 0xD425, 0xDC64, 0xCBA2, 0xBAE0, 0xB280, 0xB240, 0xB220, 0xB2A1, 0xBB82, 0xB3A1, 0xB3C0, 0xCCA1, // 0x0E50 (3664) +0xDD01, 0xCC80, 0xAB40, 0x9220, 0x91C2, 0x99C3, 0x9A02, 0xA262, 0x92C1, 0x8AE0, 0x72E0, 0x6A80, 0x6260, 0x6A60, 0x7AE0, 0x8B81, // 0x0E60 (3680) +0xDCC0, 0xE4E1, 0xED00, 0xF500, 0xF520, 0xF541, 0xED01, 0xE4C0, 0xD4A0, 0xC460, 0xB400, 0xBC00, 0xCC40, 0xE480, 0xECA0, 0xEC81, // 0x0E70 (3696) +0xE401, 0xD2E0, 0xB9E1, 0xA981, 0xAA00, 0xCB41, 0xECA1, 0xF501, 0xECE3, 0xC486, 0xB531, 0x8C51, 0x8C70, 0x9CD1, 0x9CD1, 0x73CE, // 0x0E80 (3712) +0x4207, 0x31A5, 0x4A46, 0x3182, 0x39C2, 0x5A03, 0x82E5, 0x6120, 0x8220, 0xA302, 0x9280, 0x92A0, 0x92C0, 0xA321, 0xC3C1, 0xB340, // 0x0E90 (3728) +0x9AE0, 0x9A80, 0xA261, 0xBB02, 0xDC24, 0xECA5, 0xE423, 0xCB21, 0xAA40, 0xAA60, 0xB280, 0xB302, 0xBB82, 0xB3A1, 0xB3C0, 0xCC61, // 0x0EA0 (3744) +0xDCC1, 0xCC40, 0xAB40, 0x9240, 0x99E2, 0xA1E3, 0xA203, 0x9222, 0x8240, 0x7280, 0x6A80, 0x6280, 0x6260, 0x6240, 0x72A0, 0x8361, // 0x0EB0 (3760) +0xD4A0, 0xDCC0, 0xECE0, 0xECE0, 0xE4E0, 0xE500, 0xE500, 0xDCC0, 0xCC80, 0xC460, 0xAC00, 0xB400, 0xCC40, 0xDC40, 0xE460, 0xE441, // 0x0EC0 (3776) +0xDBA2, 0xC2A2, 0xB1C2, 0xA161, 0xA1E0, 0xC341, 0xE482, 0xF4E2, 0xE4A1, 0xC444, 0xBD91, 0xAD95, 0x94D1, 0xB5D6, 0xA535, 0x8432, // 0x0ED0 (3792) +0x738F, 0x3186, 0x5268, 0x49E4, 0x3981, 0x49E3, 0x3984, 0x3101, 0x82E3, 0x8280, 0x8AA0, 0x92C0, 0x9AE0, 0xA321, 0xAB41, 0xB322, // 0x0EE0 (3808) +0xAB01, 0xB2E1, 0xAAC1, 0xB2E1, 0xBBC2, 0xDCA5, 0xDC64, 0xCB83, 0xAA60, 0xAA20, 0xB261, 0xBB02, 0xB362, 0xABA1, 0xABE1, 0xB401, // 0x0EF0 (3824) +0xCC41, 0xC3E1, 0xAB21, 0x9A60, 0xA222, 0xAA23, 0xA202, 0x9201, 0x8261, 0x72A1, 0x62A0, 0x5AA0, 0x5A60, 0x5A60, 0x6AC0, 0x8342, // 0x0F00 (3840) +0xC420, 0xCC60, 0xDCA0, 0xE4C0, 0xDCA0, 0xDCA0, 0xD4C0, 0xCCA0, 0xC480, 0xB460, 0xB420, 0xB400, 0xCC20, 0xDC40, 0xE440, 0xE401, // 0x0F10 (3856) +0xC361, 0xAAA1, 0x9200, 0x8A00, 0x8A60, 0xAB41, 0xCC61, 0xDCE2, 0xD481, 0xABA2, 0xBD0F, 0xC5F7, 0x9CB3, 0x94B2, 0xA533, 0x9471, // 0x0F20 (3872) +0x8C2F, 0x31A6, 0x29A5, 0x3A07, 0x2943, 0x3984, 0x2902, 0x3100, 0x8AC5, 0x9282, 0x9AC2, 0xAB22, 0xBB21, 0xBB20, 0xC380, 0xCBE1, // 0x0F30 (3888) +0xCBE1, 0xCBC0, 0xBB81, 0xAB00, 0xAB00, 0xCBC3, 0xDC23, 0xCBC1, 0xB2C0, 0xB280, 0xB2C1, 0xB2C2, 0xA2E3, 0xA323, 0xA383, 0xA3A2, // 0x0F40 (3904) +0xABA2, 0xABA2, 0x9B02, 0x9AE2, 0xAB22, 0xA2E2, 0x9A82, 0x9241, 0x8A81, 0x82E1, 0x7300, 0x62E0, 0x5AA0, 0x5A80, 0x7300, 0x8BC0, // 0x0F50 (3920) +0xA380, 0xB3E0, 0xCC61, 0xD461, 0xC420, 0xC420, 0xCC60, 0xCC80, 0xC480, 0xBC40, 0xB420, 0xB400, 0xCC00, 0xDC41, 0xDC00, 0xD3A1, // 0x0F60 (3936) +0xBB01, 0xAA60, 0x9A21, 0x9221, 0x8A60, 0x9B21, 0xBC21, 0xC481, 0xC421, 0x9B21, 0x940A, 0xB574, 0xAD54, 0x9492, 0xA513, 0x840F, // 0x0F70 (3952) +0x738D, 0x2124, 0x31C6, 0x4228, 0x20E3, 0x3144, 0x18A1, 0x3921, 0x9325, 0xA322, 0xAB62, 0xBBA2, 0xCBC1, 0xCBC1, 0xD421, 0xD461, // 0x0F80 (3968) +0xDCA1, 0xD481, 0xC401, 0xAB40, 0x9AC0, 0xAB21, 0xC3C1, 0xCBE1, 0xCB81, 0xC361, 0xBB22, 0xAAA1, 0x9261, 0x92A2, 0x9303, 0x9B42, // 0x0F90 (3984) +0x9B21, 0xA341, 0x9B21, 0xAB63, 0xBBE4, 0xBBA3, 0xA302, 0x9281, 0x92E1, 0x9B82, 0x93C1, 0x8360, 0x7300, 0x72E0, 0x8360, 0x9C01, // 0x0FA0 (4000) +0x8320, 0x9360, 0xABE1, 0xB3E1, 0xAB80, 0xB3A0, 0xBC20, 0xC440, 0xBC60, 0xB440, 0xAC00, 0xB3E0, 0xC400, 0xD421, 0xD3C1, 0xC320, // 0x0FB0 (4016) +0xAA80, 0xA241, 0x9221, 0x8A20, 0x8A80, 0x9320, 0x9BC0, 0xAC01, 0x9B81, 0x7A80, 0x6AC6, 0xAD52, 0xC5F6, 0xA513, 0xA533, 0xAD74, // 0x0FC0 (4032) +0xBE18, 0x634D, 0x5AEB, 0x2986, 0x10A2, 0x18C2, 0x39C6, 0x6AE8, 0xA384, 0xB3A2, 0xBBE2, 0xC401, 0xD441, 0xD461, 0xDC80, 0xE4C1, // 0x0FD0 (4048) +0xE500, 0xDCE1, 0xC441, 0xAB40, 0x9280, 0x9AC0, 0xBB81, 0xD443, 0xDC64, 0xDC64, 0xD423, 0xB341, 0x9280, 0x8A41, 0x8262, 0x8AA2, // 0x0FE0 (4064) +0x92E1, 0x9B01, 0xAB42, 0xBBE4, 0xD485, 0xCC64, 0xB3A2, 0x9B00, 0x9B40, 0xABE2, 0xB462, 0xAC01, 0x9360, 0x9360, 0x93E0, 0xA461, // 0x0FF0 (4080) +0x7300, 0x7B20, 0x8B40, 0x9340, 0x9320, 0x9B60, 0xB400, 0xBC60, 0xBC60, 0xAC40, 0xA3E0, 0xA3C0, 0xBBC0, 0xCBE1, 0xC381, 0xB2C0, // 0x1000 (4096) +0x9A40, 0x9241, 0x8A21, 0x8220, 0x8260, 0x82E0, 0x8361, 0x83A1, 0x8301, 0x6A81, 0x5223, 0x9CAF, 0xC5F6, 0xB5B6, 0xA534, 0xAD95, // 0x1010 (4112) +0xA554, 0x5B0C, 0x2104, 0x2945, 0x31A6, 0x2965, 0x738D, 0x7348, 0xA3C4, 0xC402, 0xC422, 0xCC41, 0xD480, 0xD480, 0xD460, 0xE4C0, // 0x1020 (4128) +0xE500, 0xDCE0, 0xCC40, 0xAB20, 0x9A80, 0xA2A0, 0xBB81, 0xD443, 0xE4A3, 0xECE4, 0xE503, 0xCC62, 0xAB41, 0x8A60, 0x7A20, 0x8261, // 0x1030 (4144) +0x8AC0, 0x9B00, 0xB362, 0xCC23, 0xDCC4, 0xD4C3, 0xBC42, 0xA3A0, 0xA3A0, 0xB400, 0xC461, 0xCC61, 0xBC00, 0xABC0, 0xA420, 0xAC80, // 0x1040 (4160) +0x6300, 0x6B00, 0x7B00, 0x82E0, 0x82E0, 0x9360, 0xAC21, 0xB461, 0xAC40, 0xA420, 0x93C0, 0x9360, 0xA360, 0xB381, 0xAB21, 0x9A80, // 0x1050 (4176) +0x8A40, 0x8241, 0x8241, 0x7A20, 0x7A60, 0x7AC0, 0x7321, 0x7341, 0x6AE2, 0x6283, 0x4A02, 0x8C0D, 0xCE17, 0xAD55, 0xAD75, 0xAD75, // 0x1060 (4192) +0x3A07, 0x18E3, 0x4228, 0x630B, 0x39E7, 0x4228, 0x8C4F, 0x6AA5, 0xABE4, 0xC423, 0xCC43, 0xD463, 0xD4A2, 0xD480, 0xD440, 0xDC81, // 0x1070 (4208) +0xECE0, 0xE4C1, 0xCBE0, 0xAAC0, 0x9A40, 0xA281, 0xBB41, 0xCC02, 0xD462, 0xE4C2, 0xE522, 0xE4E1, 0xC441, 0xA360, 0x92C0, 0x8AA0, // 0x1080 (4224) +0x8AC0, 0x9B01, 0xB382, 0xCC23, 0xD4A3, 0xD4C2, 0xBCA1, 0xAC20, 0xA3E0, 0xABE0, 0xC440, 0xD481, 0xCC80, 0xC440, 0xB460, 0xB460, // 0x1090 (4240) +0x6B00, 0x6B00, 0x8320, 0x8320, 0x8300, 0x9360, 0xA401, 0xAC21, 0x9C00, 0x93C0, 0x8360, 0x7B00, 0x8B00, 0x9B20, 0x9B00, 0x8A80, // 0x10A0 (4256) +0x8280, 0x8281, 0x8260, 0x8240, 0x8A40, 0x8AC0, 0x7B20, 0x6B00, 0x62A2, 0x5A62, 0x5A64, 0x8BEC, 0xC5F6, 0xBDB7, 0x9CB2, 0x5ACB, // 0x10B0 (4272) +0x52CA, 0x6B6D, 0x7BCD, 0x630B, 0x2124, 0x6B6C, 0x736A, 0x6A84, 0xABC5, 0xBBE3, 0xCC44, 0xDCA4, 0xDCC3, 0xD481, 0xD421, 0xD421, // 0x10C0 (4288) +0xDC82, 0xDC62, 0xBB80, 0xA280, 0x9200, 0xA281, 0xB322, 0xC3A2, 0xC401, 0xD481, 0xDD01, 0xE521, 0xD4C2, 0xC441, 0xB3A0, 0xA320, // 0x10D0 (4304) +0x92E0, 0x9B20, 0xB3A2, 0xC402, 0xCC62, 0xCCA2, 0xBCA1, 0xAC60, 0xA420, 0xA400, 0xB420, 0xC460, 0xCC81, 0xCCA1, 0xC481, 0xB420, // 0x10E0 (4320) +0x72E0, 0x7AE0, 0x8B20, 0x9320, 0x9320, 0x9B40, 0xA3A1, 0x9BA1, 0x8B60, 0x8360, 0x7320, 0x72C0, 0x7AA0, 0x9300, 0x9B00, 0x8AC0, // 0x10F0 (4336) +0x82C0, 0x82A0, 0x8A60, 0x9240, 0xA240, 0xA2C0, 0x8B20, 0x72E0, 0x6260, 0x6AC4, 0x5A83, 0x942C, 0xCE37, 0xC5F7, 0x7BCE, 0x73AD, // 0x1100 (4352) +0xB575, 0x9471, 0x842F, 0x5AEA, 0x4A48, 0x736C, 0x5243, 0x7B04, 0x9B64, 0xA363, 0xC3E4, 0xE4A5, 0xE4C3, 0xD481, 0xCC21, 0xC3E1, // 0x1110 (4368) +0xC402, 0xBBC2, 0xA320, 0x8A60, 0x8220, 0x8A41, 0x9AC1, 0xA321, 0xAB41, 0xBC01, 0xD4A2, 0xDD02, 0xD4C2, 0xCC61, 0xC420, 0xB3C0, // 0x1120 (4384) +0xA360, 0x9B41, 0xAB82, 0xB3A1, 0xBBE0, 0xC461, 0xBCA0, 0xAC60, 0xA440, 0x9C00, 0x9BC0, 0xA3E0, 0xB420, 0xC481, 0xC461, 0xB3E0, // 0x1130 (4400) +0x7A81, 0x82A0, 0x92E0, 0x9B00, 0x9300, 0x9B21, 0x9B61, 0x9341, 0x8300, 0x7B01, 0x72E1, 0x6AA0, 0x7AA0, 0x92E0, 0x9B20, 0x9B20, // 0x1140 (4416) +0x8AE0, 0x8AA0, 0x9A60, 0xA240, 0xB220, 0xBAA0, 0x9B20, 0x7AC0, 0x6A80, 0x6AA2, 0x6283, 0xA4CE, 0xC5F6, 0xC638, 0xA533, 0xAD74, // 0x1150 (4432) +0xBDB6, 0xA4F3, 0x8C70, 0x5289, 0x39C6, 0x5246, 0x6283, 0x8303, 0x82C2, 0x92C2, 0xBBA3, 0xDC84, 0xE4C2, 0xDCA1, 0xCC41, 0xB3C0, // 0x1160 (4448) +0x9B60, 0x9300, 0x82A0, 0x7A40, 0x7A40, 0x8241, 0x8A81, 0x92A1, 0x92C0, 0xA341, 0xBC22, 0xCC82, 0xC420, 0xBBE0, 0xC420, 0xC441, // 0x1170 (4464) +0xABC1, 0xA361, 0xA341, 0xA320, 0xAB60, 0xBC21, 0xBC80, 0xAC60, 0x9C40, 0x93E0, 0x8B80, 0x8B60, 0xA3C0, 0xB420, 0xBC00, 0xABC0, // 0x1180 (4480) +0x8A40, 0x8220, 0x8A60, 0x92C1, 0x92E1, 0x92E2, 0x8303, 0x8303, 0x7AC3, 0x72C2, 0x6AA1, 0x6A80, 0x7AA0, 0x9300, 0xA341, 0xA321, // 0x1190 (4496) +0x92E1, 0x9AA1, 0xA220, 0xB1E0, 0xB220, 0xBA81, 0xAAC1, 0x8AA0, 0x7260, 0x6A82, 0x62A5, 0xAD51, 0xBDD5, 0xBDF6, 0xB5D6, 0xA514, // 0x11A0 (4512) +0xBDF7, 0xCE59, 0x8C50, 0x5A88, 0x6A47, 0x7A45, 0x8243, 0x8A62, 0x8241, 0x8A61, 0xAB04, 0xCBE5, 0xD463, 0xCC62, 0xC402, 0xAB81, // 0x11B0 (4528) +0x8B21, 0x72E1, 0x62C0, 0x62A0, 0x6AA1, 0x72C2, 0x7AA1, 0x82A0, 0x8280, 0x92A0, 0xAB22, 0xB363, 0xA321, 0x9B00, 0xAB80, 0xC422, // 0x11C0 (4544) +0xBBC1, 0xAB61, 0x9300, 0x8AE0, 0x9B40, 0xB420, 0xBC81, 0xAC40, 0xA420, 0x9BE0, 0x9360, 0x9320, 0xA3A0, 0xB420, 0xB421, 0xA3A0, // 0x11D0 (4560) +0x8221, 0x8200, 0x8240, 0x8A81, 0x92A1, 0x8AA1, 0x82A2, 0x7AC3, 0x72A3, 0x72A3, 0x6AA2, 0x7281, 0x7AA0, 0x92E1, 0xA301, 0xA2E1, // 0x11E0 (4576) +0x9AC1, 0xA281, 0xAA01, 0xB1C0, 0xB1C0, 0xB221, 0xA261, 0x9260, 0x7241, 0x6A42, 0x62A6, 0x9C8F, 0xAD53, 0xBDD6, 0xB575, 0xA513, // 0x11F0 (4592) +0xC638, 0xBDD6, 0xA513, 0x62A9, 0x7287, 0x7A25, 0x8243, 0x8222, 0x8201, 0x8221, 0x9A83, 0xB343, 0xB3A2, 0xBBC2, 0xB3C3, 0xA383, // 0x1200 (4608) +0x8362, 0x6B21, 0x62E0, 0x5AC0, 0x6AC1, 0x72C2, 0x7AC1, 0x82C1, 0x8280, 0x8A60, 0x9280, 0x9280, 0x8260, 0x7A40, 0x92E0, 0xAB81, // 0x1210 (4624) +0xB3A2, 0xAB41, 0x92C0, 0x8AA0, 0x9B40, 0xBC21, 0xBC61, 0xB400, 0xA3E0, 0xA3C0, 0x9B80, 0xABA0, 0xB420, 0xC441, 0xB421, 0xA3A0, // 0x1220 (4640) +0x8A01, 0x8200, 0x8220, 0x8A61, 0x8A61, 0x8A62, 0x7A82, 0x7283, 0x7A83, 0x7283, 0x72A3, 0x7AA2, 0x8281, 0x92A1, 0x9AC1, 0x9AC1, // 0x1230 (4656) +0x9AA2, 0xA282, 0xB202, 0xB181, 0xB160, 0xA9A1, 0xA201, 0x9222, 0x7A23, 0x6A23, 0x7B08, 0x8BCD, 0x83CE, 0xBDB6, 0xBDB6, 0xA4F3, // 0x1240 (4672) +0xBDF6, 0xB5B6, 0xC637, 0x940E, 0x7AA7, 0x7A23, 0x8222, 0x8A22, 0x81E2, 0x81C2, 0x9222, 0x9A83, 0x9AC2, 0x9AE2, 0x9B23, 0x9364, // 0x1250 (4688) +0x8363, 0x6B22, 0x5B00, 0x5AE0, 0x6AE1, 0x72E1, 0x82E1, 0x8AE2, 0x92E1, 0x92A1, 0x8A60, 0x8220, 0x7200, 0x69E0, 0x7A40, 0x92E1, // 0x1260 (4704) +0xAB62, 0xA321, 0x8A80, 0x8260, 0xA320, 0xBC01, 0xC441, 0xB3E0, 0xB3E0, 0xB3E1, 0xABC1, 0xBBE1, 0xCC62, 0xC441, 0xB400, 0xB3E0, // 0x1270 (4720) +0x8A01, 0x81E1, 0x8221, 0x8A61, 0x8A62, 0x8262, 0x7A63, 0x7263, 0x7264, 0x7A63, 0x7A83, 0x8283, 0x8A82, 0x92A2, 0x9AA2, 0xA2A2, // 0x1280 (4736) +0x9AA2, 0xAA62, 0xB202, 0xB161, 0xA920, 0xA941, 0xA1C2, 0x9203, 0x7A23, 0x61E3, 0x6A87, 0xB4F2, 0x9470, 0x9CD2, 0xBDB6, 0x9CB2, // 0x1290 (4752) +0xBDD6, 0xBDD6, 0xC618, 0xACB1, 0x7A85, 0x8222, 0x8A22, 0x8A02, 0x81C2, 0x89C2, 0x9222, 0x9242, 0x8A62, 0x8A83, 0x8AC3, 0x8B24, // 0x12A0 (4768) +0x7343, 0x6321, 0x5B21, 0x5B00, 0x6AE1, 0x7AE1, 0x82E1, 0x92E1, 0xA322, 0x9B02, 0x8A81, 0x7A41, 0x7221, 0x6201, 0x6A00, 0x8281, // 0x12B0 (4784) +0x9B21, 0x9B01, 0x8A80, 0x8260, 0xA320, 0xBBE2, 0xC401, 0xBBE0, 0xBC01, 0xBC01, 0xB3C1, 0xBBE1, 0xCC42, 0xC421, 0xB3E1, 0xB401, // 0x12C0 (4800) +}; diff --git a/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/cat.c b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/cat.c new file mode 100644 index 0000000..bfc86c0 --- /dev/null +++ b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/cat.c @@ -0,0 +1,314 @@ +// Generated by : ImageConverter 565 v1.2 +// Dimensions : 80x60 pixels +// Size : 9 600 Bytes + +#if defined(__AVR__) + #include +#elif defined(__PIC32MX__) + #define PROGMEM +#elif defined(__arm__) + #define PROGMEM +#endif + +const unsigned short cat[0x12C0] PROGMEM ={ +0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0820, 0x0800, 0x0000, 0x0820, 0x1062, 0x0820, // 0x0010 (16) +0x0800, 0x28E3, 0x3144, 0x2903, 0x20A1, 0x1040, 0x0820, 0x0820, 0x1041, 0x20C3, 0x20E3, 0x1862, 0x1882, 0x1882, 0x18C2, 0x0840, // 0x0020 (32) +0x1000, 0x3103, 0x3103, 0x41C6, 0x6289, 0x5A68, 0x3144, 0x2081, 0x6289, 0x944F, 0x732A, 0x8BCD, 0x8BCD, 0x940E, 0x9C4F, 0x8BAC, // 0x0030 (48) +0x49E5, 0x4184, 0x6AEA, 0x5A68, 0x3964, 0x2903, 0x0800, 0x0800, 0x0800, 0x1881, 0x1041, 0x1882, 0x20A2, 0x20A2, 0x20A2, 0x20C2, // 0x0040 (64) +0x28C1, 0x28C1, 0x28E2, 0x28C2, 0x28C2, 0x28A2, 0x2082, 0x2082, 0x28C2, 0x28C2, 0x2903, 0x2903, 0x28E2, 0x2903, 0x2923, 0x2923, // 0x0050 (80) +0x0820, 0x0821, 0x0820, 0x0800, 0x0800, 0x0820, 0x0800, 0x0800, 0x0800, 0x0820, 0x0820, 0x0800, 0x0820, 0x0820, 0x94B2, 0xB575, // 0x0060 (96) +0x734D, 0x4186, 0x41C6, 0x5248, 0x6AEA, 0x5247, 0x3984, 0x3964, 0x3103, 0x20C2, 0x3124, 0x3144, 0x20C2, 0x1881, 0x3144, 0x39A5, // 0x0070 (112) +0x3944, 0x49C6, 0x5227, 0x83AD, 0x9C70, 0x7B6C, 0x732B, 0x6289, 0xACF2, 0xBD53, 0x9C4F, 0x6AC9, 0x732A, 0x5A67, 0xA490, 0xA4B0, // 0x0080 (128) +0x5A47, 0x2080, 0x3964, 0x5227, 0x6ACA, 0x734C, 0x3144, 0x1000, 0x1020, 0x1881, 0x1020, 0x1861, 0x1840, 0x3103, 0x28E2, 0x2081, // 0x0090 (144) +0x28C2, 0x1880, 0x2081, 0x28C2, 0x28E2, 0x20A1, 0x1881, 0x20A2, 0x20A2, 0x20C2, 0x28E2, 0x28E2, 0x20E2, 0x2903, 0x2923, 0x2903, // 0x00A0 (160) +0x0821, 0x0821, 0x0800, 0x0000, 0x0800, 0x0820, 0x0800, 0x0000, 0x0820, 0x0821, 0x0800, 0x0000, 0x0000, 0x0000, 0x4A28, 0xBDB6, // 0x00B0 (176) +0xE6FB, 0xD638, 0xACF3, 0x7B4C, 0x4A07, 0x6288, 0x7B4B, 0x7B4B, 0x7B6C, 0x6AA9, 0x4185, 0x4185, 0x49E6, 0x49C6, 0x5A68, 0x734B, // 0x00C0 (192) +0x6AEA, 0x6AC9, 0x734B, 0x9C70, 0x8C0F, 0x7B6C, 0x7B6C, 0x9C90, 0xD617, 0xAD12, 0x6289, 0x6ACA, 0x732B, 0x3984, 0x9C50, 0xCDD6, // 0x00D0 (208) +0x5A68, 0x2902, 0x5227, 0x732B, 0x944F, 0xA491, 0x7B4C, 0x28E3, 0x4185, 0x4185, 0x28C2, 0x1840, 0x1020, 0x28C2, 0x2081, 0x2081, // 0x00E0 (224) +0x1881, 0x20A2, 0x1881, 0x1861, 0x20A2, 0x20A1, 0x2081, 0x20A2, 0x28E2, 0x2903, 0x28E2, 0x28E2, 0x28E3, 0x28E2, 0x2903, 0x2903, // 0x00F0 (240) +0x0820, 0x0820, 0x0000, 0x0000, 0x0000, 0x0820, 0x0800, 0x0000, 0x0000, 0x0820, 0x0000, 0x0820, 0x0000, 0x0820, 0x0841, 0x18A3, // 0x0100 (256) +0x630C, 0xBDD7, 0xDE99, 0xE6DB, 0xBDB5, 0x9C71, 0x7B4C, 0x6AA9, 0x6AEA, 0x6ACA, 0x5A68, 0x41A5, 0x5227, 0x940E, 0x9C90, 0x83CD, // 0x0110 (272) +0x732A, 0x838C, 0x9C70, 0xACD1, 0x8BEE, 0x7B6C, 0x940F, 0xB533, 0xE699, 0xB533, 0x5A68, 0x734C, 0x62A9, 0x49E6, 0xACF2, 0xD657, // 0x0120 (288) +0x83AD, 0x5248, 0x5227, 0x62A9, 0xA4D2, 0xACF2, 0x8BCE, 0x6289, 0x5207, 0x5207, 0x5A68, 0x49C6, 0x28E2, 0x1840, 0x2081, 0x2081, // 0x0130 (304) +0x20A2, 0x20A2, 0x20A2, 0x28E3, 0x28E2, 0x20C2, 0x20C2, 0x20C2, 0x20C2, 0x3123, 0x3123, 0x3103, 0x2903, 0x20A2, 0x20E3, 0x28E3, // 0x0140 (320) +0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, 0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0821, // 0x0150 (336) +0x3186, 0x6B6E, 0x94B3, 0xC5F8, 0xDEBB, 0xEF1C, 0xDE9A, 0xC5B6, 0xA4B2, 0x9C71, 0x9C70, 0xA4B1, 0x942F, 0x9C90, 0x9C90, 0x7B6C, // 0x0160 (352) +0x7B6B, 0x9C6F, 0xACF1, 0xACD1, 0x7B8C, 0x734B, 0x83CD, 0xBD54, 0xCDF6, 0xCDD6, 0x734C, 0x8C0F, 0x49E6, 0x5A89, 0xBD75, 0xD658, // 0x0170 (368) +0x83AD, 0x734B, 0x62C9, 0x7B6C, 0xACD1, 0xACD1, 0x93EE, 0x6268, 0x51E6, 0x83AD, 0x9C4F, 0x72EA, 0x5A27, 0x49A5, 0x5207, 0x41A6, // 0x0180 (384) +0x3945, 0x20C3, 0x2082, 0x20A2, 0x2081, 0x28E2, 0x3144, 0x28E2, 0x3985, 0x3144, 0x28E3, 0x20C3, 0x20E3, 0x1040, 0x1040, 0x20C2, // 0x0190 (400) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, 0x0000, 0x0000, 0x0000, 0x0820, 0x0800, 0x0000, // 0x01A0 (416) +0x18C3, 0x736E, 0x8C72, 0xAD36, 0xC619, 0xD67B, 0xD69B, 0xE6FC, 0xEF3D, 0xEEFC, 0xE71B, 0xE6B9, 0xCE37, 0xBD74, 0x940E, 0x838C, // 0x01B0 (432) +0x940E, 0xA4B0, 0xA4B0, 0x942E, 0x6288, 0x5A47, 0xA4B1, 0x7B6C, 0x942F, 0xCDD6, 0x8BEE, 0x9C70, 0x6AEA, 0x9C70, 0x942F, 0xA491, // 0x01C0 (448) +0xA4B1, 0x62A9, 0x6AC9, 0x83AD, 0xACB1, 0xACB1, 0x93EE, 0x62A8, 0x72C9, 0x8BAD, 0xA470, 0xA470, 0x942F, 0x7B6C, 0x730B, 0x5207, // 0x01D0 (464) +0x3124, 0x20A2, 0x1040, 0x1881, 0x3964, 0x5247, 0x62C9, 0x62A9, 0x49E7, 0x5A69, 0x8C10, 0xAD14, 0xC5D7, 0xACF4, 0x5A89, 0x20E3, // 0x01E0 (480) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0800, 0x0841, // 0x01F0 (496) +0x0820, 0x6B2D, 0xA4F5, 0xB597, 0xC63A, 0xD67C, 0xD69C, 0xCE7B, 0xCE39, 0xCE79, 0xD699, 0xD678, 0xBD95, 0xA4B1, 0x8BCD, 0x7B2A, // 0x0200 (512) +0x9C6F, 0xACF1, 0x9C4F, 0x6AC9, 0x41A5, 0x7B6C, 0xA491, 0x5227, 0x7B4B, 0xC5B5, 0xACD2, 0x83AD, 0x9C4F, 0xC5B5, 0x5A68, 0x5A47, // 0x0210 (528) +0xACD2, 0x836C, 0x51E6, 0x6AA9, 0xA46F, 0xACB0, 0x9C4E, 0x7B2A, 0x836B, 0x93EE, 0xA490, 0xBD53, 0xCDD5, 0xACB1, 0x732B, 0x49E6, // 0x0220 (544) +0x28E2, 0x1020, 0x0800, 0x2902, 0x5247, 0x5A88, 0x62A9, 0x734D, 0xA4D3, 0xDE7A, 0xDEBB, 0xDEBB, 0xCE18, 0xAD14, 0x9CD2, 0x4207, // 0x0230 (560) +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0820, 0x0000, 0x0800, 0x0000, 0x0800, // 0x0240 (576) +0x0800, 0x41C7, 0xAD35, 0xB577, 0xC61A, 0xBDD9, 0xBE1A, 0xC63A, 0xC619, 0xBDF8, 0xD699, 0xD658, 0xB533, 0xA470, 0x9C0E, 0x8BAD, // 0x0250 (592) +0x8BAD, 0xA490, 0x9C70, 0x730A, 0x6AE9, 0xACF2, 0xACF2, 0x8BEE, 0x838C, 0xCDF6, 0x9C70, 0x9C4F, 0xC574, 0xB4F2, 0x72EA, 0x7B4C, // 0x0260 (608) +0xB533, 0xACF2, 0x5206, 0x7B4B, 0x9C4F, 0xB4D1, 0x9C4F, 0x940E, 0x93CD, 0x9C0E, 0xACB0, 0xB513, 0xCDF6, 0xD617, 0xC5D5, 0xBD95, // 0x0270 (624) +0x8BEE, 0x6289, 0x6288, 0x7B8C, 0x8C0E, 0xA4B1, 0xC5B5, 0xDE9A, 0xD65A, 0xC5B8, 0xB556, 0x9CB4, 0x7BAF, 0x630C, 0x6B4C, 0x3185, // 0x0280 (640) +0x0000, 0x0800, 0x0820, 0x0820, 0x0800, 0x0800, 0x0800, 0x0820, 0x0800, 0x0800, 0x0820, 0x0820, 0x0800, 0x0000, 0x0800, 0x0820, // 0x0290 (656) +0x1060, 0x1041, 0x8BF1, 0xCE1A, 0xB598, 0xC61A, 0xCE5B, 0xCE3A, 0xD67B, 0xCE39, 0xDE79, 0xC5B5, 0xA4B0, 0x942E, 0x7B6B, 0x838C, // 0x02A0 (672) +0x836C, 0x940E, 0xB513, 0x9450, 0x9430, 0xCDF7, 0xD658, 0xA4B1, 0x8BAD, 0xACB1, 0x9C2E, 0xAC90, 0xBD73, 0x7B4C, 0x944F, 0xC5D6, // 0x02B0 (688) +0xCDD6, 0xBD13, 0x8BAD, 0x93EE, 0xA490, 0xACB1, 0xB4D1, 0xA42E, 0x9BED, 0xA40D, 0x9BED, 0xAC6F, 0xCD94, 0xDE99, 0xDEBA, 0xE6DB, // 0x02C0 (704) +0xE6DB, 0xE6DB, 0xDE9A, 0xCE39, 0xDE7A, 0xE6BC, 0xCE3A, 0xC5F9, 0xBDB8, 0xA515, 0x9452, 0x734E, 0x62EC, 0x9CB3, 0x734D, 0x20C3, // 0x02D0 (720) +0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0820, 0x0820, 0x0800, 0x0800, 0x0820, 0x0820, 0x0800, 0x0800, 0x0820, 0x1020, // 0x02E0 (736) +0x1861, 0x1041, 0x522A, 0xD67C, 0xC61A, 0xCE5B, 0xD67B, 0xDEDD, 0xDEBC, 0xD67A, 0xC5D7, 0xBD74, 0xA4B0, 0x83AC, 0x6AC9, 0x5A27, // 0x02F0 (752) +0x6288, 0xA490, 0xAD12, 0x940F, 0x9C70, 0xCDD7, 0xE6DA, 0xB4F2, 0x93EE, 0x8BAD, 0x836C, 0x942E, 0xACD1, 0x7B6C, 0xC5B5, 0xE6DA, // 0x0300 (768) +0xDE37, 0xACD2, 0x8BCD, 0x9C90, 0xA4D2, 0x838D, 0x838C, 0x940E, 0x9BED, 0x93CC, 0x93AC, 0x9C2E, 0xBD53, 0xDE78, 0xDE99, 0xC5F8, // 0x0310 (784) +0xC5D7, 0xBDB7, 0xC5D7, 0xD65A, 0xCE3A, 0xCE19, 0xCE5A, 0xCE1A, 0xB577, 0x9CD4, 0x9CB4, 0x9CB3, 0xBD97, 0xAD35, 0x3986, 0x28E4, // 0x0320 (800) +0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x1040, // 0x0330 (816) +0x1061, 0x1061, 0x3186, 0xCE1A, 0xDEDC, 0xCE3A, 0xDEDD, 0xE6FD, 0xD65A, 0xC5B7, 0xB554, 0xB513, 0xACF1, 0x83AC, 0x51E6, 0x3102, // 0x0340 (832) +0x5A47, 0xB533, 0xACD2, 0x4A07, 0x8C0F, 0xD638, 0xE6DA, 0xC5B5, 0x8BEE, 0x838C, 0x9C4F, 0x9C4F, 0x9C70, 0x9C90, 0xE6D9, 0xEEFA, // 0x0350 (848) +0xCDF6, 0x838C, 0x732B, 0xACF2, 0xACF2, 0x6AEA, 0x49E6, 0x7B0A, 0x8BAC, 0x9C0E, 0xA42F, 0xA44F, 0xACF2, 0xCDD6, 0xC5F7, 0xB555, // 0x0360 (864) +0xB576, 0xC5F8, 0xCE39, 0xD67B, 0xD67B, 0xD69B, 0xD69C, 0xCE5B, 0xC5FA, 0xB598, 0xBDB8, 0xCE19, 0xD67A, 0x6B0C, 0x18A2, 0x28E3, // 0x0370 (880) +0x1020, 0x0820, 0x0820, 0x0820, 0x0820, 0x1020, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x1020, // 0x0380 (896) +0x1040, 0x1061, 0x2904, 0xB576, 0xDEDC, 0xC61A, 0xDEBC, 0xE6FD, 0xCE18, 0xB534, 0xBD74, 0xB512, 0xA4B1, 0x836C, 0x5A48, 0x5A48, // 0x0390 (912) +0x4164, 0xACD2, 0xBD54, 0x3985, 0x83CE, 0xE6DA, 0xFF9D, 0xD657, 0xBD53, 0xACD1, 0xB532, 0xBD53, 0xBD73, 0xD637, 0xEF3B, 0xEEFA, // 0x03A0 (928) +0xAD12, 0x41C5, 0x62C9, 0xC595, 0xC5B5, 0x6AC9, 0x3122, 0x51E5, 0x72C9, 0x9BED, 0xAC90, 0xA490, 0xB512, 0xCDB5, 0xC5B6, 0xBD96, // 0x03B0 (944) +0xC5D7, 0xCE5A, 0xD69B, 0xCE3A, 0xC63A, 0xC61A, 0xC5FA, 0xCE7B, 0xCE3A, 0xCE3A, 0xD67B, 0xEF1D, 0xB596, 0x3145, 0x3124, 0x20E3, // 0x03C0 (960) +0x0820, 0x0800, 0x0800, 0x0820, 0x1020, 0x1020, 0x1020, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, 0x0820, // 0x03D0 (976) +0x1061, 0x0840, 0x20E3, 0xA4F4, 0xEF5E, 0xBDB8, 0xBD97, 0xDE9B, 0xDE79, 0xB513, 0xACF2, 0xACF2, 0xA491, 0x8BCE, 0x93EE, 0xA491, // 0x03E0 (992) +0x940F, 0x8BCE, 0xC5D6, 0x7B6C, 0x9450, 0xEF3C, 0xFF9D, 0xE6B9, 0xDE57, 0xD616, 0xC594, 0xD616, 0xDE78, 0xE6FA, 0xFFBD, 0xEF1A, // 0x03F0 (1008) +0x942F, 0x3984, 0x838C, 0xCDF6, 0x7B4B, 0x4163, 0x4163, 0x4984, 0x5205, 0x8BAC, 0xBCF1, 0xBCF1, 0xBCF2, 0xC533, 0xC574, 0xCDD6, // 0x0400 (1024) +0xD679, 0xD69A, 0xDEBB, 0xD69B, 0xD67B, 0xCE5B, 0xC5F9, 0xBDD9, 0xCE5B, 0xDE9C, 0xDEDC, 0xDEDC, 0x62CB, 0x18A2, 0x28E3, 0x20E2, // 0x0410 (1040) +0x0820, 0x0820, 0x0820, 0x1021, 0x1041, 0x1041, 0x1041, 0x1041, 0x1021, 0x1021, 0x1021, 0x1041, 0x1041, 0x1021, 0x1021, 0x1021, // 0x0420 (1056) +0x1040, 0x1061, 0x1061, 0x4A28, 0xE6DC, 0xE6BC, 0xD67A, 0xD619, 0xC5D6, 0xBD53, 0xB533, 0xACD1, 0xA491, 0xBD54, 0xB554, 0xB513, // 0x0430 (1072) +0xC5B5, 0xBD95, 0xDE99, 0xBD75, 0xC5D6, 0xFF9D, 0xF79D, 0xDEB9, 0xD637, 0xDE98, 0xDE77, 0xDE77, 0xDE98, 0xEF1B, 0xFFDE, 0xE71B, // 0x0440 (1088) +0x9450, 0x6AEA, 0xD616, 0x9C70, 0x6AC9, 0x838C, 0x9C4F, 0x8BAC, 0x834B, 0x9C0D, 0xBD11, 0xBD32, 0xC532, 0xC533, 0xBD12, 0xB4F2, // 0x0450 (1104) +0xB554, 0xDE9A, 0xEF3D, 0xF75E, 0xEF3E, 0xE6DD, 0xD65B, 0xC5D9, 0xC5F9, 0xDE9B, 0xEF3E, 0xCE39, 0x39A6, 0x2904, 0x28E3, 0x2903, // 0x0460 (1120) +0x1040, 0x1040, 0x1040, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, 0x1041, // 0x0470 (1136) +0x1040, 0x1881, 0x1061, 0x2924, 0xBD96, 0xE6BC, 0xD639, 0xC5B6, 0xBD54, 0xBD53, 0xC594, 0xB512, 0xB4F3, 0xCDF7, 0xDE99, 0xE6B9, // 0x0480 (1152) +0xD658, 0xD658, 0xF77D, 0xFFBE, 0xEF3C, 0xFFBE, 0xF79D, 0xDEB9, 0xDE78, 0xE6B9, 0xE6D9, 0xD657, 0xDE98, 0xF75C, 0xFFDE, 0xF77D, // 0x0490 (1168) +0xBDD6, 0xCE37, 0xE6DA, 0xCDF6, 0xD617, 0xC594, 0xBD53, 0xB512, 0xACD1, 0xACD1, 0xBD33, 0xBD33, 0xC573, 0xC553, 0xBCF1, 0xACB1, // 0x04A0 (1184) +0xBD54, 0xD637, 0xDEBA, 0xEEFB, 0xE6DB, 0xC5D8, 0xB556, 0xB557, 0xCE1A, 0xDE9B, 0xDEBB, 0x8C10, 0x3145, 0x3144, 0x2903, 0x20C2, // 0x04B0 (1200) +0x1041, 0x1041, 0x1041, 0x1040, 0x1040, 0x1040, 0x1040, 0x1040, 0x1040, 0x1041, 0x1041, 0x1041, 0x1040, 0x1040, 0x1041, 0x1041, // 0x04C0 (1216) +0x1061, 0x1040, 0x18A2, 0x20C2, 0x9451, 0xE6DC, 0xC5D8, 0xA492, 0xB513, 0xCDD5, 0xBD73, 0xA490, 0xBD75, 0xCDF7, 0xD637, 0x9450, // 0x04D0 (1232) +0x41C6, 0x5269, 0x736D, 0xBDD6, 0xFFDE, 0xFFFF, 0xF79D, 0xCE58, 0xD678, 0xEEFA, 0xE6B9, 0xD637, 0xDE99, 0xF77C, 0xFFFF, 0xFFBE, // 0x04E0 (1248) +0xFFDF, 0xE6FB, 0xBDB6, 0xBD75, 0xBD95, 0xE6B9, 0xDE78, 0xD637, 0xC5D5, 0xBD54, 0xB512, 0xACD2, 0xC594, 0xCD94, 0xB511, 0xB4F1, // 0x04F0 (1264) +0xBD33, 0xB513, 0xD637, 0xE6BA, 0xCDF7, 0xB535, 0xB576, 0xD639, 0xD67A, 0xEF1D, 0xCE39, 0x41E8, 0x2904, 0x3144, 0x2102, 0x2943, // 0x0500 (1280) +0x0820, 0x1041, 0x1041, 0x1040, 0x1040, 0x1041, 0x1040, 0x0820, 0x1040, 0x1041, 0x1041, 0x1040, 0x1040, 0x1040, 0x1041, 0x1041, // 0x0510 (1296) +0x1061, 0x1881, 0x20C2, 0x20E2, 0x6B0B, 0xC5B5, 0x9C4F, 0x9C4F, 0xACB0, 0xB4D1, 0xC553, 0xC595, 0xBD54, 0xBD54, 0xACF2, 0x4A28, // 0x0520 (1312) +0x3A08, 0x2165, 0x2966, 0x39E8, 0x94B2, 0xFFFF, 0xFFBD, 0xDEB9, 0xDEB9, 0xE6F9, 0xE6FA, 0xD657, 0xE6FA, 0xFFDE, 0xFFDE, 0xFFFF, // 0x0530 (1328) +0x9CD3, 0x4A69, 0x41E7, 0x41E7, 0x4207, 0x5A8A, 0xBD95, 0xE6DA, 0xDE57, 0xCDD5, 0xBD52, 0xB511, 0xCDB4, 0xCDB4, 0xC594, 0xC594, // 0x0540 (1344) +0xC532, 0xA44F, 0xB4F2, 0xD638, 0xC5D7, 0xC5F8, 0xD69B, 0xDEFC, 0xE6FC, 0xEF5D, 0x7B8E, 0x20E3, 0x18A2, 0x2903, 0x2944, 0x2944, // 0x0550 (1360) +0x1040, 0x1041, 0x1061, 0x1041, 0x1041, 0x1061, 0x1061, 0x1041, 0x1041, 0x1041, 0x1041, 0x1061, 0x1041, 0x1040, 0x1041, 0x1061, // 0x0560 (1376) +0x1882, 0x20C2, 0x20E3, 0x2902, 0x39A5, 0x838C, 0x83AC, 0x940E, 0x93ED, 0x93CD, 0x8BAC, 0x8BAD, 0x9C50, 0xCE37, 0xB574, 0x632C, // 0x0570 (1392) +0x29C7, 0x0062, 0x08C3, 0x4A8B, 0x634D, 0xE71C, 0xFFFF, 0xDEDA, 0xDE99, 0xE6DA, 0xE6D9, 0xDEB9, 0xEF5C, 0xFFDE, 0xFFFF, 0xCE59, // 0x0580 (1408) +0x632D, 0x4A6A, 0x10C3, 0x18E4, 0x632C, 0x5AAA, 0x5269, 0xB574, 0xCDF6, 0xB533, 0xCDD5, 0xCDB5, 0xC573, 0xBD53, 0xC574, 0xB4F1, // 0x0590 (1424) +0xB4D0, 0x9BED, 0x7B4B, 0xA4B1, 0xC5D7, 0xC5D7, 0xCE39, 0xD67B, 0xDEBB, 0xBD97, 0x41C7, 0x1040, 0x1881, 0x20E3, 0x3144, 0x3144, // 0x05A0 (1440) +0x1061, 0x1061, 0x1061, 0x1061, 0x1881, 0x1881, 0x1881, 0x1881, 0x1061, 0x1061, 0x1061, 0x1881, 0x1881, 0x1061, 0x1061, 0x1881, // 0x05B0 (1456) +0x20C2, 0x20C2, 0x20E2, 0x3144, 0x6289, 0x83AC, 0x8BAC, 0x93CD, 0x6267, 0x2060, 0x3943, 0x6AA9, 0xCDF6, 0xFF7D, 0x840F, 0x4A69, // 0x05C0 (1472) +0x08A3, 0x0084, 0x4ACC, 0x73F0, 0x5B0D, 0xAD56, 0xFFFF, 0xEF3C, 0xDEDA, 0xE6FB, 0xE6DA, 0xE6DA, 0xF79D, 0xFFFF, 0xEF5D, 0x8410, // 0x05D0 (1488) +0x6BAF, 0x08A4, 0x29A7, 0x31E9, 0x1925, 0x8C92, 0x5269, 0x9C92, 0xBD74, 0x83AD, 0x8BEE, 0xB512, 0xCDB5, 0xCD94, 0xC574, 0xC553, // 0x05E0 (1504) +0xBD11, 0xB4D1, 0x8B8C, 0x836C, 0xACF3, 0xC5D7, 0xCE18, 0xD659, 0xC5D7, 0xAD34, 0x5249, 0x1881, 0x20A2, 0x3144, 0x3164, 0x41C6, // 0x05F0 (1520) +0x1881, 0x1881, 0x1881, 0x1882, 0x18A2, 0x1882, 0x1882, 0x18A2, 0x1882, 0x1881, 0x1881, 0x18A2, 0x18A2, 0x1882, 0x1881, 0x1881, // 0x0600 (1536) +0x20A2, 0x20E3, 0x2903, 0x3964, 0x6AEA, 0x838C, 0x8BAC, 0x72C9, 0x3922, 0x5A27, 0x72C9, 0x7B4C, 0xE6DA, 0xFF9D, 0x630B, 0x4A69, // 0x0610 (1552) +0x2166, 0x10E5, 0x2167, 0x5B2D, 0x6B8F, 0x7BF0, 0xF7BF, 0xF77D, 0xE71B, 0xE6DA, 0xE6FA, 0xEF3C, 0xFFFF, 0xFF9E, 0x7B8E, 0x4209, // 0x0620 (1568) +0x6B8F, 0x00A4, 0x3A2A, 0x426B, 0x2187, 0x8452, 0x528A, 0xB555, 0xF77D, 0xB533, 0x730A, 0x5A27, 0x6268, 0x7B4B, 0x940F, 0xB4D1, // 0x0630 (1584) +0xC553, 0xB4B0, 0xAC90, 0x8BAD, 0x940F, 0xCDD6, 0xCDF7, 0xB555, 0x9C92, 0x6AEB, 0x3165, 0x3985, 0x39A5, 0x41C6, 0x41E6, 0x3164, // 0x0640 (1600) +0x18A2, 0x18A1, 0x18A1, 0x18A2, 0x18A2, 0x18A1, 0x1881, 0x18A2, 0x18A2, 0x18A2, 0x18A1, 0x18A1, 0x18A2, 0x18A2, 0x1881, 0x1881, // 0x0650 (1616) +0x18A1, 0x20C2, 0x28E2, 0x3964, 0x5206, 0x6AC9, 0x7B4B, 0x4184, 0x4984, 0x72C9, 0x6AA9, 0x72EB, 0xC5B5, 0xFF9D, 0xC5D6, 0x4A69, // 0x0660 (1632) +0x3A08, 0x3A09, 0x5ACC, 0x73AF, 0x526A, 0x3986, 0xAD14, 0xE6DA, 0xDEB9, 0xCDF6, 0xEEFA, 0xEEDA, 0xEEFA, 0xA4B1, 0x4A07, 0x39A7, // 0x0670 (1648) +0x634E, 0x426B, 0x1105, 0x2146, 0x5B4D, 0x6B6E, 0x4A49, 0xDEDB, 0xFFBE, 0xDE58, 0x940F, 0x7B2B, 0x5A27, 0x3102, 0x28E2, 0x49C6, // 0x0680 (1664) +0x72E9, 0x836C, 0x93EE, 0x8BAD, 0x8BCE, 0xC574, 0xACB2, 0x6ACA, 0x4A07, 0x2904, 0x39A6, 0x5249, 0x5268, 0x5A69, 0x41C6, 0x3964, // 0x0690 (1680) +0x20C2, 0x20C2, 0x20C2, 0x20C2, 0x20C2, 0x18A1, 0x18A1, 0x18A1, 0x18A1, 0x18A1, 0x18A1, 0x1881, 0x18A1, 0x18A1, 0x18A1, 0x1881, // 0x06A0 (1696) +0x1881, 0x20C2, 0x2923, 0x3985, 0x49E6, 0x5227, 0x3103, 0x3964, 0x7B2B, 0x4184, 0x49C6, 0x51E6, 0x732B, 0xBD74, 0xF75C, 0xF73B, // 0x06B0 (1712) +0xDE99, 0xE6FB, 0xFF9D, 0xF73C, 0x732C, 0x41A5, 0x83AD, 0xC594, 0xCDB5, 0xC5B4, 0xD616, 0xC594, 0x730A, 0x3923, 0x51E6, 0x83CE, // 0x06C0 (1728) +0xB5B6, 0xA535, 0x8431, 0x73AF, 0x73AE, 0x6B6D, 0xCE38, 0xFFBE, 0xF73B, 0xACB1, 0x6288, 0x7B4B, 0xA491, 0x940F, 0x5207, 0x1860, // 0x06D0 (1744) +0x28A1, 0x4165, 0x6AA9, 0x838D, 0x730B, 0xACD2, 0xCDD6, 0x7B6D, 0x1861, 0x20C2, 0x3185, 0x5269, 0x62EA, 0x62EA, 0x41E6, 0x2902, // 0x06E0 (1760) +0x20E2, 0x20E2, 0x20E2, 0x20E2, 0x20E2, 0x20C2, 0x20C2, 0x20C2, 0x20C2, 0x20C2, 0x20C2, 0x20C2, 0x20A2, 0x20C2, 0x20C2, 0x20C2, // 0x06F0 (1776) +0x2903, 0x2902, 0x2903, 0x3144, 0x5228, 0x4A27, 0x1040, 0x5A89, 0xBD75, 0x838D, 0x5227, 0x836C, 0x7B6C, 0x7B4B, 0x9C4F, 0xC594, // 0x0700 (1792) +0xD657, 0xDE98, 0xD617, 0xB4F2, 0x6268, 0x8B8C, 0x8BAD, 0xB512, 0xB4D1, 0xB4F1, 0xBD32, 0xA44F, 0x6288, 0x3943, 0x51E6, 0xCDB5, // 0x0710 (1808) +0xFFFE, 0xFFFE, 0xFFDE, 0xF77D, 0xEF1B, 0xF73C, 0xEF1A, 0xDE78, 0xA490, 0x5A47, 0x6AC9, 0x836C, 0x62A8, 0x732B, 0x9450, 0x732B, // 0x0720 (1824) +0x3144, 0x3104, 0x4A07, 0x838D, 0x7B4B, 0x8BCE, 0xB533, 0x9C91, 0x41A6, 0x1040, 0x2924, 0x4A48, 0x5AA9, 0x62EA, 0x5247, 0x3164, // 0x0730 (1840) +0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x28E3, 0x2903, 0x20E2, 0x20E2, 0x20E2, 0x20E2, 0x20C2, 0x20E2, 0x2923, // 0x0740 (1856) +0x3123, 0x3143, 0x3964, 0x3164, 0x2923, 0x18A2, 0x1881, 0x5A8A, 0xB554, 0x8BEF, 0x41A5, 0x6268, 0x836C, 0x838C, 0x834A, 0xA46F, // 0x0750 (1872) +0xB512, 0xA490, 0x836C, 0x7B2B, 0xACD1, 0xC594, 0xA42E, 0xB4B0, 0xA44E, 0xACB0, 0xACAF, 0xB4F1, 0x9C2E, 0x72EA, 0x49C5, 0x7B4C, // 0x0760 (1888) +0xBD73, 0xDE57, 0xDE78, 0xD657, 0xD637, 0xBD74, 0xACD1, 0xA470, 0x9C4F, 0x9C4F, 0xA470, 0x7B4B, 0x7B6B, 0x7B6C, 0x9C91, 0xCE38, // 0x0770 (1904) +0x83EF, 0x5228, 0x5228, 0x730B, 0x7B6C, 0x838D, 0x8BEE, 0xA4B1, 0x6B2B, 0x3165, 0x3165, 0x3185, 0x3165, 0x5248, 0x5A89, 0x39A5, // 0x0780 (1920) +0x2903, 0x2923, 0x2923, 0x2923, 0x2903, 0x2923, 0x2923, 0x2923, 0x2923, 0x2923, 0x2923, 0x2923, 0x2903, 0x2903, 0x2903, 0x2903, // 0x0790 (1936) +0x3144, 0x3123, 0x3985, 0x4A08, 0x3165, 0x3144, 0x5A8A, 0xB554, 0x8C0F, 0x49C6, 0x5207, 0x5227, 0x6ACA, 0x732B, 0xAD12, 0xE6B9, // 0x07A0 (1952) +0xBD94, 0x5227, 0x5207, 0xB554, 0xEF1B, 0xACF2, 0x7B4C, 0x838D, 0x8BCE, 0x8BCE, 0x83CD, 0x944F, 0xCE36, 0xE697, 0xACD0, 0x6267, // 0x07B0 (1968) +0x6268, 0xA490, 0xC574, 0xBD53, 0xBD53, 0xB4D1, 0xA470, 0x8BCD, 0x8BAD, 0x836C, 0x6288, 0x732B, 0xBD54, 0xE6B9, 0xE6DA, 0xE6FB, // 0x07C0 (1984) +0xCE17, 0x6AEC, 0x3985, 0x3986, 0x41C6, 0x62A9, 0x7B6C, 0x9450, 0x7B8D, 0x5248, 0x4A07, 0x4A48, 0x4207, 0x3185, 0x3164, 0x2943, // 0x07D0 (2000) +0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x20E2, 0x20E2, // 0x07E0 (2016) +0x3123, 0x41A6, 0x4A28, 0x5269, 0x4A28, 0x5269, 0x9451, 0xB554, 0xB554, 0x838D, 0x6ACA, 0x7B6C, 0x62A9, 0x9450, 0xD658, 0xE6B9, // 0x07F0 (2032) +0xD678, 0xC5D6, 0xBD95, 0xD678, 0xFFDE, 0x9430, 0x4185, 0x6248, 0x72EA, 0x5A48, 0x4A06, 0x5247, 0xD657, 0xFF9C, 0xE678, 0x72EA, // 0x0800 (2048) +0x49A5, 0x6ACA, 0xCDF6, 0xD5F6, 0xC595, 0xB533, 0xACD1, 0xACB1, 0xA470, 0x9C2F, 0x6AEA, 0x6AEA, 0x8BEE, 0x9C50, 0xACF3, 0xDE9A, // 0x0810 (2064) +0xEF1C, 0xB575, 0x5A8A, 0x3985, 0x3985, 0x3124, 0x4A07, 0x734C, 0x734C, 0x5AAA, 0x6B4C, 0x62EB, 0x3185, 0x10A1, 0x20E2, 0x3185, // 0x0820 (2080) +0x2903, 0x2923, 0x2923, 0x2923, 0x2903, 0x2923, 0x2923, 0x2923, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x28E3, 0x28E3, // 0x0830 (2096) +0x2923, 0x3985, 0x4A28, 0x5A89, 0x5269, 0x5AAA, 0xA4B2, 0x9430, 0x734C, 0x9C91, 0x8BEE, 0x734C, 0x9450, 0xBD75, 0xD679, 0xE6FB, // 0x0840 (2112) +0xEF3C, 0xEF5C, 0xFFFE, 0xFFBE, 0xFFFE, 0xD659, 0x3965, 0x5A28, 0x5A49, 0x5228, 0x5227, 0x8C0F, 0xFF7C, 0xFF7D, 0xDE38, 0xEEBA, // 0x0850 (2128) +0xDE78, 0xC5B6, 0xC5B6, 0xEF1B, 0xE6B9, 0xC5B6, 0xACF2, 0x8BEE, 0x7B4C, 0x732B, 0x6AEA, 0x6AEA, 0x62CA, 0x6B0B, 0x9C70, 0xDE79, // 0x0860 (2144) +0xE6DB, 0xE6FC, 0xB575, 0x6AEB, 0x41C6, 0x41A6, 0x5A69, 0x83CE, 0x5AAA, 0x5269, 0x6B2C, 0x4A49, 0x2123, 0x18A2, 0x3164, 0x4A28, // 0x0870 (2160) +0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2923, 0x2903, 0x2903, 0x2923, 0x2923, 0x2903, 0x2903, 0x2923, // 0x0880 (2176) +0x3144, 0x3985, 0x5269, 0x6B2C, 0x736D, 0x7BAE, 0x83CE, 0x5A89, 0x5269, 0x734C, 0x9C71, 0x8BEF, 0x83CE, 0xB554, 0xD638, 0xD679, // 0x0890 (2192) +0xE6DB, 0xE71C, 0xF79D, 0xFFDE, 0xFFDE, 0xFFBE, 0x9C71, 0x49C7, 0x4186, 0x49C7, 0x9451, 0xFF9D, 0xFFFF, 0xFFDE, 0xFFFF, 0xDEBA, // 0x08A0 (2208) +0xDEBA, 0xF75C, 0xE6FB, 0xDEBA, 0xEF3C, 0xE6DB, 0xCDD6, 0xC5D6, 0xB534, 0x734C, 0x6AEB, 0xAD13, 0xC5D6, 0xAD13, 0x9C91, 0x9450, // 0x08B0 (2224) +0xC5F7, 0xDEBB, 0xE6FB, 0xD638, 0xA4D3, 0x732C, 0x7B8D, 0x8BEF, 0x6B2C, 0x5AAA, 0x6B2C, 0x6B2C, 0x5289, 0x2965, 0x2944, 0x41E6, // 0x08C0 (2240) +0x28E3, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2903, 0x2923, 0x2923, // 0x08D0 (2256) +0x3164, 0x3965, 0x41C6, 0x62CA, 0x736D, 0x62EB, 0x41E7, 0x41C7, 0x3145, 0x3986, 0x62CB, 0x9450, 0x9C71, 0xB535, 0xB555, 0xBDB6, // 0x08E0 (2272) +0xE6BB, 0xEF3D, 0xF79E, 0xF77D, 0xEF5D, 0xEEFC, 0xDE79, 0x93F0, 0x4165, 0x8BCF, 0xDEBA, 0xF77D, 0xF7DE, 0xFFFF, 0xF7DE, 0xE73C, // 0x08F0 (2288) +0xE6FB, 0xEF1C, 0xE6DB, 0xE6FB, 0xDEBA, 0xD679, 0xCE18, 0xBD96, 0xC5B6, 0xC5B6, 0xC5B6, 0xDE79, 0xBD74, 0x6B0B, 0x49E7, 0x41A6, // 0x0900 (2304) +0x734C, 0xB575, 0xDE9A, 0xCDF7, 0xACF3, 0x9410, 0x83CF, 0x6B2C, 0x5269, 0x62CB, 0x7BCF, 0x8C30, 0x7BCE, 0x5ACB, 0x5289, 0x4207, // 0x0910 (2320) +0x20E2, 0x20E2, 0x20E2, 0x20E2, 0x2103, 0x2103, 0x2903, 0x2903, 0x2103, 0x2903, 0x2903, 0x2903, 0x2903, 0x2103, 0x2903, 0x2923, // 0x0920 (2336) +0x3144, 0x4A07, 0x5289, 0x5A89, 0x52A9, 0x5269, 0x39A6, 0x20C2, 0x20E3, 0x4A28, 0x734C, 0x8BEF, 0x83CF, 0x9431, 0xB555, 0xB556, // 0x0930 (2352) +0xCDF8, 0xE6DB, 0xEF3C, 0xEF5D, 0xDEDA, 0xD658, 0xDE38, 0xC575, 0x51C7, 0xB4D3, 0xE679, 0xE6DA, 0xEF3C, 0xF7BD, 0xF7DE, 0xE75C, // 0x0940 (2368) +0xE71B, 0xF77D, 0xE6FB, 0xCE17, 0xCE38, 0xCE38, 0xCE18, 0xA4B2, 0xA4D3, 0xBD96, 0xB555, 0xAD14, 0x8C10, 0x5A8A, 0x41A6, 0x2924, // 0x0950 (2384) +0x3965, 0x62AA, 0x838E, 0x8C0F, 0x8C0F, 0x83AE, 0x83CE, 0x734D, 0x6B0C, 0x6B2C, 0x83EF, 0x9492, 0x8C51, 0x83EF, 0x7BCE, 0x62EB, // 0x0960 (2400) +0x2103, 0x2103, 0x20E2, 0x2103, 0x20E2, 0x20E2, 0x20E2, 0x20E2, 0x20E2, 0x20E2, 0x2903, 0x2103, 0x20E2, 0x20E2, 0x20E2, 0x2903, // 0x0970 (2416) +0x3164, 0x41C6, 0x5268, 0x5AA9, 0x5269, 0x5289, 0x5AAA, 0x4A48, 0x5AAA, 0x736D, 0x7BAE, 0xACF3, 0xCDF8, 0xCDF8, 0xC5F8, 0xBD97, // 0x0980 (2432) +0xA493, 0xB535, 0xCE38, 0xDE9A, 0xC5F7, 0xACD3, 0x8B8E, 0x6A29, 0x38A2, 0x59A6, 0x93AF, 0xC554, 0xDE59, 0xEEFB, 0xF75D, 0xEF3C, // 0x0990 (2448) +0xF73C, 0xE6DA, 0xCE18, 0xD659, 0xD659, 0xCE38, 0xCE18, 0xD679, 0xD659, 0xC5D7, 0xB575, 0xC5B7, 0xAD34, 0x8C0F, 0x62EB, 0x5249, // 0x09A0 (2464) +0x4A07, 0x41A5, 0x4A07, 0x49E7, 0x6ACA, 0x9410, 0x7B6D, 0x62CB, 0x62CB, 0x734D, 0x83F0, 0x8C31, 0x8C31, 0x8C51, 0x7BAE, 0x5A89, // 0x09B0 (2480) +0x3164, 0x3164, 0x2944, 0x2944, 0x2923, 0x2103, 0x2103, 0x2103, 0x20E2, 0x2103, 0x2103, 0x2102, 0x20E2, 0x20E2, 0x2103, 0x2923, // 0x09C0 (2496) +0x3164, 0x39A5, 0x4A27, 0x5248, 0x39A5, 0x3185, 0x4A48, 0x83CE, 0x736D, 0x6B0B, 0x9451, 0xAD34, 0xCE18, 0xE6BB, 0xEF5D, 0xDEBB, // 0x09D0 (2512) +0xB535, 0x9451, 0x83EF, 0x83EF, 0x5228, 0x28C2, 0x2841, 0x3041, 0x48E3, 0x4062, 0x3841, 0x4924, 0x7269, 0x9BEF, 0xC534, 0xC596, // 0x09E0 (2528) +0xAD13, 0x8C0F, 0x6B0B, 0x5269, 0xA4F3, 0xDE9A, 0xE6FB, 0xF77D, 0xFF9E, 0xF75D, 0xF75D, 0xEF1C, 0xDE7A, 0xCDF8, 0xA4F3, 0x8C0F, // 0x09F0 (2544) +0x734C, 0x62A9, 0x5A69, 0x730B, 0x83AD, 0x7B6D, 0x5A69, 0x5A69, 0x39A6, 0x6B0C, 0x8410, 0x9472, 0x9492, 0x8C30, 0x6AEC, 0x62AB, // 0x0A00 (2560) +0x3144, 0x3164, 0x3164, 0x3144, 0x3144, 0x3144, 0x3144, 0x3144, 0x3143, 0x3144, 0x2923, 0x3143, 0x3143, 0x2903, 0x2903, 0x2923, // 0x0A10 (2576) +0x3185, 0x41E7, 0x4A48, 0x4A48, 0x3185, 0x20C2, 0x3185, 0x4A49, 0x62EB, 0x6B2D, 0x526A, 0x8C51, 0xB556, 0xD67A, 0xF75D, 0xF73D, // 0x0A20 (2592) +0xDE7B, 0xB515, 0x83EE, 0x41E6, 0x1020, 0x1820, 0x38A2, 0x82AA, 0x9B2B, 0x7A07, 0x6124, 0x6104, 0x58A3, 0x6124, 0x5964, 0x61C5, // 0x0A30 (2608) +0x6A48, 0x59E7, 0x4186, 0x734D, 0xC5F8, 0xF7BF, 0xF7DF, 0xF7DF, 0xFFDF, 0xFFDE, 0xFF9D, 0xEEFB, 0xCE17, 0xB514, 0x9451, 0x732D, // 0x0A40 (2624) +0x62CB, 0x6AEB, 0x6B0B, 0x83AE, 0x83CE, 0x4A07, 0x20E2, 0x2103, 0x2944, 0x62EB, 0x7BCF, 0x8410, 0x7BAE, 0x6B4D, 0x734C, 0x62CA, // 0x0A50 (2640) +0x3164, 0x2944, 0x2923, 0x2923, 0x2923, 0x3144, 0x3164, 0x3164, 0x3164, 0x3164, 0x3143, 0x3164, 0x3985, 0x3144, 0x2923, 0x2903, // 0x0A60 (2656) +0x3164, 0x4207, 0x4A48, 0x4A48, 0x2944, 0x18A2, 0x18A2, 0x39C7, 0x6B2C, 0x8C31, 0x83D0, 0x83D0, 0x8C11, 0xB535, 0xCE39, 0xEF3D, // 0x0A70 (2672) +0xEF3E, 0xDEDC, 0xCE38, 0xAD13, 0x41C7, 0x1821, 0x61E7, 0xD534, 0xD554, 0xDD75, 0xC4D3, 0xABF0, 0xB3CF, 0xAB6D, 0x7248, 0x6A27, // 0x0A80 (2688) +0x51A5, 0x5207, 0x83AE, 0xD638, 0xFFFF, 0xFFDF, 0xF7BE, 0xF7BE, 0xF79D, 0xEF3C, 0xD658, 0xB554, 0x9450, 0x734D, 0x7B8E, 0x9451, // 0x0A90 (2704) +0x9C92, 0x9C71, 0x83CF, 0x62AA, 0x4A07, 0x3964, 0x3144, 0x2923, 0x3185, 0x5269, 0x738E, 0x630C, 0x5AAA, 0x62EB, 0x5A89, 0x5268, // 0x0AA0 (2720) +0x5289, 0x4A28, 0x41E7, 0x39A6, 0x3185, 0x3144, 0x2924, 0x2924, 0x2923, 0x2923, 0x2924, 0x2944, 0x2944, 0x2923, 0x2944, 0x3144, // 0x0AB0 (2736) +0x41E7, 0x4A28, 0x5289, 0x5269, 0x4A48, 0x2924, 0x18A2, 0x3986, 0x7B8F, 0x9C93, 0xB556, 0x9452, 0x7BAF, 0x7B8F, 0xACF4, 0xCE59, // 0x0AC0 (2752) +0xE73D, 0xE75D, 0xEF5D, 0xFFDF, 0xC597, 0x28C3, 0x7ACB, 0xDD96, 0xD575, 0xE5F8, 0xF679, 0xEDF8, 0xD534, 0xC471, 0xD554, 0x8B2C, // 0x0AD0 (2768) +0x4144, 0x6289, 0xC5D6, 0xFF9D, 0xFFBE, 0xF79E, 0xF79E, 0xE71B, 0xDE99, 0xC5B6, 0x9CB1, 0x7B8D, 0x734C, 0x734C, 0x7B8D, 0x9C92, // 0x0AE0 (2784) +0xAD14, 0xA4D3, 0x736D, 0x5AAA, 0x5248, 0x41C6, 0x41E6, 0x3165, 0x2944, 0x5269, 0x5ACB, 0x4A28, 0x41C6, 0x4A27, 0x4A07, 0x4A07, // 0x0AF0 (2800) +0x7BAE, 0x736D, 0x6B2C, 0x630B, 0x5ACB, 0x5AAA, 0x52A9, 0x5AAA, 0x4A68, 0x4A28, 0x4207, 0x41E7, 0x39C6, 0x39A6, 0x39A6, 0x31A5, // 0x0B00 (2816) +0x39C6, 0x4A27, 0x5AA9, 0x62EA, 0x5289, 0x3165, 0x3165, 0x6B0C, 0xA4F4, 0xAD35, 0xBD97, 0xAD15, 0x9431, 0x83CF, 0x83EF, 0x8C51, // 0x0B10 (2832) +0xB596, 0xDEFC, 0xEF7E, 0xF79F, 0xFFBF, 0x6AAB, 0x8B6D, 0xCD34, 0xD534, 0xEE18, 0xF659, 0xE5B7, 0xD4F2, 0xCCD2, 0x934D, 0x4145, // 0x0B20 (2848) +0x49C7, 0xAD13, 0xF77D, 0xFFDF, 0xF79E, 0xFF9E, 0xEEFC, 0xCE18, 0x9C92, 0x7B8E, 0x6ACA, 0x730B, 0x8BEF, 0x9451, 0x8C30, 0x7B6E, // 0x0B30 (2864) +0x6B0C, 0x5AAA, 0x5269, 0x41E7, 0x4A07, 0x5A89, 0x5268, 0x5249, 0x5269, 0x62CB, 0x5AAA, 0x62EB, 0x5289, 0x4A27, 0x4A27, 0x41E6, // 0x0B40 (2880) +0x738E, 0x738E, 0x736D, 0x736D, 0x6B4D, 0x736D, 0x738E, 0x7BCF, 0x738E, 0x736D, 0x736D, 0x738D, 0x736D, 0x6B4C, 0x630B, 0x62EB, // 0x0B50 (2896) +0x52A9, 0x4A48, 0x5289, 0x4A48, 0x5269, 0x39C7, 0x6B4D, 0x9CD3, 0xB535, 0xA4D4, 0xACF5, 0x8C11, 0x8BF0, 0x6B2D, 0x6B0C, 0x734D, // 0x0B60 (2912) +0x7B8E, 0xACF4, 0xE6BB, 0xF75E, 0xFFDF, 0xC5B6, 0x8B4C, 0xC4B2, 0xC492, 0xDD35, 0xE535, 0xDCF4, 0xCC91, 0xB3EE, 0x38C2, 0x3905, // 0x0B70 (2928) +0x9CB2, 0xF79E, 0xFFDF, 0xFFBE, 0xF77E, 0xE6DB, 0xC5D7, 0x9431, 0x83AE, 0x838E, 0x9C72, 0xA492, 0xAD14, 0xB534, 0x8C30, 0x5269, // 0x0B80 (2944) +0x3986, 0x3165, 0x41C7, 0x3985, 0x3164, 0x5228, 0x4A27, 0x39A6, 0x4A48, 0x7B8E, 0x83EF, 0x6B2C, 0x5289, 0x4A07, 0x3164, 0x41C5, // 0x0B90 (2960) +0x738E, 0x73AE, 0x73AE, 0x738E, 0x6B6D, 0x6B6E, 0x738E, 0x7BCF, 0x73AF, 0x738E, 0x7BEF, 0x8410, 0x7BCF, 0x73AE, 0x6B6D, 0x6B4C, // 0x0BA0 (2976) +0x632B, 0x5ACA, 0x4A48, 0x52AA, 0x5289, 0x6B4D, 0x8C51, 0xA4F4, 0xACF5, 0xA4F4, 0x8BF1, 0x7B8F, 0x734E, 0x83CF, 0xA4D3, 0xB555, // 0x0BB0 (2992) +0xB515, 0xB515, 0x9CB3, 0xD659, 0xEF3D, 0xEF1C, 0x938E, 0xDD95, 0xCCD2, 0xCC92, 0xD4B2, 0xD492, 0xF5B6, 0x71E7, 0x4124, 0xA4B2, // 0x0BC0 (3008) +0xFFBF, 0xFFBF, 0xF77E, 0xF75D, 0xDE9A, 0xAD14, 0x9430, 0x8C10, 0xACD3, 0xACF3, 0xB555, 0xB534, 0x9451, 0x5A8A, 0x5A6A, 0x5249, // 0x0BD0 (3024) +0x3165, 0x3165, 0x3124, 0x4A07, 0x5248, 0x2903, 0x1061, 0x2904, 0x4A49, 0x6B4D, 0x7BCF, 0x6B2C, 0x5269, 0x3185, 0x2103, 0x5248, // 0x0BE0 (3040) +0x738E, 0x7BAF, 0x7BAF, 0x7B8E, 0x738E, 0x738E, 0x738F, 0x7BAF, 0x7BAF, 0x734E, 0x738E, 0x7BCF, 0x7BCF, 0x7BAF, 0x6B4D, 0x630C, // 0x0BF0 (3056) +0x5AEB, 0x5ACA, 0x5269, 0x4207, 0x41E7, 0x630C, 0x9492, 0xAD35, 0xBD77, 0xB536, 0xA4D4, 0xAD15, 0xACF4, 0x83CF, 0x9C92, 0xB555, // 0x0C00 (3072) +0xCDF8, 0xC5B7, 0x8C10, 0x83EF, 0xC5F8, 0xF73E, 0x72CB, 0x7A8A, 0xB42F, 0xBC70, 0xC471, 0xC4B2, 0xABCF, 0x5145, 0x51E7, 0xDEBA, // 0x0C10 (3088) +0xFFBF, 0xF77E, 0xD69A, 0xA4B3, 0x8C10, 0x83CF, 0x7B8D, 0x8C0F, 0x9C91, 0x9C91, 0x9471, 0x8C0F, 0x6B2C, 0x5248, 0x5248, 0x5A69, // 0x0C20 (3104) +0x41E7, 0x3985, 0x49E6, 0x41C6, 0x3123, 0x28E2, 0x28E3, 0x41E7, 0x62EB, 0x736D, 0x8C72, 0x83F0, 0x528A, 0x41E7, 0x5289, 0x6B2B, // 0x0C30 (3120) +0x738E, 0x7BAF, 0x7BAF, 0x738F, 0x736E, 0x738E, 0x738E, 0x736E, 0x736E, 0x6B2D, 0x736E, 0x7B8F, 0x738E, 0x736E, 0x630C, 0x5ACB, // 0x0C40 (3136) +0x52AA, 0x4A68, 0x4227, 0x31A6, 0x39A6, 0x6B2C, 0x9492, 0xAD15, 0xC5B8, 0xC5B8, 0xB556, 0x9452, 0xA4B3, 0x9C92, 0x6B0C, 0x734D, // 0x0C50 (3152) +0x9CD3, 0xC618, 0x94B2, 0x5ACB, 0x630D, 0xCDD8, 0xDE19, 0x7AAB, 0x59C5, 0x6A26, 0x830A, 0x61E6, 0x61E7, 0x7ACB, 0xBD55, 0xFF9E, // 0x0C60 (3168) +0xF77D, 0xDE9A, 0xA4F3, 0x7BAE, 0x736D, 0x7B8D, 0x732B, 0x5227, 0x5248, 0x5268, 0x4207, 0x5A89, 0x6B2B, 0x8C0F, 0x8BEE, 0x5AA9, // 0x0C70 (3184) +0x4A07, 0x5A68, 0x732B, 0x83AD, 0x732B, 0x41A5, 0x20E2, 0x5269, 0x6B4D, 0x7BAF, 0x8C52, 0x7BCF, 0x6B4D, 0x5ACA, 0x5ACA, 0x630B, // 0x0C80 (3200) +0x736E, 0x738F, 0x73AF, 0x738E, 0x738F, 0x7BD0, 0x7BD0, 0x738F, 0x73AF, 0x736E, 0x738F, 0x6B6E, 0x6B6D, 0x738E, 0x632C, 0x630C, // 0x0C90 (3216) +0x52AA, 0x4A69, 0x39C7, 0x3165, 0x3165, 0x5A8A, 0x9472, 0xBD76, 0xC5D8, 0xBD97, 0xA4B3, 0x8C10, 0x9431, 0x9C92, 0x7B6D, 0x6B0C, // 0x0CA0 (3232) +0xB555, 0xCE38, 0xC5F7, 0x9471, 0x5A8A, 0x7B6E, 0xE6BB, 0xEEDC, 0xC598, 0xACF5, 0xA4D3, 0xB534, 0xCE38, 0xE6FB, 0xFFBF, 0xE6DB, // 0x0CB0 (3248) +0xBD55, 0x940F, 0x732C, 0x7B6D, 0x732C, 0x730C, 0x6289, 0x3944, 0x3964, 0x5227, 0x62A9, 0x7B8C, 0x944F, 0x7B8D, 0x5A68, 0x5228, // 0x0CC0 (3264) +0x6B0C, 0x7BAE, 0x8C0F, 0x83CE, 0x62A9, 0x5227, 0x4207, 0x62CB, 0x6B2D, 0x83F0, 0x9472, 0x7B8F, 0x4A28, 0x41C6, 0x5247, 0x4A06, // 0x0CD0 (3280) +0x7BCF, 0x738F, 0x738E, 0x73AF, 0x7BAF, 0x7BD0, 0x83F1, 0x83F1, 0x8411, 0x7BD0, 0x83F0, 0x7BD0, 0x7BCF, 0x7BCF, 0x6B6D, 0x632C, // 0x0CE0 (3296) +0x5B0B, 0x52A9, 0x4207, 0x2923, 0x2923, 0x18A2, 0x62EB, 0xA4D3, 0x9C92, 0x7B8E, 0x7B8F, 0xBD76, 0xACF4, 0xB555, 0xB535, 0xA4B2, // 0x0CF0 (3312) +0x9C71, 0x9C71, 0xBD95, 0xC5D7, 0xA4B3, 0x732C, 0x83AF, 0xD618, 0xEEFC, 0xEEDB, 0xEF1C, 0xE6DB, 0xEEFC, 0xDE9A, 0xB534, 0x8C30, // 0x0D00 (3328) +0x6AEB, 0x62A9, 0x732C, 0x83CE, 0x83AE, 0x6AEB, 0x62AA, 0x62A9, 0x62A9, 0x8BCE, 0x83CE, 0x9C70, 0x83CE, 0x6AEB, 0x6AEB, 0x9430, // 0x0D10 (3344) +0xAD34, 0xB575, 0xA4D3, 0x8BEF, 0x83AD, 0x6B0B, 0x5A89, 0x734C, 0x738E, 0x83F0, 0x83F0, 0x630C, 0x5249, 0x41C6, 0x41C5, 0x5227, // 0x0D20 (3360) +0x8411, 0x7BD0, 0x73AF, 0x7BD0, 0x7BF0, 0x7BD0, 0x7BF0, 0x83F1, 0x7BF0, 0x7BD0, 0x83F0, 0x8411, 0x8410, 0x8410, 0x7BAF, 0x738E, // 0x0D30 (3376) +0x632C, 0x52A9, 0x4207, 0x39C6, 0x2923, 0x18A1, 0x4A27, 0x734C, 0x7B8D, 0x83AE, 0xA4B2, 0xACF4, 0xBD76, 0xC5B7, 0xC5B7, 0xBD55, // 0x0D40 (3392) +0xA4D2, 0x838D, 0x9430, 0xACD3, 0xACD3, 0x8BEF, 0x5A68, 0x838D, 0xAD13, 0xCDF7, 0xD659, 0xCDF8, 0xBD76, 0x83AF, 0x41C6, 0x5A89, // 0x0D50 (3408) +0x6AEB, 0x83AD, 0xA4B2, 0xAD13, 0xAD14, 0x9C71, 0x83EF, 0x7BAE, 0x9450, 0xB534, 0xB534, 0x9410, 0x730C, 0x838E, 0xACF4, 0xC5D7, // 0x0D60 (3424) +0xCE18, 0xBD96, 0x9C71, 0x8C0F, 0x9CB1, 0x734C, 0x5289, 0x734C, 0x7BAF, 0x7BCF, 0x630C, 0x526A, 0x41E7, 0x41C6, 0x5268, 0x5267, // 0x0D70 (3440) +0x8431, 0x8411, 0x83F1, 0x83F1, 0x83F1, 0x8411, 0x8411, 0x83F1, 0x83F1, 0x7BF0, 0x8411, 0x8411, 0x7BF0, 0x7BF0, 0x7BCF, 0x7BCF, // 0x0D80 (3456) +0x6B6E, 0x5AEB, 0x4208, 0x5249, 0x62EB, 0x6AEB, 0x83CE, 0x9450, 0xA4B2, 0x9C71, 0x9450, 0x9C51, 0xB535, 0xC5B8, 0xCDF8, 0xBD35, // 0x0D90 (3472) +0x8BEF, 0x836D, 0x6269, 0x5A48, 0x940F, 0x9C50, 0x7B8C, 0x5A68, 0x41E6, 0x6B0A, 0x6AEB, 0x6AEB, 0x6ACB, 0x5A49, 0x5228, 0x734C, // 0x0DA0 (3488) +0x9C92, 0xB535, 0xC5B7, 0xD639, 0xD638, 0xC5D7, 0xBD95, 0xBD75, 0xB533, 0xA4D2, 0x83CE, 0x7B6D, 0x83CE, 0x8BCF, 0xC596, 0xCDF8, // 0x0DB0 (3504) +0xB555, 0x8C10, 0x62CB, 0x6AEB, 0x7B8D, 0x5228, 0x41E7, 0x62CB, 0x7BAE, 0x7BCF, 0x4A29, 0x2104, 0x20C2, 0x3144, 0x5247, 0x5268, // 0x0DC0 (3520) +0x8411, 0x8411, 0x83F1, 0x7BF1, 0x7BF1, 0x8411, 0x8C52, 0x8C32, 0x8C52, 0x8C32, 0x8C52, 0x8C52, 0x8431, 0x8411, 0x8411, 0x7BF0, // 0x0DD0 (3536) +0x7BD0, 0x738F, 0x7BB0, 0x9CB4, 0xBDB8, 0xBD77, 0xA4D4, 0x9C92, 0x7B6D, 0x5248, 0x62AA, 0x7B4D, 0xACF3, 0xBD96, 0xD639, 0xC597, // 0x0DE0 (3552) +0xACB3, 0x8BAE, 0x6ACA, 0x5227, 0x5A47, 0x9C2F, 0x942F, 0x41A5, 0x41C6, 0x5248, 0x3984, 0x3964, 0x5A48, 0x6AEA, 0x838E, 0x9C51, // 0x0DF0 (3568) +0xC5B8, 0xCDF9, 0xD65A, 0xE6BC, 0xDE9A, 0xDE7A, 0xC5B7, 0xB555, 0xAD13, 0x83CE, 0x62CA, 0x7B6D, 0x9C91, 0xBD95, 0xB554, 0x9430, // 0x0E00 (3584) +0x7B6E, 0x62CB, 0x5A8A, 0x62AA, 0x4A07, 0x1861, 0x2924, 0x6B0C, 0x7BCF, 0x736D, 0x5AAA, 0x3165, 0x20E3, 0x2923, 0x3144, 0x3985, // 0x0E10 (3600) +0x8C32, 0x8411, 0x8411, 0x8411, 0x83F1, 0x8411, 0x8431, 0x8C32, 0x8C52, 0x8C32, 0x8C52, 0x9473, 0x9493, 0x9473, 0x8C52, 0x8432, // 0x0E20 (3616) +0x8C32, 0x9473, 0xAD57, 0xC5F9, 0xCE1A, 0xCDF9, 0x9C93, 0x62CC, 0x3145, 0x0820, 0x3124, 0x5248, 0x62CA, 0x83CF, 0xBD96, 0xDE7A, // 0x0E30 (3632) +0xCDF8, 0xB514, 0x942F, 0x7B6C, 0x7B6B, 0x7B6B, 0x41A6, 0x49E7, 0x6ACA, 0x5227, 0x5A47, 0x730A, 0x83AD, 0x9450, 0xACF3, 0xB535, // 0x0E40 (3648) +0xC5D8, 0xC5B8, 0xDE9B, 0xDE7A, 0xDE5A, 0xD659, 0xB514, 0x838E, 0x838D, 0x83AD, 0x734C, 0x8BEF, 0x9450, 0xA4B2, 0xACF3, 0x9C71, // 0x0E50 (3664) +0xA4D3, 0xACF3, 0xA4B2, 0x83CF, 0x4A28, 0x1861, 0x3985, 0x83CF, 0x83EF, 0x5269, 0x39A6, 0x3986, 0x2944, 0x3145, 0x39A5, 0x41E6, // 0x0E60 (3680) +0x8C72, 0x8C52, 0x8C52, 0x8C32, 0x8411, 0x83F1, 0x83F1, 0x7BF0, 0x83F1, 0x8411, 0x8C32, 0x8C52, 0x8C73, 0x9473, 0x9473, 0x8C52, // 0x0E70 (3696) +0x8C51, 0x8411, 0x7BD0, 0x736F, 0xA4D5, 0xC5D9, 0xC5F9, 0xA4F5, 0x62AB, 0x5249, 0x28E3, 0x1040, 0x2904, 0x5269, 0xBD76, 0xE6BB, // 0x0E80 (3712) +0xEF1C, 0xDEBA, 0xBD95, 0xA491, 0x9C71, 0x732B, 0x5A68, 0x49C6, 0x730B, 0x6AA9, 0x732B, 0x8BCE, 0x9C71, 0xAD14, 0xB535, 0xAD14, // 0x0E90 (3728) +0xBD76, 0xACF4, 0xB535, 0xBD76, 0xB534, 0xA492, 0x9C30, 0x732C, 0x6AEB, 0x8BEF, 0x9430, 0x8BCE, 0x9C71, 0x8C10, 0x8C11, 0x9C72, // 0x0EA0 (3744) +0x8C30, 0x83EF, 0x83AE, 0x7B8D, 0x732C, 0x5A69, 0x62EB, 0x83EF, 0x9CD2, 0x738D, 0x4A28, 0x5AAA, 0x6B0B, 0x62CA, 0x6B0B, 0x7B6D, // 0x0EB0 (3760) +0x8411, 0x8411, 0x8411, 0x8411, 0x7BF0, 0x7BF0, 0x7BD0, 0x73AF, 0x73AF, 0x7BF0, 0x8411, 0x8411, 0x8411, 0x8C52, 0x9473, 0x9492, // 0x0EC0 (3776) +0x94B2, 0x5AEB, 0x3186, 0x4209, 0x6B2E, 0xAD15, 0xD65A, 0xD65A, 0xD659, 0x8C30, 0x2904, 0x20E3, 0x20C3, 0x62CB, 0xB535, 0xD659, // 0x0ED0 (3792) +0xDEBA, 0xEF5D, 0xE6FC, 0xD639, 0xAD14, 0xA491, 0x8BCE, 0x7B4B, 0x838C, 0x836D, 0x83AE, 0x8BEF, 0x8C10, 0xACF4, 0xB575, 0xACF3, // 0x0EE0 (3808) +0x9C91, 0x940F, 0x838D, 0xA4B2, 0x9C50, 0x83AE, 0x9C50, 0x940F, 0x93EF, 0x838D, 0x8BEF, 0x9430, 0xA4B3, 0xACF5, 0xC5F9, 0xC5B8, // 0x0EF0 (3824) +0x732C, 0x3985, 0x41A6, 0x7B8D, 0x9C91, 0x7B6D, 0x6B0C, 0x7B8D, 0x8C50, 0x7BAE, 0x6B2C, 0x83EF, 0x9451, 0x9C71, 0xA4B2, 0xA4D3, // 0x0F00 (3840) +0x83F1, 0x83F1, 0x7BF0, 0x83F1, 0x83F1, 0x7BF0, 0x7BD0, 0x7BB0, 0x7BB0, 0x7BD0, 0x8411, 0x8C52, 0x9473, 0x8C53, 0x9474, 0x9494, // 0x0F10 (3856) +0x8C52, 0x738F, 0x5ACC, 0x4209, 0x41E8, 0x5AAB, 0x9452, 0xBDB7, 0xD639, 0x8BF0, 0x49E7, 0x18A2, 0x1061, 0x41C7, 0x62AA, 0xA4B2, // 0x0F20 (3872) +0xDEBB, 0xEEFD, 0xE6BB, 0xE6FC, 0xBD76, 0x8C10, 0x9CB2, 0xA4B2, 0xBD75, 0xC5D6, 0xB555, 0xBD76, 0xC5B7, 0xCE19, 0xD65B, 0xCE19, // 0x0F30 (3888) +0xC5B7, 0xC5D7, 0xAD14, 0xB555, 0xBD75, 0xB575, 0xBD96, 0xA4B2, 0x83CF, 0x83AF, 0x9CB3, 0x9472, 0xA4F4, 0xB556, 0xAD35, 0xB576, // 0x0F40 (3904) +0x8C11, 0x5A8B, 0x62EB, 0x9451, 0x9450, 0x7B8D, 0x62CA, 0x83CF, 0xAD13, 0x83F0, 0x83AF, 0x9451, 0x9452, 0x9472, 0x9CD3, 0x9C93, // 0x0F50 (3920) +0x8411, 0x8C32, 0x8C32, 0x8C32, 0x8431, 0x8411, 0x8411, 0x83F0, 0x7BF0, 0x8411, 0x8412, 0x8C32, 0x9494, 0x9473, 0xA4D5, 0xAD16, // 0x0F60 (3936) +0xAD56, 0xBDD8, 0xC619, 0xB5B7, 0x8C31, 0x526A, 0x5A8B, 0x7BAF, 0xB576, 0xC5F8, 0x9451, 0x49E8, 0x18A2, 0x0820, 0x3165, 0x7B8E, // 0x0F70 (3952) +0xACF4, 0xB555, 0xD639, 0xDEBB, 0xCDF8, 0xB555, 0xA4D4, 0xACD4, 0xBD76, 0xCE18, 0xD65A, 0xD65A, 0xD65A, 0xDE9B, 0xDEBB, 0xDE7A, // 0x0F80 (3968) +0xE6BB, 0xDE9B, 0xD659, 0xC5D7, 0xD639, 0xBD96, 0xAD14, 0x9451, 0x9451, 0xA4D4, 0x9CB3, 0x9C72, 0x8C11, 0x736E, 0x6B2D, 0x6B0D, // 0x0F90 (3984) +0x8C31, 0x9C93, 0x8C51, 0x83EF, 0x734C, 0x5A89, 0x6B0B, 0x8C30, 0xBD96, 0xA4D3, 0x8C31, 0x9472, 0x9CB3, 0x9CB3, 0x9CD3, 0x9CD3, // 0x0FA0 (4000) +0x83F1, 0x8431, 0x8C31, 0x8411, 0x8411, 0x8411, 0x8411, 0x7BF0, 0x8411, 0x7BD0, 0x8C32, 0x8411, 0x9473, 0x9C93, 0x9C94, 0xBD98, // 0x0FB0 (4016) +0xC63A, 0xD67B, 0xDEDC, 0xE71D, 0xDEDC, 0xA515, 0x4A29, 0x2946, 0x4A08, 0x7BCF, 0xA4D3, 0x9CB2, 0x528A, 0x20C3, 0x18A3, 0x2925, // 0x0FC0 (4032) +0x41E7, 0x7BAE, 0xA4D3, 0xA4B3, 0x9C93, 0xC5B8, 0xACF5, 0xB557, 0xBD77, 0xBD57, 0xC5D9, 0xCE19, 0xD65A, 0xD67A, 0xDEBA, 0xCE39, // 0x0FD0 (4048) +0xCE19, 0xC5D8, 0xB535, 0xA4B3, 0xA4B3, 0x9451, 0x9C92, 0xA4D3, 0xA4D4, 0xACD4, 0x734E, 0x6AEC, 0x7B8F, 0x9C93, 0xA4B3, 0x7B6E, // 0x0FE0 (4064) +0x630C, 0x736E, 0x62EC, 0x5AAB, 0x5289, 0x62EB, 0x62CA, 0x6B0B, 0x8C30, 0x8C10, 0x9C92, 0xACF4, 0x9C93, 0x9452, 0x9CB3, 0xA4B3, // 0x0FF0 (4080) +0x7BCF, 0x7BD0, 0x7BD0, 0x7BAF, 0x7BCF, 0x7BD0, 0x7BD0, 0x7BAF, 0x73AF, 0x7BCF, 0x7BD0, 0x8411, 0x9493, 0xA4D4, 0xAD36, 0xC5D9, // 0x1000 (4096) +0xD67B, 0xD69B, 0xDEDC, 0xDEDC, 0xE6FC, 0xE71D, 0x9492, 0x3186, 0x0000, 0x0821, 0x526A, 0x9472, 0x9CB3, 0x6B2D, 0x6B4D, 0x734E, // 0x1010 (4112) +0x6B2D, 0xA4B3, 0x8C31, 0x6B2D, 0x6B0D, 0x9C73, 0x9C73, 0xBD98, 0xC5F9, 0xBD98, 0xC5D9, 0xBDB8, 0xCE19, 0xCE3A, 0xCE39, 0xBD97, // 0x1020 (4128) +0xB556, 0xAD36, 0x8C11, 0x734E, 0xAD14, 0xCDF8, 0xC5B6, 0xA4D3, 0x9451, 0xB534, 0xD659, 0x9C72, 0x41C7, 0x3986, 0xA4D3, 0xCE39, // 0x1030 (4144) +0xB556, 0x9472, 0x5249, 0x18C3, 0x41C7, 0x62CB, 0x4A28, 0x41C7, 0x3966, 0x7B8E, 0xACF4, 0xACF4, 0x9CB3, 0x9C93, 0xA4D4, 0xAD14, // 0x1040 (4160) +0x7BCF, 0x73AF, 0x738E, 0x738F, 0x7BAF, 0x7BCF, 0x7BCF, 0x73AF, 0x738F, 0x7BCF, 0x7BAF, 0x8411, 0x9493, 0x8C52, 0x7BAF, 0x5A8B, // 0x1050 (4176) +0x62ED, 0xA515, 0xCE5A, 0xE6FD, 0xDEDC, 0xE71D, 0xEF5D, 0xCE59, 0x6B2D, 0x3166, 0x18C3, 0x4A49, 0x8C31, 0x9CD4, 0xB576, 0xA4F5, // 0x1060 (4192) +0xAD15, 0xDE9B, 0xCE19, 0x8C11, 0x7BAF, 0x7B8F, 0x83F0, 0x9472, 0xA4D4, 0xA4D4, 0xBDD8, 0xC5F9, 0xCE5A, 0xC61A, 0xBDB9, 0xC5F9, // 0x1070 (4208) +0xAD36, 0x8C31, 0x8C31, 0xB535, 0x9451, 0xA4B2, 0xCE17, 0xACF3, 0x7B6D, 0x628A, 0x8C10, 0xCE18, 0xBD75, 0x4A28, 0x39A6, 0x9CD3, // 0x1080 (4224) +0xC5D8, 0xCE39, 0x9451, 0x734D, 0x736D, 0x6B4D, 0x4A08, 0x62CB, 0x39A7, 0x83AF, 0xACF4, 0xAD15, 0xACF4, 0xAD15, 0xAD15, 0xAD15, // 0x1090 (4240) +0x83F0, 0x7BAF, 0x738E, 0x73AF, 0x7BCF, 0x7BCF, 0x73AF, 0x738E, 0x7BD0, 0x7BD0, 0x8C52, 0x8431, 0x8411, 0x62CC, 0x39A7, 0x1883, // 0x10A0 (4256) +0x0000, 0x1082, 0x4A29, 0x9CF4, 0xCE7A, 0xDEDC, 0xEF3D, 0xE71D, 0xD6BB, 0xA514, 0x39E8, 0x0842, 0x18A3, 0x4A29, 0x630C, 0x8C31, // 0x10B0 (4272) +0xC619, 0xDE7C, 0xDEDC, 0xC5D9, 0xAD56, 0x9473, 0x8C52, 0x8C52, 0xA4F4, 0xAD15, 0xBDB8, 0xD65B, 0xC61A, 0xBDB9, 0xCE1A, 0xBD78, // 0x10C0 (4288) +0x9472, 0x7B8F, 0xBD96, 0x9451, 0x83CE, 0xBD75, 0xBD54, 0x942F, 0x9C71, 0xACF3, 0x62EB, 0x62AA, 0xBD95, 0xB575, 0x5269, 0x5ACB, // 0x10D0 (4304) +0x9CB3, 0xBDF8, 0xC618, 0x7BAF, 0x4A08, 0x62EC, 0x8C31, 0xA4F4, 0xAD15, 0xAD15, 0xB536, 0xB536, 0xACF5, 0xA4D4, 0xAD15, 0xB535, // 0x10E0 (4320) +0x83F0, 0x83F0, 0x7BCF, 0x7BAF, 0x73AF, 0x73AF, 0x738E, 0x736E, 0x7BB0, 0x8C32, 0x9473, 0x9452, 0x8410, 0x6B0D, 0x7B8F, 0x83F0, // 0x10F0 (4336) +0x3185, 0x0000, 0x0000, 0x0841, 0x31A6, 0x62EC, 0x7BD0, 0xBDD8, 0xD69B, 0xD67B, 0x7BF0, 0x0842, 0x0000, 0x0000, 0x0861, 0x62EC, // 0x1100 (4352) +0x8C31, 0xAD36, 0xD69B, 0xD69C, 0xBDB9, 0xA516, 0x9494, 0x9CB5, 0xA4F6, 0xB578, 0xC5D9, 0xD69C, 0xC5D9, 0xC5D9, 0xBDB8, 0x7B90, // 0x1110 (4368) +0x6AED, 0xA4F4, 0xBD96, 0x9C92, 0x83AE, 0x8BEE, 0x9C50, 0x9C91, 0x9C71, 0x9C51, 0xC5D7, 0x9C72, 0x5269, 0x6B0C, 0x8C51, 0x528A, // 0x1120 (4384) +0x6B4D, 0x8411, 0xAD35, 0x8C31, 0x526A, 0x83F0, 0xA4D4, 0xAD15, 0xB535, 0xB557, 0xB536, 0xAD16, 0xB537, 0xB536, 0xAD36, 0xB536, // 0x1130 (4400) +0x83CF, 0x83F0, 0x83F0, 0x7BAF, 0x738E, 0x736E, 0x738F, 0x738F, 0x7BD0, 0x8C31, 0x9473, 0x9472, 0x9CB3, 0xB556, 0xB576, 0xCE39, // 0x1140 (4416) +0xAD33, 0x4207, 0x20C2, 0x0000, 0x0000, 0x0000, 0x0001, 0x39A8, 0xAD56, 0xD6BC, 0xA515, 0x3187, 0x1062, 0x0820, 0x0020, 0x10A2, // 0x1150 (4432) +0x2925, 0x4A6A, 0x9493, 0xB5B8, 0xB578, 0x8C33, 0x7BD2, 0x9CB6, 0xB579, 0xB579, 0xBDB9, 0xCE1A, 0xBD98, 0xBD97, 0x8C11, 0x6B0C, // 0x1160 (4448) +0x6B2D, 0xACF4, 0xBD76, 0xB534, 0x9C71, 0x9C71, 0xA4D2, 0xACF3, 0x9C71, 0x83AE, 0xA4B2, 0xD639, 0xC5D7, 0x7B8F, 0x62EC, 0x8C51, // 0x1170 (4464) +0x528B, 0x6B2D, 0x6B0D, 0x7B8F, 0x9472, 0xACF4, 0xACF4, 0xAD15, 0xB556, 0xAD16, 0xB536, 0xB557, 0xAD16, 0xACF6, 0xB557, 0xB536, // 0x1180 (4480) +0x8410, 0x83F0, 0x8410, 0x7BF0, 0x7BAF, 0x7BAF, 0x738F, 0x738F, 0x83D0, 0x83F1, 0x83D0, 0x9CD3, 0xAD35, 0xB576, 0xB576, 0xC5F8, // 0x1190 (4496) +0xBDD6, 0x8C50, 0x2945, 0x0841, 0x0000, 0x0000, 0x0000, 0x0000, 0x738F, 0xDEFC, 0xB597, 0x7BD0, 0x41E9, 0x0000, 0x0000, 0x0000, // 0x11A0 (4512) +0x0821, 0x20E4, 0x4209, 0x9492, 0x94B3, 0x4A6A, 0x31C8, 0x6B4E, 0x8C73, 0x9CF5, 0x9CD4, 0xA515, 0xAD36, 0x83D0, 0x62EC, 0x9451, // 0x11B0 (4528) +0xAD13, 0xA4D2, 0x9C71, 0xA4B1, 0xB513, 0xC595, 0xBD74, 0xACD2, 0x8C0F, 0x9450, 0xA4F3, 0xACF3, 0xD67A, 0xE6BC, 0x9C93, 0x9CB4, // 0x11C0 (4544) +0x9C72, 0x5AAB, 0x62AB, 0x83F0, 0xA4D4, 0xB556, 0xB556, 0xB556, 0xB535, 0xB535, 0xAD15, 0xB536, 0xAD15, 0xAD15, 0xAD15, 0xAD16, // 0x11D0 (4560) +0x8431, 0x83F0, 0x7BF0, 0x7BF0, 0x83F0, 0x8410, 0x7BD0, 0x73AF, 0x8C11, 0x8C11, 0x630C, 0x6B2D, 0x8411, 0x8C11, 0x734E, 0x8C51, // 0x11E0 (4576) +0xBD96, 0xBDB6, 0x8C51, 0x5AAB, 0x3186, 0x0841, 0x0000, 0x0000, 0x528A, 0xCE5A, 0xB5B8, 0xAD57, 0x738F, 0x1062, 0x0820, 0x0000, // 0x11F0 (4592) +0x0841, 0x2924, 0x3186, 0x5ACB, 0x5ACB, 0x1062, 0x2966, 0x3187, 0x4209, 0x5AEC, 0x630D, 0x83F1, 0x7BAF, 0x4A08, 0x83F0, 0xAD14, // 0x1200 (4608) +0xB533, 0xB554, 0xB554, 0xB533, 0xA491, 0x9C50, 0x942F, 0xB533, 0xBD33, 0xB513, 0xACF3, 0xBD75, 0xC5D7, 0xCE19, 0xC5F9, 0x9473, // 0x1210 (4624) +0x9452, 0x6B2D, 0x734E, 0x9452, 0xACF4, 0xB556, 0xBD77, 0xBD77, 0xBD77, 0xBD56, 0xB556, 0xB556, 0xAD16, 0xB536, 0xB536, 0xB556, // 0x1220 (4640) +0x8410, 0x7BF0, 0x7BF0, 0x83F0, 0x83F0, 0x83F0, 0x7BD0, 0x7BD0, 0x9452, 0x9CB4, 0x9493, 0x6B4E, 0x39A7, 0x39A7, 0x41E8, 0x4A49, // 0x1230 (4656) +0x734D, 0x83EF, 0xA4F3, 0xBD96, 0xB555, 0x5AAB, 0x0020, 0x0000, 0x39C7, 0xC5F9, 0xC61A, 0xCE5B, 0x9494, 0x2925, 0x1082, 0x1061, // 0x1240 (4672) +0x1061, 0x18C2, 0x2944, 0x2103, 0x39A6, 0x526A, 0x632D, 0x6B6E, 0x736E, 0x62EC, 0x6B2D, 0x736E, 0x736E, 0x736D, 0x9C92, 0xA4B2, // 0x1250 (4688) +0x9C70, 0x83AC, 0x942F, 0x9C4F, 0x838C, 0x942F, 0x8BCD, 0x8BCD, 0x9C2F, 0x8BCE, 0x83CD, 0xA4B1, 0xB555, 0xB555, 0xCDF8, 0xA4F4, // 0x1260 (4704) +0x8C31, 0x8BF1, 0x9452, 0xA4D4, 0xA4D4, 0xAD15, 0xBD77, 0xBD97, 0xBD77, 0xBD77, 0xB556, 0xB536, 0xACF5, 0xAD16, 0xB536, 0xB556, // 0x1270 (4720) +0x8411, 0x8411, 0x8411, 0x8411, 0x83F1, 0x7BD0, 0x7BD0, 0x8C31, 0x9473, 0xB576, 0xB576, 0xB576, 0x62EC, 0x39A7, 0x7BAF, 0x9C92, // 0x1280 (4736) +0x83CF, 0x83CF, 0x9CB3, 0xB556, 0xC619, 0xA4D4, 0x10A3, 0x0000, 0x39C8, 0xC5F9, 0xD67C, 0xCE7B, 0x9CB4, 0x31A7, 0x20E3, 0x18C2, // 0x1290 (4752) +0x1061, 0x2103, 0x0840, 0x18C2, 0x5269, 0x8430, 0xA514, 0xAD35, 0xA515, 0xA4F4, 0xA515, 0x9472, 0x8C10, 0xA4D3, 0xAD34, 0xAD13, // 0x12A0 (4768) +0x9C70, 0x9C4F, 0x940E, 0x836C, 0x93EE, 0xB4F2, 0x836C, 0x6AC9, 0x730A, 0x940E, 0x940F, 0x838D, 0xACD3, 0xBD75, 0xBD76, 0xA4B3, // 0x12B0 (4784) +0x9432, 0xA4B4, 0xAD16, 0xB557, 0xAD15, 0xAD15, 0xBD97, 0xC5B8, 0xC5D8, 0xC5D8, 0xBD98, 0xB557, 0xAD15, 0xB556, 0xBD77, 0xBD77, // 0x12C0 (4800) +}; diff --git a/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/dog.c b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/dog.c new file mode 100644 index 0000000..2c25dbe --- /dev/null +++ b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/dog.c @@ -0,0 +1,314 @@ +// Generated by : ImageConverter 565 v1.2 +// Dimensions : 80x60 pixels +// Size : 9 600 Bytes + +#if defined(__AVR__) + #include +#elif defined(__PIC32MX__) + #define PROGMEM +#elif defined(__arm__) + #define PROGMEM +#endif + +const unsigned short dog[0x12C0] PROGMEM ={ +0x2B2C, 0x232C, 0x232C, 0x234C, 0x236D, 0x2B6D, 0x2B8D, 0x2B8D, 0x2BAE, 0x33AE, 0x33AE, 0x33CE, 0x33CF, 0x33CF, 0x33EF, 0x33EF, // 0x0010 (16) +0x3C10, 0x3C10, 0x3C10, 0x3C30, 0x3C30, 0x3C30, 0x3C30, 0x3C30, 0x3C10, 0x3C11, 0x3C11, 0x3C11, 0x3C11, 0x3411, 0x33F1, 0x3C11, // 0x0020 (32) +0x3BF1, 0x3BF1, 0x3BD0, 0x3BF1, 0x33F0, 0x3C11, 0x3C11, 0x3411, 0x3411, 0x3411, 0x3410, 0x3411, 0x3C11, 0x3BF1, 0x3BD0, 0x3BD1, // 0x0030 (48) +0x33D0, 0x2BD0, 0x33D0, 0x33D0, 0x2B90, 0x2B90, 0x2B90, 0x236F, 0x236F, 0x1B4F, 0x1B4F, 0x1B2F, 0x1B0F, 0x1AEF, 0x1AEF, 0x1AEF, // 0x0040 (64) +0x12EE, 0x12ED, 0x12CD, 0x12CD, 0x0ACC, 0x0AAC, 0x0AAC, 0x0A8B, 0x0A8B, 0x028B, 0x026B, 0x024A, 0x024A, 0x022A, 0x0229, 0x0229, // 0x0050 (80) +0x2B4D, 0x2B2C, 0x2B4D, 0x2B6D, 0x2B6D, 0x2B8D, 0x2BAE, 0x2BAE, 0x33AE, 0x33AE, 0x33CE, 0x33CF, 0x33CF, 0x33EF, 0x33EF, 0x3C0F, // 0x0060 (96) +0x3C10, 0x3C10, 0x3C30, 0x3C30, 0x3C30, 0x3C30, 0x3C30, 0x3C30, 0x3C31, 0x3C31, 0x3C11, 0x3C11, 0x3C31, 0x3C32, 0x3C32, 0x3411, // 0x0070 (112) +0x2C31, 0x2C51, 0x2C31, 0x3452, 0x3411, 0x3411, 0x3411, 0x3C31, 0x3C11, 0x3C32, 0x3431, 0x3411, 0x3411, 0x3411, 0x3411, 0x3C11, // 0x0080 (128) +0x3C11, 0x33F1, 0x33D0, 0x33D0, 0x2BB0, 0x2BB0, 0x2BB0, 0x2B90, 0x236F, 0x236F, 0x234F, 0x1B4F, 0x1B2F, 0x1B0F, 0x1B0E, 0x1AEE, // 0x0090 (144) +0x12EE, 0x12ED, 0x12ED, 0x12CD, 0x12CD, 0x0ACC, 0x0AAC, 0x0A8C, 0x0A8B, 0x0A8B, 0x026B, 0x026B, 0x024A, 0x024A, 0x022A, 0x022A, // 0x00A0 (160) +0x2B4D, 0x2B4D, 0x2B6D, 0x2B6D, 0x2B8D, 0x2B8E, 0x2BAE, 0x33AE, 0x33AE, 0x33CE, 0x33CF, 0x33CF, 0x33EF, 0x3BEF, 0x3C0F, 0x3C10, // 0x00B0 (176) +0x3C30, 0x3C30, 0x3C30, 0x3C30, 0x3C30, 0x3C50, 0x3C51, 0x3C51, 0x3C31, 0x3C51, 0x3C51, 0x3C32, 0x3C31, 0x3C31, 0x3C32, 0x3C32, // 0x00C0 (192) +0x3C52, 0x3452, 0x3411, 0x3C32, 0x3C32, 0x4412, 0x4412, 0x43F1, 0x3BF1, 0x4412, 0x3C31, 0x3C31, 0x3C52, 0x3C32, 0x3C11, 0x3C11, // 0x00D0 (208) +0x3C11, 0x3BF1, 0x3BF1, 0x3BF1, 0x33D1, 0x33D0, 0x3390, 0x2B90, 0x2B90, 0x2B6F, 0x236F, 0x234F, 0x234F, 0x1B2E, 0x1B0E, 0x1B0E, // 0x00E0 (224) +0x1B0E, 0x130E, 0x12ED, 0x12ED, 0x12ED, 0x12CD, 0x0ACC, 0x0AAC, 0x0A8C, 0x0A8C, 0x0A8C, 0x026B, 0x026B, 0x024A, 0x024A, 0x022A, // 0x00F0 (240) +0x2B4D, 0x2B4D, 0x2B6D, 0x2B8D, 0x2B8D, 0x2B8E, 0x33AE, 0x33AE, 0x33CE, 0x33CF, 0x33CF, 0x3BEF, 0x3BEF, 0x3C0F, 0x3C30, 0x3C30, // 0x0100 (256) +0x3C30, 0x3C30, 0x3C30, 0x4450, 0x3C51, 0x4451, 0x3C51, 0x3C51, 0x3C51, 0x3C51, 0x3C51, 0x4472, 0x4472, 0x3C52, 0x3C32, 0x4452, // 0x0110 (272) +0x4412, 0x4C32, 0x4412, 0x4412, 0x4412, 0x4412, 0x4432, 0x3C11, 0x3C31, 0x3C51, 0x3C51, 0x3C31, 0x3C31, 0x3C31, 0x3C11, 0x4431, // 0x0120 (288) +0x3C11, 0x3C11, 0x3411, 0x33F1, 0x33F1, 0x33D1, 0x33D1, 0x33D1, 0x2B90, 0x2B90, 0x2B70, 0x234F, 0x234F, 0x234E, 0x1B2E, 0x1B0E, // 0x0130 (304) +0x1B0E, 0x1B0E, 0x12EE, 0x12ED, 0x12ED, 0x12ED, 0x12CD, 0x12CC, 0x0AAC, 0x0AAC, 0x0A8C, 0x0A8B, 0x026B, 0x026B, 0x024A, 0x024A, // 0x0140 (320) +0x336D, 0x2B6D, 0x2B6D, 0x2B8D, 0x2B8E, 0x2BAE, 0x33AE, 0x33CE, 0x33CE, 0x33CF, 0x3BEF, 0x3BEF, 0x3C0F, 0x3C10, 0x3C30, 0x3C30, // 0x0150 (336) +0x3C30, 0x4450, 0x4450, 0x4450, 0x4451, 0x4451, 0x4471, 0x4471, 0x4472, 0x4472, 0x4452, 0x3C52, 0x3C31, 0x3C31, 0x4452, 0x4472, // 0x0160 (352) +0x4472, 0x4472, 0x3C51, 0x3C31, 0x3C31, 0x3C10, 0x3C31, 0x4451, 0x3C30, 0x3C30, 0x3C0F, 0x3C10, 0x4451, 0x4C71, 0x4450, 0x3C10, // 0x0170 (368) +0x4451, 0x3C31, 0x3C31, 0x3C11, 0x3411, 0x33F1, 0x2BD1, 0x2BB1, 0x2BB1, 0x2B90, 0x2B70, 0x2B70, 0x2B4F, 0x234F, 0x232F, 0x1B2E, // 0x0180 (384) +0x1B2E, 0x1B0E, 0x1B0E, 0x1AEE, 0x12EE, 0x12ED, 0x12CD, 0x12CD, 0x0AAC, 0x0AAC, 0x0A8C, 0x0A8B, 0x0A8B, 0x026B, 0x024A, 0x024A, // 0x0190 (400) +0x336D, 0x2B6D, 0x2B6D, 0x2B8D, 0x2B8E, 0x2BAE, 0x33CE, 0x33CE, 0x33CE, 0x33CF, 0x3BEF, 0x3C0F, 0x3C10, 0x3C30, 0x3C30, 0x3C30, // 0x01A0 (416) +0x4450, 0x4450, 0x4451, 0x4451, 0x4471, 0x4471, 0x4472, 0x4472, 0x4472, 0x4472, 0x4472, 0x4472, 0x4C72, 0x4C92, 0x4C72, 0x4472, // 0x01B0 (432) +0x3C71, 0x3C50, 0x3C50, 0x5492, 0x7555, 0x8DD7, 0xAE9A, 0xBF1C, 0xBF1C, 0xB69A, 0xA618, 0xA618, 0xBEFB, 0xC75D, 0xAE79, 0x8575, // 0x01C0 (448) +0x5451, 0x4C11, 0x4410, 0x4411, 0x3C11, 0x3411, 0x3411, 0x33D1, 0x2BB0, 0x3391, 0x2B70, 0x2B70, 0x2B70, 0x2B50, 0x234F, 0x232F, // 0x01D0 (464) +0x1B2E, 0x1B2E, 0x1B0E, 0x1B0E, 0x1B0E, 0x12ED, 0x12ED, 0x12ED, 0x12CC, 0x0AAC, 0x0AAC, 0x0A8B, 0x0A8B, 0x0A8B, 0x026B, 0x024A, // 0x01E0 (480) +0x2B6D, 0x2B6D, 0x2B6D, 0x2B8D, 0x2BAE, 0x2BAE, 0x33CE, 0x33CE, 0x33CF, 0x33EF, 0x3BEF, 0x3C0F, 0x3C30, 0x3C30, 0x3C50, 0x3C50, // 0x01F0 (496) +0x4451, 0x4451, 0x4451, 0x4471, 0x4471, 0x4471, 0x4472, 0x4472, 0x4C92, 0x4492, 0x4472, 0x4C72, 0x4C72, 0x4452, 0x4431, 0x4C10, // 0x0200 (512) +0x5C71, 0x8555, 0xAE99, 0xD77D, 0xF7FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7FF, // 0x0210 (528) +0xD75D, 0x9DF8, 0x6CD3, 0x5410, 0x43D0, 0x4411, 0x3C11, 0x2BB0, 0x33D1, 0x33B1, 0x2B90, 0x2B70, 0x2B70, 0x2B70, 0x234F, 0x234F, // 0x0220 (544) +0x234E, 0x1B2E, 0x1B2E, 0x1B2E, 0x1B0E, 0x1B0D, 0x12ED, 0x12ED, 0x12CC, 0x12CC, 0x12AC, 0x0AAC, 0x0A8B, 0x0A8B, 0x0A6B, 0x026A, // 0x0230 (560) +0x2B6D, 0x2B6D, 0x2B6D, 0x2B8D, 0x2BAE, 0x33CE, 0x33CE, 0x33CE, 0x33EF, 0x33EF, 0x3C0F, 0x3C10, 0x3C30, 0x3C30, 0x3C50, 0x3C50, // 0x0240 (576) +0x3C51, 0x4451, 0x4451, 0x4471, 0x4472, 0x4472, 0x4492, 0x4492, 0x4492, 0x4C72, 0x4C92, 0x4C72, 0x4451, 0x5492, 0x7DD7, 0xAF1C, // 0x0250 (592) +0xDF9E, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFDE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, // 0x0260 (608) +0xFFFF, 0xF7FF, 0xEFFF, 0xC71C, 0x7514, 0x43F0, 0x3BF0, 0x4411, 0x33D1, 0x33B1, 0x33B0, 0x2B90, 0x2B90, 0x236F, 0x236F, 0x234F, // 0x0270 (624) +0x1B4E, 0x1B2E, 0x1B2E, 0x1B2E, 0x1B0E, 0x1B0E, 0x1B0D, 0x1B0D, 0x12ED, 0x12CC, 0x12CC, 0x12AC, 0x0AAB, 0x0A8B, 0x0A8B, 0x0A6A, // 0x0280 (640) +0x2B8D, 0x2B6D, 0x2B8D, 0x2BAE, 0x2BAE, 0x2BCE, 0x2BEE, 0x2BEE, 0x33EF, 0x33EF, 0x3C0F, 0x3C0F, 0x3C30, 0x3C30, 0x3C50, 0x4450, // 0x0290 (656) +0x4471, 0x4450, 0x4471, 0x4492, 0x4472, 0x4472, 0x4C72, 0x4C72, 0x4472, 0x44B3, 0x3C72, 0x4492, 0x5492, 0xAE59, 0xFFFF, 0xFFFF, // 0x02A0 (672) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, // 0x02B0 (688) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF9E, 0xD6DB, 0xCF1C, 0xA659, 0x64D3, 0x3BF0, 0x2BAF, 0x2BD0, 0x2B8F, 0x2B6F, 0x2B4F, 0x232F, // 0x02C0 (704) +0x232F, 0x1B2F, 0x1B2E, 0x1B2E, 0x1B2E, 0x1B2D, 0x1B0D, 0x1B0D, 0x1B0C, 0x1AEC, 0x1ACB, 0x12AB, 0x12AB, 0x0AAA, 0x0AAA, 0x0A8A, // 0x02D0 (720) +0x2B6E, 0x2B6D, 0x2B8E, 0x2BAE, 0x2BAE, 0x2BCE, 0x2BCE, 0x2BCE, 0x33EF, 0x33EF, 0x3C0F, 0x3C0F, 0x3C30, 0x3C30, 0x3C50, 0x3C50, // 0x02E0 (736) +0x3C2F, 0x4471, 0x4471, 0x4492, 0x4C92, 0x4CB2, 0x4CB2, 0x4C71, 0x5CB2, 0x64F4, 0x7D56, 0xA65A, 0xD79E, 0xF7FF, 0xF7FE, 0xFFDE, // 0x02F0 (752) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0300 (768) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xF7FF, 0xF7FF, 0xD79E, 0xAE7A, 0x6CF4, 0x4BF1, 0x338F, 0x338F, 0x2B6F, 0x2B6F, // 0x0310 (784) +0x236F, 0x1B0E, 0x1B2E, 0x1B2E, 0x1B0D, 0x234D, 0x1B0C, 0x1B0C, 0x1B0C, 0x1B0B, 0x1AEB, 0x1ACB, 0x12CB, 0x12AA, 0x0AAA, 0x0A8A, // 0x0320 (800) +0x2B8E, 0x2B6E, 0x2B8E, 0x2BAE, 0x2BAE, 0x2BCF, 0x2BCF, 0x2BCF, 0x33EF, 0x3410, 0x3410, 0x3C10, 0x3C10, 0x3C30, 0x3C50, 0x3C51, // 0x0330 (816) +0x4491, 0x3C50, 0x4491, 0x4491, 0x4CB2, 0x4470, 0x5470, 0x85D6, 0xC75C, 0xE7BF, 0xF7FF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, // 0x0340 (832) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0350 (848) +0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE7DF, 0xA5F8, 0x5410, 0x3BAF, 0x2B6E, 0x236E, // 0x0360 (864) +0x1B0D, 0x2B6E, 0x234E, 0x1B2D, 0x234D, 0x1B2C, 0x232C, 0x232C, 0x230B, 0x230B, 0x22EB, 0x1AEB, 0x1ACA, 0x1ACA, 0x12CA, 0x12A9, // 0x0370 (880) +0x2B8E, 0x2B6E, 0x2B8E, 0x2BAF, 0x2BAF, 0x2BAF, 0x2BCF, 0x2BCF, 0x33EF, 0x33F0, 0x3410, 0x3C10, 0x3C10, 0x3C30, 0x3C30, 0x4451, // 0x0380 (896) +0x4451, 0x4471, 0x4491, 0x4491, 0x4C91, 0x6D13, 0xAE99, 0xEFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDE, // 0x0390 (912) +0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFDD, 0xFFDE, 0xFFFF, // 0x03A0 (928) +0xFFFF, 0xFFDF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFDE, 0xFFFE, 0xFFFF, 0xFFDF, 0xFFFF, 0xFFFF, 0xF7FF, 0xC71C, 0x74F4, 0x3BAE, 0x338E, // 0x03B0 (944) +0x338E, 0x232D, 0x236D, 0x234D, 0x234C, 0x234C, 0x1B2B, 0x232C, 0x232B, 0x230B, 0x230A, 0x22EA, 0x1AEA, 0x1ACA, 0x12C9, 0x12A9, // 0x03C0 (960) +0x2B8E, 0x2B6E, 0x2B8E, 0x2BAE, 0x2BAF, 0x2BAF, 0x2BCF, 0x2BCF, 0x33EF, 0x33EF, 0x3C0F, 0x3C10, 0x3C10, 0x3C30, 0x3C50, 0x4450, // 0x03D0 (976) +0x4430, 0x4C71, 0x4C71, 0x5471, 0x9E38, 0xE7FF, 0xEFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFDE, 0xFFDE, 0xFFFF, // 0x03E0 (992) +0xFFFE, 0xFFFE, 0xFFDD, 0xF7DC, 0xFFFC, 0xFFFC, 0xFFDD, 0xFFDD, 0xFFFE, 0xFFFE, 0xFFFD, 0xF7DC, 0xF7DC, 0xF7BC, 0xF7DC, 0xFFDD, // 0x03F0 (1008) +0xFFDE, 0xFFFF, 0xFFDE, 0xFFDE, 0xFFFE, 0xEF7C, 0xD6B8, 0xF7BD, 0xFFFE, 0xFFDE, 0xFFFF, 0xFFFF, 0xF7FF, 0xE7DF, 0x95B6, 0x438E, // 0x0400 (1024) +0x334C, 0x336D, 0x2B4C, 0x2B4C, 0x234C, 0x234C, 0x234B, 0x232B, 0x232A, 0x232A, 0x230A, 0x230A, 0x2309, 0x1AE9, 0x1AC9, 0x12C8, // 0x0410 (1040) +0x338E, 0x2B8D, 0x2B8D, 0x2BAE, 0x2BAE, 0x2BCE, 0x2BCF, 0x33CF, 0x33EF, 0x33EF, 0x3C0F, 0x3C0F, 0x3C2F, 0x4430, 0x4450, 0x4450, // 0x0420 (1056) +0x4C70, 0x4C30, 0x8554, 0xDF7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFD, 0xE73A, 0xDED9, 0xF79C, 0xF7BD, 0xF7DE, // 0x0430 (1072) +0xFFDE, 0xFFFD, 0xF7BC, 0xEF7A, 0xF79A, 0xF7DB, 0xF7BB, 0xF77B, 0xF79C, 0xFFDC, 0xF7BC, 0xEF5A, 0xEF7A, 0xF79A, 0xF79A, 0xF79B, // 0x0440 (1088) +0xFF9C, 0xFFDE, 0xFFFE, 0xF7DD, 0xF7FD, 0xE77B, 0x9D32, 0xAD93, 0xFFFD, 0xFFFE, 0xFFFE, 0xFFFF, 0xF7DE, 0xFFFF, 0xEFFF, 0x9595, // 0x0450 (1104) +0x3B6D, 0x334C, 0x338C, 0x2B4B, 0x2B4B, 0x234B, 0x2B8B, 0x234A, 0x234A, 0x232A, 0x2329, 0x2329, 0x2309, 0x2308, 0x1AE8, 0x1AE8, // 0x0460 (1120) +0x33AE, 0x338D, 0x2BAD, 0x33AD, 0x2BCE, 0x2BCE, 0x33EE, 0x33EE, 0x340F, 0x3C0F, 0x3C0F, 0x3C2F, 0x442F, 0x444F, 0x444F, 0x444F, // 0x0470 (1136) +0x4C2F, 0x8DB5, 0xD77C, 0xFFFF, 0xFFFF, 0xFFDE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFD, 0xDEF8, 0x9CAF, 0xAD51, 0xEF5A, 0xEFBC, 0xEFBC, // 0x0480 (1152) +0xFFDD, 0xFFFD, 0xF7BB, 0xEF79, 0xEF79, 0xEF79, 0xEF59, 0xEF7A, 0xEF5A, 0xEF7B, 0xEF5A, 0xE718, 0xE738, 0xE738, 0xE758, 0xEF59, // 0x0490 (1168) +0xEF7B, 0xF79C, 0xFFFD, 0xFFFD, 0xF7DD, 0xF7DD, 0xBE16, 0x8C6F, 0xE71A, 0xFFFE, 0xFFDE, 0xFFDE, 0xF79D, 0xFFFE, 0xFFFF, 0xF7FF, // 0x04A0 (1184) +0x9E16, 0x438C, 0x3B8B, 0x336B, 0x336A, 0x2B6A, 0x2B6A, 0x2B49, 0x2B49, 0x2B49, 0x2B28, 0x2B28, 0x2B28, 0x2308, 0x2307, 0x22E7, // 0x04B0 (1200) +0x3BCE, 0x33AD, 0x33AD, 0x33CE, 0x33CE, 0x33EE, 0x33EE, 0x340E, 0x3C0E, 0x3C0F, 0x3C2E, 0x442F, 0x444F, 0x444F, 0x446F, 0x4C4E, // 0x04C0 (1216) +0x95F5, 0xE7FE, 0xF7FE, 0xF7FD, 0xFFFE, 0xFFDE, 0xFFDE, 0xFFDE, 0xFF9C, 0xFFDC, 0xB592, 0x6B48, 0xAD71, 0xE718, 0xE739, 0xF79B, // 0x04D0 (1232) +0xF7BD, 0xFFBD, 0xF79B, 0xEF79, 0xE738, 0xDED6, 0xDED7, 0xEF5A, 0xEF5A, 0xEF3A, 0xE719, 0xDEF8, 0xE718, 0xDED6, 0xDED7, 0xE718, // 0x04E0 (1248) +0xDF19, 0xE75A, 0xF7BC, 0xFFDD, 0xFFDD, 0xFFBD, 0xE71A, 0x8C4F, 0xAD33, 0xFFDE, 0xFFFE, 0xFFDE, 0xEF5C, 0xF7BD, 0xFFFE, 0xFFFE, // 0x04F0 (1264) +0xEFFF, 0xB6F9, 0x438B, 0x3B6A, 0x3B8A, 0x3369, 0x3369, 0x3369, 0x2B48, 0x2B48, 0x2B48, 0x2B27, 0x2B27, 0x2B27, 0x2306, 0x2306, // 0x0500 (1280) +0x3BCD, 0x33CD, 0x33CD, 0x33ED, 0x3BED, 0x3C0D, 0x3C0D, 0x3C2D, 0x3C2D, 0x3C4D, 0x3C6D, 0x446E, 0x4C6E, 0x4C4E, 0x5C4F, 0xAE37, // 0x0510 (1296) +0xFFFF, 0xFFDE, 0xFFFD, 0xF7DD, 0xF7BC, 0xF7BC, 0xFFDC, 0xF77B, 0xF779, 0xE738, 0x94AE, 0x6B69, 0xB5B3, 0xDEF9, 0xDF39, 0xE77A, // 0x0520 (1312) +0xEF7A, 0xEF7A, 0xE718, 0xDED6, 0xCE75, 0xD6B6, 0xCE75, 0xDED7, 0xEF7A, 0xEF7A, 0xDEF8, 0xDED8, 0xD6B7, 0xCE55, 0xCE54, 0xD695, // 0x0530 (1328) +0xD6B6, 0xD6F7, 0xE739, 0xEF7B, 0xF7DC, 0xEFBC, 0xD6FA, 0x8C6F, 0x8C4D, 0xE6F8, 0xFFFE, 0xFFFE, 0xFFDE, 0xE73B, 0xFFDD, 0xFFDE, // 0x0540 (1344) +0xFFDF, 0xFFFF, 0xA5F5, 0x4B8A, 0x3B89, 0x3BC9, 0x3388, 0x3388, 0x3388, 0x3368, 0x2B68, 0x2B67, 0x2B47, 0x2B46, 0x2B25, 0x2B25, // 0x0550 (1360) +0x3BEC, 0x3BEC, 0x3BEC, 0x3C0C, 0x3C0D, 0x3C0D, 0x442D, 0x444D, 0x4C8D, 0x444D, 0x448D, 0x4C8E, 0x546E, 0x6CD0, 0xC73A, 0xF7FF, // 0x0560 (1376) +0xF7FE, 0xFFFE, 0xFFFD, 0xEF7B, 0xEF7B, 0xFFDC, 0xEF7A, 0xE719, 0xEF59, 0xD695, 0x840B, 0x736A, 0xBDD3, 0xD6D8, 0xDF18, 0xE77A, // 0x0570 (1392) +0xEF9A, 0xDF18, 0xDF17, 0xD6B5, 0xC633, 0xCE54, 0xBE13, 0xCE54, 0xCE96, 0xDF18, 0xD6D7, 0xD6B7, 0xC634, 0xBDF3, 0xBDF2, 0xBDF3, // 0x0580 (1408) +0xC634, 0xCE76, 0xCE97, 0xD6B8, 0xE77B, 0xE77B, 0xD6F9, 0x94D1, 0x6329, 0xC615, 0xFFDD, 0xF7BD, 0xFFFE, 0xEF9C, 0xDEFA, 0xFFDD, // 0x0590 (1424) +0xFFFF, 0xF7DE, 0xF7FE, 0x8D91, 0x43C9, 0x3BC8, 0x3BC7, 0x3BA7, 0x3387, 0x3387, 0x3387, 0x3367, 0x3366, 0x2B45, 0x2B45, 0x2B24, // 0x05A0 (1440) +0x440C, 0x440B, 0x440B, 0x440C, 0x442C, 0x442C, 0x444C, 0x4C4C, 0x444B, 0x4CAD, 0x4C6C, 0x546D, 0x5C6D, 0xBF19, 0xF7FE, 0xF7FE, // 0x05B0 (1456) +0xFFFE, 0xFFBD, 0xF79B, 0xEF7A, 0xF79B, 0xF79B, 0xE6F8, 0xEF39, 0xEF58, 0xC613, 0x7369, 0x738A, 0xB5B3, 0xD6B7, 0xDEF8, 0xD6F7, // 0x05C0 (1472) +0xD6D6, 0xCE95, 0xCE95, 0xCE94, 0xC632, 0xC633, 0xBE12, 0xB5B1, 0xC654, 0xCE75, 0xCE75, 0xCE96, 0xBE14, 0xB591, 0xB5B1, 0xBDD2, // 0x05D0 (1488) +0xC634, 0xCE76, 0xCE97, 0xCE97, 0xDF19, 0xDF3A, 0xDF3A, 0xB5D5, 0x6B8A, 0xA510, 0xF7BC, 0xFFFE, 0xDF1A, 0xE73B, 0xD6D9, 0xE73B, // 0x05E0 (1504) +0xFFDD, 0xF7DD, 0xEFFD, 0x95D2, 0x43A8, 0x43E7, 0x3BE7, 0x3BA6, 0x3BA6, 0x3BA6, 0x33A6, 0x3385, 0x3385, 0x3364, 0x3344, 0x3343, // 0x05F0 (1520) +0x4C2B, 0x4C0B, 0x442B, 0x442B, 0x444B, 0x446B, 0x4C6B, 0x4C8C, 0x4C8B, 0x54AC, 0x54CC, 0x5C8C, 0x7D30, 0xE7FC, 0xF7FD, 0xFFBC, // 0x0600 (1536) +0xF79C, 0xF77B, 0xDEF8, 0xE718, 0xEF59, 0xE719, 0xE6F8, 0xF779, 0xEF38, 0xBDD2, 0x6B48, 0x840C, 0xC614, 0xD6D7, 0xDF18, 0xCEB6, // 0x0610 (1552) +0xC675, 0xC654, 0xC633, 0xBE12, 0xBDF1, 0xBDD1, 0xBE12, 0xB5B1, 0xBDF2, 0xBE13, 0xBE13, 0xBDF3, 0xAD91, 0xAD71, 0xB5B1, 0xB5B1, // 0x0620 (1568) +0xB5F3, 0xC655, 0xCE76, 0xC656, 0xC677, 0xCED9, 0xD6F9, 0xADB4, 0x6349, 0x8C6D, 0xDEF9, 0xFFFE, 0xD6D9, 0xCEB8, 0xCE97, 0xCE77, // 0x0630 (1584) +0xDF1A, 0xDF1A, 0xE7DB, 0x852F, 0x4BE8, 0x4C07, 0x3BC5, 0x43E6, 0x43C5, 0x43C5, 0x3BA5, 0x3BA5, 0x3BA4, 0x3B83, 0x3B63, 0x3362, // 0x0640 (1600) +0x544B, 0x4C4A, 0x4C4A, 0x4C6B, 0x4C8B, 0x4C8B, 0x4C8B, 0x54AB, 0x54CB, 0x4C8A, 0x54CB, 0x5CAC, 0x7D0E, 0xCF37, 0xEFBB, 0xE739, // 0x0650 (1616) +0xE6F8, 0xDED7, 0xD675, 0xDED7, 0xDED7, 0xD696, 0xE6F8, 0xF779, 0xE6F7, 0xB570, 0x6307, 0x948D, 0xCE75, 0xD6D7, 0xD6D7, 0xCE96, // 0x0660 (1632) +0xC654, 0xC654, 0xC653, 0xBDF2, 0xB5B1, 0xB5B1, 0xB5D2, 0xB5D2, 0xAD91, 0xAD91, 0xADB2, 0xAD71, 0x9D10, 0xA530, 0xAD71, 0xAD71, // 0x0670 (1648) +0x9D30, 0xB5D3, 0xC635, 0xD6B8, 0xCEB8, 0xCED9, 0xCED8, 0xBE36, 0x5AE7, 0x7BEB, 0xC656, 0xF7BD, 0xDF3A, 0xC677, 0xBE15, 0xBDF5, // 0x0680 (1664) +0xC636, 0xC656, 0xE7FB, 0x8DB0, 0x4BE7, 0x4C06, 0x4405, 0x4C05, 0x43E5, 0x43C4, 0x43C4, 0x43C4, 0x3BA4, 0x3BA3, 0x3B82, 0x3B62, // 0x0690 (1680) +0x546A, 0x546A, 0x4C6A, 0x4C8A, 0x4CAA, 0x4CAA, 0x54AA, 0x54CA, 0x54EA, 0x54EA, 0x54CA, 0x64EB, 0x6CCC, 0xBEF5, 0xE778, 0xC634, // 0x06A0 (1696) +0xD675, 0xCE34, 0xCE54, 0xD695, 0xCE75, 0xD696, 0xDED7, 0xEF79, 0xDEB6, 0xA50F, 0x6327, 0x94AE, 0xC655, 0xCE96, 0xC675, 0xC654, // 0x06B0 (1712) +0xC654, 0xC654, 0xCE75, 0xBDD3, 0xB5B2, 0xC614, 0xB591, 0xAD50, 0xAD70, 0xA550, 0xAD71, 0xAD71, 0xA530, 0x9D10, 0xA510, 0x9CCF, // 0x06C0 (1728) +0x94EF, 0x9CEF, 0x9CF0, 0xC615, 0xDF39, 0xE77B, 0xCED9, 0xBE36, 0x73CB, 0x73CB, 0xBE15, 0xF7BC, 0xDF5B, 0xBE57, 0xB5F4, 0xADB3, // 0x06D0 (1744) +0xAD93, 0xB5F4, 0xD778, 0x95CF, 0x4BE6, 0x4C26, 0x4C25, 0x4C04, 0x4BE4, 0x4BE4, 0x43E4, 0x43C4, 0x43C3, 0x43A3, 0x3BA2, 0x3B82, // 0x06E0 (1760) +0x5C89, 0x5489, 0x5489, 0x54A9, 0x54A9, 0x54A9, 0x5CC9, 0x5CC9, 0x5CE9, 0x5CE9, 0x5CE9, 0x64EA, 0x74EB, 0xAE51, 0xD736, 0xBE12, // 0x06F0 (1776) +0xBDD2, 0xC613, 0xCE34, 0xC5F2, 0xC634, 0xD6B6, 0xE718, 0xE718, 0xD6B6, 0x9CCE, 0x6B68, 0x9CCF, 0xBDF4, 0xC656, 0xC696, 0xCE96, // 0x0700 (1792) +0xD6F6, 0xCE75, 0xBDF3, 0xAD71, 0xA530, 0xB5B2, 0xAD71, 0x9CCE, 0x9CEE, 0xA52F, 0xAD91, 0xA52F, 0x9D0F, 0x9D0F, 0x94AE, 0x7BEB, // 0x0710 (1808) +0x6BA9, 0x6B8A, 0x7BEC, 0x9CF0, 0xC636, 0xDF3A, 0xE77B, 0xCE97, 0x846D, 0x738A, 0xB593, 0xEF7B, 0xE75B, 0xC677, 0xA593, 0xA552, // 0x0720 (1824) +0x9D11, 0xA591, 0xC715, 0x74EB, 0x5446, 0x5445, 0x4C03, 0x5424, 0x4C03, 0x4C03, 0x4C03, 0x4BE3, 0x43E3, 0x43C3, 0x43A2, 0x43A2, // 0x0730 (1840) +0x5CA8, 0x5C88, 0x5488, 0x5CA8, 0x5CC8, 0x5CC8, 0x5CC8, 0x64E8, 0x5D08, 0x6509, 0x5CE8, 0x6D0A, 0x6CEA, 0x95CE, 0xD735, 0xADB0, // 0x0740 (1856) +0xAD70, 0xBDB2, 0xB591, 0xB591, 0xC613, 0xCE55, 0xE718, 0xDF18, 0xD695, 0x8C4C, 0x6B48, 0x9CCF, 0xB5D3, 0xC655, 0xD6D7, 0xE759, // 0x0750 (1872) +0xD6F7, 0xC634, 0xA530, 0xA530, 0x94AE, 0x9CAE, 0xA52F, 0x9CEE, 0x94CD, 0xA50F, 0xAD90, 0xA52F, 0x94EE, 0x8C8D, 0x842C, 0x73AA, // 0x0760 (1888) +0x6348, 0x4A65, 0x6B29, 0x946E, 0xA532, 0xB5F5, 0xD6F9, 0xCE97, 0x94CF, 0x6349, 0xA552, 0xEF7C, 0xDF3A, 0xC677, 0xAD93, 0x9D11, // 0x0770 (1904) +0x8CCF, 0xADD1, 0x9DF0, 0x6468, 0x5466, 0x5444, 0x5443, 0x5443, 0x5423, 0x5423, 0x4C03, 0x4C03, 0x43E3, 0x43E3, 0x43C2, 0x43A2, // 0x0780 (1920) +0x5CA7, 0x5CA7, 0x5CA7, 0x5CC8, 0x5CC8, 0x64C8, 0x64E8, 0x64E8, 0x6508, 0x64E7, 0x6D08, 0x6D28, 0x6D09, 0x7D6B, 0xA691, 0xAE71, // 0x0790 (1936) +0xA54F, 0xA50E, 0xA52F, 0xB571, 0xBDD3, 0xD676, 0xDED8, 0xE718, 0xC633, 0x7388, 0x6B68, 0x9D0F, 0xBE14, 0xCEB7, 0xE75A, 0xDF39, // 0x07A0 (1952) +0xC654, 0xA52F, 0x8C4C, 0x73A9, 0x73A8, 0x840A, 0x8C8C, 0x948D, 0x94AD, 0xA510, 0xAD91, 0xAD71, 0xA531, 0x8C6E, 0x8C2C, 0x7389, // 0x07B0 (1968) +0x52A6, 0x18E0, 0x2103, 0x39E7, 0x7BEE, 0xAD74, 0xA553, 0xB5D3, 0x8CAC, 0x52C5, 0x842C, 0xDEF9, 0xF7BE, 0xD69A, 0xA553, 0x8CEF, // 0x07C0 (1984) +0x8D2E, 0xAE71, 0x74EA, 0x5C46, 0x5C65, 0x5C64, 0x5443, 0x5C63, 0x5443, 0x5423, 0x5423, 0x4C03, 0x4BE3, 0x4BC3, 0x43C2, 0x43A2, // 0x07D0 (2000) +0x64C6, 0x64C6, 0x64C7, 0x64C7, 0x64E7, 0x64E7, 0x6507, 0x6507, 0x6507, 0x6D27, 0x6D27, 0x6D27, 0x6D28, 0x7528, 0x8DCC, 0xAE70, // 0x07E0 (2016) +0xB5D0, 0x94AC, 0xA52E, 0xA52F, 0xB592, 0xDEB7, 0xE719, 0xDED7, 0xBDD2, 0x6326, 0x6B67, 0xA52F, 0xC675, 0xD6F8, 0xD718, 0xBE15, // 0x07F0 (2032) +0xA552, 0x8C6E, 0x5AE8, 0x41E3, 0x62E7, 0x6B48, 0x842B, 0x948D, 0x9D0F, 0xAD71, 0xB5D3, 0xB5B2, 0xAD92, 0xA530, 0x9CCE, 0x7BCB, // 0x0800 (2048) +0x2962, 0x0840, 0x1081, 0x0000, 0x0860, 0x2984, 0x8C90, 0x9D10, 0x7C2A, 0x4AA4, 0x5B27, 0xBDF4, 0xF7BD, 0xE73B, 0xA552, 0x8CCE, // 0x0810 (2064) +0x9DF0, 0x856C, 0x6487, 0x5C66, 0x5C65, 0x5C64, 0x5C84, 0x5443, 0x5443, 0x5443, 0x5423, 0x4C03, 0x4BE3, 0x4BE3, 0x4BC2, 0x43A1, // 0x0820 (2080) +0x64E5, 0x64C5, 0x64C5, 0x64E6, 0x64E6, 0x6506, 0x6D06, 0x6D26, 0x6D26, 0x6D46, 0x6D46, 0x6D46, 0x7547, 0x7547, 0x7527, 0x960C, // 0x0830 (2096) +0xB650, 0xA56E, 0x94CC, 0x9CED, 0xB5B2, 0xDED7, 0xEF39, 0xDED7, 0xA50F, 0x5AE5, 0x73A8, 0x9D0E, 0xB5D2, 0xC655, 0xA551, 0x9D11, // 0x0840 (2112) +0x842E, 0x39E6, 0x18C1, 0x1060, 0x3162, 0x5265, 0x83CB, 0xA4F0, 0xAD31, 0xBDD3, 0xC635, 0xC635, 0xB5D3, 0xAD92, 0xA571, 0x9CF0, // 0x0850 (2128) +0x52A7, 0x1080, 0x0020, 0x0000, 0x0860, 0x4A87, 0xA552, 0x9D10, 0x844B, 0x52E5, 0x5B07, 0x9CF0, 0xE73A, 0xF7BC, 0xADD3, 0x9D90, // 0x0860 (2144) +0x95CD, 0x64A7, 0x6485, 0x64A5, 0x64A4, 0x5C63, 0x5CA4, 0x5C63, 0x5463, 0x5444, 0x5423, 0x5403, 0x4BE3, 0x4BE2, 0x4BC1, 0x4BA1, // 0x0870 (2160) +0x6CE5, 0x6CC5, 0x6CC5, 0x6CE5, 0x6D05, 0x6D06, 0x6D25, 0x6D45, 0x7546, 0x6D45, 0x7565, 0x7565, 0x7565, 0x7D87, 0x7546, 0x8568, // 0x0880 (2176) +0x95AB, 0xB62F, 0x9D4C, 0x9D4D, 0xBE12, 0xD696, 0xE718, 0xD676, 0x8C6C, 0x5AC5, 0x73A8, 0x8C6C, 0x9D0F, 0xA530, 0x94CE, 0x4225, // 0x0890 (2192) +0x0860, 0x0020, 0x0020, 0x18C0, 0x18A0, 0x39A3, 0x8C2D, 0xBDB3, 0xBDF4, 0xCE56, 0xCE98, 0xD6F9, 0xCED8, 0xC698, 0xBE36, 0xADB4, // 0x08A0 (2208) +0x94D0, 0x3A06, 0x2984, 0x31A5, 0x52C8, 0x8C8F, 0xA572, 0x9D10, 0x844B, 0x5B27, 0x7C0B, 0x9D10, 0xB5D3, 0xF7FC, 0xC6B6, 0x9DB0, // 0x08B0 (2224) +0x74E8, 0x64A5, 0x6CE5, 0x64A5, 0x64A4, 0x5C84, 0x5C84, 0x5C84, 0x5C64, 0x5C64, 0x5423, 0x5423, 0x5402, 0x4BE2, 0x4BC1, 0x4BC1, // 0x08C0 (2240) +0x6CE5, 0x6CC4, 0x6CE5, 0x6CE5, 0x7506, 0x7526, 0x7546, 0x7546, 0x7565, 0x7545, 0x7D65, 0x7565, 0x7545, 0x7D65, 0x7D86, 0x7D67, // 0x08D0 (2256) +0x8548, 0x9DCB, 0xB62E, 0xA5AD, 0xBE11, 0xDED6, 0xDEB6, 0xBDB2, 0x842B, 0x6B46, 0x73A8, 0x844B, 0x9D0E, 0xAD70, 0xBDF2, 0x73AA, // 0x08E0 (2272) +0x1921, 0x0860, 0x0000, 0x18A0, 0x2941, 0x734A, 0xAD52, 0xBDD4, 0xDEF9, 0xE75B, 0xE73C, 0xE77D, 0xE77D, 0xEF9E, 0xDF3C, 0xCEB9, // 0x08F0 (2288) +0xD6B8, 0x94D1, 0x73CD, 0x6BAC, 0x846E, 0x9D30, 0x9D51, 0xA571, 0x848D, 0x6369, 0x8C8E, 0xC676, 0x950F, 0xD738, 0xD758, 0x850D, // 0x0900 (2304) +0x64A6, 0x6D05, 0x64E5, 0x5CA4, 0x64A4, 0x64A4, 0x5C84, 0x5C84, 0x5C64, 0x5C64, 0x5C23, 0x5423, 0x5403, 0x53E2, 0x53C2, 0x4BC1, // 0x0910 (2320) +0x74E5, 0x74E5, 0x74E5, 0x74E5, 0x7526, 0x7526, 0x7546, 0x7546, 0x7546, 0x7D66, 0x7D66, 0x7D66, 0x7D86, 0x7D65, 0x85A6, 0x85A6, // 0x0920 (2336) +0x85A7, 0x8D88, 0x9DEB, 0xAE0D, 0xBE30, 0xDEF5, 0xBDD2, 0xA4EE, 0x842A, 0x7BC8, 0x7C09, 0x8C8C, 0x9D2F, 0xADB1, 0xAD90, 0xADB1, // 0x0930 (2352) +0x844D, 0x52A7, 0x52A6, 0x52A6, 0x6B49, 0xAD72, 0xD677, 0xE73A, 0xF79D, 0xF7DE, 0xF7DF, 0xF7BF, 0xEF9F, 0xF7BF, 0xF7BF, 0xF7DE, // 0x0940 (2368) +0xEF9C, 0xD6B8, 0xA593, 0x9511, 0x9510, 0xA591, 0xA571, 0x9D71, 0x8CEF, 0x6BCB, 0x9510, 0xDF79, 0x8D2E, 0xA5F0, 0xDFD8, 0x7D0B, // 0x0950 (2384) +0x6CC6, 0x6D05, 0x64C4, 0x64C5, 0x64C5, 0x64A5, 0x6484, 0x6484, 0x6464, 0x5C64, 0x5C23, 0x5C23, 0x5C03, 0x53E2, 0x53C2, 0x53C2, // 0x0960 (2400) +0x74E5, 0x74E5, 0x7505, 0x7506, 0x7526, 0x7D46, 0x7D46, 0x7D46, 0x7D66, 0x7D67, 0x7D66, 0x8586, 0x85A7, 0x8586, 0x85A5, 0x85A6, // 0x0970 (2416) +0x7D85, 0x85C7, 0x8D87, 0xAE2C, 0xBE50, 0xBE31, 0xA50E, 0xA50E, 0x94AC, 0x844A, 0x73E8, 0x844A, 0xA56F, 0xADB1, 0xB5D1, 0x9D2F, // 0x0980 (2432) +0xA530, 0x9CCF, 0x842C, 0x8C4D, 0xB5D3, 0xD697, 0xE73A, 0xF7BD, 0xF7BE, 0xF7DF, 0xF7DF, 0xF7FF, 0xFFFF, 0xFFDF, 0xF7BE, 0xFFFF, // 0x0990 (2448) +0xEFBD, 0xE73B, 0xD6FA, 0xB5D5, 0xA572, 0xA572, 0xA592, 0x9D72, 0x848E, 0x7C2D, 0xA5D3, 0xD758, 0x8D2C, 0x856B, 0xC753, 0x854A, // 0x09A0 (2464) +0x6D06, 0x6CE5, 0x6CC5, 0x6CE5, 0x6CC5, 0x64A5, 0x6484, 0x6484, 0x6464, 0x6444, 0x5C23, 0x5C23, 0x5C03, 0x53E3, 0x53C3, 0x53C3, // 0x09B0 (2480) +0x7505, 0x7505, 0x7525, 0x7D26, 0x7D26, 0x7D46, 0x7D46, 0x7D67, 0x8587, 0x8587, 0x8587, 0x85A7, 0x8586, 0x85C6, 0x8DC6, 0x8DC6, // 0x09C0 (2496) +0x85E6, 0x8DE6, 0x8DC7, 0x9589, 0xBE6F, 0xB5CF, 0xAD6F, 0xBDD1, 0x9D0D, 0x8CAB, 0x7C29, 0x846B, 0xA56F, 0xADD1, 0xADB1, 0xA570, // 0x09D0 (2512) +0xA52F, 0xA50F, 0x9CEF, 0xAD71, 0xC655, 0xD6B7, 0xE75B, 0xF7DD, 0xF7DE, 0xF7FF, 0xF7FF, 0xF7DF, 0xFFFF, 0xFFFF, 0xFFBE, 0xFFDE, // 0x09E0 (2528) +0xFFDF, 0xF7BE, 0xDF3C, 0xCE99, 0xADD5, 0xADB4, 0xADD4, 0xA593, 0x84AF, 0x7C6E, 0xB655, 0xDFB9, 0x8D8B, 0x7D28, 0x7D28, 0x7528, // 0x09F0 (2544) +0x7527, 0x7506, 0x6CE6, 0x64A5, 0x6CA5, 0x6CA5, 0x6484, 0x6484, 0x6464, 0x6464, 0x5C43, 0x5C23, 0x5C03, 0x5BE3, 0x53C3, 0x53C3, // 0x0A00 (2560) +0x7D06, 0x7D06, 0x7D07, 0x8527, 0x8547, 0x8547, 0x8567, 0x8567, 0x8DA8, 0x8DA8, 0x8DA8, 0x8DA8, 0x8DA7, 0x8DC8, 0x95C7, 0x95C8, // 0x0A10 (2576) +0x95E8, 0x8DC8, 0x95E8, 0x95A9, 0xB68F, 0xDF96, 0xE7B9, 0xBE14, 0xA590, 0x9D2E, 0x8CAB, 0x94CC, 0x9D4E, 0xA590, 0xADD2, 0xB5D2, // 0x0A20 (2592) +0xA570, 0xAD50, 0xAD71, 0xC614, 0xCE76, 0xDF19, 0xEF9C, 0xF7DD, 0xEFBD, 0xEF9D, 0xF7FE, 0xF7DE, 0xE77D, 0xEF9D, 0xF7DE, 0xEFBE, // 0x0A30 (2608) +0xE75D, 0xF7DF, 0xE77D, 0xC678, 0xB615, 0xB614, 0xB635, 0x9D93, 0x84EF, 0x8D0F, 0xC6D8, 0xCF57, 0x8D6A, 0x7D47, 0x7527, 0x7506, // 0x0A40 (2624) +0x6D06, 0x6D06, 0x6CE5, 0x6CE5, 0x6CC5, 0x6CA5, 0x6484, 0x6465, 0x6465, 0x6465, 0x6445, 0x6424, 0x6404, 0x5BE4, 0x5BC3, 0x53C2, // 0x0A50 (2640) +0x7D27, 0x7D07, 0x7D07, 0x7D27, 0x8547, 0x8568, 0x8D88, 0x8D88, 0x8DA8, 0x8DA8, 0x8DC8, 0x95C8, 0x95C8, 0x95C8, 0x95E8, 0x95E8, // 0x0A60 (2656) +0x95E8, 0x95E8, 0x95C8, 0x95CA, 0xBE71, 0xF7FA, 0xEFDA, 0xCE96, 0xADB0, 0xA56F, 0x9D2E, 0xA54F, 0xA58F, 0xA590, 0xB5F2, 0xB613, // 0x0A70 (2672) +0xB5D2, 0xB5B2, 0xB5F3, 0xB5F3, 0xD6B7, 0xE75A, 0xDF19, 0xDEFA, 0xDF1A, 0xDEFA, 0xADD5, 0x9D33, 0x8C91, 0x94F2, 0xADB5, 0xC658, // 0x0A80 (2688) +0xDF3C, 0xEF7D, 0xEFBE, 0xCEDA, 0xA5B3, 0xBE76, 0xB615, 0xA5D4, 0x8D10, 0xA5D3, 0xCF59, 0xBED5, 0x8D8A, 0x7D27, 0x7D47, 0x7D47, // 0x0A90 (2704) +0x7527, 0x6D06, 0x6CE5, 0x6CC5, 0x6CC5, 0x6CA5, 0x6CA5, 0x6C85, 0x6C85, 0x6C65, 0x6C65, 0x6445, 0x6424, 0x5C04, 0x5BE3, 0x5BC3, // 0x0AA0 (2720) +0x8528, 0x8528, 0x8507, 0x8527, 0x8548, 0x8D68, 0x8D88, 0x8DA9, 0x8DA8, 0x8DA8, 0x95C8, 0x95C8, 0x95C8, 0x95E8, 0x95E8, 0x95E8, // 0x0AB0 (2736) +0x95E7, 0x95E8, 0x95C9, 0xAE4E, 0xE7D9, 0xF7FD, 0xF7DC, 0xCE95, 0xB5D1, 0xADB0, 0xAD70, 0xA54F, 0x9D4E, 0xA58F, 0xB612, 0xBE54, // 0x0AC0 (2752) +0xC654, 0xC654, 0xB5F2, 0xBE14, 0xCEB6, 0xDF39, 0xDF19, 0xD6F9, 0xB5F5, 0x7C0F, 0x5B0B, 0x5B2B, 0x636C, 0x73AD, 0x73EE, 0x8C91, // 0x0AD0 (2768) +0xBE16, 0xD6FA, 0xEFDE, 0xE79D, 0xBE56, 0xB615, 0xADF5, 0xADF5, 0x9D92, 0xC6D7, 0xE7DB, 0xC6F5, 0x95AB, 0x7D48, 0x7D47, 0x7527, // 0x0AE0 (2784) +0x7527, 0x6D06, 0x6CE5, 0x6CC5, 0x6CC5, 0x6CA5, 0x6CA5, 0x6CA5, 0x6C85, 0x6C65, 0x6C45, 0x6445, 0x6425, 0x6424, 0x6404, 0x5BE3, // 0x0AF0 (2800) +0x8528, 0x8528, 0x8528, 0x8548, 0x8D69, 0x8D69, 0x8D69, 0x8D89, 0x8DA9, 0x95A9, 0x95C9, 0x95C9, 0x95C8, 0x95E9, 0x95E8, 0x9E08, // 0x0B00 (2816) +0x9E08, 0x9DC8, 0x9DEC, 0xDF97, 0xFFFD, 0xFFFF, 0xF7DC, 0xD6D7, 0xB5F2, 0xADB0, 0xA570, 0xA570, 0x9D4F, 0xA590, 0xB612, 0xBE53, // 0x0B10 (2832) +0xBE53, 0xBE13, 0xBE13, 0xBE34, 0xDF18, 0xDF39, 0xE77A, 0xCE77, 0x94B0, 0x6B6C, 0x632B, 0x5289, 0x4A68, 0x4A68, 0x52A9, 0x7BEE, // 0x0B20 (2848) +0x73ED, 0xBE37, 0xDF5C, 0xE79D, 0xCF19, 0xB636, 0xB636, 0xA5D4, 0xAE14, 0xCF38, 0xDFB9, 0xC714, 0x95AB, 0x8569, 0x7D67, 0x7547, // 0x0B30 (2864) +0x7527, 0x6D06, 0x6CE5, 0x6CC5, 0x6CC5, 0x6CA5, 0x6CA5, 0x74A6, 0x6C85, 0x6C66, 0x6C65, 0x6C46, 0x6C45, 0x6C25, 0x6404, 0x63E4, // 0x0B40 (2880) +0x8528, 0x8528, 0x8529, 0x8D49, 0x8D49, 0x8D49, 0x8D69, 0x8D69, 0x8D89, 0x9589, 0x95A9, 0x95C9, 0x95E9, 0x95E9, 0x9DE9, 0x9DE9, // 0x0B50 (2896) +0x95C8, 0x9DCB, 0xCF15, 0xFFFD, 0xF7FE, 0xFFFF, 0xF7FD, 0xE739, 0xBE33, 0xAD90, 0xA54E, 0xA58F, 0xA590, 0xA591, 0xADF1, 0xB612, // 0x0B60 (2912) +0xBE12, 0xB5D2, 0xC654, 0xD6D7, 0xDEF8, 0xD6D8, 0xC656, 0xBDF5, 0x630A, 0x5289, 0x2102, 0x0840, 0x0820, 0x0800, 0x0820, 0x39C6, // 0x0B70 (2928) +0x634B, 0xA594, 0xC679, 0xE77D, 0xDF7B, 0xCEF9, 0xBE97, 0xADF4, 0xBE96, 0xCF17, 0xC715, 0xAE70, 0x8D8A, 0x8568, 0x7D48, 0x7D47, // 0x0B80 (2944) +0x6D27, 0x6CE7, 0x6CE6, 0x6CC5, 0x6CC5, 0x6CA5, 0x74A5, 0x74A6, 0x7486, 0x7466, 0x7466, 0x7466, 0x7466, 0x6C46, 0x6C25, 0x6405, // 0x0B90 (2960) +0x8508, 0x8508, 0x8D29, 0x8D29, 0x8D49, 0x8D49, 0x8D49, 0x8D69, 0x9589, 0x9589, 0x95A9, 0x9DCA, 0x95C9, 0x9DE9, 0x95E9, 0x95C9, // 0x0BA0 (2976) +0x9DAB, 0xCED3, 0xF7FD, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFD, 0xDF19, 0xC674, 0xB5D1, 0xA56E, 0x9D2D, 0x952F, 0xA570, 0xA5B1, 0xADD1, // 0x0BB0 (2992) +0xBE13, 0xC655, 0xD6D7, 0xD6D7, 0xD6D7, 0xB5D4, 0xB5B4, 0xB5B4, 0x738C, 0x3185, 0x0820, 0x0000, 0x0000, 0x0000, 0x0000, 0x18C2, // 0x0BC0 (3008) +0x5B4B, 0x9512, 0xADD6, 0xD71C, 0xDF9C, 0xC6F9, 0xC6F8, 0xAE35, 0xBEB6, 0xC6F5, 0xB6D2, 0x9DED, 0x95CB, 0x8589, 0x7D68, 0x7D48, // 0x0BD0 (3024) +0x7527, 0x6CE7, 0x64C6, 0x64A6, 0x6CA6, 0x6CC6, 0x74A6, 0x74A7, 0x7486, 0x7487, 0x7467, 0x7467, 0x7467, 0x7446, 0x6C26, 0x6C05, // 0x0BE0 (3040) +0x84E8, 0x84E8, 0x8508, 0x8D29, 0x8D29, 0x8D49, 0x8D4A, 0x8D4A, 0x956A, 0x958A, 0x95AA, 0x95CA, 0x95C9, 0x95C9, 0x95E9, 0x9DCB, // 0x0BF0 (3056) +0xC6D3, 0xFFFD, 0xFFFF, 0xFFFF, 0xFFDE, 0xFFFE, 0xF7DB, 0xDF18, 0xCE95, 0xBE32, 0xADAF, 0x94EC, 0x8CAC, 0x950E, 0x9D4F, 0xA5B1, // 0x0C00 (3072) +0xB5F2, 0xCEB6, 0xCE96, 0xCEB6, 0xC676, 0xB5D4, 0xAD93, 0x94F1, 0x73AD, 0x1902, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0C10 (3088) +0x4288, 0x8490, 0x9D55, 0xBE59, 0xD75B, 0xC6D8, 0xC6F8, 0xB675, 0xBED5, 0xB692, 0xAE90, 0x9DEC, 0x95EB, 0x8DAA, 0x8589, 0x7D68, // 0x0C20 (3104) +0x7528, 0x6CE7, 0x64A6, 0x64A6, 0x6CA6, 0x74C6, 0x74C7, 0x7CC7, 0x7CA7, 0x7C87, 0x7C87, 0x7C88, 0x7C68, 0x7447, 0x6C27, 0x6C26, // 0x0C30 (3120) +0x84E8, 0x84E8, 0x8508, 0x8D29, 0x8D49, 0x8D49, 0x8D29, 0x8D29, 0x8D49, 0x956A, 0x958A, 0x9589, 0x95A9, 0x95CA, 0x9E0A, 0xA60D, // 0x0C40 (3136) +0xEFFA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7DD, 0xF7BB, 0xDF17, 0xCE94, 0xBE32, 0xB5D0, 0xA56E, 0x94ED, 0x84AC, 0x8CCD, 0xA591, // 0x0C50 (3152) +0xADF3, 0xADD3, 0xBE54, 0xC6B7, 0xBE76, 0xA593, 0x9511, 0x8CD1, 0x5B2B, 0x31A5, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0881, // 0x0C60 (3168) +0x4268, 0x742F, 0x9D35, 0xB639, 0xCF3A, 0xCF39, 0xAE34, 0xC6F6, 0xCF57, 0xAE71, 0xA64E, 0x9E0C, 0x8D8A, 0x8569, 0x7D48, 0x7528, // 0x0C70 (3184) +0x6CE7, 0x64C7, 0x64A6, 0x64A6, 0x6CC6, 0x74C7, 0x7CC7, 0x7CC7, 0x7CC8, 0x7CA8, 0x7CA8, 0x7CA8, 0x7C88, 0x7468, 0x7447, 0x7447, // 0x0C80 (3200) +0x7CC7, 0x7CC7, 0x84E8, 0x8D08, 0x8D29, 0x9529, 0x8D09, 0x8D09, 0x8D29, 0x954A, 0x956A, 0x9569, 0x95A9, 0x95A9, 0x958C, 0xC6B3, // 0x0C90 (3216) +0xFFFD, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDD, 0xF7BC, 0xEF5A, 0xDEF7, 0xC653, 0xBE12, 0xB5D0, 0xA56F, 0x94EC, 0x8CAC, 0x846B, 0x8CCD, // 0x0CA0 (3232) +0xADD1, 0x8D0F, 0xA591, 0xBE75, 0xB614, 0x9D72, 0x8CD0, 0x846F, 0x5B0A, 0x31A5, 0x0880, 0x0000, 0x0000, 0x0020, 0x0000, 0x18C1, // 0x0CB0 (3248) +0x4226, 0x638B, 0x8CB1, 0xB617, 0xD75B, 0xC6B8, 0xB657, 0xE7DB, 0xD757, 0xAE50, 0xA60C, 0x9DEA, 0x8D89, 0x8569, 0x7507, 0x74E7, // 0x0CC0 (3264) +0x6CE7, 0x6CA6, 0x64A6, 0x6CA7, 0x74C7, 0x7CC8, 0x7CC8, 0x84C8, 0x84C9, 0x84A9, 0x84A9, 0x84A9, 0x84A9, 0x7C89, 0x7C89, 0x7C68, // 0x0CD0 (3280) +0x7CA7, 0x7CA7, 0x7CC7, 0x84E8, 0x8CE9, 0x8CE9, 0x8CE9, 0x8CE9, 0x8D09, 0x8D2A, 0x8D4A, 0x8D49, 0x8D69, 0x956A, 0xA5EE, 0xE798, // 0x0CE0 (3296) +0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xF7BD, 0xEF7B, 0xDF18, 0xD6B6, 0xC654, 0xB5D1, 0xA56F, 0xADD0, 0x9D2E, 0x846B, 0x846B, 0x846B, // 0x0CF0 (3312) +0x94EE, 0x952F, 0x6BEA, 0xADD2, 0xBE34, 0x9D31, 0x848F, 0x73CD, 0x52C8, 0x2984, 0x0880, 0x0860, 0x0020, 0x0840, 0x18C1, 0x18E1, // 0x0D00 (3328) +0x29C3, 0x5B29, 0x7C4F, 0xB5F6, 0xCEF9, 0xC6B9, 0xDF9C, 0xF7FD, 0xE7D9, 0xBEB2, 0x9DCC, 0x95A9, 0x8548, 0x7507, 0x6CE7, 0x6CE7, // 0x0D10 (3344) +0x6CC7, 0x6CA7, 0x6C86, 0x6CA7, 0x74C8, 0x7CC8, 0x7CC8, 0x84E9, 0x84C9, 0x84A9, 0x84A9, 0x84A9, 0x84A9, 0x8489, 0x7C89, 0x7C69, // 0x0D20 (3360) +0x7C87, 0x7C87, 0x7CA8, 0x84C9, 0x8CE9, 0x8CC9, 0x8CC9, 0x8CE9, 0x8D09, 0x8D09, 0x8D29, 0x8D4A, 0x956A, 0x958B, 0xB651, 0xF7FB, // 0x0D30 (3376) +0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xF7BC, 0xEF7A, 0xE738, 0xDEF7, 0xD6B5, 0xBE12, 0xADB0, 0xA54F, 0xA54E, 0x94ED, 0x848B, 0x846B, // 0x0D40 (3392) +0x848C, 0x94EE, 0x8CCE, 0x846D, 0xAD91, 0xA571, 0x7C2D, 0x634A, 0x4A87, 0x31C4, 0x18E1, 0x1901, 0x0860, 0x0020, 0x18C1, 0x18E1, // 0x0D50 (3408) +0x29C3, 0x4286, 0x740D, 0xADD4, 0xC697, 0xD73A, 0xF7FE, 0xF7FE, 0xF7FB, 0xCF15, 0x9DEC, 0x95AA, 0x8548, 0x6CE6, 0x6CE6, 0x64A5, // 0x0D60 (3424) +0x6486, 0x6C87, 0x6C87, 0x74A7, 0x74A8, 0x7CC8, 0x84C9, 0x84E9, 0x84C9, 0x84A9, 0x84A9, 0x84AA, 0x84A9, 0x8489, 0x848A, 0x7C69, // 0x0D70 (3440) +0x7446, 0x7466, 0x7C87, 0x84A8, 0x84A9, 0x84A9, 0x84A8, 0x84C8, 0x84E9, 0x84E9, 0x8D09, 0x8D2A, 0x954A, 0x954C, 0xC694, 0xF7FC, // 0x0D80 (3456) +0xFFFE, 0xFFFF, 0xFFDE, 0xEF9C, 0xE73A, 0xDF18, 0xDF17, 0xD6F6, 0xC653, 0xBE12, 0xADB0, 0x94CC, 0x94CC, 0x94ED, 0x8C8B, 0x844A, // 0x0D90 (3472) +0x7C2A, 0x7C0A, 0x94EE, 0x8C8D, 0x7C4B, 0x8CAD, 0x844C, 0x52C6, 0x4285, 0x2982, 0x08A0, 0x0880, 0x0080, 0x08A0, 0x1901, 0x31E4, // 0x0DA0 (3488) +0x42A6, 0x6C0B, 0x9D71, 0xA593, 0xB615, 0xE75B, 0xF7FE, 0xFFFF, 0xF7FC, 0xD736, 0x9DAC, 0x8528, 0x74E6, 0x64A5, 0x64A5, 0x6485, // 0x0DB0 (3504) +0x6466, 0x6C67, 0x6C87, 0x7487, 0x74A8, 0x7CA8, 0x84C8, 0x84C9, 0x84C9, 0x84A9, 0x8489, 0x8489, 0x8489, 0x848A, 0x846A, 0x7C49, // 0x0DC0 (3520) +0x6C25, 0x7446, 0x7466, 0x7C87, 0x8488, 0x8488, 0x84A8, 0x8CC8, 0x8D09, 0x8D09, 0x8D4A, 0x8D2A, 0x8D09, 0x952C, 0xDF58, 0xFFFD, // 0x0DD0 (3536) +0xFFFE, 0xFFFF, 0xF7DD, 0xE75A, 0xDF18, 0xDF17, 0xDEF7, 0xD6B6, 0xCE94, 0xB5D1, 0x94EE, 0x846C, 0x7C2A, 0x7C2B, 0x8CAC, 0x844A, // 0x0DE0 (3552) +0x6BC8, 0x6BE8, 0x6BC8, 0x848B, 0x7C2A, 0x7C2A, 0x94ED, 0x7C6B, 0x63A8, 0x5306, 0x42A5, 0x4264, 0x42A5, 0x4AC6, 0x4AC6, 0x6BCA, // 0x0DF0 (3568) +0x84CE, 0xA5B2, 0x9D71, 0x9510, 0xB614, 0xE75A, 0xF7DE, 0xF7DE, 0xFFFD, 0xD737, 0xA5ED, 0x7D07, 0x6CC5, 0x6464, 0x5C43, 0x5C24, // 0x0E00 (3584) +0x6446, 0x6C47, 0x6C67, 0x7487, 0x7487, 0x7CA8, 0x7CA8, 0x7CA8, 0x7CA8, 0x7C68, 0x7C68, 0x7C69, 0x7C69, 0x7C69, 0x7C49, 0x7C29, // 0x0E10 (3600) +0x7446, 0x7446, 0x7C66, 0x7C67, 0x8468, 0x8488, 0x84C8, 0x8CE8, 0x8D29, 0x9529, 0x954A, 0x8D0A, 0x8D0A, 0xADD0, 0xF7FB, 0xFFFE, // 0x0E20 (3616) +0xFFFF, 0xFFFE, 0xEFBC, 0xE75A, 0xDF18, 0xDF18, 0xD6F6, 0xCE95, 0xB5B1, 0x9D0F, 0x94CE, 0x94EE, 0x94AD, 0x8C8C, 0x8CAC, 0x844A, // 0x0E30 (3632) +0x7409, 0x6BC7, 0x63A7, 0x5B66, 0x6BC7, 0x6366, 0x6BC8, 0x846A, 0x8CCC, 0x84AB, 0x742A, 0x6BC9, 0x6388, 0x63A9, 0x742B, 0x8CEE, // 0x0E40 (3648) +0x8CEF, 0x84AE, 0x848E, 0x9510, 0xADB2, 0xD6D8, 0xF7FE, 0xF7FF, 0xE79B, 0xBE94, 0x958B, 0x7CE6, 0x6CA5, 0x6464, 0x5C23, 0x6445, // 0x0E50 (3664) +0x6446, 0x6C47, 0x6C67, 0x7467, 0x7487, 0x7487, 0x7487, 0x7C67, 0x7C67, 0x7447, 0x7C47, 0x7C48, 0x7C48, 0x7C49, 0x7C29, 0x7408, // 0x0E60 (3680) +0x7C87, 0x7C87, 0x7C67, 0x7C67, 0x8488, 0x8488, 0x84C8, 0x8CE9, 0x8D29, 0x8D09, 0x8D0A, 0x8D0A, 0x9D6D, 0xD6F5, 0xFFFE, 0xFFFF, // 0x0E70 (3696) +0xF7FF, 0xF7DE, 0xEF7C, 0xDF19, 0xD6D7, 0xCEB6, 0xC674, 0xBE13, 0xBDF3, 0xB5B2, 0xB5D2, 0xA571, 0x94EE, 0x94CE, 0x8C8C, 0x846B, // 0x0E80 (3712) +0x73C8, 0x6366, 0x6B87, 0x6366, 0x5B25, 0x5304, 0x5B05, 0x6346, 0x6BA7, 0x73C8, 0x73E9, 0x7C4B, 0x7C4B, 0x7C4C, 0x7C4C, 0x7C2C, // 0x0E90 (3728) +0x848E, 0x7C4E, 0x8CEF, 0x9D30, 0xA571, 0xC696, 0xE77B, 0xE77C, 0xEFFC, 0xBEB4, 0x8D6B, 0x74C6, 0x6C84, 0x6443, 0x5C03, 0x6424, // 0x0EA0 (3744) +0x6425, 0x6C47, 0x6C46, 0x6C66, 0x6C46, 0x7446, 0x6C45, 0x7445, 0x7425, 0x6C26, 0x7426, 0x7427, 0x7407, 0x7408, 0x73E8, 0x6BC8, // 0x0EB0 (3760) +0x8CE9, 0x84C9, 0x84A8, 0x84A9, 0x8CA9, 0x8CA9, 0x8CC9, 0x8CE9, 0x8D2A, 0x8D2A, 0x8D0A, 0x952B, 0xADCF, 0xF7FA, 0xFFFF, 0xFFDF, // 0x0EC0 (3776) +0xF7BE, 0xEFBD, 0xE77B, 0xD6F9, 0xCE96, 0xC674, 0xC654, 0xC634, 0xBE13, 0xADB2, 0xA551, 0x9D30, 0x844C, 0x8CAD, 0x94CD, 0x7C0A, // 0x0ED0 (3792) +0x6346, 0x73C9, 0x6BA7, 0x6346, 0x6325, 0x6346, 0x6366, 0x5AE4, 0x52C4, 0x5AE5, 0x5B05, 0x6347, 0x6389, 0x6BAA, 0x6BCA, 0x740C, // 0x0EE0 (3808) +0x848F, 0x9511, 0x9D31, 0x9D50, 0xB5F3, 0xC696, 0xCED9, 0xE77C, 0xE7BB, 0xB673, 0x854A, 0x6CA5, 0x6463, 0x6443, 0x6423, 0x6404, // 0x0EF0 (3824) +0x6425, 0x6C26, 0x6C46, 0x6C46, 0x6C25, 0x6C25, 0x6C24, 0x6C04, 0x6C04, 0x6C05, 0x7406, 0x7406, 0x6BE7, 0x6BC7, 0x6BC7, 0x63A6, // 0x0F00 (3840) +0x952A, 0x950A, 0x8D09, 0x8D09, 0x8D29, 0x8D0A, 0x8D09, 0x8D09, 0x952A, 0x954A, 0x9529, 0x950B, 0xCEB6, 0xFFFF, 0xF7FE, 0xF7DE, // 0x0F10 (3856) +0xEFBD, 0xE79C, 0xE75B, 0xDF5A, 0xD718, 0xCEB6, 0xC654, 0xC654, 0xB5D2, 0xA570, 0x9D2F, 0x9D2F, 0x94EE, 0x8CCD, 0x848C, 0x6388, // 0x0F20 (3872) +0x6BA8, 0x73E9, 0x6367, 0x6367, 0x6346, 0x6B87, 0x5B06, 0x5AE5, 0x6326, 0x6326, 0x6347, 0x6368, 0x6388, 0x73CA, 0x740B, 0x7C4C, // 0x0F30 (3888) +0x848D, 0x94F0, 0xA592, 0xADF4, 0xBE36, 0xCED9, 0xDF3C, 0xE7BD, 0xD759, 0xAE10, 0x8D4A, 0x6C85, 0x6C65, 0x6445, 0x6424, 0x6425, // 0x0F40 (3904) +0x6406, 0x6407, 0x6C26, 0x6C45, 0x6C24, 0x6C23, 0x6403, 0x6C03, 0x6C04, 0x6C05, 0x6BE6, 0x63C6, 0x63A6, 0x63A5, 0x63A5, 0x6385, // 0x0F50 (3920) +0x952A, 0x950A, 0x9529, 0x954A, 0x954A, 0x952A, 0x9529, 0x954A, 0x9D6B, 0x952A, 0x950A, 0xB610, 0xEFBB, 0xFFFF, 0xF7FE, 0xEFDE, // 0x0F60 (3936) +0xE77C, 0xE79C, 0xE75B, 0xD6F8, 0xC696, 0xBE34, 0xB5D2, 0xAD91, 0xA570, 0xA54F, 0x9D2F, 0x9D2F, 0x94EE, 0x8CCD, 0x846C, 0x73EA, // 0x0F70 (3952) +0x73E9, 0x73E9, 0x6347, 0x5B26, 0x5B26, 0x6326, 0x6326, 0x5B05, 0x6347, 0x6347, 0x6347, 0x6348, 0x6388, 0x6BC9, 0x740B, 0x7C2C, // 0x0F80 (3968) +0x846D, 0x84AE, 0x8CF0, 0xA572, 0xB615, 0xCED9, 0xD73B, 0xE79D, 0xD738, 0xA5F0, 0x8D4A, 0x74A6, 0x6C86, 0x6C65, 0x6445, 0x6405, // 0x0F90 (3984) +0x6406, 0x6406, 0x6C26, 0x6425, 0x6403, 0x6402, 0x63E2, 0x63E3, 0x6C04, 0x6BE5, 0x63C5, 0x63A5, 0x6385, 0x5B65, 0x5B64, 0x5B64, // 0x0FA0 (4000) +0x952A, 0x952A, 0x952A, 0x9D4A, 0x954A, 0x952A, 0x952A, 0x954A, 0x9D4B, 0x9D4C, 0x9D4C, 0xD716, 0xFFFD, 0xF7FE, 0xF7DE, 0xEFBD, // 0x0FB0 (4016) +0xE79D, 0xDF5B, 0xD6D9, 0xCE97, 0xCE96, 0xCE96, 0xBE34, 0xADB2, 0x9D2F, 0x9D0F, 0x9D2F, 0x9D0F, 0x950F, 0x94EE, 0x846C, 0x740A, // 0x0FC0 (4032) +0x73EA, 0x73EA, 0x5B47, 0x52E6, 0x52C5, 0x5B06, 0x6B68, 0x6306, 0x5B06, 0x5AE6, 0x52E5, 0x5AE6, 0x6347, 0x6B89, 0x740B, 0x7C4C, // 0x0FD0 (4048) +0x84AE, 0x8CEF, 0x9510, 0x9D72, 0xADD4, 0xBE56, 0xCEFA, 0xEFFD, 0xCF37, 0x958D, 0x8509, 0x74C6, 0x74A6, 0x6C66, 0x6C46, 0x6426, // 0x0FE0 (4064) +0x6406, 0x63E5, 0x6405, 0x63E4, 0x63E3, 0x63E2, 0x63C2, 0x63E3, 0x63E4, 0x63C4, 0x63A4, 0x5B84, 0x5B64, 0x5B64, 0x5B43, 0x5342, // 0x0FF0 (4080) +0x950A, 0x950A, 0x9529, 0x954A, 0x954A, 0x8D0A, 0x8D09, 0x8D0A, 0x952B, 0x9D4C, 0xADD0, 0xF7DB, 0xFFFE, 0xF7BE, 0xEFBD, 0xEF9D, // 0x1000 (4096) +0xE77C, 0xE77B, 0xDF5A, 0xD6F8, 0xC696, 0xBE14, 0xB5D2, 0xAD91, 0x9D0F, 0x94EE, 0x94EF, 0x94EE, 0x94CE, 0x94EF, 0x8C8D, 0x7C2B, // 0x1010 (4112) +0x7C4B, 0x6BC9, 0x6348, 0x6347, 0x5B06, 0x5AE6, 0x6B88, 0x6B88, 0x6327, 0x5B06, 0x5B07, 0x5B07, 0x6348, 0x6368, 0x73EA, 0x7C4C, // 0x1020 (4128) +0x846D, 0x8CCF, 0x9D51, 0xA5B2, 0xADF4, 0xB636, 0xCED9, 0xEFDD, 0xD777, 0x8D2C, 0x7CC7, 0x74C6, 0x74A7, 0x6446, 0x6446, 0x6C26, // 0x1030 (4144) +0x63E6, 0x63E5, 0x63E4, 0x5BE4, 0x63C3, 0x63E3, 0x63C2, 0x63E3, 0x63C3, 0x63A3, 0x5B83, 0x5B63, 0x5B63, 0x5B63, 0x5342, 0x5322, // 0x1040 (4160) +0x94E9, 0x94E9, 0x9509, 0x952A, 0x952A, 0x8D0A, 0x84C9, 0x84C9, 0x950B, 0x950D, 0xC695, 0xFFFD, 0xF7FE, 0xEFBE, 0xEF9D, 0xEF9D, // 0x1050 (4176) +0xE77C, 0xDF5B, 0xDF19, 0xCEB7, 0xBE34, 0xB5D3, 0xADB2, 0xADB2, 0xA550, 0x94CE, 0x94CE, 0x8CAE, 0x846D, 0x846D, 0x846C, 0x7C4C, // 0x1060 (4192) +0x7C4C, 0x6BCA, 0x6BAA, 0x6B89, 0x6368, 0x6347, 0x6B89, 0x6BA9, 0x6B89, 0x6B68, 0x6B68, 0x6368, 0x6B89, 0x6BA9, 0x73EB, 0x7C2C, // 0x1070 (4208) +0x846D, 0x8CCF, 0x9510, 0x9D51, 0xA593, 0xB615, 0xCEFA, 0xF7FE, 0xDFD9, 0x8D4C, 0x7CC7, 0x7CE7, 0x74A7, 0x6C46, 0x6426, 0x6C27, // 0x1080 (4224) +0x6405, 0x5BE5, 0x63E4, 0x5BC3, 0x63C3, 0x63E3, 0x63E3, 0x63E4, 0x63C3, 0x5BA3, 0x5B83, 0x5B63, 0x5B63, 0x5B63, 0x5342, 0x5322, // 0x1090 (4240) +0x8CA9, 0x8CA9, 0x8D09, 0x952A, 0x954B, 0x8D2A, 0x8CEA, 0x84CA, 0x8CEA, 0xA58F, 0xEFBB, 0xF7FF, 0xF7DE, 0xEFBE, 0xE79D, 0xE77C, // 0x10A0 (4256) +0xD719, 0xCEB8, 0xBE56, 0xB614, 0xB613, 0xB613, 0xB5D2, 0xAD90, 0xA52F, 0x8C8D, 0x846C, 0x846D, 0x844C, 0x7C2C, 0x7C4C, 0x846C, // 0x10B0 (4272) +0x740B, 0x73EB, 0x7C0B, 0x6BA9, 0x6BA9, 0x73CA, 0x73CA, 0x6B89, 0x6BA9, 0x6B89, 0x6B89, 0x6B89, 0x6BCA, 0x73EB, 0x740B, 0x7C0C, // 0x10C0 (4288) +0x740B, 0x846D, 0x8CCE, 0x9510, 0x9D72, 0xB615, 0xCED9, 0xEFDD, 0xE7DA, 0x956D, 0x7D09, 0x7CE7, 0x74A7, 0x6C67, 0x6C46, 0x6426, // 0x10D0 (4304) +0x6405, 0x5BE5, 0x5BE4, 0x5BC4, 0x63E4, 0x6404, 0x63E4, 0x63E4, 0x63C3, 0x5BA3, 0x5B83, 0x5B62, 0x5B62, 0x5B62, 0x5342, 0x5321, // 0x10E0 (4320) +0x8488, 0x8CA9, 0x8CE9, 0x8D0A, 0x952B, 0x8D2B, 0x8D0B, 0x84EA, 0x84CA, 0xBE73, 0xFFFE, 0xF7FF, 0xEFBE, 0xE79D, 0xE77C, 0xD6F9, // 0x10F0 (4336) +0xCED8, 0xC697, 0xBE35, 0xADB2, 0x9D30, 0x94EE, 0x94CD, 0x8CCD, 0x9D0F, 0x9CEE, 0x8C8D, 0x844C, 0x7C4C, 0x73EB, 0x6BCA, 0x6BAA, // 0x1100 (4352) +0x740B, 0x740B, 0x73EA, 0x73CA, 0x7C0B, 0x7C0B, 0x73EA, 0x73CA, 0x6BCA, 0x6BCA, 0x6BAA, 0x6BAA, 0x6BCA, 0x73EB, 0x73EB, 0x73EB, // 0x1110 (4368) +0x73EB, 0x73EB, 0x742C, 0x848E, 0x9531, 0xB616, 0xCEDA, 0xE7BD, 0xDFBA, 0x958E, 0x8529, 0x7CE7, 0x7486, 0x6C66, 0x6446, 0x6425, // 0x1120 (4384) +0x5BE5, 0x5BC4, 0x5BE4, 0x5BC4, 0x63E4, 0x6405, 0x63E4, 0x63E4, 0x5BC3, 0x5BA3, 0x5B62, 0x5362, 0x5362, 0x5342, 0x5321, 0x4B21, // 0x1130 (4400) +0x8489, 0x8CA9, 0x8CE9, 0x8CEA, 0x8D0A, 0x8D2B, 0x8D2B, 0x850A, 0x84EB, 0xCEF5, 0xF7FE, 0xEFDF, 0xE79E, 0xE77D, 0xD73A, 0xCEB8, // 0x1140 (4416) +0xC697, 0xBE35, 0xB5D4, 0xADD3, 0xA571, 0x94EE, 0x844B, 0x7C0A, 0x7C0B, 0x94EE, 0x8CAD, 0x844C, 0x7C4C, 0x7C0B, 0x73CA, 0x6BCA, // 0x1150 (4432) +0x73CA, 0x73EA, 0x6B89, 0x6B89, 0x73EA, 0x7C0B, 0x73CA, 0x6389, 0x6B89, 0x6BCA, 0x6BCA, 0x6BAA, 0x6389, 0x6BCA, 0x6BCB, 0x73EB, // 0x1160 (4448) +0x73EB, 0x7C2C, 0x848D, 0x9510, 0x9D51, 0xADD5, 0xC699, 0xE79D, 0xDFBA, 0x958E, 0x854A, 0x7D07, 0x6C86, 0x6425, 0x6405, 0x6405, // 0x1170 (4464) +0x5BE4, 0x5BC4, 0x5BC4, 0x5BC4, 0x5BE4, 0x6405, 0x63E4, 0x63E4, 0x5BA3, 0x5B83, 0x5382, 0x5362, 0x5362, 0x5342, 0x5321, 0x4B21, // 0x1180 (4480) +0x8CAA, 0x8CCA, 0x8CEA, 0x8D0A, 0x8D0A, 0x8D0A, 0x8D0A, 0x7CAA, 0x9D71, 0xE79C, 0xE7DD, 0xE7BD, 0xE79D, 0xD71B, 0xC6D9, 0xC698, // 0x1190 (4496) +0xBE56, 0xB5F4, 0xADB3, 0x9D51, 0x9510, 0x94EF, 0x94EF, 0x846D, 0x7C2C, 0x7C2B, 0x848D, 0x846C, 0x7C2B, 0x740B, 0x7C0B, 0x6BCA, // 0x11A0 (4512) +0x6BCA, 0x6BCA, 0x6BA9, 0x6368, 0x6368, 0x6BA9, 0x6BC9, 0x6BA9, 0x6BA9, 0x6BCA, 0x6389, 0x6369, 0x6389, 0x6389, 0x6BCA, 0x6BEB, // 0x11B0 (4528) +0x7C4D, 0x7C4D, 0x84AF, 0x9511, 0xA592, 0xADF5, 0xB637, 0xCF3A, 0xDFBB, 0x9DF1, 0x852B, 0x74A7, 0x6446, 0x6405, 0x53A4, 0x5BE5, // 0x11C0 (4544) +0x53C4, 0x5BC4, 0x5BC4, 0x5BC3, 0x5BE4, 0x6405, 0x6405, 0x63E4, 0x5BA3, 0x5BA3, 0x5363, 0x5362, 0x5362, 0x5362, 0x5341, 0x4B00, // 0x11D0 (4560) +0x84AA, 0x84AA, 0x8CCA, 0x8CEA, 0x8D0A, 0x8D0A, 0x84EA, 0x7CAB, 0xBE96, 0xEFDD, 0xE7BD, 0xE79D, 0xD73B, 0xC6B9, 0xBE58, 0xB636, // 0x11E0 (4576) +0xB635, 0xADD3, 0xADD3, 0xA592, 0x94F0, 0x8CAE, 0x94CF, 0x8CCE, 0x7C2C, 0x740B, 0x7C2B, 0x7C2B, 0x7C2C, 0x740B, 0x73EB, 0x6B8A, // 0x11F0 (4592) +0x73EA, 0x73EA, 0x6BAA, 0x6B89, 0x6BA9, 0x6BCA, 0x6BA9, 0x6389, 0x6389, 0x6BA9, 0x6389, 0x6389, 0x6BAA, 0x6BAA, 0x6BEB, 0x740C, // 0x1200 (4608) +0x744D, 0x7C4D, 0x84AF, 0x8CD0, 0x8CF0, 0x9D52, 0xA5D5, 0xCEF9, 0xCF38, 0x850E, 0x74A9, 0x6C67, 0x5BE4, 0x53A4, 0x5384, 0x5364, // 0x1210 (4624) +0x5BC5, 0x5BC4, 0x5BC3, 0x5BE4, 0x63E5, 0x63E5, 0x63C3, 0x63C3, 0x5BA3, 0x5B83, 0x5363, 0x5363, 0x5342, 0x5341, 0x5341, 0x4B21, // 0x1220 (4640) +0x8469, 0x8469, 0x8489, 0x84A9, 0x84CA, 0x8CEA, 0x84EB, 0x954E, 0xD739, 0xE79D, 0xDF5C, 0xD73C, 0xCEDA, 0xBE98, 0xB657, 0xB636, // 0x1230 (4656) +0xADF4, 0x9D51, 0x9531, 0x9510, 0x94F0, 0x8CCF, 0x8CCE, 0x848D, 0x7C2B, 0x6BCA, 0x6BA9, 0x6389, 0x6BCA, 0x73CB, 0x6BAA, 0x6389, // 0x1240 (4672) +0x73EB, 0x6BCA, 0x6BAA, 0x6389, 0x6B89, 0x6BA9, 0x6BA9, 0x6BA9, 0x6369, 0x6B89, 0x6BAA, 0x6BAA, 0x6BCA, 0x6BAA, 0x6BCB, 0x740B, // 0x1250 (4688) +0x73EC, 0x742C, 0x7C6E, 0x848E, 0x84AE, 0x8D10, 0xA5B4, 0xCEF9, 0xCF38, 0x84ED, 0x6C68, 0x6406, 0x5384, 0x5344, 0x5B87, 0x5B67, // 0x1260 (4704) +0x5347, 0x5367, 0x5B67, 0x5B88, 0x63A9, 0x63A9, 0x63A8, 0x63A8, 0x6388, 0x6368, 0x5B48, 0x5B48, 0x5B47, 0x5306, 0x5B27, 0x5B68, // 0x1270 (4720) +0x7408, 0x7C28, 0x7C68, 0x7C68, 0x7C89, 0x84CA, 0x84EC, 0xADF2, 0xDF7B, 0xD73C, 0xD71C, 0xD73C, 0xC6B9, 0xBE78, 0xB636, 0xB615, // 0x1280 (4736) +0xA572, 0x94F0, 0x8CAF, 0x848E, 0x8CAE, 0x8CAF, 0x8CAE, 0x844D, 0x73EB, 0x6BAA, 0x6368, 0x5307, 0x5B48, 0x6BAA, 0x6B8A, 0x6B89, // 0x1290 (4752) +0x6BAA, 0x6BAA, 0x6389, 0x6369, 0x6348, 0x6348, 0x6B89, 0x73CA, 0x6369, 0x6B89, 0x6BAA, 0x6BAA, 0x6BEB, 0x6BAA, 0x6BAB, 0x6BCB, // 0x12A0 (4768) +0x63AA, 0x6BCB, 0x740C, 0x7C2D, 0x7C8E, 0x8D10, 0x9DB4, 0xC6F9, 0xCF38, 0x8D4E, 0x74A9, 0x63E6, 0x5B86, 0x3A83, 0x3223, 0x3A24, // 0x12B0 (4784) +0x4285, 0x4AE6, 0x4AE6, 0x4285, 0x4265, 0x4286, 0x4285, 0x4245, 0x4285, 0x4265, 0x4245, 0x4245, 0x4244, 0x3A03, 0x4225, 0x4266, // 0x12C0 (4800) +}; diff --git a/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/monkey.c b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/monkey.c new file mode 100644 index 0000000..8374cd4 --- /dev/null +++ b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Bitmap_Demo/monkey.c @@ -0,0 +1,314 @@ +// Generated by : ImageConverter 565 v1.2 +// Dimensions : 80x60 pixels +// Size : 9 600 Bytes + +#if defined(__AVR__) + #include +#elif defined(__PIC32MX__) + #define PROGMEM +#elif defined(__arm__) + #define PROGMEM +#endif + +const unsigned short monkey[0x12C0] PROGMEM ={ +0x858A, 0x858A, 0x85AA, 0x85AA, 0x8DAA, 0x8DAA, 0x8DAA, 0x8DAA, 0x8DAA, 0x8DCA, 0x8DCA, 0x8DAA, 0x8DAA, 0x95CA, 0x95CB, 0x8DAA, // 0x0010 (16) +0x8DAA, 0x8DAA, 0x8DAA, 0x95CB, 0x9DEB, 0x9E0B, 0x9DEB, 0x95EA, 0x95EA, 0x95EA, 0x95EA, 0x95EA, 0x95EA, 0x95EA, 0x95EA, 0x95EB, // 0x0020 (32) +0x95EA, 0x9DEA, 0x9E0B, 0xA62B, 0xA60A, 0x9DE9, 0x9DE9, 0x95E9, 0x95C9, 0x95E9, 0x960A, 0xA64B, 0xAE6B, 0xAE4B, 0xAE4B, 0xAE4B, // 0x0030 (48) +0xAE4B, 0xAE2A, 0xAE2A, 0xAE2A, 0xAE2A, 0xAE2A, 0xAE4B, 0xAE4B, 0xAE4B, 0xAE2B, 0xAE4B, 0xAE6B, 0xB66C, 0xB66B, 0xB66A, 0xAE6B, // 0x0040 (64) +0xB66B, 0xAE6B, 0xAE4B, 0xAE4B, 0xA62A, 0xA60A, 0xA62B, 0xAE4B, 0xAE6C, 0xAE6B, 0xAE2B, 0xA60A, 0xA60A, 0xAE4A, 0xAE6B, 0xB66B, // 0x0050 (80) +0x85AA, 0x85AA, 0x85AA, 0x85AA, 0x8DCA, 0x8DCA, 0x8DAA, 0x8DAA, 0x8DAA, 0x8DCA, 0x8DCA, 0x8DAA, 0x8DAA, 0x95CA, 0x95CB, 0x95CB, // 0x0060 (96) +0x95CA, 0x95CA, 0x95CA, 0x95EB, 0x9E0B, 0x9E0B, 0x9DEB, 0x95EA, 0x95CA, 0x95CA, 0x95C9, 0x95C9, 0x95CA, 0x95CA, 0x8DCA, 0x95CA, // 0x0070 (112) +0x95CA, 0x9DEA, 0xA62B, 0xA62B, 0xA60A, 0x9DE9, 0x95C8, 0x95C8, 0x8DA8, 0x95C8, 0x95E9, 0x9E2A, 0xA64B, 0xAE4B, 0xAE2A, 0xAE2A, // 0x0080 (128) +0xAE2A, 0xA60A, 0xAE2A, 0xAE4B, 0xAE4B, 0xAE4B, 0xAE4B, 0xAE6B, 0xAE4B, 0xAE2B, 0xAE4B, 0xAE4B, 0xB66B, 0xAE6B, 0xAE4A, 0xAE4A, // 0x0090 (144) +0xAE4A, 0xAE4A, 0xAE4A, 0xA62A, 0xA5E9, 0xA5EA, 0xA62A, 0xAE4B, 0xAE6C, 0xAE6B, 0xAE4B, 0xA62A, 0xA62A, 0xAE4B, 0xB66B, 0xB66B, // 0x00A0 (160) +0x85AB, 0x85AB, 0x85AA, 0x85AA, 0x85AA, 0x85AA, 0x85AA, 0x8DAA, 0x8DAA, 0x8DCA, 0x8DCA, 0x8DCA, 0x8DCA, 0x95CA, 0x95CA, 0x95EB, // 0x00B0 (176) +0x95EB, 0x95EB, 0x95EB, 0x9E0B, 0x9E0B, 0x9E0B, 0x9DEA, 0x95CA, 0x95EA, 0x95C9, 0x95C9, 0x8DC9, 0x8DC9, 0x8DC9, 0x8DC9, 0x95C9, // 0x00C0 (192) +0x95EA, 0x9DEA, 0xA62A, 0xA62A, 0xA62A, 0x9DE9, 0x9DC8, 0x95C8, 0x95C8, 0x9DE8, 0x9E29, 0xA64A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE2A, // 0x00D0 (208) +0xA60A, 0xA60A, 0xAE2A, 0xAE4B, 0xAE4B, 0xAE6B, 0xB66C, 0xB68C, 0xAE4B, 0xAE4B, 0xAE4B, 0xB64B, 0xB64A, 0xAE4A, 0xAE49, 0xAE4A, // 0x00E0 (224) +0xAE4A, 0xAE4A, 0xAE2A, 0xA60A, 0xA5E9, 0x9DE9, 0xA60A, 0xAE4B, 0xAE6B, 0xAE6B, 0xAE4B, 0xAE2B, 0xAE2A, 0xAE4B, 0xAE4B, 0xB66B, // 0x00F0 (240) +0x85CB, 0x85CB, 0x85CB, 0x85CB, 0x85AA, 0x858A, 0x858A, 0x858A, 0x8DAA, 0x8DCA, 0x8DCA, 0x8DCA, 0x8DCA, 0x8DCA, 0x95CA, 0x95CA, // 0x0100 (256) +0x95EA, 0x960B, 0x9E0B, 0x9E0B, 0x9E0B, 0x95EB, 0x95EA, 0x95CA, 0x95C9, 0x95C9, 0x95C9, 0x8DC9, 0x8DC9, 0x8DC9, 0x95C9, 0x95E9, // 0x0110 (272) +0x9E0A, 0xA60A, 0xA62A, 0xA62A, 0xA62A, 0x9DE9, 0x9DE9, 0x9DE9, 0x9DE8, 0x9E09, 0xA629, 0xAE49, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE2A, // 0x0120 (288) +0xA60A, 0xA60A, 0xA62A, 0xAE4B, 0xAE6B, 0xB66B, 0xB68B, 0xB68B, 0xB66B, 0xB66B, 0xB66B, 0xB66A, 0xB64A, 0xB64A, 0xB649, 0xB66A, // 0x0130 (304) +0xB66A, 0xB66A, 0xAE4A, 0xAE2A, 0xA609, 0xA609, 0xAE2A, 0xAE6B, 0xAE6B, 0xAE6B, 0xAE4B, 0xAE2A, 0xA62A, 0xAE2A, 0xAE4B, 0xAE4B, // 0x0140 (320) +0x8DCB, 0x8DCB, 0x8DCB, 0x8DCB, 0x85AA, 0x858A, 0x8569, 0x8569, 0x85AA, 0x85AA, 0x8DCA, 0x8DCA, 0x8DCA, 0x8DCA, 0x8DCA, 0x95CA, // 0x0150 (336) +0x95EA, 0x9E0A, 0x9E0B, 0x9E0B, 0x9DEB, 0x95EB, 0x95CA, 0x8DA9, 0x8DA9, 0x95A9, 0x95C9, 0x95E9, 0x95E9, 0x95E9, 0x9E0A, 0x9E0A, // 0x0160 (352) +0xA62A, 0xAE2A, 0xAE4B, 0xAE4B, 0xA62A, 0xA60A, 0xA609, 0xA629, 0xA609, 0xA629, 0xAE49, 0xAE49, 0xAE49, 0xAE4A, 0xAE4A, 0xAE4A, // 0x0170 (368) +0xA62A, 0xA60A, 0xA62A, 0xAE4B, 0xAE6B, 0xB68B, 0xB68B, 0xB68B, 0xBE8B, 0xBE8B, 0xB66B, 0xB66B, 0xB66A, 0xB64A, 0xB66A, 0xB66A, // 0x0180 (384) +0xB66A, 0xB66A, 0xB64A, 0xAE4A, 0xAE2A, 0xAE2A, 0xAE4A, 0xAE6B, 0xAE6B, 0xAE4B, 0xAE2A, 0xA60A, 0xA5E9, 0xA60A, 0xAE2A, 0xAE4B, // 0x0190 (400) +0x8DCA, 0x8DCA, 0x8DCA, 0x8DCA, 0x85AA, 0x85AA, 0x858A, 0x858A, 0x85AA, 0x85AA, 0x8DAA, 0x8DCA, 0x8DCA, 0x8DAA, 0x8DC9, 0x95C9, // 0x01A0 (416) +0x95EA, 0x9E0A, 0x9E0B, 0x9E0B, 0x9DEB, 0x95EB, 0x95CA, 0x8DA9, 0x8DA9, 0x95C9, 0x9DEA, 0x9E0A, 0x9E0A, 0x9E0A, 0xA62A, 0xA62A, // 0x01B0 (432) +0xAE4A, 0xAE4A, 0xAE4A, 0xAE4B, 0xAE6B, 0xAE4B, 0xAE4A, 0xAE4A, 0xAE49, 0xAE49, 0xB649, 0xB649, 0xB669, 0xB66A, 0xB66A, 0xAE6A, // 0x01C0 (448) +0xAE2A, 0xA60A, 0xAE2A, 0xAE4A, 0xB66A, 0xB68B, 0xBE8B, 0xBE8B, 0xBE8B, 0xBE8B, 0xB68B, 0xB66B, 0xB66A, 0xB64A, 0xB66A, 0xB66A, // 0x01D0 (464) +0xB66B, 0xB66A, 0xB66A, 0xB66A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE6A, 0xAE4A, 0xAE2A, 0xA609, 0xA609, 0xAE2A, 0xAE4A, 0xAE6B, // 0x01E0 (480) +0x8DCA, 0x8DA9, 0x85A9, 0x85AA, 0x8DAA, 0x85AA, 0x85AA, 0x85AA, 0x85AA, 0x85AA, 0x85AA, 0x8DCA, 0x8DCA, 0x8DC9, 0x8DA9, 0x95C9, // 0x01F0 (496) +0x95E9, 0x9E0A, 0x9E0A, 0x9E0B, 0x9E0A, 0x9DEB, 0x9DEA, 0x95CA, 0x95EA, 0x9DEA, 0x9E0A, 0xA62A, 0xA62A, 0xA62A, 0xA62A, 0xAE4B, // 0x0200 (512) +0xAE4A, 0xAE4A, 0xAE4B, 0xAE4B, 0xAE6B, 0xAE4B, 0xAE4B, 0xAE4B, 0xB66A, 0xB64A, 0xB649, 0xB649, 0xB669, 0xAE4A, 0xAE4A, 0xAE6A, // 0x0210 (528) +0xAE4B, 0xAE4B, 0xAE4A, 0xB66A, 0xB66B, 0xBE8B, 0xBE8B, 0xBE8B, 0xBE8B, 0xBE8B, 0xBE8B, 0xB66B, 0xB66B, 0xB66B, 0xB66B, 0xB66B, // 0x0220 (544) +0xBE8B, 0xB68B, 0xB66B, 0xB66B, 0xB66A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE6A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE6A, 0xB66A, // 0x0230 (560) +0x8DC9, 0x8DA9, 0x8589, 0x8589, 0x85A9, 0x8DAA, 0x8DCA, 0x8DCA, 0x8DAA, 0x85AA, 0x8DAA, 0x8DCA, 0x8DCA, 0x8DC9, 0x8DA9, 0x95C9, // 0x0240 (576) +0x9DE9, 0x9E0A, 0xA62A, 0x9E0A, 0x9E0B, 0x9E0B, 0x9E0B, 0x9E0B, 0x9E0B, 0x9E0B, 0x9E0A, 0x9E0A, 0xA60A, 0xA62A, 0xA62A, 0xAE2A, // 0x0250 (592) +0xAE2A, 0xAE6B, 0xB66B, 0xAE4B, 0x9E0A, 0x9DEA, 0xA62A, 0xAE6B, 0xBEAB, 0xBE8A, 0xB66A, 0xBE6A, 0xB66A, 0xB66A, 0xAE6A, 0xAE6B, // 0x0260 (608) +0xB66B, 0xAE4B, 0xB66A, 0xB68B, 0xB68B, 0xBE8B, 0xBEAB, 0xBEAB, 0xBE8B, 0xBE8B, 0xBE8B, 0xBE8B, 0xB68B, 0xB66B, 0xB66B, 0xB66B, // 0x0270 (624) +0xB68B, 0xB66B, 0xB66A, 0xB66A, 0xB66A, 0xB66A, 0xAE6A, 0xB66A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE6A, 0xAE6A, 0xAE6A, 0xAE6A, 0xAE6A, // 0x0280 (640) +0x85E9, 0x85C8, 0x8589, 0x85A9, 0x8DAA, 0x8DCB, 0x95EB, 0x95EB, 0x95EA, 0x95EA, 0x95EA, 0x95EA, 0x95C9, 0x8DA9, 0x95AA, 0x95CA, // 0x0290 (656) +0x9E0A, 0x9E2A, 0x9E2A, 0xA609, 0xA60A, 0xA62B, 0xAE2C, 0xA60C, 0xA62C, 0x9DEC, 0x9E0B, 0x9E0A, 0x9E2A, 0xA609, 0xA62A, 0xAE2A, // 0x02A0 (672) +0xBE6B, 0xAE0C, 0x7CAA, 0x6C6C, 0x642C, 0x644D, 0x74AF, 0x6C6D, 0x6429, 0x8D8B, 0xBECC, 0xB66A, 0xBE4B, 0xBE4C, 0xB64B, 0xB66C, // 0x02B0 (688) +0xAE4B, 0xAE4B, 0xB68C, 0xB68C, 0xB68B, 0xB68B, 0xBE8B, 0xBEAC, 0xBE8C, 0xBE8C, 0xBE8C, 0xBE8C, 0xB68C, 0xB66C, 0xAE6C, 0xB68C, // 0x02C0 (704) +0xB68C, 0xB68C, 0xB68C, 0xB68C, 0xB68B, 0xB68B, 0xB66B, 0xB66A, 0xB66A, 0xAE4A, 0xAE49, 0xAE4A, 0xAE4A, 0xB66A, 0xB669, 0xAE49, // 0x02D0 (720) +0x85C9, 0x85A9, 0x8589, 0x85AA, 0x8DAB, 0x8DCB, 0x95EB, 0x95EB, 0x960A, 0x960A, 0x960A, 0x9609, 0x95E9, 0x95C9, 0x95C9, 0x95EA, // 0x02E0 (736) +0x960A, 0x9E0A, 0x9E2A, 0xA60A, 0xA62A, 0xA62B, 0xA62C, 0xA62D, 0xA62C, 0xA62C, 0x960B, 0x95EA, 0x9E2B, 0xA62B, 0xA60B, 0xAE4D, // 0x02F0 (752) +0x8D4B, 0x4305, 0x53A9, 0x748E, 0x746E, 0x6C0D, 0x7C8F, 0x9552, 0x7CAE, 0x640A, 0x7CCA, 0xAE8F, 0xAE6D, 0xAE6C, 0xA68B, 0xAE8C, // 0x0300 (768) +0xB68D, 0xB66D, 0xB66D, 0xB66D, 0xB68D, 0xBE8D, 0xBE8D, 0xB68C, 0xBE8D, 0xBE8D, 0xBE8D, 0xB68D, 0xB66C, 0xAE6C, 0xAE6D, 0xB66D, // 0x0310 (784) +0xB68D, 0xB68D, 0xB6AD, 0xB68C, 0xB68C, 0xB68C, 0xB66B, 0xB66B, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4A, // 0x0320 (800) +0x7DAA, 0x7D8A, 0x7D8A, 0x85AB, 0x85AB, 0x8DCC, 0x8DEC, 0x95EC, 0x960B, 0x960A, 0x9E0A, 0x9E2A, 0x9609, 0x95E9, 0x95E9, 0x95EA, // 0x0330 (816) +0x95EB, 0x9E0B, 0x9E0B, 0x9E0B, 0xA62B, 0xA64C, 0xA64D, 0xA64D, 0x9E0C, 0x9E0C, 0x95EB, 0x95EB, 0x9E2C, 0x9E0C, 0xB66F, 0x84CA, // 0x0340 (832) +0x3203, 0x6BAB, 0xAD71, 0xAD50, 0xB530, 0x940B, 0xACED, 0xAD0D, 0xAD2E, 0xBDB0, 0x846B, 0x8CCB, 0xB66E, 0xA64C, 0xAE6D, 0xAE8E, // 0x0350 (848) +0xAE4E, 0xAE6E, 0xB66E, 0xB66E, 0xB64D, 0xB66E, 0xBEAE, 0xBE8E, 0xBE8E, 0xBE8E, 0xB6AE, 0xB68E, 0xAE6E, 0xAE4D, 0xAE6D, 0xAE6D, // 0x0360 (864) +0xB68E, 0xB68E, 0xB68E, 0xB68D, 0xB68D, 0xB68C, 0xB66C, 0xB66B, 0xAE4A, 0xAE2A, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE4B, 0xAE4B, 0xAE4B, // 0x0370 (880) +0x7DAA, 0x7D8A, 0x7D8A, 0x7D8B, 0x85AC, 0x85AC, 0x8DCC, 0x95EC, 0x95EC, 0x960B, 0x960B, 0x960B, 0x960B, 0x95EA, 0x95EA, 0x95EB, // 0x0380 (896) +0x95EC, 0x95EC, 0x9E0C, 0x9E2C, 0xA62C, 0xA62C, 0xA64D, 0x9E4D, 0x9E2D, 0x960C, 0x960C, 0x9E0C, 0x9E0D, 0xA62F, 0x954D, 0x29C0, // 0x0390 (912) +0x7368, 0xB50F, 0x9BE9, 0x9387, 0xA40B, 0xAC2B, 0x9BE8, 0x8345, 0x93A6, 0x8B86, 0xACCC, 0x83C8, 0x9D6C, 0xBE90, 0xBE50, 0xAE0F, // 0x03A0 (928) +0xB66F, 0xAE6F, 0xAE6F, 0xAE8F, 0xAE4E, 0xB66E, 0xB6AF, 0xB66E, 0xB68F, 0xB68F, 0xB6AF, 0xB68E, 0xAE6E, 0xAE6E, 0xA64E, 0xAE4E, // 0x03B0 (944) +0xB66F, 0xB66E, 0xB68E, 0xB68E, 0xB68E, 0xB68D, 0xB66D, 0xB66C, 0xAE4B, 0xAE2B, 0xAE2B, 0xAE4B, 0xAE4B, 0xAE4B, 0xAE4C, 0xAE4C, // 0x03C0 (960) +0x7D8A, 0x7D8B, 0x7DAB, 0x7DAB, 0x85AB, 0x85AC, 0x85CC, 0x8DCD, 0x8DED, 0x95ED, 0x95EC, 0x95EC, 0x95EC, 0x95EC, 0x95CC, 0x95CC, // 0x03D0 (976) +0x95EC, 0x95ED, 0x960D, 0x9E0C, 0x9E0C, 0x9E2D, 0x9E2D, 0x9E2D, 0x960D, 0x960D, 0x95EC, 0x95CC, 0x95CD, 0xAE31, 0x42C5, 0x2980, // 0x03E0 (992) +0x9C6C, 0x93C9, 0x8B87, 0x8347, 0x6AE7, 0x8BED, 0x7B4B, 0x62A9, 0x7308, 0x7B28, 0x6AE7, 0x7BCA, 0x42A5, 0x9D8F, 0xB671, 0xB670, // 0x03F0 (1008) +0xAE8F, 0xAE8F, 0xB68F, 0xAE8E, 0xAE6E, 0xAE6E, 0xB6AF, 0xB6AF, 0xB6AF, 0xB6AF, 0xB68F, 0xAE8F, 0xAE6E, 0xAE4E, 0xA64E, 0xA64E, // 0x0400 (1024) +0xAE4F, 0xAE6F, 0xB66F, 0xB68F, 0xB68E, 0xB68E, 0xB66D, 0xAE6D, 0xAE4C, 0xAE4C, 0xAE4C, 0xAE4C, 0xAE4C, 0xAE4C, 0xAE4C, 0xAE4C, // 0x0410 (1040) +0x7D8A, 0x7DAA, 0x7DAB, 0x7DAB, 0x7DAB, 0x7DAC, 0x85AC, 0x85CD, 0x8DEE, 0x8DEE, 0x8DED, 0x8DED, 0x8DCD, 0x8DCD, 0x8DCD, 0x8DCD, // 0x0420 (1056) +0x8DED, 0x95ED, 0x960D, 0x960D, 0x9E0D, 0x9E0D, 0x9E2D, 0x9E2E, 0x9E4E, 0x9E2E, 0x9E2E, 0x95AD, 0xA5EF, 0x84CC, 0x10E0, 0x5266, // 0x0430 (1072) +0x7B4A, 0x6A67, 0x6A87, 0x6AC7, 0x944E, 0x9470, 0x7BCF, 0x9CB2, 0x734C, 0x62A9, 0x5AA8, 0x7BAB, 0x4246, 0x4265, 0xAE10, 0xB690, // 0x0440 (1088) +0xB66F, 0xAE6F, 0xB68F, 0xAE6F, 0xAE6F, 0xB68F, 0xAE6E, 0xAE6F, 0xB68F, 0xB68F, 0xAE8F, 0xAE6E, 0xAE4E, 0xA64E, 0xAE4E, 0xAE4E, // 0x0450 (1104) +0xAE4E, 0xAE4E, 0xAE6E, 0xAE8F, 0xB68F, 0xB68F, 0xB66E, 0xAE4E, 0xAE4D, 0xAE4D, 0xAE4D, 0xAE4D, 0xA64D, 0xA64D, 0xA64D, 0xA64D, // 0x0460 (1120) +0x7DAA, 0x7DAA, 0x85AB, 0x85AB, 0x7DAB, 0x7DAB, 0x85AC, 0x85CD, 0x8DED, 0x8DED, 0x8DCD, 0x85CD, 0x8DCD, 0x8DCD, 0x8DCC, 0x8DCC, // 0x0470 (1136) +0x95EC, 0x95EC, 0x960C, 0x95ED, 0x95ED, 0x960D, 0x960E, 0x9E0E, 0x9E2F, 0x9E0E, 0x95EE, 0x95AD, 0xADF0, 0x5306, 0x10A0, 0x5AA8, // 0x0480 (1152) +0x7AEA, 0x6207, 0x72EA, 0x9C2F, 0x8BED, 0x942E, 0xA490, 0x8BCE, 0xAD13, 0xB534, 0x83AD, 0x942E, 0x62C9, 0x20A0, 0x5285, 0xAD90, // 0x0490 (1168) +0xBEB3, 0xB672, 0xB671, 0xAE50, 0xAE70, 0xB691, 0xAE4F, 0xB690, 0xAE4F, 0xAE4F, 0xAE6F, 0xAE6F, 0xAE4E, 0xAE4E, 0xAE6E, 0xAE6E, // 0x04A0 (1184) +0xAE4E, 0xAE6E, 0xAE6E, 0xAE6E, 0xB68F, 0xB68F, 0xB68F, 0xAE6E, 0xAE6E, 0xAE4E, 0xAE4E, 0xA64D, 0xA62D, 0xA64D, 0xA66D, 0xA64D, // 0x04B0 (1200) +0x7D8A, 0x85AB, 0x85AB, 0x85AB, 0x7DAB, 0x7DAB, 0x85CC, 0x85ED, 0x8DED, 0x8DED, 0x85CD, 0x85CC, 0x85AC, 0x85CB, 0x8DCB, 0x8DCB, // 0x04C0 (1216) +0x960C, 0x960C, 0x95EC, 0x95ED, 0x95ED, 0x95ED, 0x960E, 0x9E0F, 0x9E2F, 0xA650, 0x9DEE, 0x8D6D, 0x84CC, 0x2160, 0x10A0, 0x5AA7, // 0x04D0 (1232) +0x8BEB, 0x8BCB, 0xA46F, 0xB4F3, 0xAC71, 0xAC71, 0xAC71, 0xB4B3, 0xC598, 0xDE5B, 0xCDF9, 0x9C71, 0x6288, 0x3102, 0x3963, 0x4A26, // 0x04E0 (1248) +0x63AA, 0x84CD, 0xB653, 0xBEB4, 0xB673, 0xA5D0, 0x850C, 0x8D4D, 0xA5EF, 0xA62F, 0xAE6F, 0xAE6F, 0xAE6E, 0xAE6E, 0xAE6E, 0xB68F, // 0x04F0 (1264) +0xAE6E, 0xAE6E, 0xAE6E, 0xAE6E, 0xAE8F, 0xB68F, 0xB68F, 0xB66F, 0xAE6F, 0xAE4E, 0xA64E, 0xA64D, 0xA62D, 0xA64D, 0xA64D, 0xA64D, // 0x0500 (1280) +0x7D69, 0x7D8A, 0x85AB, 0x85AB, 0x85AB, 0x7D8C, 0x85AC, 0x85ED, 0x85ED, 0x85ED, 0x85CC, 0x85AC, 0x85AB, 0x85AB, 0x8DCB, 0x95EC, // 0x0510 (1296) +0x9E2B, 0x9E2B, 0xA64C, 0xA62B, 0x9E2C, 0x9E2C, 0x9E4D, 0xA66E, 0xAE8F, 0xA5EF, 0x94CE, 0x5AA8, 0x628A, 0x28E4, 0x18A1, 0x49E6, // 0x0520 (1312) +0x7B4B, 0x9BCD, 0xC490, 0xCCF2, 0xD553, 0xBCD1, 0x9BCE, 0xA3CE, 0xB410, 0xC4D3, 0xEEDA, 0xD658, 0x72CA, 0x30C3, 0x41A5, 0x5A68, // 0x0530 (1328) +0x5A48, 0x6248, 0x72EB, 0x9410, 0x8C12, 0x7391, 0x6B71, 0x6370, 0x73F1, 0x9D14, 0x9D31, 0xA58E, 0xB66E, 0xB6AD, 0xB6AE, 0xAEAE, // 0x0540 (1344) +0xAE8E, 0xAE6E, 0xAE8D, 0xAE6D, 0xB68F, 0xBE90, 0xB670, 0xB691, 0xB670, 0xAE50, 0xAE4E, 0xA64E, 0xA64D, 0xA64D, 0xA64E, 0xAE4E, // 0x0550 (1360) +0x7549, 0x7D6A, 0x85AB, 0x85AA, 0x85AB, 0x85AB, 0x85CC, 0x8DED, 0x8DED, 0x85CD, 0x85CC, 0x8DEC, 0x85AA, 0x8DCB, 0x960B, 0x960B, // 0x0560 (1376) +0xA64B, 0xAE6C, 0x9DAD, 0x8CEC, 0x7C4C, 0x6BCC, 0x742E, 0x94F2, 0x73ED, 0x52C8, 0x62C8, 0x49E4, 0x4162, 0x3901, 0x2880, 0x4983, // 0x0570 (1392) +0x72E8, 0xB48F, 0xC4D1, 0xD4F2, 0xCCD1, 0xD574, 0xE657, 0xDE17, 0xD5B5, 0xD595, 0xA470, 0xCD95, 0xA450, 0x28A1, 0x4164, 0x49E6, // 0x0580 (1408) +0x3984, 0x3143, 0x4185, 0x5207, 0x732B, 0x6AEA, 0x9450, 0x8C30, 0x8BF0, 0x9C93, 0xA4B4, 0xAD14, 0x94CF, 0x8CCD, 0x9DCE, 0xB6AF, // 0x0590 (1424) +0xB6AF, 0xAE4E, 0xB66E, 0xBEAE, 0xB66E, 0xB66E, 0xBEB0, 0xB690, 0xAE6F, 0xAE6F, 0xAE6E, 0xAE6E, 0xA64D, 0xA64D, 0xAE4E, 0xAE6E, // 0x05A0 (1440) +0x756B, 0x7D8B, 0x85AB, 0x85CA, 0x85AA, 0x85AA, 0x85CC, 0x8DED, 0x8DED, 0x8DCD, 0x8DEC, 0x8DEC, 0x8DCB, 0x8DCA, 0x9E2C, 0xA62D, // 0x05B0 (1456) +0x9DCD, 0x6BE8, 0x6349, 0x632C, 0x6B4F, 0x6B2F, 0x6B2F, 0x6B50, 0x4A2A, 0x2945, 0x3984, 0x5205, 0x5A25, 0x4962, 0x3081, 0x38C2, // 0x05C0 (1472) +0x8B29, 0xBCAF, 0x8AC9, 0x9B6C, 0xF698, 0xB4F2, 0x8C2F, 0x9470, 0xC5D5, 0xDE17, 0x5985, 0x6185, 0xAC50, 0x3902, 0x3943, 0x1060, // 0x05D0 (1488) +0x6348, 0x7BEB, 0x49E7, 0x7B2D, 0x6AAA, 0x93AE, 0x9BEE, 0x9C0E, 0xA450, 0x9C0F, 0x9BEF, 0xBD14, 0xACD3, 0x8BEF, 0x5AE9, 0x7C4B, // 0x05E0 (1504) +0xB630, 0xBE90, 0xB66E, 0xBE8E, 0xB68E, 0xB68E, 0xB68E, 0xB66E, 0xAE6E, 0xAE6E, 0xAE6E, 0xAE6D, 0xAE6D, 0xA64D, 0xAE4E, 0xAE6E, // 0x05F0 (1520) +0x7D8C, 0x7D8B, 0x7DAB, 0x85AA, 0x85AA, 0x85AA, 0x8DCC, 0x8DCC, 0x8DEC, 0x95EC, 0x8DCB, 0x8DAB, 0x9E0D, 0xA62F, 0x8D4D, 0x744B, // 0x0600 (1536) +0x6BAC, 0x632C, 0x73AE, 0x8C11, 0x83F0, 0x83D0, 0x6B2E, 0x736F, 0x736F, 0x4A29, 0x39A6, 0x20E2, 0x3963, 0x49C5, 0x30E3, 0x30C2, // 0x0610 (1552) +0x938B, 0xA3ED, 0x50E2, 0xCCD2, 0xBCF3, 0x9C10, 0xB514, 0xCDF7, 0xE6BA, 0xCDD6, 0x30A2, 0x6207, 0xB4D2, 0x28A1, 0x4144, 0x3122, // 0x0620 (1568) +0x6B69, 0x52A7, 0x5269, 0x51E9, 0x72AC, 0x93B0, 0x8B2E, 0x9BCF, 0xAC50, 0x7AE9, 0x8328, 0xC510, 0xB4AF, 0x9BEE, 0x72EB, 0x6ACA, // 0x0630 (1584) +0x7BEA, 0xADCF, 0xBE70, 0xBE8F, 0xBECF, 0xB66D, 0xB6AE, 0xB68E, 0xAE6E, 0xAE6D, 0xAE6D, 0xAE6D, 0xA64D, 0xA64D, 0xA64E, 0xAE4E, // 0x0640 (1600) +0x7D8B, 0x7D8B, 0x7D8B, 0x7D8B, 0x7D8A, 0x85AB, 0x8DCB, 0x95EC, 0x8DEB, 0x960C, 0x9E0C, 0x9E0D, 0x8D2D, 0x742B, 0x52E9, 0x6B4C, // 0x0650 (1616) +0x734D, 0x940F, 0x9C4F, 0x7B4B, 0x7B6C, 0x8BCF, 0x8BF1, 0x62AC, 0x7B90, 0x62AC, 0x4A29, 0x3165, 0x20E2, 0x3164, 0x28E1, 0x1820, // 0x0660 (1632) +0x7A88, 0xB40F, 0x6145, 0x7269, 0xDEB9, 0xF7DE, 0xE6DB, 0xCDB7, 0xDDF9, 0xEE5A, 0x726A, 0xCD56, 0xAC92, 0x28A1, 0x3964, 0x6B2B, // 0x0670 (1648) +0x6B6B, 0x10A1, 0x4A06, 0x3924, 0x72CB, 0x7AEC, 0x6AAB, 0x8B8E, 0x9C50, 0x2881, 0x3921, 0x7B08, 0x9BEA, 0xAC2C, 0x936B, 0x72A8, // 0x0680 (1664) +0x6B29, 0x7C0A, 0xC672, 0xC670, 0xBE8F, 0xB68E, 0xAE6D, 0xAE6E, 0xAE6D, 0xA64D, 0xA62D, 0xA62D, 0x9E2C, 0xA62D, 0x9E2E, 0xA62E, // 0x0690 (1680) +0x7D8B, 0x7D8B, 0x7D6B, 0x7D6B, 0x7D8B, 0x85AB, 0x8DEB, 0x8DEB, 0x9E2C, 0x9DEC, 0x9DEE, 0x8D0C, 0x6B89, 0x5AA8, 0x62CB, 0x72EC, // 0x06A0 (1696) +0x93AD, 0xB490, 0xB4CF, 0x6266, 0x49A4, 0x7B2C, 0xA472, 0x832D, 0x5A08, 0x93EF, 0x6ACA, 0x28C2, 0x20C2, 0x28E3, 0x20A1, 0x1860, // 0x06B0 (1712) +0x30E2, 0xAC71, 0xA38E, 0x7A89, 0xC554, 0xCDD6, 0xBCD3, 0xAC11, 0xB473, 0xDDF9, 0xEF1C, 0xE6DB, 0x732C, 0x28E1, 0x2922, 0x948E, // 0x06C0 (1728) +0x8C8E, 0x10C0, 0x3983, 0x49A4, 0x72CA, 0x59E7, 0x6AEA, 0x942F, 0x5228, 0x0800, 0x1820, 0x30C1, 0x8329, 0xB46D, 0xB46E, 0x82C9, // 0x06D0 (1744) +0x5A46, 0x62E8, 0x840A, 0xBE31, 0xBE70, 0xB68F, 0xB6AF, 0xAE8E, 0xAE6E, 0xA62D, 0x9E0C, 0x9DEC, 0x9DEC, 0x9E0D, 0x9E0D, 0x9E0E, // 0x06E0 (1760) +0x7DAB, 0x7D8B, 0x7D8B, 0x7D8C, 0x7DAC, 0x85CC, 0x8DEB, 0x8DEC, 0x95EC, 0x9DEE, 0x7C8B, 0x73AA, 0x736B, 0x62A9, 0x7B2B, 0x9BCD, // 0x06F0 (1776) +0xAC0E, 0x8309, 0x51A4, 0x2080, 0x2902, 0x8C0E, 0x83AC, 0x7B0A, 0x4143, 0x7B2A, 0x730A, 0x28A1, 0x2081, 0x20C2, 0x1061, 0x1861, // 0x0700 (1792) +0x1840, 0x51C6, 0xB470, 0xB44F, 0xBCD0, 0xBCF1, 0xBD12, 0xAC2F, 0xABF0, 0xCCF5, 0xDDF8, 0xC5B6, 0x4A26, 0x2982, 0x1980, 0x8D0D, // 0x0710 (1808) +0xB632, 0x29A1, 0x3141, 0x3922, 0x6227, 0x59E6, 0x6AA8, 0xA4B0, 0x4A06, 0x1020, 0x2081, 0x1840, 0x51E4, 0x832A, 0x938B, 0x7A88, // 0x0720 (1824) +0x4144, 0x5206, 0x4A24, 0x9D0D, 0xBE90, 0xB66F, 0xAE4E, 0xAE8E, 0xAE6E, 0xA62D, 0x9E0C, 0x9DEC, 0x9DEC, 0x9E0D, 0x960D, 0x960D, // 0x0730 (1840) +0x7D8B, 0x7D8B, 0x7D8B, 0x7D8C, 0x85CC, 0x85EC, 0x8E0B, 0x8E0C, 0x95EE, 0x850D, 0x5328, 0x7BAD, 0x62C9, 0x832B, 0xAC4D, 0xA42C, // 0x0740 (1856) +0x7AC7, 0x30C0, 0x1020, 0x0860, 0x29A4, 0x740D, 0x73AB, 0x62E8, 0x3102, 0x834C, 0x6A89, 0x20A1, 0x20C1, 0x2963, 0x0880, 0x0880, // 0x0750 (1872) +0x18C2, 0x18A1, 0x6A67, 0xC48F, 0xBC2D, 0xCCAF, 0xC4F0, 0xAC4E, 0x9BCE, 0xBC92, 0xDE18, 0x940F, 0x2942, 0x6BC9, 0x748A, 0x95AE, // 0x0760 (1888) +0xC6F5, 0x4AC7, 0x3143, 0x3923, 0x72A8, 0x7287, 0x6226, 0x8B8C, 0x72EA, 0x3944, 0x3122, 0x2080, 0x2080, 0x4963, 0x6226, 0x6226, // 0x0770 (1904) +0x51A6, 0x49A5, 0x39A2, 0x6B67, 0xC691, 0xB68F, 0xAE6E, 0xAE6E, 0xAE6E, 0xA62D, 0xA60C, 0x9E0C, 0x9E0C, 0x9E2C, 0x9E2C, 0x962C, // 0x0780 (1920) +0x7D8C, 0x7D8C, 0x75AA, 0x7DCB, 0x7DEB, 0x85EC, 0x8DED, 0x95CD, 0x9DAF, 0x6BA9, 0x4A44, 0x5205, 0x51C5, 0x82EA, 0xAC2E, 0x9BAC, // 0x0790 (1936) +0x49C5, 0x1020, 0x3081, 0x38A1, 0x38A1, 0x59C6, 0x836C, 0x6288, 0x3942, 0x8BAC, 0x49A7, 0x2061, 0x3142, 0x39A4, 0x18A0, 0x1080, // 0x07A0 (1952) +0x10A0, 0x1902, 0x2102, 0x6B2A, 0xA4B0, 0xBD12, 0xBCB1, 0xAC2F, 0xAC2F, 0xCD54, 0xA470, 0x41C5, 0x2141, 0x5305, 0x854B, 0xAE4F, // 0x07B0 (1968) +0xBE52, 0x6B89, 0x3982, 0x3983, 0x49E7, 0x6ACA, 0x3963, 0x5244, 0xAD6E, 0xB630, 0x8D6C, 0x9D6E, 0x5264, 0x5A24, 0x82E7, 0x7245, // 0x07C0 (1984) +0x61E5, 0x51A5, 0x3963, 0x5286, 0xB60F, 0xB68F, 0xAE6F, 0xAE6E, 0xA64D, 0xA64C, 0xA62C, 0xA62C, 0xA62C, 0xA62C, 0xA62D, 0x9E0D, // 0x07D0 (2000) +0x7D8B, 0x7D8B, 0x7DAB, 0x85CB, 0x85AB, 0x85CC, 0x8DCC, 0x95CD, 0x8D2D, 0x3203, 0x39C3, 0x3983, 0x49A4, 0x6226, 0x5183, 0x4142, // 0x07E0 (2016) +0x1880, 0x2100, 0x39C2, 0x6326, 0x844A, 0x8C4B, 0x736A, 0x5206, 0x51C5, 0x93AD, 0x4964, 0x28C1, 0x3182, 0x4A45, 0x3184, 0x18A1, // 0x07F0 (2032) +0x1840, 0x3103, 0x3102, 0x3102, 0x49E6, 0x730B, 0x940F, 0xACD2, 0xACF3, 0x7B6D, 0x49E6, 0x20C1, 0x18C0, 0x2142, 0x31C3, 0x4225, // 0x0800 (2048) +0x18E0, 0x20C0, 0x3962, 0x41A3, 0x3141, 0x4A05, 0x41C4, 0x6B08, 0xA56E, 0xB64F, 0xAE70, 0xBE91, 0x8C6A, 0x6285, 0x8B49, 0x7AA8, // 0x0810 (2064) +0x7267, 0x51C5, 0x4184, 0x3982, 0x9D2C, 0xBE8F, 0xAE4E, 0xAE6E, 0xA64D, 0xA62C, 0xA62B, 0xA60B, 0xA60B, 0xA62C, 0xA62C, 0xA62D, // 0x0820 (2080) +0x856B, 0x858B, 0x8DCB, 0x85CB, 0x85AB, 0x85CB, 0x8DAB, 0x95CE, 0x744B, 0x29C2, 0x2962, 0x3142, 0x3943, 0x5206, 0x30C0, 0x20A0, // 0x0830 (2096) +0x5B26, 0x7C89, 0x8D4A, 0xAE4D, 0xAE8D, 0x958B, 0x52E5, 0x4A05, 0x8BAD, 0x836C, 0x28C0, 0x3121, 0x4A45, 0x4225, 0x2923, 0x20A1, // 0x0840 (2112) +0x2860, 0x4122, 0x6225, 0x51C4, 0x4183, 0x3942, 0x3964, 0x5A89, 0x4A07, 0x41E6, 0x3163, 0x18A0, 0x18A0, 0x1860, 0x1000, 0x0800, // 0x0850 (2128) +0x28C3, 0x2081, 0x28E1, 0x3121, 0x3121, 0x5245, 0x62E7, 0x7BC9, 0xB60F, 0xAE2E, 0x9E0C, 0xAE4E, 0x94EB, 0x62C5, 0x7AE8, 0x7AC8, // 0x0860 (2144) +0x7267, 0x51A5, 0x4184, 0x3141, 0x6346, 0xBE70, 0xB66F, 0xAE4D, 0xAE4C, 0xA62B, 0xA62B, 0xA60B, 0xA62B, 0xA62B, 0xA62C, 0xA64C, // 0x0870 (2160) +0x8D8A, 0x858A, 0x8DAA, 0x85AA, 0x85AA, 0x85AB, 0x858B, 0x9DCE, 0x6BE9, 0x2982, 0x2942, 0x3963, 0x49C5, 0x49A5, 0x3922, 0x3181, // 0x0880 (2176) +0x8D6C, 0x9E4C, 0x9E4B, 0xA62A, 0x9E09, 0xA5CB, 0x9D4D, 0x6B49, 0x6AE9, 0x3963, 0x2101, 0x2963, 0x18C0, 0x18C1, 0x3102, 0x30C1, // 0x0890 (2192) +0x4141, 0x4982, 0x6A85, 0x7AE7, 0x8327, 0x8B69, 0x7266, 0x6225, 0x6226, 0x5A05, 0x4183, 0x28C0, 0x1880, 0x1040, 0x1881, 0x3124, // 0x08A0 (2208) +0x49C6, 0x49C5, 0x49A4, 0x3923, 0x3102, 0x28E0, 0x7388, 0xB5EF, 0xB64E, 0xAE4C, 0xAE6C, 0xAE4D, 0x94EB, 0x5264, 0x7B08, 0x7AA8, // 0x08B0 (2224) +0x6A67, 0x51C5, 0x4184, 0x3142, 0x3180, 0x9D4D, 0xBE8F, 0xAE4D, 0xAE6C, 0xAE4C, 0xA62B, 0xA60A, 0xA60A, 0xA62A, 0xA62B, 0xA62B, // 0x08C0 (2240) +0x85AA, 0x85AA, 0x7DAA, 0x7D8A, 0x7DAA, 0x85AB, 0x858B, 0x95AE, 0x4AC6, 0x20E1, 0x3122, 0x3943, 0x5A06, 0x49A5, 0x3922, 0x4203, // 0x08D0 (2256) +0x856A, 0x8DE9, 0x95E8, 0xA609, 0xADE9, 0xB62D, 0x94EC, 0x2982, 0x18C1, 0x20A1, 0x28E1, 0x1880, 0x0820, 0x1040, 0x20C1, 0x3962, // 0x08E0 (2272) +0x51C4, 0x51E3, 0x72A6, 0x7AA6, 0x82C6, 0xABCA, 0xABC9, 0x9327, 0x7A86, 0x6A25, 0x59C5, 0x3902, 0x2080, 0x20A1, 0x3963, 0x49E4, // 0x08F0 (2288) +0x49A4, 0x5206, 0x5A26, 0x51E6, 0x4143, 0x28E1, 0x20C0, 0x6B66, 0xBE8D, 0xB66B, 0xAE4B, 0xB68D, 0x9D4B, 0x4A62, 0x72E8, 0x72A8, // 0x0900 (2304) +0x6226, 0x5A06, 0x49C5, 0x3942, 0x2940, 0x6BA7, 0xBE4F, 0xAE2C, 0xAE4C, 0xA62B, 0xA62B, 0x9E0A, 0x9E0A, 0x9E0A, 0xA62A, 0xA62B, // 0x0910 (2320) +0x85A9, 0x85CA, 0x7D8A, 0x7569, 0x7D8A, 0x7D8A, 0x8DAC, 0x850B, 0x2161, 0x20E2, 0x3123, 0x4144, 0x59E5, 0x59E5, 0x4143, 0x4A24, // 0x0920 (2336) +0x954B, 0x9DEA, 0xAE29, 0xB64A, 0xB64C, 0x7C68, 0x1100, 0x18C1, 0x28E3, 0x30C2, 0x30A0, 0x38C1, 0x28C2, 0x20A1, 0x18A0, 0x2922, // 0x0930 (2352) +0x4964, 0x5184, 0x7AA8, 0x8B09, 0x82A7, 0x8AC7, 0x9B68, 0xA389, 0x82E7, 0x6A47, 0x59E6, 0x4124, 0x30A2, 0x28A2, 0x49A4, 0x72C9, // 0x0940 (2368) +0x72C9, 0x5A06, 0x5205, 0x5204, 0x51C5, 0x4143, 0x28E1, 0x1080, 0x5B25, 0xC6AF, 0xB68D, 0xB66C, 0xADCC, 0x5283, 0x6AA7, 0x6A68, // 0x0950 (2384) +0x6206, 0x5A06, 0x51C5, 0x4184, 0x3962, 0x4A43, 0xADCD, 0xB62C, 0xAE2B, 0xA60B, 0x9E0B, 0x9E0A, 0x9E0A, 0x9E0A, 0xA60A, 0x9E0A, // 0x0960 (2400) +0x85A9, 0x85AA, 0x7D6A, 0x756A, 0x7D8A, 0x858A, 0x95EC, 0x63A6, 0x10C0, 0x28E2, 0x3923, 0x49A5, 0x6246, 0x4183, 0x3962, 0x4A24, // 0x0970 (2416) +0x954B, 0xA5EA, 0xA609, 0xBE6C, 0x7C88, 0x10E0, 0x18E0, 0x3123, 0x4144, 0x4124, 0x4943, 0x4963, 0x3102, 0x2081, 0x20C1, 0x30E2, // 0x0980 (2432) +0x4143, 0x5184, 0x6A26, 0x8AC9, 0x9B6A, 0xA38A, 0x9B6A, 0x9B6A, 0x936A, 0x7AC9, 0x6227, 0x4985, 0x4164, 0x3903, 0x3903, 0x4985, // 0x0990 (2448) +0x6249, 0x6A89, 0x5A45, 0x49A3, 0x51C5, 0x4964, 0x3923, 0x28E1, 0x1060, 0x6327, 0xBE4F, 0xC690, 0x950C, 0x4202, 0x6266, 0x72A8, // 0x09A0 (2464) +0x6A47, 0x6226, 0x59E6, 0x5206, 0x41A5, 0x39C2, 0x94CA, 0xB64D, 0xA60B, 0xA60B, 0x9E0B, 0x9E0A, 0x9E0A, 0x9E0A, 0x9E0A, 0x9DEA, // 0x09B0 (2480) +0x85A9, 0x7D69, 0x7D49, 0x7D6A, 0x7D8B, 0x858B, 0x95CC, 0x3A61, 0x10C0, 0x2903, 0x28A1, 0x51A5, 0x5205, 0x4182, 0x3121, 0x52A5, // 0x09C0 (2496) +0x9DCC, 0x9E0A, 0xAE8B, 0x8D29, 0x1920, 0x20E0, 0x28E1, 0x3943, 0x4963, 0x4984, 0x49C5, 0x3963, 0x3964, 0x28C2, 0x3901, 0x4942, // 0x09D0 (2512) +0x4142, 0x6245, 0x6A65, 0x7AA6, 0x9369, 0xAC0C, 0x9B6A, 0xA3AB, 0x938B, 0x7AE8, 0x6A86, 0x51E4, 0x49C4, 0x51E5, 0x51E7, 0x51A6, // 0x09E0 (2528) +0x51A6, 0x6228, 0x6AC9, 0x5A46, 0x51A4, 0x4923, 0x4145, 0x3924, 0x2901, 0x2100, 0x39C2, 0x8C6C, 0x73C9, 0x2120, 0x5203, 0x5A04, // 0x09F0 (2544) +0x6A66, 0x6A88, 0x6A88, 0x6A89, 0x6289, 0x41C3, 0x6BA5, 0xAE0C, 0xA5EB, 0x9DEB, 0x9DEB, 0x9E0A, 0x9E0A, 0x9E0A, 0x9DEA, 0x9DEA, // 0x0A00 (2560) +0x7588, 0x7D68, 0x8569, 0x8569, 0x85A8, 0x95CB, 0x8CAB, 0x2120, 0x2101, 0x20C0, 0x3923, 0x5A06, 0x59E6, 0x49C4, 0x3101, 0x4A43, // 0x0A10 (2576) +0x9DCC, 0xA64D, 0x9D8E, 0x2961, 0x18A0, 0x28E1, 0x3922, 0x49C5, 0x4984, 0x51E6, 0x4963, 0x4122, 0x4122, 0x3901, 0x49A4, 0x4143, // 0x0A20 (2592) +0x4983, 0x59E5, 0x72A8, 0x7287, 0x8309, 0x938B, 0x8B4A, 0x8B2A, 0x8329, 0x7AC9, 0x72C9, 0x6A67, 0x51A5, 0x5A06, 0x6AC9, 0x6AC9, // 0x0A30 (2608) +0x6AC9, 0x6AA9, 0x7AEA, 0x72EA, 0x3943, 0x3943, 0x3943, 0x4184, 0x4984, 0x4985, 0x28E3, 0x2923, 0x39C5, 0x1880, 0x49C4, 0x6205, // 0x0A40 (2624) +0x72A8, 0x830A, 0x72C9, 0x6226, 0x5205, 0x5226, 0x4A04, 0xA52E, 0x9E0C, 0x95EA, 0x960A, 0x9E0A, 0x9E09, 0x9E0A, 0x9DE9, 0x9DC9, // 0x0A50 (2640) +0x6D48, 0x7549, 0x7D49, 0x8569, 0x8589, 0x95CC, 0x7409, 0x18A0, 0x20E0, 0x28E1, 0x49A5, 0x5A07, 0x51C5, 0x51C5, 0x3963, 0x4203, // 0x0A60 (2656) +0x9DCD, 0xA62F, 0x42A4, 0x0840, 0x2902, 0x28C1, 0x49C5, 0x49C5, 0x49C5, 0x51C5, 0x4143, 0x51A4, 0x51A4, 0x51A4, 0x5A05, 0x51A4, // 0x0A70 (2672) +0x4163, 0x51A4, 0x6A87, 0x72A8, 0x832A, 0x8309, 0x72A8, 0x7AC8, 0x7AC8, 0x7AC9, 0x6A88, 0x6A68, 0x51E6, 0x5A27, 0x6AA9, 0x6AA9, // 0x0A80 (2688) +0x7B0A, 0x832B, 0x834C, 0x6A68, 0x3102, 0x3943, 0x4184, 0x51E5, 0x51E5, 0x49A5, 0x3964, 0x3123, 0x18A1, 0x1020, 0x3922, 0x6226, // 0x0A90 (2704) +0x7288, 0x7AC9, 0x72A8, 0x6247, 0x5205, 0x5205, 0x49C4, 0x7BEA, 0x9DEC, 0x95CA, 0x8DC9, 0x95E9, 0x9E09, 0x9E0A, 0x9DE9, 0x95C9, // 0x0AA0 (2720) +0x6508, 0x6D49, 0x7529, 0x858B, 0x85AA, 0x95ED, 0x5B27, 0x18A0, 0x2901, 0x3123, 0x4164, 0x4965, 0x49A5, 0x51C5, 0x3963, 0x4224, // 0x0AB0 (2736) +0xADF0, 0x748A, 0x0080, 0x18A0, 0x2081, 0x3123, 0x4184, 0x49A4, 0x4984, 0x4184, 0x4984, 0x6206, 0x6226, 0x7287, 0x6A67, 0x6226, // 0x0AC0 (2752) +0x4963, 0x4983, 0x5A06, 0x6A88, 0x832A, 0x72A8, 0x5A06, 0x6226, 0x830A, 0x7B0A, 0x6A88, 0x6268, 0x5A47, 0x6247, 0x6268, 0x6268, // 0x0AD0 (2768) +0x834B, 0x93CD, 0x9C0E, 0x51C5, 0x3923, 0x4984, 0x5206, 0x6247, 0x72A8, 0x72A9, 0x49A5, 0x3964, 0x20C2, 0x1860, 0x30E1, 0x59E5, // 0x0AE0 (2784) +0x6226, 0x6A68, 0x6AA8, 0x6267, 0x5A46, 0x5205, 0x49E4, 0x6B68, 0x9DCC, 0x8DCA, 0x8D88, 0x8DA9, 0x95E9, 0x95E9, 0x95C9, 0x95A9, // 0x0AF0 (2800) +0x5CE8, 0x6509, 0x6D2A, 0x7D8C, 0x7DAB, 0x8DAD, 0x4264, 0x2101, 0x28E1, 0x3943, 0x4185, 0x51C6, 0x6247, 0x5A06, 0x3943, 0x3983, // 0x0B00 (2816) +0x73EB, 0x1920, 0x10A0, 0x2923, 0x3123, 0x3102, 0x3102, 0x3122, 0x28C1, 0x3943, 0x5A06, 0x6226, 0x72A7, 0x8309, 0x6A67, 0x6A47, // 0x0B10 (2832) +0x51C4, 0x51A4, 0x59E6, 0x6AA8, 0x834B, 0x72C9, 0x51C5, 0x51C5, 0x72CA, 0x6A88, 0x6247, 0x5A27, 0x6248, 0x6248, 0x5A27, 0x6248, // 0x0B20 (2848) +0x832A, 0x9C0E, 0x9C2F, 0x30E2, 0x4184, 0x51C5, 0x5A26, 0x6A67, 0x7AEA, 0x7AEA, 0x6A89, 0x49C6, 0x3944, 0x20A1, 0x2060, 0x51C5, // 0x0B30 (2864) +0x51C4, 0x6206, 0x5A26, 0x59E6, 0x5A47, 0x5A47, 0x5A46, 0x5AC6, 0x956B, 0x8DAA, 0x8D69, 0x8D68, 0x8D88, 0x8DA9, 0x8D89, 0x8D89, // 0x0B40 (2880) +0x5D09, 0x6509, 0x6D2B, 0x756C, 0x758B, 0x7D0B, 0x31C3, 0x3122, 0x3102, 0x3923, 0x49C5, 0x51C5, 0x49C5, 0x51C5, 0x4984, 0x3102, // 0x0B50 (2896) +0x18E0, 0x0040, 0x20C2, 0x3944, 0x4164, 0x3102, 0x28E1, 0x3122, 0x20A1, 0x2080, 0x51E5, 0x7AE9, 0x7AE8, 0x8B49, 0x8309, 0x59E5, // 0x0B60 (2912) +0x51A4, 0x49A4, 0x51E6, 0x6A88, 0x72EA, 0x6268, 0x4144, 0x4985, 0x6268, 0x51E6, 0x5A27, 0x5207, 0x6248, 0x6247, 0x5A27, 0x6A68, // 0x0B70 (2928) +0x832B, 0xA44F, 0x6AC9, 0x1860, 0x4184, 0x5A06, 0x6226, 0x6A67, 0x7AC8, 0x7AE9, 0x7B0A, 0x6248, 0x4164, 0x2081, 0x2080, 0x49C4, // 0x0B80 (2944) +0x51C5, 0x6206, 0x5A26, 0x51A4, 0x51C5, 0x5A47, 0x6287, 0x4203, 0x7CA9, 0x8DAA, 0x8D69, 0x8549, 0x8548, 0x8568, 0x8D69, 0x8D69, // 0x0B90 (2960) +0x5D08, 0x6509, 0x6D4B, 0x6D4B, 0x758B, 0x6CAA, 0x2961, 0x3143, 0x3103, 0x4164, 0x49C5, 0x51E5, 0x51E5, 0x5206, 0x49A5, 0x30E2, // 0x0BA0 (2976) +0x0820, 0x18A1, 0x3124, 0x4165, 0x3963, 0x3102, 0x4184, 0x3123, 0x20A1, 0x28C2, 0x3102, 0x7AE9, 0x9BEB, 0x9BCB, 0x938B, 0x6A46, // 0x0BB0 (2992) +0x51A4, 0x49A4, 0x5A06, 0x6A88, 0x72EA, 0x6268, 0x3944, 0x4185, 0x6AAA, 0x5207, 0x5A27, 0x5A27, 0x6A89, 0x6A88, 0x6247, 0x72A9, // 0x0BC0 (3008) +0x8B8C, 0x9BED, 0x2902, 0x1040, 0x2902, 0x51E6, 0x6246, 0x6246, 0x7287, 0x8329, 0x72C9, 0x6A68, 0x49A5, 0x28A1, 0x28A1, 0x49E5, // 0x0BD0 (3024) +0x6226, 0x5A05, 0x6246, 0x59E6, 0x4984, 0x51E6, 0x6288, 0x41E3, 0x6C07, 0x8D6A, 0x8549, 0x8528, 0x7D28, 0x8528, 0x8549, 0x8549, // 0x0BE0 (3040) +0x5D08, 0x6509, 0x6D4A, 0x6D4B, 0x758B, 0x6469, 0x2141, 0x3122, 0x3923, 0x4164, 0x4184, 0x49C4, 0x5206, 0x5206, 0x4164, 0x3103, // 0x0BF0 (3056) +0x1860, 0x28C2, 0x4185, 0x51C5, 0x4142, 0x4142, 0x5206, 0x3143, 0x28E2, 0x28C2, 0x1840, 0x6226, 0x9BEC, 0xA3EB, 0xA3EC, 0x7AA8, // 0x0C00 (3072) +0x51A4, 0x51A5, 0x6A88, 0x6A68, 0x6AC9, 0x6268, 0x4164, 0x3964, 0x6AAA, 0x6268, 0x5A27, 0x6268, 0x72C9, 0x72A9, 0x6A68, 0x832A, // 0x0C10 (3088) +0x93AC, 0x6AA8, 0x0800, 0x1060, 0x1860, 0x3943, 0x59E6, 0x59C4, 0x6226, 0x7AC8, 0x7AE9, 0x6247, 0x51C5, 0x3923, 0x1840, 0x5206, // 0x0C20 (3104) +0x6A87, 0x6226, 0x6226, 0x5A06, 0x49A5, 0x51C5, 0x5A47, 0x41E3, 0x6BE7, 0x8D4A, 0x8509, 0x8508, 0x7D08, 0x7D08, 0x8528, 0x7D28, // 0x0C30 (3120) +0x6548, 0x6D49, 0x6D6A, 0x6D6B, 0x758B, 0x6469, 0x2961, 0x3922, 0x4143, 0x4984, 0x49A4, 0x51E5, 0x49E5, 0x49C5, 0x4964, 0x3903, // 0x0C40 (3136) +0x2061, 0x3944, 0x49A5, 0x51A5, 0x4163, 0x49A4, 0x49E5, 0x4185, 0x28E3, 0x20C2, 0x1820, 0x3921, 0x8B49, 0x9BCB, 0xA40C, 0x7AA7, // 0x0C50 (3152) +0x51C4, 0x6226, 0x834B, 0x6A88, 0x6AA9, 0x6248, 0x4185, 0x3964, 0x5A68, 0x6AAA, 0x6268, 0x72C9, 0x72E9, 0x6A88, 0x6A67, 0x8B6B, // 0x0C60 (3168) +0x93AD, 0x4163, 0x0840, 0x1080, 0x1040, 0x28C1, 0x51A5, 0x5183, 0x59E4, 0x6A66, 0x72C8, 0x6A67, 0x59E6, 0x4143, 0x20A0, 0x49C4, // 0x0C70 (3184) +0x6A87, 0x72C9, 0x6AA8, 0x59E6, 0x49A5, 0x51C5, 0x51E6, 0x49E4, 0x7428, 0x958B, 0x8509, 0x8509, 0x7D28, 0x7D28, 0x8529, 0x7D28, // 0x0C80 (3200) +0x6D69, 0x7569, 0x7569, 0x7D69, 0x7DAA, 0x6C68, 0x2141, 0x3944, 0x4184, 0x49C5, 0x4984, 0x4984, 0x51C5, 0x51E6, 0x49A4, 0x3963, // 0x0C90 (3216) +0x20A1, 0x28E2, 0x49A5, 0x4964, 0x4964, 0x5A06, 0x49A5, 0x3964, 0x2102, 0x1080, 0x1060, 0x1860, 0x6267, 0x93EC, 0x938A, 0x7286, // 0x0CA0 (3232) +0x59E4, 0x7AA8, 0x832A, 0x72A9, 0x832B, 0x6228, 0x4185, 0x4164, 0x5A48, 0x6AAA, 0x6A88, 0x7AEA, 0x7B0A, 0x8B6B, 0x938B, 0xA40E, // 0x0CB0 (3248) +0x8B6C, 0x30C2, 0x1860, 0x20C1, 0x1080, 0x1080, 0x41C2, 0x5A44, 0x51A4, 0x59A5, 0x6206, 0x5A06, 0x51C4, 0x4963, 0x30C1, 0x6226, // 0x0CC0 (3264) +0x7AC9, 0x7AE9, 0x6A68, 0x51C5, 0x4984, 0x51C5, 0x51E5, 0x41E3, 0x6BC6, 0x956A, 0x854A, 0x8529, 0x8528, 0x7D28, 0x8548, 0x7D48, // 0x0CD0 (3280) +0x7569, 0x7D8A, 0x7D89, 0x7D69, 0x85AA, 0x6C68, 0x2961, 0x3984, 0x4184, 0x4164, 0x3942, 0x4984, 0x51E5, 0x51E5, 0x49C5, 0x49C5, // 0x0CE0 (3296) +0x28E2, 0x28E2, 0x4164, 0x4964, 0x59E6, 0x51C5, 0x3963, 0x2902, 0x18C1, 0x1060, 0x1040, 0x1040, 0x4163, 0x836A, 0x8B6A, 0x7AC8, // 0x0CF0 (3312) +0x9BEC, 0xB490, 0x834A, 0x832B, 0x8B8C, 0x6248, 0x49A5, 0x4164, 0x5207, 0x6AA9, 0x7B2B, 0x72C9, 0x7B0A, 0xBCD1, 0xC552, 0xB48F, // 0x0D00 (3328) +0x8B8C, 0x30E1, 0x20C0, 0x2922, 0x20C2, 0x0820, 0x28C1, 0x6267, 0x6A87, 0x59E4, 0x4983, 0x5183, 0x4162, 0x4142, 0x4122, 0x6206, // 0x0D10 (3344) +0x8309, 0x6A87, 0x59C5, 0x51A4, 0x4963, 0x51A4, 0x5A26, 0x41E3, 0x6385, 0x958B, 0x8D8A, 0x8D69, 0x8549, 0x8549, 0x8569, 0x7D48, // 0x0D20 (3360) +0x7D89, 0x85AA, 0x8589, 0x7D69, 0x85AA, 0x6C48, 0x2961, 0x4185, 0x51E5, 0x49A4, 0x4983, 0x51A4, 0x59E5, 0x59E6, 0x5A06, 0x51E6, // 0x0D30 (3376) +0x3102, 0x28C1, 0x4163, 0x5A06, 0x6227, 0x4984, 0x3102, 0x20E2, 0x1080, 0x1060, 0x20A1, 0x2060, 0x30C1, 0x72A8, 0x8B4A, 0x8309, // 0x0D40 (3392) +0xBCD0, 0xCD53, 0x93CC, 0x93CD, 0x9C2E, 0x6268, 0x5206, 0x4164, 0x5A27, 0x72EA, 0x834B, 0x72A9, 0x834B, 0xB490, 0xC511, 0xB490, // 0x0D50 (3408) +0x8B6B, 0x38E1, 0x28E0, 0x2901, 0x20C2, 0x1042, 0x1020, 0x3944, 0x5A46, 0x6A87, 0x6245, 0x59E4, 0x4983, 0x5184, 0x4984, 0x4123, // 0x0D60 (3424) +0x7288, 0x7288, 0x59E5, 0x51A4, 0x4963, 0x4983, 0x5205, 0x4203, 0x6385, 0x95AB, 0x8D8A, 0x8D8A, 0x8D69, 0x8D89, 0x8D69, 0x8548, // 0x0D70 (3440) +0x8589, 0x85AA, 0x8568, 0x7D48, 0x858A, 0x6406, 0x2961, 0x49A5, 0x49A5, 0x4163, 0x4163, 0x49A4, 0x5A26, 0x6247, 0x6A88, 0x5A27, // 0x0D80 (3456) +0x3122, 0x28E1, 0x51C5, 0x6A88, 0x51C5, 0x3103, 0x20C1, 0x1880, 0x0840, 0x1880, 0x3964, 0x30E2, 0x38E1, 0x6226, 0x8329, 0x8B4A, // 0x0D90 (3472) +0x9C0D, 0xAC8F, 0x9C0D, 0xA44F, 0xA44F, 0x72EA, 0x5A27, 0x49A5, 0x5A07, 0x7B2B, 0x7B2B, 0x72A9, 0x8B6B, 0xA40E, 0xAC4E, 0xA42E, // 0x0DA0 (3488) +0x832A, 0x3902, 0x3941, 0x3142, 0x20A2, 0x1021, 0x1041, 0x1860, 0x3123, 0x49A5, 0x5205, 0x6266, 0x6226, 0x51A4, 0x51A5, 0x59E6, // 0x0DB0 (3504) +0x59C5, 0x6A46, 0x59E5, 0x49A3, 0x4963, 0x4963, 0x49A4, 0x39C2, 0x6BE7, 0x9DCC, 0x8D89, 0x8DA9, 0x8D89, 0x8D89, 0x8D88, 0x8D68, // 0x0DC0 (3520) +0x85A9, 0x8DAA, 0x8568, 0x8548, 0x858A, 0x6427, 0x2961, 0x49A5, 0x4164, 0x4163, 0x51A4, 0x51C5, 0x49A4, 0x4984, 0x5A26, 0x5A47, // 0x0DD0 (3536) +0x3943, 0x28C1, 0x49A5, 0x49A5, 0x3123, 0x20A1, 0x18A1, 0x1060, 0x1060, 0x20C2, 0x5206, 0x4984, 0x4943, 0x6205, 0x7B09, 0x8B8B, // 0x0DE0 (3552) +0x8B6B, 0x93CC, 0x8BAC, 0xAC6F, 0xA44F, 0x7B2B, 0x51E6, 0x6247, 0x6248, 0x6AA9, 0x7B0A, 0x7AEA, 0x834B, 0xA42E, 0xA40E, 0x8B8C, // 0x0DF0 (3568) +0x72C9, 0x3923, 0x3923, 0x3102, 0x1880, 0x0820, 0x2962, 0x20E0, 0x18A0, 0x28E2, 0x3122, 0x3923, 0x4163, 0x4983, 0x4964, 0x5185, // 0x0E00 (3584) +0x51A5, 0x59C5, 0x6246, 0x6246, 0x51C4, 0x4963, 0x4183, 0x41C3, 0x6BC8, 0x9DAC, 0x95AA, 0x95C9, 0x95A9, 0x95A9, 0x8D89, 0x8D88, // 0x0E10 (3600) +0x85A9, 0x85A9, 0x8568, 0x8569, 0x858A, 0x6C47, 0x2961, 0x4184, 0x4164, 0x4163, 0x4983, 0x4963, 0x4983, 0x51C5, 0x5A46, 0x5A06, // 0x0E20 (3616) +0x3943, 0x28C1, 0x30E2, 0x28A1, 0x20C1, 0x18A1, 0x1080, 0x1080, 0x0840, 0x20C1, 0x5206, 0x59E5, 0x51A4, 0x6226, 0x7AE8, 0x8BAB, // 0x0E30 (3632) +0x836A, 0x8B6B, 0x832A, 0x93CD, 0x9C2E, 0x72C9, 0x5206, 0x7B0B, 0x6A89, 0x5A47, 0x6AA9, 0x7AEA, 0x7B0A, 0x93CD, 0x834A, 0x7B0A, // 0x0E40 (3648) +0x6A89, 0x4985, 0x3103, 0x20A1, 0x1880, 0x0860, 0x5B46, 0x6BC8, 0x3A03, 0x2121, 0x20E0, 0x3101, 0x3122, 0x3922, 0x3922, 0x4164, // 0x0E50 (3664) +0x4984, 0x51A4, 0x5A25, 0x5A25, 0x4984, 0x3902, 0x30E1, 0x3982, 0x5B26, 0x954C, 0x9E0B, 0x9DEA, 0x95C9, 0x95C9, 0x95A9, 0x8D89, // 0x0E60 (3680) +0x8589, 0x8589, 0x8568, 0x8569, 0x8569, 0x7488, 0x2982, 0x3964, 0x4164, 0x49A4, 0x49A4, 0x4163, 0x4183, 0x5206, 0x5A46, 0x51C5, // 0x0E70 (3696) +0x3102, 0x30E2, 0x28C1, 0x20C2, 0x20C1, 0x18C1, 0x0860, 0x0860, 0x0840, 0x20A0, 0x49C5, 0x59E5, 0x51A4, 0x6246, 0x72C8, 0x834A, // 0x0E80 (3712) +0x7AE8, 0x7AE9, 0x832A, 0x7B0A, 0x93CD, 0x6AA8, 0x72C9, 0x7B2B, 0x6268, 0x6A89, 0x6A88, 0x6A88, 0x7AEA, 0x834B, 0x72A8, 0x72A9, // 0x0E90 (3728) +0x5A47, 0x3944, 0x28C2, 0x28A1, 0x1880, 0x0040, 0x6BE6, 0xAE2D, 0x958B, 0x5B85, 0x31A0, 0x20E0, 0x28E0, 0x3102, 0x3102, 0x3123, // 0x0EA0 (3744) +0x4164, 0x41A4, 0x4183, 0x3942, 0x4143, 0x38E2, 0x30A1, 0x3121, 0x4A64, 0x84AA, 0xA60B, 0x9E0A, 0x9DC9, 0x9DEA, 0x95C9, 0x8DA9, // 0x0EB0 (3760) +0x7D89, 0x7D69, 0x7D68, 0x7D48, 0x7D49, 0x7CCA, 0x31A3, 0x3984, 0x4184, 0x4984, 0x4163, 0x4983, 0x4984, 0x51E5, 0x51C4, 0x4163, // 0x0EC0 (3776) +0x3102, 0x28C1, 0x28E1, 0x20C2, 0x18A1, 0x0840, 0x18E2, 0x2122, 0x1080, 0x1860, 0x4184, 0x4984, 0x4963, 0x5A05, 0x6A87, 0x72C8, // 0x0ED0 (3792) +0x6A66, 0x7287, 0x834A, 0x7AE9, 0x8B8B, 0x7B2A, 0x836C, 0x72C9, 0x6268, 0x72C9, 0x5A06, 0x6268, 0x7AEA, 0x6A88, 0x6247, 0x6288, // 0x0EE0 (3808) +0x5A06, 0x3923, 0x30E2, 0x28A1, 0x1060, 0x0880, 0x63E5, 0xA60B, 0x9E09, 0xAE4C, 0x950A, 0x5B06, 0x3163, 0x20C1, 0x20C1, 0x2902, // 0x0EF0 (3824) +0x3103, 0x3123, 0x3121, 0x3100, 0x30C1, 0x30A2, 0x3903, 0x3963, 0x39C3, 0x73E8, 0x9DCB, 0x9DE9, 0x9DE9, 0x95CA, 0x8DC9, 0x8DA9, // 0x0F00 (3840) +0x7D6C, 0x7D6B, 0x7548, 0x7569, 0x7549, 0x7CEB, 0x4A44, 0x4143, 0x49A4, 0x4183, 0x41A3, 0x5204, 0x62A6, 0x49C4, 0x4163, 0x30E2, // 0x0F10 (3856) +0x30E2, 0x20A1, 0x20C1, 0x1080, 0x0880, 0x2182, 0x3285, 0x3A45, 0x18A1, 0x2081, 0x3122, 0x3942, 0x4983, 0x59E5, 0x6225, 0x6226, // 0x0F20 (3872) +0x5A05, 0x6226, 0x72A8, 0x7AE9, 0x7B2A, 0x8B8B, 0x8B8C, 0x5A26, 0x6246, 0x7B0A, 0x5A26, 0x6267, 0x6AA9, 0x6268, 0x5A47, 0x5A47, // 0x0F30 (3888) +0x49C5, 0x3943, 0x28E1, 0x28C1, 0x1880, 0x0860, 0x6386, 0x9DEC, 0x95A9, 0x95E9, 0x9E0A, 0x9DEB, 0x8D09, 0x5B64, 0x29C0, 0x1920, // 0x0F40 (3904) +0x18E0, 0x28C2, 0x28C2, 0x28A2, 0x30A2, 0x30C2, 0x4143, 0x41A3, 0x4A44, 0x6B87, 0x8D2B, 0x9DCC, 0x95CB, 0x95C9, 0x8DA8, 0x8DA8, // 0x0F50 (3920) +0x7D6C, 0x7D8B, 0x6D48, 0x6D68, 0x6529, 0x7D2B, 0x52A6, 0x3962, 0x3983, 0x3983, 0x3982, 0x49E4, 0x49A3, 0x4163, 0x3902, 0x3902, // 0x0F60 (3936) +0x2081, 0x20A1, 0x1080, 0x0880, 0x29E3, 0x5BA8, 0x6449, 0x5BC8, 0x2100, 0x20A0, 0x3122, 0x3122, 0x4163, 0x51C5, 0x59E5, 0x59E6, // 0x0F70 (3952) +0x59E5, 0x59E5, 0x6AA8, 0x7B09, 0x836B, 0x834A, 0x832A, 0x51E5, 0x6A87, 0x7B0A, 0x6247, 0x5A06, 0x6267, 0x5A27, 0x51E6, 0x51E6, // 0x0F80 (3968) +0x4184, 0x3923, 0x30E2, 0x28A1, 0x20A1, 0x1080, 0x5304, 0x9DCC, 0x95A9, 0x95E9, 0x95C9, 0x95A9, 0xA5EB, 0xAE0D, 0x8D2B, 0x6C08, // 0x0F90 (3984) +0x4283, 0x31A1, 0x2100, 0x2900, 0x3121, 0x3161, 0x41C2, 0x4A43, 0x4AA3, 0x5BA6, 0x7CC9, 0x8D8A, 0x8DAA, 0x8589, 0x8568, 0x8568, // 0x0FA0 (4000) +0x7D4B, 0x7D6B, 0x6D69, 0x6D69, 0x6549, 0x754C, 0x4B06, 0x2942, 0x3162, 0x2901, 0x3142, 0x3922, 0x3922, 0x4164, 0x3902, 0x28C2, // 0x0FB0 (4016) +0x20A2, 0x1860, 0x10A0, 0x29C2, 0x6429, 0x8D8C, 0x858B, 0x7CEA, 0x31A1, 0x20C0, 0x3121, 0x3102, 0x3943, 0x49A5, 0x49C5, 0x49C5, // 0x0FC0 (4032) +0x49A4, 0x51A4, 0x6267, 0x72C8, 0x7B0A, 0x6A88, 0x6AA8, 0x51C4, 0x7B2A, 0x834B, 0x6AA8, 0x51E5, 0x5A26, 0x5A06, 0x51E5, 0x4164, // 0x0FD0 (4048) +0x3943, 0x3103, 0x30E2, 0x28A1, 0x20A2, 0x18C0, 0x3A42, 0x958B, 0x8568, 0x8DA8, 0x8DC9, 0x95E9, 0x9DE9, 0x9DEA, 0xA60C, 0xA5ED, // 0x0FE0 (4064) +0x9DAC, 0x8CEA, 0x6C06, 0x5B65, 0x5B44, 0x6386, 0x6C07, 0x7448, 0x7CC8, 0x7D09, 0x856A, 0x8DCA, 0x8DAA, 0x8568, 0x7D47, 0x7D48, // 0x0FF0 (4080) +0x7D6B, 0x7D8B, 0x758A, 0x758A, 0x6D6B, 0x6D0B, 0x4286, 0x2922, 0x2902, 0x28E2, 0x30C1, 0x38E2, 0x3903, 0x30C2, 0x28E2, 0x18A0, // 0x1000 (4096) +0x10A0, 0x1941, 0x3AA4, 0x5C08, 0x7D6B, 0x85AB, 0x7DCA, 0x8DAC, 0x4263, 0x28E0, 0x3102, 0x30E2, 0x3923, 0x49A5, 0x49C5, 0x41A4, // 0x1010 (4112) +0x4184, 0x4984, 0x5A06, 0x6226, 0x6226, 0x59E5, 0x6A67, 0x6267, 0x7B09, 0x834A, 0x6AA8, 0x51C4, 0x49A4, 0x49A4, 0x51C5, 0x4164, // 0x1020 (4128) +0x3122, 0x3903, 0x30E2, 0x30A2, 0x28A2, 0x20E1, 0x29E1, 0x8D2B, 0x8DCA, 0x8DA9, 0x8DC9, 0x95EA, 0x95E9, 0x9DEA, 0x9DEB, 0x9DEB, // 0x1030 (4144) +0x9E0B, 0xA64C, 0xA64C, 0x9DEB, 0x9DCB, 0xA5EC, 0xA62C, 0x9E0C, 0x9E0B, 0x95EA, 0x8DEA, 0x8DC9, 0x8589, 0x8548, 0x7D28, 0x8528, // 0x1040 (4160) +0x756B, 0x754A, 0x756A, 0x754A, 0x754B, 0x6429, 0x39C3, 0x3122, 0x3102, 0x30E1, 0x30C1, 0x30A1, 0x28A1, 0x20C1, 0x10A0, 0x1100, // 0x1050 (4176) +0x2A22, 0x53A7, 0x7D0B, 0x7D4A, 0x7D8A, 0x7DAA, 0x7DCA, 0x8DAC, 0x52C6, 0x28E1, 0x3102, 0x30E2, 0x3923, 0x4164, 0x4183, 0x4183, // 0x1060 (4192) +0x4163, 0x4984, 0x51A5, 0x49A4, 0x4984, 0x51C5, 0x6A88, 0x72C9, 0x8B8B, 0x836B, 0x6267, 0x49C4, 0x4983, 0x4983, 0x51E5, 0x4163, // 0x1070 (4208) +0x30E2, 0x3902, 0x3902, 0x30E2, 0x28A1, 0x20E1, 0x31E1, 0x84EA, 0x8D8A, 0x85A9, 0x8DAA, 0x8DCA, 0x95C9, 0x95EA, 0x95EB, 0x95EB, // 0x1080 (4224) +0x95EA, 0x9E0A, 0x9E2B, 0x9E0B, 0x9DEA, 0x9DEA, 0x960A, 0x9E0A, 0x960A, 0x95E9, 0x95E9, 0x8DC9, 0x8DA8, 0x8568, 0x8547, 0x8548, // 0x1090 (4240) +0x6D6A, 0x6D4A, 0x756B, 0x7D6B, 0x7D2B, 0x53A7, 0x31A2, 0x41A3, 0x3982, 0x39A2, 0x4A25, 0x41C4, 0x2941, 0x1900, 0x19A1, 0x4B86, // 0x10A0 (4256) +0x6CA8, 0x7D8B, 0x85CB, 0x7D8A, 0x7DAA, 0x85EB, 0x7DAA, 0x8DAC, 0x5B27, 0x20E1, 0x3122, 0x3102, 0x3902, 0x4143, 0x4143, 0x4963, // 0x10B0 (4272) +0x4163, 0x4984, 0x4184, 0x4163, 0x4163, 0x49C5, 0x6267, 0x6267, 0x8BAC, 0x7B2A, 0x51E5, 0x4984, 0x4184, 0x49A4, 0x51C5, 0x3943, // 0x10C0 (4288) +0x30E1, 0x3922, 0x3902, 0x3902, 0x28C1, 0x2101, 0x3A22, 0x84EB, 0x8DAB, 0x8589, 0x8D8A, 0x95CA, 0x95EA, 0x95CA, 0x95EB, 0x9DEB, // 0x10D0 (4304) +0xA62B, 0xA62B, 0xA62B, 0xA62B, 0x9E2B, 0x9E0B, 0x9E0B, 0x9E2B, 0x9E0A, 0x9E0A, 0x9E09, 0x95E9, 0x95C8, 0x8D88, 0x8D68, 0x8D68, // 0x10E0 (4320) +0x6549, 0x6D49, 0x7549, 0x7D4A, 0x74EA, 0x4B65, 0x3A63, 0x4AC5, 0x5B87, 0x6409, 0x4B46, 0x3A83, 0x3A63, 0x42E4, 0x7CEA, 0x858B, // 0x10F0 (4336) +0x7D8A, 0x7DAA, 0x7D89, 0x85AA, 0x8DAA, 0x8DAA, 0x85AA, 0x9DED, 0x73C9, 0x2120, 0x2941, 0x2922, 0x3122, 0x3943, 0x3923, 0x4144, // 0x1100 (4352) +0x4143, 0x4143, 0x3943, 0x3923, 0x4143, 0x4164, 0x51E5, 0x49A4, 0x5A27, 0x51E6, 0x4143, 0x3922, 0x3902, 0x4143, 0x4164, 0x3923, // 0x1110 (4368) +0x28E1, 0x3102, 0x3902, 0x3902, 0x3102, 0x2100, 0x4263, 0x954C, 0x8D8A, 0x8DAA, 0x95CA, 0x95CA, 0x95C9, 0x95CA, 0x95EA, 0x9E0B, // 0x1120 (4384) +0x9E0A, 0xA62B, 0xA62B, 0xA60B, 0x9E0B, 0x9E0B, 0xA62B, 0xA60B, 0xA62A, 0xA60A, 0x9E0A, 0x9DE9, 0x95C8, 0x8DA8, 0x8DA8, 0x8DA8, // 0x1130 (4400) +0x6D69, 0x6D89, 0x7549, 0x7D4A, 0x6D2A, 0x5407, 0x6449, 0x74CB, 0x6CEA, 0x5468, 0x43E6, 0x5448, 0x6468, 0x7D2B, 0x7D6A, 0x7D89, // 0x1140 (4416) +0x7DAA, 0x85A9, 0x8DAA, 0x95EB, 0x8D8A, 0x95CB, 0x95EA, 0x9DEC, 0x8CAB, 0x2980, 0x2960, 0x2941, 0x3142, 0x3944, 0x3923, 0x3904, // 0x1150 (4432) +0x3923, 0x3102, 0x3102, 0x3102, 0x3943, 0x3923, 0x4184, 0x3943, 0x3943, 0x3923, 0x3923, 0x3902, 0x3902, 0x3943, 0x3923, 0x3102, // 0x1160 (4448) +0x28C1, 0x28C2, 0x3102, 0x3102, 0x3122, 0x2920, 0x4282, 0x9DAC, 0x95CA, 0x95EA, 0x95CA, 0x95CA, 0x9DE9, 0x9DE9, 0x9DEA, 0x9E0A, // 0x1170 (4464) +0xA62A, 0xAE4B, 0xAE6B, 0xAE4B, 0xA64B, 0xA62B, 0xA62B, 0xA62B, 0xAE2B, 0xA60A, 0xA60A, 0x9E0A, 0x9DE9, 0x95C8, 0x8DC8, 0x95E9, // 0x1180 (4480) +0x6D69, 0x6D69, 0x6D48, 0x7569, 0x7548, 0x6D28, 0x7549, 0x756A, 0x7549, 0x6D29, 0x6508, 0x6D29, 0x6D69, 0x7569, 0x7589, 0x7D89, // 0x1190 (4496) +0x85A9, 0x8DAA, 0x95C9, 0x95C9, 0x8DCA, 0x95EB, 0x9DEC, 0xA5EC, 0x9DCC, 0x4261, 0x2900, 0x3103, 0x3923, 0x3123, 0x3103, 0x28E2, // 0x11A0 (4512) +0x28E2, 0x3102, 0x28E1, 0x28E1, 0x3102, 0x3102, 0x3122, 0x3102, 0x3102, 0x30E2, 0x28C2, 0x30E2, 0x3102, 0x3102, 0x30E2, 0x3102, // 0x11B0 (4528) +0x20C1, 0x28C1, 0x30E2, 0x3102, 0x3121, 0x2900, 0x4202, 0xADAD, 0xADEA, 0xA5E9, 0x9E09, 0x95E9, 0x9DE9, 0x9E0A, 0xA60A, 0xA62A, // 0x11C0 (4544) +0xAE4B, 0xAE4B, 0xAE4B, 0xAE4B, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE2A, 0xA64A, 0xA62A, 0xA62A, 0x9E2A, 0x9DE9, 0x95E9, 0x9DE8, 0x9DC8, // 0x11D0 (4560) +0x6D69, 0x6D69, 0x6D48, 0x7569, 0x7569, 0x7569, 0x7569, 0x756A, 0x6D49, 0x6D29, 0x6509, 0x6D49, 0x7569, 0x7D89, 0x7D89, 0x7DA9, // 0x11E0 (4576) +0x85AA, 0x8DAA, 0x95C9, 0x95C9, 0x8DEA, 0x95EB, 0x9DEC, 0x9DEC, 0xA62D, 0x5B65, 0x2920, 0x3123, 0x3102, 0x28E2, 0x20C2, 0x20C1, // 0x11F0 (4592) +0x20A1, 0x28E2, 0x28E2, 0x28E2, 0x28E2, 0x28C1, 0x28E1, 0x28E1, 0x28E1, 0x28E1, 0x28C1, 0x28C2, 0x30E2, 0x30E2, 0x30E2, 0x3102, // 0x1200 (4608) +0x20A1, 0x1880, 0x28E2, 0x3102, 0x3101, 0x2900, 0x39A1, 0xA56D, 0xAE2B, 0xA629, 0x9E0A, 0x9E0A, 0x9E0A, 0xA62A, 0xA62A, 0xA64A, // 0x1210 (4624) +0xAE4B, 0xAE4B, 0xB66B, 0xAE4B, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE2A, 0xA62A, 0xA60A, 0x9E2A, 0x9E0A, 0x9DE9, 0x95E9, 0x9DE8, 0x9DC8, // 0x1220 (4640) +0x6549, 0x6549, 0x6528, 0x6D49, 0x7569, 0x7569, 0x7D6A, 0x754A, 0x6D29, 0x6D09, 0x6D09, 0x7549, 0x7589, 0x7D89, 0x7DA9, 0x85A9, // 0x1230 (4656) +0x8DA9, 0x8DCA, 0x95C9, 0x95E9, 0x95EA, 0x95EB, 0x9DEC, 0x9DEC, 0xA62D, 0x7448, 0x2940, 0x3123, 0x28E2, 0x20A1, 0x1881, 0x1881, // 0x1240 (4672) +0x1880, 0x28E2, 0x2902, 0x2902, 0x28C1, 0x20A1, 0x20A1, 0x20A1, 0x20A1, 0x28A1, 0x20A1, 0x20A1, 0x28A2, 0x28C2, 0x28C2, 0x30E3, // 0x1250 (4688) +0x1881, 0x1040, 0x28C2, 0x20A1, 0x28E1, 0x2921, 0x2920, 0x8CAA, 0xB64C, 0xAE2A, 0xA62A, 0xA62A, 0xA62A, 0xA62B, 0xA62A, 0xAE4B, // 0x1260 (4704) +0xAE4B, 0xAE6B, 0xB66B, 0xAE4B, 0xAE4A, 0xAE4A, 0xAE4A, 0xAE2A, 0xA62A, 0x9E09, 0x9E09, 0x9E09, 0x9DE9, 0x95E9, 0x9DE8, 0x9DC8, // 0x1270 (4720) +0x6529, 0x6549, 0x6528, 0x6D28, 0x7549, 0x7549, 0x756A, 0x7529, 0x6D29, 0x6D09, 0x6D08, 0x7549, 0x7D69, 0x7D89, 0x85A9, 0x85A9, // 0x1280 (4736) +0x8DA9, 0x8DC9, 0x95C9, 0x95E9, 0x95EA, 0x960B, 0x95EC, 0x9DEC, 0x9E0D, 0x7C89, 0x2120, 0x3122, 0x20C1, 0x1880, 0x1881, 0x1881, // 0x1290 (4752) +0x1860, 0x28E2, 0x3102, 0x3102, 0x20C2, 0x1881, 0x1881, 0x20A1, 0x2081, 0x20A1, 0x20A1, 0x20A1, 0x20A1, 0x20A1, 0x28C2, 0x28E2, // 0x12A0 (4768) +0x1860, 0x1060, 0x20A2, 0x1860, 0x20C1, 0x3121, 0x2100, 0x73E7, 0xBE4D, 0xAE2A, 0xA62A, 0xA62A, 0xA62B, 0xA62A, 0xA62A, 0xAE2A, // 0x12B0 (4784) +0xAE4B, 0xAE4B, 0xAE4B, 0xAE4B, 0xAE4A, 0xAE4A, 0xAE4A, 0xA62A, 0xA62A, 0x9E09, 0x9DE9, 0x95E9, 0x95E9, 0x95E9, 0x9DE8, 0x95C8, // 0x12C0 (4800) +}; diff --git a/libraries/UTFT_Buttons/examples/UTFT_Buttons_Demo_320x240/UTFT_Buttons_Demo_320x240.ino b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Demo_320x240/UTFT_Buttons_Demo_320x240.ino new file mode 100644 index 0000000..6b5cb1a --- /dev/null +++ b/libraries/UTFT_Buttons/examples/UTFT_Buttons_Demo_320x240/UTFT_Buttons_Demo_320x240.ino @@ -0,0 +1,125 @@ +// UTFT_Buttons_Demo_320x240 (C)2013 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// A small demo to demonstrate the use of some of the +// functions of the UTFT_Buttons add-on library. +// +// This demo was made for modules with a screen resolution +// of 320x240 pixels, but should work on larger screens as +// well. +// +// This program requires both the UTFT and UTouch libraries +// in addition to the UTFT_Buttons add-on library. +// + +#include +#include +#include + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; +extern uint8_t BigFont[]; +extern uint8_t Dingbats1_XL[]; + +// Set up UTFT... +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino 2009/Uno/Leonardo shield : ,19,18,17,16 +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Standard chipKit Uno32/uC32 : ,34,35,36,37 +// Standard chipKit Max32 : ,82,83,84,85 +// AquaLEDSource All in One Super Screw Shield : ,82,83,84,85 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +// Set up UTouch... +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino 2009/Uno/Leonardo shield : 15,10,14,9,8 +// Standard Arduino Mega/Due shield : 6,5,4,3,2 +// CTE TFT LCD/SD Shield for Arduino Due : 6,5,4,3,2 +// Standard chipKit Uno32/uC32 : 20,21,22,23,24 +// Standard chipKit Max32 : 62,63,64,65,66 +// AquaLEDSource All in One Super Screw Shield : 62,63,64,65,66 +UTouch myTouch(6,5,4,3,2); + +// Finally we set up UTFT_Buttons :) +UTFT_Buttons myButtons(&myGLCD, &myTouch); + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(SmallFont); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_MEDIUM); + + myButtons.setTextFont(BigFont); + myButtons.setSymbolFont(Dingbats1_XL); +} + +void loop() +{ + int but1, but2, but3, but4, butX, butY, pressed_button; + boolean default_colors = true; + + but1 = myButtons.addButton( 10, 20, 300, 30, "Button 1"); + but2 = myButtons.addButton( 10, 60, 300, 30, "Button 2"); + but3 = myButtons.addButton( 10, 100, 300, 30, "Button 3"); + but4 = myButtons.addButton( 10, 140, 300, 30, "Button 4", BUTTON_DISABLED); + butX = myButtons.addButton(279, 199, 40, 40, "a", BUTTON_SYMBOL); + butY = myButtons.addButton( 0, 199, 100, 40, "I", BUTTON_SYMBOL | BUTTON_SYMBOL_REP_3X); + myButtons.drawButtons(); + + myGLCD.print("You pressed:", 110, 205); + myGLCD.setColor(VGA_BLACK); + myGLCD.setBackColor(VGA_WHITE); + myGLCD.print("None ", 110, 220); + + while(1) + { + if (myTouch.dataAvailable() == true) + { + pressed_button = myButtons.checkButtons(); + + if (pressed_button==butX) + { + if (myButtons.buttonEnabled(but4)) + myButtons.disableButton(but4, true); + else + myButtons.enableButton(but4, true); + } + else if (pressed_button==butY) + { + if (default_colors) + { + myButtons.setButtonColors(VGA_YELLOW, VGA_RED, VGA_YELLOW, VGA_BLUE, VGA_GRAY); + myButtons.relabelButton(butY, "_"); + myButtons.drawButtons(); + default_colors=false; + } + else + { + myButtons.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_BLUE); + myButtons.relabelButton(butY, "I"); + myButtons.drawButtons(); + default_colors=true; + } + } + if (pressed_button==but1) + myGLCD.print("Button 1", 110, 220); + if (pressed_button==but2) + myGLCD.print("Button 2", 110, 220); + if (pressed_button==but3) + myGLCD.print("Button 3", 110, 220); + if (pressed_button==but4) + myGLCD.print("Button 4", 110, 220); + if (pressed_button==-1) + myGLCD.print("None ", 110, 220); + } + } +} + diff --git a/libraries/UTFT_Buttons/fonts.c b/libraries/UTFT_Buttons/fonts.c new file mode 100644 index 0000000..b189f8e --- /dev/null +++ b/libraries/UTFT_Buttons/fonts.c @@ -0,0 +1,117 @@ +#if defined(__AVR__) + #include + #define fontdatatype const uint8_t +#elif defined(__PIC32MX__) + #define PROGMEM + #define fontdatatype const unsigned char +#elif defined(__arm__) + #define PROGMEM + #define fontdatatype const unsigned char +#endif + +// Dingbats1_XL.c +// Font type : Full (95 characters) +// Font size : 32x24 pixels +fontdatatype Dingbats1_XL[9124] PROGMEM={ +0x20,0x18,0x20,0x5F, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x0D,0xC0,0x00,0x00,0x1E,0xE0,0x00,0x00,0x33,0x30,0x00,0x00,0x61,0x98,0x00,0x00,0xCC,0xCC,0x00,0x00,0xCC,0x6C,0x00,0x01,0x80,0x36,0x00,0x03,0x02,0x36,0x00,0x07,0x06,0x1B,0x00,0x01,0x8E,0x1B,0x00,0x00,0xF6,0x1B,0x00,0x00,0x06,0x1B,0x00,0x00,0x06,0x1B,0x00,0x00,0x06,0x1B,0x00,0x00,0x07,0xFB,0x00,0x00,0x07,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ! +0x00,0x00,0x00,0x00,0x07,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0x00,0x06,0x00,0x03,0x00,0x06,0x00,0x03,0x00,0x06,0x06,0x33,0x00,0x06,0x06,0x33,0x00,0x06,0x00,0x33,0x00,0x06,0x00,0x33,0x00,0x07,0x00,0x33,0x00,0x03,0x80,0x33,0x00,0x01,0xC0,0x33,0x00,0x00,0xFC,0x33,0x00,0x00,0x7C,0x33,0x00,0x00,0x0C,0x3F,0x00,0x00,0x0C,0x1E,0x00,0x00,0x0C,0x00,0x00,0x00,0x1B,0xFC,0x00,0x00,0x19,0x24,0x00,0x00,0x1F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x00,0x00,0xEF,0xDC,0x00,0x00,0xFF,0xFC,0x00,0x00,0xD0,0x2C,0x00,0x00,0xC0,0x0C,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x03,0x00,0x03,0x00,0x03,0x0C,0xC3,0x00,0x03,0x0C,0xC3,0x00,0x03,0x00,0x03,0x00,0x03,0x03,0x03,0x00,0x01,0x8A,0x46,0x00,0x01,0x8F,0xC6,0x00,0x00,0xE0,0x1C,0x00,0x00,0x70,0x38,0x00,0x00,0x3F,0xF0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // # +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x1E,0x00,0x03,0xF7,0xBF,0x00,0x03,0xFF,0xFF,0x00,0x03,0xF0,0x3F,0x00,0x03,0xE0,0x1F,0x00,0x01,0x80,0x06,0x00,0x01,0x9C,0x66,0x00,0x03,0x35,0xB3,0x00,0x03,0x35,0x33,0x00,0x03,0x3C,0xF3,0x00,0x03,0x7C,0x7B,0x00,0x03,0x38,0x73,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x00,0xE0,0x1C,0x00,0x00,0x70,0x38,0x00,0x00,0x3F,0xF0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // $ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x00,0x00,0x30,0x3F,0x00,0x00,0x40,0x00,0x80,0x00,0x80,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x30,0x00,0x80,0x02,0x30,0x00,0x80,0x02,0x00,0x01,0x80,0x02,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x01,0x00,0x02,0x01,0x01,0x00,0x02,0x7F,0x01,0x00,0x02,0x41,0x01,0x00,0x02,0x41,0x02,0x00,0x02,0x41,0x02,0x00,0x01,0x38,0xFC,0x00,0x01,0x88,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // % +0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x1F,0xE0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x7F,0xF8,0x00,0x00,0x7F,0xFC,0x00,0x00,0xFF,0xFC,0x00,0x00,0xFF,0xFC,0x00,0x01,0xC0,0x0E,0x00,0x01,0x9F,0xE6,0x00,0x01,0x8C,0xC6,0x00,0x01,0xCC,0xCE,0x00,0x01,0xC0,0x0E,0x00,0x01,0xCC,0xCE,0x00,0x01,0x97,0xA6,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x00,0xC0,0x0C,0x00,0x00,0xFF,0xFC,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // & +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x06,0xC0,0x03,0x00,0x04,0x40,0x02,0x80,0x06,0x40,0x02,0x40,0x0E,0x20,0x01,0x40,0x01,0x2E,0x03,0x20,0x00,0x91,0x02,0x20,0x00,0x85,0xFE,0x20,0x04,0x45,0x69,0x20,0x0C,0xC3,0x00,0x20,0x1F,0xE0,0x00,0x60,0x10,0x00,0x00,0x40,0x18,0x0E,0x99,0x80,0x0F,0xF8,0xE1,0x00,0x00,0x0F,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x00,0x00,0xFF,0xFC,0x00,0x00,0x8F,0xC6,0x00,0x01,0xBF,0xF6,0x00,0x01,0xF8,0x7E,0x00,0x01,0xE0,0x1F,0x00,0x03,0xC0,0x0F,0x00,0x03,0x80,0x07,0x00,0x03,0x8C,0xC6,0x00,0x03,0x8C,0xC7,0x00,0x03,0x80,0x07,0x00,0x03,0x83,0x07,0x00,0x03,0xC9,0x4F,0x00,0x03,0xCF,0xCF,0x00,0x03,0xC0,0x0F,0x00,0x00,0xF0,0x3C,0x00,0x00,0xFC,0xFC,0x00,0x00,0x3F,0xF0,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ( +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x19,0xE0,0x00,0x00,0x39,0xE0,0x00,0x00,0x5F,0xE0,0x00,0x00,0x3F,0xE0,0x00,0x00,0x17,0xE0,0x00,0x00,0x13,0xF0,0x00,0x00,0x13,0xF0,0x00,0x00,0x33,0xF8,0x00,0x00,0x23,0xF8,0x00,0x00,0x23,0xFC,0x00,0x00,0x23,0xF0,0x00,0x00,0x33,0xF0,0x00,0x00,0x1B,0xF0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x21,0xF8,0x00,0x00,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ) +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xC0,0x1F,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xC0,0x10,0x7F,0xFF,0xC0,0x15,0x7F,0xFD,0xC0,0x15,0xBF,0xF8,0xE0,0x0A,0xFF,0xF8,0x60,0x0F,0x3F,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x01,0xFF,0x80,0x00,0x00,0x07,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // * +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1F,0xC0,0x00,0x00,0xFF,0xE0,0x00,0x01,0xEF,0xF1,0xC0,0x03,0xEF,0xFB,0x80,0x06,0x6F,0xFF,0x00,0x0E,0x63,0xFF,0x00,0x07,0xF3,0xFB,0x80,0x03,0xEB,0xF1,0x80,0x00,0xFF,0xF0,0x40,0x00,0x1C,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x23,0x01,0x00,0x00,0xC0,0x83,0x00,0x01,0x80,0x4F,0x00,0x02,0x60,0x3F,0x00,0x06,0x60,0x3F,0x00,0x01,0x80,0x4F,0x00,0x00,0xC0,0x83,0x00,0x00,0x23,0x01,0x00,0x00,0x17,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // , +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0x67,0x98,0x00,0x00,0xF0,0x3C,0x00,0x01,0xE7,0x9E,0x00,0x03,0xEF,0xFF,0x00,0x02,0x0C,0x31,0x00,0x03,0xF8,0xDF,0x80,0x07,0xE8,0xDF,0x80,0x07,0xF8,0x1F,0x80,0x07,0xF8,0x3F,0x80,0x07,0xE8,0xFF,0x80,0x07,0x28,0xD3,0x80,0x06,0x1C,0xE1,0x80,0x02,0x17,0x21,0x00,0x02,0x1F,0xE1,0x00,0x02,0x10,0x21,0x00,0x03,0xF0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x70,0x00,0x00,0x14,0x50,0x00,0x00,0x92,0x94,0x00,0x00,0xFA,0xBE,0x00,0x00,0xFA,0xBE,0x00,0x00,0xFB,0xBE,0x00,0x00,0x73,0x9C,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x07,0xC0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x07,0xC0,0x00,0x00,0x03,0x80,0x00,0x00,0x06,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x3F,0xA0,0x00,0x00,0x7F,0xE0,0x00,0x00,0x7D,0xE0,0x00,0x00,0xF0,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xFB,0xE0,0x00,0x00,0xFF,0xF0,0x00,0x00,0xFF,0xF8,0x00,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xFC,0x00,0x00,0x7F,0xFC,0x00,0x00,0x7F,0xFC,0x00,0x00,0x77,0xFE,0x00,0x00,0x77,0xFE,0x00,0x00,0x77,0x1F,0x00,0x00,0x77,0x1C,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // / + +0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x30,0x30,0x00,0x00,0xC0,0x0C,0x00,0x01,0x80,0xC6,0x00,0x01,0x01,0xF2,0x00,0x02,0x03,0xF1,0x00,0x02,0x07,0xA1,0x00,0x04,0x07,0x60,0x80,0x04,0x0E,0x00,0x80,0x04,0x0C,0x00,0x80,0x04,0x1C,0x00,0x80,0x04,0x1C,0x00,0x80,0x04,0x1C,0x00,0x80,0x02,0x3E,0x01,0x00,0x02,0x3A,0x01,0x00,0x01,0x14,0x02,0x00,0x00,0x24,0x06,0x00,0x00,0x20,0x0C,0x00,0x00,0x30,0x30,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0x80,0x05,0x00,0x00,0x80,0x05,0xC0,0x00,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x07,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0x80,0x02,0x00,0x00,0x80,0x06,0xFE,0x3E,0x80,0x06,0xFE,0x00,0x80,0x06,0x00,0x00,0x80,0x06,0xFF,0xFE,0x80,0x06,0xFE,0xFE,0x80,0x06,0x00,0x00,0x80,0x07,0xFF,0xFF,0x80,0x04,0x00,0x01,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xC6,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x82,0x00,0x03,0xFF,0x83,0x80,0x02,0x00,0x44,0x80,0x06,0x07,0x38,0x80,0x06,0x18,0xC0,0x80,0x06,0x10,0x40,0x80,0x06,0x10,0x40,0x80,0x06,0x18,0xC0,0x80,0x06,0x07,0x00,0x80,0x07,0xFF,0xFF,0x80,0x04,0x00,0x01,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x78,0x00,0x00,0x10,0xCC,0x00,0x00,0x10,0x84,0x00,0x00,0x10,0x84,0x00,0x00,0x10,0x84,0x00,0x00,0x19,0x84,0x00,0x00,0x0F,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0xEE,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x10,0x78,0x00,0x00,0x10,0xCC,0x00,0x00,0x10,0x84,0x00,0x00,0x10,0x84,0x00,0x00,0x10,0x84,0x00,0x00,0x19,0x84,0x00,0x00,0x0F,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 5 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x47,0x10,0x00,0x00,0xCF,0x98,0x00,0x00,0xEF,0xB8,0x00,0x01,0xDF,0xDC,0x00,0x03,0xCF,0x9E,0x00,0x01,0xFF,0xFC,0x00,0x01,0xFF,0xFC,0x00,0x03,0xDF,0xDE,0x00,0x03,0xAF,0xAE,0x00,0x07,0xFF,0xFF,0x00,0x03,0xDF,0xDE,0x00,0x03,0xBF,0xEE,0x00,0x07,0x87,0x0F,0x00,0x07,0xF7,0x7F,0x00,0x08,0xE7,0x38,0x80,0x00,0xE7,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xB0,0x00,0x00,0x37,0xB0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x03,0xC3,0x0F,0x00,0x01,0xE3,0x1E,0x00,0x00,0xF3,0x3C,0x00,0x00,0x7B,0x78,0x00,0x00,0x3F,0xF0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 +0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x1F,0xC0,0x00,0x00,0x27,0x20,0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0xE0,0x00,0x00,0x7F,0xF0,0x00,0x00,0x9F,0xC8,0x00,0x00,0x3F,0xE0,0x00,0x00,0xFF,0xF8,0x00,0x01,0xFF,0xFC,0x00,0x03,0xFF,0xFE,0x00,0x04,0x07,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x1B,0x80,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x3F,0xF8,0x00,0x00,0x7F,0xFC,0x00,0x00,0xFF,0xFE,0x00,0x00,0xE1,0x0E,0x00,0x00,0xE1,0x0E,0x00,0x00,0xE1,0x0E,0x00,0x00,0xFF,0xFE,0x00,0x00,0xFF,0xFE,0x00,0x00,0xE1,0x0E,0x00,0x00,0xE1,0x0E,0x00,0x00,0xE1,0x0E,0x00,0x00,0xFF,0xFE,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x40,0x04,0x00,0x00,0x59,0xB4,0x00,0x00,0x59,0xB4,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x59,0xB4,0x00,0x00,0x59,0xB4,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x59,0xB4,0x00,0x00,0x59,0xB4,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x41,0x84,0x00,0x00,0x41,0x84,0x00,0x00,0x41,0x84,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : +0x00,0x00,0x00,0x00,0x03,0xFF,0xE0,0x00,0x02,0x00,0x20,0x00,0x02,0xFF,0xA0,0x00,0x02,0x00,0x20,0x00,0x02,0xFF,0xA0,0x00,0x02,0x00,0x20,0x00,0x02,0xFF,0xA0,0x00,0x02,0x00,0x20,0x00,0x02,0xFF,0xA0,0x00,0x02,0x00,0x20,0x00,0x02,0xFF,0xA0,0x00,0x02,0xFF,0xA0,0x00,0x02,0x00,0x20,0x00,0x02,0xFF,0xA0,0x00,0x02,0x00,0x20,0x00,0x02,0x3E,0x20,0x00,0x02,0x3E,0x20,0x00,0x02,0x3E,0x20,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ; +0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x7F,0xF8,0x00,0x00,0xFF,0xFC,0x00,0x01,0xFF,0xFE,0x00,0x01,0xFC,0xFE,0x00,0x01,0xF8,0x7E,0x00,0x01,0xF8,0x7E,0x00,0x01,0xF8,0x7E,0x00,0x01,0xF8,0x7E,0x00,0x01,0xF8,0x7E,0x00,0x01,0xF8,0x7E,0x00,0x01,0xF8,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // < +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFD,0xFC,0x00,0x03,0x22,0x26,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x22,0x26,0x00,0x00,0x7D,0xFC,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x08,0x42,0x00,0x03,0x18,0xC6,0x00,0x03,0x39,0xCE,0x00,0x03,0x7B,0xFE,0x00,0x03,0xFF,0xFE,0x00,0x03,0xFF,0xFE,0x00,0x03,0xFF,0xFE,0x00,0x03,0xFF,0xFE,0x00,0x03,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = +0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x18,0x0F,0xC0,0x60,0x17,0xDF,0xEF,0xA0,0x10,0x71,0x38,0x20,0x10,0x31,0x30,0x20,0x10,0xD1,0x2C,0x20,0x1F,0x1F,0xE3,0xE0,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // > +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0C,0x60,0x00,0x00,0x09,0x20,0x00,0x00,0x09,0xA0,0x00,0x00,0x08,0x20,0x00,0x00,0x0C,0x60,0x00,0x00,0x0F,0xE0,0x00,0x00,0x7F,0xFC,0x00,0x00,0x7F,0xFC,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xFF,0x00,0x01,0xFC,0x7F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? + +0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0B,0xE0,0x00,0x00,0x08,0x78,0x00,0x00,0x08,0x08,0x00,0x00,0x0F,0x08,0x00,0x00,0x0B,0xE8,0x00,0x00,0x08,0x78,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x78,0x08,0x00,0x00,0xF8,0x08,0x00,0x01,0xF8,0x08,0x00,0x01,0xF0,0x78,0x00,0x01,0xE0,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // @ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x38,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x1C,0x38,0x00,0x01,0x00,0x00,0x00,0x01,0xCF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x01,0xCF,0xF0,0x00,0x01,0x07,0xE0,0x00,0x00,0x05,0xA0,0x00,0x00,0x0D,0xB0,0x00,0x00,0x09,0x90,0x00,0x00,0x19,0x98,0x00,0x00,0x11,0x88,0x00,0x00,0x31,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // A +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0xA0,0x14,0x00,0x01,0x40,0x14,0x00,0x01,0xC0,0x18,0x00,0x01,0x40,0x18,0x00,0x01,0x40,0x28,0x00,0x01,0xFF,0xF8,0x00,0x01,0x40,0x18,0x00,0x01,0x40,0x14,0x00,0x00,0xC0,0x1C,0x00,0x00,0xA0,0x14,0x00,0x00,0xA0,0x0C,0x00,0x00,0x7F,0xFC,0x00,0x00,0xA0,0x0E,0x00,0x00,0xE0,0x0C,0x00,0x00,0xE0,0x0C,0x00,0x00,0xC0,0x14,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // B +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x01,0xF6,0x00,0x00,0x3E,0xCE,0x00,0x03,0xF9,0xF0,0x00,0x02,0x3E,0x00,0x00,0x03,0xFF,0xFE,0x00,0x03,0x1C,0xE2,0x00,0x03,0xFF,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // C +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xE0,0x00,0x00,0x82,0x20,0x00,0x00,0x82,0x20,0x00,0x00,0xFF,0x20,0x00,0x00,0x81,0x20,0x00,0x00,0xFF,0xE0,0x00,0x00,0x8E,0x20,0x00,0x00,0xFF,0xE0,0x00,0x00,0x80,0x20,0x00,0x00,0xFF,0xE0,0x00,0x00,0x87,0x20,0x00,0x00,0x85,0xE0,0x00,0x00,0xFD,0x30,0x00,0x00,0x15,0x2E,0x00,0x00,0x6F,0x2A,0x00,0x00,0x41,0xEE,0x00,0x00,0x3C,0x3C,0x00,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // D +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x2C,0x80,0x00,0x00,0x24,0x80,0x00,0x00,0x12,0x50,0x00,0x00,0x49,0xB8,0x00,0x00,0x44,0xF0,0x00,0x00,0x43,0x5C,0x00,0x00,0xA0,0xBF,0x80,0x07,0x1D,0x7F,0x80,0x00,0xA0,0x8F,0x80,0x00,0x40,0x07,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // E +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x30,0xC0,0x00,0x00,0x20,0x40,0x00,0x00,0x40,0x23,0x00,0x00,0x40,0x26,0x00,0x00,0x40,0x26,0x00,0x00,0x40,0x2E,0x00,0x00,0x20,0x5A,0x00,0x00,0x30,0xF1,0x00,0x00,0x0F,0x19,0x00,0x00,0x05,0x1E,0x00,0x00,0x77,0x3C,0x00,0x00,0x7C,0x7C,0x00,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xF0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // F +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x00,0x06,0xD8,0x00,0x00,0x04,0xC8,0x00,0x00,0x0D,0xA8,0x00,0x00,0x15,0xFC,0x00,0x00,0x65,0xA6,0x00,0x00,0xE3,0x72,0x00,0x01,0xF6,0x9C,0x00,0x03,0xFB,0x67,0x00,0x00,0xFC,0x97,0x00,0x00,0x7E,0x3F,0x00,0x00,0x3D,0xFF,0x80,0x00,0x17,0x50,0x00,0x00,0x39,0xD8,0x00,0x00,0x0E,0xC8,0x00,0x00,0x04,0xC8,0x00,0x00,0x09,0xB8,0x00,0x00,0x1B,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // G +0x00,0x00,0x00,0x00,0x00,0x10,0x18,0x00,0x00,0x10,0x10,0x00,0x04,0x08,0x20,0x00,0x02,0x0B,0xA0,0xC0,0x01,0x03,0xE1,0x00,0x00,0x83,0xF2,0x00,0x00,0x0F,0xFC,0x00,0x00,0x33,0xFE,0x00,0x08,0x61,0xFF,0x00,0x07,0x76,0x3F,0x00,0x00,0x78,0x0F,0x00,0x00,0x7C,0x0F,0x00,0x00,0x3E,0x06,0x00,0x00,0x9F,0xF8,0x00,0x01,0x0F,0xFA,0x00,0x06,0x07,0xF9,0x00,0x08,0x03,0xF8,0x80,0x00,0x1B,0xF8,0xC0,0x00,0x10,0x00,0x00,0x00,0x20,0x84,0x00,0x00,0x20,0x84,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, // H +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x7F,0xF8,0x00,0x00,0x64,0x98,0x00,0x00,0x64,0x98,0x00,0x00,0x7F,0xF8,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFE,0x00,0x03,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0x80,0x01,0xF7,0xBE,0x00,0x01,0xF7,0xBE,0x00,0x00,0xE3,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // I +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF8,0x00,0x0F,0xC7,0xFC,0x00,0x01,0xFF,0xFC,0x00,0x00,0x07,0xFC,0x00,0x00,0x07,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x01,0x00,0x00,0x80,0x01,0x80,0x01,0x80,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // J +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x10,0x44,0x00,0x00,0x20,0x24,0x00,0x00,0x47,0x16,0x00,0x00,0xC8,0x9E,0x00,0x03,0x50,0x4F,0x00,0x04,0x50,0x4F,0x00,0x02,0x90,0x4F,0x00,0x07,0x88,0x87,0x80,0x07,0x87,0x1F,0x80,0x07,0xE5,0x3F,0xC0,0x0F,0xF7,0x7F,0x00,0x0F,0xF8,0xFE,0x00,0x03,0xFD,0xFC,0x00,0x00,0x7D,0xF8,0x00,0x00,0x7F,0xF0,0x00,0x00,0x7F,0xF0,0x00,0x00,0x7F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // K +0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x40,0x00,0x00,0x02,0x40,0x00,0x00,0x04,0x40,0x00,0x00,0x04,0xC0,0x00,0x00,0x03,0x80,0x00,0x00,0x07,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x19,0xC0,0x00,0x00,0x37,0xE0,0x00,0x00,0x35,0x70,0x00,0x00,0x35,0x30,0x00,0x00,0x33,0x30,0x00,0x00,0x19,0x20,0x00,0x00,0x1C,0xE0,0x00,0x00,0x07,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x0E,0x80,0x00,0x00,0x0E,0x80,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // L +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0x70,0x00,0x00,0x01,0x18,0x00,0x00,0x01,0x08,0x00,0x00,0x01,0x08,0x00,0x00,0x01,0x08,0x00,0x00,0x01,0x08,0x00,0x00,0x01,0x10,0x00,0x00,0x01,0x20,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // M +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0x80,0x04,0x00,0x00,0x80,0x04,0xFF,0xFC,0x80,0x05,0xFF,0xFE,0x80,0x05,0xFF,0x06,0x80,0x05,0xFF,0x06,0x80,0x05,0xFF,0x06,0x80,0x05,0xFF,0xF6,0x80,0x05,0xFF,0xF6,0x80,0x05,0xFF,0xF6,0x80,0x05,0xFF,0xFE,0x80,0x05,0xFF,0xFE,0x80,0x05,0xFF,0xFE,0x80,0x05,0xFF,0xFE,0x80,0x04,0x00,0x00,0x80,0x05,0x9B,0xC0,0x80,0x04,0x00,0x00,0x80,0x07,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // N +0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x01,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x03,0xFF,0xFE,0x00,0x02,0x4F,0x0E,0x00,0x02,0x4C,0xE6,0x00,0x02,0x7D,0xF6,0x00,0x02,0x4B,0xFA,0x00,0x02,0x4B,0xFA,0x00,0x02,0x7B,0xFA,0x00,0x02,0x7B,0xFA,0x00,0x02,0x7D,0xF6,0x00,0x02,0x7C,0xE6,0x00,0x02,0x7F,0x1E,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // O + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x00,0x00,0x16,0xD0,0x00,0x00,0x19,0x30,0x00,0x00,0x16,0xD0,0x00,0x00,0x16,0xD0,0x00,0x00,0x19,0x30,0x00,0x00,0x16,0xD0,0x00,0x00,0x3F,0xF8,0x00,0x00,0x30,0x18,0x00,0x00,0x3F,0xF8,0x00,0x00,0x3F,0xF8,0x00,0x00,0x3F,0xF8,0x00,0x00,0x2F,0xE8,0x00,0x00,0x20,0x08,0x00,0x00,0x1F,0xF0,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x80,0x00,0x00,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xC0,0x0F,0xC0,0x0F,0xC0,0x00,0x0F,0xC0,0x00,0x0F,0x9C,0xE7,0xC0,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x60,0x18,0x00,0x00,0xE0,0x1C,0x00,0x00,0xF0,0x3C,0x00,0x01,0xF0,0x3E,0x00,0x01,0xF8,0x7E,0x00,0x01,0xFF,0xFE,0x00,0x01,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Q +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,0x00,0x3C,0x10,0x00,0x01,0xF0,0x08,0x00,0x1E,0x3C,0x04,0x00,0xFC,0x3E,0x04,0x01,0x83,0x3C,0x04,0x01,0x01,0x38,0x04,0x02,0x06,0xB0,0x04,0x7E,0x18,0xB0,0x04,0x81,0x17,0xB0,0x04,0x80,0xE8,0xB0,0x04,0xC0,0x28,0xB0,0x04,0x5F,0x98,0x80,0x04,0x20,0x48,0x80,0x04,0x10,0x04,0x80,0x38,0x08,0x03,0x83,0xC0,0x04,0x01,0x9C,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // R +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,0x00,0x1C,0x10,0x00,0x01,0xE0,0x08,0x00,0x0E,0x00,0x04,0x00,0x7C,0x00,0x04,0x01,0x83,0x00,0x04,0x01,0x01,0x00,0x04,0x02,0x00,0x80,0x14,0x7E,0x00,0x80,0xE4,0x81,0x00,0x8F,0xE4,0x80,0xC0,0xBF,0xE4,0xC0,0x20,0xB1,0xC4,0x5F,0x90,0x80,0xC4,0x20,0x48,0x80,0x04,0x10,0x04,0x80,0x38,0x08,0x02,0x83,0xC0,0x04,0x01,0x9C,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // S +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x08,0x10,0x00,0x00,0x08,0x10,0x00,0x00,0x78,0x0F,0xFE,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x41,0xFF,0xFF,0xF8,0x41,0x00,0x00,0x08,0x42,0x00,0x00,0x10,0x42,0x00,0x00,0x10,0x44,0x00,0x00,0x20,0x48,0x00,0x00,0x20,0x48,0x00,0x00,0x40,0x50,0x00,0x00,0x80,0x50,0x00,0x00,0x80,0x60,0x00,0x01,0x00,0x60,0x00,0x01,0x00,0x7F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // T +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // U +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x00,0x00,0x1F,0xF0,0x00,0x07,0x3F,0xF8,0x00,0x07,0x40,0x04,0x00,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xF8,0x3F,0xC0,0x07,0xF0,0x1F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xF0,0x1F,0xC0,0x07,0xF8,0x3F,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // V +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x30,0x30,0x00,0x00,0x40,0x08,0x00,0x00,0x83,0x04,0x00,0x01,0x03,0x02,0x00,0x01,0x03,0x02,0x00,0x02,0x03,0x01,0x00,0x02,0x03,0x01,0x00,0x02,0x03,0xF9,0x00,0x02,0x03,0xF9,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x00,0x80,0x04,0x00,0x00,0x40,0x08,0x00,0x00,0x30,0x30,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // W +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x10,0x80,0x00,0x00,0x10,0x80,0x03,0xC0,0x10,0x80,0x1F,0xE0,0x0F,0xF0,0x7F,0x00,0x00,0x3F,0xF8,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x3F,0xF8,0x00,0x0F,0xF0,0x7F,0x00,0x10,0x80,0x1F,0xC0,0x10,0x80,0x03,0xE0,0x10,0x80,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // X +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x18,0x30,0x00,0x00,0x33,0xD8,0x00,0x00,0x2C,0x68,0x00,0x00,0x50,0x14,0x00,0x00,0x50,0x14,0x00,0x00,0x50,0x14,0x00,0x00,0x50,0x14,0x00,0x00,0xFF,0xFE,0x00,0x00,0xFF,0xFE,0x00,0x00,0xFE,0xFE,0x00,0x00,0xFC,0x7E,0x00,0x00,0xFE,0xFE,0x00,0x00,0xFE,0xFE,0x00,0x00,0x7E,0xFC,0x00,0x00,0x3F,0xF8,0x00,0x00,0x1F,0xF0,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Y +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xFC,0x00,0x00,0x03,0xFE,0x00,0x00,0x07,0xC7,0x00,0x00,0x07,0xC7,0x00,0x00,0x07,0xC7,0x00,0x00,0x07,0xFF,0x00,0x00,0x0F,0xFF,0x00,0x00,0x0F,0xFE,0x00,0x00,0x0F,0xFC,0x00,0x00,0x3F,0xF8,0x00,0x00,0x3F,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xFC,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Z +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x20,0x10,0x00,0x00,0x40,0x08,0x00,0x00,0x40,0x08,0x00,0x00,0x40,0x08,0x00,0x00,0x80,0x04,0x00,0x01,0xFF,0xFF,0x00,0x03,0x9F,0xE7,0x00,0x03,0x0F,0xC3,0x00,0x03,0x0F,0xC3,0x00,0x03,0x9F,0xE7,0x00,0x03,0xFF,0xFF,0x00,0x00,0xE0,0x1C,0x00,0x00,0xE0,0x1C,0x00,0x00,0xE0,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // [ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x04,0x80,0x00,0x00,0x1F,0xE0,0x00,0x00,0x20,0x10,0x00,0x00,0x40,0x10,0x00,0x00,0x40,0x08,0x00,0x00,0x40,0x08,0x00,0x00,0x80,0x04,0x00,0x01,0xFF,0xFF,0x00,0x03,0x9F,0xE7,0x00,0x03,0x0F,0xC3,0x00,0x03,0x0F,0xC3,0x00,0x03,0x9F,0xE7,0x00,0x03,0xFF,0xFF,0x00,0x00,0xE0,0x1C,0x00,0x00,0xE0,0x1C,0x00,0x00,0xE0,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0xE0,0x1C,0x00,0x01,0xE0,0x1E,0x00,0x01,0xFF,0xFE,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x01,0xFF,0xFE,0x00,0x01,0xCF,0xCE,0x00,0x01,0x87,0x86,0x00,0x01,0x87,0x86,0x00,0x01,0xCF,0xCE,0x00,0x01,0xFF,0xFE,0x00,0x00,0x70,0x38,0x00,0x00,0x70,0x38,0x00,0x00,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ] +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x7F,0xFC,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x40,0x04,0x00,0x00,0x7F,0xFC,0x00,0x00,0x47,0x8C,0x00,0x00,0x47,0x8C,0x00,0x00,0x47,0x8C,0x00,0x00,0x7F,0xFC,0x00,0x00,0x30,0x18,0x00,0x00,0x20,0x08,0x00,0x00,0x40,0x04,0x00,0x01,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x07,0x80,0x00,0x01,0x07,0x80,0x00,0x01,0x87,0xC0,0x00,0x01,0x87,0xC0,0x00,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x01,0x87,0xC0,0x00,0x01,0x87,0x80,0x00,0x01,0x07,0x80,0x00,0x00,0x07,0x80,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // _ + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x0F,0xFF,0xC0,0x00,0x0F,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0x00,0x0F,0xFF,0xF8,0x80,0x0F,0xFF,0xF8,0x80,0x0F,0xFF,0xF8,0x80,0x0F,0xFF,0xF8,0x40,0x00,0x00,0x3F,0xC0,0x0F,0xFF,0xFF,0xC0,0x0F,0x01,0xF9,0xC0,0x0E,0xC6,0xF6,0xC0,0x0D,0xEF,0x6F,0x40,0x01,0xEF,0x0F,0x00,0x00,0xC6,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x06,0x60,0x00,0x00,0x08,0x20,0x00,0x00,0x1E,0x20,0x00,0x00,0x6E,0x40,0x00,0x00,0xB5,0x80,0x00,0x03,0x4B,0x00,0x00,0x04,0x94,0x00,0x00,0x1B,0x68,0x00,0x00,0x24,0xB0,0x00,0x00,0x5B,0x40,0x00,0x01,0xA5,0x80,0x00,0x01,0x5A,0x00,0x00,0x02,0x6C,0x00,0x00,0x04,0x50,0x00,0x00,0x0C,0xE0,0x00,0x00,0x0F,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xF0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x33,0x80,0x00,0x00,0x47,0x80,0x00,0x00,0x8E,0x63,0xF0,0x01,0x1C,0x1E,0x70,0x01,0x38,0x02,0x70,0x02,0x38,0x02,0x70,0x02,0x7B,0x02,0x70,0x04,0x7C,0x02,0x70,0x04,0x80,0x02,0x70,0x07,0x80,0x06,0x70,0x0B,0x7F,0xFB,0xF0,0x0A,0x00,0x00,0x70,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // b +0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x05,0xF0,0x00,0x00,0x0F,0x60,0x00,0x00,0x0D,0xC0,0x00,0x00,0x0F,0x60,0x00,0x00,0x0B,0xC0,0x00,0x00,0x16,0x80,0x00,0x00,0x12,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFC,0x00,0x00,0x18,0x1C,0x00,0x00,0x3F,0xE4,0x00,0x00,0x20,0x24,0x00,0x00,0x27,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x3F,0xE4,0x00,0x00,0x20,0x24,0x00,0x00,0x27,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x20,0x28,0x00,0x00,0x20,0x30,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0x20,0x10,0x00,0x00,0x20,0x10,0x00,0x00,0x30,0x50,0x00,0x00,0x2F,0xD0,0x00,0x00,0x17,0xE0,0x00,0x00,0x13,0xA0,0x00,0x00,0x0B,0x40,0x00,0x00,0x05,0x80,0x00,0x00,0x05,0x80,0x00,0x00,0x09,0x40,0x00,0x00,0x11,0x20,0x00,0x00,0x11,0x20,0x00,0x00,0x21,0x10,0x00,0x00,0x27,0x90,0x00,0x00,0x2F,0xD0,0x00,0x00,0x2F,0xD0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFD,0xFF,0x00,0x0C,0x07,0x01,0x80,0x3C,0x02,0x01,0xE0,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x34,0x02,0x01,0x60,0x37,0xFA,0xFF,0x60,0x38,0x07,0x01,0x60,0x38,0x02,0x00,0xE0,0x3F,0xFA,0xFF,0xE0,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x3E,0x00,0x00,0x80,0x24,0x00,0x00,0x80,0x28,0x00,0x00,0x80,0x30,0x00,0x00,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // g +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0xBF,0x82,0x00,0x00,0x80,0x02,0x00,0x00,0x80,0x02,0x00,0x00,0xBF,0xFA,0x00,0x00,0xBF,0xFA,0x00,0x00,0x80,0x02,0x00,0x00,0xBF,0xFA,0x00,0x00,0x80,0x02,0x00,0x00,0xBF,0xFA,0x00,0x00,0x80,0x02,0x00,0x00,0xBF,0xBE,0x00,0x00,0x80,0x24,0x00,0x00,0x80,0x28,0x00,0x00,0x80,0x30,0x00,0x00,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // h +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x08,0x00,0x80,0x00,0x08,0x00,0x80,0x00,0x7F,0xFC,0x80,0x00,0x40,0x04,0x80,0x01,0xFF,0xF4,0x80,0x01,0x00,0x14,0x80,0x01,0x00,0x14,0x80,0x01,0x7F,0x94,0x80,0x01,0x00,0x14,0x80,0x01,0x7F,0x94,0x80,0x01,0x00,0x14,0x80,0x01,0x7F,0x94,0x80,0x01,0x00,0x14,0x80,0x01,0x00,0x14,0x80,0x01,0x7F,0x94,0x80,0x01,0x00,0x14,0x80,0x01,0x7F,0x97,0x80,0x01,0x00,0x14,0x00,0x01,0x7E,0x14,0x00,0x01,0x00,0x1C,0x00,0x01,0xFF,0xF0,0x00, // i +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xE0,0x08,0x00,0x00,0x20,0x08,0x00,0x03,0xA0,0x09,0xFC,0x03,0xA0,0x08,0x00,0x03,0xA0,0x09,0xFC,0x03,0xA0,0x08,0x00,0x03,0xA0,0x08,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x09,0xFF,0xF8,0x20,0x08,0x00,0x00,0x20,0x09,0xFF,0xF8,0x20,0x08,0x00,0x00,0x20,0x09,0xFF,0xF8,0x20,0x08,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x0F,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // j +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xE0,0x0C,0x00,0x00,0x60,0x0A,0x00,0x00,0xA0,0x09,0x00,0x01,0x20,0x08,0x80,0x02,0x20,0x08,0x40,0x04,0x20,0x08,0x20,0x08,0x20,0x08,0x10,0x10,0x20,0x08,0x08,0x20,0x20,0x08,0x0C,0x60,0x20,0x08,0x1A,0xB0,0x20,0x08,0x23,0x88,0x20,0x08,0x40,0x04,0x20,0x08,0x80,0x02,0x20,0x09,0x00,0x01,0x20,0x0A,0x00,0x00,0xA0,0x0C,0x00,0x00,0x60,0x0F,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // k +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFC,0x00,0x01,0xE0,0x1E,0x00,0x01,0xE0,0xDE,0x00,0x01,0xE0,0xDE,0x00,0x01,0xE0,0xDE,0x00,0x01,0xE0,0xDE,0x00,0x01,0xE0,0x1E,0x00,0x01,0xFF,0xFE,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0x80,0x06,0x00,0x01,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // l +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0x00,0x02,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x02,0x00,0x02,0x00,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x00,0x03,0xF8,0xFF,0x00,0x03,0xF0,0x7F,0x00,0x03,0xF0,0x7F,0x00,0x03,0xF0,0x7F,0x00,0x03,0xF8,0xFF,0x00,0x03,0xFF,0xFF,0x00,0x03,0xFC,0xFF,0x00,0x03,0xFC,0xFF,0x00,0x03,0xFC,0xFF,0x00,0x03,0xFC,0xFF,0x00,0x03,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // m +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x04,0xF8,0x7C,0x80,0x04,0x8C,0xC4,0x80,0x05,0x8C,0xC6,0x80,0x05,0x8C,0xC6,0x80,0x04,0xFC,0xFC,0x80,0x04,0xF8,0x7C,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x06,0xFF,0xFD,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // n +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x3E,0x30,0x00,0x00,0x7E,0x08,0x00,0x00,0xFE,0x04,0x00,0x01,0x78,0x02,0x00,0x01,0xF7,0x82,0x00,0x02,0xF8,0x61,0x00,0x03,0xF0,0x31,0x00,0x03,0xE3,0x11,0x00,0x03,0xE3,0x1F,0x00,0x02,0x23,0x1F,0x00,0x02,0x10,0x3F,0x00,0x01,0x18,0x7E,0x00,0x01,0x07,0xFE,0x00,0x00,0x81,0xFC,0x00,0x00,0x41,0xF8,0x00,0x00,0x31,0xF0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // o + +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x31,0xF0,0x00,0x00,0x5F,0xF8,0x00,0x00,0xA7,0xFC,0x00,0x01,0xD9,0xFE,0x00,0x01,0xA7,0xFE,0x00,0x01,0xD8,0x3E,0x00,0x03,0xA0,0x1F,0x00,0x03,0xA3,0x1F,0x00,0x03,0xE3,0x1F,0x00,0x03,0xE3,0x1D,0x00,0x01,0xE0,0x2E,0x00,0x01,0xF0,0x3A,0x00,0x01,0xFF,0xEA,0x00,0x00,0xFE,0x74,0x00,0x00,0x7F,0xC8,0x00,0x00,0x3E,0x30,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // p +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFE,0x00,0x01,0x00,0x02,0x00,0x01,0x7F,0xFE,0x00,0x01,0x40,0x06,0x00,0x01,0x40,0x06,0x00,0x01,0x40,0x06,0x00,0x01,0x40,0x06,0x00,0x01,0x40,0x06,0x00,0x01,0x40,0x06,0x00,0x01,0x40,0x06,0x00,0x01,0x7F,0xFE,0x00,0x01,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x01,0x00,0x01,0x00,0x03,0x6F,0x79,0x80,0x02,0xDF,0xBC,0x80,0x02,0x00,0x00,0x80,0x03,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // q +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xFE,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xC0,0x10,0x00,0x00,0x40,0x10,0x00,0x00,0x40,0x17,0xBD,0xED,0xC0,0x10,0x00,0x00,0x40,0x17,0xBD,0xED,0xC0,0x10,0x00,0x00,0x40,0x17,0x7E,0xED,0xC0,0x10,0x00,0x00,0x40,0x10,0x00,0x00,0x40,0x1F,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // r +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x40,0x08,0x00,0x00,0x40,0x08,0x00,0x00,0x40,0x08,0x00,0x00,0x40,0x7F,0x00,0x00,0x40,0x89,0x80,0x00,0x40,0x88,0x80,0x03,0x80,0xFF,0x80,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,0xC1,0x80,0x00,0x00,0x63,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // s +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x01,0x00,0x01,0x00,0x01,0x3F,0xF9,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // t +0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x07,0xC0,0x00,0x00,0x0B,0xA0,0x00,0x00,0x0B,0xA0,0x00,0x00,0x09,0x20,0x00,0x00,0x09,0x20,0x00,0x00,0x07,0xC0,0x00,0x00,0x05,0x20,0x00,0x00,0x1A,0x20,0x00,0x00,0x13,0x10,0x00,0x00,0x12,0x90,0x00,0x00,0x1C,0x78,0x00,0x00,0x1C,0x38,0x00,0x00,0x1C,0x38,0x00,0x00,0x1C,0x38,0x00,0x00,0x1C,0x38,0x00,0x00,0x0C,0x30,0x00,0x00,0x0E,0x70,0x00,0x00,0x06,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // u +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x70,0x00,0x00,0x25,0x78,0x00,0x00,0x27,0xF8,0x00,0x00,0x1F,0xF0,0x00,0x00,0x7F,0xE0,0x00,0x00,0xFF,0x80,0x00,0x01,0xFF,0x80,0x00,0x01,0xFC,0x80,0x00,0x00,0xF2,0x40,0x00,0x00,0xE2,0x20,0x00,0x00,0x01,0x20,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // v +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x47,0x80,0x00,0x00,0x88,0x00,0x00,0x03,0x07,0x80,0x01,0xEC,0x21,0x00,0x02,0x10,0xDE,0x00,0x07,0x83,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0xC8,0x00,0x00,0x07,0x90,0x00,0x00,0x02,0x10,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // w +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x3F,0x80,0x00,0x00,0x7F,0x80,0x00,0x00,0x7F,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0x60,0x00,0x00,0x02,0xA0,0x00,0x00,0x05,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0xD0,0x00,0x00,0x01,0x20,0x00,0x00,0x02,0x20,0x00,0x00,0x02,0x40,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // x +0x00,0x0F,0xFC,0x00,0x00,0x08,0x06,0x00,0x00,0x0B,0xF7,0x00,0x00,0x08,0x00,0x80,0x00,0x0B,0xFE,0x80,0x00,0x08,0x00,0x80,0x07,0xFB,0xFE,0xC0,0x06,0x48,0x00,0xC0,0x06,0x4B,0x80,0xC0,0x06,0x48,0x00,0xC0,0x06,0x5F,0xFF,0xC0,0x06,0x50,0x00,0x40,0x06,0x50,0x6F,0x40,0x06,0x50,0x6F,0x40,0x06,0x50,0x6F,0x40,0x06,0x57,0x6F,0x40,0x06,0x57,0x6F,0x40,0x06,0x57,0x6F,0x40,0x07,0xD0,0x00,0x40,0x07,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // y +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x80,0x38,0x00,0x00,0x80,0x3C,0x00,0x00,0x80,0x3C,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x04,0x00,0x03,0xFF,0xFF,0x00,0x02,0x00,0x01,0x00,0x0F,0xFF,0xFF,0xC0,0x09,0x24,0x80,0x40,0x09,0x24,0x80,0x40,0x09,0xFF,0x80,0x40,0x08,0x00,0x00,0x40,0x08,0x00,0x00,0x40,0x0F,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // z +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x7B,0xE0,0x00,0x00,0x7A,0x20,0x00,0x00,0x7A,0x20,0x00,0x00,0xFE,0x3C,0x00,0x00,0x80,0x04,0x00,0x03,0xBF,0x77,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x03,0xFF,0xFF,0x00,0x01,0xFF,0xFE,0x00,0x01,0xFF,0xFC,0x00,0x01,0xFF,0xFC,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x0D,0x80,0x00,0x00,0x1A,0xC0,0x00,0x00,0x15,0x40,0x00,0x00,0x17,0x40,0x00,0x00,0x12,0x40,0x00,0x00,0x67,0x30,0x00,0x00,0xD2,0x58,0x00,0x01,0x97,0x4C,0x00,0x02,0x17,0x42,0x00,0x02,0x12,0x42,0x00,0x02,0x18,0xC2,0x00,0x03,0xE7,0x3E,0x00,0x03,0xE7,0x3E,0x00,0x00,0x3D,0xE0,0x00,0x00,0x3D,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xC0,0x00,0x00,0x3D,0xE0,0x00,0x00,0x0A,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, // | +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x77,0xFF,0xC0,0x00,0x37,0xFD,0xC0,0x00,0x2F,0xF8,0x00,0x03,0xEF,0xE7,0x00,0x04,0x67,0xE8,0x80,0x08,0x93,0xD0,0x40,0x09,0x91,0xFE,0x40,0x0B,0xD0,0xFE,0x40,0x09,0x10,0x10,0x40,0x04,0x20,0x08,0x80,0x03,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // } +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x1F,0xF0,0x00,0x00,0x34,0x30,0x00,0x03,0xE4,0x4F,0x80,0x06,0x72,0x5C,0xC0,0x0C,0x5A,0x94,0x60,0x08,0xC9,0xA6,0x20,0x08,0x89,0xFE,0x20,0x08,0x08,0x20,0x20,0x0C,0x10,0x10,0x60,0x06,0x30,0x18,0xC0,0x03,0xE0,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ +}; diff --git a/libraries/UTFT_Buttons/hardware/arm/HW_ARM_defines.h b/libraries/UTFT_Buttons/hardware/arm/HW_ARM_defines.h new file mode 100644 index 0000000..d97e072 --- /dev/null +++ b/libraries/UTFT_Buttons/hardware/arm/HW_ARM_defines.h @@ -0,0 +1 @@ +#define bitmapdatatype unsigned short* diff --git a/libraries/UTFT_Buttons/hardware/avr/HW_AVR_defines.h b/libraries/UTFT_Buttons/hardware/avr/HW_AVR_defines.h new file mode 100644 index 0000000..767d242 --- /dev/null +++ b/libraries/UTFT_Buttons/hardware/avr/HW_AVR_defines.h @@ -0,0 +1 @@ +#define bitmapdatatype unsigned int* diff --git a/libraries/UTFT_Buttons/hardware/pic32/HW_PIC32_defines.h b/libraries/UTFT_Buttons/hardware/pic32/HW_PIC32_defines.h new file mode 100644 index 0000000..05a1580 --- /dev/null +++ b/libraries/UTFT_Buttons/hardware/pic32/HW_PIC32_defines.h @@ -0,0 +1,2 @@ +#define bitmapdatatype unsigned short* + diff --git a/libraries/UTFT_Buttons/keywords.txt b/libraries/UTFT_Buttons/keywords.txt new file mode 100644 index 0000000..31c2cbf --- /dev/null +++ b/libraries/UTFT_Buttons/keywords.txt @@ -0,0 +1,22 @@ +UTFT_Buttons KEYWORD1 + +addButton KEYWORD2 +drawButtons KEYWORD2 +drawButton KEYWORD2 +enableButton KEYWORD2 +disableButton KEYWORD2 +relabelButton KEYWORD2 +buttonEnabled KEYWORD2 +deleteButton KEYWORD2 +deleteAllButtons KEYWORD2 +checkButtons KEYWORD2 +setTextFont KEYWORD2 +setSymbolFont KEYWORD2 +setButtonColors KEYWORD2 + +BUTTON_DISABLED LITERAL1 +BUTTON_SYMBOL LITERAL1 +BUTTON_SYMBOL_REP_3X LITERAL1 +BUTTON_BITMAP LITERAL1 +BUTTON_NO_BORDER LITERAL1 +BUTTON_UNUSED LITERAL1 diff --git a/libraries/UTFT_Buttons/version.txt b/libraries/UTFT_Buttons/version.txt new file mode 100644 index 0000000..877994d --- /dev/null +++ b/libraries/UTFT_Buttons/version.txt @@ -0,0 +1,3 @@ +Version: + 1.0 24 May 2013 - initial release + 1.01 08 Sep 2014 - fixed compatibility-issues with Arduino 1.5.7 diff --git a/libraries/UTouch/License - CC BY-NC-SA 3.0 - Legal.pdf b/libraries/UTouch/License - CC BY-NC-SA 3.0 - Legal.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed326c9d62012e183e6190ca9bf7bfdaec7ed4ed GIT binary patch literal 150761 zcma&N19&A}vj!U5c6N-3ZQHhO+qP{^Ji)}aZQIU76HanxzVrR(|L=Xid(P?S*}Hpp zuUfTM)mv{@uj);vAR}-tm@&G0_dQku)69W@FE4>_monGb7B^CxYdI^9wfR&j6z{Je1%f|Z`?n4eQ)7D*Qw2jOTj$>zh3#!zZS9-^tn>;_rY4rgF7{5p74h-Wi`p4G zc{;cNm{@*`D$$Es+PIiH(Tmv_x|se~5A>2E+B~A1oD7_dV$6&Tf{aXTEDW4%3}Q^I zVj>LeVhn5|3?h6y%$!2Z%z|vf%*;aULM$vyg3OE@LW~?@f=q&J>?|UJe7f|Kb|$7C z+Q04adlJ8YnAroEnEp~KV`^vaVgX=e;P^8-xBr?nJH3*<{qJ$H{?$bJx3K_h4D>3V z4yN=PN~UJ?>e`F|W&q=Fb2z&=nHt){!&qz^8JQR$85kHD7T>B{uK96g9ZR&hP;yCn|jmlq5sa+=C*;UZ4wF)lme@OQXlfIycj&pzdZyG!^-(@@BEXU0gN0R^#8I2D=WS7Zx1p4dwM$dWcAq>r-?vi?S~Gd z)w)hosp+TPPxnDM(siOcvq=cGUW~D_=6vDLBWkA%4tj?7FW%_8_*76Qrxaki!PbZc zSiGnuWdn=~6Cz<()J`}rNA!nf^iCuTXjcT|wApu7mV{+VF#ykAWd1AtD#{2mS4k8% z_QY@3;k#0Y$c)uUc6F%rd`UCNR@93NK0nDvvu3{DO%J1{js1f){=(DWa2FQ)jX-4= zlfU+Yt}Yg$Zl-oF^dk1g@(!kU^ul7Y^lD81J##j`-`l@{sO(~BXJY7N^50jPIOydm zk*VM2k_{kq?7$n0eRjg`RN5T9qG5lgq7(|}`iUCa&Qj4U0B9MRSs3V*04%>%+lu{{ z{@>qD|2kBq44%K;*e@BQd(RH7(}S(}4)p)osOZ%IEdLI-zo7W{lw?g^3{4DO41Z(w zFMKK(nw!cPdfL0X(97GI{#Ufo|2gRlU}F5M#b3x3{w-o-Z~h;B{zt?L+uOPPwu`g& z??C?@ivZ@o1Od!{1qp!p4}bhV`B$6*nEz4>VE!Zi`y~6Hoi4qwlf8qGy@xgf-R~ZL ze^@zL>3)lIurShbGU?KbJK4KB09ZNxG^UsRO#_DiL*w7f@p~};8oiRKv%Ra6vFYDj zV(+BvU}$Xmhgg&u04#s0|9!{^VEL=_KfL1MBL3TXE`QpH|7r6F{7Qcu`+JtZ >V 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⎻-tUSZ|(H0NjqB5L}S~$db>mU`T|jN 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 Dw3!jg literal 0 HcmV?d00001 diff --git a/libraries/UTouch/License - CC BY-NC-SA 3.0 - Summary.pdf b/libraries/UTouch/License - CC BY-NC-SA 3.0 - Summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b35e677e66c08dbb9caccc1c135051624b16b0d7 GIT binary patch literal 109586 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%0Aw`tglGsl`4d>k#@@?6B) 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 g@OZxgFA`CAsDFt1M#e8bpQYW literal 0 HcmV?d00001 diff --git a/libraries/UTouch/UTouch.cpp b/libraries/UTouch/UTouch.cpp new file mode 100644 index 0000000..f5aad74 --- /dev/null +++ b/libraries/UTouch/UTouch.cpp @@ -0,0 +1,262 @@ +/* + UTouch.cpp - Arduino/chipKit library support for Color TFT LCD Touch screens + Copyright (C)2010-2014 Henning Karlsen. All right reserved + + Basic functionality of this library are based on the demo-code provided by + ITead studio. You can find the latest version of the library at + http://www.henningkarlsen.com/electronics + + If you make any modifications or improvements to the code, I would appreciate + that you share the code with me so that I might include it in the next release. + I can be contacted through http://www.henningkarlsen.com/electronics/contact.php + + This library is free software; you can redistribute it and/or + modify it under the terms of the CC BY-NC-SA 3.0 license. + Please see the included documents for further information. + + Commercial use of this library requires you to buy a license that + will allow commercial use. This includes using the library, + modified or not, as a tool to sell products. + + The license applies to all part of the library including the + examples and tools supplied with the library. +*/ + +#include "UTouch.h" +#include "UTouchCD.h" + +#if defined(__AVR__) + #include "hardware/avr/HW_AVR.inc" +#elif defined(__PIC32MX__) + #include "hardware/pic32/HW_PIC32.inc" +#elif defined(__arm__) + #include "hardware/arm/HW_ARM.inc" +#endif + +UTouch::UTouch(byte tclk, byte tcs, byte din, byte dout, byte irq) +{ + T_CLK = tclk; + T_CS = tcs; + T_DIN = din; + T_DOUT = dout; + T_IRQ = irq; +} + +void UTouch::InitTouch(byte orientation) +{ + orient = orientation; + _default_orientation = CAL_S>>31; + touch_x_left = (CAL_X>>14) & 0x3FFF; + touch_x_right = CAL_X & 0x3FFF; + touch_y_top = (CAL_Y>>14) & 0x3FFF; + touch_y_bottom = CAL_Y & 0x3FFF; + disp_x_size = (CAL_S>>12) & 0x0FFF; + disp_y_size = CAL_S & 0x0FFF; + prec = 10; + + P_CLK = portOutputRegister(digitalPinToPort(T_CLK)); + B_CLK = digitalPinToBitMask(T_CLK); + P_CS = portOutputRegister(digitalPinToPort(T_CS)); + B_CS = digitalPinToBitMask(T_CS); + P_DIN = portOutputRegister(digitalPinToPort(T_DIN)); + B_DIN = digitalPinToBitMask(T_DIN); + P_DOUT = portInputRegister(digitalPinToPort(T_DOUT)); + B_DOUT = digitalPinToBitMask(T_DOUT); + P_IRQ = portInputRegister(digitalPinToPort(T_IRQ)); + B_IRQ = digitalPinToBitMask(T_IRQ); + + pinMode(T_CLK, OUTPUT); + pinMode(T_CS, OUTPUT); + pinMode(T_DIN, OUTPUT); + pinMode(T_DOUT, INPUT); + pinMode(T_IRQ, OUTPUT); + + sbi(P_CS, B_CS); + sbi(P_CLK, B_CLK); + sbi(P_DIN, B_DIN); + sbi(P_IRQ, B_IRQ); +} + +void UTouch::read() +{ + unsigned long tx=0, temp_x=0; + unsigned long ty=0, temp_y=0; + unsigned long minx=99999, maxx=0; + unsigned long miny=99999, maxy=0; + int datacount=0; + + cbi(P_CS, B_CS); + + pinMode(T_IRQ, INPUT); + for (int i=0; i0) and (temp_x<4096) and (temp_y>0) and (temp_y<4096)) + { + tx+=temp_x; + ty+=temp_y; + if (prec>5) + { + if (temp_xmaxx) + maxx=temp_x; + if (temp_ymaxy) + maxy=temp_y; + } + datacount++; + } + } + } + } + pinMode(T_IRQ, OUTPUT); + + if (prec>5) + { + tx = tx-(minx+maxx); + ty = ty-(miny+maxy); + datacount -= 2; + } + + sbi(P_CS, B_CS); + if ((datacount==(prec-2)) or (datacount==PREC_LOW)) + { + if (orient == _default_orientation) + { + TP_X=ty/datacount; + TP_Y=tx/datacount; + } + else + { + TP_X=tx/datacount; + TP_Y=ty/datacount; + } + } + else + { + TP_X=-1; + TP_Y=-1; + } +} + +bool UTouch::dataAvailable() +{ + bool avail; + pinMode(T_IRQ, INPUT); + avail = !(rbi(P_IRQ, B_IRQ)); + pinMode(T_IRQ, OUTPUT); + return avail; +} + +int16_t UTouch::getX() +{ + long c; + + if ((TP_X==-1) or (TP_Y==-1)) + return -1; + if (orient == _default_orientation) + { + c = long(long(TP_X - touch_x_left) * (disp_x_size)) / long(touch_x_right - touch_x_left); + if (c<0) + c = 0; + if (c>disp_x_size) + c = disp_x_size; + } + else + { + if (_default_orientation == PORTRAIT) + c = long(long(TP_X - touch_y_top) * (-disp_y_size)) / long(touch_y_bottom - touch_y_top) + long(disp_y_size); + else + c = long(long(TP_X - touch_y_top) * (disp_y_size)) / long(touch_y_bottom - touch_y_top); + if (c<0) + c = 0; + if (c>disp_y_size) + c = disp_y_size; + } + return c; +} + +int16_t UTouch::getY() +{ + int c; + + if ((TP_X==-1) or (TP_Y==-1)) + return -1; + if (orient == _default_orientation) + { + c = long(long(TP_Y - touch_y_top) * (disp_y_size)) / long(touch_y_bottom - touch_y_top); + if (c<0) + c = 0; + if (c>disp_y_size) + c = disp_y_size; + } + else + { + if (_default_orientation == PORTRAIT) + c = long(long(TP_Y - touch_x_left) * (disp_x_size)) / long(touch_x_right - touch_x_left); + else + c = long(long(TP_Y - touch_x_left) * (-disp_x_size)) / long(touch_x_right - touch_x_left) + long(disp_x_size); + if (c<0) + c = 0; + if (c>disp_x_size) + c = disp_x_size; + } + return c; +} + +void UTouch::setPrecision(byte precision) +{ + switch (precision) + { + case PREC_LOW: + prec=1; // DO NOT CHANGE! + break; + case PREC_MEDIUM: + prec=12; // Iterations + 2 + break; + case PREC_HI: + prec=27; // Iterations + 2 + break; + case PREC_EXTREME: + prec=102; // Iterations + 2 + break; + default: + prec=12; // Iterations + 2 + break; + } +} + +void UTouch::calibrateRead() +{ + unsigned long tx=0; + unsigned long ty=0; + + cbi(P_CS, B_CS); + + touch_WriteData(0x90); + pulse_high(P_CLK, B_CLK); + tx=touch_ReadData(); + + touch_WriteData(0xD0); + pulse_high(P_CLK, B_CLK); + ty=touch_ReadData(); + + sbi(P_CS, B_CS); + + TP_X=ty; + TP_Y=tx; +} + diff --git a/libraries/UTouch/UTouch.h b/libraries/UTouch/UTouch.h new file mode 100644 index 0000000..a087db7 --- /dev/null +++ b/libraries/UTouch/UTouch.h @@ -0,0 +1,80 @@ +/* + UTouch.h - Arduino/chipKit library support for Color TFT LCD Touch screens + Copyright (C)2010-2014 Henning Karlsen. All right reserved + + Basic functionality of this library are based on the demo-code provided by + ITead studio. You can find the latest version of the library at + http://www.henningkarlsen.com/electronics + + If you make any modifications or improvements to the code, I would appreciate + that you share the code with me so that I might include it in the next release. + I can be contacted through http://www.henningkarlsen.com/electronics/contact.php + + This library is free software; you can redistribute it and/or + modify it under the terms of the CC BY-NC-SA 3.0 license. + Please see the included documents for further information. + + Commercial use of this library requires you to buy a license that + will allow commercial use. This includes using the library, + modified or not, as a tool to sell products. + + The license applies to all part of the library including the + examples and tools supplied with the library. +*/ + +#ifndef UTouch_h +#define UTouch_h + +#define UTOUCH_VERSION 124 + +#if defined(__AVR__) + #include "Arduino.h" + #include "hardware/avr/HW_AVR_defines.h" +#elif defined(__PIC32MX__) + #include "WProgram.h" + #include "hardware/pic32/HW_PIC32_defines.h" +#elif defined(__arm__) + #include "Arduino.h" + #include "hardware/arm/HW_ARM_defines.h" +#endif + +#define PORTRAIT 0 +#define LANDSCAPE 1 + +#define PREC_LOW 1 +#define PREC_MEDIUM 2 +#define PREC_HI 3 +#define PREC_EXTREME 4 + +class UTouch +{ + public: + int16_t TP_X ,TP_Y; + + UTouch(byte tclk, byte tcs, byte tdin, byte dout, byte irq); + + void InitTouch(byte orientation = LANDSCAPE); + void read(); + bool dataAvailable(); + int16_t getX(); + int16_t getY(); + void setPrecision(byte precision); + + void calibrateRead(); + + private: + regtype *P_CLK, *P_CS, *P_DIN, *P_DOUT, *P_IRQ; + regsize B_CLK, B_CS, B_DIN, B_DOUT, B_IRQ; + byte T_CLK, T_CS, T_DIN, T_DOUT, T_IRQ; + long _default_orientation; + byte orient; + byte prec; + byte display_model; + long disp_x_size, disp_y_size, default_orientation; + long touch_x_left, touch_x_right, touch_y_top, touch_y_bottom; + + void touch_WriteData(byte data); + word touch_ReadData(); +}; + +#endif \ No newline at end of file diff --git a/libraries/UTouch/UTouchCD.h b/libraries/UTouch/UTouchCD.h new file mode 100644 index 0000000..de55930 --- /dev/null +++ b/libraries/UTouch/UTouchCD.h @@ -0,0 +1,21 @@ +// UTouchCD.h +// ---------- +// +// Since there are slight deviations in all touch screens you should run a +// calibration on your display module. Run the UTouch_Calibration sketch +// that came with this library and follow the on-screen instructions to +// update this file. +// +// Remember that is you have multiple display modules they will probably +// require different calibration data so you should run the calibration +// every time you switch to another module. +// You can, of course, store calibration data for all your modules here +// and comment out the ones you dont need at the moment. +// + +// These calibration settings works with my ITDB02-3.2S. +// They MIGHT work on your display module, but you should run the +// calibration sketch anyway. +#define CAL_X 0x00378F66UL +#define CAL_Y 0x03C34155UL +#define CAL_S 0x000EF13FUL diff --git a/libraries/UTouch/examples/Arduino/UTouch_ButtonTest/UTouch_ButtonTest.ino b/libraries/UTouch/examples/Arduino/UTouch_ButtonTest/UTouch_ButtonTest.ino new file mode 100644 index 0000000..35b842c --- /dev/null +++ b/libraries/UTouch/examples/Arduino/UTouch_ButtonTest/UTouch_ButtonTest.ino @@ -0,0 +1,253 @@ +// UTouch_ButtonTest (C)2010-2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a quick demo of how create and use buttons. +// +// This program requires the UTFT library. +// +// It is assumed that the display module is connected to an +// appropriate shield or that you know how to change the pin +// numbers in the setup. +// + +#include +#include + +// Initialize display +// ------------------ +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : ,19,18,17,16 +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +// Initialize touchscreen +// ---------------------- +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : 15,10,14, 9, 8 +// Standard Arduino Mega/Due shield : 6, 5, 4, 3, 2 +// CTE TFT LCD/SD Shield for Arduino Due : 6, 5, 4, 3, 2 +// Teensy 3.x TFT Test Board : 26,31,27,28,29 +// ElecHouse TFT LCD/SD Shield for Arduino Due : 25,26,27,29,30 +// +UTouch myTouch( 6, 5, 4, 3, 2); + +// Declare which fonts we will be using +extern uint8_t BigFont[]; + +int x, y; +char stCurrent[20]=""; +int stCurrentLen=0; +char stLast[20]=""; + +/************************* +** Custom functions ** +*************************/ + +void drawButtons() +{ +// Draw the upper row of buttons + for (x=0; x<5; x++) + { + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (10+(x*60), 10, 60+(x*60), 60); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (10+(x*60), 10, 60+(x*60), 60); + myGLCD.printNumI(x+1, 27+(x*60), 27); + } +// Draw the center row of buttons + for (x=0; x<5; x++) + { + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (10+(x*60), 70, 60+(x*60), 120); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (10+(x*60), 70, 60+(x*60), 120); + if (x<4) + myGLCD.printNumI(x+6, 27+(x*60), 87); + } + myGLCD.print("0", 267, 87); +// Draw the lower row of buttons + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (10, 130, 150, 180); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (10, 130, 150, 180); + myGLCD.print("Clear", 40, 147); + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (160, 130, 300, 180); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (160, 130, 300, 180); + myGLCD.print("Enter", 190, 147); + myGLCD.setBackColor (0, 0, 0); +} + +void updateStr(int val) +{ + if (stCurrentLen<20) + { + stCurrent[stCurrentLen]=val; + stCurrent[stCurrentLen+1]='\0'; + stCurrentLen++; + myGLCD.setColor(0, 255, 0); + myGLCD.print(stCurrent, LEFT, 224); + } + else + { + myGLCD.setColor(255, 0, 0); + myGLCD.print("BUFFER FULL!", CENTER, 192); + delay(500); + myGLCD.print(" ", CENTER, 192); + delay(500); + myGLCD.print("BUFFER FULL!", CENTER, 192); + delay(500); + myGLCD.print(" ", CENTER, 192); + myGLCD.setColor(0, 255, 0); + } +} + +// Draw a red frame while a button is touched +void waitForIt(int x1, int y1, int x2, int y2) +{ + myGLCD.setColor(255, 0, 0); + myGLCD.drawRoundRect (x1, y1, x2, y2); + while (myTouch.dataAvailable()) + myTouch.read(); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (x1, y1, x2, y2); +} + +/************************* +** Required functions ** +*************************/ + +void setup() +{ +// Initial setup + myGLCD.InitLCD(); + myGLCD.clrScr(); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_MEDIUM); + + myGLCD.setFont(BigFont); + myGLCD.setBackColor(0, 0, 255); + drawButtons(); +} + +void loop() +{ + while (true) + { + if (myTouch.dataAvailable()) + { + myTouch.read(); + x=myTouch.getX(); + y=myTouch.getY(); + + if ((y>=10) && (y<=60)) // Upper row + { + if ((x>=10) && (x<=60)) // Button: 1 + { + waitForIt(10, 10, 60, 60); + updateStr('1'); + } + if ((x>=70) && (x<=120)) // Button: 2 + { + waitForIt(70, 10, 120, 60); + updateStr('2'); + } + if ((x>=130) && (x<=180)) // Button: 3 + { + waitForIt(130, 10, 180, 60); + updateStr('3'); + } + if ((x>=190) && (x<=240)) // Button: 4 + { + waitForIt(190, 10, 240, 60); + updateStr('4'); + } + if ((x>=250) && (x<=300)) // Button: 5 + { + waitForIt(250, 10, 300, 60); + updateStr('5'); + } + } + + if ((y>=70) && (y<=120)) // Center row + { + if ((x>=10) && (x<=60)) // Button: 6 + { + waitForIt(10, 70, 60, 120); + updateStr('6'); + } + if ((x>=70) && (x<=120)) // Button: 7 + { + waitForIt(70, 70, 120, 120); + updateStr('7'); + } + if ((x>=130) && (x<=180)) // Button: 8 + { + waitForIt(130, 70, 180, 120); + updateStr('8'); + } + if ((x>=190) && (x<=240)) // Button: 9 + { + waitForIt(190, 70, 240, 120); + updateStr('9'); + } + if ((x>=250) && (x<=300)) // Button: 0 + { + waitForIt(250, 70, 300, 120); + updateStr('0'); + } + } + + if ((y>=130) && (y<=180)) // Upper row + { + if ((x>=10) && (x<=150)) // Button: Clear + { + waitForIt(10, 130, 150, 180); + stCurrent[0]='\0'; + stCurrentLen=0; + myGLCD.setColor(0, 0, 0); + myGLCD.fillRect(0, 224, 319, 239); + } + if ((x>=160) && (x<=300)) // Button: Enter + { + waitForIt(160, 130, 300, 180); + if (stCurrentLen>0) + { + for (x=0; x +#include + +// Define the orientation of the touch screen. Further +// information can be found in the instructions. +#define TOUCH_ORIENTATION PORTRAIT + +// Initialize display +// ------------------ +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : ,19,18,17,16 +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +// Initialize touchscreen +// ---------------------- +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : 15,10,14, 9, 8 +// Standard Arduino Mega/Due shield : 6, 5, 4, 3, 2 +// CTE TFT LCD/SD Shield for Arduino Due : 6, 5, 4, 3, 2 +// Teensy 3.x TFT Test Board : 26,31,27,28,29 +// ElecHouse TFT LCD/SD Shield for Arduino Due : 25,26,27,29,30 +// +UTouch myTouch( 6, 5, 4, 3, 2); + +// ************************************ +// DO NOT EDIT ANYTHING BELOW THIS LINE +// ************************************ + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +uint32_t cx, cy; +uint32_t rx[8], ry[8]; +uint32_t clx, crx, cty, cby; +float px, py; +int dispx, dispy, text_y_center; +uint32_t calx, caly, cals; +char buf[13]; + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(SmallFont); + + myTouch.InitTouch(TOUCH_ORIENTATION); + dispx=myGLCD.getDisplayXSize(); + dispy=myGLCD.getDisplayYSize(); + text_y_center=(dispy/2)-6; +} + +void drawCrossHair(int x, int y) +{ + myGLCD.drawRect(x-10, y-10, x+10, y+10); + myGLCD.drawLine(x-5, y, x+5, y); + myGLCD.drawLine(x, y-5, x, y+5); +} + +void readCoordinates() +{ + int iter = 5000; + int failcount = 0; + int cnt = 0; + uint32_t tx=0; + uint32_t ty=0; + boolean OK = false; + + while (OK == false) + { + myGLCD.setColor(255, 255, 255); + myGLCD.print("* PRESS *", CENTER, text_y_center); + while (myTouch.dataAvailable() == false) {} + myGLCD.print("* HOLD! *", CENTER, text_y_center); + while ((myTouch.dataAvailable() == true) && (cnt=iter) + { + OK = true; + } + else + { + tx = 0; + ty = 0; + cnt = 0; + } + if (failcount>=10000) + fail(); + } + + cx = tx / iter; + cy = ty / iter; +} + +void calibrate(int x, int y, int i) +{ + myGLCD.setColor(255, 255, 255); + drawCrossHair(x,y); + myGLCD.setBackColor(255, 0, 0); + readCoordinates(); + myGLCD.setColor(255, 255, 255); + myGLCD.print("* RELEASE *", CENTER, text_y_center); + myGLCD.setColor(80, 80, 80); + drawCrossHair(x,y); + rx[i]=cx; + ry[i]=cy; + while (myTouch.dataAvailable() == true) {} +} + +void waitForTouch() +{ + while (myTouch.dataAvailable() == true) {} + while (myTouch.dataAvailable() == false) {} + while (myTouch.dataAvailable() == true) {} +} + +void toHex(uint32_t num) +{ + buf[0] = '0'; + buf[1] = 'x'; + buf[10] = 'U'; + buf[11] = 'L'; + buf[12] = 0; + for (int zz=9; zz>1; zz--) + { + if ((num & 0xF) > 9) + buf[zz] = (num & 0xF) + 55; + else + buf[zz] = (num & 0xF) + 48; + num=num>>4; + } +} + +void startup() +{ + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, dispx-1, 13); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.drawLine(0, 14, dispx-1, 14); + myGLCD.print("UTouch Calibration", CENTER, 1); + myGLCD.setBackColor(0, 0, 0); + + if (dispx==220) + { + myGLCD.print("Use a stylus or something", LEFT, 30); + myGLCD.print("similar to touch as close", LEFT, 42); + myGLCD.print("to the center of the", LEFT, 54); + myGLCD.print("highlighted crosshair as", LEFT, 66); + myGLCD.print("possible. Keep as still as", LEFT, 78); + myGLCD.print("possible and keep holding", LEFT, 90); + myGLCD.print("until the highlight is", LEFT, 102); + myGLCD.print("removed. Repeat for all", LEFT, 114); + myGLCD.print("crosshairs in sequence.", LEFT, 126); + myGLCD.print("Touch screen to continue", CENTER, 162); + } + else + { + myGLCD.print("INSTRUCTIONS", CENTER, 30); + myGLCD.print("Use a stylus or something similar to", LEFT, 50); + myGLCD.print("touch as close to the center of the", LEFT, 62); + myGLCD.print("highlighted crosshair as possible. Keep", LEFT, 74); + myGLCD.print("as still as possible and keep holding", LEFT, 86); + myGLCD.print("until the highlight is removed. Repeat", LEFT, 98); + myGLCD.print("for all crosshairs in sequence.", LEFT, 110); + + myGLCD.print("Further instructions will be displayed", LEFT, 134); + myGLCD.print("when the calibration is complete.", LEFT, 146); + + myGLCD.print("Do NOT use your finger as a calibration", LEFT, 170); + myGLCD.print("stylus or the result WILL BE imprecise.", LEFT, 182); + + myGLCD.print("Touch screen to continue", CENTER, 226); + } + + waitForTouch(); + myGLCD.clrScr(); +} + +void done() +{ + myGLCD.clrScr(); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, dispx-1, 13); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.drawLine(0, 14, dispx-1, 14); + myGLCD.print("UTouch Calibration", CENTER, 1); + myGLCD.setBackColor(0, 0, 0); + + if (dispx==220) + { + myGLCD.print("To use the new calibration", LEFT, 30); + myGLCD.print("settings you must edit the", LEFT, 42); + myGLCD.setColor(160, 160, 255); + myGLCD.print("UTouchCD.h", LEFT, 54); + myGLCD.setColor(255, 255, 255); + myGLCD.print("file and change", 88, 54); + myGLCD.print("the following values. The", LEFT, 66); + myGLCD.print("values are located right", LEFT, 78); + myGLCD.print("below the opening comment.", LEFT, 90); + myGLCD.print("CAL_X", LEFT, 110); + myGLCD.print("CAL_Y", LEFT, 122); + myGLCD.print("CAL_S", LEFT, 134); + toHex(calx); + myGLCD.print(buf, 75, 110); + toHex(caly); + myGLCD.print(buf, 75, 122); + toHex(cals); + myGLCD.print(buf, 75, 134); + } + else + { + myGLCD.print("CALIBRATION COMPLETE", CENTER, 30); + myGLCD.print("To use the new calibration", LEFT, 50); + myGLCD.print("settings you must edit the", LEFT, 62); + myGLCD.setColor(160, 160, 255); + myGLCD.print("UTouchCD.h", LEFT, 74); + myGLCD.setColor(255, 255, 255); + myGLCD.print("file and change", 88, 74); + myGLCD.print("the following values.", LEFT, 86); + myGLCD.print("The values are located right", LEFT, 98); + myGLCD.print("below the opening comment in", LEFT, 110); + myGLCD.print("the file.", LEFT, 122); + myGLCD.print("CAL_X", LEFT, 150); + myGLCD.print("CAL_Y", LEFT, 162); + myGLCD.print("CAL_S", LEFT, 174); + + toHex(calx); + myGLCD.print(buf, 75, 150); + toHex(caly); + myGLCD.print(buf, 75, 162); + toHex(cals); + myGLCD.print(buf, 75, 174); + } + +} + +void fail() +{ + myGLCD.clrScr(); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, dispx-1, 13); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.drawLine(0, 14, dispx-1, 14); + myGLCD.print("UTouch Calibration FAILED", CENTER, 1); + myGLCD.setBackColor(0, 0, 0); + + myGLCD.print("Unable to read the position", LEFT, 30); + myGLCD.print("of the press. This is a", LEFT, 42); + myGLCD.print("hardware issue and can", 88, 54); + myGLCD.print("not be corrected in", LEFT, 66); + myGLCD.print("software.", LEFT, 78); + + while(true) {}; +} + +void loop() +{ + startup(); + + myGLCD.setColor(80, 80, 80); + drawCrossHair(dispx-11, 10); + drawCrossHair(dispx/2, 10); + drawCrossHair(10, 10); + drawCrossHair(dispx-11, dispy/2); + drawCrossHair(10, dispy/2); + drawCrossHair(dispx-11, dispy-11); + drawCrossHair(dispx/2, dispy-11); + drawCrossHair(10, dispy-11); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("***********", CENTER, text_y_center-12); + myGLCD.print("***********", CENTER, text_y_center+12); + + calibrate(10, 10, 0); + calibrate(10, dispy/2, 1); + calibrate(10, dispy-11, 2); + calibrate(dispx/2, 10, 3); + calibrate(dispx/2, dispy-11, 4); + calibrate(dispx-11, 10, 5); + calibrate(dispx-11, dispy/2, 6); + calibrate(dispx-11, dispy-11, 7); + + if (TOUCH_ORIENTATION == LANDSCAPE) + cals=(long(dispx-1)<<12)+(dispy-1); + else + cals=(long(dispy-1)<<12)+(dispx-1); + + if (TOUCH_ORIENTATION == PORTRAIT) + px = abs(((float(rx[2]+rx[4]+rx[7])/3)-(float(rx[0]+rx[3]+rx[5])/3))/(dispy-20)); // PORTRAIT + else + px = abs(((float(rx[5]+rx[6]+rx[7])/3)-(float(rx[0]+rx[1]+rx[2])/3))/(dispy-20)); // LANDSCAPE + + if (TOUCH_ORIENTATION == PORTRAIT) + { + clx = (((rx[0]+rx[3]+rx[5])/3)); // PORTRAIT + crx = (((rx[2]+rx[4]+rx[7])/3)); // PORTRAIT + } + else + { + clx = (((rx[0]+rx[1]+rx[2])/3)); // LANDSCAPE + crx = (((rx[5]+rx[6]+rx[7])/3)); // LANDSCAPE + } + if (clx +#include + +// Initialize display +// ------------------ +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : ,19,18,17,16 +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +// Initialize touchscreen +// ---------------------- +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : 15,10,14, 9, 8 +// Standard Arduino Mega/Due shield : 6, 5, 4, 3, 2 +// CTE TFT LCD/SD Shield for Arduino Due : 6, 5, 4, 3, 2 +// Teensy 3.x TFT Test Board : 26,31,27,28,29 +// ElecHouse TFT LCD/SD Shield for Arduino Due : 25,26,27,29,30 +// +UTouch myTouch( 6, 5, 4, 3, 2); + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_MEDIUM); +} + +void loop() +{ + long x, y; + + while (myTouch.dataAvailable() == true) + { + myTouch.read(); + x = myTouch.getX(); + y = myTouch.getY(); + if ((x!=-1) and (y!=-1)) + { + myGLCD.drawPixel (x, y); + } + } +} + diff --git a/libraries/UTouch/examples/Arduino/UTouch_QuickPaint/UTouch_QuickPaint.ino b/libraries/UTouch/examples/Arduino/UTouch_QuickPaint/UTouch_QuickPaint.ino new file mode 100644 index 0000000..3ff70fc --- /dev/null +++ b/libraries/UTouch/examples/Arduino/UTouch_QuickPaint/UTouch_QuickPaint.ino @@ -0,0 +1,172 @@ +// UTouch_QuickPaint (C)2013-2014 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a quick demo of how to use the library. +// +// This program requires the UTFT library and a display +// module with at least 320x240 pixels resolution. +// +// It is assumed that the display module is connected to an +// appropriate shield or that you know how to change the pin +// numbers in the setup. +// + +#include +#include + +// Initialize display +// ------------------ +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : ,19,18,17,16 +// Standard Arduino Mega/Due shield : ,38,39,40,41 +// CTE TFT LCD/SD Shield for Arduino Due : ,25,26,27,28 +// Teensy 3.x TFT Test Board : ,23,22, 3, 4 +// ElecHouse TFT LCD/SD Shield for Arduino Due : ,22,23,31,33 +// +// Remember to change the model parameter to suit your display module! +UTFT myGLCD(ITDB32S,38,39,40,41); + +// Initialize touchscreen +// ---------------------- +// Set the pins to the correct ones for your development board +// ----------------------------------------------------------- +// Standard Arduino Uno/2009 Shield : 15,10,14, 9, 8 +// Standard Arduino Mega/Due shield : 6, 5, 4, 3, 2 +// CTE TFT LCD/SD Shield for Arduino Due : 6, 5, 4, 3, 2 +// Teensy 3.x TFT Test Board : 26,31,27,28,29 +// ElecHouse TFT LCD/SD Shield for Arduino Due : 25,26,27,29,30 +// +UTouch myTouch( 6, 5, 4, 3, 2); + +// Declare which fonts we will be using +extern uint8_t BigFont[]; + +int color = 0; +word colorlist[] = {VGA_WHITE, VGA_BLACK, VGA_RED, VGA_BLUE, VGA_GREEN, VGA_FUCHSIA, VGA_YELLOW, VGA_AQUA}; +int bsize = 4; + +void drawColorMarkerAndBrushSize(int col) +{ + myGLCD.setColor(VGA_BLACK); + myGLCD.fillRect(25, 0, 31, 239); + myGLCD.fillRect(myGLCD.getDisplayXSize()-31, 161, myGLCD.getDisplayXSize()-1, 191); + myGLCD.setColor(VGA_WHITE); + myGLCD.drawPixel(25, (col*30)+15); + for (int i=1; i<7; i++) + myGLCD.drawLine(25+i, ((col*30)+15)-i, 25+i, ((col*30)+15)+i); + + if (color==1) + myGLCD.setColor(VGA_WHITE); + else + myGLCD.setColor(colorlist[col]); + if (bsize==1) + myGLCD.drawPixel(myGLCD.getDisplayXSize()-15, 177); + else + myGLCD.fillCircle(myGLCD.getDisplayXSize()-15, 177, bsize); + + myGLCD.setColor(colorlist[col]); +} + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(BigFont); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_HI); + + myGLCD.setColor(VGA_WHITE); + myGLCD.drawLine(32,0,32,myGLCD.getDisplayYSize()-1); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,0,myGLCD.getDisplayXSize()-32,myGLCD.getDisplayYSize()-1); + myGLCD.print("C", myGLCD.getDisplayXSize()-24, 8); + myGLCD.print("L", myGLCD.getDisplayXSize()-24, 24); + myGLCD.print("E", myGLCD.getDisplayXSize()-24, 40); + myGLCD.print("A", myGLCD.getDisplayXSize()-24, 56); + myGLCD.print("R", myGLCD.getDisplayXSize()-24, 72); + myGLCD.print("+", myGLCD.getDisplayXSize()-24, 136); + myGLCD.print("-", myGLCD.getDisplayXSize()-24, 200); + myGLCD.fillRect(myGLCD.getDisplayXSize()-32,96,myGLCD.getDisplayXSize()-1,128); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,160,myGLCD.getDisplayXSize()-1,160); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,192,myGLCD.getDisplayXSize()-1,192); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,224,myGLCD.getDisplayXSize()-1,224); + for (int i=0; i<8; i++) + { + myGLCD.setColor(colorlist[i]); + myGLCD.fillRect(0, (i*30), 24, (((i+1)*30)-1)); + } + drawColorMarkerAndBrushSize(color); +} + +void loop() +{ + long x, y; + + while (myTouch.dataAvailable() == true) + { + myTouch.read(); + x = myTouch.getX(); + y = myTouch.getY(); + if ((x!=-1) and (y!=-1)) + { + if (x>(31+bsize) and (x128) and (y<160)) + { + if (bsize<7) + { + bsize++; + drawColorMarkerAndBrushSize(color); + while (myTouch.dataAvailable()) {}; + delay(50); + } + } + if ((y>160) and (y<192)) + { + bsize=4; + drawColorMarkerAndBrushSize(color); + while (myTouch.dataAvailable()) {}; + delay(50); + } + if ((y>192) and (y<224)) + { + if (bsize>1) + { + bsize--; + drawColorMarkerAndBrushSize(color); + while (myTouch.dataAvailable()) {}; + delay(50); + } + } + } + } + } + } +} + diff --git a/libraries/UTouch/examples/chipKit/UTouch_ButtonTest/UTouch_ButtonTest.pde b/libraries/UTouch/examples/chipKit/UTouch_ButtonTest/UTouch_ButtonTest.pde new file mode 100644 index 0000000..22ae1dd --- /dev/null +++ b/libraries/UTouch/examples/chipKit/UTouch_ButtonTest/UTouch_ButtonTest.pde @@ -0,0 +1,236 @@ +// UTouch_ButtonTest (C)2010-2012 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a quick demo of how create and use buttons. +// +// This program requires the UTFT library. +// +// It is assumed that the display module is connected to an +// appropriate shield or that you know how to change the pin +// numbers in the setup. +// + +#include +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; + +// Uncomment the next line for chipKit Uno32 +//UTFT myGLCD(ITDB24D,34,35,36,37); // Remember to change the model parameter to suit your display module! +//UTouch myTouch(20,21,22,23,24); + +// Uncomment the next line for chipKit Max32 +UTFT myGLCD(ITDB32S,82,83,84,85); // Remember to change the model parameter to suit your display module! +UTouch myTouch(62,63,64,65,66); + +int x, y; +char stCurrent[20]=""; +int stCurrentLen=0; +char stLast[20]=""; + +/************************* +** Custom functions ** +*************************/ + +void drawButtons() +{ +// Draw the upper row of buttons + for (x=0; x<5; x++) + { + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (10+(x*60), 10, 60+(x*60), 60); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (10+(x*60), 10, 60+(x*60), 60); + myGLCD.printNumI(x+1, 27+(x*60), 27); + } +// Draw the center row of buttons + for (x=0; x<5; x++) + { + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (10+(x*60), 70, 60+(x*60), 120); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (10+(x*60), 70, 60+(x*60), 120); + if (x<4) + myGLCD.printNumI(x+6, 27+(x*60), 87); + } + myGLCD.print("0", 267, 87); +// Draw the lower row of buttons + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (10, 130, 150, 180); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (10, 130, 150, 180); + myGLCD.print("Clear", 40, 147); + myGLCD.setColor(0, 0, 255); + myGLCD.fillRoundRect (160, 130, 300, 180); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (160, 130, 300, 180); + myGLCD.print("Enter", 190, 147); + myGLCD.setBackColor (0, 0, 0); +} + +void updateStr(int val) +{ + if (stCurrentLen<20) + { + stCurrent[stCurrentLen]=val; + stCurrent[stCurrentLen+1]='\0'; + stCurrentLen++; + myGLCD.setColor(0, 255, 0); + myGLCD.print(stCurrent, LEFT, 224); + } + else + { + myGLCD.setColor(255, 0, 0); + myGLCD.print("BUFFER FULL!", CENTER, 192); + delay(500); + myGLCD.print(" ", CENTER, 192); + delay(500); + myGLCD.print("BUFFER FULL!", CENTER, 192); + delay(500); + myGLCD.print(" ", CENTER, 192); + myGLCD.setColor(0, 255, 0); + } +} + +// Draw a red frame while a button is touched +void waitForIt(int x1, int y1, int x2, int y2) +{ + myGLCD.setColor(255, 0, 0); + myGLCD.drawRoundRect (x1, y1, x2, y2); + while (myTouch.dataAvailable()) + myTouch.read(); + myGLCD.setColor(255, 255, 255); + myGLCD.drawRoundRect (x1, y1, x2, y2); +} + +/************************* +** Required functions ** +*************************/ + +void setup() +{ +// Initial setup + myGLCD.InitLCD(); + myGLCD.clrScr(); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_MEDIUM); + + myGLCD.setFont(BigFont); + myGLCD.setBackColor(0, 0, 255); + drawButtons(); +} + +void loop() +{ + while (true) + { + if (myTouch.dataAvailable()) + { + myTouch.read(); + x=myTouch.getX(); + y=myTouch.getY(); + + if ((y>=10) && (y<=60)) // Upper row + { + if ((x>=10) && (x<=60)) // Button: 1 + { + waitForIt(10, 10, 60, 60); + updateStr('1'); + } + if ((x>=70) && (x<=120)) // Button: 2 + { + waitForIt(70, 10, 120, 60); + updateStr('2'); + } + if ((x>=130) && (x<=180)) // Button: 3 + { + waitForIt(130, 10, 180, 60); + updateStr('3'); + } + if ((x>=190) && (x<=240)) // Button: 4 + { + waitForIt(190, 10, 240, 60); + updateStr('4'); + } + if ((x>=250) && (x<=300)) // Button: 5 + { + waitForIt(250, 10, 300, 60); + updateStr('5'); + } + } + + if ((y>=70) && (y<=120)) // Center row + { + if ((x>=10) && (x<=60)) // Button: 6 + { + waitForIt(10, 70, 60, 120); + updateStr('6'); + } + if ((x>=70) && (x<=120)) // Button: 7 + { + waitForIt(70, 70, 120, 120); + updateStr('7'); + } + if ((x>=130) && (x<=180)) // Button: 8 + { + waitForIt(130, 70, 180, 120); + updateStr('8'); + } + if ((x>=190) && (x<=240)) // Button: 9 + { + waitForIt(190, 70, 240, 120); + updateStr('9'); + } + if ((x>=250) && (x<=300)) // Button: 0 + { + waitForIt(250, 70, 300, 120); + updateStr('0'); + } + } + + if ((y>=130) && (y<=180)) // Upper row + { + if ((x>=10) && (x<=150)) // Button: Clear + { + waitForIt(10, 130, 150, 180); + stCurrent[0]='\0'; + stCurrentLen=0; + myGLCD.setColor(0, 0, 0); + myGLCD.fillRect(0, 224, 319, 239); + } + if ((x>=160) && (x<=300)) // Button: Enter + { + waitForIt(160, 130, 300, 180); + if (stCurrentLen>0) + { + for (x=0; x +#include + +// Define the orientation of the touch screen. Further +// information can be found in the instructions. +#define TOUCH_ORIENTATION PORTRAIT + +// Declare which fonts we will be using +extern uint8_t SmallFont[]; + +// Uncomment the next line for chipKit Uno32 +//UTFT myGLCD(ITDB24D,34,35,36,37); // Remember to change the model parameter to suit your display module! +//UTouch myTouch(20,21,22,23,24); + +// Uncomment the next line for chipKit Max32 +UTFT myGLCD(ITDB32S,82,83,84,85); // Remember to change the model parameter to suit your display module! +UTouch myTouch(62,63,64,65,66); + +// ************************************ +// DO NOT EDIT ANYTHING BELOW THIS LINE +// ************************************ +uint32_t cx, cy; +uint32_t rx[8], ry[8]; +uint32_t clx, crx, cty, cby; +float px, py; +int dispx, dispy, text_y_center; +uint32_t calx, caly, cals; +char buf[13]; + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(SmallFont); + + myTouch.InitTouch(TOUCH_ORIENTATION); + dispx=myGLCD.getDisplayXSize(); + dispy=myGLCD.getDisplayYSize(); + text_y_center=(dispy/2)-6; +} + +void drawCrossHair(int x, int y) +{ + myGLCD.drawRect(x-10, y-10, x+10, y+10); + myGLCD.drawLine(x-5, y, x+5, y); + myGLCD.drawLine(x, y-5, x, y+5); +} + +void readCoordinates() +{ + int iter = 5000; + int failcount = 0; + int cnt = 0; + uint32_t tx=0; + uint32_t ty=0; + boolean OK = false; + + while (OK == false) + { + myGLCD.setColor(255, 255, 255); + myGLCD.print("* PRESS *", CENTER, text_y_center); + while (myTouch.dataAvailable() == false) {} + myGLCD.print("* HOLD! *", CENTER, text_y_center); + while ((myTouch.dataAvailable() == true) && (cnt=iter) + { + OK = true; + } + else + { + tx = 0; + ty = 0; + cnt = 0; + } + if (failcount>=10000) + fail(); + } + + cx = tx / iter; + cy = ty / iter; +} + +void calibrate(int x, int y, int i) +{ + myGLCD.setColor(255, 255, 255); + drawCrossHair(x,y); + myGLCD.setBackColor(255, 0, 0); + readCoordinates(); + myGLCD.setColor(255, 255, 255); + myGLCD.print("* RELEASE *", CENTER, text_y_center); + myGLCD.setColor(80, 80, 80); + drawCrossHair(x,y); + rx[i]=cx; + ry[i]=cy; + while (myTouch.dataAvailable() == true) {} +} + +void waitForTouch() +{ + while (myTouch.dataAvailable() == true) {} + while (myTouch.dataAvailable() == false) {} + while (myTouch.dataAvailable() == true) {} +} + +void toHex(uint32_t num) +{ + buf[0] = '0'; + buf[1] = 'x'; + buf[10] = 'U'; + buf[11] = 'L'; + buf[12] = 0; + for (int zz=9; zz>1; zz--) + { + if ((num & 0xF) > 9) + buf[zz] = (num & 0xF) + 55; + else + buf[zz] = (num & 0xF) + 48; + num=num>>4; + } +} + +void startup() +{ + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, dispx-1, 13); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.drawLine(0, 14, dispx-1, 14); + myGLCD.print("UTouch Calibration", CENTER, 1); + myGLCD.setBackColor(0, 0, 0); + + if (dispx==220) + { + myGLCD.print("Use a stylus or something", LEFT, 30); + myGLCD.print("similar to touch as close", LEFT, 42); + myGLCD.print("to the center of the", LEFT, 54); + myGLCD.print("highlighted crosshair as", LEFT, 66); + myGLCD.print("possible. Keep as still as", LEFT, 78); + myGLCD.print("possible and keep holding", LEFT, 90); + myGLCD.print("until the highlight is", LEFT, 102); + myGLCD.print("removed. Repeat for all", LEFT, 114); + myGLCD.print("crosshairs in sequence.", LEFT, 126); + myGLCD.print("Touch screen to continue", CENTER, 162); + } + else + { + myGLCD.print("INSTRUCTIONS", CENTER, 30); + myGLCD.print("Use a stylus or something similar to", LEFT, 50); + myGLCD.print("touch as close to the center of the", LEFT, 62); + myGLCD.print("highlighted crosshair as possible. Keep", LEFT, 74); + myGLCD.print("as still as possible and keep holding", LEFT, 86); + myGLCD.print("until the highlight is removed. Repeat", LEFT, 98); + myGLCD.print("for all crosshairs in sequence.", LEFT, 110); + + myGLCD.print("Further instructions will be displayed", LEFT, 134); + myGLCD.print("when the calibration is complete.", LEFT, 146); + + myGLCD.print("Do NOT use your finger as a calibration", LEFT, 170); + myGLCD.print("stylus or the result WILL BE imprecise.", LEFT, 182); + + myGLCD.print("Touch screen to continue", CENTER, 226); + } + + waitForTouch(); + myGLCD.clrScr(); +} + +void done() +{ + myGLCD.clrScr(); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, dispx-1, 13); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.drawLine(0, 14, dispx-1, 14); + myGLCD.print("UTouch Calibration", CENTER, 1); + myGLCD.setBackColor(0, 0, 0); + + if (dispx==220) + { + myGLCD.print("To use the new calibration", LEFT, 30); + myGLCD.print("settings you must edit the", LEFT, 42); + myGLCD.setColor(160, 160, 255); + myGLCD.print("UTouchCD.h", LEFT, 54); + myGLCD.setColor(255, 255, 255); + myGLCD.print("file and change", 88, 54); + myGLCD.print("the following values. The", LEFT, 66); + myGLCD.print("values are located right", LEFT, 78); + myGLCD.print("below the opening comment.", LEFT, 90); + myGLCD.print("CAL_X", LEFT, 110); + myGLCD.print("CAL_Y", LEFT, 122); + myGLCD.print("CAL_S", LEFT, 134); + toHex(calx); + myGLCD.print(buf, 75, 110); + toHex(caly); + myGLCD.print(buf, 75, 122); + toHex(cals); + myGLCD.print(buf, 75, 134); + } + else + { + myGLCD.print("CALIBRATION COMPLETE", CENTER, 30); + myGLCD.print("To use the new calibration", LEFT, 50); + myGLCD.print("settings you must edit the", LEFT, 62); + myGLCD.setColor(160, 160, 255); + myGLCD.print("UTouchCD.h", LEFT, 74); + myGLCD.setColor(255, 255, 255); + myGLCD.print("file and change", 88, 74); + myGLCD.print("the following values.", LEFT, 86); + myGLCD.print("The values are located right", LEFT, 98); + myGLCD.print("below the opening comment in", LEFT, 110); + myGLCD.print("the file.", LEFT, 122); + myGLCD.print("CAL_X", LEFT, 150); + myGLCD.print("CAL_Y", LEFT, 162); + myGLCD.print("CAL_S", LEFT, 174); + + toHex(calx); + myGLCD.print(buf, 75, 150); + toHex(caly); + myGLCD.print(buf, 75, 162); + toHex(cals); + myGLCD.print(buf, 75, 174); + } + +} + +void fail() +{ + myGLCD.clrScr(); + myGLCD.setColor(255, 0, 0); + myGLCD.fillRect(0, 0, dispx-1, 13); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.drawLine(0, 14, dispx-1, 14); + myGLCD.print("UTouch Calibration FAILED", CENTER, 1); + myGLCD.setBackColor(0, 0, 0); + + myGLCD.print("Unable to read the position", LEFT, 30); + myGLCD.print("of the press. This is a", LEFT, 42); + myGLCD.print("hardware issue and can", 88, 54); + myGLCD.print("not be corrected in", LEFT, 66); + myGLCD.print("software.", LEFT, 78); + + while(true) {}; +} + +void loop() +{ + startup(); + + myGLCD.setColor(80, 80, 80); + drawCrossHair(dispx-11, 10); + drawCrossHair(dispx/2, 10); + drawCrossHair(10, 10); + drawCrossHair(dispx-11, dispy/2); + drawCrossHair(10, dispy/2); + drawCrossHair(dispx-11, dispy-11); + drawCrossHair(dispx/2, dispy-11); + drawCrossHair(10, dispy-11); + myGLCD.setColor(255, 255, 255); + myGLCD.setBackColor(255, 0, 0); + myGLCD.print("***********", CENTER, text_y_center-12); + myGLCD.print("***********", CENTER, text_y_center+12); + + calibrate(10, 10, 0); + calibrate(10, dispy/2, 1); + calibrate(10, dispy-11, 2); + calibrate(dispx/2, 10, 3); + calibrate(dispx/2, dispy-11, 4); + calibrate(dispx-11, 10, 5); + calibrate(dispx-11, dispy/2, 6); + calibrate(dispx-11, dispy-11, 7); + + if (TOUCH_ORIENTATION == LANDSCAPE) + cals=(long(dispx-1)<<12)+(dispy-1); + else + cals=(long(dispy-1)<<12)+(dispx-1); + + if (TOUCH_ORIENTATION == PORTRAIT) + px = abs(((float(rx[2]+rx[4]+rx[7])/3)-(float(rx[0]+rx[3]+rx[5])/3))/(dispy-20)); // PORTRAIT + else + px = abs(((float(rx[5]+rx[6]+rx[7])/3)-(float(rx[0]+rx[1]+rx[2])/3))/(dispy-20)); // LANDSCAPE + + if (TOUCH_ORIENTATION == PORTRAIT) + { + clx = (((rx[0]+rx[3]+rx[5])/3)); // PORTRAIT + crx = (((rx[2]+rx[4]+rx[7])/3)); // PORTRAIT + } + else + { + clx = (((rx[0]+rx[1]+rx[2])/3)); // LANDSCAPE + crx = (((rx[5]+rx[6]+rx[7])/3)); // LANDSCAPE + } + if (clx +#include + +// Uncomment the next line for chipKit Uno32 +//UTFT myGLCD(ITDB24D,34,35,36,37); // Remember to change the model parameter to suit your display module! +//UTouch myTouch(20,21,22,23,24); + +// Uncomment the next line for chipKit Max32 +UTFT myGLCD(ITDB32S,82,83,84,85); // Remember to change the model parameter to suit your display module! +UTouch myTouch(62,63,64,65,66); + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_MEDIUM); +} + +void loop() +{ + long x, y; + + while (myTouch.dataAvailable() == true) + { + myTouch.read(); + x = myTouch.getX(); + y = myTouch.getY(); + if ((x!=-1) and (y!=-1)) + myGLCD.drawPixel (x, y); + } +} + diff --git a/libraries/UTouch/examples/chipKit/UTouch_QuickPaint/UTouch_QuickPaint.pde b/libraries/UTouch/examples/chipKit/UTouch_QuickPaint/UTouch_QuickPaint.pde new file mode 100644 index 0000000..fa6ed09 --- /dev/null +++ b/libraries/UTouch/examples/chipKit/UTouch_QuickPaint/UTouch_QuickPaint.pde @@ -0,0 +1,155 @@ +// UTouch_QuickPaint (C)2013 Henning Karlsen +// web: http://www.henningkarlsen.com/electronics +// +// This program is a quick demo of how to use the library. +// +// This program requires the UTFT library and a display +// module with at least 320x240 pixels resolution. +// +// It is assumed that the display module is connected to an +// appropriate shield or that you know how to change the pin +// numbers in the setup. +// + +#include +#include + +// Declare which fonts we will be using +extern uint8_t BigFont[]; + +// Uncomment the next line for chipKit Uno32 +//UTFT myGLCD(ITDB24D,34,35,36,37); // Remember to change the model parameter to suit your display module! +//UTouch myTouch(20,21,22,23,24); + +// Uncomment the next line for chipKit Max32 +UTFT myGLCD(ITDB32S,82,83,84,85); // Remember to change the model parameter to suit your display module! +UTouch myTouch(62,63,64,65,66); + +int color = 0; +word colorlist[] = {VGA_WHITE, VGA_BLACK, VGA_RED, VGA_BLUE, VGA_GREEN, VGA_FUCHSIA, VGA_YELLOW, VGA_AQUA}; +int bsize = 4; + +void drawColorMarkerAndBrushSize(int col) +{ + myGLCD.setColor(VGA_BLACK); + myGLCD.fillRect(25, 0, 31, 239); + myGLCD.fillRect(myGLCD.getDisplayXSize()-31, 161, myGLCD.getDisplayXSize()-1, 191); + myGLCD.setColor(VGA_WHITE); + myGLCD.drawPixel(25, (col*30)+15); + for (int i=1; i<7; i++) + myGLCD.drawLine(25+i, ((col*30)+15)-i, 25+i, ((col*30)+15)+i); + + if (color==1) + myGLCD.setColor(VGA_WHITE); + else + myGLCD.setColor(colorlist[col]); + if (bsize==1) + myGLCD.drawPixel(myGLCD.getDisplayXSize()-15, 177); + else + myGLCD.fillCircle(myGLCD.getDisplayXSize()-15, 177, bsize); + + myGLCD.setColor(colorlist[col]); +} + +void setup() +{ + myGLCD.InitLCD(); + myGLCD.clrScr(); + myGLCD.setFont(BigFont); + + myTouch.InitTouch(); + myTouch.setPrecision(PREC_HI); + + myGLCD.setColor(VGA_WHITE); + myGLCD.drawLine(32,0,32,myGLCD.getDisplayYSize()-1); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,0,myGLCD.getDisplayXSize()-32,myGLCD.getDisplayYSize()-1); + myGLCD.print("C", myGLCD.getDisplayXSize()-24, 8); + myGLCD.print("L", myGLCD.getDisplayXSize()-24, 24); + myGLCD.print("E", myGLCD.getDisplayXSize()-24, 40); + myGLCD.print("A", myGLCD.getDisplayXSize()-24, 56); + myGLCD.print("R", myGLCD.getDisplayXSize()-24, 72); + myGLCD.print("+", myGLCD.getDisplayXSize()-24, 136); + myGLCD.print("-", myGLCD.getDisplayXSize()-24, 200); + myGLCD.fillRect(myGLCD.getDisplayXSize()-32,96,myGLCD.getDisplayXSize()-1,128); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,160,myGLCD.getDisplayXSize()-1,160); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,192,myGLCD.getDisplayXSize()-1,192); + myGLCD.drawLine(myGLCD.getDisplayXSize()-32,224,myGLCD.getDisplayXSize()-1,224); + for (int i=0; i<8; i++) + { + myGLCD.setColor(colorlist[i]); + myGLCD.fillRect(0, (i*30), 24, (((i+1)*30)-1)); + } + drawColorMarkerAndBrushSize(color); +} + +void loop() +{ + long x, y; + + while (myTouch.dataAvailable() == true) + { + myTouch.read(); + x = myTouch.getX(); + y = myTouch.getY(); + if ((x!=-1) and (y!=-1)) + { + if (x>(31+bsize) and (x128) and (y<160)) + { + if (bsize<7) + { + bsize++; + drawColorMarkerAndBrushSize(color); + while (myTouch.dataAvailable()) {}; + delay(50); + } + } + if ((y>160) and (y<192)) + { + bsize=4; + drawColorMarkerAndBrushSize(color); + while (myTouch.dataAvailable()) {}; + delay(50); + } + if ((y>192) and (y<224)) + { + if (bsize>1) + { + bsize--; + drawColorMarkerAndBrushSize(color); + while (myTouch.dataAvailable()) {}; + delay(50); + } + } + } + } + } + } +} + diff --git a/libraries/UTouch/hardware/arm/HW_ARM.inc b/libraries/UTouch/hardware/arm/HW_ARM.inc new file mode 100644 index 0000000..069ac43 --- /dev/null +++ b/libraries/UTouch/hardware/arm/HW_ARM.inc @@ -0,0 +1,36 @@ +// Results becomes inaccurate if direct port manipulation is used hence the use of digitalWrite() and digitalRead() + +void UTouch::touch_WriteData(byte data) +{ + byte temp; + + temp=data; + cbi(P_CLK, B_CLK); + + for(byte count=0; count<8; count++) + { + if(temp & 0x80) + digitalWrite(T_DIN, HIGH); + else + digitalWrite(T_DIN, LOW); + temp = temp << 1; + digitalWrite(T_CLK, LOW); + digitalWrite(T_CLK, HIGH); + } +} + +word UTouch::touch_ReadData() +{ + word data = 0; + + for(byte count=0; count<12; count++) + { + data <<= 1; + digitalWrite(T_CLK, HIGH); + digitalWrite(T_CLK, LOW); + if (digitalRead(T_DOUT)) + data++; + } + return(data); +} + diff --git a/libraries/UTouch/hardware/arm/HW_ARM_defines.h b/libraries/UTouch/hardware/arm/HW_ARM_defines.h new file mode 100644 index 0000000..f5f7465 --- /dev/null +++ b/libraries/UTouch/hardware/arm/HW_ARM_defines.h @@ -0,0 +1,17 @@ +// *** Hardwarespecific defines *** +#define cbi(reg, bitmask) *reg &= ~bitmask +#define sbi(reg, bitmask) *reg |= bitmask +#define rbi(reg, bitmask) ((*reg) & bitmask) + +#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask); +#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask); + +#define swap(type, i, j) {type t = i; i = j; j = t;} + +#if defined(TEENSYDUINO) && TEENSYDUINO >= 117 + #define regtype volatile uint8_t + #define regsize uint8_t +#else + #define regtype volatile uint32_t + #define regsize uint32_t +#endif diff --git a/libraries/UTouch/hardware/avr/HW_AVR.inc b/libraries/UTouch/hardware/avr/HW_AVR.inc new file mode 100644 index 0000000..1450b37 --- /dev/null +++ b/libraries/UTouch/hardware/avr/HW_AVR.inc @@ -0,0 +1,34 @@ +void UTouch::touch_WriteData(byte data) +{ + byte temp; + + temp=data; + cbi(P_CLK, B_CLK); + + for(byte count=0; count<8; count++) + { + if(temp & 0x80) + sbi(P_DIN, B_DIN); + else + cbi(P_DIN, B_DIN); + temp = temp << 1; + cbi(P_CLK, B_CLK); + sbi(P_CLK, B_CLK); + } +} + +word UTouch::touch_ReadData() +{ + word data = 0; + + for(byte count=0; count<12; count++) + { + data <<= 1; + sbi(P_CLK, B_CLK); + cbi(P_CLK, B_CLK); + if (rbi(P_DOUT, B_DOUT)) + data++; + } + return(data); +} + diff --git a/libraries/UTouch/hardware/avr/HW_AVR_defines.h b/libraries/UTouch/hardware/avr/HW_AVR_defines.h new file mode 100644 index 0000000..318bdd1 --- /dev/null +++ b/libraries/UTouch/hardware/avr/HW_AVR_defines.h @@ -0,0 +1,12 @@ +// *** Hardwarespecific defines *** +#define cbi(reg, bitmask) *reg &= ~bitmask +#define sbi(reg, bitmask) *reg |= bitmask +#define rbi(reg, bitmask) ((*reg) & bitmask) + +#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask); +#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask); + +#define swap(type, i, j) {type t = i; i = j; j = t;} + +#define regtype volatile uint8_t +#define regsize uint8_t diff --git a/libraries/UTouch/hardware/pic32/HW_PIC32.inc b/libraries/UTouch/hardware/pic32/HW_PIC32.inc new file mode 100644 index 0000000..58c1724 --- /dev/null +++ b/libraries/UTouch/hardware/pic32/HW_PIC32.inc @@ -0,0 +1,36 @@ +// Direct port manipulation does not work at the moment, hence the use of digitalWrite() and digitalRead() + +void UTouch::touch_WriteData(byte data) +{ + byte temp; + + temp=data; + cbi(P_CLK, B_CLK); + + for(byte count=0; count<8; count++) + { + if(temp & 0x80) + digitalWrite(T_DIN, HIGH); + else + digitalWrite(T_DIN, LOW); + temp = temp << 1; + digitalWrite(T_CLK, LOW); + digitalWrite(T_CLK, HIGH); + } +} + +word UTouch::touch_ReadData() +{ + word data = 0; + + for(byte count=0; count<12; count++) + { + data <<= 1; + digitalWrite(T_CLK, HIGH); + digitalWrite(T_CLK, LOW); + if (digitalRead(T_DOUT)) + data++; + } + return(data); +} + diff --git a/libraries/UTouch/hardware/pic32/HW_PIC32_defines.h b/libraries/UTouch/hardware/pic32/HW_PIC32_defines.h new file mode 100644 index 0000000..821e561 --- /dev/null +++ b/libraries/UTouch/hardware/pic32/HW_PIC32_defines.h @@ -0,0 +1,12 @@ +// *** Hardwarespecific defines *** +#define cbi(reg, bitmask) (*(reg + 1)) = bitmask +#define sbi(reg, bitmask) (*(reg + 2)) = bitmask +#define rbi(reg, bitmask) (*(reg) & bitmask) + +#define pulse_high(reg, bitmask) sbi(reg, bitmask); cbi(reg, bitmask); +#define pulse_low(reg, bitmask) cbi(reg, bitmask); sbi(reg, bitmask); + +#define swap(type, i, j) {type t = i; i = j; j = t;} + +#define regtype volatile uint32_t +#define regsize uint16_t diff --git a/libraries/UTouch/keywords.txt b/libraries/UTouch/keywords.txt new file mode 100644 index 0000000..a79eafe --- /dev/null +++ b/libraries/UTouch/keywords.txt @@ -0,0 +1,17 @@ +UTouch KEYWORD1 + +InitTouch KEYWORD2 +read KEYWORD2 +dataAvailable KEYWORD2 +getX KEYWORD2 +getY KEYWORD2 +setPrecision KEYWORD2 + +PREC_LOW LITERAL1 +PREC_MEDIUM LITERAL1 +PREC_HI LITERAL1 +PREC_EXTREME LITERAL1 +PORTRAIT LITERAL1 +LANDSCAPE LITERAL1 +TP_X LITERAL1 +TP_Y LITERAL1 diff --git a/libraries/UTouch/version.txt b/libraries/UTouch/version.txt new file mode 100644 index 0000000..476825a --- /dev/null +++ b/libraries/UTouch/version.txt @@ -0,0 +1,18 @@ +Version: + 1.0 1 Dec 2012 - initial release + 1.1 23 May 2013 - added support for more display modules + modified calibration to try to compensate for slight flaws in some (larger) touchscreens + changed license to CC BY-NC-SA 3.0 + 1.2 22 Sep 2013 - general optimization + fixed some issues with calibration + made modifications to reduce erroneous readings + added support for more display modules + added UTouch_QuickPaint example + 1.21 06 Dec 2013 - added support for ElecFreaks TFT01-4.3 + added support for Coldtears 3.5" and 4.0" modules + 1.22 18 Feb 2014 - added support for Teensy 3.x Boards + added support for three display modules from ElecHouse + made some modifications to improve accuracy when precision is set to medium or higher + 1.23 16 Mar 2014 - fixed a bug that were introduced in v1.22 + 1.24 05 May 2014 - added support for DisplayModule DM-TFT24-104 and DM-TFT28-103 + added support for Coldtears 5" and 7" CPLD modules diff --git a/libraries/readme.txt b/libraries/readme.txt new file mode 100644 index 0000000..a8f1390 --- /dev/null +++ b/libraries/readme.txt @@ -0,0 +1 @@ +For information on installing libraries, see: http://arduino.cc/en/Guide/Libraries diff --git a/libraries/sha204/sha204_lib_return_codes.h b/libraries/sha204/sha204_lib_return_codes.h new file mode 100644 index 0000000..db61120 --- /dev/null +++ b/libraries/sha204/sha204_lib_return_codes.h @@ -0,0 +1,48 @@ +// ---------------------------------------------------------------------------- +// ATMEL Microcontroller Software Support - Colorado Springs, CO - +// ---------------------------------------------------------------------------- +// DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE +// DISCLAIMED. IN NO EVENT SHALL ATMEL 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. +// ---------------------------------------------------------------------------- + +/** \file + * \brief SHA204 Library Return Code Definitions + * \author Atmel Crypto Products + * \date September 27, 2010 + */ + +#ifndef SHA204_LIB_RETURN_CODES_H +# define SHA204_LIB_RETURN_CODES_H + +#include // data type definitions + +/** \todo Use same values for same meanings for SHA204 and AES132. + * */ + +#define SHA204_SUCCESS ((uint8_t) 0x00) //!< Function succeeded. +#define SHA204_PARSE_ERROR ((uint8_t) 0xD2) //!< response status byte indicates parsing error +#define SHA204_CMD_FAIL ((uint8_t) 0xD3) //!< response status byte indicates command execution error +#define SHA204_STATUS_CRC ((uint8_t) 0xD4) //!< response status byte indicates CRC error +#define SHA204_STATUS_UNKNOWN ((uint8_t) 0xD5) //!< response status byte is unknown +#define SHA204_FUNC_FAIL ((uint8_t) 0xE0) //!< Function could not execute due to incorrect condition / state. +#define SHA204_GEN_FAIL ((uint8_t) 0xE1) //!< unspecified error +#define SHA204_BAD_PARAM ((uint8_t) 0xE2) //!< bad argument (out of range, null pointer, etc.) +#define SHA204_INVALID_ID ((uint8_t) 0xE3) //!< invalid device id, id not set +#define SHA204_INVALID_SIZE ((uint8_t) 0xE4) //!< Count value is out of range or greater than buffer size. +#define SHA204_BAD_CRC ((uint8_t) 0xE5) //!< incorrect CRC received +#define SHA204_RX_FAIL ((uint8_t) 0xE6) //!< Timed out while waiting for response. Number of bytes received is > 0. +#define SHA204_RX_NO_RESPONSE ((uint8_t) 0xE7) //!< Not an error while the Command layer is polling for a command response. +#define SHA204_RESYNC_WITH_WAKEUP ((uint8_t) 0xE8) //!< re-synchronization succeeded, but only after generating a Wake-up + +#define SHA204_COMM_FAIL ((uint8_t) 0xF0) //!< Communication with device failed. Same as in hardware dependent modules. +#define SHA204_TIMEOUT ((uint8_t) 0xF1) //!< Timed out while waiting for response. Number of bytes received is 0. + +#endif diff --git a/libraries/sha204/sha204_library.cpp b/libraries/sha204/sha204_library.cpp new file mode 100644 index 0000000..8728096 --- /dev/null +++ b/libraries/sha204/sha204_library.cpp @@ -0,0 +1,832 @@ +#include "Arduino.h" +#include "sha204_library.h" +#include "sha204_lib_return_codes.h" + + +// atsha204Class Constructor +// Feed this function the Arduino-ized pin number you want to assign to the ATSHA204's SDA pin +// This will find the DDRX, PORTX, and PINX registrs it'll need to point to to control that pin +// As well as the bit value for each of those registers +atsha204Class::atsha204Class(uint8_t pin) +{ + device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin + uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers + + // Point to data direction register port of pin + device_port_DDR = portModeRegister(port); + // Point to output register of pin + device_port_OUT = portOutputRegister(port); + // Point to input register of pin + device_port_IN = portInputRegister(port); +} + +/* Puts a the ATSHA204's unique, 4-byte serial number in the response array + returns an SHA204 Return code */ +uint8_t atsha204Class::getSerialNumber(uint8_t * response) +{ + uint8_t readCommand[READ_COUNT]; + uint8_t readResponse[READ_4_RSP_SIZE]; + + /* read from bytes 0->3 of config zone */ + uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); + if (!returnCode) // should return 0 if successful + { + for (int i=0; i<4; i++) // store bytes 0-3 into respones array + response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; + + /* read from bytes 8->11 of config zone */ + returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47); + + for (int i=4; i<8; i++) // store bytes 4-7 of SN into response array + response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)]; + + if (!returnCode) + { /* Finally if last two reads were successful, read byte 8 of the SN */ + returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); + response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE + } + } + + return returnCode; +} + +/* Calculates CRC16 value of provided data (and optionally including provided existing CRC16 data) + returns the calculated CRC16 value */ +uint16_t atsha204Class::calculateAndUpdateCrc(uint8_t length, uint8_t *data, uint16_t current_crc) +{ + uint8_t counter; + uint16_t crc_register = current_crc; + uint16_t polynom = 0x8005; + uint8_t shift_register; + uint8_t data_bit, crc_bit; + + for (counter = 0; counter < length; counter++) + { + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) + { + data_bit = (data[counter] & shift_register) ? 1 : 0; + crc_bit = crc_register >> 15; + + // Shift CRC to the left by 1. + crc_register <<= 1; + + if ((data_bit ^ crc_bit) != 0) + crc_register ^= polynom; + } + } + return crc_register; +} + +/* SWI bit bang functions */ + +void atsha204Class::swi_set_signal_pin(uint8_t is_high) +{ + *device_port_DDR |= device_pin; + + if (is_high) + *device_port_OUT |= device_pin; + else + *device_port_OUT &= ~device_pin; +} + +uint8_t atsha204Class::swi_send_bytes(uint8_t count, uint8_t *buffer) +{ + uint8_t i, bit_mask; + + // Disable interrupts while sending. + noInterrupts(); //swi_disable_interrupts(); + + // Set signal pin as output. + *device_port_OUT |= device_pin; + *device_port_DDR |= device_pin; + + // Wait turn around time. + delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; + + for (i = 0; i < count; i++) + { + for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) + { + if (bit_mask & buffer[i]) + { + *device_port_OUT &= ~device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + *device_port_OUT |= device_pin; + delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; + } + else + { + // Send a zero bit. + *device_port_OUT &= ~device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + *device_port_OUT |= device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + *device_port_OUT &= ~device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + *device_port_OUT |= device_pin; + delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5; + } + } + } + interrupts(); //swi_enable_interrupts(); + return SWI_FUNCTION_RETCODE_SUCCESS; +} + +uint8_t atsha204Class::swi_send_byte(uint8_t value) +{ + return swi_send_bytes(1, &value); +} + +uint8_t atsha204Class::swi_receive_bytes(uint8_t count, uint8_t *buffer) +{ + uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS; + uint8_t i; + uint8_t bit_mask; + uint8_t pulse_count; + uint8_t timeout_count; + + // Disable interrupts while receiving. + noInterrupts(); //swi_disable_interrupts(); + + // Configure signal pin as input. + *device_port_DDR &= ~device_pin; + + // Receive bits and store in buffer. + for (i = 0; i < count; i++) + { + for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) + { + pulse_count = 0; + + // Make sure that the variable below is big enough. + // Change it to uint16_t if 255 is too small, but be aware that + // the loop resolution decreases on an 8-bit controller in that case. + timeout_count = START_PULSE_TIME_OUT; + + // Detect start bit. + while (--timeout_count > 0) + { + // Wait for falling edge. + if ((*device_port_IN & device_pin) == 0) + break; + } + + if (timeout_count == 0) + { + status = SWI_FUNCTION_RETCODE_TIMEOUT; + break; + } + + do + { + // Wait for rising edge. + if ((*device_port_IN & device_pin) != 0) + { + // For an Atmel microcontroller this might be faster than "pulse_count++". + pulse_count = 1; + break; + } + } while (--timeout_count > 0); + + if (pulse_count == 0) + { + status = SWI_FUNCTION_RETCODE_TIMEOUT; + break; + } + + // Trying to measure the time of start bit and calculating the timeout + // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU. + // So let's just wait the maximum time for the falling edge of a zero bit + // to arrive after we have detected the rising edge of the start bit. + timeout_count = ZERO_PULSE_TIME_OUT; + + // Detect possible edge indicating zero bit. + do + { + if ((*device_port_IN & device_pin) == 0) + { + // For an Atmel microcontroller this might be faster than "pulse_count++". + pulse_count = 2; + break; + } + } while (--timeout_count > 0); + + // Wait for rising edge of zero pulse before returning. Otherwise we might interpret + // its rising edge as the next start pulse. + if (pulse_count == 2) + { + do + { + if ((*device_port_IN & device_pin) != 0) + break; + } while (timeout_count-- > 0); + } + + // Update byte at current buffer index. + else + buffer[i] |= bit_mask; // received "one" bit + } + + if (status != SWI_FUNCTION_RETCODE_SUCCESS) + break; + } + interrupts(); //swi_enable_interrupts(); + + if (status == SWI_FUNCTION_RETCODE_TIMEOUT) + { + if (i > 0) + // Indicate that we timed out after having received at least one byte. + status = SWI_FUNCTION_RETCODE_RX_FAIL; + } + return status; +} + +/* Physical functions */ + +uint8_t atsha204Class::sha204p_wakeup() +{ + swi_set_signal_pin(0); + delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH); + swi_set_signal_pin(1); + delay(SHA204_WAKEUP_DELAY); + + return SHA204_SUCCESS; +} + +uint8_t atsha204Class::sha204p_sleep() +{ + return swi_send_byte(SHA204_SWI_FLAG_SLEEP); +} + +uint8_t atsha204Class::sha204p_resync(uint8_t size, uint8_t *response) +{ + delay(SHA204_SYNC_TIMEOUT); + return sha204p_receive_response(size, response); +} + +uint8_t atsha204Class::sha204p_receive_response(uint8_t size, uint8_t *response) +{ + uint8_t count_byte; + uint8_t i; + uint8_t ret_code; + + for (i = 0; i < size; i++) + response[i] = 0; + + (void) swi_send_byte(SHA204_SWI_FLAG_TX); + + ret_code = swi_receive_bytes(size, response); + if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) + { + count_byte = response[SHA204_BUFFER_POS_COUNT]; + if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) + return SHA204_INVALID_SIZE; + + return SHA204_SUCCESS; + } + + // Translate error so that the Communication layer + // can distinguish between a real error or the + // device being busy executing a command. + if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) + return SHA204_RX_NO_RESPONSE; + else + return SHA204_RX_FAIL; +} + +uint8_t atsha204Class::sha204p_send_command(uint8_t count, uint8_t * command) +{ + uint8_t ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); + if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) + return SHA204_COMM_FAIL; + + return swi_send_bytes(count, command); +} + +/* Communication functions */ + +uint8_t atsha204Class::sha204c_wakeup(uint8_t *response) +{ + uint8_t ret_code = sha204p_wakeup(); + if (ret_code != SHA204_SUCCESS) + return ret_code; + + ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); + if (ret_code != SHA204_SUCCESS) + return ret_code; + + // Verify status response. + if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) + ret_code = SHA204_INVALID_SIZE; + else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) + ret_code = SHA204_COMM_FAIL; + else + { + if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) + || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) + ret_code = SHA204_BAD_CRC; + } + if (ret_code != SHA204_SUCCESS) + delay(SHA204_COMMAND_EXEC_MAX); + + return ret_code; +} + +uint8_t atsha204Class::sha204c_resync(uint8_t size, uint8_t *response) +{ + // Try to re-synchronize without sending a Wake token + // (step 1 of the re-synchronization process). + uint8_t ret_code = sha204p_resync(size, response); + if (ret_code == SHA204_SUCCESS) + return ret_code; + + // We lost communication. Send a Wake pulse and try + // to receive a response (steps 2 and 3 of the + // re-synchronization process). + (void) sha204p_sleep(); + ret_code = sha204c_wakeup(response); + + // Translate a return value of success into one + // that indicates that the device had to be woken up + // and might have lost its TempKey. + return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); +} + +uint8_t atsha204Class::sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout) +{ + uint8_t ret_code = SHA204_FUNC_FAIL; + uint8_t ret_code_resync; + uint8_t n_retries_send; + uint8_t n_retries_receive; + uint8_t i; + uint8_t status_byte; + uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; + uint8_t count_minus_crc = count - SHA204_CRC_SIZE; + uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; + volatile uint16_t timeout_countdown; + + // Append CRC. + sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc); + + // Retry loop for sending a command and receiving a response. + n_retries_send = SHA204_RETRY_COUNT + 1; + + while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) + { + // Send command. + ret_code = sha204p_send_command(count, tx_buffer); + if (ret_code != SHA204_SUCCESS) + { + if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) + return ret_code; // The device seems to be dead in the water. + else + continue; + } + + // Wait minimum command execution time and then start polling for a response. + delay(execution_delay); + + // Retry loop for receiving a response. + n_retries_receive = SHA204_RETRY_COUNT + 1; + while (n_retries_receive-- > 0) + { + // Reset response buffer. + for (i = 0; i < rx_size; i++) + rx_buffer[i] = 0; + + // Poll for response. + timeout_countdown = execution_timeout_us; + do + { + ret_code = sha204p_receive_response(rx_size, rx_buffer); + timeout_countdown -= SHA204_RESPONSE_TIMEOUT; + } + while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE)); + + if (ret_code == SHA204_RX_NO_RESPONSE) + { + // We did not receive a response. Re-synchronize and send command again. + if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) + // The device seems to be dead in the water. + return ret_code; + else + break; + } + + // Check whether we received a valid response. + if (ret_code == SHA204_INVALID_SIZE) + { + // We see 0xFF for the count when communication got out of sync. + ret_code_resync = sha204c_resync(rx_size, rx_buffer); + if (ret_code_resync == SHA204_SUCCESS) + // We did not have to wake up the device. Try receiving response again. + continue; + if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) + // We could re-synchronize, but only after waking up the device. + // Re-send command. + break; + else + // We failed to re-synchronize. + return ret_code; + } + + // We received a response of valid size. + // Check the consistency of the response. + ret_code = sha204c_check_crc(rx_buffer); + if (ret_code == SHA204_SUCCESS) + { + // Received valid response. + if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) + // Received non-status response. We are done. + return ret_code; + + // Received status response. + status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; + + // Translate the three possible device status error codes + // into library return codes. + if (status_byte == SHA204_STATUS_BYTE_PARSE) + return SHA204_PARSE_ERROR; + if (status_byte == SHA204_STATUS_BYTE_EXEC) + return SHA204_CMD_FAIL; + if (status_byte == SHA204_STATUS_BYTE_COMM) + { + // In case of the device status byte indicating a communication + // error this function exits the retry loop for receiving a response + // and enters the overall retry loop + // (send command / receive response). + ret_code = SHA204_STATUS_CRC; + break; + } + + // Received status response from CheckMAC, DeriveKey, GenDig, + // Lock, Nonce, Pause, UpdateExtra, or Write command. + return ret_code; + } + + else + { + // Received response with incorrect CRC. + ret_code_resync = sha204c_resync(rx_size, rx_buffer); + if (ret_code_resync == SHA204_SUCCESS) + // We did not have to wake up the device. Try receiving response again. + continue; + if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) + // We could re-synchronize, but only after waking up the device. + // Re-send command. + break; + else + // We failed to re-synchronize. + return ret_code; + } // block end of check response consistency + + } // block end of receive retry loop + + } // block end of send and receive retry loop + + return ret_code; +} + + +/* Marshaling functions */ + +uint8_t atsha204Class::sha204m_random(uint8_t * tx_buffer, uint8_t * rx_buffer, uint8_t mode) +{ + if (!tx_buffer || !rx_buffer || (mode > RANDOM_NO_SEED_UPDATE)) + return SHA204_BAD_PARAM; + + tx_buffer[SHA204_COUNT_IDX] = RANDOM_COUNT; + tx_buffer[SHA204_OPCODE_IDX] = SHA204_RANDOM; + tx_buffer[RANDOM_MODE_IDX] = mode & RANDOM_SEED_UPDATE; + + tx_buffer[RANDOM_PARAM2_IDX] = + tx_buffer[RANDOM_PARAM2_IDX + 1] = 0; + + return sha204c_send_and_receive(&tx_buffer[0], RANDOM_RSP_SIZE, &rx_buffer[0], RANDOM_DELAY, RANDOM_EXEC_MAX - RANDOM_DELAY); +} + +uint8_t atsha204Class::sha204m_dev_rev(uint8_t *tx_buffer, uint8_t *rx_buffer) +{ + if (!tx_buffer || !rx_buffer) + return SHA204_BAD_PARAM; + + tx_buffer[SHA204_COUNT_IDX] = DEVREV_COUNT; + tx_buffer[SHA204_OPCODE_IDX] = SHA204_DEVREV; + + // Parameters are 0. + tx_buffer[DEVREV_PARAM1_IDX] = + tx_buffer[DEVREV_PARAM2_IDX] = + tx_buffer[DEVREV_PARAM2_IDX + 1] = 0; + + return sha204c_send_and_receive(&tx_buffer[0], DEVREV_RSP_SIZE, &rx_buffer[0], + DEVREV_DELAY, DEVREV_EXEC_MAX - DEVREV_DELAY); +} + +uint8_t atsha204Class::sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address) +{ + uint8_t rx_size; + + if (!tx_buffer || !rx_buffer || ((zone & ~READ_ZONE_MASK) != 0) + || ((zone & READ_ZONE_MODE_32_BYTES) && (zone == SHA204_ZONE_OTP))) + return SHA204_BAD_PARAM; + + address >>= 2; + if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_CONFIG) + { + if (address > SHA204_ADDRESS_MASK_CONFIG) + return SHA204_BAD_PARAM; + } + else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_OTP) + { + if (address > SHA204_ADDRESS_MASK_OTP) + return SHA204_BAD_PARAM; + } + else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_DATA) + { + if (address > SHA204_ADDRESS_MASK) + return SHA204_BAD_PARAM; + } + + tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; + tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; + tx_buffer[READ_ZONE_IDX] = zone; + tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK); + tx_buffer[READ_ADDR_IDX + 1] = 0; + + rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; + + return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, READ_EXEC_MAX - READ_DELAY); +} + +uint8_t atsha204Class::sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2, + uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3, + uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) +{ + uint8_t poll_delay, poll_timeout, response_size; + uint8_t *p_buffer; + uint8_t len; + + uint8_t ret_code = sha204m_check_parameters(op_code, param1, param2, + datalen1, data1, datalen2, data2, datalen3, data3, + tx_size, tx_buffer, rx_size, rx_buffer); + if (ret_code != SHA204_SUCCESS) + return ret_code; + + // Supply delays and response size. + switch (op_code) + { + case SHA204_CHECKMAC: + poll_delay = CHECKMAC_DELAY; + poll_timeout = CHECKMAC_EXEC_MAX - CHECKMAC_DELAY; + response_size = CHECKMAC_RSP_SIZE; + break; + + case SHA204_DERIVE_KEY: + poll_delay = DERIVE_KEY_DELAY; + poll_timeout = DERIVE_KEY_EXEC_MAX - DERIVE_KEY_DELAY; + response_size = DERIVE_KEY_RSP_SIZE; + break; + + case SHA204_DEVREV: + poll_delay = DEVREV_DELAY; + poll_timeout = DEVREV_EXEC_MAX - DEVREV_DELAY; + response_size = DEVREV_RSP_SIZE; + break; + + case SHA204_GENDIG: + poll_delay = GENDIG_DELAY; + poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; + response_size = GENDIG_RSP_SIZE; + break; + + case SHA204_HMAC: + poll_delay = HMAC_DELAY; + poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; + response_size = HMAC_RSP_SIZE; + break; + + case SHA204_LOCK: + poll_delay = LOCK_DELAY; + poll_timeout = LOCK_EXEC_MAX - LOCK_DELAY; + response_size = LOCK_RSP_SIZE; + break; + + case SHA204_MAC: + poll_delay = MAC_DELAY; + poll_timeout = MAC_EXEC_MAX - MAC_DELAY; + response_size = MAC_RSP_SIZE; + break; + + case SHA204_NONCE: + poll_delay = NONCE_DELAY; + poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; + response_size = param1 == NONCE_MODE_PASSTHROUGH + ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; + break; + + case SHA204_PAUSE: + poll_delay = PAUSE_DELAY; + poll_timeout = PAUSE_EXEC_MAX - PAUSE_DELAY; + response_size = PAUSE_RSP_SIZE; + break; + + case SHA204_RANDOM: + poll_delay = RANDOM_DELAY; + poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; + response_size = RANDOM_RSP_SIZE; + break; + + case SHA204_READ: + poll_delay = READ_DELAY; + poll_timeout = READ_EXEC_MAX - READ_DELAY; + response_size = (param1 & SHA204_ZONE_COUNT_FLAG) + ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; + break; + + case SHA204_UPDATE_EXTRA: + poll_delay = UPDATE_DELAY; + poll_timeout = UPDATE_EXEC_MAX - UPDATE_DELAY; + response_size = UPDATE_RSP_SIZE; + break; + + case SHA204_WRITE: + poll_delay = WRITE_DELAY; + poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; + response_size = WRITE_RSP_SIZE; + break; + + default: + poll_delay = 0; + poll_timeout = SHA204_COMMAND_EXEC_MAX; + response_size = rx_size; + } + + // Assemble command. + len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN; + p_buffer = tx_buffer; + *p_buffer++ = len; + *p_buffer++ = op_code; + *p_buffer++ = param1; + *p_buffer++ = param2 & 0xFF; + *p_buffer++ = param2 >> 8; + + if (datalen1 > 0) { + memcpy(p_buffer, data1, datalen1); + p_buffer += datalen1; + } + if (datalen2 > 0) { + memcpy(p_buffer, data2, datalen2); + p_buffer += datalen2; + } + if (datalen3 > 0) { + memcpy(p_buffer, data3, datalen3); + p_buffer += datalen3; + } + + sha204c_calculate_crc(len - SHA204_CRC_SIZE, tx_buffer, p_buffer); + + // Send command and receive response. + return sha204c_send_and_receive(&tx_buffer[0], response_size, + &rx_buffer[0], poll_delay, poll_timeout); +} + +uint8_t atsha204Class::sha204m_check_parameters(uint8_t op_code, uint8_t param1, uint16_t param2, + uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3, + uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) +{ +#ifdef SHA204_CHECK_PARAMETERS + + uint8_t len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN; + if (!tx_buffer || tx_size < len || rx_size < SHA204_RSP_SIZE_MIN || !rx_buffer) + return SHA204_BAD_PARAM; + + if ((datalen1 > 0 && !data1) || (datalen2 > 0 && !data2) || (datalen3 > 0 && !data3)) + return SHA204_BAD_PARAM; + + // Check parameters depending on op-code. + switch (op_code) + { + case SHA204_CHECKMAC: + if ( + // no null pointers allowed + !data1 || !data2 + // No reserved bits should be set. + || (param1 | CHECKMAC_MODE_MASK) != CHECKMAC_MODE_MASK + // key_id > 15 not allowed + || param2 > SHA204_KEY_ID_MAX + ) + return SHA204_BAD_PARAM; + break; + + case SHA204_DERIVE_KEY: + if (param2 > SHA204_KEY_ID_MAX) + return SHA204_BAD_PARAM; + break; + + case SHA204_DEVREV: + break; + + case SHA204_GENDIG: + if ((param1 != GENDIG_ZONE_OTP) && (param1 != GENDIG_ZONE_DATA)) + return SHA204_BAD_PARAM; + break; + + case SHA204_HMAC: + if ((param1 & ~HMAC_MODE_MASK) != 0) + return SHA204_BAD_PARAM; + break; + + case SHA204_LOCK: + if (((param1 & ~LOCK_ZONE_MASK) != 0) + || ((param1 & LOCK_ZONE_NO_CRC) && (param2 != 0))) + return SHA204_BAD_PARAM; + break; + + case SHA204_MAC: + if (((param1 & ~MAC_MODE_MASK) != 0) + || (((param1 & MAC_MODE_BLOCK2_TEMPKEY) == 0) && !data1)) + return SHA204_BAD_PARAM; + break; + + case SHA204_NONCE: + if ( !data1 + || (param1 > NONCE_MODE_PASSTHROUGH) + || (param1 == NONCE_MODE_INVALID) + ) + return SHA204_BAD_PARAM; + break; + + case SHA204_PAUSE: + break; + + case SHA204_RANDOM: + if (param1 > RANDOM_NO_SEED_UPDATE) + return SHA204_BAD_PARAM; + break; + + case SHA204_READ: + if (((param1 & ~READ_ZONE_MASK) != 0) + || ((param1 & READ_ZONE_MODE_32_BYTES) && (param1 == SHA204_ZONE_OTP))) + return SHA204_BAD_PARAM; + break; + + case SHA204_TEMPSENSE: + break; + + case SHA204_UPDATE_EXTRA: + if (param1 > UPDATE_CONFIG_BYTE_86) + return SHA204_BAD_PARAM; + break; + + case SHA204_WRITE: + if (!data1 || ((param1 & ~WRITE_ZONE_MASK) != 0)) + return SHA204_BAD_PARAM; + break; + + default: + // unknown op-code + return SHA204_BAD_PARAM; + } + + return SHA204_SUCCESS; + +#else + (void)rx_size; + (void)tx_size; + (void)tx_buffer; + (void)rx_buffer; + (void)param1; + (void)param2; + (void)data1; + (void)data2; + (void)data3; + (void)datalen1; + (void)datalen2; + (void)datalen3; + (void)op_code; + return SHA204_SUCCESS; +#endif +} + +/* CRC Calculator and Checker */ + +void atsha204Class::sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) +{ + uint16_t crc_register = 0; + + crc_register = calculateAndUpdateCrc(length, data, crc_register); + crc[0] = (uint8_t) (crc_register & 0x00FF); + crc[1] = (uint8_t) (crc_register >> 8); +} + +uint8_t atsha204Class::sha204c_check_crc(uint8_t *response) +{ + uint8_t crc[SHA204_CRC_SIZE]; + uint8_t count = response[SHA204_BUFFER_POS_COUNT]; + + count -= SHA204_CRC_SIZE; + sha204c_calculate_crc(count, response, crc); + + return (crc[0] == response[count] && crc[1] == response[count + 1]) + ? SHA204_SUCCESS : SHA204_BAD_CRC; +} diff --git a/libraries/sha204/sha204_library.h b/libraries/sha204/sha204_library.h new file mode 100644 index 0000000..3e2c9f0 --- /dev/null +++ b/libraries/sha204/sha204_library.h @@ -0,0 +1,321 @@ +#include "Arduino.h" + +#ifndef sha204_library_H +#define sha204_library_H + +/* bitbang_config.h */ + +#define PORT_ACCESS_TIME (630) //! time it takes to toggle the pin at CPU clock of 16 MHz (ns) +#define START_PULSE_WIDTH (4340) //! width of start pulse (ns) +#define BIT_DELAY (4) //! delay macro for width of one pulse (start pulse or zero pulse, in ns) +#define RX_TX_DELAY (15) //! turn around time when switching from receive to transmit +#define START_PULSE_TIME_OUT (255) //! This value is decremented while waiting for the falling edge of a start pulse. +#define ZERO_PULSE_TIME_OUT (26) //! This value is decremented while waiting for the falling edge of a zero pulse. + +/* swi_phys.h */ + +#define SWI_FUNCTION_RETCODE_SUCCESS ((uint8_t) 0x00) //!< Communication with device succeeded. +#define SWI_FUNCTION_RETCODE_TIMEOUT ((uint8_t) 0xF1) //!< Communication timed out. +#define SWI_FUNCTION_RETCODE_RX_FAIL ((uint8_t) 0xF9) //!< Communication failed after at least one byte was received. + +/* sha204_physical.h */ + +#define SHA204_RSP_SIZE_MIN ((uint8_t) 4) //!< minimum number of bytes in response +#define SHA204_RSP_SIZE_MAX ((uint8_t) 35) //!< maximum size of response packet +#define SHA204_BUFFER_POS_COUNT (0) //!< buffer index of count byte in command or response +#define SHA204_BUFFER_POS_DATA (1) //!< buffer index of data in response +#define SHA204_WAKEUP_PULSE_WIDTH (uint8_t) (6.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! width of Wakeup pulse in 10 us units +#define SHA204_WAKEUP_DELAY (uint8_t) (3.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! delay between Wakeup pulse and communication in ms + +/* sha204_swi.c */ +#define SHA204_SWI_FLAG_CMD ((uint8_t) 0x77) //!< flag preceding a command +#define SHA204_SWI_FLAG_TX ((uint8_t) 0x88) //!< flag requesting a response +#define SHA204_SWI_FLAG_IDLE ((uint8_t) 0xBB) //!< flag requesting to go into Idle mode +#define SHA204_SWI_FLAG_SLEEP ((uint8_t) 0xCC) //!< flag requesting to go into Sleep mode + +/* sha204_comm_marshaling.h */ +// command op-code definitions +#define SHA204_CHECKMAC ((uint8_t) 0x28) //!< CheckMac command op-code +#define SHA204_DERIVE_KEY ((uint8_t) 0x1C) //!< DeriveKey command op-code +#define SHA204_DEVREV ((uint8_t) 0x30) //!< DevRev command op-code +#define SHA204_GENDIG ((uint8_t) 0x15) //!< GenDig command op-code +#define SHA204_HMAC ((uint8_t) 0x11) //!< HMAC command op-code +#define SHA204_LOCK ((uint8_t) 0x17) //!< Lock command op-code +#define SHA204_MAC ((uint8_t) 0x08) //!< MAC command op-code +#define SHA204_NONCE ((uint8_t) 0x16) //!< Nonce command op-code +#define SHA204_PAUSE ((uint8_t) 0x01) //!< Pause command op-code +#define SHA204_RANDOM ((uint8_t) 0x1B) //!< Random command op-code +#define SHA204_READ ((uint8_t) 0x02) //!< Read command op-code +#define SHA204_UPDATE_EXTRA ((uint8_t) 0x20) //!< UpdateExtra command op-code +#define SHA204_WRITE ((uint8_t) 0x12) //!< Write command op-code + +// packet size definitions +#define SHA204_RSP_SIZE_VAL ((uint8_t) 7) //!< size of response packet containing four bytes of data + +// parameter range definitions +#define SHA204_KEY_ID_MAX ((uint8_t) 15) //!< maximum value for key id +#define SHA204_OTP_BLOCK_MAX ((uint8_t) 1) //!< maximum value for OTP block + +// definitions for command packet indexes common to all commands +#define SHA204_COUNT_IDX ( 0) //!< command packet index for count +#define SHA204_OPCODE_IDX ( 1) //!< command packet index for op-code +#define SHA204_PARAM1_IDX ( 2) //!< command packet index for first parameter +#define SHA204_PARAM2_IDX ( 3) //!< command packet index for second parameter +#define SHA204_DATA_IDX ( 5) //!< command packet index for second parameter + +// zone definitions +#define SHA204_ZONE_CONFIG ((uint8_t) 0x00) //!< Configuration zone +#define SHA204_ZONE_OTP ((uint8_t) 0x01) //!< OTP (One Time Programming) zone +#define SHA204_ZONE_DATA ((uint8_t) 0x02) //!< Data zone +#define SHA204_ZONE_MASK ((uint8_t) 0x03) //!< Zone mask +#define SHA204_ZONE_COUNT_FLAG ((uint8_t) 0x80) //!< Zone bit 7 set: Access 32 bytes, otherwise 4 bytes. +#define SHA204_ZONE_ACCESS_4 ((uint8_t) 4) //!< Read or write 4 bytes. +#define SHA204_ZONE_ACCESS_32 ((uint8_t) 32) //!< Read or write 32 bytes. +#define SHA204_ADDRESS_MASK_CONFIG ( 0x001F) //!< Address bits 5 to 7 are 0 for Configuration zone. +#define SHA204_ADDRESS_MASK_OTP ( 0x000F) //!< Address bits 4 to 7 are 0 for OTP zone. +#define SHA204_ADDRESS_MASK ( 0x007F) //!< Address bit 7 to 15 are always 0. + +// CheckMAC command definitions +#define CHECKMAC_MODE_IDX SHA204_PARAM1_IDX //!< CheckMAC command index for mode +#define CHECKMAC_KEYID_IDX SHA204_PARAM2_IDX //!< CheckMAC command index for key identifier +#define CHECKMAC_CLIENT_CHALLENGE_IDX SHA204_DATA_IDX //!< CheckMAC command index for client challenge +#define CHECKMAC_CLIENT_RESPONSE_IDX (37) //!< CheckMAC command index for client response +#define CHECKMAC_DATA_IDX (69) //!< CheckMAC command index for other data +#define CHECKMAC_COUNT (84) //!< CheckMAC command packet size +#define CHECKMAC_MODE_MASK ((uint8_t) 0x27) //!< CheckMAC mode bits 3, 4, 6, and 7 are 0. +#define CHECKMAC_CLIENT_CHALLENGE_SIZE (32) //!< CheckMAC size of client challenge +#define CHECKMAC_CLIENT_RESPONSE_SIZE (32) //!< CheckMAC size of client response +#define CHECKMAC_OTHER_DATA_SIZE (13) //!< CheckMAC size of "other data" + +// DeriveKey command definitions +#define DERIVE_KEY_RANDOM_IDX SHA204_PARAM1_IDX //!< DeriveKey command index for random bit +#define DERIVE_KEY_TARGETKEY_IDX SHA204_PARAM2_IDX //!< DeriveKey command index for target slot +#define DERIVE_KEY_MAC_IDX SHA204_DATA_IDX //!< DeriveKey command index for optional MAC +#define DERIVE_KEY_COUNT_SMALL SHA204_CMD_SIZE_MIN //!< DeriveKey command packet size without MAC +#define DERIVE_KEY_COUNT_LARGE (39) //!< DeriveKey command packet size with MAC +#define DERIVE_KEY_RANDOM_FLAG ((uint8_t) 4) //!< DeriveKey 1. parameter +#define DERIVE_KEY_MAC_SIZE (32) //!< DeriveKey MAC size + +// DevRev command definitions +#define DEVREV_PARAM1_IDX SHA204_PARAM1_IDX //!< DevRev command index for 1. parameter (ignored) +#define DEVREV_PARAM2_IDX SHA204_PARAM2_IDX //!< DevRev command index for 2. parameter (ignored) +#define DEVREV_COUNT SHA204_CMD_SIZE_MIN //!< DevRev command packet size + +// GenDig command definitions +#define GENDIG_ZONE_IDX SHA204_PARAM1_IDX //!< GenDig command index for zone +#define GENDIG_KEYID_IDX SHA204_PARAM2_IDX //!< GenDig command index for key id +#define GENDIG_DATA_IDX SHA204_DATA_IDX //!< GenDig command index for optional data +#define GENDIG_COUNT SHA204_CMD_SIZE_MIN //!< GenDig command packet size without "other data" +#define GENDIG_COUNT_DATA (11) //!< GenDig command packet size with "other data" +#define GENDIG_OTHER_DATA_SIZE (4) //!< GenDig size of "other data" +#define GENDIG_ZONE_CONFIG ((uint8_t) 0) //!< GenDig zone id config +#define GENDIG_ZONE_OTP ((uint8_t) 1) //!< GenDig zone id OTP +#define GENDIG_ZONE_DATA ((uint8_t) 2) //!< GenDig zone id data + +// HMAC command definitions +#define HMAC_MODE_IDX SHA204_PARAM1_IDX //!< HMAC command index for mode +#define HMAC_KEYID_IDX SHA204_PARAM2_IDX //!< HMAC command index for key id +#define HMAC_COUNT SHA204_CMD_SIZE_MIN //!< HMAC command packet size +#define HMAC_MODE_MASK ((uint8_t) 0x74) //!< HMAC mode bits 0, 1, 3, and 7 are 0. + +// Lock command definitions +#define LOCK_ZONE_IDX SHA204_PARAM1_IDX //!< Lock command index for zone +#define LOCK_SUMMARY_IDX SHA204_PARAM2_IDX //!< Lock command index for summary +#define LOCK_COUNT SHA204_CMD_SIZE_MIN //!< Lock command packet size +#define LOCK_ZONE_NO_CONFIG ((uint8_t) 0x01) //!< Lock zone is OTP or Data +#define LOCK_ZONE_NO_CRC ((uint8_t) 0x80) //!< Lock command: Ignore summary. +#define LOCK_ZONE_MASK (0x81) //!< Lock parameter 1 bits 2 to 6 are 0. + +// Mac command definitions +#define MAC_MODE_IDX SHA204_PARAM1_IDX //!< MAC command index for mode +#define MAC_KEYID_IDX SHA204_PARAM2_IDX //!< MAC command index for key id +#define MAC_CHALLENGE_IDX SHA204_DATA_IDX //!< MAC command index for optional challenge +#define MAC_COUNT_SHORT SHA204_CMD_SIZE_MIN //!< MAC command packet size without challenge +#define MAC_COUNT_LONG (39) //!< MAC command packet size with challenge +#define MAC_MODE_BLOCK2_TEMPKEY ((uint8_t) 0x01) //!< MAC mode bit 0: second SHA block from TempKey +#define MAC_MODE_BLOCK1_TEMPKEY ((uint8_t) 0x02) //!< MAC mode bit 1: first SHA block from TempKey +#define MAC_MODE_SOURCE_FLAG_MATCH ((uint8_t) 0x04) //!< MAC mode bit 2: match TempKey.SourceFlag +#define MAC_MODE_PASSTHROUGH ((uint8_t) 0x07) //!< MAC mode bit 0-2: pass-through mode +#define MAC_MODE_INCLUDE_OTP_88 ((uint8_t) 0x10) //!< MAC mode bit 4: include first 88 OTP bits +#define MAC_MODE_INCLUDE_OTP_64 ((uint8_t) 0x20) //!< MAC mode bit 5: include first 64 OTP bits +#define MAC_MODE_INCLUDE_SN ((uint8_t) 0x40) //!< MAC mode bit 6: include serial number +#define MAC_CHALLENGE_SIZE (32) //!< MAC size of challenge +#define MAC_MODE_MASK ((uint8_t) 0x77) //!< MAC mode bits 3 and 7 are 0. + +// Nonce command definitions +#define NONCE_MODE_IDX SHA204_PARAM1_IDX //!< Nonce command index for mode +#define NONCE_PARAM2_IDX SHA204_PARAM2_IDX //!< Nonce command index for 2. parameter +#define NONCE_INPUT_IDX SHA204_DATA_IDX //!< Nonce command index for input data +#define NONCE_COUNT_SHORT (27) //!< Nonce command packet size for 20 bytes of data +#define NONCE_COUNT_LONG (39) //!< Nonce command packet size for 32 bytes of data +#define NONCE_MODE_MASK ((uint8_t) 3) //!< Nonce mode bits 2 to 7 are 0. +#define NONCE_MODE_SEED_UPDATE ((uint8_t) 0x00) //!< Nonce mode: update seed +#define NONCE_MODE_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Nonce mode: do not update seed +#define NONCE_MODE_INVALID ((uint8_t) 0x02) //!< Nonce mode 2 is invalid. +#define NONCE_MODE_PASSTHROUGH ((uint8_t) 0x03) //!< Nonce mode: pass-through +#define NONCE_NUMIN_SIZE (20) //!< Nonce data length +#define NONCE_NUMIN_SIZE_PASSTHROUGH (32) //!< Nonce data length in pass-through mode (mode = 3) + +// Pause command definitions +#define PAUSE_SELECT_IDX SHA204_PARAM1_IDX //!< Pause command index for Selector +#define PAUSE_PARAM2_IDX SHA204_PARAM2_IDX //!< Pause command index for 2. parameter +#define PAUSE_COUNT SHA204_CMD_SIZE_MIN //!< Pause command packet size + +// Random command definitions +#define RANDOM_MODE_IDX SHA204_PARAM1_IDX //!< Random command index for mode +#define RANDOM_PARAM2_IDX SHA204_PARAM2_IDX //!< Random command index for 2. parameter +#define RANDOM_COUNT SHA204_CMD_SIZE_MIN //!< Random command packet size +#define RANDOM_SEED_UPDATE ((uint8_t) 0x00) //!< Random mode for automatic seed update +#define RANDOM_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Random mode for no seed update + +// Read command definitions +#define READ_ZONE_IDX SHA204_PARAM1_IDX //!< Read command index for zone +#define READ_ADDR_IDX SHA204_PARAM2_IDX //!< Read command index for address +#define READ_COUNT SHA204_CMD_SIZE_MIN //!< Read command packet size +#define READ_ZONE_MASK ((uint8_t) 0x83) //!< Read zone bits 2 to 6 are 0. +#define READ_ZONE_MODE_32_BYTES ((uint8_t) 0x80) //!< Read mode: 32 bytes + +// UpdateExtra command definitions +#define UPDATE_MODE_IDX SHA204_PARAM1_IDX //!< UpdateExtra command index for mode +#define UPDATE_VALUE_IDX SHA204_PARAM2_IDX //!< UpdateExtra command index for new value +#define UPDATE_COUNT SHA204_CMD_SIZE_MIN //!< UpdateExtra command packet size +#define UPDATE_CONFIG_BYTE_86 ((uint8_t) 0x01) //!< UpdateExtra mode: update Config byte 86 + +// Write command definitions +#define WRITE_ZONE_IDX SHA204_PARAM1_IDX //!< Write command index for zone +#define WRITE_ADDR_IDX SHA204_PARAM2_IDX //!< Write command index for address +#define WRITE_VALUE_IDX SHA204_DATA_IDX //!< Write command index for data +#define WRITE_MAC_VS_IDX ( 9) //!< Write command index for MAC following short data +#define WRITE_MAC_VL_IDX (37) //!< Write command index for MAC following long data +#define WRITE_COUNT_SHORT (11) //!< Write command packet size with short data and no MAC +#define WRITE_COUNT_LONG (39) //!< Write command packet size with long data and no MAC +#define WRITE_COUNT_SHORT_MAC (43) //!< Write command packet size with short data and MAC +#define WRITE_COUNT_LONG_MAC (71) //!< Write command packet size with long data and MAC +#define WRITE_MAC_SIZE (32) //!< Write MAC size +#define WRITE_ZONE_MASK ((uint8_t) 0xC3) //!< Write zone bits 2 to 5 are 0. +#define WRITE_ZONE_WITH_MAC ((uint8_t) 0x40) //!< Write zone bit 6: write encrypted with MAC + +// Response size definitions +#define CHECKMAC_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of DeriveKey command +#define DERIVE_KEY_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of DeriveKey command +#define DEVREV_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of DevRev command returns 4 bytes +#define GENDIG_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of GenDig command +#define HMAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of HMAC command +#define LOCK_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Lock command +#define MAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of MAC command +#define NONCE_RSP_SIZE_SHORT SHA204_RSP_SIZE_MIN //!< response size of Nonce command with mode[0:1] = 3 +#define NONCE_RSP_SIZE_LONG SHA204_RSP_SIZE_MAX //!< response size of Nonce command +#define PAUSE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Pause command +#define RANDOM_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Random command +#define READ_4_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of Read command when reading 4 bytes +#define READ_32_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Read command when reading 32 bytes +#define TEMP_SENSE_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of TempSense command returns 4 bytes +#define UPDATE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of UpdateExtra command +#define WRITE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Write command + +// command timing definitions for minimum execution times (ms) +#define CHECKMAC_DELAY ((uint8_t) (12.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define DERIVE_KEY_DELAY ((uint8_t) (14.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define DEVREV_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define GENDIG_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define HMAC_DELAY ((uint8_t) (27.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define LOCK_DELAY ((uint8_t) ( 5.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define MAC_DELAY ((uint8_t) (12.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define NONCE_DELAY ((uint8_t) (22.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define PAUSE_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define RANDOM_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define READ_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define TEMP_SENSE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define UPDATE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) +#define WRITE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5)) + +// command timing definitions for maximum execution times (ms) +#define CHECKMAC_EXEC_MAX ((uint8_t) (38.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define DERIVE_KEY_EXEC_MAX ((uint8_t) (62.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define DEVREV_EXEC_MAX ((uint8_t) ( 2.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define GENDIG_EXEC_MAX ((uint8_t) (43.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define HMAC_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define LOCK_EXEC_MAX ((uint8_t) (24.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define MAC_EXEC_MAX ((uint8_t) (35.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define NONCE_EXEC_MAX ((uint8_t) (60.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define PAUSE_EXEC_MAX ((uint8_t) ( 2.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define RANDOM_EXEC_MAX ((uint8_t) (50.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define READ_EXEC_MAX ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define TEMP_SENSE_EXEC_MAX ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define UPDATE_EXEC_MAX ((uint8_t) ( 6.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) +#define WRITE_EXEC_MAX ((uint8_t) (42.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) + +/* from sha204_config.h */ + +#define CPU_CLOCK_DEVIATION_POSITIVE (1.01) +#define CPU_CLOCK_DEVIATION_NEGATIVE (0.99) +#define SHA204_RETRY_COUNT (1) +#define SWI_RECEIVE_TIME_OUT ((uint16_t) 163) //! #START_PULSE_TIME_OUT in us instead of loop counts +#define SWI_US_PER_BYTE ((uint16_t) 313) //! It takes 312.5 us to send a byte (9 single-wire bits / 230400 Baud * 8 flag bits). +#define SHA204_SYNC_TIMEOUT ((uint8_t) 85)//! delay before sending a transmit flag in the synchronization routine +#define SHA204_RESPONSE_TIMEOUT ((uint16_t) SWI_RECEIVE_TIME_OUT + SWI_US_PER_BYTE) //! SWI response timeout is the sum of receive timeout and the time it takes to send the TX flag. + +/* from sha204_comm.h */ + +#define SHA204_COMMAND_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) //! maximum command delay +#define SHA204_CMD_SIZE_MIN ((uint8_t) 7) //! minimum number of bytes in command (from count byte to second CRC byte) +#define SHA204_CMD_SIZE_MAX ((uint8_t) 84) //! maximum size of command packet (CheckMac) +#define SHA204_CRC_SIZE ((uint8_t) 2) //! number of CRC bytes +#define SHA204_BUFFER_POS_STATUS (1) //! buffer index of status byte in status response +#define SHA204_BUFFER_POS_DATA (1) //! buffer index of first data byte in data response +#define SHA204_STATUS_BYTE_WAKEUP ((uint8_t) 0x11) //! command parse error +#define SHA204_STATUS_BYTE_PARSE ((uint8_t) 0x03) //! command parse error +#define SHA204_STATUS_BYTE_EXEC ((uint8_t) 0x0F) //! command execution error +#define SHA204_STATUS_BYTE_COMM ((uint8_t) 0xFF) //! communication error + +/* EEPROM Addresses */ +/* Configuration Zone */ +#define ADDRESS_SN03 0 // SN[0:3] are bytes 0->3 of configuration zone +#define ADDRESS_RevNum 4 // bytes 4->7 of config zone are RevNum +#define ADDRESS_SN47 8 // SN[4:7] are bytes 8->11 of config zone +#define ADDRESS_SN8 12 // SN[8] is byte 12 of config zone, should be 0xEE +#define ADDRESS_I2CEN 14 // I2C Enable, bit 0 represents I2C enable status +#define ADDRESS_I2CADD 16 // Defines I2C address of SHA204 +#define ADDRESS_OTPMODE 18 // Sets the One-time-programmable mode +#define ADDRESS_SELECTOR 19 // Controls writability of Selector + + +class atsha204Class +{ +private: + uint8_t device_pin; + volatile uint8_t *device_port_DDR, *device_port_OUT, *device_port_IN; + void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc); + uint8_t sha204c_check_crc(uint8_t *response); + void swi_set_signal_pin(uint8_t is_high); + uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer); + uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer); + uint8_t swi_send_byte(uint8_t value); + uint8_t sha204p_receive_response(uint8_t size, uint8_t *response); + uint8_t sha204p_wakeup(); + uint8_t sha204p_send_command(uint8_t count, uint8_t * command); + uint8_t sha204p_sleep(); + uint8_t sha204p_resync(uint8_t size, uint8_t *response); + + +public: + atsha204Class(uint8_t pin); // Constructor + uint8_t sha204c_wakeup(uint8_t *response); + uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout); + uint8_t sha204c_resync(uint8_t size, uint8_t *response); + uint8_t sha204m_random(uint8_t * tx_buffer, uint8_t * rx_buffer, uint8_t mode); + uint8_t sha204m_dev_rev(uint8_t *tx_buffer, uint8_t *rx_buffer); + uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address); + uint8_t sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2, + uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3, + uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); + uint8_t sha204m_check_parameters(uint8_t op_code, uint8_t param1, uint16_t param2, + uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3, + uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); + + uint8_t getSerialNumber(uint8_t *response); + uint16_t calculateAndUpdateCrc(uint8_t length, uint8_t *data, uint16_t current_crc); + +}; + +#endif