From c7a68c0205cd87aa220b399584d6333ac60aa6d3 Mon Sep 17 00:00:00 2001 From: topicchi Date: Tue, 24 Sep 2024 16:54:39 +0000 Subject: [PATCH] --- .../Birthday_Candles/Birthday_Candles.ino | 3 +- .../library.properties | 2 +- .../utility/CPlay_CapacitiveSensor.cpp | 24 +- .../Adafruit_GFX_Library/Adafruit_SPITFT.cpp | 30 +- .../Fonts/FreeMono12pt7b.h | 3 + .../Fonts/FreeMono18pt7b.h | 3 + .../Fonts/FreeMono24pt7b.h | 3 + .../Fonts/FreeMono9pt7b.h | 3 + .../Fonts/FreeMonoBold12pt7b.h | 3 + .../Fonts/FreeMonoBold18pt7b.h | 3 + .../Fonts/FreeMonoBold24pt7b.h | 3 + .../Fonts/FreeMonoBold9pt7b.h | 3 + .../Fonts/FreeMonoBoldOblique12pt7b.h | 3 + .../Fonts/FreeMonoBoldOblique18pt7b.h | 3 + .../Fonts/FreeMonoBoldOblique24pt7b.h | 3 + .../Fonts/FreeMonoBoldOblique9pt7b.h | 3 + .../Fonts/FreeMonoOblique12pt7b.h | 3 + .../Fonts/FreeMonoOblique18pt7b.h | 3 + .../Fonts/FreeMonoOblique24pt7b.h | 3 + .../Fonts/FreeMonoOblique9pt7b.h | 3 + .../Fonts/FreeSans12pt7b.h | 3 + .../Fonts/FreeSans18pt7b.h | 3 + .../Fonts/FreeSans24pt7b.h | 3 + .../Fonts/FreeSans9pt7b.h | 3 + .../Fonts/FreeSansBold12pt7b.h | 3 + .../Fonts/FreeSansBold18pt7b.h | 3 + .../Fonts/FreeSansBold24pt7b.h | 3 + .../Fonts/FreeSansBold9pt7b.h | 3 + .../Fonts/FreeSansBoldOblique12pt7b.h | 3 + .../Fonts/FreeSansBoldOblique18pt7b.h | 3 + .../Fonts/FreeSansBoldOblique24pt7b.h | 3 + .../Fonts/FreeSansBoldOblique9pt7b.h | 3 + .../Fonts/FreeSansOblique12pt7b.h | 3 + .../Fonts/FreeSansOblique18pt7b.h | 3 + .../Fonts/FreeSansOblique24pt7b.h | 3 + .../Fonts/FreeSansOblique9pt7b.h | 3 + .../Fonts/FreeSerif12pt7b.h | 3 + .../Fonts/FreeSerif18pt7b.h | 3 + .../Fonts/FreeSerif24pt7b.h | 3 + .../Fonts/FreeSerif9pt7b.h | 3 + .../Fonts/FreeSerifBold12pt7b.h | 3 + .../Fonts/FreeSerifBold18pt7b.h | 3 + .../Fonts/FreeSerifBold24pt7b.h | 3 + .../Fonts/FreeSerifBold9pt7b.h | 3 + .../Fonts/FreeSerifBoldItalic12pt7b.h | 3 + .../Fonts/FreeSerifBoldItalic18pt7b.h | 3 + .../Fonts/FreeSerifBoldItalic24pt7b.h | 3 + .../Fonts/FreeSerifBoldItalic9pt7b.h | 3 + .../Fonts/FreeSerifItalic12pt7b.h | 3 + .../Fonts/FreeSerifItalic18pt7b.h | 3 + .../Fonts/FreeSerifItalic24pt7b.h | 3 + .../Fonts/FreeSerifItalic9pt7b.h | 3 + .../Adafruit_GFX_Library/Fonts/Org_01.h | 3 + .../Adafruit_GFX_Library/Fonts/Picopixel.h | 3 + .../Fonts/Tiny3x3a2pt7b.h | 3 + .../Adafruit_GFX_Library/Fonts/TomThumb.h | 3 + .../Adafruit_GFX_Library/library.properties | 2 +- .../library.properties | 2 +- .../Adafruit_Sensor.cpp | 42 ++ .../Adafruit_Unified_Sensor/Adafruit_Sensor.h | 50 +- .../Adafruit_Unified_Sensor/README.md | 58 +- .../library.properties | 2 +- trunk/Arduino/libraries/ArduinoOTA/README.md | 90 ++- .../examples/ATmega_SD/ATmega_SD.ino | 1 + .../OTASketchDownload/OTASketchDownload.ino | 4 +- .../examples/OTEthernet/OTEthernet.ino | 1 + .../examples/OTEthernet_SD/OTEthernet_SD.ino | 1 + .../examples/SerialWiFiOTA/SerialWiFiOTA.ino | 14 +- .../ArduinoOTA/extras/avr/platform.local.txt | 1 + .../libraries/ArduinoOTA/library.properties | 4 +- .../libraries/ArduinoOTA/src/ArduinoOTA.h | 42 +- .../ArduinoOTA/src/InternalStorage.cpp | 20 +- .../libraries/ArduinoOTA/src/OTAStorage.cpp | 9 +- .../libraries/DHT_sensor_library/DHT.cpp | 4 +- .../libraries/DHT_sensor_library/DHT.h | 12 +- .../examples/DHTtester/DHTtester.ino | 3 +- .../DHT_sensor_library/library.properties | 2 +- .../libraries/EspSoftwareSerial/README.md | 95 ++- .../examples/loopback/loopback.ino | 48 +- .../examples/onewiretest/onewiretest.ino | 63 +- .../examples/repeater/repeater.ino | 40 +- .../examples/swsertest/swsertest.ino | 81 ++- .../libraries/EspSoftwareSerial/keywords.txt | 4 +- .../libraries/EspSoftwareSerial/library.json | 21 +- .../EspSoftwareSerial/library.properties | 2 +- .../EspSoftwareSerial/src/SoftwareSerial.cpp | 474 +++++++------ .../EspSoftwareSerial/src/SoftwareSerial.h | 335 +++++++-- .../src/circular_queue/Delegate.h | 195 ++++-- .../src/circular_queue/MultiDelegate.h | 4 +- .../src/circular_queue/circular_queue.h | 90 +-- .../src/circular_queue/circular_queue_mp.h | 348 ++++++---- .../src/circular_queue/ghostl.h | 2 +- .../libraries/Ethernet/library.properties | 2 +- .../libraries/Ethernet/src/Ethernet.cpp | 16 +- .../libraries/IRremote/Contributing.md | 18 +- .../libraries/IRremote/Contributors.md | 5 + trunk/Arduino/libraries/IRremote/Doxyfile | 13 +- trunk/Arduino/libraries/IRremote/README.md | 651 ++++++++++++------ trunk/Arduino/libraries/IRremote/changelog.md | 86 +++ .../examples/IRremoteInfo/IRremoteInfo.ino | 13 + .../IRremote/examples/MicroGirs/MicroGirs.ino | 216 +++--- trunk/Arduino/libraries/IRremote/keywords.txt | 4 +- trunk/Arduino/libraries/IRremote/library.json | 5 +- .../libraries/IRremote/library.properties | 6 +- .../Arduino/libraries/IRremote/src/IRremote.h | 604 ++-------------- .../libraries/Keyboard/library.properties | 2 +- .../Arduino/libraries/Keyboard/src/Keyboard.h | 2 + trunk/Arduino/libraries/OneWire/library.json | 2 +- .../libraries/OneWire/library.properties | 2 +- .../OneWire/util/OneWire_direct_gpio.h | 67 +- .../OneWire/util/OneWire_direct_regtype.h | 3 + trunk/Arduino/libraries/SdFat/LICENSE.md | 2 +- trunk/Arduino/libraries/SdFat/README.md | 11 +- .../DirectoryFunctions/DirectoryFunctions.ino | 9 +- .../SdFat/examples/OpenNext/OpenNext.ino | 6 +- .../SdFat/examples/QuickStart/QuickStart.ino | 39 +- .../examples/SdFormatter/SdFormatter.ino | 74 +- .../SdFat/examples/SdInfo/SdInfo.ino | 45 +- .../examples/SoftwareSpi/SoftwareSpi.ino | 4 +- .../TeensySdioDemo/TeensySdioDemo.ino | 43 +- .../libraries/SdFat/examples/bench/bench.ino | 39 +- .../SdFat/examples/rename/rename.ino | 7 +- .../Arduino/libraries/SdFat/extras/cpplint.py | 2 +- .../libraries/SdFat/library.properties | 2 +- .../libraries/SdFat/src/FatLib/FatFile.cpp | 177 +++-- .../libraries/SdFat/src/FatLib/FatFile.h | 176 ++--- .../libraries/SdFat/src/FatLib/FatFileLFN.cpp | 111 ++- .../SdFat/src/FatLib/FatFilePrint.cpp | 4 +- .../libraries/SdFat/src/FatLib/FatFileSFN.cpp | 24 +- .../libraries/SdFat/src/FatLib/FatLib.h | 2 +- .../libraries/SdFat/src/FatLib/FatVolume.cpp | 4 +- .../libraries/SdFat/src/FatLib/FatVolume.h | 48 +- trunk/Arduino/libraries/SdFat/src/FreeStack.h | 12 +- .../libraries/SdFat/src/MinimumSerial.cpp | 15 +- .../libraries/SdFat/src/MinimumSerial.h | 4 +- .../libraries/SdFat/src/SdCard/SdSpiCard.cpp | 196 +++--- .../libraries/SdFat/src/SdCard/SdSpiCard.h | 147 ++-- .../libraries/SdFat/src/SdCard/SdioCard.h | 26 +- .../libraries/SdFat/src/SdCard/SdioTeensy.cpp | 358 +++++----- trunk/Arduino/libraries/SdFat/src/SdFat.h | 62 +- .../Arduino/libraries/SdFat/src/SdFatConfig.h | 49 +- .../SdFat/src/SpiDriver/SdSpiDriver.h | 27 +- .../SdFat/src/SpiDriver/SdSpiParticle.cpp | 31 +- .../SdFat/src/SpiDriver/SdSpiSTM32.cpp | 82 +-- .../SdFat/src/SpiDriver/SdSpiTeensy3.cpp | 26 +- trunk/Arduino/libraries/SdFat/src/sdios.h | 2 +- trunk/Arduino/libraries/Servo/docs/api.md | 14 +- trunk/Arduino/libraries/Servo/docs/readme.md | 4 +- .../libraries/Servo/examples/Knob/readme.md | 2 +- .../examples/Sweep/images/sweep_schem.png | Bin 20480 -> 11238 bytes .../libraries/Servo/examples/Sweep/readme.md | 4 +- .../libraries/Servo/library.properties | 4 +- trunk/Arduino/libraries/Servo/src/Servo.h | 4 +- .../libraries/Servo/src/mbed/Servo.cpp | 14 +- .../libraries/Servo/src/mbed/ServoTimers.h | 2 +- .../libraries/TFT_eSPI/Extensions/Button.h | 4 +- .../TFT_eSPI/Extensions/Smooth_font.cpp | 26 +- .../libraries/TFT_eSPI/Extensions/Sprite.cpp | 52 +- .../libraries/TFT_eSPI/Extensions/Sprite.h | 24 +- .../libraries/TFT_eSPI/Extensions/Touch.cpp | 6 +- .../libraries/TFT_eSPI/Extensions/Touch.h | 5 +- .../libraries/TFT_eSPI/Fonts/Font32rle.c | 2 +- .../libraries/TFT_eSPI/Fonts/Font64rle.c | 2 +- .../libraries/TFT_eSPI/Fonts/Font72rle.c | 2 +- .../libraries/TFT_eSPI/Fonts/Font72x53rle.c | 2 +- .../libraries/TFT_eSPI/Fonts/Font7srle.c | 2 +- .../libraries/TFT_eSPI/Fonts/glcdfont.c | 5 +- .../TFT_eSPI/Processors/TFT_eSPI_ESP32.c | 323 ++++++--- .../TFT_eSPI/Processors/TFT_eSPI_ESP32.h | 339 ++++++--- .../TFT_eSPI/Processors/TFT_eSPI_ESP8266.c | 6 +- .../TFT_eSPI/Processors/TFT_eSPI_ESP8266.h | 21 +- .../TFT_eSPI/Processors/TFT_eSPI_Generic.c | 10 +- .../TFT_eSPI/Processors/TFT_eSPI_Generic.h | 68 +- .../TFT_eSPI/Processors/TFT_eSPI_STM32.c | 263 ++++--- .../TFT_eSPI/Processors/TFT_eSPI_STM32.h | 533 ++++++++------ trunk/Arduino/libraries/TFT_eSPI/README.md | 100 +-- trunk/Arduino/libraries/TFT_eSPI/README.txt | 4 +- .../TFT_eSPI/TFT_Drivers/HX8357D_Init.h | 4 +- .../TFT_eSPI/TFT_Drivers/ILI9163_Defines.h | 9 +- .../TFT_eSPI/TFT_Drivers/ILI9341_Defines.h | 10 +- .../TFT_eSPI/TFT_Drivers/ILI9341_Init.h | 2 +- .../TFT_eSPI/TFT_Drivers/ILI9481_Init.h | 34 +- .../TFT_eSPI/TFT_Drivers/ILI9486_Defines.h | 9 +- .../TFT_eSPI/TFT_Drivers/ILI9486_Init.h | 6 +- .../TFT_eSPI/TFT_Drivers/ILI9488_Init.h | 6 +- .../TFT_eSPI/TFT_Drivers/R61581_Init.h | 2 +- .../TFT_eSPI/TFT_Drivers/RM68140_Init.h | 2 +- .../TFT_eSPI/TFT_Drivers/S6D02A1_Defines.h | 9 +- .../TFT_eSPI/TFT_Drivers/ST7735_Defines.h | 9 +- .../TFT_eSPI/TFT_Drivers/ST7789_Init.h | 7 +- .../TFT_eSPI/TFT_Drivers/ST7796_Defines.h | 15 +- .../TFT_eSPI/TFT_Drivers/ST7796_Init.h | 2 +- .../TFT_eSPI/TFT_Drivers/ST7796_Rotation.h | 28 + trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.cpp | 467 +++++++------ trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.h | 100 ++- .../Create_font/Create_font.pde | 61 +- .../Screenshot_client/Screenshot_client.pde | 2 +- trunk/Arduino/libraries/TFT_eSPI/User_Setup.h | 34 +- .../libraries/TFT_eSPI/User_Setup_Select.h | 65 +- .../User_Setups/Setup13_ILI9481_Parallel.h | 2 +- .../TFT_eSPI/User_Setups/Setup17_ePaper.h | 33 +- .../User_Setups/Setup22_TTGO_T4_v1.3.h | 5 +- .../User_Setups/Setup26_TTGO_T_Wristband.h | 2 + .../User_Setups/Setup27_RPi_ST7796_ESP32.h | 4 +- .../User_Setups/Setup28_RPi_ST7796_ESP8266.h | 3 +- .../User_Setups/Setup29_ILI9341_STM32.h | 33 +- .../Setup30_ILI9341_Parallel_STM32.h | 8 +- .../Setup31_ST7796_Parallel_STM32.h | 6 +- .../User_Setups/Setup32_ILI9341_STM32F103.h | 1 + .../User_Setups/Setup33_RPi_ILI9486_STM32.h | 4 +- .../Setup34_ILI9481_Parallel_STM32.h | 6 +- .../Setup35_ILI9341_STM32_Port_Bus.h | 10 +- .../User_Setups/Setup44_TTGO_CameraPlus.h | 2 + .../User_Setups/Setup45_TTGO_T_Watch.h | 2 + .../TFT_eSPI/User_Setups/SetupX_Template.h | 14 +- .../TFT_eSPI/User_Setups/User_Custom_Fonts.h | 4 +- .../160 x 128/TFT_Ellipse/TFT_Ellipse.ino | 4 +- .../160 x 128/TFT_Meter_5/TFT_Meter_5.ino | 2 +- .../TFT_Print_Test/TFT_Print_Test.ino | 2 +- .../160 x 128/TFT_Rainbow/TFT_Rainbow.ino | 2 +- .../160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino | 6 +- .../All_Free_Fonts_Demo.ino | 2 +- .../Free_Font_Demo/Free_Font_Demo.ino | 2 +- .../Keypad_240x320/Keypad_240x320.ino | 8 +- .../Read_ID_bitbash/Read_ID_bitbash.ino | 4 +- .../320 x 240/TFT_ArcFill/TFT_ArcFill.ino | 10 +- .../TFT_Custom_Fonts/TFT_Custom_Fonts.ino | 2 +- .../TFT_FillArcSpiral/TFT_FillArcSpiral.ino | 8 +- .../TFT_Mandlebrot/TFT_Mandlebrot.ino | 2 +- .../TFT_Meter_linear/TFT_Meter_linear.ino | 6 +- .../320 x 240/TFT_Meters/TFT_Meters.ino | 4 +- .../320 x 240/TFT_Pie_Chart/TFT_Pie_Chart.ino | 6 +- .../TFT_Print_Test/TFT_Print_Test.ino | 2 +- .../TFT_Rainbow_one_lib.ino | 4 +- .../320 x 240/TFT_Read_Reg/TFT_Read_Reg.ino | 6 +- .../320 x 240/TFT_Spiro/TFT_Spiro.ino | 4 +- .../320 x 240/TFT_Starfield/TFT_Starfield.ino | 4 +- .../320 x 240/TFT_Terminal/TFT_Terminal.ino | 2 +- .../Free_Font_Demo/Free_Font_Demo.ino | 2 +- .../Keypad_480x320/Keypad_480x320.ino | 8 +- .../480 x 320/TFT_Meter_4/TFT_Meter_4.ino | 6 +- .../480 x 320/TFT_Meters/TFT_Meters.ino | 4 +- .../TFT_Print_Test/TFT_Print_Test.ino | 2 +- .../TFT_Rainbow480/TFT_Rainbow480.ino | 4 +- .../480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino | 8 +- .../TFT_ring_meter/TFT_ring_meter.ino | 12 +- .../Touch_Controller_Demo.ino | 2 +- .../examples/DMA test/Flash_Jpg_DMA/panda.h | 10 +- .../SpriteRotatingCube/SpriteRotatingCube.ino | 10 +- .../DMA test/boing_ball/boing_ball.ino | 12 +- .../ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino | 4 +- .../ESP8266_uncannyEyes.ino | 4 +- .../screenshotToConsole.ino | 2 +- .../TFT_Button_Label_Datum.ino | 4 +- .../TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino | 2 +- .../Generic/TFT_SPIFFS_BMP/BMP_functions.ino | 2 +- .../TFT_Screen_Capture/processing_sketch.ino | 2 +- .../TFT_Screen_Capture/screenServer.ino | 12 +- .../alphaBlend_Test/alphaBlend_Test.ino | 18 +- .../Font_Demo_1_Array/Font_Demo_1_Array.ino | 12 +- .../Font_Demo_1_Array/NotoSansBold15.h | 4 +- .../Font_Demo_1_Array/NotoSansBold36.h | 4 +- .../Font_Demo_2_Array/Font_Demo_2_Array.ino | 10 +- .../Font_Demo_2_Array/NotoSansBold15.h | 4 +- .../Font_Demo_2_Array/NotoSansBold36.h | 4 +- .../Font_Demo_3_Array/Font_Demo_3_Array.ino | 12 +- .../Font_Demo_3_Array/NotoSansBold15.h | 4 +- .../Font_Demo_3_Array/NotoSansBold36.h | 4 +- .../Font_Demo_3_Array/NotoSansMonoSCB20.h | 4 +- .../Font_Demo_4_Array/Font_Demo_4_Array.ino | 2 +- .../Font_Demo_4_Array/NotoSansBold15.h | 4 +- .../Font_Demo_4_Array/NotoSansBold36.h | 4 +- .../Print_Smooth_Font/Final_Frontier_28.h | 4 +- .../Print_Smooth_Font/Print_Smooth_Font.ino | 8 +- .../Smooth_font_gradient/NotoSansBold15.h | 4 +- .../Smooth_font_gradient/NotoSansBold36.h | 4 +- .../Smooth_font_gradient.ino | 4 +- .../Smooth_font_reading_TFT/NotoSansBold15.h | 4 +- .../Smooth_font_reading_TFT/NotoSansBold36.h | 4 +- .../Smooth_font_reading_TFT.ino | 6 +- .../Unicode_test/Final_Frontier_28.h | 4 +- .../Unicode_test/Latin_Hiragana_24.h | 4 +- .../Unicode_test/Unicode_Test_72.h | 4 +- .../FLASH_Array/Unicode_test/Unicode_test.ino | 6 +- .../ESP32_Smooth_Font_SD.ino | 8 +- .../SPIFFS/Font_Demo_1/Font_Demo_1.ino | 10 +- .../SPIFFS/Font_Demo_2/Font_Demo_2.ino | 10 +- .../SPIFFS/Font_Demo_3/Font_Demo_3.ino | 14 +- .../SPIFFS/Font_Demo_4/Font_Demo_4.ino | 4 +- .../Print_Smooth_Font/Print_Smooth_Font.ino | 10 +- .../Smooth_font_gradient.ino | 6 +- .../Smooth_font_reading_TFT.ino | 8 +- .../SPIFFS/Unicode_test/Unicode_test.ino | 4 +- .../Sprite/Animated_dial/Animated_dial.ino | 19 +- .../Sprite/Animated_dial/NotoSansBold36.h | 4 +- .../examples/Sprite/Animated_dial/dial.h | 4 +- .../One_bit_Sprite_Demo.ino | 2 +- .../Rotated_Sprite_1/Rotated_Sprite_1.ino | 4 +- .../Rotated_Sprite_2/Rotated_Sprite_2.ino | 2 +- .../Rotated_Sprite_3/Rotated_Sprite_3.ino | 4 +- .../Sprite_RLE_Font_test.ino | 2 +- .../Sprite/Sprite_draw/Sprite_draw.ino | 12 +- .../Sprite_draw_4bit/Sprite_draw_4bit.ino | 8 +- .../Sprite_image_4bit/Sprite_image_4bit.ino | 12 +- .../Sprite/Sprite_scroll/Sprite_scroll.ino | 4 +- .../Sprite_scroll_16bit.ino | 6 +- .../Sprite_scroll_1bit/Sprite_scroll_1bit.ino | 4 +- .../Sprite_scroll_4bit/Sprite_scroll_4bit.ino | 6 +- .../Sprite_scroll_8bit/Sprite_scroll_8bit.ino | 16 +- .../Sprite_scroll_wrap_1bit.ino | 2 +- .../Transparent_Sprite_Demo.ino | 10 +- .../Transparent_Sprite_Demo_4bit.ino | 14 +- .../Colour_Test/Colour_Test.ino | 69 +- .../Read_User_Setup/Read_User_Setup.ino | 2 +- .../Floyd_Steinberg/Floyd_Steinberg.ino | 2 +- .../Floyd_Steinberg/Floyd_Steinberg_BMP.ino | 12 +- trunk/Arduino/libraries/TFT_eSPI/library.json | 2 +- .../libraries/TFT_eSPI/library.properties | 4 +- trunk/Arduino/libraries/TFT_eSPI/license.txt | 8 +- trunk/Arduino/libraries/Ticker/README.md | 251 +++++-- trunk/Arduino/libraries/Ticker/Ticker.cpp | 37 +- trunk/Arduino/libraries/Ticker/Ticker.h | 31 +- .../Ticker/examples/Ticker/Ticker.ino | 2 +- trunk/Arduino/libraries/Ticker/keywords.txt | 1 + trunk/Arduino/libraries/Ticker/library.json | 2 +- .../libraries/Ticker/library.properties | 2 +- trunk/Arduino/libraries/TimerOne/README.md | 6 +- trunk/Arduino/libraries/TimerOne/TimerOne.cpp | 23 +- trunk/Arduino/libraries/TimerOne/TimerOne.h | 329 ++++++++- .../TimerOne/config/known_16bit_timers.h | 56 +- trunk/Arduino/libraries/TimerOne/library.json | 2 +- .../libraries/TimerOne/library.properties | 4 +- 332 files changed, 6098 insertions(+), 4139 deletions(-) diff --git a/trunk/Arduino/libraries/Adafruit_Circuit_Playground/examples/Microphone_Demos/Birthday_Candles/Birthday_Candles.ino b/trunk/Arduino/libraries/Adafruit_Circuit_Playground/examples/Microphone_Demos/Birthday_Candles/Birthday_Candles.ino index f9f96ef3..22262bbd 100644 --- a/trunk/Arduino/libraries/Adafruit_Circuit_Playground/examples/Microphone_Demos/Birthday_Candles/Birthday_Candles.ino +++ b/trunk/Arduino/libraries/Adafruit_Circuit_Playground/examples/Microphone_Demos/Birthday_Candles/Birthday_Candles.ino @@ -233,13 +233,14 @@ void animatePixels(uint32_t current) { // NeoPixel writing like the other animations. The pixels are instead // changed only once when the number of lit candles changes (see the // waitBreath function's loop). + default: break; } } // Helper to change the color of a NeoPixel on the Circuit Playground board. // Will automatically convert from HSV color space to RGB and apply gamma // correction. -float setPixelHSV(int i, float h, float s, float v) { +void setPixelHSV(int i, float h, float s, float v) { // Convert HSV to RGB float r, g, b = 0.0; HSVtoRGB(&r, &g, &b, h, s, v); diff --git a/trunk/Arduino/libraries/Adafruit_Circuit_Playground/library.properties b/trunk/Arduino/libraries/Adafruit_Circuit_Playground/library.properties index e5b9f1db..2f3516e2 100644 --- a/trunk/Arduino/libraries/Adafruit_Circuit_Playground/library.properties +++ b/trunk/Arduino/libraries/Adafruit_Circuit_Playground/library.properties @@ -1,5 +1,5 @@ name=Adafruit Circuit Playground -version=1.11.5 +version=1.12.0 author=Adafruit maintainer=Adafruit sentence=All in one library to control Adafruit's Circuit Playground board. diff --git a/trunk/Arduino/libraries/Adafruit_Circuit_Playground/utility/CPlay_CapacitiveSensor.cpp b/trunk/Arduino/libraries/Adafruit_Circuit_Playground/utility/CPlay_CapacitiveSensor.cpp index cb12f79e..3374b076 100644 --- a/trunk/Arduino/libraries/Adafruit_Circuit_Playground/utility/CPlay_CapacitiveSensor.cpp +++ b/trunk/Arduino/libraries/Adafruit_Circuit_Playground/utility/CPlay_CapacitiveSensor.cpp @@ -46,13 +46,13 @@ CPlay_CapacitiveSensor::CPlay_CapacitiveSensor(uint8_t sendPin, uint8_t receiveP if ((sendPin != 255) && (sendPin >= NUM_DIGITAL_PINS)) error = -3; if (receivePin >= NUM_DIGITAL_PINS) error = -2; #endif - if (sendPin != -1) { // sendpin to OUTPUT if we have one + if (sendPin != 255) { // sendpin to OUTPUT if we have one #ifdef ARDUINO_TEEONARDU_FLORA // terrible hack! - DDRD |= _BV(5); + DDRD |= _BV(5); #else - pinMode(sendPin, OUTPUT); + pinMode(sendPin, OUTPUT); #endif - } + } pinMode(receivePin, INPUT); // receivePin to INPUT @@ -63,13 +63,13 @@ CPlay_CapacitiveSensor::CPlay_CapacitiveSensor(uint8_t sendPin, uint8_t receiveP digitalWrite(sendPin, LOW); #endif - if (sendPin != -1) { - send_outport = portOutputRegister(digitalPinToPort(sendPin)); - send_mask = digitalPinToBitMask(sendPin); - } else { - send_outport = NULL; - send_mask = 0; - } + if (sendPin != 255) { + send_outport = portOutputRegister(digitalPinToPort(sendPin)); + send_mask = digitalPinToBitMask(sendPin); + } else { + send_outport = NULL; + send_mask = 0; + } recv_outport = portOutputRegister(digitalPinToPort(receivePin)); recv_inport = portInputRegister(digitalPinToPort(receivePin)); @@ -216,7 +216,7 @@ int CPlay_CapacitiveSensor::SenseOneCycle(void) } //Serial.print("SenseOneCycle(1): "); Serial.println(total); - if (total > CS_Timeout_Millis) { + if (total >= CS_Timeout_Millis) { return -2; // total variable over timeout } } diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Adafruit_SPITFT.cpp b/trunk/Arduino/libraries/Adafruit_GFX_Library/Adafruit_SPITFT.cpp index 2c8ef01b..eeffce78 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Adafruit_SPITFT.cpp +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Adafruit_SPITFT.cpp @@ -1348,7 +1348,7 @@ void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len) { if (pixelsThisPass > 50000) pixelsThisPass = 50000; len -= pixelsThisPass; - yield(); // Periodic yield() on long fills + delay(1); // Periodic delay on long fills while (pixelsThisPass--) { hwspi._spi->write(hi); hwspi._spi->write(lo); @@ -2305,10 +2305,6 @@ inline void Adafruit_SPITFT::SPI_MOSI_HIGH(void) { #endif // end !HAS_PORT_SET_CLR #else // !USE_FAST_PINIO digitalWrite(swspi._mosi, HIGH); -#if defined(ESP32) - for (volatile uint8_t i = 0; i < 1; i++) - ; -#endif // end ESP32 #endif // end !USE_FAST_PINIO } @@ -2328,10 +2324,6 @@ inline void Adafruit_SPITFT::SPI_MOSI_LOW(void) { #endif // end !HAS_PORT_SET_CLR #else // !USE_FAST_PINIO digitalWrite(swspi._mosi, LOW); -#if defined(ESP32) - for (volatile uint8_t i = 0; i < 1; i++) - ; -#endif // end ESP32 #endif // end !USE_FAST_PINIO } @@ -2343,22 +2335,14 @@ inline void Adafruit_SPITFT::SPI_SCK_HIGH(void) { #if defined(HAS_PORT_SET_CLR) #if defined(KINETISK) *swspi.sckPortSet = 1; -#else // !KINETISK +#else // !KINETISK *swspi.sckPortSet = swspi.sckPinMask; -#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x - for (volatile uint8_t i = 0; i < 1; i++) - ; -#endif #endif #else // !HAS_PORT_SET_CLR *swspi.sckPort |= swspi.sckPinMaskSet; #endif // end !HAS_PORT_SET_CLR #else // !USE_FAST_PINIO digitalWrite(swspi._sck, HIGH); -#if defined(ESP32) - for (volatile uint8_t i = 0; i < 1; i++) - ; -#endif // end ESP32 #endif // end !USE_FAST_PINIO } @@ -2370,22 +2354,14 @@ inline void Adafruit_SPITFT::SPI_SCK_LOW(void) { #if defined(HAS_PORT_SET_CLR) #if defined(KINETISK) *swspi.sckPortClr = 1; -#else // !KINETISK +#else // !KINETISK *swspi.sckPortClr = swspi.sckPinMask; -#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x - for (volatile uint8_t i = 0; i < 1; i++) - ; -#endif #endif #else // !HAS_PORT_SET_CLR *swspi.sckPort &= swspi.sckPinMaskClr; #endif // end !HAS_PORT_SET_CLR #else // !USE_FAST_PINIO digitalWrite(swspi._sck, LOW); -#if defined(ESP32) - for (volatile uint8_t i = 0; i < 1; i++) - ; -#endif // end ESP32 #endif // end !USE_FAST_PINIO } diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono12pt7b.h index effbf4d1..d124f207 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMono12pt7bBitmaps[] PROGMEM = { 0x49, 0x24, 0x92, 0x48, 0x01, 0xF8, 0xE7, 0xE7, 0x67, 0x42, 0x42, 0x42, 0x42, 0x09, 0x02, 0x41, 0x10, 0x44, 0x11, 0x1F, 0xF1, 0x10, 0x4C, 0x12, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono18pt7b.h index 2361c981..6a3641c3 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMono18pt7bBitmaps[] PROGMEM = { 0x27, 0x77, 0x77, 0x77, 0x77, 0x22, 0x22, 0x20, 0x00, 0x6F, 0xF6, 0xF1, 0xFE, 0x3F, 0xC7, 0xF8, 0xFF, 0x1E, 0xC3, 0x98, 0x33, 0x06, 0x60, 0xCC, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono24pt7b.h index 8596d0ab..2540ed49 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMono24pt7bBitmaps[] PROGMEM = { 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x10, 0x84, 0x21, 0x08, 0x00, 0x00, 0x00, 0x03, 0xBF, 0xFF, 0xB8, 0xFE, 0x7F, 0x7C, 0x3E, 0x7C, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono9pt7b.h index a3034eb0..a2e9a00d 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMono9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMono9pt7bBitmaps[] PROGMEM = { 0xAA, 0xA8, 0x0C, 0xED, 0x24, 0x92, 0x48, 0x24, 0x48, 0x91, 0x2F, 0xE4, 0x89, 0x7F, 0x28, 0x51, 0x22, 0x40, 0x08, 0x3E, 0x62, 0x40, 0x30, 0x0E, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold12pt7b.h index 9faf3518..a205386a 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBold12pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xF6, 0x66, 0x60, 0x6F, 0x60, 0xE7, 0xE7, 0x62, 0x42, 0x42, 0x42, 0x42, 0x11, 0x87, 0x30, 0xC6, 0x18, 0xC3, 0x31, 0xFF, 0xFF, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold18pt7b.h index fee446bb..36664c1d 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBold18pt7bBitmaps[] PROGMEM = { 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x9C, 0xE7, 0x39, 0xC4, 0x03, 0xBF, 0xFF, 0xB8, 0xF1, 0xFE, 0x3F, 0xC7, 0xF8, 0xFF, 0x1E, 0xC1, 0x98, 0x33, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold24pt7b.h index 5ff07d40..eb79d6e8 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBold24pt7bBitmaps[] PROGMEM = { 0x38, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE3, 0x82, 0x00, 0x00, 0x00, 0x71, 0xF7, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold9pt7b.h index 3fb82aac..44320f81 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBold9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBold9pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xD2, 0x1F, 0x80, 0xEC, 0x89, 0x12, 0x24, 0x40, 0x36, 0x36, 0x36, 0x7F, 0x7F, 0x36, 0xFF, 0xFF, 0x3C, 0x3C, 0x3C, 0x00, 0x18, 0xFF, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique12pt7b.h index 6f18c478..095fdd34 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBoldOblique12pt7bBitmaps[] PROGMEM = { 0x1C, 0xF3, 0xCE, 0x38, 0xE7, 0x1C, 0x61, 0x86, 0x00, 0x63, 0x8C, 0x00, 0xE7, 0xE7, 0xE6, 0xC6, 0xC6, 0xC4, 0x84, 0x03, 0x30, 0x19, 0x81, 0xDC, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique18pt7b.h index 76b07640..0400f254 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBoldOblique18pt7bBitmaps[] PROGMEM = { 0x0F, 0x07, 0xC7, 0xE3, 0xF1, 0xF0, 0xF8, 0xFC, 0x7C, 0x3E, 0x1F, 0x0F, 0x07, 0x87, 0xC3, 0xC1, 0xE0, 0x60, 0x00, 0x38, 0x3E, 0x1F, 0x0F, 0x83, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique24pt7b.h index b0c33706..ac923bff 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBoldOblique24pt7bBitmaps[] PROGMEM = { 0x01, 0xE0, 0x3F, 0x07, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xC0, 0xFC, 0x1F, 0xC1, 0xF8, 0x1F, 0x81, 0xF8, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique9pt7b.h index 334ab7b9..86d3e9c7 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoBoldOblique9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoBoldOblique9pt7bBitmaps[] PROGMEM = { 0x39, 0xCC, 0x67, 0x31, 0x8C, 0x07, 0x38, 0x6C, 0xD9, 0x36, 0x48, 0x80, 0x09, 0x0D, 0x86, 0xCF, 0xF7, 0xF9, 0xB3, 0xFD, 0xFE, 0x6C, 0x36, 0x1B, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique12pt7b.h index f17a0f84..06176033 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoOblique12pt7bBitmaps[] PROGMEM = { 0x11, 0x11, 0x12, 0x22, 0x22, 0x00, 0x0E, 0xE0, 0xE7, 0xE7, 0xC6, 0xC6, 0xC6, 0x84, 0x84, 0x02, 0x40, 0x88, 0x12, 0x02, 0x40, 0x48, 0x7F, 0xC2, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique18pt7b.h index 93fa1cfb..c12ae08b 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoOblique18pt7bBitmaps[] PROGMEM = { 0x00, 0x1C, 0x38, 0x70, 0xC1, 0x83, 0x06, 0x18, 0x30, 0x60, 0xC1, 0x02, 0x04, 0x00, 0x00, 0x01, 0xC7, 0x8F, 0x1C, 0x00, 0x78, 0x7B, 0xC3, 0xFC, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique24pt7b.h index ca097393..28bbf9e3 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoOblique24pt7bBitmaps[] PROGMEM = { 0x01, 0xC0, 0xF0, 0x3C, 0x0E, 0x03, 0x81, 0xE0, 0x78, 0x1C, 0x07, 0x01, 0xC0, 0xE0, 0x38, 0x0E, 0x03, 0x00, 0xC0, 0x70, 0x1C, 0x06, 0x01, 0x80, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique9pt7b.h index e39ef495..1e829640 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeMonoOblique9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeMonoOblique9pt7bBitmaps[] PROGMEM = { 0x11, 0x22, 0x24, 0x40, 0x00, 0xC0, 0xDE, 0xE5, 0x29, 0x00, 0x09, 0x05, 0x02, 0x82, 0x47, 0xF8, 0xA0, 0x51, 0xFE, 0x28, 0x14, 0x0A, 0x09, 0x00, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans12pt7b.h index 4e027fc9..6e77392e 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSans12pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xCF, 0x3C, 0xF3, 0x8A, 0x20, 0x06, 0x30, 0x31, 0x03, 0x18, 0x18, 0xC7, 0xFF, 0xBF, 0xFC, 0x31, 0x03, 0x18, 0x18, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans18pt7b.h index 82ac4797..f3a96060 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSans18pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x20, 0x3F, 0xFC, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8E, 0x82, 0x41, 0x00, 0x01, 0xC3, 0x80, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans24pt7b.h index 5939c316..35595305 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSans24pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x66, 0x00, 0x0F, 0xFF, 0xFF, 0xF1, 0xFE, 0x3F, 0xC7, 0xF8, 0xFF, 0x1F, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans9pt7b.h index f151f326..91c33b03 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSans9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSans9pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xF8, 0xC0, 0xDE, 0xF7, 0x20, 0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, 0x10, 0x1F, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold12pt7b.h index d75ef625..c1d6ef4f 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBold12pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x60, 0xFF, 0xF0, 0xF3, 0xFC, 0xFF, 0x3F, 0xCF, 0x61, 0x98, 0x60, 0x0E, 0x70, 0x73, 0x83, 0x18, 0xFF, 0xF7, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold18pt7b.h index ed34c632..f0e2807b 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBold18pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE7, 0x39, 0xCE, 0x73, 0x80, 0x0F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xC7, 0xFE, 0x3F, 0xF1, 0xFF, 0x8F, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold24pt7b.h index b128e215..5dd7a54a 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBold24pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xC7, 0x0E, 0x1C, 0x00, 0x00, 0x07, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold9pt7b.h index 3d850f4b..cffb178d 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBold9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBold9pt7bBitmaps[] PROGMEM = { 0xFF, 0xFF, 0xFE, 0x48, 0x7E, 0xEF, 0xDF, 0xBF, 0x74, 0x40, 0x19, 0x86, 0x67, 0xFD, 0xFF, 0x33, 0x0C, 0xC3, 0x33, 0xFE, 0xFF, 0x99, 0x86, 0x61, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique12pt7b.h index f7c769cb..ff76ce35 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBoldOblique12pt7bBitmaps[] PROGMEM = { 0x1C, 0x3C, 0x78, 0xE1, 0xC3, 0x8F, 0x1C, 0x38, 0x70, 0xC1, 0x83, 0x00, 0x1C, 0x78, 0xF0, 0x71, 0xFC, 0xFE, 0x3B, 0x8E, 0xC3, 0x30, 0xC0, 0x01, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique18pt7b.h index c947f66d..441c6b50 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBoldOblique18pt7bBitmaps[] PROGMEM = { 0x06, 0x01, 0xC0, 0x7C, 0x1F, 0x0F, 0xC3, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xC0, 0xF0, 0x7C, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1C, 0x07, 0x01, 0xC0, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique24pt7b.h index 69ba7afb..a20229d6 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBoldOblique24pt7bBitmaps[] PROGMEM = { 0x01, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, 0xFF, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x01, 0xFC, 0x07, 0xE0, 0x1F, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique9pt7b.h index 263e615e..ff72f735 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansBoldOblique9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansBoldOblique9pt7bBitmaps[] PROGMEM = { 0x21, 0x8E, 0x73, 0x18, 0xC6, 0x21, 0x19, 0xCE, 0x00, 0xEF, 0xDF, 0xBE, 0x68, 0x80, 0x06, 0xC1, 0x99, 0xFF, 0xBF, 0xF1, 0xB0, 0x66, 0x0C, 0xC7, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique12pt7b.h index b9fbbfc4..ce55f4d2 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansOblique12pt7bBitmaps[] PROGMEM = { 0x0C, 0x61, 0x86, 0x18, 0x63, 0x0C, 0x30, 0xC2, 0x18, 0x61, 0x00, 0x00, 0xC3, 0x00, 0xCF, 0x3C, 0xE2, 0x8A, 0x20, 0x01, 0x8C, 0x03, 0x18, 0x06, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique18pt7b.h index cb1106aa..f85b07fe 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansOblique18pt7bBitmaps[] PROGMEM = { 0x03, 0x83, 0x81, 0xC0, 0xE0, 0x70, 0x78, 0x38, 0x1C, 0x0E, 0x07, 0x07, 0x83, 0x81, 0xC0, 0xE0, 0x60, 0x30, 0x30, 0x18, 0x0C, 0x04, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique24pt7b.h index d5fd29fc..805aefaf 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansOblique24pt7bBitmaps[] PROGMEM = { 0x01, 0xE0, 0x3C, 0x0F, 0x81, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique9pt7b.h index a44f3738..0b5db813 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSansOblique9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSansOblique9pt7bBitmaps[] PROGMEM = { 0x10, 0x84, 0x22, 0x10, 0x84, 0x42, 0x10, 0x08, 0x00, 0xDE, 0xE5, 0x20, 0x06, 0x40, 0x88, 0x13, 0x06, 0x43, 0xFE, 0x32, 0x04, 0x40, 0x98, 0x32, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif12pt7b.h index 052857a4..22cb53de 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerif12pt7bBitmaps[] PROGMEM = { 0xFF, 0xFE, 0xA8, 0x3F, 0xCF, 0x3C, 0xF3, 0x8A, 0x20, 0x0C, 0x40, 0xC4, 0x08, 0x40, 0x8C, 0x08, 0xC7, 0xFF, 0x18, 0x81, 0x88, 0x10, 0x81, 0x08, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif18pt7b.h index 4eeb1550..3fd1ba59 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerif18pt7bBitmaps[] PROGMEM = { 0x6F, 0xFF, 0xFF, 0xFE, 0x66, 0x66, 0x66, 0x64, 0x40, 0x00, 0x6F, 0xF6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x46, 0x42, 0x42, 0x42, 0x03, 0x06, 0x01, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif24pt7b.h index 5cd6d14b..cac19998 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerif24pt7bBitmaps[] PROGMEM = { 0x77, 0xBF, 0xFF, 0xFF, 0xFF, 0xFB, 0x9C, 0xE7, 0x39, 0xCE, 0x61, 0x08, 0x42, 0x10, 0x84, 0x00, 0x00, 0xEF, 0xFF, 0xEE, 0x60, 0x6F, 0x0F, 0xF0, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif9pt7b.h index 7acf307e..22f82e45 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerif9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerif9pt7bBitmaps[] PROGMEM = { 0xFF, 0xEA, 0x03, 0xDE, 0xF7, 0x20, 0x11, 0x09, 0x04, 0x82, 0x4F, 0xF9, 0x10, 0x89, 0xFF, 0x24, 0x12, 0x09, 0x0C, 0x80, 0x10, 0x7C, 0xD6, 0xD2, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold12pt7b.h index 7b4b0c92..9dedae04 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBold12pt7bBitmaps[] PROGMEM = { 0x7F, 0xFF, 0x77, 0x66, 0x22, 0x00, 0x6F, 0xF7, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3A, 0x09, 0x04, 0x0C, 0x40, 0xCC, 0x0C, 0xC0, 0x8C, 0x18, 0xC7, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold18pt7b.h index d28014e9..faecf4f7 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBold18pt7bBitmaps[] PROGMEM = { 0x7B, 0xEF, 0xFF, 0xFF, 0xF7, 0x9E, 0x71, 0xC7, 0x0C, 0x20, 0x82, 0x00, 0x00, 0x07, 0x3E, 0xFF, 0xFF, 0xDC, 0x60, 0x37, 0x83, 0xFC, 0x1F, 0xE0, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold24pt7b.h index a1850514..e6681f5b 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBold24pt7bBitmaps[] PROGMEM = { 0x3C, 0x7E, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x7E, 0x7C, 0x7C, 0x3C, 0x3C, 0x38, 0x38, 0x38, 0x38, 0x18, 0x10, 0x10, 0x10, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold9pt7b.h index 37ac7147..2f1cf8f7 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBold9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBold9pt7bBitmaps[] PROGMEM = { 0xFF, 0xF4, 0x92, 0x1F, 0xF0, 0xCF, 0x3C, 0xE3, 0x88, 0x13, 0x09, 0x84, 0xC2, 0x47, 0xF9, 0x90, 0xC8, 0x4C, 0xFF, 0x13, 0x09, 0x0C, 0x86, 0x40, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic12pt7b.h index 79d8d7a7..d6674ce8 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBoldItalic12pt7bBitmaps[] PROGMEM = { 0x07, 0x07, 0x07, 0x0F, 0x0E, 0x0E, 0x0C, 0x0C, 0x08, 0x18, 0x10, 0x00, 0x00, 0x60, 0xF0, 0xF0, 0x60, 0x61, 0xF1, 0xF8, 0xF8, 0x6C, 0x34, 0x12, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic18pt7b.h index 750b81d9..8e75b241 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBoldItalic18pt7bBitmaps[] PROGMEM = { 0x01, 0xC0, 0x7C, 0x0F, 0x81, 0xF0, 0x3E, 0x07, 0x80, 0xF0, 0x3C, 0x07, 0x80, 0xE0, 0x1C, 0x03, 0x00, 0x60, 0x0C, 0x03, 0x00, 0x60, 0x08, 0x00, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic24pt7b.h index f5b7ed88..e2fa4cb9 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBoldItalic24pt7bBitmaps[] PROGMEM = { 0x00, 0x3C, 0x00, 0xFC, 0x01, 0xF8, 0x07, 0xF0, 0x0F, 0xE0, 0x1F, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0xF8, 0x01, 0xF0, 0x07, 0xC0, 0x0F, 0x80, 0x1E, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic9pt7b.h index 50a2ebe6..b5d9a551 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifBoldItalic9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifBoldItalic9pt7bBitmaps[] PROGMEM = { 0x0C, 0x31, 0xC6, 0x18, 0x41, 0x08, 0x20, 0x0E, 0x38, 0xE0, 0xCF, 0x38, 0xA2, 0x88, 0x02, 0x40, 0xC8, 0x13, 0x06, 0x43, 0xFC, 0x32, 0x06, 0x40, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic12pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic12pt7b.h index 967a52fd..85de005f 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic12pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic12pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifItalic12pt7bBitmaps[] PROGMEM = { 0x0C, 0x31, 0xC6, 0x18, 0x43, 0x0C, 0x20, 0x84, 0x10, 0x03, 0x0C, 0x30, 0x66, 0xCD, 0x12, 0x24, 0x51, 0x00, 0x03, 0x10, 0x11, 0x80, 0x8C, 0x0C, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic18pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic18pt7b.h index 7200365d..c25db35b 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic18pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic18pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifItalic18pt7bBitmaps[] PROGMEM = { 0x01, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0x81, 0xE0, 0x70, 0x1C, 0x06, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x02, 0x01, 0x80, 0x40, 0x10, 0x00, 0x00, 0x01, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic24pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic24pt7b.h index e14a151b..98233a78 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic24pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic24pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifItalic24pt7bBitmaps[] PROGMEM = { 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x01, 0xF0, 0x1E, 0x01, 0xE0, 0x1C, 0x01, 0xC0, 0x3C, 0x03, 0x80, 0x38, 0x03, 0x80, 0x30, 0x07, 0x00, 0x60, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic9pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic9pt7b.h index 9f3d5df0..be4ad051 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic9pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/FreeSerifItalic9pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + const uint8_t FreeSerifItalic9pt7bBitmaps[] PROGMEM = { 0x11, 0x12, 0x22, 0x24, 0x40, 0x0C, 0xDE, 0xE5, 0x40, 0x04, 0x82, 0x20, 0x98, 0x24, 0x7F, 0xC4, 0x82, 0x23, 0xFC, 0x24, 0x11, 0x04, 0x83, 0x20, diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Org_01.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Org_01.h index eabbd92a..9b80258e 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Org_01.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Org_01.h @@ -1,3 +1,6 @@ +#pragma once +#include + // Org_v01 by Orgdot (www.orgdot.com/aliasfonts). A tiny, // stylized font with all characters within a 6 pixel height. diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Picopixel.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Picopixel.h index c1a00928..463b1b56 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Picopixel.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Picopixel.h @@ -1,3 +1,6 @@ +#pragma once +#include + // Picopixel by Sebastian Weber. A tiny font // with all characters within a 6 pixel height. diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Tiny3x3a2pt7b.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Tiny3x3a2pt7b.h index c3071d74..5b0ba4a0 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Tiny3x3a2pt7b.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/Tiny3x3a2pt7b.h @@ -1,3 +1,6 @@ +#pragma once +#include + /** ** The FontStruction “Tiny3x3a” ** (https://fontstruct.com/fontstructions/show/670512) by “Michaelangel007” is diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/TomThumb.h b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/TomThumb.h index 08b20800..21555002 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/TomThumb.h +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/Fonts/TomThumb.h @@ -1,3 +1,6 @@ +#pragma once +#include + /** ** The original 3x5 font is licensed under the 3-clause BSD license: ** diff --git a/trunk/Arduino/libraries/Adafruit_GFX_Library/library.properties b/trunk/Arduino/libraries/Adafruit_GFX_Library/library.properties index bd92ca6f..7d8849e5 100644 --- a/trunk/Arduino/libraries/Adafruit_GFX_Library/library.properties +++ b/trunk/Arduino/libraries/Adafruit_GFX_Library/library.properties @@ -1,5 +1,5 @@ name=Adafruit GFX Library -version=1.11.5 +version=1.11.9 author=Adafruit maintainer=Adafruit sentence=Adafruit GFX graphics core library, this is the 'core' class that all our other graphics libraries derive from. diff --git a/trunk/Arduino/libraries/Adafruit_Motor_Shield_V2_Library/library.properties b/trunk/Arduino/libraries/Adafruit_Motor_Shield_V2_Library/library.properties index 5e1171a7..53b9491d 100644 --- a/trunk/Arduino/libraries/Adafruit_Motor_Shield_V2_Library/library.properties +++ b/trunk/Arduino/libraries/Adafruit_Motor_Shield_V2_Library/library.properties @@ -1,5 +1,5 @@ name=Adafruit Motor Shield V2 Library -version=1.1.1 +version=1.1.3 author=Adafruit maintainer=Adafruit sentence=Library for the Adafruit Motor Shield V2 for Arduino. It supports DC motors & stepper motors with microstepping as well as stacking-support. diff --git a/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.cpp b/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.cpp index 2a4513e0..b854a5ab 100644 --- a/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.cpp +++ b/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.cpp @@ -61,6 +61,48 @@ void Adafruit_Sensor::printSensorDetails(void) { case SENSOR_TYPE_COLOR: Serial.print(F("Color (RGBA)")); break; + case SENSOR_TYPE_TVOC: + Serial.print(F("Total Volatile Organic Compounds (ppb)")); + break; + case SENSOR_TYPE_VOC_INDEX: + Serial.print(F("Volatile Organic Compounds (Index)")); + break; + case SENSOR_TYPE_NOX_INDEX: + Serial.print(F("Nitrogen Oxides (Index)")); + break; + case SENSOR_TYPE_CO2: + Serial.print(F("Carbon Dioxide (ppm)")); + break; + case SENSOR_TYPE_ECO2: + Serial.print(F("Equivalent/estimated CO2 (ppm)")); + break; + case SENSOR_TYPE_PM10_STD: + Serial.print(F("Standard Particulate Matter 1.0 (ppm)")); + break; + case SENSOR_TYPE_PM25_STD: + Serial.print(F("Standard Particulate Matter 2.5 (ppm)")); + break; + case SENSOR_TYPE_PM100_STD: + Serial.print(F("Standard Particulate Matter 10.0 (ppm)")); + break; + case SENSOR_TYPE_PM10_ENV: + Serial.print(F("Environmental Particulate Matter 1.0 (ppm)")); + break; + case SENSOR_TYPE_PM25_ENV: + Serial.print(F("Environmental Particulate Matter 2.5 (ppm)")); + break; + case SENSOR_TYPE_PM100_ENV: + Serial.print(F("Environmental Particulate Matter 10.0 (ppm)")); + break; + case SENSOR_TYPE_GAS_RESISTANCE: + Serial.print(F("Gas Resistance (ohms)")); + break; + case SENSOR_TYPE_UNITLESS_PERCENT: + Serial.print(F("Unitless Percent (%)")); + break; + case SENSOR_TYPE_ALTITUDE: + Serial.print(F("Altitude (m)")); + break; } Serial.println(); diff --git a/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h b/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h index 087eda5a..8c6a07df 100644 --- a/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h +++ b/trunk/Arduino/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h @@ -66,7 +66,21 @@ typedef enum { SENSOR_TYPE_OBJECT_TEMPERATURE = (14), SENSOR_TYPE_VOLTAGE = (15), SENSOR_TYPE_CURRENT = (16), - SENSOR_TYPE_COLOR = (17) + SENSOR_TYPE_COLOR = (17), + SENSOR_TYPE_TVOC = (18), + SENSOR_TYPE_VOC_INDEX = (19), + SENSOR_TYPE_NOX_INDEX = (20), + SENSOR_TYPE_CO2 = (21), + SENSOR_TYPE_ECO2 = (22), + SENSOR_TYPE_PM10_STD = (23), + SENSOR_TYPE_PM25_STD = (24), + SENSOR_TYPE_PM100_STD = (25), + SENSOR_TYPE_PM10_ENV = (26), + SENSOR_TYPE_PM25_ENV = (27), + SENSOR_TYPE_PM100_ENV = (28), + SENSOR_TYPE_GAS_RESISTANCE = (29), + SENSOR_TYPE_UNITLESS_PERCENT = (30), + SENSOR_TYPE_ALTITUDE = (31) } sensors_type_t; /** struct sensors_vec_s is used to return a vector in a common format. */ @@ -120,7 +134,7 @@ typedef struct { int32_t reserved0; /**< reserved */ int32_t timestamp; /**< time is in milliseconds */ union { - float data[4]; ///< Raw data + float data[4]; ///< Raw data */ sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */ sensors_vec_t @@ -134,8 +148,33 @@ typedef struct { float relative_humidity; /**< relative humidity in percent */ float current; /**< current in milliamps (mA) */ float voltage; /**< voltage in volts (V) */ - sensors_color_t color; /**< color in RGB component values */ - }; ///< Union for the wide ranges of data we can carry + float tvoc; /**< Total Volatile Organic Compounds, in ppb */ + float voc_index; /**< VOC (Volatile Organic Compound) index where 100 is + normal (unitless) */ + float nox_index; /**< NOx (Nitrogen Oxides) index where 100 is normal + (unitless) */ + float CO2; /**< Measured CO2 in parts per million (ppm) */ + float eCO2; /**< equivalent/estimated CO2 in parts per million (ppm + estimated from some other measurement) */ + float pm10_std; /**< Standard Particulate Matter <=1.0 in parts per million + (ppm) */ + float pm25_std; /**< Standard Particulate Matter <=2.5 in parts per million + (ppm) */ + float pm100_std; /**< Standard Particulate Matter <=10.0 in parts per + million (ppm) */ + float pm10_env; /**< Environmental Particulate Matter <=1.0 in parts per + million (ppm) */ + float pm25_env; /**< Environmental Particulate Matter <=2.5 in parts per + million (ppm) */ + float pm100_env; /**< Environmental Particulate Matter <=10.0 in parts per + million (ppm) */ + float gas_resistance; /**< Proportional to the amount of VOC particles in + the air (Ohms) */ + float unitless_percent; /** maintainer=Adafruit sentence=Required for all Adafruit Unified Sensor based libraries. diff --git a/trunk/Arduino/libraries/ArduinoOTA/README.md b/trunk/Arduino/libraries/ArduinoOTA/README.md index d1eb630d..e282e023 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/README.md +++ b/trunk/Arduino/libraries/ArduinoOTA/README.md @@ -1,6 +1,5 @@ -Buy Me A Coffee -# Arduino library to upload sketch over network to supported Arduino board +# Arduino library to update the sketch over the network This library allows you to update sketches on your board over WiFi or Ethernet. @@ -25,25 +24,30 @@ The library is a modification of the Arduino WiFi101OTA library. ## Supported micro-controllers * classic ATmega AVR with at least 64 kB of flash (Arduino Mega, [MegaCore](https://github.com/MCUdude/MegaCore) MCUs, MightyCore 1284p and 644) -* Arduino SAMD boards like Zero, M0 or MKR and the new "Nano 33 IoT" +* Arduino SAMD boards like Zero, M0, MKR and Nano 33 IoT +* Arduino Uno R4 boards * nRF5 board supported by [nRF5 core](https://github.com/sandeepmistry/arduino-nRF5). * RP2040 boards with [Pico core](https://github.com/earlephilhower/arduino-pico) * STM32F boards with [STM32 core](https://github.com/stm32duino/Arduino_Core_STM32) * boards supported by ESP8266 and ESP32 Arduino boards package * any board with MCU with SD bootloader +* any board with custom Storage and boot-load solution for that storage +* Nano RP2040 Connect with mbed core with custom storage example and SFU library ## Supported networking libraries +The ArduinoOTA library will work any proper Arduino Ethernet or WiFi library. For Ethernet library add `#define OTETHERNET` before including the ArduinoOTA library. If you don't want a network port or the library doesn't support it, add `#define NO_OTA_PORT` before including the ArduinoOTA library. If you only want to use InternalStorage without the network upload from IDE, add `#define NO_OTA_NETWORK` before including the ArduinoOTA library. + +Tested libraries are: * Ethernet library - Ethernet shields and modules with Wiznet 5100, 5200 and 5500 chips * WiFi101 - MKR 1000, Arduino WiFi101 shield and Adafruit WINC1500 WiFi shield or module * WiFiNINA - MKR 1010, MKR 4000, Nano 33 IoT and any supported MCU with attached ESP32 as SPI network adapter with WiFiNINA firmware +* WiFiS3 library of Arduino Uno R4 WiFi * WiFiEspAT - esp8266 or ESP32 as network adapter with AT firmware -* WiFiLink - esp8266 as network adapter with WiFiLink firmware (SPI or Serial) -* EthernetENC and UIPEthernet - shields and modules with ENC28j60 chip -* WiFi - Arduino WiFi Shield (not tested) -* WiFi library of ESP8266 and ESP32 Arduino boards package +* EthernetENC - shields and modules with ENC28j60 chip +* WiFi library of the Pico Core including its Ethernet network interfaces -UIPEthernet, EthernetENC and WiFi library don't support UDP multicast for MDNS, so Arduino IDE will not show the network upload port. WiFiLink doesn't support UDP multicast, but the firmware propagates the MDNS record. +EthernetENC and WiFiEspAT with esp8266 doesn't support UDP multicast for MDNS, so Arduino IDE will not show the network upload port. ## Installation @@ -53,19 +57,23 @@ Note for platformio users: Please, don't use this library with platformio. It wa Arduino SAMD boards (Zero, M0, MKR, Nano 33 IoT) are supported 'out of the box'. Additionally to upload over the internal flash as temporary storage, upload over SD card and over MEM shield's flash is possible. For upload over SD card use the SDU library as shown in the WiFi101_SD_OTA or similar for upload over MKR MEM shield use the SFU library. -For nRF5 boards two lines need to be added to platform.txt file of the nRF5 Arduino package. For details scroll down. - -For RP2040 and STM32F1 boards, platform.local.txt from extras folder has to be copied into boards package installation folder. +For Uno R4, RP2040, nRF5 and STM32 boards, platform.local.txt from extras folder has to be copied into boards package installation folder. For nRF5 details scroll down. For RP2040 the bundled ArduinoOTA library must be deleted. For ESP8266 and ESP32 boards, platform.local.txt from extras folder has to be copied into boards package installation folder and the bundled ArduinoOTA library must be deleted. For details scroll down. ATmega boards require to flash a modified Optiboot bootloader for flash write operations. Details are below. -For other MCU upload over SD card is possible if the MCU has SD bootloader which can bootload the update bin from SD card. See the ATmega-SD example. Some MCU can use a second stage SD bootloader linked to the sketch as a library similar to SAMD package's SDU library. For upload the 'fake OTA programmer' technique can be configured. +For other MCU upload over SD card is possible if the MCU has SD bootloader which can bootload the update bin from SD card. See the ATmega-SD example. Some MCU can use a second stage SD bootloader linked to the sketch as a library similar to SAMD package's SDU library. + +With InternalStorage the sketch binary size is limited to half of the available flash memory size. The available flash size may be reduced by the bootloader and EEPROM emulation space. + +For upload the 'OTA programmer' technique can be configured. + +The upload tool in IDE gas a timeout 10 seconds. For some sketch size, MCU or library it is too short. To set longer timeout, [download](https://github.com/arduino/arduinoOTA/releases) newer version of the tool, replace the 1.3.0 arduinoOTA executable and in platform.local.txt add the -t option in seconds. ## OTA Upload from IDE without 'network port' -Some of the supported networking libraries don't have the UDP.beginMulticast function and can't start a MDNS service to propagate the network port for Arduino IDE. And sometimes the MDNS port is not detected for the good libraries too. Arduino IDE doesn't yet allow to enter the IP address. +Some networking libraries don't have the UDP.beginMulticast function and can't start a MDNS service to propagate the network port for Arduino IDE. And sometimes the MDNS port is not detected for the good libraries too. Arduino IDE doesn't yet allow to enter the IP address. The workaround is to configure a fake programmer for Arduino OTA. You can use [my_boards](https://github.com/jandrassy/my_boards) as starting point. For Arduino Mega it is the best option for all ArduinoOTA aspects, for other boards it gives you control about your custom settings. In your copy of my_boards in programmers.txt, configure the IP address and restart the IDE. Note: the esp boards packages can't be used as referenced packages in my_boards style. @@ -75,14 +83,19 @@ Example OTA 'programmer' configuration in programmers.txt: ``` arduinoOTA104.name=Arduino OTA (192.168.1.104) arduinoOTA104.program.tool=arduinoOTA +arduinoOTA104.program.tool.default=arduinoOTA arduinoOTA104.ip=192.168.1.104 ``` In IDE select in Tools menu the "Arduino OTA (...)" programmer and use "Upload using programmer" from the Sketch menu in IDE. +Important! If you test OTA with the 'fake' programmer, close the Serial Monitor in IDE. With Serial Monitor open, IDE will reset the board after upload tool finishes. The board then doesn't finish to apply the update. + ## OTA update as download -*Note: Don't use this for esp8266 and esp32 Arduino. Use the ESP8266httpUpdate and the esp32 HTTPUpdate library for OTA update download for esp8266/esp32. Or use the Update object from esp8266 core ot the Update library directly.* +*Note: For Arduino MKR WiFi 1010 and Arduino Nano 33 IoT the SNU library and storage support in the nina firmware can be used for OTA update as download. See the SNU library example in the IDE Examples menu.* + +*Note: Don't use this for esp8266 and esp32 Arduino. Use the ESP8266httpUpdate and the esp32 HTTPUpdate library for OTA update download for esp8266/esp32. Or use the Update object from esp8266 core of the Update library directly.* The WiFi101OTA and ArduinoOTA libraries were created for upload from IDE. But in some scenarios as for example deployed sleeping battery powered devices it is better to have the update available for download by the device. @@ -96,21 +109,23 @@ The sizes of networking library and the SD library allows the use of ArduinoOTA *Side note: There are other network upload options for here excluded ATmega328p: ([Ariadne bootloader](https://github.com/loathingKernel/ariadne-bootloader) for Wiznet chips, [WiFiLink firmware](https://github.com/jandrassy/arduino-firmware-wifilink) for the esp8266) or [AvrDudeTelnet](https://github.com/jandrassy/lab/blob/master/AvrDudeTelnet/AvrDudeTelnet.ino) upload (Linux only).* -For upload with ArduinoOTA library over InternalStorage, Optiboot bootloader with [`copy_flash_pages` function](https://github.com/Optiboot/optiboot/pull/269) is required. MegaCore and MightyCore by [MCUDude](https://github.com/MCUdude) have Optiboot binaries with `copy_flash_pages` function ready to be burn to your ATmega. +For upload with ArduinoOTA library over InternalStorage, Optiboot bootloader with [`copy_flash_pages` function](https://github.com/Optiboot/optiboot/pull/269) is required. MegaCore and MightyCore by [MCUDude](https://github.com/MCUdude) before version 3 has Optiboot binaries with `copy_flash_pages` function ready to be burn to your ATmega. The most common Arduino ATmega board with more than 64 kB of flash memory is Arduino Mega. To use it with ArduinoOTA library, you can't use it directly with the Arduino AVR package, because the package doesn't have the right fuse settings for Mega with Optiboot. You can download [my boards definitions](https://github.com/jandrassy/my_boards) and use it [to burn](https://arduino.stackexchange.com/questions/473/how-do-i-burn-the-bootloader) the modified Optiboot and to upload sketches to your Mega over USB and over network. -For SDStorage a 'SD bootloader' is required to load the uploaded file from the SD card. There is no good SD bootloader. 2boots works only with not available old types of SD cards and zevero/avr_boot doesn't yet support USB upload of sketch. The SDStorage was tested with zevero/avr_boot. The ATmega_SD example shows how to use this ArduinoOTA library with SD bootloader. +For SDStorage a 'SD bootloader' is required to load the uploaded file from the SD card. The SDStorage was tested with zevero/avr_boot. Note that the zevero/avr_boot doesn't support USB upload of sketch. The ATmega_SD example shows how to use this ArduinoOTA library with SD bootloader. -To use remote upload from IDE with SDStorage or InternalStorage, copy platform.local.txt from extras/avr folder, next to platform.txt in the boards package used (Arduino-avr or MCUdude packages). You can find the location of boards packages in Arduino IDE Preferences as the location of the preferences.txt file at the bottom of the Preferences dialog. It is clickable and opens the folder. There find the boards package in packages folder. +To use remote upload from IDE with SDStorage or InternalStorage, copy platform.local.txt from extras/avr folder, next to platform.txt in the boards package used (Arduino-avr or MCUdude packages). The IDE upload tool is installed with Arduino AVR core package. At least version 1.2 of the arduinoOTA tool is required. For upload from command line without IDE see the command template in extras/avr/platform.local.txt. ## ESP8266 and ESP32 support -The ArduinoOTA library bundled with ESP8266 and ESP32 Arduino packages works only with native WiFi libraries. This library allows to upload a sketch to esp8266 or esp32 over Ethernet with Ethernet or EthernetENC library. Upload over the native WiFi library works too. +This library allows to upload a sketch to esp8266 or esp32 over Ethernet with Ethernet or EthernetENC library. -To use this library instead of the bundled library, the bundled library must be removed from the boards package library folder. To override the configuration of OTA upload in platform.txt, copy the platform.local.txt file from extras folder of this library next to platform.txt file in boards package installation folder. You can find the location of boards packages in Arduino IDE Preferences as the location of the preferences.txt file at the bottom of the Preferences dialog. It is clickable and opens the folder. There find the boards package in packages folder. +*Note: Both esp8266 and esp32 Arduino core now support wired Ethernet as additional network interface for their WiFi library (STA and SoftAP are the 'built-in' network interfaces). With Ethernet over WiFi library you can use the standard OTA upload of the esp8266 and esp32 core with wired Ethernet.* + +To use this library instead of the bundled library, the bundled library must be removed from the boards package library folder. To override the configuration of OTA upload in platform.txt, copy the platform.local.txt file from extras folder of this library next to platform.txt file in boards package installation folder. For Arduino IDE 2 use platform.local.txt from extras/IDE2. This library supports SPIFFS upload to esp8266 and esp32, but the IDE plugins have the network upload tool hardcoded to espota. It can't be changed in configuration. To upload SPIFFS, call the plugin in Tools menu and after it fails to upload over network, go to location of the created bin file and upload the file with arduinoOTA tool from command line. The location of the file is printed in the IDE console window. Upload command example (linux): ``` @@ -122,7 +137,7 @@ This library supports SPIFFS upload to esp8266 and esp32, but the IDE plugins ha For SD card update use [SDUnRF5 library](https://github.com/jandrassy/SDUnRF5). -To use remote upload from IDE with SDStorage or InternalStorage, copy platform.local.txt from extras/nRF5 folder, next to platform.txt in the nRF5 boards package. You can find the location of boards packages in Arduino IDE Preferences as the location of the preferences.txt file at the bottom of the Preferences dialog. It is clickable and opens the folder. There find the boards package in packages folder. +To use remote upload from IDE with SDStorage or InternalStorage, copy platform.local.txt from extras/nRF5 folder, next to platform.txt in the nRF5 boards package. If SoftDevice is not used, the sketch is written from address 0. For write to address 0 the sketch must be compiled with -fno-delete-null-pointer-checks. The setting is in extras/nRF5/platform.local.txt. @@ -136,20 +151,25 @@ void shutdown() { ## Arduino 'network port' -The Arduino IDE detects the Arduino 'network port' using mDNS system. This requires the use of UDP multicast. From networking libraries supported for OTA upload only Ethernet, WiFiNina, WiFi101 and the esp libraries support multicast. For these libraries ArduinoOTA.h at defaults starts the mDNS service. +The Arduino IDE detects the Arduino 'network port' using mDNS system. This requires the use of UDP multicast. From networking libraries supported for OTA upload only Ethernet, WiFiNina and WiFi101 libraries support multicast. For these libraries ArduinoOTA.h at defaults starts the mDNS service. In some networks or on some computers UDP mDNS doesn't work. You can still use the ArduinoOTA library for upload from command line or with the fake programmer trick described elsewhere in this README. It is possible to suppress use of the mDNS service by the library. Only define NO_OTA_PORT before the include like this: ``` -#define NO_OTA_PORT -#include + #define NO_OTA_PORT + #include ``` ## Troubleshooting To see the details of upload command in IDE, set verbose mode for upload in IDE Preferences. arduinoOTA tool version should be 1.2 or higher. +### Compilation errors + +* undefined reference to `InternalStorage' - make sure you selected a board supported by the ArduinoOTA library +* 'ArduinoOTA' was not declared in this scope - make sure a networking library is included before the ArduinoOTA.h include + ### No OTA network port in IDE tools menu Not with all supported networking libraries this library can propagate a 'network port'. See the list in 'Supported networking libraries' section of this page. @@ -170,13 +190,22 @@ platform.txt in my_boards and the fake programmer tool definition in platform.lo The wrong upload command from AVR boards platform.txt is used. Did you copy `extras/avr/platform.local.txt` next to platform.txt as required? +### Upload fails after 10 seconds + +If upload fails with `Flashing sketch ... Error flashing the sketch` after 10 seconds, the problem is the 10 seconds timeout of IDE's upload tool. + +To set longer timeout, [download](https://github.com/arduino/arduinoOTA/releases) newer version of the tool, replace the 1.3.0 arduinoOTA executable and in platform.local.txt add the -t option in seconds. + + ### Upload returns OK but the sketch is not replaced. The final loading of the uploaded binary is in some cases not under control of the ArduinoOTA library. -For SD card way the SD bootloader or the SDU library is responsible for loading the new binary. So SD bootloader must be present and in case of SDU, the uploaded sketch must contain the SDU library. +For SD card way the SD bootloader or the SDU library is responsible for loading the new binary. So SD bootloader must be present and in case of SDU, the uploaded sketch must contain the SDU library. Note that other SPI devices may disturb access to the SD card from the bootloader/SDU. Make sure there are pull-up resistors on the CS pins. For AVR InternalStorage upload the final loading is done by the Optiboot with `copy_flash_pages` function. Optiboot 8 without `copy_flash_pages` will successfully store the binary to upper half of the flash but will not copy it to run location in flash. + +If you test OTA with the 'fake' programmer, close the Serial Monitor in IDE. With Serial Monitor open, IDE will reset the board after upload tool finishes. The board then doesn't finish to apply the update. ### Only the first OTA upload works @@ -189,16 +218,20 @@ Does the OTA uploaded sketch have ArduinoOTA? - Arduino MKR Zero - Crowduino M0 SD - Arduino Nano 33 IoT + - Arduino MKR WiFi 1000 - [Arduino MKR WiFi 1010](https://github.com/jandrassy/ArduinoOTA/issues/46) - - Arduino MKR WiFi 1000 (with Blynk.Edgent) - [Adafruit Feather M0 Express](https://github.com/jandrassy/ArduinoOTA/discussions/77) * SAMD51 - [Seeed Wio Terminal](https://github.com/jandrassy/ArduinoOTA/pull/104) (with Blynk.Edgent) +* Renesas core + - Uno R4 WiFi * RP2040 - Raspberry Pi Pico + - Arduino RP2040 Connect * STM32 - BluePill F103CB (128kB flash) - BlackPill F411CE + - [NUCLEO-F303RE](https://github.com/JAndrassy/ArduinoOTA/issues/203) * nRF5 - Seeed Arch Link (nRF51 board) - [nrf52832 board](https://github.com/jandrassy/ArduinoOTA/issues/1) @@ -209,10 +242,3 @@ Does the OTA uploaded sketch have ArduinoOTA? - Wemos D1 mini * esp32 - ESP32 Dev Module -* STM32 Blue Pill - tested only upload to SD card, without the final bootload - -## Contribution - -Please report tested boards. - -Other ARM based MCUs could be added with code similar to SAMD and nRF5. diff --git a/trunk/Arduino/libraries/ArduinoOTA/examples/ATmega_SD/ATmega_SD.ino b/trunk/Arduino/libraries/ArduinoOTA/examples/ATmega_SD/ATmega_SD.ino index 4d0acda8..e2e11ab9 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/examples/ATmega_SD/ATmega_SD.ino +++ b/trunk/Arduino/libraries/ArduinoOTA/examples/ATmega_SD/ATmega_SD.ino @@ -20,6 +20,7 @@ #include #include #include +#define OTETHERNET #include // Enter a MAC address for your controller below. diff --git a/trunk/Arduino/libraries/ArduinoOTA/examples/Advanced/OTASketchDownload/OTASketchDownload.ino b/trunk/Arduino/libraries/ArduinoOTA/examples/Advanced/OTASketchDownload/OTASketchDownload.ino index 444191fd..ac5a6765 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/examples/Advanced/OTASketchDownload/OTASketchDownload.ino +++ b/trunk/Arduino/libraries/ArduinoOTA/examples/Advanced/OTASketchDownload/OTASketchDownload.ino @@ -16,10 +16,12 @@ by Juraj Andrassy */ -#include // only for InternalStorage #include #include +#define NO_OTA_NETWORK +#include // only for InternalStorage + const short VERSION = 1; byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; diff --git a/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet/OTEthernet.ino b/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet/OTEthernet.ino index 88c083d3..4a204d7b 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet/OTEthernet.ino +++ b/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet/OTEthernet.ino @@ -19,6 +19,7 @@ #include #include +#define OTETHERNET #include //#define Serial SerialUSB diff --git a/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet_SD/OTEthernet_SD.ino b/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet_SD/OTEthernet_SD.ino index 64bc3eac..033f3116 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet_SD/OTEthernet_SD.ino +++ b/trunk/Arduino/libraries/ArduinoOTA/examples/OTEthernet_SD/OTEthernet_SD.ino @@ -20,6 +20,7 @@ #include #include #include +#define OTETHERNET #include #include diff --git a/trunk/Arduino/libraries/ArduinoOTA/examples/SerialWiFiOTA/SerialWiFiOTA.ino b/trunk/Arduino/libraries/ArduinoOTA/examples/SerialWiFiOTA/SerialWiFiOTA.ino index d6107624..094dc0c7 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/examples/SerialWiFiOTA/SerialWiFiOTA.ino +++ b/trunk/Arduino/libraries/ArduinoOTA/examples/SerialWiFiOTA/SerialWiFiOTA.ino @@ -1,8 +1,6 @@ /* - This example polls for sketch updates over WiFi module on Serial1, - sketches can be updated by selecting a network port from within - the Arduino IDE: Tools -> Port -> Network Ports ... + This example polls for sketch updates over WiFi module on Serial1. created 13 July 2010 by dlf (Metodo2 srl) @@ -16,6 +14,16 @@ #include #include +#include + +// Emulate Serial1 on pins 6/7 if not present +#if defined(ARDUINO_ARCH_AVR) && !defined(HAVE_HWSERIAL1) +#include +SoftwareSerial Serial1(6, 7); // RX, TX +#define AT_BAUD_RATE 9600 +#else +#define AT_BAUD_RATE 115200 +#endif void setup() { diff --git a/trunk/Arduino/libraries/ArduinoOTA/extras/avr/platform.local.txt b/trunk/Arduino/libraries/ArduinoOTA/extras/avr/platform.local.txt index 274ec775..96e59dd7 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/extras/avr/platform.local.txt +++ b/trunk/Arduino/libraries/ArduinoOTA/extras/avr/platform.local.txt @@ -8,6 +8,7 @@ tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b #IDE 2 +upload.tool.network=arduino_ota tools.arduino_ota.cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA tools.arduino_ota.upload.field.password=Password tools.arduino_ota.upload.field.password.secret=true diff --git a/trunk/Arduino/libraries/ArduinoOTA/library.properties b/trunk/Arduino/libraries/ArduinoOTA/library.properties index dc7f6530..1ca5f4d4 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/library.properties +++ b/trunk/Arduino/libraries/ArduinoOTA/library.properties @@ -1,9 +1,9 @@ name=ArduinoOTA -version=1.0.9 +version=1.1.0 author=Arduino,Juraj Andrassy maintainer=Juraj Andrassy sentence=Upload sketch over network to Arduino board with WiFi or Ethernet libraries -paragraph=Based on WiFi101OTA library. Uploads over Ethernet, EthernetENC, WiFi101, WiFiNina, WiFiEspAT to SAMD, nRF5, RP2040, STM32F, ESP and to classic ATmega with more than 64 kB flash memory. +paragraph=Based on WiFi101OTA library. Updates SAMD, Uno R4, nRF5, RP2040, STM32F and to classic ATmega with more than 64 kB flash memory. category=Other url=https://github.com/jandrassy/ArduinoOTA architectures=* diff --git a/trunk/Arduino/libraries/ArduinoOTA/src/ArduinoOTA.h b/trunk/Arduino/libraries/ArduinoOTA/src/ArduinoOTA.h index 5ba00362..2789f878 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/src/ArduinoOTA.h +++ b/trunk/Arduino/libraries/ArduinoOTA/src/ArduinoOTA.h @@ -20,6 +20,7 @@ #define _ARDUINOOTA_H_ #include "WiFiOTA.h" + #ifdef __AVR__ #if FLASHEND >= 0xFFFF #include "InternalStorageAVR.h" @@ -28,6 +29,8 @@ #include #elif defined(ARDUINO_ARCH_RP2040) #include +#elif defined(ARDUINO_ARCH_RENESAS_UNO) +#include #elif defined(ESP8266) || defined(ESP32) #include "InternalStorageESP.h" #else @@ -59,10 +62,10 @@ public: } void end() { -#if defined(ESP8266) || defined(ESP32) - server.stop(); -#elif defined(_WIFI_ESP_AT_H_) +#if defined(_WIFI_ESP_AT_H_)|| defined(WiFiS3_h) || defined(ESP32) || defined(UIPETHERNET_H) server.end(); +#elif defined(ESP8266) || (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)) + server.stop(); #else //#warning "The networking library doesn't have a function to stop the server" #endif @@ -107,37 +110,38 @@ public: WiFiOTAClass::pollMdns(mdnsSocket); } + void handle() { // alias + poll(); + } + }; -#if defined(ethernet_h_) || defined(ethernet_h) // Ethernet library +#ifndef NO_OTA_NETWORK + +#if defined(ethernet_h_) || defined(ethernet_h) || defined(UIPETHERNET_H) +#define OTETHERNET +#endif +#if defined(UIPETHERNET_H) || defined(WIFIESPAT1) // no UDP multicast implementation +#define NO_OTA_PORT +#endif + +#ifdef OTETHERNET #ifdef NO_OTA_PORT ArduinoOTAClass ArduinoOTA; #else ArduinoOTAMdnsClass ArduinoOTA; #endif -#elif defined(UIPETHERNET_H) // no UDP multicast implementation yet -ArduinoOTAClass ArduinoOTA; +#else -#elif defined(WiFiNINA_h) || defined(WIFI_H) || defined(ESP8266) || defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W) // NINA, WiFi101 and Espressif WiFi #ifdef NO_OTA_PORT ArduinoOTAClass ArduinoOTA; #else #include ArduinoOTAMdnsClass ArduinoOTA; #endif - -#elif defined(_WIFI_ESP_AT_H_) && !defined(WIFIESPAT1) && !defined(NO_OTA_PORT) // WiFiEspAT with AT2 has UDP multicast -ArduinoOTAMdnsClass ArduinoOTA; - -#elif defined(WiFi_h) || defined(_WIFI_ESP_AT_H_) // WiFi, WiFiLink and WiFiEspAT lib (no UDP multicast) for WiFiLink the firmware handles mdns -ArduinoOTAClass ArduinoOTA; - -#elif defined(_WIFISPI_H_INCLUDED) // no UDP multicast implementation -ArduinoOTAClass ArduinoOTA; - -#else -#warning "Network library not included or not supported" +#endif + #endif #endif diff --git a/trunk/Arduino/libraries/ArduinoOTA/src/InternalStorage.cpp b/trunk/Arduino/libraries/ArduinoOTA/src/InternalStorage.cpp index 03c7625e..cb7bd06b 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/src/InternalStorage.cpp +++ b/trunk/Arduino/libraries/ArduinoOTA/src/InternalStorage.cpp @@ -63,7 +63,7 @@ extern "C" { while (NRF_NVMC->READY == NVMC_READY_READY_Busy); #endif } - + #if defined(__SAMD51__) // Invalidate all CMCC cache entries if CMCC cache is enabled. __attribute__ ((long_call, noinline, section (".data#"))) @@ -94,7 +94,7 @@ extern "C" { for (int i = 0; i < length; i += rowSize) { NVMCTRL->ADDR.reg = ((uint32_t)(address + i)) / 2; NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER; - + waitForReady(); } #elif defined(ARDUINO_ARCH_NRF5) @@ -113,7 +113,7 @@ extern "C" { waitForReady(); NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; waitForReady(); -#endif +#endif } __attribute__ ((long_call, noinline, section (".data#"))) @@ -156,7 +156,10 @@ int InternalStorageClass::open(int length) NVMCTRL->CTRLB.bit.MANW = 0; #endif +#if !defined(ARDUINO_ARCH_NRF5) + // Erase all pages eraseFlash(STORAGE_START_ADDRESS, pageAlignedLength, PAGE_SIZE); +#endif return 1; } @@ -169,6 +172,13 @@ size_t InternalStorageClass::write(uint8_t b) if (_writeIndex == 4) { _writeIndex = 0; +#if defined(ARDUINO_ARCH_NRF5) + // Erase a single page if needed + if ((int)(_writeAddress) % PAGE_SIZE == 0) { + eraseFlash((int)_writeAddress, PAGE_SIZE, PAGE_SIZE); + } +#endif + *_writeAddress = _addressData.u32; _writeAddress++; @@ -184,6 +194,10 @@ void InternalStorageClass::close() while ((int)_writeAddress % PAGE_SIZE) { write(0xff); } + + // Re-calculate pageAlignedLength in case the actually written binary + // is smaller then the size provided in open() + pageAlignedLength = (_writeAddress - (uint32_t*)STORAGE_START_ADDRESS) * sizeof(uint32_t); } void InternalStorageClass::clear() diff --git a/trunk/Arduino/libraries/ArduinoOTA/src/OTAStorage.cpp b/trunk/Arduino/libraries/ArduinoOTA/src/OTAStorage.cpp index 04e649a6..f1c598c0 100644 --- a/trunk/Arduino/libraries/ArduinoOTA/src/OTAStorage.cpp +++ b/trunk/Arduino/libraries/ArduinoOTA/src/OTAStorage.cpp @@ -22,6 +22,9 @@ extern "C" char * g_pfnVectors; // at first address of the binary. 0x0000 withou #include extern "C" uint8_t _FS_start; extern "C" uint8_t _EEPROM_start; +#elif defined(ARDUINO_ARCH_RENESAS_UNO) +#include +extern "C" uint8_t __ROM_Start; #elif defined(ARDUINO_ARCH_MEGAAVR) #include #elif defined(__AVR__) @@ -47,10 +50,14 @@ OTAStorage::OTAStorage() : PAGE_SIZE(4), //for FLASH_TYPEPROGRAM_WORD #endif MAX_FLASH((min(LL_GetFlashSize(), 512ul) * 1024)) // LL_GetFlashSize returns size in kB. 512 is max for a bank -#elif defined(ARDUINO_ARCH_RP2040) +#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED) SKETCH_START_ADDRESS(0), PAGE_SIZE(FLASH_PAGE_SIZE), MAX_FLASH((uint32_t) min(&_FS_start, &_EEPROM_start) - XIP_BASE) +#elif defined(ARDUINO_ARCH_RENESAS_UNO) + SKETCH_START_ADDRESS((uint32_t)(&__ROM_Start)), + PAGE_SIZE(BSP_FEATURE_FLASH_LP_CF_BLOCK_SIZE), + MAX_FLASH(BSP_ROM_SIZE_BYTES) #elif defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR) SKETCH_START_ADDRESS(0), PAGE_SIZE(SPM_PAGESIZE), diff --git a/trunk/Arduino/libraries/DHT_sensor_library/DHT.cpp b/trunk/Arduino/libraries/DHT_sensor_library/DHT.cpp index b3646122..a48ac746 100644 --- a/trunk/Arduino/libraries/DHT_sensor_library/DHT.cpp +++ b/trunk/Arduino/libraries/DHT_sensor_library/DHT.cpp @@ -360,7 +360,9 @@ bool DHT::read(bool force) { // in the very latest IDE versions): // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c uint32_t DHT::expectPulse(bool level) { -#if (F_CPU > 16000000L) +// F_CPU is not be known at compile time on platforms such as STM32F103. +// The preprocessor seems to evaluate it to zero in that case. +#if (F_CPU > 16000000L) || (F_CPU == 0L) uint32_t count = 0; #else uint16_t count = 0; // To work fast enough on slower AVR boards diff --git a/trunk/Arduino/libraries/DHT_sensor_library/DHT.h b/trunk/Arduino/libraries/DHT_sensor_library/DHT.h index c3ab67ff..95570e1c 100644 --- a/trunk/Arduino/libraries/DHT_sensor_library/DHT.h +++ b/trunk/Arduino/libraries/DHT_sensor_library/DHT.h @@ -41,13 +41,13 @@ #endif /* Define types of sensors. */ -#define DHT11 11 /**< DHT TYPE 11 */ -#define DHT12 12 /**< DHY TYPE 12 */ -#define DHT22 22 /**< DHT TYPE 22 */ -#define DHT21 21 /**< DHT TYPE 21 */ -#define AM2301 21 /**< AM2301 */ +static const uint8_t DHT11{11}; /**< DHT TYPE 11 */ +static const uint8_t DHT12{12}; /**< DHY TYPE 12 */ +static const uint8_t DHT21{21}; /**< DHT TYPE 21 */ +static const uint8_t DHT22{22}; /**< DHT TYPE 22 */ +static const uint8_t AM2301{21}; /**< AM2301 */ -#if (TARGET_NAME == ARDUINO_NANO33BLE) +#if defined(TARGET_NAME) && (TARGET_NAME == ARDUINO_NANO33BLE) #ifndef microsecondsToClockCycles /*! * As of 7 Sep 2020 the Arduino Nano 33 BLE boards do not have diff --git a/trunk/Arduino/libraries/DHT_sensor_library/examples/DHTtester/DHTtester.ino b/trunk/Arduino/libraries/DHT_sensor_library/examples/DHTtester/DHTtester.ino index ff7a9611..d13507bf 100644 --- a/trunk/Arduino/libraries/DHT_sensor_library/examples/DHTtester/DHTtester.ino +++ b/trunk/Arduino/libraries/DHT_sensor_library/examples/DHTtester/DHTtester.ino @@ -20,7 +20,8 @@ // NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 // to 3.3V instead of 5V! // Connect pin 2 of the sensor to whatever your DHTPIN is -// Connect pin 4 (on the right) of the sensor to GROUND +// Connect pin 3 (on the right) of the sensor to GROUND (if your sensor has 3 pins) +// Connect pin 4 (on the right) of the sensor to GROUND and leave the pin 3 EMPTY (if your sensor has 4 pins) // Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor // Initialize DHT sensor. diff --git a/trunk/Arduino/libraries/DHT_sensor_library/library.properties b/trunk/Arduino/libraries/DHT_sensor_library/library.properties index 7029bfb4..e33d7d47 100644 --- a/trunk/Arduino/libraries/DHT_sensor_library/library.properties +++ b/trunk/Arduino/libraries/DHT_sensor_library/library.properties @@ -1,5 +1,5 @@ name=DHT sensor library -version=1.4.0 +version=1.4.6 author=Adafruit maintainer=Adafruit sentence=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/README.md b/trunk/Arduino/libraries/EspSoftwareSerial/README.md index 2d14c9e6..37b106c5 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/README.md +++ b/trunk/Arduino/libraries/EspSoftwareSerial/README.md @@ -1,6 +1,6 @@ # EspSoftwareSerial -## Implementation of the Arduino software serial library for the ESP8266 / ESP32 +## Implementation of the Arduino software serial library for the ESP8266 / ESP32 family This fork implements interrupt service routine best practice. In the receive interrupt, instead of blocking for whole bytes @@ -12,12 +12,13 @@ Except at high bitrates, depending on other ongoing activity, interrupts in particular, this software serial adapter supports full duplex receive and send. At high bitrates (115200bps) send bit timing can be improved at the expense of blocking concurrent -full duplex receives, with the ``SoftwareSerial::enableIntTx(false)`` function call. +full duplex receives, with the +`EspSoftwareSerial::UART::enableIntTx(false)` function call. The same functionality is given as the corresponding AVR library but several instances can be active at the same time. Speed up to 115200 baud is supported. Besides a constructor compatible to the AVR SoftwareSerial class, -and updated constructor that takes no arguments exists, instead the ``begin()`` +and updated constructor that takes no arguments exists, instead the `begin()` function can handle the pin assignments and logic inversion. It also has optional input buffer capacity arguments for byte buffer and ISR bit buffer. This way, it is a better drop-in replacement for the hardware serial APIs on the ESP MCUs. @@ -27,11 +28,13 @@ ongoing, there will be some inexactness in interrupt timings. This may lead to inevitable, but few, bit errors when having heavy data traffic at high baud rates. +This library supports ESP8266, ESP32, ESP32-S2 and ESP32-C3 devices. + ## Resource optimization The memory footprint can be optimized to just fit the amount of expected incoming asynchronous data. -For this, the ``SoftwareSerial`` constructor provides two arguments. First, the +For this, the `EspSoftwareSerial::UART` constructor provides two arguments. First, the octet buffer capacity for assembled received octets can be set. Read calls are satisfied from this buffer, freeing it in return. Second, the signal edge detection buffer of 32bit fields can be resized. @@ -57,49 +60,93 @@ data until the next read call. For the swsertest.ino example, this results in the following optimized constructor arguments to spend only the minimum RAM on buffers required: -The octet buffer capacity (``bufCapacity``) is 93 (91 characters net plus two tolerance). -The signal edge detection buffer capacity (``isrBufCapacity``) is 10, as each octet has -10 bits on the wire, which are immediately received during the write, and each +The octet buffer capacity (`bufCapacity`) is 95 (93 characters net plus two tolerance). +The signal edge detection buffer capacity (`isrBufCapacity`) is 11, as each +single octet can have up to 11 bits on the wire, +which are immediately received during the write, and each write call causes the signal edge detection to promote the previously sent and received bits to the octet buffer. In a more generalized scenario, calculate the bits (use message size in octets times 10) that may be asynchronously received to determine the value for -``isrBufCapacity`` in the constructor. Also use the number of received octets -that must be buffered for reading as the value of ``bufCapacity``. +`isrBufCapacity` in the constructor. Also use the number of received octets +that must be buffered for reading as the value of `bufCapacity`. The more frequently your code calls write or read functions, the greater the -chances are that you can reduce the ``isrBufCapacity`` footprint without losing data, +chances are that you can reduce the `isrBufCapacity` footprint without losing data, and each time you call read to fetch from the octet buffer, you reduce the need for space there. -## SoftwareSerialConfig and parity -The configuration of the data stream is done via a ``SoftwareSerialConfig`` -argument to ``begin()``. Word lengths can be set to between 5 and 8 bits, parity +## EspSoftwareSerial::Config and parity +The configuration of the data stream is done via a `EspSoftwareSerial::Config` +argument to `begin()`. Word lengths can be set to between 5 and 8 bits, parity can be N(one), O(dd) or E(ven) and 1 or 2 stop bits can be used. The default is -``SWSERIAL_8N1`` using 8 bits, no parity and 1 stop bit but any combination can -be used, e.g. ``SWSERIAL_7E2``. If using EVEN or ODD parity, any parity errors -can be detected with the ``peekParityError()`` function. Note that parity -checking must be done before ``read()``, as the parity information is removed -from the buffer when reading the corresponding byte. +`SWSERIAL_8N1` using 8 bits, no parity and 1 stop bit but any combination can +be used, e.g. `SWSERIAL_7E2`. If using EVEN or ODD parity, any parity errors +can be detected with the `readParity()` and `parityEven()` or `parityOdd()` +functions respectively. Note that the result of `readParity()` always applies +to the preceding `read()` or `peek()` call, and is undefined if they report +no data or an error. To allow flexible 9-bit and data/addressing protocols, the additional parity modes MARK and SPACE are also available. Furthermore, the parity mode can be -individually set in each call to ``write()``. +individually set in each call to `write()`. This allows a simple implementation of protocols where the parity bit is used to distinguish between data and addresses/commands ("9-bit" protocols). First set -up SoftwareSerial with parity mode SPACE, e.g. ``SWSERIAL_8S1``. This will add a +up EspSoftwareSerial::UART with parity mode SPACE, e.g. `SWSERIAL_8S1`. This will add a parity bit to every byte sent, setting it to logical zero (SPACE parity). To detect incoming bytes with the parity bit set (MARK parity), use the -``peekParityError()`` function. To send a byte with the parity bit set, just add -``MARK`` as the second argument when writing, e.g. ``write(ch, MARK)``. +`readParity()` function. To send a byte with the parity bit set, just add +`MARK` as the second argument when writing, e.g. `write(ch, SWSERIAL_PARITY_MARK)`. + +## Checking for correct pin selection / configuration +In general, most pins on the ESP8266 and ESP32 devices can be used by EspSoftwareSerial, +however each device has a number of pins that have special functions or require careful +handling to prevent undesirable situations, for example they are connected to the +on-board SPI flash memory or they are used to determine boot and programming modes +after powerup or brownouts. These pins are not able to be configured by this library. + +The exact list for each device can be found in the +[ESP32 data sheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +in sections 2.2 (Pin Descriptions) and 2.4 (Strapping pins). There is a discussion +dedicated to the use of GPIO12 in this +[note about GPIO12](https://github.com/espressif/esp-idf/tree/release/v3.2/examples/storage/sd_card#note-about-gpio12). +Refer to the `isValidPin()`, `isValidRxPin()` and `isValidTxPin()` +functions in the `EspSoftwareSerial::GpioCapabilities` class for the GPIO restrictions +enforced by this library by default. + +The easiest and safest method is to test the object returned at runtime, to see if +it is valid. For example: + +``` +#include + +#define MYPORT_TX 12 +#define MYPORT_RX 13 + +EspSoftwareSerial::UART myPort; + +[...] + +Serial.begin(115200); // Standard hardware serial port + +myPort.begin(38400, SWSERIAL_8N1, MYPORT_RX, MYPORT_TX, false); +if (!myPort) { // If the object did not initialize, then its configuration is invalid + Serial.println("Invalid EspSoftwareSerial pin configuration, check config"); + while (1) { // Don't continue with invalid configuration + delay (1000); + } +} + +[...] +``` ## Using and updating EspSoftwareSerial in the esp8266com/esp8266 Arduino build environment EspSoftwareSerial is both part of the BSP download for ESP8266 in Arduino, and it is set up as a Git submodule in the esp8266 source tree, -specifically in ``.../esp8266/libraries/SoftwareSerial`` when using a Github +specifically in `.../esp8266/libraries/SoftwareSerial` when using a Github repository clone in your Arduino sketchbook hardware directory. This supersedes any version of EspSoftwareSerial installed for instance via the Arduino library manager, it is not required to install EspSoftwareSerial @@ -109,7 +156,7 @@ The responsible maintainer of the esp8266 repository has kindly shared the following command line instructions to use, if one wishes to manually update EspSoftwareSerial to a newer release than pulled in via the ESP8266 Arduino BSP: -To update esp8266/arduino SoftwareSerial submodule to lastest master: +To update esp8266/arduino EspSoftwareSerial submodule to lastest master: Clean it (optional): ```shell diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/examples/loopback/loopback.ino b/trunk/Arduino/libraries/EspSoftwareSerial/examples/loopback/loopback.ino index ad599e9b..d72544f3 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/examples/loopback/loopback.ino +++ b/trunk/Arduino/libraries/EspSoftwareSerial/examples/loopback/loopback.ino @@ -1,33 +1,35 @@ #include // On ESP8266: -// Local SoftwareSerial loopback, connect D5 (rx) and D6 (tx). +// Local EspSoftwareSerial loopback, connect D5 (rx) and D6 (tx). // For local hardware loopback, connect D5 to D8 (tx), D6 to D7 (rx). // For hardware send/sink, connect D7 (rx) and D8 (tx). // Hint: The logger is run at 9600bps such that enableIntTx(true) can remain unchanged. Blocking -// interrupts severely impacts the ability of the SoftwareSerial devices to operate concurrently +// interrupts severely impacts the ability of the EspSoftwareSerial devices to operate concurrently // and/or in duplex mode. // Operating in software serial full duplex mode, runs at 19200bps and few errors (~2.5%). // Operating in software serial half duplex mode (both loopback and repeater), // runs at 57600bps with nearly no errors. // Operating loopback in full duplex, and repeater in half duplex, runs at 38400bps with nearly no errors. // On ESP32: -// For SoftwareSerial or hardware send/sink, connect D5 (rx) and D6 (tx). +// For EspSoftwareSerial or hardware send/sink, connect D5 (rx) and D6 (tx). // Hardware Serial2 defaults to D4 (rx), D3 (tx). // For local hardware loopback, connect D5 (rx) to D3 (tx), D6 (tx) to D4 (rx). #ifndef D5 #if defined(ESP8266) -#define D5 (14) -#define D6 (12) -#define D7 (13) #define D8 (15) +#define D5 (14) +#define D7 (13) +#define D6 (12) +#define RX (3) #define TX (1) #elif defined(ESP32) -#define D5 (18) -#define D6 (19) -#define D7 (23) #define D8 (5) +#define D5 (18) +#define D7 (23) +#define D6 (19) +#define RX (3) #define TX (1) #endif #endif @@ -45,11 +47,11 @@ constexpr int IUTBITRATE = 19200; #endif #if defined(ESP8266) -constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1; -constexpr SerialConfig hwSerialConfig = SERIAL_8E1; +constexpr EspSoftwareSerial::Config swSerialConfig = EspSoftwareSerial::SWSERIAL_8E1; +constexpr SerialConfig hwSerialConfig = ::SERIAL_8E1; #elif defined(ESP32) -constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1; -constexpr uint32_t hwSerialConfig = SERIAL_8E1; +constexpr EspSoftwareSerial::Config swSerialConfig = EspSoftwareSerial::SWSERIAL_8E1; +constexpr uint32_t hwSerialConfig = ::SERIAL_8E1; #else constexpr unsigned swSerialConfig = 3; #endif @@ -70,37 +72,37 @@ constexpr int ReportInterval = IUTBITRATE / 8; #if defined(ESP8266) #if defined(HWLOOPBACK) || defined(HWSOURCESWSINK) HardwareSerial& hwSerial(Serial); -SoftwareSerial serialIUT; -SoftwareSerial logger; +EspSoftwareSerial::UART serialIUT; +EspSoftwareSerial::UART logger; #elif defined(HWSOURCESINK) HardwareSerial& serialIUT(Serial); -SoftwareSerial logger; +EspSoftwareSerial::UART logger; #else -SoftwareSerial serialIUT; +EspSoftwareSerial::UART serialIUT; HardwareSerial& logger(Serial); #endif #elif defined(ESP32) #if defined(HWLOOPBACK) || defined (HWSOURCESWSINK) HardwareSerial& hwSerial(Serial2); -SoftwareSerial serialIUT; +EspSoftwareSerial::UART serialIUT; #elif defined(HWSOURCESINK) HardwareSerial& serialIUT(Serial2); #else -SoftwareSerial serialIUT; +EspSoftwareSerial::UART serialIUT; #endif HardwareSerial& logger(Serial); #else -SoftwareSerial serialIUT(14, 12); +EspSoftwareSerial::UART serialIUT(14, 12); HardwareSerial& logger(Serial); #endif void setup() { #if defined(ESP8266) #if defined(HWLOOPBACK) || defined(HWSOURCESINK) || defined(HWSOURCESWSINK) - Serial.begin(IUTBITRATE, hwSerialConfig, SERIAL_FULL, 1, invert); + Serial.begin(IUTBITRATE, hwSerialConfig, ::SERIAL_FULL, 1, invert); Serial.swap(); Serial.setRxBufferSize(2 * BLOCKSIZE); - logger.begin(9600, SWSERIAL_8N1, -1, TX); + logger.begin(9600, EspSoftwareSerial::SWSERIAL_8N1, -1, TX); #else logger.begin(9600); #endif @@ -132,7 +134,7 @@ void setup() { logger.begin(9600); #endif - logger.println(PSTR("Loopback example for EspSoftwareSerial")); + logger.println(PSTR("Loopback example for EspEspSoftwareSerial")); start = micros(); txCount = 0; diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/examples/onewiretest/onewiretest.ino b/trunk/Arduino/libraries/EspSoftwareSerial/examples/onewiretest/onewiretest.ino index 7d8a743f..aeb3bf8a 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/examples/onewiretest/onewiretest.ino +++ b/trunk/Arduino/libraries/EspSoftwareSerial/examples/onewiretest/onewiretest.ino @@ -1,17 +1,48 @@ -#include #include "SoftwareSerial.h" -SoftwareSerial swSer1; -SoftwareSerial swSer2; +#ifndef D5 +#if defined(ESP8266) +#define D5 (14) +#define D6 (12) +#elif defined(ESP32) +#define D5 (18) +#define D6 (19) +#endif +#endif + +EspSoftwareSerial::UART swSer1; +EspSoftwareSerial::UART swSer2; + +void checkSwSerial(EspSoftwareSerial::UART* ss) { + byte ch; + while (!Serial.available()); + ss->enableTx(true); + while (Serial.available()) { + ch = Serial.read(); + ss->write(ch); + } + ss->enableTx(false); + // wait 1 second for the reply from EspSoftwareSerial if any + delay(1000); + if (ss->available()) { + Serial.print(PSTR("\nResult:")); + while (ss->available()) { + ch = (byte)ss->read(); + Serial.print(ch < 0x10 ? PSTR(" 0") : PSTR(" ")); + Serial.print(ch, HEX); + } + Serial.println(); + } +} void setup() { delay(2000); Serial.begin(115200); Serial.println(PSTR("\nOne Wire Half Duplex Serial Tester")); - swSer1.begin(115200, SWSERIAL_8N1, 12, 12, false, 256); + swSer1.begin(115200, EspSoftwareSerial::SWSERIAL_8N1, D6, D6, false, 256); // high speed half duplex, turn off interrupts during tx swSer1.enableIntTx(false); - swSer2.begin(115200, SWSERIAL_8N1, 14, 14, false, 256); + swSer2.begin(115200, EspSoftwareSerial::SWSERIAL_8N1, D5, D5, false, 256); // high speed half duplex, turn off interrupts during tx swSer2.enableIntTx(false); } @@ -26,25 +57,3 @@ void loop() { checkSwSerial(&swSer2); } - -void checkSwSerial(SoftwareSerial* ss) { - byte ch; - while (!Serial.available()); - ss->enableTx(true); - while (Serial.available()) { - ch = Serial.read(); - ss->write(ch); - } - ss->enableTx(false); - // wait 1 second for the reply from SOftwareSerial if any - delay(1000); - if (ss->available()) { - Serial.print(PSTR("\nResult:")); - while (ss->available()) { - ch = (byte)ss->read(); - Serial.print(ch < 0x10 ? PSTR(" 0") : PSTR(" ")); - Serial.print(ch, HEX); - } - Serial.println(); - } -} diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/examples/repeater/repeater.ino b/trunk/Arduino/libraries/EspSoftwareSerial/examples/repeater/repeater.ino index d9230a8b..57a29c06 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/examples/repeater/repeater.ino +++ b/trunk/Arduino/libraries/EspSoftwareSerial/examples/repeater/repeater.ino @@ -1,26 +1,28 @@ #include // On ESP8266: -// SoftwareSerial loopback for remote source (loopback.ino), or hardware loopback. +// EspSoftwareSerial loopback for remote source (loopback.ino), or hardware loopback. // Connect source D5 (rx) to local D8 (tx), source D6 (tx) to local D7 (rx). // Hint: The logger is run at 9600bps such that enableIntTx(true) can remain unchanged. Blocking -// interrupts severely impacts the ability of the SoftwareSerial devices to operate concurrently +// interrupts severely impacts the ability of the EspSoftwareSerial devices to operate concurrently // and/or in duplex mode. // On ESP32: // For software or hardware loopback, connect source rx to local D8 (tx), source tx to local D7 (rx). #ifndef D5 #if defined(ESP8266) -#define D5 (14) -#define D6 (12) -#define D7 (13) #define D8 (15) +#define D5 (14) +#define D7 (13) +#define D6 (12) +#define RX (3) #define TX (1) #elif defined(ESP32) -#define D5 (18) -#define D6 (19) -#define D7 (23) #define D8 (5) +#define D5 (18) +#define D7 (23) +#define D6 (19) +#define RX (3) #define TX (1) #endif #endif @@ -35,11 +37,11 @@ constexpr int IUTBITRATE = 19200; #endif #if defined(ESP8266) -constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1; -constexpr SerialConfig hwSerialConfig = SERIAL_8E1; +constexpr EspSoftwareSerial::Config swSerialConfig = EspSoftwareSerial::SWSERIAL_8E1; +constexpr SerialConfig hwSerialConfig = ::SERIAL_8E1; #elif defined(ESP32) -constexpr SoftwareSerialConfig swSerialConfig = SWSERIAL_8E1; -constexpr uint32_t hwSerialConfig = SERIAL_8E1; +constexpr EspSoftwareSerial::Config swSerialConfig = EspSoftwareSerial::SWSERIAL_8E1; +constexpr uint32_t hwSerialConfig = ::SERIAL_8E1; #else constexpr unsigned swSerialConfig = 3; #endif @@ -58,30 +60,30 @@ constexpr int ReportInterval = IUTBITRATE / 8; #if defined(ESP8266) #if defined(HWLOOPBACK) HardwareSerial& repeater(Serial); -SoftwareSerial logger; +EspSoftwareSerial::UART logger; #else -SoftwareSerial repeater; +EspSoftwareSerial::UART repeater; HardwareSerial& logger(Serial); #endif #elif defined(ESP32) #if defined(HWLOOPBACK) HardwareSerial& repeater(Serial2); #else -SoftwareSerial repeater; +EspSoftwareSerial::UART repeater; #endif HardwareSerial& logger(Serial); #else -SoftwareSerial repeater(14, 12); +EspSoftwareSerial::UART repeater(14, 12); HardwareSerial& logger(Serial); #endif void setup() { #if defined(ESP8266) #if defined(HWLOOPBACK) - repeater.begin(IUTBITRATE, hwSerialConfig, SERIAL_FULL, 1, invert); + repeater.begin(IUTBITRATE, hwSerialConfig, ::SERIAL_FULL, 1, invert); repeater.swap(); repeater.setRxBufferSize(2 * BLOCKSIZE); - logger.begin(9600, SWSERIAL_8N1, -1, TX); + logger.begin(9600, EspSoftwareSerial::SWSERIAL_8N1, -1, TX); #else repeater.begin(IUTBITRATE, swSerialConfig, D7, D8, invert, 4 * BLOCKSIZE); #ifdef HALFDUPLEX @@ -105,7 +107,7 @@ void setup() { logger.begin(9600); #endif - logger.println(PSTR("Repeater example for EspSoftwareSerial")); + logger.println(PSTR("Repeater example for EspEspSoftwareSerial")); start = micros(); rxCount = 0; seqErrors = 0; diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/examples/swsertest/swsertest.ino b/trunk/Arduino/libraries/EspSoftwareSerial/examples/swsertest/swsertest.ino index b2b13b73..1a24844d 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/examples/swsertest/swsertest.ino +++ b/trunk/Arduino/libraries/EspSoftwareSerial/examples/swsertest/swsertest.ino @@ -1,21 +1,28 @@ // On ESP8266: -// At 80MHz runs up 57600ps, and at 160MHz CPU frequency up to 115200bps with only negligible errors. -// Connect pin 12 to 14. +// At 80MHz runs up 57600bps, and at 160MHz CPU frequency up to 115200bps with only negligible errors. +// Connect pin 13 to 15. +// For verification and as a example for how to use SW serial on the USB to PC connection, +// which allows the use of HW Serial on GPIO13 and GPIO15 instead, #define SWAPSERIAL below. +// Notice how the bitrates are also swapped then between RX/TX and GPIO13/GPIO15. +// Builtin debug output etc. must be stopped on HW Serial in this case, as it would interfere with the +// external communication on GPIO13/GPIO15. #include #ifndef D5 #if defined(ESP8266) -#define D5 (14) -#define D6 (12) -#define D7 (13) #define D8 (15) +#define D5 (14) +#define D7 (13) +#define D6 (12) +#define RX (3) #define TX (1) #elif defined(ESP32) -#define D5 (18) -#define D6 (19) -#define D7 (23) #define D8 (5) +#define D5 (18) +#define D7 (23) +#define D6 (19) +#define RX (3) #define TX (1) #endif #endif @@ -26,33 +33,47 @@ #define BAUD_RATE 57600 #endif -SoftwareSerial swSer; +#undef SWAPSERIAL + +#ifndef SWAPSERIAL +auto& usbSerial = Serial; +EspSoftwareSerial::UART testSerial; +#else +EspSoftwareSerial::UART usbSerial; +auto& testSerial = Serial; +#endif void setup() { - Serial.begin(115200); - // Important: the buffer size optimizations here, in particular the isrBufSize (11) that is only sufficiently - // large to hold a single 8N1 word, are on the basis that any char written to the loopback SoftwareSerial - // adapter gets read before another write is performed. - // Block writes with a size greater than 1 would usually fail. Do not copy this into your own project without - // reading the documentation. - swSer.begin(BAUD_RATE, SWSERIAL_8N1, D5, D6, false, 95, 11); +#ifndef SWAPSERIAL + usbSerial.begin(115200); + // Important: the buffer size optimizations here, in particular the isrBufSize (11) that is only sufficiently + // large to hold a single word (up to start - 8 data - parity - stop), are on the basis that any char written + // to the loopback EspSoftwareSerial adapter gets read before another write is performed. + // Block writes with a size greater than 1 would usually fail. Do not copy this into your own project without + // reading the documentation. + testSerial.begin(BAUD_RATE, EspSoftwareSerial::SWSERIAL_8N1, D7, D8, false, 95, 11); +#else + testSerial.begin(115200); + testSerial.setDebugOutput(false); + testSerial.swap(); + usbSerial.begin(BAUD_RATE, EspSoftwareSerial::SWSERIAL_8N1, RX, TX, false, 95); +#endif - Serial.println(PSTR("\nSoftware serial test started")); + usbSerial.println(PSTR("\nSoftware serial test started")); - for (char ch = ' '; ch <= 'z'; ch++) { - swSer.write(ch); - } - swSer.println(); + for (char ch = ' '; ch <= 'z'; ch++) { + testSerial.write(ch); + } + testSerial.println(); } void loop() { - while (swSer.available() > 0) { - Serial.write(swSer.read()); - yield(); - } - while (Serial.available() > 0) { - swSer.write(Serial.read()); - yield(); - } - + while (testSerial.available() > 0) { + usbSerial.write(testSerial.read()); + yield(); + } + while (usbSerial.available() > 0) { + testSerial.write(usbSerial.read()); + yield(); + } } diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/keywords.txt b/trunk/Arduino/libraries/EspSoftwareSerial/keywords.txt index 52d48ab3..df0426d1 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/keywords.txt +++ b/trunk/Arduino/libraries/EspSoftwareSerial/keywords.txt @@ -1,5 +1,5 @@ ####################################### -# Syntax Coloring Map for SoftwareSerial +# Syntax Coloring Map for EspSoftwareSerial # (esp8266) ####################################### @@ -7,6 +7,7 @@ # Datatypes (KEYWORD1) ####################################### +EspSoftwareSerial KEYWORD1 SoftwareSerial KEYWORD1 ####################################### @@ -30,7 +31,6 @@ end KEYWORD2 isListening KEYWORD2 stopListening KEYWORD2 onReceive KEYWORD2 -perform_work KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/library.json b/trunk/Arduino/libraries/EspSoftwareSerial/library.json index c25d4991..ef549eb2 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/library.json +++ b/trunk/Arduino/libraries/EspSoftwareSerial/library.json @@ -1,15 +1,26 @@ { "name": "EspSoftwareSerial", - "version": "6.9.0", - "keywords": [ - "serial", "io", "softwareserial" - ], + "version": "8.1.0", "description": "Implementation of the Arduino software serial for ESP8266/ESP32.", + "keywords": [ + "serial", "io", "softwareserial" + ], "repository": { "type": "git", "url": "https://github.com/plerup/espsoftwareserial" }, + "authors": [ + { + "name": "Dirk Kaar" + }, + { + "name": "Peter Lerup" + } + ], + "license": "LGPL-2.1+", "frameworks": "arduino", - "platforms": "*" + "platforms": [ + "espressif8266", "espressif32" + ] } diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/library.properties b/trunk/Arduino/libraries/EspSoftwareSerial/library.properties index 6eaf546c..66ac3893 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/library.properties +++ b/trunk/Arduino/libraries/EspSoftwareSerial/library.properties @@ -1,5 +1,5 @@ name=EspSoftwareSerial -version=6.9.0 +version=8.1.0 author=Dirk Kaar, Peter Lerup maintainer=Dirk Kaar sentence=Implementation of the Arduino software serial for ESP8266/ESP32. diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.cpp b/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.cpp index 048e895a..61461d26 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.cpp +++ b/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.cpp @@ -23,86 +23,106 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "SoftwareSerial.h" #include -#ifdef ESP32 -#define xt_rsil(a) (a) -#define xt_wsr_ps(a) +using namespace EspSoftwareSerial; + +#ifndef ESP32 +uint32_t UARTBase::m_savedPS = 0; +#else +portMUX_TYPE UARTBase::m_interruptsMux = portMUX_INITIALIZER_UNLOCKED; #endif +ALWAYS_INLINE_ATTR inline void IRAM_ATTR UARTBase::disableInterrupts() +{ +#ifndef ESP32 + m_savedPS = xt_rsil(15); +#else + taskENTER_CRITICAL(&m_interruptsMux); +#endif +} + +ALWAYS_INLINE_ATTR inline void IRAM_ATTR UARTBase::restoreInterrupts() +{ +#ifndef ESP32 + xt_wsr_ps(m_savedPS); +#else + taskEXIT_CRITICAL(&m_interruptsMux); +#endif +} + constexpr uint8_t BYTE_ALL_BITS_SET = ~static_cast(0); -SoftwareSerial::SoftwareSerial() { - m_isrOverflow = false; +UARTBase::UARTBase() { } -SoftwareSerial::SoftwareSerial(int8_t rxPin, int8_t txPin, bool invert) +UARTBase::UARTBase(int8_t rxPin, int8_t txPin, bool invert) { - m_isrOverflow = false; m_rxPin = rxPin; m_txPin = txPin; m_invert = invert; } -SoftwareSerial::~SoftwareSerial() { +UARTBase::~UARTBase() { end(); } -bool SoftwareSerial::isValidGPIOpin(int8_t pin) { -#if defined(ESP8266) - return (pin >= 0 && pin <= 16) && !isFlashInterfacePin(pin); -#elif defined(ESP32) - return (pin >= 0 && pin <= 5) || (pin >= 12 && pin <= 19) || - (pin >= 21 && pin <= 23) || (pin >= 25 && pin <= 27) || (pin >= 32 && pin <= 35); -#else - return true; -#endif +void UARTBase::setRxGPIOPinMode() { + if (m_rxValid) { + pinMode(m_rxPin, m_rxGPIOHasPullUp && m_rxGPIOPullUpEnabled ? INPUT_PULLUP : INPUT); + } } -bool SoftwareSerial::isValidRxGPIOpin(int8_t pin) { - return isValidGPIOpin(pin) -#if defined(ESP8266) - && (pin != 16) -#endif - ; +void UARTBase::setTxGPIOPinMode() { + if (m_txValid) { + pinMode(m_txPin, m_txGPIOOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT); + } } -void SoftwareSerial::begin(uint32_t baud, SoftwareSerialConfig config, +void UARTBase::begin(uint32_t baud, Config config, int8_t rxPin, int8_t txPin, - bool invert, int bufCapacity, int isrBufCapacity) { + bool invert) { if (-1 != rxPin) m_rxPin = rxPin; if (-1 != txPin) m_txPin = txPin; m_oneWire = (m_rxPin == m_txPin); m_invert = invert; m_dataBits = 5 + (config & 07); - m_parityMode = static_cast(config & 070); + m_parityMode = static_cast(config & 070); m_stopBits = 1 + ((config & 0300) ? 1 : 0); m_pduBits = m_dataBits + static_cast(m_parityMode) + m_stopBits; - m_bitCycles = (ESP.getCpuFreqMHz() * 1000000UL + baud / 2) / baud; + m_bitTicks = (microsToTicks(1000000UL) + baud / 2) / baud; m_intTxEnabled = true; - if (isValidRxGPIOpin(m_rxPin)) { - m_buffer.reset(new circular_queue((bufCapacity > 0) ? bufCapacity : 64)); - if (m_parityMode) - { - m_parityBuffer.reset(new circular_queue((m_buffer->capacity() + 7) / 8)); - m_parityInPos = m_parityOutPos = 1; - } - m_isrBuffer.reset(new circular_queue((isrBufCapacity > 0) ? - isrBufCapacity : m_buffer->capacity() * (2 + m_dataBits + static_cast(m_parityMode)))); - if (m_buffer && (!m_parityMode || m_parityBuffer) && m_isrBuffer) { - m_rxValid = true; - pinMode(m_rxPin, INPUT_PULLUP); - } - } - if (isValidGPIOpin(m_txPin)) { - m_txValid = true; - if (!m_oneWire) { - pinMode(m_txPin, OUTPUT); - digitalWrite(m_txPin, !m_invert); - } - } - if (!m_rxEnabled) { enableRx(true); } } -void SoftwareSerial::end() +void UARTBase::beginRx(bool hasPullUp, int bufCapacity, int isrBufCapacity) { + m_rxGPIOHasPullUp = hasPullUp; + m_rxReg = portInputRegister(digitalPinToPort(m_rxPin)); + m_rxBitMask = digitalPinToBitMask(m_rxPin); + m_buffer.reset(new circular_queue((bufCapacity > 0) ? bufCapacity : 64)); + if (m_parityMode) + { + m_parityBuffer.reset(new circular_queue((m_buffer->capacity() + 7) / 8)); + m_parityInPos = m_parityOutPos = 1; + } + m_isrBuffer.reset(new circular_queue((isrBufCapacity > 0) ? + isrBufCapacity : m_buffer->capacity() * (2 + m_dataBits + static_cast(m_parityMode)))); + if (m_buffer && (!m_parityMode || m_parityBuffer) && m_isrBuffer) { + m_rxValid = true; + setRxGPIOPinMode(); + } +} + +void UARTBase::beginTx() { +#if !defined(ESP8266) + m_txReg = portOutputRegister(digitalPinToPort(m_txPin)); +#endif + m_txBitMask = digitalPinToBitMask(m_txPin); + m_txValid = true; + if (!m_oneWire) { + setTxGPIOPinMode(); + digitalWrite(m_txPin, !m_invert); + } +} + +void UARTBase::end() { enableRx(false); m_txValid = false; @@ -115,12 +135,12 @@ void SoftwareSerial::end() } } -uint32_t SoftwareSerial::baudRate() { - return ESP.getCpuFreqMHz() * 1000000UL / m_bitCycles; +uint32_t UARTBase::baudRate() { + return 1000000UL / ticksToMicros(m_bitTicks); } -void SoftwareSerial::setTransmitEnablePin(int8_t txEnablePin) { - if (isValidGPIOpin(txEnablePin)) { +void UARTBase::setTransmitEnablePin(int8_t txEnablePin) { + if (-1 != txEnablePin) { m_txEnableValid = true; m_txEnablePin = txEnablePin; pinMode(m_txEnablePin, OUTPUT); @@ -131,31 +151,41 @@ void SoftwareSerial::setTransmitEnablePin(int8_t txEnablePin) { } } -void SoftwareSerial::enableIntTx(bool on) { +void UARTBase::enableIntTx(bool on) { m_intTxEnabled = on; } -void SoftwareSerial::enableTx(bool on) { +void UARTBase::enableRxGPIOPullUp(bool on) { + m_rxGPIOPullUpEnabled = on; + setRxGPIOPinMode(); +} + +void UARTBase::enableTxGPIOOpenDrain(bool on) { + m_txGPIOOpenDrain = on; + setTxGPIOPinMode(); +} + +void UARTBase::enableTx(bool on) { if (m_txValid && m_oneWire) { if (on) { enableRx(false); - pinMode(m_txPin, OUTPUT); + setTxGPIOPinMode(); digitalWrite(m_txPin, !m_invert); } else { - pinMode(m_rxPin, INPUT_PULLUP); + setRxGPIOPinMode(); enableRx(true); } } } -void SoftwareSerial::enableRx(bool on) { - if (m_rxValid) { +void UARTBase::enableRx(bool on) { + if (m_rxValid && on != m_rxEnabled) { if (on) { - m_rxCurBit = m_pduBits - 1; - // Init to stop bit level and current cycle - m_isrLastCycle = (ESP.getCycleCount() | 1) ^ m_invert; - if (m_bitCycles >= (ESP.getCpuFreqMHz() * 1000000UL) / 74880UL) + m_rxLastBit = m_pduBits - 1; + // Init to stop bit level and current tick + m_isrLastTick = (microsToTicks(micros()) | 1) ^ m_invert; + if (m_bitTicks >= microsToTicks(1000000UL / 74880UL)) attachInterruptArg(digitalPinToInterrupt(m_rxPin), reinterpret_cast(rxBitISR), this, CHANGE); else attachInterruptArg(digitalPinToInterrupt(m_rxPin), reinterpret_cast(rxBitSyncISR), this, m_invert ? RISING : FALLING); @@ -167,7 +197,7 @@ void SoftwareSerial::enableRx(bool on) { } } -int SoftwareSerial::read() { +int UARTBase::read() { if (!m_rxValid) { return -1; } if (!m_buffer->available()) { rxBits(); @@ -187,9 +217,9 @@ int SoftwareSerial::read() { return val; } -size_t SoftwareSerial::read(uint8_t* buffer, size_t size) { +int UARTBase::read(uint8_t* buffer, size_t size) { if (!m_rxValid) { return 0; } - size_t avail; + int avail; if (0 == (avail = m_buffer->pop_n(buffer, size))) { rxBits(); avail = m_buffer->pop_n(buffer, size); @@ -204,7 +234,7 @@ size_t SoftwareSerial::read(uint8_t* buffer, size_t size) { return avail; } -size_t SoftwareSerial::readBytes(uint8_t* buffer, size_t size) { +size_t UARTBase::readBytes(uint8_t* buffer, size_t size) { if (!m_rxValid || !size) { return 0; } size_t count = 0; auto start = millis(); @@ -212,13 +242,17 @@ size_t SoftwareSerial::readBytes(uint8_t* buffer, size_t size) { auto readCnt = read(&buffer[count], size - count); count += readCnt; if (count >= size) break; - if (readCnt) start = millis(); - else optimistic_yield(1000UL); + if (readCnt) { + start = millis(); + } + else { + optimistic_yield(1000UL); + } } while (millis() - start < _timeout); return count; } -int SoftwareSerial::available() { +int UARTBase::available() { if (!m_rxValid) { return 0; } rxBits(); int avail = m_buffer->available(); @@ -228,66 +262,90 @@ int SoftwareSerial::available() { return avail; } -void ICACHE_RAM_ATTR SoftwareSerial::preciseDelay(bool sync) { - if (!sync) +void UARTBase::lazyDelay() { + // Reenable interrupts while delaying to avoid other tasks piling up + if (!m_intTxEnabled) { restoreInterrupts(); } + const auto expired = microsToTicks(micros()) - m_periodStart; + const int32_t remaining = m_periodDuration - expired; + const uint32_t ms = remaining > 0 ? ticksToMicros(remaining) / 1000UL : 0; + if (ms > 0) { - // Reenable interrupts while delaying to avoid other tasks piling up - if (!m_intTxEnabled) { xt_wsr_ps(m_savedPS); } - const auto expired = ESP.getCycleCount() - m_periodStart; - const auto ms = (m_periodDuration - expired) / ESP.getCpuFreqMHz() / 1000UL; - if (ms) - { - delay(ms); - } - else - { - do - { - optimistic_yield(10000UL); - } - while ((ESP.getCycleCount() - m_periodStart) < m_periodDuration); - } - // Disable interrupts again - if (!m_intTxEnabled) { m_savedPS = xt_rsil(15); } + delay(ms); } else { - while ((ESP.getCycleCount() - m_periodStart) < m_periodDuration) {} + optimistic_yield(10000UL); } - m_periodDuration = 0; - m_periodStart = ESP.getCycleCount(); + // Assure that below-ms part of delays are not elided + preciseDelay(); + // Disable interrupts again if applicable + if (!m_intTxEnabled) { disableInterrupts(); } } -void ICACHE_RAM_ATTR SoftwareSerial::writePeriod( +void IRAM_ATTR UARTBase::preciseDelay() { + uint32_t ticks; + do { + ticks = microsToTicks(micros()); + } while ((ticks - m_periodStart) < m_periodDuration); + m_periodDuration = 0; + m_periodStart = ticks; +} + +void IRAM_ATTR UARTBase::writePeriod( uint32_t dutyCycle, uint32_t offCycle, bool withStopBit) { - preciseDelay(true); + preciseDelay(); if (dutyCycle) { - digitalWrite(m_txPin, HIGH); +#if defined(ESP8266) + if (16 == m_txPin) { + GP16O = 1; + } + else { + GPOS = m_txBitMask; + } +#else + *m_txReg = *m_txReg | m_txBitMask; +#endif m_periodDuration += dutyCycle; - if (offCycle || (withStopBit && !m_invert)) preciseDelay(!withStopBit || m_invert); + if (offCycle || (withStopBit && !m_invert)) { + if (!withStopBit || m_invert) { + preciseDelay(); + } + else { + lazyDelay(); + } + } } if (offCycle) { - digitalWrite(m_txPin, LOW); +#if defined(ESP8266) + if (16 == m_txPin) { + GP16O = 0; + } + else { + GPOC = m_txBitMask; + } +#else + *m_txReg = *m_txReg & ~m_txBitMask; +#endif m_periodDuration += offCycle; - if (withStopBit && m_invert) preciseDelay(false); + if (withStopBit && m_invert) lazyDelay(); } } -size_t SoftwareSerial::write(uint8_t byte) { +size_t UARTBase::write(uint8_t byte) { return write(&byte, 1); } -size_t SoftwareSerial::write(uint8_t byte, SoftwareSerialParity parity) { +size_t UARTBase::write(uint8_t byte, Parity parity) { return write(&byte, 1, parity); } -size_t SoftwareSerial::write(const uint8_t* buffer, size_t size) { +size_t UARTBase::write(const uint8_t* buffer, size_t size) { return write(buffer, size, m_parityMode); } -size_t ICACHE_RAM_ATTR SoftwareSerial::write(const uint8_t* buffer, size_t size, SoftwareSerialParity parity) { +size_t IRAM_ATTR UARTBase::write(const uint8_t* buffer, size_t size, Parity parity) { if (m_rxValid) { rxBits(); } if (!m_txValid) { return -1; } @@ -300,12 +358,12 @@ size_t ICACHE_RAM_ATTR SoftwareSerial::write(const uint8_t* buffer, size_t size, uint32_t offCycle = 0; if (!m_intTxEnabled) { // Disable interrupts in order to get a clean transmit timing - m_savedPS = xt_rsil(15); + disableInterrupts(); } const uint32_t dataMask = ((1UL << m_dataBits) - 1); bool withStopBit = true; m_periodDuration = 0; - m_periodStart = ESP.getCycleCount(); + m_periodStart = microsToTicks(micros()); for (size_t cnt = 0; cnt < size; ++cnt) { uint8_t byte = pgm_read_byte(buffer + cnt) & dataMask; // push LSB start-data-parity-stop bit pattern into uint32_t @@ -317,24 +375,24 @@ size_t ICACHE_RAM_ATTR SoftwareSerial::write(const uint8_t* buffer, size_t size, uint32_t parityBit; switch (parity) { - case SWSERIAL_PARITY_EVEN: + case PARITY_EVEN: // from inverted, so use odd parity parityBit = byte; parityBit ^= parityBit >> 4; parityBit &= 0xf; parityBit = (0x9669 >> parityBit) & 1; break; - case SWSERIAL_PARITY_ODD: + case PARITY_ODD: // from inverted, so use even parity parityBit = byte; parityBit ^= parityBit >> 4; parityBit &= 0xf; parityBit = (0x6996 >> parityBit) & 1; break; - case SWSERIAL_PARITY_MARK: + case PARITY_MARK: parityBit = 0; break; - case SWSERIAL_PARITY_SPACE: + case PARITY_SPACE: // suppresses warning parityBit uninitialized default: parityBit = 1; @@ -356,18 +414,18 @@ size_t ICACHE_RAM_ATTR SoftwareSerial::write(const uint8_t* buffer, size_t size, dutyCycle = offCycle = 0; } if (b) { - dutyCycle += m_bitCycles; + dutyCycle += m_bitTicks; } else { - offCycle += m_bitCycles; + offCycle += m_bitTicks; } } withStopBit = true; } writePeriod(dutyCycle, offCycle, true); if (!m_intTxEnabled) { - // restore the interrupt state - xt_wsr_ps(m_savedPS); + // restore the interrupt state if applicable + restoreInterrupts(); } if (m_txEnableValid) { digitalWrite(m_txEnablePin, LOW); @@ -375,7 +433,7 @@ size_t ICACHE_RAM_ATTR SoftwareSerial::write(const uint8_t* buffer, size_t size, return size; } -void SoftwareSerial::flush() { +void UARTBase::flush() { if (!m_rxValid) { return; } m_buffer->flush(); if (m_parityBuffer) @@ -385,13 +443,13 @@ void SoftwareSerial::flush() { } } -bool SoftwareSerial::overflow() { +bool UARTBase::overflow() { bool res = m_overflow; m_overflow = false; return res; } -int SoftwareSerial::peek() { +int UARTBase::peek() { if (!m_rxValid) { return -1; } if (!m_buffer->available()) { rxBits(); @@ -402,8 +460,7 @@ int SoftwareSerial::peek() { return val; } -void SoftwareSerial::rxBits() { - int isrAvail = m_isrBuffer->available(); +void UARTBase::rxBits() { #ifdef ESP8266 if (m_isrOverflow.load()) { m_overflow = true; @@ -415,139 +472,150 @@ void SoftwareSerial::rxBits() { } #endif - // stop bit can go undetected if leading data bits are at same level - // and there was also no next start bit yet, so one byte may be pending. - // low-cost check first - if (!isrAvail && m_rxCurBit >= -1 && m_rxCurBit < m_pduBits - m_stopBits) { - uint32_t detectionCycles = (m_pduBits - m_stopBits - m_rxCurBit) * m_bitCycles; - if (ESP.getCycleCount() - m_isrLastCycle > detectionCycles) { + m_isrBuffer->for_each(m_isrBufferForEachDel); + + // A stop bit can go undetected if leading data bits are at same level + // and there was also no next start bit yet, so one word may be pending. + // Check that there was no new ISR data received in the meantime, inserting an + // extraneous stop level bit out of sequence breaks rx. + if (m_rxLastBit < m_pduBits - 1) { + const uint32_t detectionTicks = (m_pduBits - 1 - m_rxLastBit) * m_bitTicks; + if (!m_isrBuffer->available() && microsToTicks(micros()) - m_isrLastTick > detectionTicks) { // Produce faux stop bit level, prevents start bit maldetection - // cycle's LSB is repurposed for the level bit - rxBits(((m_isrLastCycle + detectionCycles) | 1) ^ m_invert); + // tick's LSB is repurposed for the level bit + rxBits(((m_isrLastTick + detectionTicks) | 1) ^ m_invert); } } - - m_isrBuffer->for_each([this](const uint32_t& isrCycle) { rxBits(isrCycle); }); } -void SoftwareSerial::rxBits(const uint32_t& isrCycle) { - bool level = (m_isrLastCycle & 1) ^ m_invert; +void UARTBase::rxBits(const uint32_t isrTick) { + const bool level = (m_isrLastTick & 1) ^ m_invert; - // error introduced by edge value in LSB of isrCycle is negligible - int32_t cycles = isrCycle - m_isrLastCycle; - m_isrLastCycle = isrCycle; + // error introduced by edge value in LSB of isrTick is negligible + uint32_t ticks = isrTick - m_isrLastTick; + m_isrLastTick = isrTick; - uint8_t bits = cycles / m_bitCycles; - if (cycles % m_bitCycles > (m_bitCycles >> 1)) ++bits; + uint32_t bits = ticks / m_bitTicks; + if (ticks % m_bitTicks > (m_bitTicks >> 1)) ++bits; while (bits > 0) { // start bit detection - if (m_rxCurBit >= (m_pduBits - 1)) { - // leading edge of start bit + if (m_rxLastBit >= (m_pduBits - 1)) { + // leading edge of start bit? if (level) break; - m_rxCurBit = -1; + m_rxLastBit = -1; --bits; continue; } // data bits - if (m_rxCurBit >= -1 && m_rxCurBit < (m_dataBits - 1)) { - int8_t dataBits = min(bits, static_cast(m_dataBits - 1 - m_rxCurBit)); - m_rxCurBit += dataBits; + if (m_rxLastBit < (m_dataBits - 1)) { + uint8_t dataBits = min(bits, static_cast(m_dataBits - 1 - m_rxLastBit)); + m_rxLastBit += dataBits; bits -= dataBits; m_rxCurByte >>= dataBits; if (level) { m_rxCurByte |= (BYTE_ALL_BITS_SET << (8 - dataBits)); } continue; } // parity bit - if (m_parityMode && m_rxCurBit == (m_dataBits - 1)) { - ++m_rxCurBit; + if (m_parityMode && m_rxLastBit == (m_dataBits - 1)) { + ++m_rxLastBit; --bits; m_rxCurParity = level; continue; } // stop bits - if (m_rxCurBit < (m_pduBits - m_stopBits - 1)) { - ++m_rxCurBit; - --bits; - continue; - } - if (m_rxCurBit == (m_pduBits - m_stopBits - 1)) { - // Store the received value in the buffer unless we have an overflow - // if not high stop bit level, discard word - if (level) - { - m_rxCurByte >>= (sizeof(uint8_t) * 8 - m_dataBits); - if (!m_buffer->push(m_rxCurByte)) { - m_overflow = true; - } - else { - if (m_parityBuffer) + // Store the received value in the buffer unless we have an overflow + // if not high stop bit level, discard word + if (bits >= static_cast(m_pduBits - 1 - m_rxLastBit) && level) { + m_rxCurByte >>= (sizeof(uint8_t) * 8 - m_dataBits); + if (!m_buffer->push(m_rxCurByte)) { + m_overflow = true; + } + else { + if (m_parityBuffer) + { + if (m_rxCurParity) { + m_parityBuffer->pushpeek() |= m_parityInPos; + } + else { + m_parityBuffer->pushpeek() &= ~m_parityInPos; + } + m_parityInPos <<= 1; + if (!m_parityInPos) { - if (m_rxCurParity) { - m_parityBuffer->pushpeek() |= m_parityInPos; - } - else { - m_parityBuffer->pushpeek() &= ~m_parityInPos; - } - m_parityInPos <<= 1; - if (!m_parityInPos) - { - m_parityBuffer->push(); - m_parityInPos = 1; - } + m_parityBuffer->push(); + m_parityInPos = 1; } } } - m_rxCurBit = m_pduBits; - // reset to 0 is important for masked bit logic - m_rxCurByte = 0; - m_rxCurParity = false; - break; } + m_rxLastBit = m_pduBits - 1; + // reset to 0 is important for masked bit logic + m_rxCurByte = 0; + m_rxCurParity = false; break; } } -void ICACHE_RAM_ATTR SoftwareSerial::rxBitISR(SoftwareSerial* self) { - uint32_t curCycle = ESP.getCycleCount(); - bool level = digitalRead(self->m_rxPin); +void IRAM_ATTR UARTBase::rxBitISR(UARTBase* self) { + const bool level = *self->m_rxReg & self->m_rxBitMask; + const uint32_t curTick = microsToTicks(micros()); + const bool empty = !self->m_isrBuffer->available(); - // Store level and cycle in the buffer unless we have an overflow - // cycle's LSB is repurposed for the level bit - if (!self->m_isrBuffer->push((curCycle | 1U) ^ !level)) self->m_isrOverflow.store(true); + // Store level and tick in the buffer unless we have an overflow + // tick's LSB is repurposed for the level bit + if (!self->m_isrBuffer->push((curTick | 1U) ^ !level)) self->m_isrOverflow.store(true); + // Trigger rx callback only when receiver is starved + if (empty) self->m_rxHandler(); } -void ICACHE_RAM_ATTR SoftwareSerial::rxBitSyncISR(SoftwareSerial* self) { - uint32_t start = ESP.getCycleCount(); - uint32_t wait = self->m_bitCycles - 172U; - +void IRAM_ATTR UARTBase::rxBitSyncISR(UARTBase* self) { bool level = self->m_invert; - // Store level and cycle in the buffer unless we have an overflow - // cycle's LSB is repurposed for the level bit + const uint32_t start = microsToTicks(micros()); + uint32_t wait = self->m_bitTicks; + const bool empty = !self->m_isrBuffer->available(); + + // Store level and tick in the buffer unless we have an overflow + // tick's LSB is repurposed for the level bit if (!self->m_isrBuffer->push(((start + wait) | 1U) ^ !level)) self->m_isrOverflow.store(true); for (uint32_t i = 0; i < self->m_pduBits; ++i) { - while (ESP.getCycleCount() - start < wait) {}; - wait += self->m_bitCycles; + while (microsToTicks(micros()) - start < wait) {}; + wait += self->m_bitTicks; - // Store level and cycle in the buffer unless we have an overflow - // cycle's LSB is repurposed for the level bit - if (digitalRead(self->m_rxPin) != level) + // Store level and tick in the buffer unless we have an overflow + // tick's LSB is repurposed for the level bit + if (static_cast(*self->m_rxReg & self->m_rxBitMask) != level) { if (!self->m_isrBuffer->push(((start + wait) | 1U) ^ level)) self->m_isrOverflow.store(true); level = !level; } } + // Trigger rx callback only when receiver is starved + if (empty) self->m_rxHandler(); } -void SoftwareSerial::onReceive(Delegate handler) { - receiveHandler = handler; +void UARTBase::onReceive(const Delegate& handler) { + disableInterrupts(); + m_rxHandler = handler; + restoreInterrupts(); } -void SoftwareSerial::perform_work() { - if (!m_rxValid) { return; } - rxBits(); - if (receiveHandler) { - int avail = m_buffer->available(); - if (avail) { receiveHandler(avail); } - } +void UARTBase::onReceive(Delegate&& handler) { + disableInterrupts(); + m_rxHandler = std::move(handler); + restoreInterrupts(); } + +#if __GNUC__ < 12 +// The template member functions below must be in IRAM, but due to a bug GCC doesn't currently +// honor the attribute. Instead, it is possible to do explicit specialization and adorn +// these with the IRAM attribute: +// Delegate<>::operator (), circular_queue<>::available, +// circular_queue<>::available_for_push, circular_queue<>::push_peek, circular_queue<>::push + +template void IRAM_ATTR delegate::detail::DelegateImpl::operator()() const; +template size_t IRAM_ATTR circular_queue::available() const; +template bool IRAM_ATTR circular_queue::push(uint32_t&&); +template bool IRAM_ATTR circular_queue::push(const uint32_t&); +#endif // __GNUC__ < 12 + diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h b/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h index bf301fd5..13a11b15 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h +++ b/trunk/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h @@ -1,7 +1,5 @@ /* -SoftwareSerial.h - -SoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266/ESP32. +SoftwareSerial.h - Implementation of the Arduino software serial for ESP8266/ESP32. Copyright (c) 2015-2016 Peter Lerup. All rights reserved. Copyright (c) 2018-2019 Dirk O. Kaar. All rights reserved. @@ -27,52 +25,129 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "circular_queue/circular_queue.h" #include -enum SoftwareSerialParity : uint8_t { - SWSERIAL_PARITY_NONE = 000, - SWSERIAL_PARITY_EVEN = 020, - SWSERIAL_PARITY_ODD = 030, - SWSERIAL_PARITY_MARK = 040, - SWSERIAL_PARITY_SPACE = 070, +namespace EspSoftwareSerial { + +// Interface definition for template argument of BasicUART +class IGpioCapabilities { +public: + static constexpr bool isValidPin(int8_t pin); + static constexpr bool isValidInputPin(int8_t pin); + static constexpr bool isValidOutputPin(int8_t pin); + // result is only defined for a valid Rx pin + static constexpr bool hasPullUp(int8_t pin); }; -enum SoftwareSerialConfig { - SWSERIAL_5N1 = SWSERIAL_PARITY_NONE, +class GpioCapabilities : private IGpioCapabilities { +public: + static constexpr bool isValidPin(int8_t pin) { + #if defined(ESP8266) + return (pin >= 0 && pin <= 16) && !isFlashInterfacePin(pin); + #elif defined(ESP32) + // Remove the strapping pins as defined in the datasheets, they affect bootup and other critical operations + // Remmove the flash memory pins on related devices, since using these causes memory access issues. + #ifdef CONFIG_IDF_TARGET_ESP32 + // Datasheet https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf, + // Pinout https://docs.espressif.com/projects/esp-idf/en/latest/esp32/_images/esp32-devkitC-v4-pinout.jpg + return (pin == 1) || (pin >= 3 && pin <= 5) || + (pin >= 12 && pin <= 15) || + (!psramFound() && pin >= 16 && pin <= 17) || + (pin >= 18 && pin <= 19) || + (pin >= 21 && pin <= 23) || (pin >= 25 && pin <= 27) || (pin >= 32 && pin <= 39); + #elif CONFIG_IDF_TARGET_ESP32S2 + // Datasheet https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf, + // Pinout https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/esp32-s2_saola1-pinout.jpg + return (pin >= 1 && pin <= 21) || (pin >= 33 && pin <= 44); + #elif CONFIG_IDF_TARGET_ESP32C3 + // Datasheet https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf, + // Pinout https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/_images/esp32-c3-devkitm-1-v1-pinout.jpg + return (pin >= 0 && pin <= 1) || (pin >= 3 && pin <= 7) || (pin >= 18 && pin <= 21); + #else + return pin >= 0; + #endif + #else + return pin >= 0; + #endif + } + + static constexpr bool isValidInputPin(int8_t pin) { + return isValidPin(pin) + #if defined(ESP8266) + && (pin != 16) + #endif + ; + } + + static constexpr bool isValidOutputPin(int8_t pin) { + return isValidPin(pin) + #if defined(ESP32) + #ifdef CONFIG_IDF_TARGET_ESP32 + && (pin < 34) + #elif CONFIG_IDF_TARGET_ESP32S2 + && (pin <= 45) + #elif CONFIG_IDF_TARGET_ESP32C3 + // no restrictions + #endif + #endif + ; + } + + // result is only defined for a valid Rx pin + static constexpr bool hasPullUp(int8_t pin) { + #if defined(ESP32) + return !(pin >= 34 && pin <= 39); + #else + (void)pin; + return true; + #endif + } +}; + +enum Parity : uint8_t { + PARITY_NONE = 000, + PARITY_EVEN = 020, + PARITY_ODD = 030, + PARITY_MARK = 040, + PARITY_SPACE = 070, +}; + +enum Config { + SWSERIAL_5N1 = PARITY_NONE, SWSERIAL_6N1, SWSERIAL_7N1, SWSERIAL_8N1, - SWSERIAL_5E1 = SWSERIAL_PARITY_EVEN, + SWSERIAL_5E1 = PARITY_EVEN, SWSERIAL_6E1, SWSERIAL_7E1, SWSERIAL_8E1, - SWSERIAL_5O1 = SWSERIAL_PARITY_ODD, + SWSERIAL_5O1 = PARITY_ODD, SWSERIAL_6O1, SWSERIAL_7O1, SWSERIAL_8O1, - SWSERIAL_5M1 = SWSERIAL_PARITY_MARK, + SWSERIAL_5M1 = PARITY_MARK, SWSERIAL_6M1, SWSERIAL_7M1, SWSERIAL_8M1, - SWSERIAL_5S1 = SWSERIAL_PARITY_SPACE, + SWSERIAL_5S1 = PARITY_SPACE, SWSERIAL_6S1, SWSERIAL_7S1, SWSERIAL_8S1, - SWSERIAL_5N2 = 0200 | SWSERIAL_PARITY_NONE, + SWSERIAL_5N2 = 0200 | PARITY_NONE, SWSERIAL_6N2, SWSERIAL_7N2, SWSERIAL_8N2, - SWSERIAL_5E2 = 0200 | SWSERIAL_PARITY_EVEN, + SWSERIAL_5E2 = 0200 | PARITY_EVEN, SWSERIAL_6E2, SWSERIAL_7E2, SWSERIAL_8E2, - SWSERIAL_5O2 = 0200 | SWSERIAL_PARITY_ODD, + SWSERIAL_5O2 = 0200 | PARITY_ODD, SWSERIAL_6O2, SWSERIAL_7O2, SWSERIAL_8O2, - SWSERIAL_5M2 = 0200 | SWSERIAL_PARITY_MARK, + SWSERIAL_5M2 = 0200 | PARITY_MARK, SWSERIAL_6M2, SWSERIAL_7M2, SWSERIAL_8M2, - SWSERIAL_5S2 = 0200 | SWSERIAL_PARITY_SPACE, + SWSERIAL_5S2 = 0200 | PARITY_SPACE, SWSERIAL_6S2, SWSERIAL_7S2, SWSERIAL_8S2, @@ -84,17 +159,17 @@ enum SoftwareSerialConfig { /// Instead, the begin() function handles pin assignments and logic inversion. /// It also has optional input buffer capacity arguments for byte buffer and ISR bit buffer. /// Bitrates up to at least 115200 can be used. -class SoftwareSerial : public Stream { +class UARTBase : public Stream { public: - SoftwareSerial(); + UARTBase(); /// Ctor to set defaults for pins. /// @param rxPin the GPIO pin used for RX /// @param txPin -1 for onewire protocol, GPIO pin used for twowire TX - SoftwareSerial(int8_t rxPin, int8_t txPin = -1, bool invert = false); - SoftwareSerial(const SoftwareSerial&) = delete; - SoftwareSerial& operator= (const SoftwareSerial&) = delete; - virtual ~SoftwareSerial(); - /// Configure the SoftwareSerial object for use. + UARTBase(int8_t rxPin, int8_t txPin = -1, bool invert = false); + UARTBase(const UARTBase&) = delete; + UARTBase& operator= (const UARTBase&) = delete; + virtual ~UARTBase(); + /// Configure the UARTBase object for use. /// @param baud the TX/RX bitrate /// @param config sets databits, parity, and stop bit count /// @param rxPin -1 or default: either no RX pin, or keeps the rxPin set in the ctor @@ -102,39 +177,35 @@ public: /// @param invert true: uses invert line level logic /// @param bufCapacity the capacity for the received bytes buffer /// @param isrBufCapacity 0: derived from bufCapacity. The capacity of the internal asynchronous - /// bit receive buffer, a suggested size is bufCapacity times the sum of - /// start, data, parity and stop bit count. - void begin(uint32_t baud, SoftwareSerialConfig config, - int8_t rxPin, int8_t txPin, bool invert, - int bufCapacity = 64, int isrBufCapacity = 0); - void begin(uint32_t baud, SoftwareSerialConfig config, - int8_t rxPin, int8_t txPin) { - begin(baud, config, rxPin, txPin, m_invert); - } - void begin(uint32_t baud, SoftwareSerialConfig config, - int8_t rxPin) { - begin(baud, config, rxPin, m_txPin, m_invert); - } - void begin(uint32_t baud, SoftwareSerialConfig config = SWSERIAL_8N1) { - begin(baud, config, m_rxPin, m_txPin, m_invert); - } + /// bit receive buffer, a suggested size is bufCapacity times the sum of + /// start, data, parity and stop bit count. + void begin(uint32_t baud, Config config, + int8_t rxPin, int8_t txPin, bool invert); uint32_t baudRate(); /// Transmit control pin. void setTransmitEnablePin(int8_t txEnablePin); - /// Enable or disable interrupts during tx. + /// Enable (default) or disable interrupts during tx. void enableIntTx(bool on); + /// Enable (default) or disable internal rx GPIO pull-up. + void enableRxGPIOPullUp(bool on); + /// Enable or disable (default) tx GPIO output mode. + void enableTxGPIOOpenDrain(bool on); bool overflow(); int available() override; +#if defined(ESP8266) + int availableForWrite() override { +#else int availableForWrite() { +#endif if (!m_txValid) return 0; return 1; } int peek() override; int read() override; - /// @returns The verbatim parity bit associated with the last read() or peek() call + /// @returns The verbatim parity bit associated with the last successful read() or peek() call bool readParity() { return m_lastReadParity; @@ -152,9 +223,13 @@ public: return (0x9669 >> byte) & 1; } /// The read(buffer, size) functions are non-blocking, the same as readBytes but without timeout - size_t read(uint8_t* buffer, size_t size); + int read(uint8_t* buffer, size_t size) +#if defined(ESP8266) + override +#endif + ; /// The read(buffer, size) functions are non-blocking, the same as readBytes but without timeout - size_t read(char* buffer, size_t size) { + int read(char* buffer, size_t size) { return read(reinterpret_cast(buffer), size); } /// @returns The number of bytes read into buffer, up to size. Times out if the limit set through @@ -167,13 +242,13 @@ public: } void flush() override; size_t write(uint8_t byte) override; - size_t write(uint8_t byte, SoftwareSerialParity parity); + size_t write(uint8_t byte, Parity parity); size_t write(const uint8_t* buffer, size_t size) override; size_t write(const char* buffer, size_t size) { return write(reinterpret_cast(buffer), size); } - size_t write(const uint8_t* buffer, size_t size, SoftwareSerialParity parity); - size_t write(const char* buffer, size_t size, SoftwareSerialParity parity) { + size_t write(const uint8_t* buffer, size_t size, Parity parity); + size_t write(const char* buffer, size_t size, Parity parity) { return write(reinterpret_cast(buffer), size, parity); } operator bool() const { @@ -191,36 +266,72 @@ public: bool isListening() { return m_rxEnabled; } bool stopListening() { enableRx(false); return true; } - /// Set an event handler for received data. - void onReceive(Delegate handler); + /// onReceive sets a callback that will be called in interrupt context + /// when data is received. + /// More precisely, the callback is triggered when UARTBase detects + /// a new reception, which may not yet have completed on invocation. + /// Reading - never from this interrupt context - should therefore be + /// delayed at least for the duration of one incoming word. + void onReceive(const Delegate& handler); + /// onReceive sets a callback that will be called in interrupt context + /// when data is received. + /// More precisely, the callback is triggered when UARTBase detects + /// a new reception, which may not yet have completed on invocation. + /// Reading - never from this interrupt context - should therefore be + /// delayed at least for the duration of one incoming word. + void onReceive(Delegate&& handler); - /// Run the internal processing and event engine. Can be iteratively called - /// from loop, or otherwise scheduled. + [[deprecated("function removed; semantics of onReceive() changed; check the header file.")]] void perform_work(); using Print::write; +protected: + void beginRx(bool hasPullUp, int bufCapacity, int isrBufCapacity); + void beginTx(); + // Member variables + int8_t m_rxPin = -1; + int8_t m_txPin = -1; + bool m_invert = false; + private: - // If sync is false, it's legal to exceed the deadline, for instance, + // It's legal to exceed the deadline, for instance, // by enabling interrupts. - void preciseDelay(bool sync); + void lazyDelay(); + // Synchronous precise delay + void preciseDelay(); // If withStopBit is set, either cycle contains a stop bit. // If dutyCycle == 0, the level is not forced to HIGH. // If offCycle == 0, the level remains unchanged from dutyCycle. void writePeriod( uint32_t dutyCycle, uint32_t offCycle, bool withStopBit); - bool isValidGPIOpin(int8_t pin); - bool isValidRxGPIOpin(int8_t pin); + // safely set the pin mode for the Rx GPIO pin + void setRxGPIOPinMode(); + // safely set the pin mode for the Tx GPIO pin + void setTxGPIOPinMode(); /* check m_rxValid that calling is safe */ void rxBits(); - void rxBits(const uint32_t& isrCycle); + void rxBits(const uint32_t isrTick); + static void disableInterrupts(); + static void restoreInterrupts(); - static void rxBitISR(SoftwareSerial* self); - static void rxBitSyncISR(SoftwareSerial* self); + static void rxBitISR(UARTBase* self); + static void rxBitSyncISR(UARTBase* self); + + static inline uint32_t IRAM_ATTR microsToTicks(uint32_t micros) ALWAYS_INLINE_ATTR { + return micros << 1; + } + static inline uint32_t ticksToMicros(uint32_t ticks) ALWAYS_INLINE_ATTR { + return ticks >> 1; + } // Member variables - int8_t m_rxPin = -1; - int8_t m_txPin = -1; + volatile uint32_t* m_rxReg; + uint32_t m_rxBitMask; +#if !defined(ESP8266) + volatile uint32_t* m_txReg; +#endif + uint32_t m_txBitMask; int8_t m_txEnablePin = -1; uint8_t m_dataBits; bool m_oneWire; @@ -228,31 +339,111 @@ private: bool m_rxEnabled = false; bool m_txValid = false; bool m_txEnableValid = false; - bool m_invert; /// PDU bits include data, parity and stop bits; the start bit is not counted. uint8_t m_pduBits; bool m_intTxEnabled; - SoftwareSerialParity m_parityMode; + bool m_rxGPIOHasPullUp = false; + bool m_rxGPIOPullUpEnabled = true; + bool m_txGPIOOpenDrain = false; + Parity m_parityMode; uint8_t m_stopBits; bool m_lastReadParity; bool m_overflow = false; - uint32_t m_bitCycles; + uint32_t m_bitTicks; uint8_t m_parityInPos; uint8_t m_parityOutPos; - int8_t m_rxCurBit; // 0 thru (m_pduBits - m_stopBits - 1): data/parity bits. -1: start bit. (m_pduBits - 1): stop bit. + int8_t m_rxLastBit; // 0 thru (m_pduBits - m_stopBits - 1): data/parity bits. -1: start bit. (m_pduBits - 1): stop bit. uint8_t m_rxCurByte = 0; std::unique_ptr > m_buffer; std::unique_ptr > m_parityBuffer; uint32_t m_periodStart; uint32_t m_periodDuration; - uint32_t m_savedPS = 0; +#ifndef ESP32 + static uint32_t m_savedPS; +#else + static portMUX_TYPE m_interruptsMux; +#endif // the ISR stores the relative bit times in the buffer. The inversion corrected level is used as sign bit (2's complement): // 1 = positive including 0, 0 = negative. - std::unique_ptr > m_isrBuffer; - std::atomic m_isrOverflow; - uint32_t m_isrLastCycle; + std::unique_ptr > m_isrBuffer; + const Delegate m_isrBufferForEachDel { [](UARTBase* self, uint32_t&& isrTick) { self->rxBits(isrTick); }, this }; + std::atomic m_isrOverflow { false }; + uint32_t m_isrLastTick; bool m_rxCurParity = false; - Delegate receiveHandler; + Delegate m_rxHandler; }; +template< class GpioCapabilities > class BasicUART : public UARTBase { + static_assert(std::is_base_of::value, + "template argument is not derived from IGpioCapabilities"); +public: + BasicUART() : UARTBase() { + } + /// Ctor to set defaults for pins. + /// @param rxPin the GPIO pin used for RX + /// @param txPin -1 for onewire protocol, GPIO pin used for twowire TX + BasicUART(int8_t rxPin, int8_t txPin = -1, bool invert = false) : + UARTBase(rxPin, txPin, invert) { + } + + /// Configure the BasicUART object for use. + /// @param baud the TX/RX bitrate + /// @param config sets databits, parity, and stop bit count + /// @param rxPin -1 or default: either no RX pin, or keeps the rxPin set in the ctor + /// @param txPin -1 or default: either no TX pin (onewire), or keeps the txPin set in the ctor + /// @param invert true: uses invert line level logic + /// @param bufCapacity the capacity for the received bytes buffer + /// @param isrBufCapacity 0: derived from bufCapacity. The capacity of the internal asynchronous + /// bit receive buffer, a suggested size is bufCapacity times the sum of + /// start, data, parity and stop bit count. + void begin(uint32_t baud, Config config, + int8_t rxPin, int8_t txPin, bool invert, + int bufCapacity = 64, int isrBufCapacity = 0) { + UARTBase::begin(baud, config, rxPin, txPin, invert); + if (GpioCapabilities::isValidInputPin(rxPin)) { + beginRx(GpioCapabilities:: hasPullUp(rxPin), bufCapacity, isrBufCapacity); + } + if (GpioCapabilities::isValidOutputPin(txPin)) { + beginTx(); + } + enableRx(true); + } + void begin(uint32_t baud, Config config, + int8_t rxPin, int8_t txPin) { + begin(baud, config, rxPin, txPin, m_invert); + } + void begin(uint32_t baud, Config config, + int8_t rxPin) { + begin(baud, config, rxPin, m_txPin, m_invert); + } + void begin(uint32_t baud, Config config = SWSERIAL_8N1) { + begin(baud, config, m_rxPin, m_txPin, m_invert); + } + void setTransmitEnablePin(int8_t txEnablePin) { + UARTBase::setTransmitEnablePin( + GpioCapabilities::isValidOutputPin(txEnablePin) ? txEnablePin : -1); + } +}; + +using UART = BasicUART< GpioCapabilities >; + +}; // namespace EspSoftwareSerial + +using SoftwareSerial = EspSoftwareSerial::UART; +using namespace EspSoftwareSerial; + +#if __GNUC__ < 12 +// The template member functions below must be in IRAM, but due to a bug GCC doesn't currently +// honor the attribute. Instead, it is possible to do explicit specialization and adorn +// these with the IRAM attribute: +// Delegate<>::operator (), circular_queue<>::available, +// circular_queue<>::available_for_push, circular_queue<>::push_peek, circular_queue<>::push + +extern template void delegate::detail::DelegateImpl::operator()() const; +extern template size_t circular_queue::available() const; +extern template bool circular_queue::push(uint32_t&&); +extern template bool circular_queue::push(const uint32_t&); +#endif // __GNUC__ < 12 + #endif // __SoftwareSerial_h + diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/Delegate.h b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/Delegate.h index 4ec3616d..6bede69c 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/Delegate.h +++ b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/Delegate.h @@ -25,10 +25,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #elif defined(ESP32) #include #else -#define ICACHE_RAM_ATTR #define IRAM_ATTR #endif +#if defined(__GNUC__) +#undef ALWAYS_INLINE_ATTR +#define ALWAYS_INLINE_ATTR __attribute__((always_inline)) +#else +#define ALWAYS_INLINE_ATTR +#endif + #if !defined(ARDUINO) || defined(ESP8266) || defined(ESP32) #include #include @@ -40,7 +46,7 @@ namespace { template - R IRAM_ATTR vPtrToFunPtrExec(void* fn, P... args) + ALWAYS_INLINE_ATTR inline R IRAM_ATTR vPtrToFunPtrExec(void* fn, P... args) { using target_type = R(P...); return reinterpret_cast(fn)(std::forward(args...)); @@ -254,7 +260,7 @@ namespace delegate return *this; } - operator bool() const + IRAM_ATTR operator bool() const { if (FP == kind) { @@ -270,7 +276,7 @@ namespace delegate } } - static R IRAM_ATTR vPtrToFunAPtrExec(void* self, P... args) + static inline R IRAM_ATTR vPtrToFunAPtrExec(void* self, P... args) ALWAYS_INLINE_ATTR { return static_cast(self)->fnA( static_cast(self)->obj, @@ -324,24 +330,32 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()(P... args) const { if (FP == kind) { - return fn(std::forward(args...)); + if (fn) return fn(std::forward(args...)); } else if (FPA == kind) { - return fnA(obj, std::forward(args...)); + if (fnA) return fnA(obj, std::forward(args...)); } else { - return functional(std::forward(args...)); + if (functional) return functional(std::forward(args...)); } + return R(); } protected: - enum { FUNC, FP, FPA } kind; union { FunctionType functional; FunPtr fn; @@ -350,6 +364,7 @@ namespace delegate A obj; }; }; + enum { FUNC, FP, FPA } kind; }; #else template @@ -421,10 +436,10 @@ namespace delegate DelegatePImpl::fn = fn; } - template DelegatePImpl(F fn) + template DelegatePImpl(F functional) { kind = FP; - DelegatePImpl::fn = std::forward(fn); + fn = std::forward(functional); } DelegatePImpl& operator=(const DelegatePImpl& del) @@ -495,7 +510,7 @@ namespace delegate return *this; } - operator bool() const + IRAM_ATTR operator bool() const { if (FP == kind) { @@ -507,7 +522,7 @@ namespace delegate } } - static R IRAM_ATTR vPtrToFunAPtrExec(void* self, P... args) + static inline R IRAM_ATTR vPtrToFunAPtrExec(void* self, P... args) ALWAYS_INLINE_ATTR { return static_cast(self)->fnA( static_cast(self)->obj, @@ -538,25 +553,34 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()(P... args) const { if (FP == kind) { - return fn(std::forward(args...)); + if (fn) return fn(std::forward(args...)); } else { - return fnA(obj, std::forward(args...)); + if (fnA) return fnA(obj, std::forward(args...)); } + return R(); } protected: - enum { FP, FPA } kind; union { FunPtr fn; FunAPtr fnA; }; A obj; + enum { FP, FPA } kind; }; #endif @@ -694,7 +718,7 @@ namespace delegate return *this; } - operator bool() const + IRAM_ATTR operator bool() const { if (FP == kind) { @@ -745,24 +769,33 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()(P... args) const { if (FP == kind) { - return fn(std::forward(args...)); + if (fn) return fn(std::forward(args...)); } else { - return functional(std::forward(args...)); + if (functional) return functional(std::forward(args...)); } + return R(); } protected: - enum { FUNC, FP } kind; union { FunctionType functional; FunPtr fn; }; + enum { FUNC, FP } kind; }; #else template @@ -823,13 +856,13 @@ namespace delegate return *this; } - DelegatePImpl& IRAM_ATTR operator=(std::nullptr_t) + inline DelegatePImpl& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { fn = nullptr; return *this; } - operator bool() const + inline IRAM_ATTR operator bool() const ALWAYS_INLINE_ATTR { return fn; } @@ -844,9 +877,18 @@ namespace delegate return reinterpret_cast(fn); } - R IRAM_ATTR operator()(P... args) const + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. + inline R IRAM_ATTR operator()(P... args) const ALWAYS_INLINE_ATTR { - return fn(std::forward(args...)); + if (fn) return fn(std::forward(args...)); + return R(); } protected: @@ -1055,7 +1097,7 @@ namespace delegate return *this; } - operator bool() const + IRAM_ATTR operator bool() const { if (FP == kind) { @@ -1071,7 +1113,7 @@ namespace delegate } } - static R IRAM_ATTR vPtrToFunAPtrExec(void* self) + static inline R IRAM_ATTR vPtrToFunAPtrExec(void* self) ALWAYS_INLINE_ATTR { return static_cast(self)->fnA( static_cast(self)->obj); @@ -1124,24 +1166,32 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()() const { if (FP == kind) { - return fn(); + if (fn) return fn(); } else if (FPA == kind) { - return fnA(obj); + if (fnA) return fnA(obj); } else { - return functional(); + if (functional) return functional(); } + return R(); } protected: - enum { FUNC, FP, FPA } kind; union { FunctionType functional; FunPtr fn; @@ -1150,6 +1200,7 @@ namespace delegate A obj; }; }; + enum { FUNC, FP, FPA } kind; }; #else template @@ -1295,7 +1346,7 @@ namespace delegate return *this; } - operator bool() const + IRAM_ATTR operator bool() const { if (FP == kind) { @@ -1307,7 +1358,7 @@ namespace delegate } } - static R IRAM_ATTR vPtrToFunAPtrExec(void* self) + static inline R IRAM_ATTR vPtrToFunAPtrExec(void* self) ALWAYS_INLINE_ATTR { return static_cast(self)->fnA( static_cast(self)->obj); @@ -1337,25 +1388,34 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()() const { if (FP == kind) { - return fn(); + if (fn) return fn(); } else { - return fnA(obj); + if (fnA) return fnA(obj); } + return R(); } protected: - enum { FP, FPA } kind; union { FunPtr fn; FunAPtr fnA; }; A obj; + enum { FP, FPA } kind; }; #endif @@ -1493,7 +1553,7 @@ namespace delegate return *this; } - operator bool() const + IRAM_ATTR operator bool() const { if (FP == kind) { @@ -1544,24 +1604,33 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()() const { if (FP == kind) { - return fn(); + if (fn) return fn(); } else { - return functional(); + if (functional) return functional(); } + return R(); } protected: - enum { FUNC, FP } kind; union { FunctionType functional; FunPtr fn; }; + enum { FUNC, FP } kind; }; #else template @@ -1622,13 +1691,13 @@ namespace delegate return *this; } - DelegateImpl& IRAM_ATTR operator=(std::nullptr_t) + inline DelegateImpl& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { fn = nullptr; return *this; } - operator bool() const + inline IRAM_ATTR operator bool() const ALWAYS_INLINE_ATTR { return fn; } @@ -1643,9 +1712,18 @@ namespace delegate return nullptr; } - R IRAM_ATTR operator()() const + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. + inline R IRAM_ATTR operator()() const ALWAYS_INLINE_ATTR { - return fn(); + if (fn) return fn(); + return R(); } protected: @@ -1691,7 +1769,7 @@ namespace delegate Delegate(FunPtr fn) : detail::DelegatePImpl::DelegatePImpl(fn) {} - template Delegate(F functional) : detail::DelegatePImpl::DelegatePImpl(functional) {} + template Delegate(F functional) : detail::DelegatePImpl::DelegatePImpl(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { detail::DelegatePImpl::operator=(del); @@ -1708,7 +1786,7 @@ namespace delegate return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { detail::DelegatePImpl::operator=(nullptr); return *this; } @@ -1770,7 +1848,7 @@ namespace delegate Delegate(FunPtr fn) : detail::DelegatePImpl::DelegatePImpl(fn) {} - template Delegate(F functional) : detail::DelegatePImpl::DelegatePImpl(functional) {} + template Delegate(F functional) : detail::DelegatePImpl::DelegatePImpl(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { detail::DelegatePImpl::operator=(del); @@ -1787,7 +1865,7 @@ namespace delegate return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { detail::DelegatePImpl::operator=(nullptr); return *this; } @@ -1826,7 +1904,7 @@ namespace delegate Delegate(FunPtr fn) : detail::DelegatePImpl::DelegatePImpl(fn) {} - template Delegate(F functional) : detail::DelegatePImpl::DelegatePImpl(functional) {} + template Delegate(F functional) : detail::DelegatePImpl::DelegatePImpl(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { detail::DelegatePImpl::operator=(del); @@ -1843,7 +1921,7 @@ namespace delegate return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { detail::DelegatePImpl::operator=(nullptr); return *this; } @@ -1887,7 +1965,7 @@ namespace delegate Delegate(FunPtr fn) : detail::DelegateImpl::DelegateImpl(fn) {} - template Delegate(F functional) : detail::DelegateImpl::DelegateImpl(functional) {} + template Delegate(F functional) : detail::DelegateImpl::DelegateImpl(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { detail::DelegateImpl::operator=(del); @@ -1904,7 +1982,7 @@ namespace delegate return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { detail::DelegateImpl::operator=(nullptr); return *this; } @@ -1966,7 +2044,7 @@ namespace delegate Delegate(FunPtr fn) : detail::DelegateImpl::DelegateImpl(fn) {} - template Delegate(F functional) : detail::DelegateImpl::DelegateImpl(functional) {} + template Delegate(F functional) : detail::DelegateImpl::DelegateImpl(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { detail::DelegateImpl::operator=(del); @@ -1983,7 +2061,7 @@ namespace delegate return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { detail::DelegateImpl::operator=(nullptr); return *this; } @@ -2022,7 +2100,7 @@ namespace delegate Delegate(FunPtr fn) : detail::DelegateImpl::DelegateImpl(fn) {} - template Delegate(F functional) : detail::DelegateImpl::DelegateImpl(functional) {} + template Delegate(F functional) : detail::DelegateImpl::DelegateImpl(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { detail::DelegateImpl::operator=(del); @@ -2039,7 +2117,7 @@ namespace delegate return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { detail::DelegateImpl::operator=(nullptr); return *this; } @@ -2067,7 +2145,7 @@ public: Delegate(typename delegate::detail::Delegate::FunPtr fn) : delegate::detail::Delegate::Delegate(fn) {} - template Delegate(F functional) : delegate::detail::Delegate::Delegate(functional) {} + template Delegate(F functional) : delegate::detail::Delegate::Delegate(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { delegate::detail::Delegate::operator=(del); @@ -2084,11 +2162,12 @@ public: return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { delegate::detail::Delegate::operator=(nullptr); return *this; } }; + template class Delegate : public delegate::detail::Delegate { public: @@ -2104,7 +2183,7 @@ public: Delegate(typename delegate::detail::Delegate::FunPtr fn) : delegate::detail::Delegate::Delegate(fn) {} - template Delegate(F functional) : delegate::detail::Delegate::Delegate(functional) {} + template Delegate(F functional) : delegate::detail::Delegate::Delegate(std::forward(functional)) {} Delegate& operator=(const Delegate& del) { delegate::detail::Delegate::operator=(del); @@ -2121,7 +2200,7 @@ public: return *this; } - Delegate& IRAM_ATTR operator=(std::nullptr_t) { + inline Delegate& IRAM_ATTR operator=(std::nullptr_t) ALWAYS_INLINE_ATTR { delegate::detail::Delegate::operator=(nullptr); return *this; } diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/MultiDelegate.h b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/MultiDelegate.h index 36cbd94b..aee07418 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/MultiDelegate.h +++ b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/MultiDelegate.h @@ -281,12 +281,12 @@ namespace delegate return iterator(); } - const Delegate* IRAM_ATTR add(const Delegate& del) + const Delegate* add(const Delegate& del) { return add(Delegate(del)); } - const Delegate* IRAM_ATTR add(Delegate&& del) + const Delegate* add(Delegate&& del) { if (!del) return nullptr; diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue.h b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue.h index 72b056dd..3bd5e000 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue.h +++ b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue.h @@ -35,10 +35,16 @@ using std::min; #endif #if !defined(ESP32) && !defined(ESP8266) -#define ICACHE_RAM_ATTR #define IRAM_ATTR #endif +#if defined(__GNUC__) +#undef ALWAYS_INLINE_ATTR +#define ALWAYS_INLINE_ATTR __attribute__((always_inline)) +#else +#define ALWAYS_INLINE_ATTR +#endif + /*! @brief Instance class for a single-producer, single-consumer circular queue / ring buffer (FIFO). This implementation is lock-free between producer and consumer for the available(), peek(), @@ -109,7 +115,7 @@ public: /*! @brief Get a snapshot number of elements that can be retrieved by pop. */ - size_t available() const + size_t IRAM_ATTR available() const { int avail = static_cast(m_inPos.load() - m_outPos.load()); if (avail < 0) avail += m_bufSize; @@ -119,7 +125,7 @@ public: /*! @brief Get the remaining free elementes for pushing. */ - size_t available_for_push() const + size_t IRAM_ATTR available_for_push() const { int avail = static_cast(m_outPos.load() - m_inPos.load()) - 1; if (avail < 0) avail += m_bufSize; @@ -154,21 +160,42 @@ public: @return true if the queue accepted the value, false if the queue was full. */ - bool IRAM_ATTR push(); + bool IRAM_ATTR push() + { + const auto inPos = m_inPos.load(std::memory_order_acquire); + const size_t next = (inPos + 1) % m_bufSize; + if (next == m_outPos.load(std::memory_order_relaxed)) { + return false; + } + std::atomic_thread_fence(std::memory_order_release); + m_inPos.store(next, std::memory_order_release); + return true; + } /*! @brief Move the rvalue parameter into the queue. @return true if the queue accepted the value, false if the queue was full. */ - bool IRAM_ATTR push(T&& val); + bool IRAM_ATTR push(T&& val) + { + const auto inPos = m_inPos.load(std::memory_order_acquire); + const size_t next = (inPos + 1) % m_bufSize; + if (next == m_outPos.load(std::memory_order_relaxed)) { + return false; + } + m_buffer[inPos] = std::move(val); + std::atomic_thread_fence(std::memory_order_release); + m_inPos.store(next, std::memory_order_release); + return true; + } /*! @brief Push a copy of the parameter into the queue. @return true if the queue accepted the value, false if the queue was full. */ - bool IRAM_ATTR push(const T& val) + inline bool IRAM_ATTR push(const T& val) ALWAYS_INLINE_ATTR { T v(val); return push(std::move(v)); @@ -224,7 +251,6 @@ public: #endif protected: - const T defaultValue = {}; size_t m_bufSize; #if defined(ESP8266) || defined(ESP32) || !defined(ARDUINO) std::unique_ptr m_buffer; @@ -244,43 +270,8 @@ bool circular_queue::capacity(const size_t cap) const auto available = pop_n(buffer, cap); m_buffer.reset(buffer); m_bufSize = cap + 1; - std::atomic_thread_fence(std::memory_order_release); m_inPos.store(available, std::memory_order_relaxed); - m_outPos.store(0, std::memory_order_release); - return true; -} - -template< typename T, typename ForEachArg > -bool IRAM_ATTR circular_queue::push() -{ - const auto inPos = m_inPos.load(std::memory_order_acquire); - const size_t next = (inPos + 1) % m_bufSize; - if (next == m_outPos.load(std::memory_order_relaxed)) { - return false; - } - - std::atomic_thread_fence(std::memory_order_acquire); - - m_inPos.store(next, std::memory_order_release); - return true; -} - -template< typename T, typename ForEachArg > -bool IRAM_ATTR circular_queue::push(T&& val) -{ - const auto inPos = m_inPos.load(std::memory_order_acquire); - const size_t next = (inPos + 1) % m_bufSize; - if (next == m_outPos.load(std::memory_order_relaxed)) { - return false; - } - - std::atomic_thread_fence(std::memory_order_acquire); - - m_buffer[inPos] = std::move(val); - - std::atomic_thread_fence(std::memory_order_release); - - m_inPos.store(next, std::memory_order_release); + m_outPos.store(0, std::memory_order_relaxed); return true; } @@ -296,8 +287,6 @@ size_t circular_queue::push_n(const T* buffer, size_t size) if (!blockSize) return 0; int next = (inPos + blockSize) % m_bufSize; - std::atomic_thread_fence(std::memory_order_acquire); - auto dest = m_buffer.get() + inPos; std::copy_n(std::make_move_iterator(buffer), blockSize, dest); size = min(size - blockSize, outPos > 1 ? static_cast(outPos - next - 1) : 0); @@ -306,7 +295,6 @@ size_t circular_queue::push_n(const T* buffer, size_t size) std::copy_n(std::make_move_iterator(buffer + blockSize), size, dest); std::atomic_thread_fence(std::memory_order_release); - m_inPos.store(next, std::memory_order_release); return blockSize + size; } @@ -316,14 +304,12 @@ template< typename T, typename ForEachArg > T circular_queue::pop() { const auto outPos = m_outPos.load(std::memory_order_acquire); - if (m_inPos.load(std::memory_order_relaxed) == outPos) return defaultValue; + if (m_inPos.load(std::memory_order_relaxed) == outPos) return {}; std::atomic_thread_fence(std::memory_order_acquire); auto val = std::move(m_buffer[outPos]); - std::atomic_thread_fence(std::memory_order_release); - m_outPos.store((outPos + 1) % m_bufSize, std::memory_order_release); return val; } @@ -344,8 +330,6 @@ size_t circular_queue::pop_n(T* buffer, size_t size) { std::copy_n(std::make_move_iterator(m_buffer.get()), avail, buffer); } - std::atomic_thread_fence(std::memory_order_release); - m_outPos.store((outPos + size) % m_bufSize, std::memory_order_release); return size; } @@ -364,7 +348,6 @@ void circular_queue::for_each(Delegate fun while (outPos != inPos) { fun(std::move(m_buffer[outPos])); - std::atomic_thread_fence(std::memory_order_release); outPos = (outPos + 1) % m_bufSize; m_outPos.store(outPos, std::memory_order_release); } @@ -379,11 +362,11 @@ bool circular_queue::for_each_rev_requeue(Delegate::m_inPos.load(std::memory_order_acquire); auto outPos = circular_queue::m_outPos.load(std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_acquire); if (outPos == inPos0) return false; auto pos = inPos0; auto outPos1 = inPos0; const auto posDecr = circular_queue::m_bufSize - 1; + std::atomic_thread_fence(std::memory_order_acquire); do { pos = (pos + posDecr) % circular_queue::m_bufSize; T&& val = std::move(circular_queue::m_buffer[pos]); @@ -393,6 +376,7 @@ bool circular_queue::for_each_rev_requeue(Delegate::m_buffer[outPos1] = std::move(val); } } while (pos != outPos); + std::atomic_thread_fence(std::memory_order_release); circular_queue::m_outPos.store(outPos1, std::memory_order_release); return true; } diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue_mp.h b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue_mp.h index ba376890..7d3b98e6 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue_mp.h +++ b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/circular_queue_mp.h @@ -22,56 +22,71 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "circular_queue.h" -#ifdef ESP8266 -#include "interrupts.h" -#else -#include +#if defined(ESP8266) +#include +using esp8266::InterruptLock; #endif /*! @brief Instance class for a multi-producer, single-consumer circular queue / ring buffer (FIFO). This implementation is lock-free between producers and consumer for the available(), peek(), - pop(), and push() type functions, but is guarded to safely allow only a single producer - at any instant. + pop(), and push() type functions. */ template< typename T, typename ForEachArg = void > class circular_queue_mp : protected circular_queue { public: - circular_queue_mp() = default; + circular_queue_mp() : circular_queue() + { + m_inPos_mp.store(0); + m_concurrent_mp.store(0); + } circular_queue_mp(const size_t capacity) : circular_queue(capacity) - {} - circular_queue_mp(circular_queue&& cq) : circular_queue(std::move(cq)) - {} - using circular_queue::operator=; + { + m_inPos_mp.store(0); + m_concurrent_mp.store(0); + } + circular_queue_mp(circular_queue_mp&& cq) : circular_queue(std::move(cq)) + { + m_inPos_mp.store(cq.m_inPos_mp.load()); + m_concurrent_mp.store(cq.m_concurrent_mp.load()); + } + circular_queue_mp& operator=(circular_queue_mp&& cq) + { + circular_queue::operator=(std::move(cq)); + m_inPos_mp.store(cq.m_inPos_mp.load()); + m_concurrent_mp.store(cq.m_concurrent_mp.load()); + } + circular_queue_mp& operator=(const circular_queue_mp&) = delete; + using circular_queue::capacity; using circular_queue::flush; - using circular_queue::available; - using circular_queue::available_for_push; using circular_queue::peek; using circular_queue::pop; using circular_queue::pop_n; using circular_queue::for_each; using circular_queue::for_each_rev_requeue; + T& pushpeek() = delete; + bool push() = delete; + + inline size_t IRAM_ATTR available() const ALWAYS_INLINE_ATTR + { + return circular_queue::available(); + } + inline size_t IRAM_ATTR available_for_push() const ALWAYS_INLINE_ATTR + { + return circular_queue::available_for_push(); + } + /*! @brief Resize the queue. The available elements in the queue are preserved. - This is not lock-free, but safe, concurrent producer or consumer access - is guarded. + This is not lock-free and concurrent producer or consumer access + will lead to corruption. @return True if the new capacity could accommodate the present elements in the queue, otherwise nothing is done and false is returned. */ - bool capacity(const size_t cap) - { -#ifdef ESP8266 - esp8266::InterruptLock lock; -#else - std::lock_guard lock(m_pushMtx); -#endif - return circular_queue::capacity(cap); - } - - bool IRAM_ATTR push() = delete; + bool capacity(const size_t cap); /*! @brief Move the rvalue parameter into the queue, guarded @@ -79,15 +94,7 @@ public: @return true if the queue accepted the value, false if the queue was full. */ - bool IRAM_ATTR push(T&& val) - { -#ifdef ESP8266 - esp8266::InterruptLock lock; -#else - std::lock_guard lock(m_pushMtx); -#endif - return circular_queue::push(std::move(val)); - } + bool push(T&& val); /*! @brief Push a copy of the parameter into the queue, guarded @@ -95,106 +102,209 @@ public: @return true if the queue accepted the value, false if the queue was full. */ - bool IRAM_ATTR push(const T& val) + inline bool IRAM_ATTR push(const T& val) ALWAYS_INLINE_ATTR { -#ifdef ESP8266 - esp8266::InterruptLock lock; -#else - std::lock_guard lock(m_pushMtx); -#endif - return circular_queue::push(val); + T v(val); + return push(std::move(v)); } /*! @brief Push copies of multiple elements from a buffer into the queue, - in order, beginning at buffer's head. This is guarded for - multiple producers, push_n() is atomic. + in order, beginning at buffer's head. This is safe for + multiple producers. @return The number of elements actually copied into the queue, counted from the buffer head. */ - size_t push_n(const T* buffer, size_t size) - { -#ifdef ESP8266 - esp8266::InterruptLock lock; -#else - std::lock_guard lock(m_pushMtx); +#if defined(ESP8266) || defined(ESP32) || !defined(ARDUINO) + size_t push_n(const T* buffer, size_t size); #endif - return circular_queue::push_n(buffer, size); - } - /*! - @brief Pops the next available element from the queue, requeues - it immediately. - @return A reference to the just requeued element, or the default - value of type T if the queue is empty. - */ - T& pop_requeue(); - - /*! - @brief Iterate over, pop and optionally requeue each available element from the queue, - calling back fun with a reference of every single element. - Requeuing is dependent on the return boolean of the callback function. If it - returns true, the requeue occurs. - */ - bool for_each_requeue(const Delegate& fun); - -#ifndef ESP8266 protected: - std::mutex m_pushMtx; -#endif + std::atomic m_inPos_mp; + std::atomic m_concurrent_mp; }; template< typename T, typename ForEachArg > -T& circular_queue_mp::pop_requeue() +bool circular_queue_mp::capacity(const size_t cap) { -#ifdef ESP8266 - esp8266::InterruptLock lock; -#else - std::lock_guard lock(m_pushMtx); -#endif - const auto outPos = circular_queue::m_outPos.load(std::memory_order_acquire); - const auto inPos = circular_queue::m_inPos.load(std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_acquire); - if (inPos == outPos) return circular_queue::defaultValue; - T& val = circular_queue::m_buffer[inPos] = std::move(circular_queue::m_buffer[outPos]); - const auto bufSize = circular_queue::m_bufSize; - std::atomic_thread_fence(std::memory_order_release); - circular_queue::m_outPos.store((outPos + 1) % bufSize, std::memory_order_relaxed); - circular_queue::m_inPos.store((inPos + 1) % bufSize, std::memory_order_release); - return val; -} - -template< typename T, typename ForEachArg > -bool circular_queue_mp::for_each_requeue(const Delegate& fun) -{ - auto inPos0 = circular_queue::m_inPos.load(std::memory_order_acquire); - auto outPos = circular_queue::m_outPos.load(std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_acquire); - if (outPos == inPos0) return false; - do { - T&& val = std::move(circular_queue::m_buffer[outPos]); - if (fun(val)) - { -#ifdef ESP8266 - esp8266::InterruptLock lock; -#else - std::lock_guard lock(m_pushMtx); -#endif - std::atomic_thread_fence(std::memory_order_release); - auto inPos = circular_queue::m_inPos.load(std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_acquire); - circular_queue::m_buffer[inPos] = std::move(val); - std::atomic_thread_fence(std::memory_order_release); - circular_queue::m_inPos.store((inPos + 1) % circular_queue::m_bufSize, std::memory_order_release); - } - else - { - std::atomic_thread_fence(std::memory_order_release); - } - outPos = (outPos + 1) % circular_queue::m_bufSize; - circular_queue::m_outPos.store(outPos, std::memory_order_release); - } while (outPos != inPos0); + if (cap + 1 == circular_queue::m_bufSize) return true; + else if (!circular_queue::capacity(cap)) return false; + m_inPos_mp.store(circular_queue::m_inPos.load(std::memory_order_relaxed), + std::memory_order_relaxed); + m_concurrent_mp.store(0, std::memory_order_relaxed); return true; } +template< typename T, typename ForEachArg > +bool IRAM_ATTR circular_queue_mp::push(T&& val) +{ + size_t inPos_mp; + size_t next; +#if !defined(ESP32) && defined(ARDUINO) + class InterruptLock { + public: + InterruptLock() { + noInterrupts(); + } + ~InterruptLock() { + interrupts(); + } + }; + { + InterruptLock lock; +#else + ++m_concurrent_mp; + do + { +#endif + inPos_mp = m_inPos_mp.load(std::memory_order_relaxed); + next = (inPos_mp + 1) % circular_queue::m_bufSize; + if (next == circular_queue::m_outPos.load(std::memory_order_relaxed)) { +#if !defined(ESP32) && defined(ARDUINO) + return false; + } + m_inPos_mp.store(next, std::memory_order_relaxed); + m_concurrent_mp.store(m_concurrent_mp.load(std::memory_order_relaxed) + 1, + std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + } +#else + int concurrent_mp; + do + { + inPos_mp = m_inPos_mp.load(); + concurrent_mp = m_concurrent_mp.load(); + if (1 == concurrent_mp) + { + circular_queue::m_inPos.store(inPos_mp, std::memory_order_release); + } + } + while (!m_concurrent_mp.compare_exchange_weak(concurrent_mp, concurrent_mp - 1)); + return false; + } + } + while (!m_inPos_mp.compare_exchange_weak(inPos_mp, next)); +#endif + + circular_queue::m_buffer[inPos_mp] = std::move(val); + + std::atomic_thread_fence(std::memory_order_release); + +#if !defined(ESP32) && defined(ARDUINO) + { + InterruptLock lock; + if (1 == m_concurrent_mp.load(std::memory_order_relaxed)) + { + inPos_mp = m_inPos_mp.load(std::memory_order_relaxed); + circular_queue::m_inPos.store(inPos_mp, std::memory_order_relaxed); + } + m_concurrent_mp.store(m_concurrent_mp.load(std::memory_order_relaxed) - 1, + std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + } +#else + int concurrent_mp; + do + { + inPos_mp = m_inPos_mp.load(); + concurrent_mp = m_concurrent_mp.load(); + if (1 == concurrent_mp) + { + circular_queue::m_inPos.store(inPos_mp, std::memory_order_release); + } + } + while (!m_concurrent_mp.compare_exchange_weak(concurrent_mp, concurrent_mp - 1)); +#endif + + return true; +} + +#if defined(ESP8266) || defined(ESP32) || !defined(ARDUINO) +template< typename T, typename ForEachArg > +size_t circular_queue_mp::push_n(const T* buffer, size_t size) +{ + const auto outPos = circular_queue::m_outPos.load(std::memory_order_relaxed); + size_t inPos_mp; + size_t next; + size_t blockSize; +#if !defined(ESP32) && defined(ARDUINO) + { + InterruptLock lock; +#else + ++m_concurrent_mp; + do + { +#endif + inPos_mp = m_inPos_mp.load(std::memory_order_relaxed); + blockSize = (outPos > inPos_mp) ? outPos - 1 - inPos_mp : (outPos == 0) ? circular_queue::m_bufSize - 1 - inPos_mp : circular_queue::m_bufSize - inPos_mp; + blockSize = min(size, blockSize); + if (!blockSize) + { +#if !defined(ESP32) && defined(ARDUINO) + return 0; + } + next = (inPos_mp + blockSize) % circular_queue::m_bufSize; + m_inPos_mp.store(next, std::memory_order_relaxed); + m_concurrent_mp.store(m_concurrent_mp.load(std::memory_order_relaxed) + 1, + std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + } +#else + int concurrent_mp = m_concurrent_mp.load(); + do + { + inPos_mp = m_inPos_mp.load(); + concurrent_mp = m_concurrent_mp.load(); + if (1 == concurrent_mp) + { + circular_queue::m_inPos.store(inPos_mp, std::memory_order_release); + } + } + while (!m_concurrent_mp.compare_exchange_weak(concurrent_mp, concurrent_mp - 1)); + return false; + } + } + while (!m_inPos_mp.compare_exchange_weak(inPos_mp, next)); +#endif + + auto dest = circular_queue::m_buffer.get() + inPos_mp; + std::copy_n(std::make_move_iterator(buffer), blockSize, dest); + size = min(size - blockSize, outPos > 1 ? static_cast(outPos - next - 1) : 0); + next += size; + dest = circular_queue::m_buffer.get(); + std::copy_n(std::make_move_iterator(buffer + blockSize), size, dest); + + std::atomic_thread_fence(std::memory_order_release); + +#if !defined(ESP32) && defined(ARDUINO) + { + InterruptLock lock; + if (1 == m_concurrent_mp.load(std::memory_order_relaxed)) + { + inPos_mp = m_inPos_mp.load(std::memory_order_relaxed); + circular_queue::m_inPos.store(inPos_mp, std::memory_order_relaxed); + } + m_concurrent_mp.store(m_concurrent_mp.load(std::memory_order_relaxed) - 1, + std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + } +#else + int concurrent_mp; + do + { + inPos_mp = m_inPos_mp.load(); + concurrent_mp = m_concurrent_mp.load(); + if (1 == concurrent_mp) + { + circular_queue::m_inPos.store(inPos_mp, std::memory_order_release); + } + } + while (!m_concurrent_mp.compare_exchange_weak(concurrent_mp, concurrent_mp - 1)); +#endif + + return blockSize + size; +} + +#endif + #endif // __circular_queue_mp_h diff --git a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/ghostl.h b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/ghostl.h index 50f522c9..ba3f8639 100644 --- a/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/ghostl.h +++ b/trunk/Arduino/libraries/EspSoftwareSerial/src/circular_queue/ghostl.h @@ -47,7 +47,7 @@ namespace std T load(std::memory_order = std::memory_order_seq_cst) const volatile noexcept { return value; } }; inline void atomic_thread_fence(std::memory_order order) noexcept {} - template< typename T > T&& move(T& t) noexcept { return static_cast(t); } + template< typename T > T&& move(T& t) noexcept { return static_cast(t); } #endif template< typename T, size_t long N > struct array diff --git a/trunk/Arduino/libraries/Ethernet/library.properties b/trunk/Arduino/libraries/Ethernet/library.properties index dee6ce04..f3f36166 100644 --- a/trunk/Arduino/libraries/Ethernet/library.properties +++ b/trunk/Arduino/libraries/Ethernet/library.properties @@ -1,5 +1,5 @@ name=Ethernet -version=2.0.1 +version=2.0.2 author=Various (see AUTHORS file for details) maintainer=Arduino sentence=Enables network connection (local and Internet) using the Arduino Ethernet Board or Shield. diff --git a/trunk/Arduino/libraries/Ethernet/src/Ethernet.cpp b/trunk/Arduino/libraries/Ethernet/src/Ethernet.cpp index 9257090c..8d9ce7fd 100644 --- a/trunk/Arduino/libraries/Ethernet/src/Ethernet.cpp +++ b/trunk/Arduino/libraries/Ethernet/src/Ethernet.cpp @@ -83,19 +83,9 @@ void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress g if (W5100.init() == 0) return; SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setMACAddress(mac); -#ifdef ESP8266 - W5100.setIPAddress(&ip[0]); - W5100.setGatewayIp(&gateway[0]); - W5100.setSubnetMask(&subnet[0]); -#elif ARDUINO > 106 || TEENSYDUINO > 121 - W5100.setIPAddress(ip._address.bytes); - W5100.setGatewayIp(gateway._address.bytes); - W5100.setSubnetMask(subnet._address.bytes); -#else - W5100.setIPAddress(ip._address); - W5100.setGatewayIp(gateway._address); - W5100.setSubnetMask(subnet._address); -#endif + W5100.setIPAddress(ip.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); SPI.endTransaction(); _dnsServerAddress = dns; } diff --git a/trunk/Arduino/libraries/IRremote/Contributing.md b/trunk/Arduino/libraries/IRremote/Contributing.md index 7ebd5fe6..4424f809 100644 --- a/trunk/Arduino/libraries/IRremote/Contributing.md +++ b/trunk/Arduino/libraries/IRremote/Contributing.md @@ -10,12 +10,16 @@ If you want to contribute to this project: ## Guidelines The following are some guidelines to observe when creating discussions / PRs: -- Be friendly; it is important that we can all enjoy a safe space as we are all working on the same project and **it is okay for people to have different ideas**. -- Use reasonable titles; refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile:. -- Use the style; we use the original [C Style by Kerninghan / Ritchie](https://en.wikipedia.org/wiki/Indentation_style#K&R_style) in [variant: 1TBS (OTBS)](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)). - In short: 4 spaces indentation, no tabs, opening braces on the same line, braces are mandatory on all if/while/do, no hard line length limit. - To beautify your code, you may use the online formatter [here](https://www.freecodeformat.com/c-format.php). -- Cover **all** occurences of the problem / addition you address with your PR. Do not forget the documentation like it is done for existing code. Code changes without proper documentation will be rejected! +#### Be friendly +It is important that we can all enjoy a safe space as we are all working on the same project and **it is okay for people to have different ideas**. +#### Use reasonable titles +Refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile:. +#### Use the formatting style +We use the original [C Style by Kerninghan / Ritchie](https://en.wikipedia.org/wiki/Indentation_style#K&R_style) in [variant: 1TBS (OTBS)](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)).
+In short: 4 spaces indentation, no tabs, opening braces on the same line, braces are mandatory on all if/while/do, no hard line length limit.
+To beautify your code, you may use the online formatter [here](https://www.freecodeformat.com/c-format.php). +#### Cover **all** occurences of the problem / addition you address with your PR + Do not forget the documentation like it is done for existing code. Code changes without proper documentation will be rejected! ## Adding new protocols To add a new protocol is quite straightforward. Best is too look at the existing protocols to find a similar one and modify it.
@@ -25,7 +29,7 @@ The **durations** you receive are likely to be longer for marks and shorter for but this depends on the receiver circuit in use. Most protocols use multiples of one time-unit for marks and spaces like e.g. [NEC](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_NEC.hpp#L62). It's easy to be off-by-one with the last bit, since the last space is not recorded by IRremote. Try to make use of the template functions `decodePulseDistanceData()` and `sendPulseDistanceData()`. -If your protocol supports address and code fields, try to reflect this in your api like it is done in [`sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_NEC.hpp#L96) +If your protocol supports address and code fields, try to reflect this in your api like it is done in [`sendNEC(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aIsRepeat)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_NEC.hpp#L96) and [`decodeNEC()`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_NEC.hpp#L194).
### Integration diff --git a/trunk/Arduino/libraries/IRremote/Contributors.md b/trunk/Arduino/libraries/IRremote/Contributors.md index c1175fba..349ccec1 100644 --- a/trunk/Arduino/libraries/IRremote/Contributors.md +++ b/trunk/Arduino/libraries/IRremote/Contributors.md @@ -26,5 +26,10 @@ These are the active contributors of this project that you may contact if there - [Jim-2249](https://github.com/Jim-2249) - [pmalasp](https://github.com/pmalasp ) - [ElectronicsArchiver}(https://github.com/ElectronicsArchiver) improving documentation +- [Stephen Humphries](https://github.com/sjahu)Fix for: Prevent long delay caused by overflow when frame duration < repeat period #1028 +- [Daniel Wallner](https://github.com/danielwallner) Bang & Olufsen protocol. +- [slott](https://stackoverflow.com/users/11680056/sklott) Seeduino print(unsigned long long...) support. +- [Joe Ostrander](https://github.com/joeostrander) Added support for attiny1614. +- [Buzzerb](https://github.com/Buzzerb) Added Extended NEC protocol to TinyIR and making it more consistent. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/trunk/Arduino/libraries/IRremote/Doxyfile b/trunk/Arduino/libraries/IRremote/Doxyfile index e9122046..a879240e 100644 --- a/trunk/Arduino/libraries/IRremote/Doxyfile +++ b/trunk/Arduino/libraries/IRremote/Doxyfile @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = +OUTPUT_DIRECTORY = E:\WORKSPACE_ARDUINO\lib\Arduino-IRremote_gh-pages # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -307,7 +307,7 @@ OPTIMIZE_OUTPUT_SLICE = NO # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. -EXTENSION_MAPPING = ino=C++ cpp=C++ h=C++ +EXTENSION_MAPPING = ino=C++ cpp=C++ h=C++ hpp=C++ # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable @@ -815,7 +815,6 @@ WARN_LOGFILE = INPUT = src \ src/private \ - examples/MicroGirs \ . # This tag can be used to specify the character encoding of the source files @@ -843,7 +842,7 @@ INPUT_ENCODING = UTF-8 # C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, # *.vhdl, *.ucf, *.qsf and *.ice. -FILE_PATTERNS = *.ino *.cpp *.c *.h *.md +FILE_PATTERNS = *.ino *.cpp *.c *.h *.hpp *.md # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -1064,7 +1063,7 @@ VERBATIM_HEADERS = YES # classes, structs, unions or interfaces. # The default value is: YES. -ALPHABETICAL_INDEX = YES +ALPHABETICAL_INDEX = NO # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. @@ -1096,8 +1095,6 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -# This name is selected to be able to easily publish with GitHub's gh-pages. - HTML_OUTPUT = docs # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each @@ -1457,7 +1454,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. diff --git a/trunk/Arduino/libraries/IRremote/README.md b/trunk/Arduino/libraries/IRremote/README.md index c312bc94..16b7eb64 100644 --- a/trunk/Arduino/libraries/IRremote/README.md +++ b/trunk/Arduino/libraries/IRremote/README.md @@ -4,12 +4,12 @@ A library enabling the sending & receiving of infra-red signals. [![Badge License: MIT](https://img.shields.io/badge/License-MIT-ac8b11.svg?style=for-the-badge&labelColor=yellow)](https://opensource.org/licenses/MIT) -     +     [![Badge Version](https://img.shields.io/github/v/release/Arduino-IRremote/Arduino-IRremote?include_prereleases&style=for-the-badge&color=33660e&labelColor=428813&logoColor=white&logo=DocuSign)](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/latest) -     +     [![Badge Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremote/Arduino-IRremote/latest?style=for-the-badge&color=004463&labelColor=00557f)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master) -     -[![Badge LibraryBuild](https://img.shields.io/github/workflow/status/Arduino-IRremote/Arduino-IRremote/LibraryBuild?style=for-the-badge&labelColor=752a61&color=551f47)](https://github.com/Arduino-IRremote/Arduino-IRremote/actions) +     +[![Badge LibraryBuild](https://img.shields.io/github/actions/workflow/status/Arduino-IRremote/Arduino-IRremote/LibraryBuild.yml?branch=master&style=for-the-badge&color=551f47&labelColor=752a61)](https://github.com/Arduino-IRremote/Arduino-IRremote/actions)

[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua) @@ -17,59 +17,70 @@ A library enabling the sending & receiving of infra-red signals. Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libraries/i-rremote). [![Button Install](https://img.shields.io/badge/Install-yellow?style=for-the-badge&logoColor=white&logo=GitBook)](https://www.ardu-badge.com/IRremote) -     +     [![Button API](https://img.shields.io/badge/API-1c8840?style=for-the-badge&logoColor=white&logo=OpenStreetMap)](https://arduino-irremote.github.io/Arduino-IRremote/classIRrecv.html) -     +     [![Button Changelog](https://img.shields.io/badge/Changelog-00557f?style=for-the-badge&logoColor=white&logo=AzureArtifacts)](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md) -     +     [![Button Contribute](https://img.shields.io/badge/Contribute-752a61?style=for-the-badge&logoColor=white&logo=GitHub)](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributing.md) +#### If you find this program useful, please give it a star. + +🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/Arduino-IRremote/Arduino-IRremote) + -# Overview -- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-ir-protocols) -- [Features](https://github.com/Arduino-IRremote/Arduino-IRremote#features) - * [New features with version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote#new-features-with-version-3x) -- [Converting your 2.x program to the 3.x version](https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-3x-version) - * [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote#staying-on-2x) - * [How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes) -- [Errors with using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote#errors-with-using-the-3x-versions-for-old-tutorials) -- [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote#why-hpp-instead-of-cpp) -- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote#using-the-new-hpp-files) -- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#receiving-ir-codes) - * [Data format](https://github.com/Arduino-IRremote/Arduino-IRremote#data-format) -- [Minimal NEC receiver](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-nec-receiver) -- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#sending-ir-codes) - + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote#list-of-public-ir-code-databases) -- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote#faq-and-hints) - * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote#problems-with-neopixels-fastled-etc) - * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote#does-not-workcompile-with-another-library) - * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote#multiple-ir-receiver) - * [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote#increase-strength-of-sent-output-signal) - * [Minimal CPU frequency](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-cpu-frequency) -- [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#handling-unknown-protocols) - * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote#disclaimer) - * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolpulse_distance) - * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown) - * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-deal-with-protocols-not-supported-by-irremote) -- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library) -- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote#wokwi-online-examples) -- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote#issues-and-discussions) -- [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library) - + [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#changing-include-h-files-with-arduino-ide) - + [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#modifying-compile-options--macros-with-sloeber-ide) -- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-boards) -- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage) - * [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite) - * [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#hardware-pwm-signal-generation-for-sending) - * [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#why-do-we-use-30-duty-cycle-for-sending) -- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote#how-we-decode-signals) -- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote#nec-encoding-diagrams) -- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries) -- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote#useful-links) +# Table of content +- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols) +- [Features](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#features) + * [New features with version 4.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-with-version-4x) + * [New features with version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-with-version-3x) +- [Converting your 2.x program to the 4.x version](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#converting-your-2x-program-to-the-4x-version) + * [How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes) +- [Errors with using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#errors-with-using-the-3x-versions-for-old-tutorials) + * [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#staying-on-2x) +- [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-hpp-instead-of-cpp) +- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-hpp-files) +- [IRReceiver pinouts](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irreceiver-pinouts) +- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-ir-codes) + * [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#decodedirdata-structure) + * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ambiguous-protocols) + * [Unknown protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#unknown-protocol) +- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes) + * [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#send-pin) + + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases) +- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) +- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol) +- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) + * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc) + * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library) + * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver) + * [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#increase-strength-of-sent-output-signal) + * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-cpu-clock-frequency) + * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#bang--olufsen-protocol) +- [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#handling-unknown-protocols) + * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#disclaimer) + * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolpulse_distance) + * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolunknown) + * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-deal-with-protocols-not-supported-by-irremote) +- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library) +- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#wokwi-online-examples) +- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#issues-and-discussions) +- [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library) + + [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#changing-include-h-files-with-arduino-ide) + + [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide) +- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-boards) +- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage) + * [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite) + * [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#hardware-pwm-signal-generation-for-sending) + * [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-do-we-use-30-duty-cycle-for-sending) +- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-we-decode-signals) +- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#nec-encoding-diagrams) +- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries) +- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#useful-links) - [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md) -- [License](https://github.com/Arduino-IRremote/Arduino-IRremote#license) -- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote#copyright) +- [License](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#license) +- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#copyright)
@@ -78,9 +89,9 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr ` JVC `     ` LG `     ` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` -` Universal Distance `     ` Hash `     ` Pronto ` - -` BoseWave `     ` Lego `     ` Whynter `     ` MagiQuest ` +` Universal Pulse Distance `     ` Universal Pulse Width `     ` Hash `     ` Pronto ` + +` BoseWave `     ` Bang & Olufsen `     ` Lego `     ` FAST `     ` Whynter `     ` MagiQuest ` Protocols can be switched off and on by defining macros before the line `#include ` like [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33): @@ -96,8 +107,22 @@ Protocols can be switched off and on by defining macros before the line `#includ - Actively maintained. - Allows receiving and sending of **raw timing data**. +## New features with version 4.x +- **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `IrSender.begin(DISABLE_LED_FEEDBACK, 0)` instead. +- New universal **Pulse Distance / Pulse Width decoder** added, which covers many previous unknown protocols. +- Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`. +- RawData type is now 64 bit for 32 bit platforms and therefore `decodedIRData.decodedRawData` can contain complete frame information for more protocols than with 32 bit as before. +- **Callback** after receiving a command - It calls your code as soon as a message was received. +- Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols. +- New FAST protocol. +- Automatic printout of the **corresponding send function** with printIRSendUsage(). + +#### Converting your 3.x program to the 4.x version +- You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder). +- The parameter `bool hasStopBit` is not longer required and removed e.g. for function `sendPulseDistanceWidth()`. + ## New features with version 3.x -- **Any pin** can be used for sending / receiving. +- **Any pin** can be used for receiving and if `SEND_PWM_BY_TIMER` is not defined also for sending. - Feedback LED can be activated for sending / receiving. - An 8/16 bit ****command** value as well as an 16 bit **address** and a protocol number is provided for decoding (instead of the old 32 bit value). - Protocol values comply to **protocol standards**.
@@ -109,13 +134,13 @@ Protocols can be switched off and on by defining macros before the line `#includ - Allows for the generation of non PWM signal to just **simulate an active low receiver signal** for direct connect to existent receiving devices without using IR. - Easy protocol configuration, **directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57)**.
Reduces memory footprint and decreases decoding time. -- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-nec-receiver), which **does not require any timer resource**. - -[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries). +- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-nec-receiver), which **does not require any timer resource**. + +[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries).
-# Converting your 2.x program to the 3.x version +# Converting your 2.x program to the 4.x version Starting with the 3.1 version, **the generation of PWM for sending is done by software**, thus saving the hardware timer and **enabling arbitrary output pins for sending**.
If you use an (old) Arduino core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h, if you get false error messages regarding begin() during compilation. @@ -124,18 +149,23 @@ If you use an (old) Arduino core that does not use the `-flto` flag for compile, - Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar. - Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106) or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().
-For sending, call `IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK);` or `IrSender.begin(IR_SEND_PIN, DISABLE_LED_FEEDBACK);` in setup(). +For sending, call `IrSender.begin();` in setup().
+If IR_SEND_PIN is not defined (before the line `#include `) you must use e.g. `IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);` - Old `decode(decode_results *aResults)` function is replaced by simple `decode()`. So if you have a statement `if(irrecv.decode(&results))` replace it with `if (IrReceiver.decode())`. - The decoded result is now in in `IrReceiver.decodedIRData` and not in `results` any more, therefore replace any occurrences of `results.value` and `results.decode_type` (and similar) to `IrReceiver.decodedIRData.decodedRawData` and `IrReceiver.decodedIRData.protocol`. -- Overflow, Repeat and other flags are now in [`IrReceiver.receivedIRData.flags`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L164-L187). +- Overflow, Repeat and other flags are now in [`IrReceiver.receivedIRData.flags`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L90-L101). - Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`. +- The 5 protocols **NEC, Panasonic, Sony, Samsung and JVC** have been converted to LSB first. Send functions for sending old MSB data for **NEC** and **JVC** were renamed to `sendNECMSB`, and `sendJVCMSB()`. The old `sendSAMSUNG()` and `sendSony()` MSB functions are still available. The old MSB version of `sendPanasonic()` function was deleted, since it had bugs nobody recognized.
+For converting MSB codes to LSB see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes). + ### Example -#### 2.x program: +#### Old 2.x program: ```c++ #include +#define RECV_PIN 2 IRrecv irrecv(RECV_PIN); decode_results results; @@ -156,10 +186,11 @@ void loop() { } ``` -#### 3.x program: +#### New 4.x program: ```c++ #include +#define IR_RECEIVE_PIN 2 void setup() { @@ -169,28 +200,15 @@ void setup() void loop() { if (IrReceiver.decode()) { - Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); - IrReceiver.printIRResultShort(&Serial); // optional use new print version + Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data + IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line + IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data ... IrReceiver.resume(); // Enable receiving of the next value } ... } ``` -## Staying on 2.x -Consider using the [original 2.4 release form 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0) -or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
-It may be sufficient and deals flawlessly with 32 bit IR codes.
-If this doesn't fit your case, be assured that 3.x is at least trying to be backwards compatible, so your old examples should still work fine. - -### Drawbacks -- Only the following decoders are available:
- ` NEC `     ` Denon `     ` Panasonic `     ` JVC `     ` LG `
- ` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` -- The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`. -- The old functions `sendNEC()` and `sendJVC()` are renamed to `sendNECMSB()` and `sendJVCMSB()`.
- Use them to send your **old MSB-first 32 bit IR data codes**. -- No decoding by a (constant) 8/16 bit address and an 8 bit command. ## How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes For the new decoders for **NEC, Panasonic, Sony, Samsung and JVC**, the result `IrReceiver.decodedIRData.decodedRawData` is now **LSB-first**, as the definition of these protocols suggests!
@@ -210,12 +228,30 @@ Example: `0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.
`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`.
If you **read the first binary sequence backwards** (right to left), you get the second sequence. +You may use `bitreverseOneByte()` or `bitreverse32Bit()` for this.
-# Errors with using the 3.x versions for old tutorials +# Errors with using the 4.x versions for old tutorials If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`, just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
-Most likely your code will run and you will not miss the new features... +Most likely your code will run and you will not miss the new features. + +
+ +## Staying on 2.x +Consider using the [original 2.4 release form 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0) +or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
+It may be sufficient and deals flawlessly with 32 bit IR codes.
+If this doesn't fit your case, be assured that 3.x is at least trying to be backwards compatible, so your old examples should still work fine. + +### Drawbacks +- Only the following decoders are available:
+ ` NEC `     ` Denon `     ` Panasonic `     ` JVC `     ` LG `
+ ` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` +- The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`. +- The old functions `sendNEC()` and `sendJVC()` are renamed to `sendNECMSB()` and `sendJVCMSB()`.
+ Use them to send your **old MSB-first 32 bit IR data codes**. +- No decoding by a (constant) 8/16 bit address and an 8 bit command.
@@ -228,7 +264,7 @@ And now our problem with Arduino is:
IDE's like [Sloeber](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-sloeber-ide) or [PlatformIO](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project. They add these options at each compiler call e.g. `-DTRACE`. -But Arduino lacks this feature. +But Arduino lacks this feature. So the **workaround** is not to compile all sources separately, but to concatenate them to one huge source file by including them in your source.
This is done by e.g. `#include "IRremote.hpp"`. @@ -249,7 +285,7 @@ In **all other files** you must use the following, to **prevent `multiple defini #include ``` -**Ensure that all macros in your main program are defined before any** `#include `.
+**Ensure that all macros in your main program are defined before any** `#include `.
The following macros will definitely be overridden with default values otherwise: - `RAW_BUFFER_LENGTH` - `IR_SEND_PIN` @@ -257,14 +293,16 @@ The following macros will definitely be overridden with default values otherwise
-# Receiving IR codes -Check for **received data** with:
-`if (IrReceiver.decode()) {}`
-This also decodes the received data. +# IRReceiver pinouts +![IRReceiver Pinout](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IRReceiverPinout.jpg) -## Data format +# Receiving IR codes +Check for a **completly received IR frame** with:
+`if (IrReceiver.decode()) {}`
+This also decodes the received data.
After successful decoding, the IR data is contained in the IRData structure, available as `IrReceiver.decodedIRData`. +## decodedIRData structure ```c++ struct IRData { decode_type_t protocol; // UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ... @@ -272,16 +310,29 @@ struct IRData { uint16_t command; // Decoded command uint16_t extra; // Used for Kaseikyo unknown vendor ID. Ticks used for decoding Distance protocol. uint16_t numberOfBits; // Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible. - uint8_t flags; // See IRDATA_FLAGS_* definitions - uint32_t decodedRawData; // Up to 32 bit decoded raw data, used for sendRaw functions. + uint8_t flags; // IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions + IRRawDataType decodedRawData; // Up to 32 (64 bit for 32 bit CPU architectures) bit decoded raw data, used for sendRaw functions. uint32_t decodedRawDataArray[RAW_DATA_ARRAY_SIZE]; // 32 bit decoded raw data, to be used for send function. irparams_struct *rawDataPtr; // Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR. }; ``` +#### Flags +This is the [list of flags](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L88) contained in the flags field.
+Check it with e.g. `if(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)`. + +| Flag name | Description | +|:---|----| +| IRDATA_FLAGS_IS_REPEAT | The gap between the preceding frame is as smaller than the maximum gap expected for a repeat. !!!We do not check for changed command or address, because it is almost not possible to press 2 different buttons on the remote within around 100 ms!!! +| IRDATA_FLAGS_IS_AUTO_REPEAT | The current repeat frame is a repeat, that is always sent after a regular frame and cannot be avoided. Only specified for protocols DENON, and LEGO. | +| IRDATA_FLAGS_PARITY_FAILED | The current (autorepeat) frame violated parity check. | +| IRDATA_FLAGS_TOGGLE_BIT | Is set if RC5 or RC6 toggle bit is set. | +| IRDATA_FLAGS_EXTRA_INFO | There is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID, or in decodedRawDataArray). | +| IRDATA_FLAGS_WAS_OVERFLOW | irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag. | +| IRDATA_FLAGS_IS_MSB_FIRST | This value is mainly determined by the (known) protocol. | #### To access the **RAW data**, use: ```c++ -uint32_t myRawdata= IrReceiver.decodedIRData.decodedRawData; +auto myRawdata= IrReceiver.decodedIRData.decodedRawData; ``` The definitions for the `IrReceiver.decodedIRData.flags` are described [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L128-L140). @@ -295,35 +346,170 @@ IrReceiver.printIRResultShort(&Serial); ```c++ IrReceiver.printIRResultRawFormatted(&Serial, true);` ``` +The raw data depends on the internal state of the Arduino timer in relation to the received signal and might therefore be slightly different each time. (resolution problem). The decoded values are the interpreted ones which are tolerant to such slight differences! -
+#### Print how to send the received data: +```c++ +IrReceiver.printIRSendUsage(&Serial); +``` -# Minimal NEC receiver -For applications only requiring NEC protocol, there is a special receiver included,
-which has very **small code size of 500 bytes and does NOT require any timer**. +## Ambiguous protocols +### NEC, Extended NEC, ONKYO +The **NEC protocol** is defined as 8 bit address and 8 bit command. But the physical address and data fields are each 16 bit wide. +The additional 8 bits are used to send the inverted address or command for parity checking.
+The **extended NEC protocol** uses the additional 8 parity bit of address for a 16 bit address, thus disabling the parity check for address.
+The **ONKYO protocol** in turn uses the additional 8 parity bit of address and command for a 16 bit address and command. -Check out the [MinimalReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#minimalreceiver) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote#irdispatcherdemo) examples. +The decoder reduces the 16 bit values to 8 bit ones if the parity is correct. +If the parity is not correct, it assumes no parity error, but takes the values as 16 bit values without parity assuming extended NEC or extended NEC protocol protocol. + +But now we have a problem when we want to receive e.g. the **16 bit** address 0x00FF or 0x32CD! +The decoder interprets this as a NEC 8 bit address 0x00 / 0x32 with correct parity of 0xFF / 0xCD and reduces it to 0x00 / 0x32. + +One way to handle this, is to force the library to **always** use the ONKYO protocol interpretation by using `#define DECODE_ONKYO`. +Another way is to check if `IrReceiver.decodedIRData.protocol` is NEC and not ONKYO and to revert the parity reducing manually. + +### NEC, NEC2 +On a long press, the **NEC protocol** does not repeat its frame, it sends a special short repeat frame. +This enables an easy distinction between long presses and repeated presses and saves a bit of battery energy. +This behavior is quite unique for NEC and its derived protocols like LG and Samsung. + +But of course there are also remote control systems, that uses the NEC protocol but only repeat the first frame when a long press is made instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.
+But be careful, the NEC2 protocol can only be detected by the NEC library decoder **after** the first frame and if you do a long press! + +### Samsung, SamsungLG +On a long press, the **SamsungLG protocol** does not repeat its frame, it sends a special short repeat frame. + +## Unknown protocol +If your protocol seems not to be supported by this library, you may try the [IRMP library](https://github.com/IRMP-org/IRMP).
# Sending IR codes -Please do not use the old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957A8,2)`, -even if this functions are used in a lot of **(old)** tutorials. They are only kept for backward compatibility and unsupported as well as error prone.
-**It is recommended** to use the **new structured functions** with address and command parameters like e.g. `IrSender.sendNEC(0xA8, 0x19, 2)`. -Especially if you are able to receive these remote codes and get the address and command values. -You will discover that **the address is a constant** and the commands sometimes are sensibly grouped. +If you have a device at hand which can generate the IR codes you want to work with (aka IR remote), **it is recommended** to receive the codes with the [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino), which will tell you on the serial output how to send them. + +``` +Protocol=LG Address=0x2 Command=0x3434 Raw-Data=0x23434E 28 bits MSB first +Send with: IrSender.sendLG(0x2, 0x3434, ); +``` +You will discover that **the address is a constant** and the commands sometimes are sensibly grouped.
+If you are uncertain about the numbers of repeats to use for sending, **3** is a good starting point. If this works, you can check lower values afterwards. + +If you have enabled `DECODE_DISTANCE_WIDTH`, the code printed by `printIRSendUsage()` **differs between 8 and 32 bit platforms**, so it is best to run the receiving program on the same platform as the sending program. + +The codes found in the [irdb database](https://github.com/probonopd/irdb/tree/master/codes) specify a **device**, a **subdevice** and a **function**. Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function* is the **command parameter** for the **new structured functions** with address, command and repeat-count parameters like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.
+An **exact mapping** can be found in the [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols). "D" and "S" denotes device and subdevice and "F" denotes the function. + +**All sending functions support the sending of repeats** if sensible. +Repeat frames are sent at a fixed period determined by the protocol. e.g. 110 ms from start to start for NEC.
+Keep in mind, that **there is no delay after the last sent mark**. +If you handle the sending of repeat frames by your own, you must insert sensible delays before the repeat frames to enable correct decoding. + +The old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957A8,2)` are kept for backward compatibility to **(old)** tutorials and unsupported as well as error prone. + +## Send pin +Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active. +If `IR_SEND_PIN` is specified (as c macro), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this `IR_SEND_PIN` macro. Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library). ### List of public IR code databases http://www.harctoolbox.org/IR-resources.html +## Flipper Zero +[Flipper IRDB Database](https://github.com/Lucaslhm/Flipper-IRDB) + +| [Flipper decoding](https://github.com/flipperdevices/flipperzero-firmware/tree/release/lib/infrared/encoder_decoder) | [IRremote decoding](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src) | +|-|-| +| Samsung32 | Samsung | +| NEC | NEC | +| NECext | ONKYO | +| [\\\\\\\\\](https://github.com/flipperdevices/flipperzero-firmware/blob/027ea9ea36da137144548295c016d99255af53c3/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c#L26)
and ID is MSB of address.
address: 8A 02 20 00
command: 56 03 00 00
-> **IRremote:**
Address 0x6A8, sendPanasonic (for 02 20) and Command 0x35 | \\\\\\\ | +
+ +# Tiny NEC receiver and sender +For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included,
+which has very **small code size of 500 bytes and does NOT require any timer**. + +Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irdispatcherdemo) examples.
+Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRremote.hpp`. + +### TinyIRReceiver usage +```c++ +//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO +#include "TinyIRReceiver.hpp" + +void setup() { + initPCIInterruptForTinyReceiver(); // Enables the interrupt generation on change of IR input signal +} + +void loop() { + if (TinyIRReceiverData.justWritten) { + TinyIRReceiverData.justWritten = false; + printTinyReceiverResultMinimal(&Serial); + } +} +``` + +### TinyIRSender usage +```c++ +#include "TinyIRSender.hpp" + +void setup() { + sendNEC(3, 0, 11, 2); // Send address 0 and command 11 on pin 3 with 2 repeats. +} + +void loop() {} +``` + +Another tiny receiver and sender **supporting more protocols** can be found [here](https://github.com/LuisMiCa/IRsmallDecoder). + +# The FAST protocol +The FAST protocol is a proprietary modified JVC protocol **without address, with parity and with a shorter header**. +It is meant to have a quick response to the event which sent the protocol frame on another board. +FAST takes **21 ms for sending** and is sent at a **50 ms period**. +It has full 8 bit parity for error detection. + +### FAST protocol characteristics: +- Bit timing is like JVC +- The header is shorter, 3156 µs vs. 12500 µs +- No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. +- Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. + +### Sending FAST protocol with IRremote +```c++ +#define IR_SEND_PIN 3 +#include + +void setup() { + sendFAST(11, 2); // Send command 11 on pin 3 with 2 repeats. +} + +void loop() {} +``` + +### Sending FAST protocol with TinyIRSender +```c++ +#define USE_FAST_PROTOCOL // Use FAST protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command +#include "TinyIRSender.hpp" + +void setup() { + sendFAST(3, 11, 2); // Send command 11 on pin 3 with 2 repeats. +} + +void loop() {} +``` +
+ +The FAST protocol can be received by IRremote and TinyIRReceiver. + # FAQ and hints ## Problems with Neopixels, FastLed etc. -IRremote will not work right when you use **Neopixels** (aka WS2811/WS2812/WS2812B) or other libraries blocking interrupts for a longer time (> 50 s).
-Whether you use the Adafruit Neopixel lib, or FastLED, interrupts get disabled on many lower end CPUs like the basic Arduinos for longer than 50 s. -In turn, this stops the IR interrupt handler from running when it needs to. +IRremote will not work right when you use **Neopixels** (aka WS2811/WS2812/WS2812B) or other libraries blocking interrupts for a longer time (> 50 µs).
+Whether you use the Adafruit Neopixel lib, or FastLED, interrupts get disabled on many lower end CPUs like the basic Arduinos for longer than 50 µs. +In turn, this stops the IR interrupt handler from running when it needs to. See also this [video](https://www.youtube.com/watch?v=62-nEJtm070). One **workaround** is to wait for the IR receiver to be idle before you send the Neopixel data with `if (IrReceiver.isIdle()) { strip.show();}`.
This **prevents at least breaking a running IR transmission** and -depending of the update rate of the Neopixel- may work quite well.
@@ -332,26 +518,35 @@ There are some other solutions to this on more powerful processors, ## Does not work/compile with another library **Another library is only working/compiling** if you deactivate the line `IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);`.
-This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage). +This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). ## Multiple IR receivers -You can use **multiple IR receiver** by just connecting the output pins of several IR receivers together. +IRreceiver consists of one timer triggered function reading the digital IR signal value from one pin every 50 µs.
+So **multiple IR receivers** can only be used by connecting the output pins of several IR receivers together. The IR receivers use an NPN transistor as output device with just a 30k resistor to VCC. -This is almost "open collector" and allows connecting of several output pins to one Arduino input pin. +This is almost "open collector" and allows connecting of several output pins to one Arduino input pin.
+But keep in mind, that any weak / disturbed signal from one of the receivers will in turn also disturb a good signal from another one. ## Increase strength of sent output signal **The best way to increase the IR power for free** is to use 2 or 3 IR diodes in series. One diode requires 1.2 volt at 20 mA or 1.5 volt at 100 mA so you can supply up to 3 diodes with a 5 volt output.
-To power **2 diodes** with 1.2 volt and 20 mA and a 5 volt supply, set the resistor to: (5 V - 2.4 V) -> 2.6 V / 20 mA = **130 Ω**.
+To power **2 diodes** with 1.2 V and 20 mA and a 5 V supply, set the resistor to: (5 V - 2.4 V) -> 2.6 V / 20 mA = **130 Ω**.
For **3 diodes** it requires 1.4 V / 20 mA = **70 Ω**.
The actual current might be lower since of **loss at the AVR pin**. E.g. 0.3 V at 20 mA.
If you do not require more current than 20 mA, there is no need to use an external transistor (at least for AVR chips). On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :grinning:. -## Minimal CPU frequency -For receiving, the **minimal CPU frequency is 4 MHz**, since the 50 s timer ISR takes around 12 s on a 16 MHz ATmega.
+## Minimal CPU clock frequency +For receiving, the **minimal CPU clock frequency is 4 MHz**, since the 50 µs timer ISR (Interrupt Service Routine) takes around 12 µs on a 16 MHz ATmega.
+The TinyReceiver, which reqires no polling, runs with 1 MHz.
For sending, the **default software generated PWM has problems on AVR running with 8 MHz**. The PWM frequency is around 30 instead of 38 kHz and RC6 is not reliable. You can switch to timer PWM generation by `#define SEND_PWM_BY_TIMER`. +## Bang & Olufsen protocol +The Bang & Olufsen protocol decoder is not enabled by default, i.e if no protocol is enabled explicitly by #define `DECODE_`. It must always be enabled explicitly by `#define DECODE_BEO`. +This is because it has an **IR transmit frequency of 455 kHz** and therefore requires a different receiver hardware (TSOP7000).
+And because **generating a 455 kHz PWM signal is currently only implemented for `SEND_PWM_BY_TIMER`**, sending only works if `SEND_PWM_BY_TIMER` or `USE_NO_SEND_PWM` is defined.
+For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_BangOlufsen.hpp#L44). + # Handling unknown Protocols ## Disclaimer **This library was designed to fit inside MCUs with relatively low levels of resources and was intended to work as a library together with other applications which also require some resources of the MCU to operate.** @@ -381,11 +576,11 @@ If this does not suit you for further research, you can change it [here](https:/ ## Protocol=UNKNOWN If you see something like `Protocol=UNKNOWN Hash=0x13BD886C 35 bits received` as output of e.g. the ReceiveDemo example, you either have a problem with decoding a protocol, or an unsupported protocol. -- If you have an **odd number of bits** received, it is likely, that your receiver circuit has problems. Maybe because the IR signal is too weak. -- If you see timings like `+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550` then one 450 s space was split into two 150 and 100 s spaces with a spike / error signal of 200 s between. Maybe because of a defective receiver or a weak signal in conjunction with another light emitting source nearby. +- If you have an **odd number of bits** received, your receiver circuit probably has problems. Maybe because the IR signal is too weak. +- If you see timings like `+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550` then one 450 µs space was split into two 150 and 100 µs spaces with a spike / error signal of 200 µs between. Maybe because of a defective receiver or a weak signal in conjunction with another light emitting source nearby. - If you see timings like `+ 500,- 550 + 450,- 550 + 500,- 500 + 500,-1550`, then marks are generally shorter than spaces and therefore `MARK_EXCESS_MICROS` (specified in your ino file) should be **negative** to compensate for this at decoding. - If you see `Protocol=UNKNOWN Hash=0x0 1 bits received` it may be that the space after the initial mark is longer than [`RECORD_GAP_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.h#L124). - This was observed for some LG air conditioner protocols. Try again with a line e.g. `#define RECORD_GAP_MICROS 12000` before the line `#include ` in your ino file. + This was observed for some LG air conditioner protocols. Try again with a line e.g. `#define RECORD_GAP_MICROS 12000` before the line `#include ` in your .ino file. - To see more info supporting you to find the reason for your UNKNOWN protocol, you must enable the line `//#define DEBUG` in IRremoteInt.h. ## How to deal with protocols not supported by IRremote @@ -404,42 +599,55 @@ If you do not know which protocol your IR transmitter uses, you have several cho
# Examples for this library -In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's. +The examples are available at File > Examples > Examples from Custom Libraries / IRremote.
+ In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's. #### SimpleReceiver + SimpleSender -This examples are a good starting point. +The **[SimpleReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino)** and **[SimpleSender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/SimpleSender.ino)** examples are a good starting point. A simple example can be tested online with [WOKWI](https://wokwi.com/projects/338611596994544210). -#### ReceiveDemo -Receives all protocols and **generates a beep with the Arduino tone() function** on each packet received. By connecting pin 5 to ground, you can see the raw values for each packet. **Example how to use IRremote and tone() together**. +#### TinyReceiver + TinySender +If **code size** or **timer usage** matters, look at these examples.
+The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library +which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**. +They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
+TinyReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075). -#### AllProtocols -Like ReceiveDemo but with 1604 LCD output and without tone(). +The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.
+It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example. It has options to send using Extended NEC, ONKYO and FAST protocols. +Saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, which does the same, but uses the IRRemote library (and is therefore much more flexible). + +#### SmallReceiver +If the protocol is not NEC and code size matters, look at this [example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SmallReceiver/SmallReceiver.ino).
+ +#### ReceiveDemo + AllProtocolsOnLCD +[ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino) receives all protocols and **generates a beep with the Arduino tone() function** on each packet received.
+Long press of one IR button (receiving of multiple repeats for one command) is detected.
+[AllProtocolsOnLCD](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino) additionally **displays the short result on a 1602 LCD**. The LCD can be connected parallel or serial (I2C).
+By connecting debug pin to ground, you can force printing of the raw values for each frame. The pin number of the debug pin is printed during setup, because it depends on board and LCD connection type.
+This example also serves as an **example how to use IRremote and tone() together**. #### ReceiveDump -Receives all protocols and dumps the received signal in different flavors. Since the printing takes so much time, repeat signals may be skipped or interpreted as UNKNOWN. +Receives all protocols and dumps the received signal in different flavors including Pronto format. Since the printing takes much time, repeat signals may be skipped or interpreted as UNKNOWN. #### SendDemo Sends all available protocols at least once. -#### SendAndReceive + UnitTest -ReceiveDemo + SendDemo in one program. **Receiving while sending**. +#### SendAndReceive +Demonstrates **receiving while sending**. #### ReceiveAndSend -Record and **play back last received IR signal** at button press. +Record and **play back last received IR signal** at button press. IR frames of known protocols are sent by the approriate protocol encoder. `UNKNOWN` protocol frames are stored as raw data and sent with `sendRaw()`. -### ReceiveOneAndSendMultiple +#### ReceiveAndSendDistanceWidth +Try to decode each IR frame with the *universal* **DistanceWidth decoder**, store the data and send it on button press with `sendPulseDistanceWidthFromArray()`.
+Storing data for distance width protocol requires 17 bytes. +The ReceiveAndSend example requires 16 bytes for known protocol data and 37 bytes for raw data of e.g.NEC protocol. + +#### ReceiveOneAndSendMultiple Serves as a IR **remote macro expander**. Receives Samsung32 protocol and on receiving a specified input frame, it sends multiple Samsung32 frames with appropriate delays in between. This serves as a **Netflix-key emulation** for my old Samsung H5273 TV. -#### SmallReceiver -If **code size** matters, look at these example.
- -#### MinimalReceiver -The MinimalReceiver example uses the **TinyReceiver** library which can **only receive NEC codes, but does not require any timer**.
-MinimalReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075). -Click on the receiver while simulation is running to specify individual IR codes. - #### IRDispatcherDemo Framework for **calling different functions of your program** for different IR codes. @@ -447,26 +655,35 @@ Framework for **calling different functions of your program** for different IR c **Control a relay** (connected to an output pin) with your remote. #### IRremoteExtensionTest -Example for a user defined class, which itself uses the IRrecv class from IRremote. +[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino) for a user defined class, which itself uses the IRrecv class from IRremote. #### SendLGAirConditionerDemo -Example for sending LG air conditioner IR codes controlled by Serial input.
+[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino) for sending LG air conditioner IR codes controlled by Serial input.
By just using the function `bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter)` you can control the air conditioner by any other command source.
The file *acLG.h* contains the command documentation of the LG air conditioner IR protocol. Based on reverse engineering of the LG AKB73315611 remote. ![LG AKB73315611 remote](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/LG_AKB73315611.jpg)
IReceiverTimingAnalysis can be tested online with [WOKWI](https://wokwi.com/projects/299033930562011656) Click on the receiver while simulation is running to specify individual IR codes. +#### ReceiveAndSendHob2Hood +[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/ReceiveAndSendHobToHood.ino) for receiving and sending AEG / Elektrolux Hob2Hood protocol.
+ #### ReceiverTimingAnalysis -This example analyzes the signal delivered by your IR receiver module. +This [example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino) analyzes the signal delivered by your IR receiver module. Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.
It also computes the `MARK_EXCESS_MICROS` value, which is the extension of the mark (pulse) duration introduced by the IR receiver module.
It can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299033930562011656). Click on the receiver while simulation is running to specify individual NEC IR codes. +#### UnitTest +ReceiveDemo + SendDemo in one program. Demonstrates **receiving while sending**. +Here you see the delay of the receiver output (blue) from the IR diode input (yellow). +![Delay](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_UnitTest_delay.bmp) + # WOKWI online examples -- [Simple receiver](https://wokwi.com/projects/338611596994544210). -- [MinimalReceiver](https://wokwi.com/arduino/projects/339264565653013075) +- [Simple receiver](https://wokwi.com/projects/338611596994544210) +- [Simple toggle by IR key 5](https://wokwi.com/projects/338611596994544210) +- [TinyReceiver](https://wokwi.com/arduino/projects/339264565653013075) - [ReceiverTimingAnalysis](https://wokwi.com/projects/299033930562011656) - [Receiver with LCD output and switch statement](https://wokwi.com/projects/298934082074575369) @@ -485,33 +702,46 @@ These macros must be defined in your program **before** the line `#include ` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) | +| `DECODE_STRICT_CHECKS` | disabled | Check for additional required characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. | +| `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. | | `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. | -| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 s.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | +| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | | `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | -| `IR_SEND_PIN` | disabled | If specified (as constant), reduces program size and improves send timing for AVR. If you want to use a runtime variable send pin e.g. with `setSendPin(uint8_t aSendPinNumber)` , you must disable this macro. | -| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use (restricted) hardware PWM. Enabled for ESP32 and RP2040 in all examples. | -| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Overrides `SEND_PWM_BY_TIMER` definition. | +| `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | +| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the advantage of more exact PWM generation, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the disadvantage of using a hardware timer, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). | +| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | | `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | -| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BOSEWAVE, WHYNTER and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. | +| `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. | +| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. | | `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. | -| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR processing time. | -| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 s at 38 kHz. | +| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. | +| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. | | `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING` | 25 | Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. | | `DEBUG` | disabled | Enables lots of lovely debug output. | | `IR_USE_AVR_TIMER*` | | Selection of timer to be used for generating IR receiving sample interval. | These next macros for **TinyIRReceiver** must be defined in your program before the line `#include ` to take effect. | Name | Default value | Description | -|:---|---:|----| -| `IR_INPUT_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. | +|-|-:|-| +| `IR_RECEIVE_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. | | `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. | | `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED function. Saves 14 bytes program memory. | -| `DISABLE_NEC_SPECIAL_REPEAT_SUPPORT` | disabled | Disables the detection of full NEC frame repeats. Saves 40 bytes program memory. | +| `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. | +| `USE_EXTENDED_NEC_PROTOCOL` | disabled | Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | +| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | +| `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. | +| `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. | +| `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the fixed function `void handleReceivedTinyIRData()` each time a frame or repeat is received. | + +The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect. +| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. | +| `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. | +| `BUZZER_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. | ### Changing include (*.h) files with Arduino IDE First, use *Sketch > Show Sketch Folder (Ctrl+K)*.
@@ -532,9 +762,12 @@ If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easi # Supported Boards **Issues and discussions with the content "Is it possible to use this library with the ATTinyXYZ? / board XYZ" without any reasonable explanations will be immediately closed without further notice.**

-ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the pro board. +Digispark boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the Digispark Pro board.
+ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore). + - Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc. -- Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / Teensy-LC - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries); Credits: PaulStoffregen (Teensy Team) +- Arduino Uno R4, but not yet tested, because of lack of a R4 board. **Sending does not work** on the `arduino:renesas_uno:unor4wifi`. +- Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / 3.2 / Teensy-LC - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries); Credits: PaulStoffregen (Teensy Team) - Sanguino - ATmega8, 48, 88, 168, 328 - ATmega8535, 16, 32, 164, 324, 644, 1284, @@ -543,66 +776,73 @@ ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](ht - ATtiny3217 (Tiny Core 32 Dev Board) - ATtiny84, 85, 167 (Digispark + Digispark Pro) - SAMD21 (Zero, MKR*, **but not SAMD51 and not DUE, the latter is SAM architecture**) -- ESP32 (ESP32 C3 since board package 2.0.2 from Espressif) -- ESP8266 [This fork](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md) +- ESP8266 +- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) **not for ESP32 core version > 3.0.0** - Sparkfun Pro Micro - Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE - BluePill with STM32 - RP2040 based boards (Raspberry Pi Pico, Nano RP2040 Connect etc.) +For ESP8266/ESP32, [this library](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md) + We are open to suggestions for adding support to new boards, however we highly recommend you contact your supplier first and ask them to provide support from their side.
If you can provide **examples of using a periodic timer for interrupts** for the new board, and the board name for selection in the Arduino IDE, then you have way better chances to get your board supported by IRremote.
# Timer and pin usage -The **receiver sample interval of 50 s is generated by a timer**. On many boards this must be a hardware timer. On some boards where a software timer is available, the software timer is used.
-Every pin can be used for receiving. +The **receiver sample interval of 50 µs is generated by a timer**. On many boards this must be a hardware timer. On some boards where a software timer is available, the software timer is used. -The MinimalReceiver example uses the **TinyReceiver** library, which can **only receive NEC codes, but does not require any timer**. +Every pin can be used for receiving.
+If software PWM is selected, which is default, every pin can also be used for sending. Sending with software PWM does not require a timer! + +The TinyReceiver example uses the **TinyReceiver** library, which can **only receive NEC codes, but does not require any timer** and runs even on a 1 MHz ATtiny85. + +The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). The selected timer can be adjusted here. -The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). It can be adjusted here.
**Be aware that the hardware timer used for receiving should not be used for analogWrite()!**.
-| Board/CPU | Receive
& PWM Timers| Hardware-PWM Pin | analogWrite()
pins occupied by timer | -|--------------------------------------------------------------------------|-------------------|---------------------|-----------------------| -| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore) | **1** | **6** | -| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **0**, 1 | **0**, 4 | **0**, 1 & 4 | -| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** | -| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **9** | **8 - 15** | -| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore) | **TCB0** | **PA05** | -| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore) | **TCA0**, TCD | % | -| [ATmega8](https://github.com/MCUdude/MiniCore) | **1** | **9** | +| Board/CPU | Receive
& send PWM Timer
Default timer is **bold** | Hardware-Send-PWM Pin | analogWrite()
pins occupied by timer | +|-|-|-|-| +| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x4.md) | **1** | **6** | | +| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x5.md) | **0**, 1 | **0**, 4 | **0**, 1 & 4 | +| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x8.md) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** | +| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x7.md) | **1** | **9**, 8 - 15 | **8 - 15** | +| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x04.md) | **TCB0** | **PA05** | +| [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x14.md) | **TCA0** | **PA3** | +| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x17.md) | **TCA0**, TCD | % | +| [ATmega8](https://github.com/MCUdude/MiniCore#supported-microcontrollers) | **1** | **9** | +| [ATmega1284](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2**, 3 | 13, 14, 6 | +| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2** | 13, **14** | +| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | **1** | **13** | +| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore#supported-microcontrollers) | **1** | **13** | +| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore#pinout ) | **1** | **13** | | ATmega168, **ATmega328** | 1, **2** | 9, **3** | 9 & 10, **3 & 11** | -| [ATmega1284](https://github.com/MCUdude/MightyCore) | 1, **2**, 3 | 13, 14, 6 | -| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore) | 1, **2** | 13, **14** | -| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore) | **1** | **13** | -| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore) | **1** | **13** | -| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore) | **1** | **13** | -| ATmega1280, ATmega2560 | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | -| ATmega4809 | **TCB0** | **A4** | -| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | -| Zero (SAMD) | **TC3** | \*, **9** | -| [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins | -| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | +| ATmega1280, **ATmega2560** | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | 5, 6, **9**, 11, 46 | +| ATmega4809 | **TCB0** | **A4** | | +| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | 5, **9**, 13 | +| Zero (SAMD) | **TC3** | \*, **9** | | +| [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins | | +| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | | | [Teensy 1.0](https://www.pjrc.com/teensy/pinout.html) | **1** | **17** | 15, 18 | | [Teensy 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, 3, **4_HS** | 9, **10**, 14 | 12 | | [Teensy++ 1.0 / 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, **2**, 3 | **1**, 16, 25 | 0 | | [Teensy-LC](https://www.pjrc.com/teensy/pinout.html) | **TPM1** | **16** | 17 | -| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** | +| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** | | | [Teensy 4.0 - 4.1](https://www.pjrc.com/teensy/pinout.html) | **FlexPWM1.3** | **8** | 7, 25 | -| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** | +| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** | | [BluePill / STM32F103C8T6](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill) | **TIM4** | % | **PB6 & PB7 & PB8 & PB9** | -| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin | +| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin | | [RP2040 / Mbed based](https://github.com/arduino/ArduinoCore-mbed) | Mbed Ticker | All pins | No pin | +### No timer required for sending The **send PWM signal** is by default generated by software. **Therefore every pin can be used for sending**. The PWM pulse length is guaranteed to be constant by using `delayMicroseconds()`. Take care not to generate interrupts during sending with software generated PWM, otherwise you will get jitter in the generated PWM. E.g. wait for a former `Serial.print()` statement to be finished by `Serial.flush()`. -Since the Arduino `micros()` function has a resolution of 4 s at 16 MHz, we always see a small jitter in the signal, which seems to be OK for the receivers. +Since the Arduino `micros()` function has a resolution of 4 µs at 16 MHz, we always see a small jitter in the signal, which seems to be OK for the receivers. -| Software generated PWM showing small jitter because of the limited resolution of 4 s of the Arduino core `micros()` function for an ATmega328 | Detail (ATmega328 generated) showing 30% duty cycle | +| Software generated PWM showing small jitter because of the limited resolution of 4 µs of the Arduino core `micros()` function for an ATmega328 | Detail (ATmega328 generated) showing 30% duty cycle | |-|-| | ![Software PWM](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_jitter.png) | ![Software PWM detail](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_detail.png) | @@ -633,17 +873,17 @@ For other boards/platforms you must look for the appropriate section guarded by ### Stop and start timer Another approach can be to share the timer **sequentially** if their functionality is used only for a short period of time like for the **Arduino tone() command**. An example can be seen [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169), where the timer settings for IR receive are restored after the tone has stopped. -For this we must call `IrReceiver.start()` or better `IrReceiver.start(microsecondsOfToneDuration)`.
+For this we must call `IrReceiver.restartTimer()` or better `IrReceiver.restartTimer(microsecondsOfToneDuration)`.
This only works since each call to` tone()` completely initializes the timer 2 used by the `tone()` command. ## Hardware-PWM signal generation for sending If you define `SEND_PWM_BY_TIMER`, the send PWM signal is forced to be generated by a hardware timer on most platforms.
-The same timer as for the receiver is used.
-Since each hardware timer has its dedicated output pins, you must change timer to change PWM output.
+By default, the same timer as for the receiver is used.
+Since each hardware timer has its dedicated output pin(s), you must change timer or timer sub-specifications to change PWM output pin. See [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp)
**Exeptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/39bdf8d7bf5b90dc221f8ae9fb3efed9f0a8a1db/examples/SimpleSender/PinDefinitionsAndMore.h#L273), where **PWM generation does not require a timer**. ## Why do we use 30% duty cycle for sending -We do it according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf): +We [do it](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRSend.hpp#L1192) according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf): - Carrier duty cycle 50 %, peak current of emitter IF = 200 mA, the resulting transmission distance is 25 m. - Carrier duty cycle 10 %, peak current of emitter IF = 800 mA, the resulting transmission distance is 29 m. - Factor 1.16 The reason is, that it is not the pure energy of the fundamental which is responsible for the receiver to detect a signal. @@ -652,11 +892,12 @@ Due to automatic gain control and other bias effects, high intensity of the 38 k
# How we decode signals -The IR signal is sampled at a **50 s interval**. For a constant 525 s pulse or pause we therefore get 10 or 11 samples, each with 50% probability.
-And believe me, if you send a 525 s signal, your receiver will output something between around 400 and 700 s!
+The IR signal is sampled at a **50 µs interval**. For a constant 525 µs pulse or pause we therefore get 10 or 11 samples, each with 50% probability.
+And believe me, if you send a 525 µs signal, your receiver will output something between around 400 and 700 µs!
Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).
-E.g. for the NEC protocol with its 560 s unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 s and 15 ticks / 750 s (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
-And since the receivers generated marks are longer or shorter than the spaces, we have introduced the [`MARK_EXCESS_MICROS` value]/https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown) +E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
+And since the receivers generated marks are longer or shorter than the spaces, +we have introduced the [`MARK_EXCESS_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library) macro to compensate for this receiver (and signal strength as well as ambient light dependent :disappointed: ) specific deviation.
Welcome to the world of **real world signal processing**. @@ -672,29 +913,29 @@ Created with sigrok PulseView with IR_NEC decoder by DjordjeMandic.

# Quick comparison of 5 Arduino IR receiving libraries -[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**. - **This is a short comparison and may not be complete or correct.** I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR lib for my project and to have a quick overview, when to choose which library.
-It is dated from **24.06.2022**. If you have complains about the data or request for extensions, please send a PM or open a discussion. +It is dated from **24.06.2022** and updated 10/2023. If you have complains about the data or request for extensions, please send a PM or open a discussion. -| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)
**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [Minimal NEC](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/MinimalReceiver) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder) -|---------|------|-----------|--------|----------|----------|----------| -| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC | NEC + RC5 + Sony + Samsung | +[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**. + +| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)
**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [TinyIR](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver/TinyReceiver.ino) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder) +|-|-|-|-|-|-|-| +| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC + FAST | NEC + RC5 + Sony + Samsung | | Timing method receive | Timer2 or interrupt for pin 2 or 3 | **Interrupt** | Timer2 or interrupt for pin 2 or 3 | Timer2 | **Interrupt** | **Interrupt** | -| Timing method send | PWM and timing with Timer2 interrupts | Timer2 interrupts | Timer2 and blocking wait | PWM with Timer2 and/or blocking wait with delay
Microseconds() | % | % | -| Send pins| All | All | All ? | Timer dependent | % | % | +| Timing method send | PWM and timing with Timer2 interrupts | Timer2 interrupts | Timer2 and blocking wait | PWM with Timer2 and/or blocking wait with delay
Microseconds() | blocking wait with delay
Microseconds() | % | +| Send pins| All | All | All ? | Timer dependent | All | % | | Decode method | OnTheFly | OnTheFly | RAM | RAM | OnTheFly | OnTheFly | -| Encode method | OnTheFly | OnTheFly | OnTheFly | OnTheFly or RAM | % | % | -| Callback suppport | x | % | % | % | x | % | -| Repeat handling | Receive + Send (partially) | % | ? | Receive + Send | Receive | Receive | -| LED feedback | x | % | x | x | x | % | +| Encode method | OnTheFly | OnTheFly | OnTheFly | OnTheFly or RAM | OnTheFly | % | +| Callback support | x | % | % | x | x | % | +| Repeat handling | Receive + Send (partially) | % | ? | Receive + Send | Receive + Send | Receive | +| LED feedback | x | % | x | x | Receive | % | | FLASH usage (simple NEC example with 5 prints) | 1820
(4300 for 15 main / 8000 for all 40 protocols)
(+200 for callback)
(+80 for interrupt at pin 2+3)| 1270
(1400 for pin 2+3) | 4830 | 1770 | **900** | ?1100? | | RAM usage | 52
(73 / 100 for 15 (main) / 40 protocols) | 62 | 334 | 227 | **19** | 29 | | Supported platforms | **avr, megaavr, attiny, Digispark (Pro), esp8266, ESP32, STM32, SAMD 21, Apollo3
(plus arm and pic for non Arduino IDE)** | avr, esp8266 | avr, SAMD 21, SAMD 51 | avr, attiny, [esp8266](https://github.com/crankyoldgit/IRremoteESP8266), esp32, SAM, SAMD | **All platforms with attach
Interrupt()** | **All platforms with attach
Interrupt()** | -| Last library update | 6/2022 | 4/2018 | 3/2022 | 6/2022 | 6/2022 | 2/2022 | -| Remarks | Decodes 40 protocols concurrently.
39 Protocols to send.
Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 45 issues, no reaction for at least one year.** | Decoding and sending are easy to extend.
Supports **Pronto** codes. | Requires no timer. | Requires no timer. | +| Last library update | 5/2023 | 4/2018 | 11/2022 | 9/2023 | 5/2023 | 2/2022 | +| Remarks | Decodes 40 protocols concurrently.
39 Protocols to send.
Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 63 issues, 10 pull requests.* | Universal decoder and encoder.
Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. | \* The Hash protocol gives you a hash as code, which may be sufficient to distinguish your keys on the remote, but may not work with some protocols like Mitsubishi @@ -703,7 +944,9 @@ It is dated from **24.06.2022**. If you have complains about the data or request # Useful links - [List of public IR code databases](http://www.harctoolbox.org/IR-resources.html) - [LIRC database](http://lirc-remotes.sourceforge.net/remotes-table.html) -- [IRMP list of IR protocols](https://www.mikrocontroller.net/articles/IRMP_-_english#IR_Protocols] +- [IRMP list of IR protocols](https://www.mikrocontroller.net/articles/IRMP_-_english#IR_Protocols) +- [IRDB database for IR codes](https://github.com/probonopd/irdb/tree/master/codes) +- [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols) - [IR Remote Control Theory and some protocols (upper right hamburger icon)](https://www.sbprojects.net/knowledge/ir/) - [Interpreting Decoded IR Signals (v2.45)](http://www.hifi-remote.com/johnsfine/DecodeIR.html) - ["Recording long Infrared Remote control signals with Arduino"](https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino) @@ -717,4 +960,4 @@ From the version 2.8.0, the license is the MIT license. # Copyright Initially coded 2009 Ken Shirriff http://www.righto.com
Copyright (c) 2016-2017 Rafi Khan
-Copyright (c) 2020-2022 [Armin Joachimsmeyer](https://github.com/ArminJo) +Copyright (c) 2020-2023 [Armin Joachimsmeyer](https://github.com/ArminJo) diff --git a/trunk/Arduino/libraries/IRremote/changelog.md b/trunk/Arduino/libraries/IRremote/changelog.md index 008746f7..74d08b45 100644 --- a/trunk/Arduino/libraries/IRremote/changelog.md +++ b/trunk/Arduino/libraries/IRremote/changelog.md @@ -2,6 +2,92 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.3.0 +- Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). + Therefore IrSender.begin(DISABLE_LED_FEEDBACK) will not longer work! +- Added convenience function isIRReceiverAttachedForTinyReceiver(). +- Added Extended NEC Protocol macro to TinyIR by Buzzerb. +- Fixed sendSamsung() / sendSamsungLG() bug. +- Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd(). +- Added rawlen and initialGap to IRData. +- Added ReceiveAndSendHobToHood example. +- Changed RECORD_GAP_MICROS default value from 5000 to 8000. + +# 4.2.1 +- Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. +- TinyReceiver 2.0 + - New TinyIRReceiverData which is filled with address, command and flags. + - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal(). + - Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated. +- Fix changing IR_SEND_PIN dynamically for ESP32. +- Fix wrong type of tEnableLEDFeedback. +- Support for ESP32-C3. + +# 4.2.0 +- The old decode function is renamed to decode_old(decode_results *aResults). decode (decode_results *aResults) is only available in IRremote.h and prints a message. +- Added DECODE_ONKYO, to force 16 bit command and data decoding. +- Enable Bang&Olufsen 455 kHz if SEND_PWM_BY_TIMER is defined. +- Fixed bug: TinyReceiver throwing ISR not in IRAM on ESP8266. +- Usage of ATTinyCore pin numbering scheme e.g. PIN_PB2. +- Added ARDUINO_ARCH_NRF52 to support Seeed XIAO nRF52840 Sense. +- First untested support of Uno R4. +- Extraced version macros to IRVersion.h. + +## 4.1.2 +- Workaround for ESP32 RTOS delay() timing bug influencing the mark() function. + +## 4.1.1 +- SAMD51 use timer3 if timer5 not available. +- Disabled #define LOCAL_DEBUG in IRReceive.hpp, which was accidently enabled at 4.1.0. + +## 4.1.0 +- Fixed bug in printing durations > 64535 in printIRResultRawFormatted(). +- Narrowed constraints for RC5 RC6 number of bits. +- Changed the first parameter of printTinyReceiverResultMinimal() to &Serial. +- Removed 3 Serial prints for deprecation warnings to fix #1094. +- Version 1.2.0 of TinyIR. Now FAST protocol with 40 ms period and shorter header space. +- Removed field "bool hasStopBit" and parameter "bool aSendStopBit" from PulseDistanceWidthProtocolConstants structure and related functions. +- Changed a lot of "unsigned int" types to "uint16_t" types. +- Improved overflow handling. +- Improved software PWM generation. +- Added FAST protocol. +- Improved handling of PULSE_DISTANCE + PULSE_WIDTH protocols. +- New example ReceiveAndSendDistanceWidth. +- Removed the automatic restarting of the receiver timer after sending with SEND_PWM_BY_TIMER enabled. +- Split ISR into ISR and function IRPinChangeInterruptHandler(). +- Added functions addTicksToInternalTickCounter() and addMicrosToInternalTickCounter(). + +## 4.0.0 +- Added decoding of PulseDistanceWidth protocols and therefore changed function decodeDistance() to decodeDistanceWidth() and filename ir_DistanceProtocol.hpp to ir_DistanceWidthProtocol.hpp. +- Removed static function printIRSendUsage(), but kept class function printIRSendUsage(). +- Changed type of decodedRawData and decodedRawDataArray which is now 64 bit for 32 bit platforms. +- Added receiver callback functionality and registerReceiveCompleteCallback() function. +- Introduced common structure PulseDistanceWidthProtocolConstants. +- Where possible, changed all send and decode functions to use PulseDistanceWidthProtocolConstants. +- Improved MSB/LSB handling +- New convenience fuctions bitreverse32Bit() and bitreverseOneByte(). +- Improved Magiquest protocol. +- Fix for #1028 - Prevent long delay caused by overflow when frame duration < repeat period - Thanks to Stephen Humphries! +- Support for ATtiny816 - Thanks to elockman. +- Added Bang&Olufsen protocol. #1030. +- Third parameter of function "void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)" is not optional anymore and this function is now only available if IR_SEND_PIN is not defined. #1033. +- Fixed bug in sendSony() for command parameter > 0x7F; +- Fixed bug with swapped LG2 header mark and space. +- Disabled strict checks while decoding. They can be enabled by defining DECODE_STRICT_CHECKS. +- Merged the 2 decode pulse width and distance functions. +- Changed macro names _REPEAT_SPACE to _REPEAT_DISTANCE. +- Improved TinyIRReceiver,added FAST protocol for it and added TinyIRSender.hpp and TinySender example, renamed TinyReceiver.h to TinyIR.h. +- Added DISABLE_CODE_FOR_RECEIVER to save program memory and RAM if receiving functionality is not required. +- Extracted protocol functions used by receive and send to IRProtocol.hpp. +- Analyzed Denon code table and therefore changed Denon from MSB to LSB first. +- Renamed sendRC6(aRawData...) to sendRC6Raw( aRawData...). +- Support for seeduino which lacks the print(unsigned long long...) method. Thanks to sklott https://stackoverflow.com/users/11680056/sklott +- Added support for attiny1614 by Joe Ostrander. +- Fixed SEND_PWM_BY_TIMER for ATtiny167 thanks to freskpe. +- Improved SHARP repeat decoding. +- Replaced macros TIMER_EN/DISABLE_RECEIVE_INTR and EN/DISABLE_SEND_PWM_BY_TIMER by functions. +- Added SAMSUNG48 protocol and sendSamsung48() function. + ## 3.9.0 - Improved documentation with the help of [ElectronicsArchiver}(https://github.com/ElectronicsArchiver). - Added NEC2 protocol. diff --git a/trunk/Arduino/libraries/IRremote/examples/IRremoteInfo/IRremoteInfo.ino b/trunk/Arduino/libraries/IRremote/examples/IRremoteInfo/IRremoteInfo.ino index 77b8a8dd..22ae75fb 100644 --- a/trunk/Arduino/libraries/IRremote/examples/IRremoteInfo/IRremoteInfo.ino +++ b/trunk/Arduino/libraries/IRremote/examples/IRremoteInfo/IRremoteInfo.ino @@ -296,6 +296,13 @@ void dumpProtocols() { #if !defined(EXCLUDE_EXOTIC_PROTOCOLS) // saves around 2000 bytes program memory + Serial.print(F("BANG_OLUFSEN: ")); +#if defined(DECODE_BEO) + Serial.println(F("Enabled")); +#else + Serial.println(F("Disabled")); +#endif + Serial.print(F("BOSEWAVE: ")); #if defined(DECODE_BOSEWAVE) Serial.println(F("Enabled")); @@ -310,6 +317,12 @@ void dumpProtocols() { Serial.println(F("Disabled")); #endif + Serial.print(F("FAST: ")); +#if defined(DECODE_FAST) + Serial.println(F("Enabled")); +#else + Serial.println(F("Disabled")); +#endif #endif } diff --git a/trunk/Arduino/libraries/IRremote/examples/MicroGirs/MicroGirs.ino b/trunk/Arduino/libraries/IRremote/examples/MicroGirs/MicroGirs.ino index df36013b..52e6c3a8 100644 --- a/trunk/Arduino/libraries/IRremote/examples/MicroGirs/MicroGirs.ino +++ b/trunk/Arduino/libraries/IRremote/examples/MicroGirs/MicroGirs.ino @@ -61,27 +61,29 @@ * In IrSqrutinizer, recognition of repeating signals will therefore not work. * The size of the data is platform dependent ("unsigned int", which is 16 bit on AVR boards, 32 bits on 32 bit boards). * - * For minimal footprint, undefine all DECODE* and SEND_* in IRremote.h. - * - * For optimal results, try for example to set _GAP to 100000 - * (what a brilliant variable name!!) and RAW_BUFFER_LENGTH to 251 - * in IRremoteInt.h. */ +#include -// Change the following two entries if desired +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. -/** - * Input Pin used by the receiver, can be arbitrary (almost...) - */ -#define INPUTPIN 5 +#if !defined(RAW_BUFFER_LENGTH) +# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF +#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF +#define RAW_BUFFER_LENGTH 500 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# else +#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# endif +#endif /** * Baud rate for the serial/USB connection. * (115200 is the default for IrScrutinizer and Lirc.) */ #define BAUDRATE 115200 +#define NO_DECODER -#include +#include "IRremote.hpp" #include /** @@ -107,14 +109,14 @@ /** * The modules supported, as given by the "modules" command. */ -#ifdef TRANSMIT -#ifdef RECEIVE +#if defined(TRANSMIT) +#if defined(RECEIVE) #define modulesSupported "base transmit receive" #else // ! RECEIVE #define modulesSupported "base transmit" #endif #else // !TRANSMIT -#ifdef RECEIVE +#if defined(RECEIVE) #define modulesSupported "base receive" #else // ! RECETVE #error At lease one of TRANSMIT and RECEIVE must be defined @@ -146,26 +148,12 @@ typedef unsigned frequency_t; // max 65535, unless 32-bit /** * Type used for durations in micro seconds. */ -typedef unsigned microseconds_t; // max 65535, unless 32-bit +typedef uint16_t microseconds_t; // max 65535 static const microseconds_t DUMMYENDING = 40000U; static const frequency_t FREQUENCY_T_MAX = UINT16_MAX; static const frequency_t MICROSECONDS_T_MAX = UINT16_MAX; -#ifdef RECEIVE -/** - * Instance of the IRremote class. - */ -IRrecv irRecv(INPUTPIN); -#endif - -#ifdef TRANSMIT -/*} - * Instance of the IRremote class. - */ -IRsend irSend; -#endif - /** * Our own tokenizer class. Breaks the command line into tokens. * Usage outside of this package is discouraged. @@ -175,12 +163,11 @@ private: static const int invalidIndex = -1; int index; // signed since invalidIndex is possible - const String& payload; + const String &payload; void trim(); public: Tokenizer(const String &str); - virtual ~Tokenizer(); String getToken(); String getRest(); @@ -192,10 +179,8 @@ public: static const int invalid = INT_MAX; }; -Tokenizer::Tokenizer(const String& str) : index(0), payload(str) { -} - -Tokenizer::~Tokenizer() { +Tokenizer::Tokenizer(const String &str) : + index(0), payload(str) { } String Tokenizer::getRest() { @@ -210,7 +195,7 @@ String Tokenizer::getLine() { int i = payload.indexOf('\n', index); String s = (i > 0) ? payload.substring(index, i) : payload.substring(index); - index = (i > 0) ? i+1 : invalidIndex; + index = (i > 0) ? i + 1 : invalidIndex; return s; } @@ -222,9 +207,9 @@ String Tokenizer::getToken() { String s = (i > 0) ? payload.substring(index, i) : payload.substring(index); index = (i > 0) ? i : invalidIndex; if (index != invalidIndex) - if (index != invalidIndex) - while (payload.charAt(index) == ' ') - index++; + if (index != invalidIndex) + while (payload.charAt(index) == ' ') + index++; return s; } @@ -244,9 +229,9 @@ frequency_t Tokenizer::getFrequency() { } ///////////////// end Tokenizer ///////////////////////////////// -#ifdef TRANSMIT +#if defined(TRANSMIT) static inline unsigned hz2khz(frequency_t hz) { - return (hz + 500)/1000; + return (hz + 500) / 1000; } /** @@ -266,49 +251,48 @@ static inline unsigned hz2khz(frequency_t hz) { * @param frequency Modulation frequency, in Hz (not kHz as normally in IRremote) * @param times Number of times to send the signal, in the sense above. */ -static void sendRaw(const microseconds_t intro[], unsigned lengthIntro, - const microseconds_t repeat[], unsigned lengthRepeat, - const microseconds_t ending[], unsigned lengthEnding, - frequency_t frequency, unsigned times) { +static void sendRaw(const microseconds_t intro[], unsigned lengthIntro, const microseconds_t repeat[], unsigned lengthRepeat, + const microseconds_t ending[], unsigned lengthEnding, frequency_t frequency, unsigned times) { if (lengthIntro > 0U) - irSend.sendRaw(intro, lengthIntro, hz2khz(frequency)); + IrSender.sendRaw(intro, lengthIntro, hz2khz(frequency)); if (lengthRepeat > 0U) for (unsigned i = 0U; i < times - (lengthIntro > 0U); i++) - irSend.sendRaw(repeat, lengthRepeat, hz2khz(frequency)); + IrSender.sendRaw(repeat, lengthRepeat, hz2khz(frequency)); if (lengthEnding > 0U) - irSend.sendRaw(ending, lengthEnding, hz2khz(frequency)); + IrSender.sendRaw(ending, lengthEnding, hz2khz(frequency)); } #endif // TRANSMIT -#ifdef RECEIVE -/** - * Reads a command from the stream given as argument. - * @param stream Stream to read from, typically Serial. - */ -static void receive(Stream& stream) { - irRecv.enableIRIn(); - irRecv.resume(); // Receive the next value +#if defined(RECEIVE) - while (!irRecv.decode()) { - } - irRecv.disableIRIn(); - - dump(stream); -} - -static void dump(Stream& stream) { - unsigned int count = irRecv.results.rawlen; +static void dump(Stream &stream) { + unsigned int count = IrReceiver.decodedIRData.rawDataPtr->rawlen; // If buffer gets full, count = RAW_BUFFER_LENGTH, which is odd, // and IrScrutinizer does not like that. - count &= ~1; + count &= ~1; for (unsigned int i = 1; i < count; i++) { stream.write(i & 1 ? '+' : '-'); - stream.print(irRecv.results.rawbuf[i] * MICROS_PER_TICK, DEC); + stream.print(IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK, DEC); stream.print(" "); } stream.print('-'); stream.println(DUMMYENDING); } + +/** + * Reads a command from the stream given as argument. + * @param stream Stream to read from, typically Serial. + */ +static void receive(Stream &stream) { + IrReceiver.start(); + + while (!IrReceiver.decode()) { + } + IrReceiver.stop(); + + dump(stream); +} + #endif // RECEIVE /** @@ -320,19 +304,27 @@ void setup() { ; // wait for serial port to connect. Serial.println(F(PROGNAME " " VERSION)); - //Serial.setTimeout(SERIALTIMEOUT); -/* -#ifdef RECEIVE - // There is unfortunately no disableIRIn in IRremote. - // Therefore, turn it on, and leave it on. - // We _hope_ that it will not interfere with sending. - irRecv.enableIRIn(); + // Just to know which program is running on my Arduino + Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); + +#if defined(RECEIVE) + // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED + IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); + + Serial.print(F("Ready to receive IR signals of protocols: ")); + printActiveIRProtocols(&Serial); + Serial.print(F("at pin ")); #endif -*/ + +#if defined(IR_SEND_PIN) + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin +#else + IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin +#endif + } - -static String readCommand(Stream& stream) { +static String readCommand(Stream &stream) { while (stream.available() == 0) { } @@ -341,7 +333,7 @@ static String readCommand(Stream& stream) { return line; } -static void processCommand(const String& line, Stream& stream) { +static void processCommand(const String &line, Stream &stream) { Tokenizer tokenizer(line); String cmd = tokenizer.getToken(); @@ -353,47 +345,47 @@ static void processCommand(const String& line, Stream& stream) { } switch (cmd[0]) { - case 'm': - stream.println(F(modulesSupported)); - break; + case 'm': + stream.println(F(modulesSupported)); + break; -#ifdef RECEIVE - case 'r': // receive +#if defined(RECEIVE) + case 'r': // receive //case 'a': //case 'c': - receive(stream); - break; + receive(stream); + break; #endif // RECEIVE -#ifdef TRANSMIT - case 's': // send - { - // TODO: handle unparsable data gracefully - unsigned noSends = (unsigned) tokenizer.getInt(); - frequency_t frequency = tokenizer.getFrequency(); - unsigned introLength = (unsigned) tokenizer.getInt(); - unsigned repeatLength = (unsigned) tokenizer.getInt(); - unsigned endingLength = (unsigned) tokenizer.getInt(); - microseconds_t intro[introLength]; - microseconds_t repeat[repeatLength]; - microseconds_t ending[endingLength]; - for (unsigned i = 0; i < introLength; i++) - intro[i] = tokenizer.getMicroseconds(); - for (unsigned i = 0; i < repeatLength; i++) - repeat[i] = tokenizer.getMicroseconds(); - for (unsigned i = 0; i < endingLength; i++) - ending[i] = tokenizer.getMicroseconds(); - sendRaw(intro, introLength, repeat, repeatLength, ending, endingLength, frequency, noSends); - stream.println(F(okString)); - } - break; +#if defined(TRANSMIT) + case 's': // send + { + // TODO: handle unparsable data gracefully + unsigned noSends = (unsigned) tokenizer.getInt(); + frequency_t frequency = tokenizer.getFrequency(); + unsigned introLength = (unsigned) tokenizer.getInt(); + unsigned repeatLength = (unsigned) tokenizer.getInt(); + unsigned endingLength = (unsigned) tokenizer.getInt(); + microseconds_t intro[introLength]; + microseconds_t repeat[repeatLength]; + microseconds_t ending[endingLength]; + for (unsigned i = 0; i < introLength; i++) + intro[i] = tokenizer.getMicroseconds(); + for (unsigned i = 0; i < repeatLength; i++) + repeat[i] = tokenizer.getMicroseconds(); + for (unsigned i = 0; i < endingLength; i++) + ending[i] = tokenizer.getMicroseconds(); + sendRaw(intro, introLength, repeat, repeatLength, ending, endingLength, frequency, noSends); + stream.println(F(okString)); + } + break; #endif // TRANSMIT - case 'v': // version - stream.println(F(PROGNAME " " VERSION)); - break; - default: - stream.println(F(errorString)); + case 'v': // version + stream.println(F(PROGNAME " " VERSION)); + break; + default: + stream.println(F(errorString)); } } diff --git a/trunk/Arduino/libraries/IRremote/keywords.txt b/trunk/Arduino/libraries/IRremote/keywords.txt index da69d1e3..935f913e 100644 --- a/trunk/Arduino/libraries/IRremote/keywords.txt +++ b/trunk/Arduino/libraries/IRremote/keywords.txt @@ -66,7 +66,7 @@ sendLegoPowerFunctions KEYWORD2 sendMagiQuest KEYWORD2 sendPronto KEYWORD2 sendMagiQuest KEYWORD2 - +sendFAST KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### @@ -92,10 +92,12 @@ SHARP LITERAL1 SONY LITERAL1 ONKYO LITERAL1 APPLE LITERAL1 +BANG_OLUFSEN LITERAL1 BOSEWAVE LITERAL1 LEGO_PF LITERAL1 MAGIQUEST LITERAL1 WHYNTER LITERAL1 +FAST LITERAL1 UNKNOWN LITERAL1 IR_RECEIVE_PIN LITERAL1 IR_SEND_PIN LITERAL1 diff --git a/trunk/Arduino/libraries/IRremote/library.json b/trunk/Arduino/libraries/IRremote/library.json index 811b3973..0bf21962 100644 --- a/trunk/Arduino/libraries/IRremote/library.json +++ b/trunk/Arduino/libraries/IRremote/library.json @@ -7,14 +7,15 @@ "type": "git", "url": "https://github.com/z3t0/Arduino-IRremote.git" }, - "version": "3.9.0", + "version": "4.3.0", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : [ { "name":"Armin Joachimsmeyer", - "email":"armin.arduino@gmail.com" + "email":"armin.arduino@gmail.com", + "maintainer": true }, { "name":"Rafi Khan", diff --git a/trunk/Arduino/libraries/IRremote/library.properties b/trunk/Arduino/libraries/IRremote/library.properties index 5b313ea3..cc6e5e95 100644 --- a/trunk/Arduino/libraries/IRremote/library.properties +++ b/trunk/Arduino/libraries/IRremote/library.properties @@ -1,10 +1,10 @@ name=IRremote -version=3.9.0 +version=4.3.0 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols -paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BoseWave, Lego, Whynter, MagiQuest.

New: Added NEC2 protocol. Improved Magiquest protocol. Added function sendPulseDistanceWidth().
Release notes
+paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BangOlufsen, BoseWave, Lego, Whynter, FAST, MagiQuest, Universal Pulse Distance and Pulse Width. NEW: TinyRSender improvements, sendSamsung bug fixes, new fields rawlen and initialGap and new functions stop/startTimer...(). category=Communication url=https://github.com/Arduino-IRremote/Arduino-IRremote -architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040 +architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040,renesas_uno includes=IRremote.hpp diff --git a/trunk/Arduino/libraries/IRremote/src/IRremote.h b/trunk/Arduino/libraries/IRremote/src/IRremote.h index a299236d..3af3f582 100644 --- a/trunk/Arduino/libraries/IRremote/src/IRremote.h +++ b/trunk/Arduino/libraries/IRremote/src/IRremote.h @@ -1,570 +1,58 @@ /** * @file IRremote.h - * @brief Public API to the library. + * + * @brief Stub for backward compatibility */ -//****************************************************************************** -// IRremote -// Version 2.0.1 June, 2015 -// Copyright 2009 Ken Shirriff -// For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html -// Edited by Mitra to add new controller SANYO -// -// Interrupt code based on NECIRrcv by Joe Knapp -// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 -// Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ -// -// JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) -// LG added by Darryl Smith (based on the JVC protocol) -// Whynter A/C ARC-110WD added by Francesco Meschia -// MagiQuest added by E. Stuart Hicks (based on code by mpflaga - https://github.com/mpflaga/Arduino-IRremote/) -//****************************************************************************** #ifndef IRremote_h #define IRremote_h -//------------------------------------------------------------------------------ -#include "private/IRremoteInt.h" +#include "IRremote.hpp" -/**************************************************** - * PROTOCOLS - ****************************************************/ -//------------------------------------------------------------------------------ -// Supported IR protocols -// Each protocol you include costs memory and, during decode, costs time -// Disable (set to 0) all the protocols you do not need/want! -// -#define DECODE_AIWA_RC_T501 1 -#define SEND_AIWA_RC_T501 1 +#warning Thank you for using the IRremote library! +#warning It seems, that you are using a old version 2.0 code / example. +#warning This version is no longer supported! +#warning Please use one of the new code examples from the library available at "File > Examples > Examples from Custom Libraries / IRremote". +#warning Or downgrade your library to version 2.6.0. +#warning Start with the SimpleReceiver or SimpleSender example. +#warning The examples are documented here: https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library +#warning A guide how to convert your 2.0 program is here: https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version -#define DECODE_BOSEWAVE 1 -#define SEND_BOSEWAVE 1 - -#define DECODE_DENON 1 -#define SEND_DENON 1 - -#define DECODE_DISH 0 // NOT WRITTEN -#define SEND_DISH 1 - -#define DECODE_JVC 1 -#define SEND_JVC 1 - -#define DECODE_LEGO_PF 0 // NOT WRITTEN -#define SEND_LEGO_PF 1 - -#define DECODE_LG 1 -#define SEND_LG 1 - -#define DECODE_MAGIQUEST 1 -#define SEND_MAGIQUEST 1 - -#define DECODE_MITSUBISHI 1 -#define SEND_MITSUBISHI 0 // NOT WRITTEN - -//#define USE_NEC_STANDARD // remove comment to have the standard NEC decoding (LSB first) available. -#if defined(USE_NEC_STANDARD) -#define DECODE_NEC_STANDARD 1 -#define DECODE_NEC 0 -#define LSB_FIRST_REQUIRED -#else -#define DECODE_NEC_STANDARD 0 -#define DECODE_NEC 1 -#endif -#define SEND_NEC 1 -#define SEND_NEC_STANDARD 1 - -#define DECODE_PANASONIC 1 -#define SEND_PANASONIC 1 - -#define DECODE_RC5 1 -#define SEND_RC5 1 - -#define DECODE_RC6 1 -#define SEND_RC6 1 - -#define DECODE_SAMSUNG 1 -#define SEND_SAMSUNG 1 - -#define DECODE_SANYO 1 -#define SEND_SANYO 0 // NOT WRITTEN - -#define DECODE_SHARP 1 -#define SEND_SHARP 1 - -#define DECODE_SHARP_ALT 1 -#define SEND_SHARP_ALT 1 -#if SEND_SHARP_ALT -#define LSB_FIRST_REQUIRED -#endif - -#define DECODE_SONY 1 -#define SEND_SONY 1 - -#define DECODE_WHYNTER 1 -#define SEND_WHYNTER 1 - -#define DECODE_HASH 1 // special decoder for all protocols - -/** - * An enum consisting of all supported formats. - * You do NOT need to remove entries from this list when disabling protocols! - */ -typedef enum { - UNKNOWN = -1, - UNUSED = 0, - AIWA_RC_T501, - BOSEWAVE, - DENON, - DISH, - JVC, - LEGO_PF, - LG, - MAGIQUEST, - MITSUBISHI, - NEC_STANDARD, - NEC, - PANASONIC, - RC5, - RC6, - SAMSUNG, - SANYO, - SHARP, - SHARP_ALT, - SONY, - WHYNTER, -} decode_type_t; - -/** - * Comment this out for lots of lovely debug output. - */ -//#define DEBUG -//------------------------------------------------------------------------------ -// Debug directives -// -#ifdef DEBUG -# define DBG_PRINT(...) Serial.print(__VA_ARGS__) -# define DBG_PRINTLN(...) Serial.println(__VA_ARGS__) -#else -/** - * If DEBUG, print the arguments, otherwise do nothing. - */ -# define DBG_PRINT(...) void() -/** - * If DEBUG, print the arguments as a line, otherwise do nothing. - */ -# define DBG_PRINTLN(...) void() -#endif - -//------------------------------------------------------------------------------ -// Helper macro for getting a macro definition as string -// -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) - -//------------------------------------------------------------------------------ -// Mark & Space matching functions -// -int MATCH(int measured, int desired); -int MATCH_MARK(int measured_ticks, int desired_us); -int MATCH_SPACE(int measured_ticks, int desired_us); - -/**************************************************** - * RECEIVING - ****************************************************/ -/** - * Results returned from the decoder - */ -struct decode_results { - decode_type_t decode_type; ///< UNKNOWN, NEC, SONY, RC5, ... - unsigned int address; ///< Used by Panasonic & Sharp6 NEC_standard [16-bits] - unsigned long value; ///< Decoded value / command [max 32-bits] - int bits; ///< Number of bits in decoded value - unsigned int magnitude; ///< Used by MagiQuest [16-bits] - bool isRepeat; ///< True if repeat of value is detected - - // next 3 values are copies of irparams values - unsigned int *rawbuf; ///< Raw intervals in 50uS ticks - unsigned int rawlen; ///< Number of records in rawbuf - bool overflow; ///< true if IR raw code too long -}; - -/** - * DEPRECATED - * Decoded value for NEC and others when a repeat code is received - * Use Flag decode_results.isRepeat (see above) instead - */ -#define REPEAT 0xFFFFFFFF - -/** - * Main class for receiving IR - */ -class IRrecv { -public: - /** - * Instantiate the IRrecv class. Multiple instantiation is not supported. - * @param recvpin Arduino pin to use. No sanity check is made. - */ - IRrecv(int recvpin); - /** - * Instantiate the IRrecv class. Multiple instantiation is not supported. - * @param recvpin Arduino pin to use, where a demodulating IR receiver is connected. - * @param blinkpin pin to blink when receiving IR. Not supported by all hardware. No sanity check is made. - */ - IRrecv(int recvpin, int blinkpin); - - /** - * TODO: Why is this public??? - * @param blinkflag - */ - void blink13(int blinkflag); - - /** - * Attempt to decode the recently receive IR signal - * @param results decode_results instance returning the decode, if any. - * @return success of operation. - */ - bool decode(decode_results *aResults);__attribute__ ((deprecated ("You should use decode() without a parameter."))) - ; // deprecated - bool decode(); - - /** - * Enable IR reception. - */ - void enableIRIn(); - - /** - * Disable IR reception. - */ - void disableIRIn(); - - /** - * Returns status of reception - * @return true if no reception is on-going. - */ - bool isIdle(); - - /** - * Returns status of reception and copies IR-data to decode_results buffer if true. - * @return true if data is available. - */ - bool available(); - - /** - * Called to re-enable IR reception. - */ - void resume(); - - const char* getProtocolString(); - void printResultShort(Print * aSerial); - - /** - * Print the result (second argument) as Pronto Hex on the Stream supplied as argument. - * @param stream The Stream on which to write, often Serial - * @param results the decode_results as delivered from irrecv.decode. - * @param frequency Modulation frequency in Hz. Often 38000Hz. - */ - void dumpPronto(Stream& stream, unsigned int frequency = 38000U); - - unsigned long decodePulseDistanceData(uint8_t aNumberOfBits, uint8_t aStartOffset, unsigned int aBitMarkMicros, - unsigned int aOneSpaceMicros, unsigned int aZeroSpaceMicros, bool aMSBfirst = true); - - decode_results results; // the instance for decoding - -private: -#if DECODE_HASH - bool decodeHash(); - bool decodeHash(decode_results *aResults); - int compare(unsigned int oldval, unsigned int newval); -#endif - - //...................................................................... -#if DECODE_RC5 - /** - * Try to decode the recently received IR signal as an RC5 signal- - * @param results decode_results instance returning the decode, if any. - * @return Success of the operation. - */ - bool decodeRC5(); - bool decodeRC5(decode_results *aResults); -#endif -#if DECODE_RC6 - bool decodeRC6(); - bool decodeRC6(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_NEC - bool decodeNEC(); - bool decodeNEC(decode_results *aResults); -#endif -#if DECODE_NEC_STANDARD - bool decodeNECStandard(); -#endif - - //...................................................................... -#if DECODE_SONY - bool decodeSony(); - bool decodeSony(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_PANASONIC - bool decodePanasonic(); - bool decodePanasonic(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_JVC - bool decodeJVC(); - bool decodeJVC(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_SAMSUNG - bool decodeSAMSUNG(); - bool decodeSAMSUNG(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_WHYNTER - bool decodeWhynter(); - bool decodeWhynter(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_AIWA_RC_T501 - bool decodeAiwaRCT501(); - bool decodeAiwaRCT501(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_LG - bool decodeLG(); - bool decodeLG(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_SANYO - bool decodeSanyo(); - bool decodeSanyo(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_MITSUBISHI - bool decodeMitsubishi(); - bool decodeMitsubishi(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_DISH - bool decodeDish () ; // NOT WRITTEN -#endif - //...................................................................... -#if DECODE_SHARP - bool decodeSharp(); - bool decodeSharp(decode_results *aResults); -#endif -#if DECODE_SHARP_ALT - bool decodeSharpAlt(); - bool decodeSharpAlt(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_DENON - bool decodeDenon(); - bool decodeDenon(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_LEGO_PF - bool decodeLegoPowerFunctions (decode_results *aResults) ; -#endif - //...................................................................... -#if DECODE_BOSEWAVE - bool decodeBoseWave(); - bool decodeBoseWave(decode_results *aResults); -#endif - //...................................................................... -#if DECODE_MAGIQUEST - bool decodeMagiQuest(); - bool decodeMagiQuest(decode_results *aResults); -#endif -}; - -/**************************************************** - * SENDING - ****************************************************/ -/** - * Define to use no carrier PWM, just simulate an active low receiver signal. - */ -//#define USE_NO_SEND_PWM -/** - * Define to use carrier PWM generation in software, instead of hardware PWM. - */ -//#define USE_SOFT_SEND_PWM -/** - * If USE_SOFT_SEND_PWM, this amount is subtracted from the on-time of the pulses. - */ -#ifndef PULSE_CORRECTION_MICROS -#define PULSE_CORRECTION_MICROS 3 -#endif -/** - * If USE_SOFT_SEND_PWM, use spin wait instead of delayMicros(). - */ -//#define USE_SPIN_WAIT -/** - * Main class for sending IR - */ -class IRsend { -public: -#if defined(USE_SOFT_SEND_PWM) || defined(USE_NO_SEND_PWM) - IRsend(int pin = IR_SEND_PIN) { - sendPin = pin; +/********************************************************************************************************************** + * The OLD and DEPRECATED decode function with parameter aResults, kept for backward compatibility to old 2.0 tutorials + * This function calls the old MSB first decoders and fills only the 3 variables: + * aResults->value + * aResults->bits + * aResults->decode_type + * It prints a message on the first call. + **********************************************************************************************************************/ +bool IRrecv::decode(decode_results *aResults) { + static bool sMessageWasSent = false; + if (!sMessageWasSent) { + Serial.println(F("**************************************************************************************************")); + Serial.println(F("Thank you for using the IRremote library!")); + Serial.println(F("It seems, that you are using a old version 2.0 code / example.")); + Serial.println(F("This version is no longer supported!")); + Serial.println(F("Please use one of the new code examples from the library,")); + Serial.println(F(" available at \"File > Examples > Examples from Custom Libraries / IRremote\".")); + Serial.println(F("Or downgrade your library to version 2.6.0.")); + Serial.println(); + Serial.println(F("Start with the SimpleReceiver or SimpleSender example.")); + Serial.println(); + Serial.println(F("The examples are documented here:")); + Serial.println(F(" https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library")); + Serial.println(F("A guide how to convert your 2.0 program is here:")); + Serial.println(F(" https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version")); + Serial.println(); + Serial.println(F("Thanks")); + Serial.println(F("**************************************************************************************************")); + Serial.println(); + Serial.println(); + sMessageWasSent = true; } -#else - IRsend() { - } -#endif - - void custom_delay_usec(unsigned long uSecs); - void enableIROut(int khz); - void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros, - unsigned int aZeroSpaceMicros, unsigned long aData, uint8_t aNumberOfBits, bool aMSBfirst = true); - void mark(unsigned int usec); - void space(unsigned int usec); - void sendRaw(const unsigned int buf[], unsigned int len, unsigned int hz); - void sendRaw_P(const unsigned int buf[], unsigned int len, unsigned int hz); - - //...................................................................... -#if SEND_RC5 - void sendRC5(unsigned long data, int nbits); - void sendRC5ext(uint8_t addr, uint8_t cmd, boolean toggle); -#endif -#if SEND_RC6 - void sendRC6(unsigned long data, int nbits); -#endif - //...................................................................... -#if SEND_NEC || SEND_NEC_STANDARD - void sendNECRepeat(); -#endif -#if SEND_NEC - void sendNEC(unsigned long data, int nbits, bool repeat = false); -#endif -#if SEND_NEC_STANDARD - void sendNECStandard(uint16_t aAddress, uint8_t aCommand, uint8_t aNumberOfRepeats = 0); -#endif - //...................................................................... -#if SEND_SONY - void sendSony(unsigned long data, int nbits); -#endif - //...................................................................... -#if SEND_PANASONIC - void sendPanasonic(unsigned int address, unsigned long data); -#endif - //...................................................................... -#if SEND_JVC - // JVC does NOT repeat by sending a separate code (like NEC does). - // The JVC protocol repeats by skipping the header. - // To send a JVC repeat signal, send the original code value - // and set 'repeat' to true - void sendJVC(unsigned long data, int nbits, bool repeat = false); -#endif - //...................................................................... -#if SEND_SAMSUNG - void sendSAMSUNG(unsigned long data, int nbits); -#endif - //...................................................................... -#if SEND_WHYNTER - void sendWhynter(unsigned long data, int nbits); -#endif - //...................................................................... -#if SEND_AIWA_RC_T501 - void sendAiwaRCT501(int code); -#endif - //...................................................................... -#if SEND_LG - void sendLG(unsigned long data, int nbits); -#endif - //...................................................................... -#if SEND_SANYO - void sendSanyo ( ) ; // NOT WRITTEN -#endif - //...................................................................... -#if SEND_MISUBISHI - void sendMitsubishi ( ) ; // NOT WRITTEN -#endif - //...................................................................... -#if SEND_DISH - void sendDISH(unsigned long data, int nbits); -#endif - //...................................................................... -#if SEND_SHARP - void sendSharpRaw(unsigned long data, int nbits); - void sendSharp(unsigned int address, unsigned int command); -#endif -#if SEND_SHARP_ALT - void sendSharpAltRaw(unsigned int data, int nbits); - void sendSharpAlt(uint8_t address, uint8_t command); -#endif - //...................................................................... -#if SEND_DENON - void sendDenon(unsigned long data, int nbits); -#endif - //...................................................................... -#if SEND_LEGO_PF - void sendLegoPowerFunctions(uint16_t data, bool repeat = true); -#endif - //...................................................................... -#if SEND_BOSEWAVE - void sendBoseWave(unsigned char code); -#endif - //...................................................................... -#if SEND_MAGIQUEST - void sendMagiQuest(unsigned long wand_id, unsigned int magnitude); -#endif - - /** - * Parse the string given as Pronto Hex, and send it a number of times given - * as the second argument. Thereby the division of the Pronto Hex into - * an intro-sequence and a repeat sequence is taken into account: - * First the intro sequence is sent, then the repeat sequence is sent times-1 times. - * However, if the intro sequence is empty, the repeat sequence is sent times times. - * Reference. - * - * Note: Using this function is very wasteful for the memory consumption on - * a small board. - * Normally it is a much better ide to use a tool like e.g. IrScrutinizer - * to transform Pronto type signals offline - * to a more memory efficient format. - * - * @param prontoHexString C type string (null terminated) containing a Pronto Hex representation. - * @param times Number of times to send the signal. - */ - void sendPronto(const char* prontoHexString, unsigned int times = 1U); - - void sendPronto(const uint16_t* data, unsigned int length, unsigned int times = 1U); - -#if HAS_FLASH_READ || defined(DOXYGEN) - void sendPronto_PF(uint_farptr_t str, unsigned int times = 1U); - - /** - * Version of sendPronto that reads from PROGMEM, saving RAM memory. - * @param pronto C type string (null terminated) containing a Pronto Hex representation. - * @param times Number of times to send the signal. - */ - void sendPronto_PF(const char *str, unsigned int times = 1U); - void sendPronto(const __FlashStringHelper *str, unsigned int times = 1U); -#endif - -private: -#if (DECODE_RC5 || DECODE_RC6) - /** - * This helper function is shared by RC5 and RC6 - */ - int getRClevel(decode_results *results, unsigned int *offset, int *used, int t1); -#endif - -#if defined(USE_SOFT_SEND_PWM) || defined(USE_NO_SEND_PWM) - int sendPin; - -# if defined(USE_SOFT_SEND_PWM) - unsigned int periodTimeMicros; - unsigned int periodOnTimeMicros; - - void sleepMicros(unsigned long us); - void sleepUntilMicros(unsigned long targetTime); -# endif - -#else - const int sendPin = IR_SEND_PIN; -#endif -}; + return decode_old(aResults); +} #endif // IRremote_h +#pragma once + diff --git a/trunk/Arduino/libraries/Keyboard/library.properties b/trunk/Arduino/libraries/Keyboard/library.properties index e5061d03..b5c99d89 100644 --- a/trunk/Arduino/libraries/Keyboard/library.properties +++ b/trunk/Arduino/libraries/Keyboard/library.properties @@ -1,5 +1,5 @@ name=Keyboard -version=1.0.4 +version=1.0.5 author=Arduino maintainer=Arduino sentence=Allows an Arduino board with USB capabilities to act as a Keyboard. diff --git a/trunk/Arduino/libraries/Keyboard/src/Keyboard.h b/trunk/Arduino/libraries/Keyboard/src/Keyboard.h index 9dbb3a95..e110404a 100644 --- a/trunk/Arduino/libraries/Keyboard/src/Keyboard.h +++ b/trunk/Arduino/libraries/Keyboard/src/Keyboard.h @@ -116,8 +116,10 @@ extern const uint8_t KeyboardLayout_en_US[]; extern const uint8_t KeyboardLayout_es_ES[]; extern const uint8_t KeyboardLayout_fr_FR[]; extern const uint8_t KeyboardLayout_it_IT[]; +extern const uint8_t KeyboardLayout_pt_PT[]; extern const uint8_t KeyboardLayout_sv_SE[]; extern const uint8_t KeyboardLayout_da_DK[]; +extern const uint8_t KeyboardLayout_hu_HU[]; // Low level key report: up to 6 keys and shift, ctrl etc at once typedef struct diff --git a/trunk/Arduino/libraries/OneWire/library.json b/trunk/Arduino/libraries/OneWire/library.json index c5298494..f370f06f 100644 --- a/trunk/Arduino/libraries/OneWire/library.json +++ b/trunk/Arduino/libraries/OneWire/library.json @@ -52,7 +52,7 @@ "type": "git", "url": "https://github.com/PaulStoffregen/OneWire" }, - "version": "2.3.5", + "version": "2.3.7", "homepage": "https://www.pjrc.com/teensy/td_libs_OneWire.html", "frameworks": "Arduino", "examples": [ diff --git a/trunk/Arduino/libraries/OneWire/library.properties b/trunk/Arduino/libraries/OneWire/library.properties index a7e4ad7d..5256ce47 100644 --- a/trunk/Arduino/libraries/OneWire/library.properties +++ b/trunk/Arduino/libraries/OneWire/library.properties @@ -1,5 +1,5 @@ name=OneWire -version=2.3.5 +version=2.3.7 author=Jim Studt, Tom Pollard, Robin James, Glenn Trewitt, Jason Dangel, Guillermo Lovato, Paul Stoffregen, Scott Roberts, Bertrik Sikken, Mark Tillotson, Ken Butcher, Roger Clark, Love Nystrom maintainer=Paul Stoffregen sentence=Access 1-wire temperature sensors, memory and other chips. diff --git a/trunk/Arduino/libraries/OneWire/util/OneWire_direct_gpio.h b/trunk/Arduino/libraries/OneWire/util/OneWire_direct_gpio.h index 07713671..435443a8 100644 --- a/trunk/Arduino/libraries/OneWire/util/OneWire_direct_gpio.h +++ b/trunk/Arduino/libraries/OneWire/util/OneWire_direct_gpio.h @@ -127,10 +127,14 @@ static inline __attribute__((always_inline)) IO_REG_TYPE directRead(IO_REG_TYPE pin) { +#if CONFIG_IDF_TARGET_ESP32C3 + return (GPIO.in.val >> pin) & 0x1; +#else // plain ESP32 if ( pin < 32 ) return (GPIO.in >> pin) & 0x1; - else if ( pin < 40 ) + else if ( pin < 46 ) return (GPIO.in1.val >> (pin - 32)) & 0x1; +#endif return 0; } @@ -138,26 +142,38 @@ IO_REG_TYPE directRead(IO_REG_TYPE pin) static inline __attribute__((always_inline)) void directWriteLow(IO_REG_TYPE pin) { +#if CONFIG_IDF_TARGET_ESP32C3 + GPIO.out_w1tc.val = ((uint32_t)1 << pin); +#else // plain ESP32 if ( pin < 32 ) GPIO.out_w1tc = ((uint32_t)1 << pin); - else if ( pin < 34 ) + else if ( pin < 46 ) GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); +#endif } static inline __attribute__((always_inline)) void directWriteHigh(IO_REG_TYPE pin) { +#if CONFIG_IDF_TARGET_ESP32C3 + GPIO.out_w1ts.val = ((uint32_t)1 << pin); +#else // plain ESP32 if ( pin < 32 ) GPIO.out_w1ts = ((uint32_t)1 << pin); - else if ( pin < 34 ) + else if ( pin < 46 ) GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); +#endif } static inline __attribute__((always_inline)) void directModeInput(IO_REG_TYPE pin) { +#if CONFIG_IDF_TARGET_ESP32C3 + GPIO.enable_w1tc.val = ((uint32_t)1 << (pin)); +#else if ( digitalPinIsValid(pin) ) { +#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4 uint32_t rtc_reg(rtc_gpio_desc[pin].reg); if ( rtc_reg ) // RTC pins PULL settings @@ -165,27 +181,25 @@ void directModeInput(IO_REG_TYPE pin) ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); } - +#endif + // Input if ( pin < 32 ) GPIO.enable_w1tc = ((uint32_t)1 << pin); else GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); - - uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? - pinFunction |= FUN_IE; // input enable but required for output as well? - pinFunction |= ((uint32_t)2 << MCU_SEL_S); - - ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; - - GPIO.pin[pin].val = 0; } +#endif } static inline __attribute__((always_inline)) void directModeOutput(IO_REG_TYPE pin) { +#if CONFIG_IDF_TARGET_ESP32C3 + GPIO.enable_w1ts.val = ((uint32_t)1 << (pin)); +#else if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs { +#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4 uint32_t rtc_reg(rtc_gpio_desc[pin].reg); if ( rtc_reg ) // RTC pins PULL settings @@ -193,20 +207,14 @@ void directModeOutput(IO_REG_TYPE pin) ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); } - +#endif + // Output if ( pin < 32 ) GPIO.enable_w1ts = ((uint32_t)1 << pin); else // already validated to pins <= 33 GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); - - uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? - pinFunction |= FUN_IE; // input enable but required for output as well? - pinFunction |= ((uint32_t)2 << MCU_SEL_S); - - ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; - - GPIO.pin[pin].val = 0; } +#endif } #define DIRECT_READ(base, pin) directRead(pin) @@ -250,6 +258,23 @@ void directModeOutput(IO_REG_TYPE pin) #define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask)) #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask)) +#elif defined(__ASR6501__) +#define PIN_IN_PORT(pin) (pin % PIN_NUMBER_IN_PORT) +#define PORT_FROM_PIN(pin) (pin / PIN_NUMBER_IN_PORT) +#define PORT_OFFSET(port) (PORT_REG_SHFIT * port) +#define PORT_ADDRESS(pin) (CYDEV_GPIO_BASE + PORT_OFFSET(PORT_FROM_PIN(pin))) + +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, pin) CY_SYS_PINS_READ_PIN(PORT_ADDRESS(pin)+4, PIN_IN_PORT(pin)) +#define DIRECT_WRITE_LOW(base, pin) CY_SYS_PINS_CLEAR_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin)) +#define DIRECT_WRITE_HIGH(base, pin) CY_SYS_PINS_SET_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin)) +#define DIRECT_MODE_INPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin)+8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_DIG_HIZ) +#define DIRECT_MODE_OUTPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin)+8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_STRONG) + #elif defined(RBL_NRF51822) #define PIN_TO_BASEREG(pin) (0) #define PIN_TO_BITMASK(pin) (pin) diff --git a/trunk/Arduino/libraries/OneWire/util/OneWire_direct_regtype.h b/trunk/Arduino/libraries/OneWire/util/OneWire_direct_regtype.h index 21c4634e..ca6aff7e 100644 --- a/trunk/Arduino/libraries/OneWire/util/OneWire_direct_regtype.h +++ b/trunk/Arduino/libraries/OneWire/util/OneWire_direct_regtype.h @@ -36,6 +36,9 @@ #elif defined(__SAMD21G18A__) #define IO_REG_TYPE uint32_t +#elif defined(__ASR6501__) +#define IO_REG_TYPE uint32_t + #elif defined(RBL_NRF51822) #define IO_REG_TYPE uint32_t diff --git a/trunk/Arduino/libraries/SdFat/LICENSE.md b/trunk/Arduino/libraries/SdFat/LICENSE.md index ab36c873..a8147353 100644 --- a/trunk/Arduino/libraries/SdFat/LICENSE.md +++ b/trunk/Arduino/libraries/SdFat/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2011..2017 Bill Greiman +Copyright (c) 2011..2020 Bill Greiman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/trunk/Arduino/libraries/SdFat/README.md b/trunk/Arduino/libraries/SdFat/README.md index c3abc011..ec001ee1 100644 --- a/trunk/Arduino/libraries/SdFat/README.md +++ b/trunk/Arduino/libraries/SdFat/README.md @@ -1,8 +1,13 @@ -### Warning: This is SdFat Version 2. +### Warning: Major Reformat of Source in 2.2.2 -Earlier releases of Version 1 are here: +There are a huge number of changes in 2.2.2 since I decided to use clang-format +to force Google style formatting. -https://github.com/greiman/SdFat/releases +I did this to avoid warnings from the static analysis programs Cppcheck and +cpplint. + +clang-format is aggressive so it may actually cause code to fail. For example +clang-format rearranges the order of includes according to the selected style. UTF-8 encoded filenames are supported in v2.1.0 or later. diff --git a/trunk/Arduino/libraries/SdFat/examples/DirectoryFunctions/DirectoryFunctions.ino b/trunk/Arduino/libraries/SdFat/examples/DirectoryFunctions/DirectoryFunctions.ino index 008d1fb9..e102a438 100644 --- a/trunk/Arduino/libraries/SdFat/examples/DirectoryFunctions/DirectoryFunctions.ino +++ b/trunk/Arduino/libraries/SdFat/examples/DirectoryFunctions/DirectoryFunctions.ino @@ -19,7 +19,7 @@ // SDCARD_SS_PIN is defined for the built-in SD on some boards. #ifndef SDCARD_SS_PIN const uint8_t SD_CS_PIN = SS; -#else // SDCARD_SS_PIN +#else // SDCARD_SS_PIN // Assume built-in SD is used. const uint8_t SD_CS_PIN = SDCARD_SS_PIN; #endif // SDCARD_SS_PIN @@ -30,7 +30,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN; // Try to select the best SD card configuration. #if HAS_SDIO_CLASS #define SD_CONFIG SdioConfig(FIFO_SDIO) -#elif ENABLE_DEDICATED_SPI +#elif ENABLE_DEDICATED_SPI #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK) #else // HAS_SDIO_CLASS #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK) @@ -78,9 +78,8 @@ void setup() { if (!sd.begin(SD_CONFIG)) { sd.initErrorHalt(&Serial); } - if (sd.exists("Folder1") - || sd.exists("Folder1/file1.txt") - || sd.exists("Folder1/File2.txt")) { + if (sd.exists("Folder1") || sd.exists("Folder1/file1.txt") || + sd.exists("Folder1/File2.txt")) { error("Please remove existing Folder1, file1.txt, and File2.txt"); } diff --git a/trunk/Arduino/libraries/SdFat/examples/OpenNext/OpenNext.ino b/trunk/Arduino/libraries/SdFat/examples/OpenNext/OpenNext.ino index 6ca5426f..51fd4911 100644 --- a/trunk/Arduino/libraries/SdFat/examples/OpenNext/OpenNext.ino +++ b/trunk/Arduino/libraries/SdFat/examples/OpenNext/OpenNext.ino @@ -18,7 +18,7 @@ // SDCARD_SS_PIN is defined for the built-in SD on some boards. #ifndef SDCARD_SS_PIN const uint8_t SD_CS_PIN = SS; -#else // SDCARD_SS_PIN +#else // SDCARD_SS_PIN // Assume built-in SD is used. const uint8_t SD_CS_PIN = SDCARD_SS_PIN; #endif // SDCARD_SS_PIN @@ -29,7 +29,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN; // Try to select the best SD card configuration. #if HAS_SDIO_CLASS #define SD_CONFIG SdioConfig(FIFO_SDIO) -#elif ENABLE_DEDICATED_SPI +#elif ENABLE_DEDICATED_SPI #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK) #else // HAS_SDIO_CLASS #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK) @@ -76,7 +76,7 @@ void setup() { sd.initErrorHalt(&Serial); } // Open root directory - if (!dir.open("/")){ + if (!dir.open("/")) { error("dir.open failed"); } // Open next file in root. diff --git a/trunk/Arduino/libraries/SdFat/examples/QuickStart/QuickStart.ino b/trunk/Arduino/libraries/SdFat/examples/QuickStart/QuickStart.ino index f69adf93..83fe99ac 100644 --- a/trunk/Arduino/libraries/SdFat/examples/QuickStart/QuickStart.ino +++ b/trunk/Arduino/libraries/SdFat/examples/QuickStart/QuickStart.ino @@ -1,6 +1,7 @@ // Quick hardware test for SPI card access. // #include + #include "SdFat.h" #include "sdios.h" @@ -81,17 +82,17 @@ void setup() { if (DISABLE_CHIP_SELECT < 0) { cout << F( - "\nBe sure to edit DISABLE_CHIP_SELECT if you have\n" - "a second SPI device. For example, with the Ethernet\n" - "shield, DISABLE_CHIP_SELECT should be set to 10\n" - "to disable the Ethernet controller.\n"); + "\nBe sure to edit DISABLE_CHIP_SELECT if you have\n" + "a second SPI device. For example, with the Ethernet\n" + "shield, DISABLE_CHIP_SELECT should be set to 10\n" + "to disable the Ethernet controller.\n"); } cout << F( - "\nSD chip select is the key hardware option.\n" - "Common values are:\n" - "Arduino Ethernet shield, pin 4\n" - "Sparkfun SD shield, pin 8\n" - "Adafruit SD shields and modules, pin 10\n"); + "\nSD chip select is the key hardware option.\n" + "Common values are:\n" + "Arduino Ethernet shield, pin 4\n" + "Sparkfun SD shield, pin 8\n" + "Adafruit SD shields and modules, pin 10\n"); } bool firstTry = true; @@ -117,8 +118,8 @@ void loop() { } if (DISABLE_CHIP_SELECT < 0) { cout << F( - "\nAssuming the SD is the only SPI device.\n" - "Edit DISABLE_CHIP_SELECT to disable another device.\n"); + "\nAssuming the SD is the only SPI device.\n" + "Edit DISABLE_CHIP_SELECT to disable another device.\n"); } else { cout << F("\nDisabling SPI device on pin "); cout << int(DISABLE_CHIP_SELECT) << endl; @@ -128,12 +129,12 @@ void loop() { if (!sd.begin(chipSelect, SPI_SPEED)) { if (sd.card()->errorCode()) { cout << F( - "\nSD initialization failed.\n" - "Do not reformat the card!\n" - "Is the card correctly inserted?\n" - "Is chipSelect set to the correct value?\n" - "Does another SPI device need to be disabled?\n" - "Is there a wiring/soldering problem?\n"); + "\nSD initialization failed.\n" + "Do not reformat the card!\n" + "Is the card correctly inserted?\n" + "Is chipSelect set to the correct value?\n" + "Does another SPI device need to be disabled?\n" + "Is there a wiring/soldering problem?\n"); cout << F("\nerrorCode: ") << hex << showbase; cout << int(sd.card()->errorCode()); cout << F(", errorData: ") << int(sd.card()->errorData()); @@ -169,8 +170,8 @@ void loop() { cout << F("Files found (date time size name):\n"); sd.ls(LS_R | LS_DATE | LS_SIZE); - if ((sizeMB > 1100 && sd.vol()->sectorsPerCluster() < 64) - || (sizeMB < 2200 && sd.vol()->fatType() == 32)) { + if ((sizeMB > 1100 && sd.vol()->sectorsPerCluster() < 64) || + (sizeMB < 2200 && sd.vol()->fatType() == 32)) { cout << F("\nThis card should be reformatted for best performance.\n"); cout << F("Use a cluster size of 32 KB for cards larger than 1 GB.\n"); cout << F("Only cards larger than 2 GB should be formatted FAT32.\n"); diff --git a/trunk/Arduino/libraries/SdFat/examples/SdFormatter/SdFormatter.ino b/trunk/Arduino/libraries/SdFat/examples/SdFormatter/SdFormatter.ino index 18db8cfb..6cfd37be 100644 --- a/trunk/Arduino/libraries/SdFat/examples/SdFormatter/SdFormatter.ino +++ b/trunk/Arduino/libraries/SdFat/examples/SdFormatter/SdFormatter.ino @@ -31,7 +31,7 @@ const int8_t DISABLE_CS_PIN = -1; // SDCARD_SS_PIN is defined for the built-in SD on some boards. #ifndef SDCARD_SS_PIN const uint8_t SD_CS_PIN = SS; -#else // SDCARD_SS_PIN +#else // SDCARD_SS_PIN // Assume built-in SD is used. const uint8_t SD_CS_PIN = SDCARD_SS_PIN; #endif // SDCARD_SS_PIN @@ -42,7 +42,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN; // Try to select the best SD card configuration. #if HAS_SDIO_CLASS #define SD_CONFIG SdioConfig(FIFO_SDIO) -#elif ENABLE_DEDICATED_SPI +#elif ENABLE_DEDICATED_SPI #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK) #else // HAS_SDIO_CLASS #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK) @@ -52,14 +52,18 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN; ArduinoOutStream cout(Serial); //------------------------------------------------------------------------------ uint32_t cardSectorCount = 0; -uint8_t sectorBuffer[512]; +uint8_t sectorBuffer[512]; //------------------------------------------------------------------------------ // SdCardFactory constructs and initializes the appropriate card. SdCardFactory cardFactory; // Pointer to generic SD card. SdCard* m_card = nullptr; //------------------------------------------------------------------------------ -#define sdError(msg) {cout << F("error: ") << F(msg) << endl; sdErrorHalt();} +#define sdError(msg) \ + { \ + cout << F("error: ") << F(msg) << endl; \ + sdErrorHalt(); \ + } //------------------------------------------------------------------------------ void sdErrorHalt() { if (!m_card) { @@ -73,7 +77,8 @@ void sdErrorHalt() { cout << F(" = ") << int(m_card->errorCode()) << endl; cout << F("SD errorData = ") << int(m_card->errorData()) << endl; } - while (true) {} + while (true) { + } } //------------------------------------------------------------------------------ void clearSerialInput() { @@ -102,7 +107,7 @@ void eraseCard() { sdError("erase failed"); } cout << '.'; - if ((n++)%64 == 63) { + if ((n++) % 64 == 63) { cout << endl; } firstBlock += ERASE_SIZE; @@ -123,9 +128,9 @@ void formatCard() { FatFormatter fatFormatter; // Format exFAT if larger than 32GB. - bool rtn = cardSectorCount > 67108864 ? - exFatFormatter.format(m_card, sectorBuffer, &Serial) : - fatFormatter.format(m_card, sectorBuffer, &Serial); + bool rtn = cardSectorCount > 67108864 + ? exFatFormatter.format(m_card, sectorBuffer, &Serial) + : fatFormatter.format(m_card, sectorBuffer, &Serial); if (!rtn) { sdErrorHalt(); @@ -136,8 +141,8 @@ void formatCard() { void printConfig(SdSpiConfig config) { if (DISABLE_CS_PIN < 0) { cout << F( - "\nAssuming the SD is the only SPI device.\n" - "Edit DISABLE_CS_PIN to disable an SPI device.\n"); + "\nAssuming the SD is the only SPI device.\n" + "Edit DISABLE_CS_PIN to disable an SPI device.\n"); } else { cout << F("\nDisabling SPI device on pin "); cout << int(DISABLE_CS_PIN) << endl; @@ -169,19 +174,19 @@ void setup() { clearSerialInput(); cout << F( - "\n" - "This program can erase and/or format SD/SDHC/SDXC cards.\n" - "\n" - "Erase uses the card's fast flash erase command.\n" - "Flash erase sets all data to 0X00 for most cards\n" - "and 0XFF for a few vendor's cards.\n" - "\n" - "Cards up to 2 GiB (GiB = 2^30 bytes) will be formated FAT16.\n" - "Cards larger than 2 GiB and up to 32 GiB will be formatted\n" - "FAT32. Cards larger than 32 GiB will be formatted exFAT.\n" - "\n" - "Warning, all data on the card will be erased.\n" - "Enter 'Y' to continue: "); + "\n" + "This program can erase and/or format SD/SDHC/SDXC cards.\n" + "\n" + "Erase uses the card's fast flash erase command.\n" + "Flash erase sets all data to 0X00 for most cards\n" + "and 0XFF for a few vendor's cards.\n" + "\n" + "Cards up to 2 GiB (GiB = 2^30 bytes) will be formated FAT16.\n" + "Cards larger than 2 GiB and up to 32 GiB will be formatted\n" + "FAT32. Cards larger than 32 GiB will be formatted exFAT.\n" + "\n" + "Warning, all data on the card will be erased.\n" + "Enter 'Y' to continue: "); while (!Serial.available()) { yield(); } @@ -207,9 +212,9 @@ void setup() { return; } - cout << F("\nCard size: ") << cardSectorCount*5.12e-7; + cout << F("\nCard size: ") << cardSectorCount * 5.12e-7; cout << F(" GB (GB = 1E9 bytes)\n"); - cout << F("Card size: ") << cardSectorCount/2097152.0; + cout << F("Card size: ") << cardSectorCount / 2097152.0; cout << F(" GiB (GiB = 2^30 bytes)\n"); cout << F("Card will be formated "); @@ -221,13 +226,13 @@ void setup() { cout << F("FAT16\n"); } cout << F( - "\n" - "Options are:\n" - "E - erase the card and skip formatting.\n" - "F - erase and then format the card. (recommended)\n" - "Q - quick format the card without erase.\n" - "\n" - "Enter option: "); + "\n" + "Options are:\n" + "E - erase the card and skip formatting.\n" + "F - erase and then format the card. (recommended)\n" + "Q - quick format the card without erase.\n" + "\n" + "Enter option: "); while (!Serial.available()) { yield(); @@ -245,5 +250,4 @@ void setup() { formatCard(); } } -void loop() { -} \ No newline at end of file +void loop() {} \ No newline at end of file diff --git a/trunk/Arduino/libraries/SdFat/examples/SdInfo/SdInfo.ino b/trunk/Arduino/libraries/SdFat/examples/SdInfo/SdInfo.ino index b046a612..7ac7815d 100644 --- a/trunk/Arduino/libraries/SdFat/examples/SdInfo/SdInfo.ino +++ b/trunk/Arduino/libraries/SdFat/examples/SdInfo/SdInfo.ino @@ -20,7 +20,7 @@ const int8_t DISABLE_CS_PIN = -1; // SDCARD_SS_PIN is defined for the built-in SD on some boards. #ifndef SDCARD_SS_PIN const uint8_t SD_CS_PIN = SS; -#else // SDCARD_SS_PIN +#else // SDCARD_SS_PIN const uint8_t SD_CS_PIN = SDCARD_SS_PIN; #endif // SDCARD_SS_PIN @@ -99,7 +99,7 @@ void errorPrint() { bool mbrDmp() { MbrSector_t mbr; bool valid = true; - if (!sd.card()->readSector(0, (uint8_t*)&mbr)) { + if (!sd.card()->readSector(0, (uint8_t *)&mbr)) { cout << F("\nread MBR failed.\n"); errorPrint(); return false; @@ -114,11 +114,11 @@ bool mbrDmp() { } cout << int(ip) << ',' << uppercase << showbase << hex; cout << int(pt->boot) << ','; - for (int i = 0; i < 3; i++ ) { + for (int i = 0; i < 3; i++) { cout << int(pt->beginCHS[i]) << ','; } cout << int(pt->type) << ','; - for (int i = 0; i < 3; i++ ) { + for (int i = 0; i < 3; i++) { cout << int(pt->endCHS[i]) << ','; } cout << dec << getLe32(pt->relativeSectors) << ','; @@ -141,18 +141,17 @@ void dmpVol() { cout << F("sectorsPerCluster: ") << sd.sectorsPerCluster() << endl; cout << F("fatStartSector: ") << sd.fatStartSector() << endl; cout << F("dataStartSector: ") << sd.dataStartSector() << endl; - cout << F("clusterCount: ") << sd.clusterCount() << endl; + cout << F("clusterCount: ") << sd.clusterCount() << endl; cout << F("freeClusterCount: "); if (freeClusterCount >= 0) { cout << freeClusterCount << endl; } else { cout << F("failed\n"); - errorPrint(); + errorPrint(); } } //------------------------------------------------------------------------------ void printCardType() { - cout << F("\nCard type: "); switch (sd.card()->type()) { @@ -180,8 +179,8 @@ void printCardType() { void printConfig(SdSpiConfig config) { if (DISABLE_CS_PIN < 0) { cout << F( - "\nAssuming the SD is the only SPI device.\n" - "Edit DISABLE_CS_PIN to disable an SPI device.\n"); + "\nAssuming the SD is the only SPI device.\n" + "Edit DISABLE_CS_PIN to disable an SPI device.\n"); } else { cout << F("\nDisabling SPI device on pin "); cout << int(DISABLE_CS_PIN) << endl; @@ -205,7 +204,6 @@ void setup() { } cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl; printConfig(SD_CONFIG); - } //------------------------------------------------------------------------------ void loop() { @@ -220,15 +218,14 @@ void loop() { uint32_t t = millis(); if (!sd.cardBegin(SD_CONFIG)) { cout << F( - "\nSD initialization failed.\n" - "Do not reformat the card!\n" - "Is the card correctly inserted?\n" - "Is there a wiring/soldering problem?\n"); + "\nSD initialization failed.\n" + "Do not reformat the card!\n" + "Is the card correctly inserted?\n" + "Is there a wiring/soldering problem?\n"); if (isSpi(SD_CONFIG)) { cout << F( - "Is SD_CS_PIN set to the correct value?\n" - "Does another SPI device need to be disabled?\n" - ); + "Is SD_CS_PIN set to the correct value?\n" + "Does another SPI device need to be disabled?\n"); } errorPrint(); return; @@ -236,23 +233,21 @@ void loop() { t = millis() - t; cout << F("init time: ") << dec << t << " ms" << endl; - if (!sd.card()->readCID(&cid) || - !sd.card()->readCSD(&csd) || - !sd.card()->readOCR(&ocr) || - !sd.card()->readSCR(&scr)) { + if (!sd.card()->readCID(&cid) || !sd.card()->readCSD(&csd) || + !sd.card()->readOCR(&ocr) || !sd.card()->readSCR(&scr)) { cout << F("readInfo failed\n"); errorPrint(); return; } printCardType(); - cout << F("sdSpecVer: ") << 0.01*scr.sdSpecVer() << endl; + cout << F("sdSpecVer: ") << 0.01 * scr.sdSpecVer() << endl; cout << F("HighSpeedMode: "); - if (scr.sdSpecVer() && - sd.card()->cardCMD6(0X00FFFFFF, cmd6Data) && (2 & cmd6Data[13])) { + if (scr.sdSpecVer() && sd.card()->cardCMD6(0X00FFFFFF, cmd6Data) && + (2 & cmd6Data[13])) { cout << F("true\n"); } else { cout << F("false\n"); - } + } cidDmp(); csdDmp(); cout << F("\nOCR: ") << uppercase << showbase; diff --git a/trunk/Arduino/libraries/SdFat/examples/SoftwareSpi/SoftwareSpi.ino b/trunk/Arduino/libraries/SdFat/examples/SoftwareSpi/SoftwareSpi.ino index b9559658..388bf9f2 100644 --- a/trunk/Arduino/libraries/SdFat/examples/SoftwareSpi/SoftwareSpi.ino +++ b/trunk/Arduino/libraries/SdFat/examples/SoftwareSpi/SoftwareSpi.ino @@ -16,7 +16,7 @@ const uint8_t SD_CS_PIN = 10; // Pin numbers in templates must be constants. const uint8_t SOFT_MISO_PIN = 12; const uint8_t SOFT_MOSI_PIN = 11; -const uint8_t SOFT_SCK_PIN = 13; +const uint8_t SOFT_SCK_PIN = 13; // SdFat software SPI template SoftSpiDriver softSpi; @@ -77,4 +77,4 @@ void setup() { void loop() {} #else // SPI_DRIVER_SELECT #error SPI_DRIVER_SELECT must be two in SdFat/SdFatConfig.h -#endif //SPI_DRIVER_SELECT \ No newline at end of file +#endif // SPI_DRIVER_SELECT \ No newline at end of file diff --git a/trunk/Arduino/libraries/SdFat/examples/TeensySdioDemo/TeensySdioDemo.ino b/trunk/Arduino/libraries/SdFat/examples/TeensySdioDemo/TeensySdioDemo.ino index cf79f7e2..6dfbd9d8 100644 --- a/trunk/Arduino/libraries/SdFat/examples/TeensySdioDemo/TeensySdioDemo.ino +++ b/trunk/Arduino/libraries/SdFat/examples/TeensySdioDemo/TeensySdioDemo.ino @@ -7,7 +7,7 @@ // SDCARD_SS_PIN is defined for the built-in SD on some boards. #ifndef SDCARD_SS_PIN const uint8_t SD_CS_PIN = SS; -#else // SDCARD_SS_PIN +#else // SDCARD_SS_PIN // Assume built-in SD is used. const uint8_t SD_CS_PIN = SDCARD_SS_PIN; #endif // SDCARD_SS_PIN @@ -20,7 +20,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN; const size_t BUF_DIM = 32768; // 8 MiB file. -const uint32_t FILE_SIZE = 256UL*BUF_DIM; +const uint32_t FILE_SIZE = 256UL * BUF_DIM; #if SD_FAT_TYPE == 0 SdFat sd; @@ -72,13 +72,12 @@ void errorHalt(const char* msg) { Serial.print(", ErrorData: 0X"); Serial.println(sd.sdErrorData(), HEX); } - while (true) {} + while (true) { + } } bool ready = false; //------------------------------------------------------------------------------ -bool sdBusy() { - return ready ? sd.card()->isBusy() : false; -} +bool sdBusy() { return ready ? sd.card()->isBusy() : false; } //------------------------------------------------------------------------------ // Replace "weak" system yield() function. void yield() { @@ -110,7 +109,7 @@ void runTest() { Serial.println("\nsize,write,read"); Serial.println("bytes,KB/sec,KB/sec"); for (size_t nb = 512; nb <= BUF_DIM; nb *= 2) { - uint32_t nRdWr = FILE_SIZE/nb; + uint32_t nRdWr = FILE_SIZE / nb; if (!file.truncate(0)) { errorHalt("truncate failed"); } @@ -121,14 +120,14 @@ void runTest() { for (uint32_t n = 0; n < nRdWr; n++) { // Set start and end of buffer. buf32[0] = n; - buf32[nb/4 - 1] = n; + buf32[nb / 4 - 1] = n; if (nb != file.write(buf, nb)) { errorHalt("write failed"); } } t = micros() - t; totalMicros += t; - Serial.print(1000.0*FILE_SIZE/t); + Serial.print(1000.0 * FILE_SIZE / t); Serial.print(','); file.rewind(); t = micros(); @@ -138,13 +137,13 @@ void runTest() { errorHalt("read failed"); } // crude check of data. - if (buf32[0] != n || buf32[nb/4 - 1] != n) { + if (buf32[0] != n || buf32[nb / 4 - 1] != n) { errorHalt("data check"); } } t = micros() - t; totalMicros += t; - Serial.println(1000.0*FILE_SIZE/t); + Serial.println(1000.0 * FILE_SIZE / t); } file.close(); Serial.print("\ntotalMicros "); @@ -155,8 +154,8 @@ void runTest() { Serial.println(yieldCalls); Serial.print("yieldMaxUsec "); Serial.println(yieldMaxUsec); -// Serial.print("kHzSdClk "); -// Serial.println(kHzSdClk()); + // Serial.print("kHzSdClk "); + // Serial.println(kHzSdClk()); Serial.println("Done"); } //------------------------------------------------------------------------------ @@ -171,22 +170,22 @@ void loop() { if (warn) { warn = false; Serial.println( - "SD cards must be power cycled to leave\n" - "SPI mode so do SDIO tests first.\n" - "\nCycle power on the card if an error occurs."); + "SD cards must be power cycled to leave\n" + "SPI mode so do SDIO tests first.\n" + "\nCycle power on the card if an error occurs."); } clearSerialInput(); Serial.println( - "\nType '1' for FIFO SDIO" - "\n '2' for DMA SDIO" - "\n '3' for Dedicated SPI" - "\n '4' for Shared SPI"); + "\nType '1' for FIFO SDIO" + "\n '2' for DMA SDIO" + "\n '3' for Dedicated SPI" + "\n '4' for Shared SPI"); while (!Serial.available()) { } char c = Serial.read(); - if (c =='1') { + if (c == '1') { if (!sd.begin(SdioConfig(FIFO_SDIO))) { errorHalt("begin failed"); } @@ -202,7 +201,7 @@ void loop() { errorHalt("begin failed"); } Serial.println("\nDedicated SPI mode."); -#else // ENABLE_DEDICATED_SPI +#else // ENABLE_DEDICATED_SPI Serial.println("ENABLE_DEDICATED_SPI must be non-zero."); return; #endif // ENABLE_DEDICATED_SPI diff --git a/trunk/Arduino/libraries/SdFat/examples/bench/bench.ino b/trunk/Arduino/libraries/SdFat/examples/bench/bench.ino index e4e017bf..4778f44d 100644 --- a/trunk/Arduino/libraries/SdFat/examples/bench/bench.ino +++ b/trunk/Arduino/libraries/SdFat/examples/bench/bench.ino @@ -1,9 +1,9 @@ /* * This program is a simple binary write/read benchmark. */ +#include "FreeStack.h" #include "SdFat.h" #include "sdios.h" -#include "FreeStack.h" // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. @@ -19,7 +19,7 @@ // SDCARD_SS_PIN is defined for the built-in SD on some boards. #ifndef SDCARD_SS_PIN const uint8_t SD_CS_PIN = SS; -#else // SDCARD_SS_PIN +#else // SDCARD_SS_PIN // Assume built-in SD is used. const uint8_t SD_CS_PIN = SDCARD_SS_PIN; #endif // SDCARD_SS_PIN @@ -30,7 +30,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN; // Try to select the best SD card configuration. #if HAS_SDIO_CLASS #define SD_CONFIG SdioConfig(FIFO_SDIO) -#elif ENABLE_DEDICATED_SPI +#elif ENABLE_DEDICATED_SPI #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK) #else // HAS_SDIO_CLASS #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK) @@ -58,10 +58,10 @@ const uint8_t READ_COUNT = 2; // End of configuration constants. //------------------------------------------------------------------------------ // File size in bytes. -const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB; +const uint32_t FILE_SIZE = 1000000UL * FILE_SIZE_MB; // Insure 4-byte alignment. -uint32_t buf32[(BUF_SIZE + 3)/4]; +uint32_t buf32[(BUF_SIZE + 3) / 4]; uint8_t* buf = (uint8_t*)buf32; #if SD_FAT_TYPE == 0 @@ -125,8 +125,8 @@ void setup() { cout << F("\nUse a freshly formatted SD for best performance.\n"); if (!ENABLE_DEDICATED_SPI) { cout << F( - "\nSet ENABLE_DEDICATED_SPI nonzero in\n" - "SdFatConfig.h for best SPI performance.\n"); + "\nSet ENABLE_DEDICATED_SPI nonzero in\n" + "SdFatConfig.h for best SPI performance.\n"); } // use uppercase in hex and use 0X base prefix cout << uppercase << showbase << endl; @@ -161,7 +161,7 @@ void loop() { cout << F("Type is FAT") << int(sd.fatType()) << endl; } - cout << F("Card size: ") << sd.card()->sectorCount()*512E-9; + cout << F("Card size: ") << sd.card()->sectorCount() * 512E-9; cout << F(" GB (GB = 1E9 bytes)") << endl; cidDmp(); @@ -176,17 +176,17 @@ void loop() { for (size_t i = 0; i < (BUF_SIZE - 2); i++) { buf[i] = 'A' + (i % 26); } - buf[BUF_SIZE-2] = '\r'; + buf[BUF_SIZE - 2] = '\r'; } - buf[BUF_SIZE-1] = '\n'; + buf[BUF_SIZE - 1] = '\n'; cout << F("FILE_SIZE_MB = ") << FILE_SIZE_MB << endl; cout << F("BUF_SIZE = ") << BUF_SIZE << F(" bytes\n"); cout << F("Starting write test, please wait.") << endl << endl; // do write test - uint32_t n = FILE_SIZE/BUF_SIZE; - cout < [file] ... The style guidelines this tries to follow are those in - https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml + https://google.github.io/styleguide/cppguide.html Every problem is given a confidence score from 1-5, with 5 meaning we are certain of the problem, and 1 meaning it could be a legitimate construct. diff --git a/trunk/Arduino/libraries/SdFat/library.properties b/trunk/Arduino/libraries/SdFat/library.properties index e026c868..b5738f7b 100644 --- a/trunk/Arduino/libraries/SdFat/library.properties +++ b/trunk/Arduino/libraries/SdFat/library.properties @@ -1,5 +1,5 @@ name=SdFat -version=2.2.0 +version=2.2.2 license=MIT author=Bill Greiman maintainer=Bill Greiman diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.cpp b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.cpp index 0793d920..6d1fb43f 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.cpp +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.cpp @@ -42,9 +42,9 @@ bool FatFile::addCluster() { m_flags |= FILE_FLAG_DIR_DIRTY; return true; - fail: +fail: return false; -#else // USE_FAT_FILE_FLAG_CONTIGUOUS +#else // USE_FAT_FILE_FLAG_CONTIGUOUS m_flags |= FILE_FLAG_DIR_DIRTY; return m_vol->allocateCluster(m_curCluster, &m_curCluster); #endif // USE_FAT_FILE_FLAG_CONTIGUOUS @@ -61,7 +61,7 @@ bool FatFile::addDirCluster() { goto fail; } // max folder size - if (m_curPosition >= 512UL*4095) { + if (m_curPosition >= 512UL * 4095) { DBG_FAIL_MACRO; goto fail; } @@ -82,7 +82,7 @@ bool FatFile::addDirCluster() { m_curPosition += m_vol->bytesPerCluster(); return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -105,7 +105,7 @@ bool FatFile::attrib(uint8_t bits) { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -120,7 +120,7 @@ DirFat_t* FatFile::cacheDirEntry(uint8_t action) { } return dir + (m_dirIndex & 0XF); - fail: +fail: return nullptr; } //------------------------------------------------------------------------------ @@ -137,7 +137,7 @@ bool FatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) { DBG_FAIL_MACRO; goto fail; } - for (uint32_t c = m_firstCluster; ; c++) { + for (uint32_t c = m_firstCluster;; c++) { uint32_t next; int8_t fg = m_vol->fatGet(c, &next); if (fg < 0) { @@ -158,14 +158,14 @@ bool FatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) { *bgnSector = m_vol->clusterStartSector(m_firstCluster); } if (endSector) { - *endSector = m_vol->clusterStartSector(c) - + m_vol->sectorsPerCluster() - 1; + *endSector = + m_vol->clusterStartSector(c) + m_vol->sectorsPerCluster() - 1; } return true; } } - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -178,12 +178,12 @@ bool FatFile::createContiguous(const char* path, uint32_t size) { return true; } close(); - fail: +fail: return false; } //------------------------------------------------------------------------------ -bool FatFile::createContiguous(FatFile* dirFile, - const char* path, uint32_t size) { +bool FatFile::createContiguous(FatFile* dirFile, const char* path, + uint32_t size) { if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) { DBG_FAIL_MACRO; goto fail; @@ -192,7 +192,7 @@ bool FatFile::createContiguous(FatFile* dirFile, return true; } close(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -213,7 +213,7 @@ bool FatFile::dirEntry(DirFat_t* dst) { memcpy(dst, dir, sizeof(DirFat_t)); return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -223,7 +223,7 @@ uint32_t FatFile::dirSize() { return 0; } if (isRootFixed()) { - return FS_DIR_SIZE*m_vol->rootDirEntryCount(); + return FS_DIR_SIZE * m_vol->rootDirEntryCount(); } uint16_t n = 0; uint32_t c = isRoot32() ? m_vol->rootDirStart() : m_firstCluster; @@ -234,7 +234,7 @@ uint32_t FatFile::dirSize() { } n += m_vol->sectorsPerCluster(); } while (fg); - return 512UL*n; + return 512UL * n; } //------------------------------------------------------------------------------ int FatFile::fgets(char* str, int num, char* delim) { @@ -288,7 +288,7 @@ bool FatFile::getAccessDate(uint16_t* pdate) { *pdate = getLe16(dir.accessDate); return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -302,7 +302,7 @@ bool FatFile::getCreateDateTime(uint16_t* pdate, uint16_t* ptime) { *ptime = getLe16(dir.createTime); return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -316,13 +316,11 @@ bool FatFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) { *ptime = getLe16(dir.modifyTime); return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ -bool FatFile::isBusy() { - return m_vol->isBusy(); -} +bool FatFile::isBusy() { return m_vol->isBusy(); } //------------------------------------------------------------------------------ bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) { FatName_t fname; @@ -362,7 +360,7 @@ bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) { } return mkdir(parent, &fname); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -433,7 +431,7 @@ bool FatFile::mkdir(FatFile* parent, FatName_t* fname) { // write first sector return m_vol->cacheSync(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -485,7 +483,7 @@ bool FatFile::open(FatFile* dirFile, const char* path, oflag_t oflag) { } return open(dirFile, &fname, oflag); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -509,7 +507,7 @@ bool FatFile::open(FatFile* dirFile, uint16_t index, oflag_t oflag) { break; } if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) { - if (!dirFile->seekSet(32UL*(index - i))) { + if (!dirFile->seekSet(32UL * (index - i))) { DBG_FAIL_MACRO; goto fail; } @@ -530,7 +528,7 @@ bool FatFile::open(FatFile* dirFile, uint16_t index, oflag_t oflag) { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -591,8 +589,8 @@ bool FatFile::openCachedEntry(FatFile* dirFile, uint16_t dirIndex, m_dirSector = m_vol->cacheSectorNumber(); // copy first cluster number for directory fields - firstCluster = ((uint32_t)getLe16(dir->firstClusterHigh) << 16) - | getLe16(dir->firstClusterLow); + firstCluster = ((uint32_t)getLe16(dir->firstClusterHigh) << 16) | + getLe16(dir->firstClusterLow); if (oflag & O_TRUNC) { if (firstCluster && !m_vol->freeChain(firstCluster)) { @@ -611,7 +609,7 @@ bool FatFile::openCachedEntry(FatFile* dirFile, uint16_t dirIndex, } return true; - fail: +fail: m_attributes = FILE_ATTR_CLOSED; m_flags = 0; return false; @@ -638,7 +636,7 @@ bool FatFile::openCwd() { rewind(); return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -655,7 +653,7 @@ bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) { } while (1) { // read entry into cache - index = dirFile->curPosition()/FS_DIR_SIZE; + index = dirFile->curPosition() / FS_DIR_SIZE; DirFat_t* dir = dirFile->readDirCache(); if (!dir) { if (dirFile->getError()) { @@ -691,7 +689,7 @@ bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) { } } - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -706,34 +704,34 @@ bool FatFile::openRoot(FatVolume* vol) { m_vol = vol; switch (vol->fatType()) { #if FAT12_SUPPORT - case 12: + case 12: #endif // FAT12_SUPPORT - case 16: - m_attributes = FILE_ATTR_ROOT_FIXED; - break; + case 16: + m_attributes = FILE_ATTR_ROOT_FIXED; + break; - case 32: - m_attributes = FILE_ATTR_ROOT32; - break; + case 32: + m_attributes = FILE_ATTR_ROOT32; + break; - default: - DBG_FAIL_MACRO; - goto fail; + default: + DBG_FAIL_MACRO; + goto fail; } // read only m_flags = FILE_FLAG_READ; return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ int FatFile::peek() { - uint32_t curPosition = m_curPosition; - uint32_t curCluster = m_curCluster; + uint32_t saveCurPosition = m_curPosition; + uint32_t saveCurCluster = m_curCluster; int c = read(); - m_curPosition = curPosition; - m_curCluster = curCluster; + m_curPosition = saveCurPosition; + m_curCluster = saveCurCluster; return c; } //------------------------------------------------------------------------------ @@ -754,13 +752,13 @@ bool FatFile::preAllocate(uint32_t length) { #if USE_FAT_FILE_FLAG_CONTIGUOUS // Mark contiguous and insure sync() will update dir entry m_flags |= FILE_FLAG_PREALLOCATE | FILE_FLAG_CONTIGUOUS | FILE_FLAG_DIR_DIRTY; -#else // USE_FAT_FILE_FLAG_CONTIGUOUS +#else // USE_FAT_FILE_FLAG_CONTIGUOUS // insure sync() will update dir entry m_flags |= FILE_FLAG_DIR_DIRTY; #endif // USE_FAT_FILE_FLAG_CONTIGUOUS return sync(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -785,7 +783,7 @@ int FatFile::read(void* buf, size_t nbyte) { } } else if (isRootFixed()) { uint16_t tmp16 = - FS_DIR_SIZE*m_vol->m_rootDirEntryCount - (uint16_t)m_curPosition; + FS_DIR_SIZE * m_vol->m_rootDirEntryCount - (uint16_t)m_curPosition; if (nbyte > tmp16) { nbyte = tmp16; } @@ -795,8 +793,8 @@ int FatFile::read(void* buf, size_t nbyte) { size_t n; offset = m_curPosition & m_vol->sectorMask(); // offset in sector if (isRootFixed()) { - sector = m_vol->rootDirStart() - + (m_curPosition >> m_vol->bytesPerSectorShift()); + sector = m_vol->rootDirStart() + + (m_curPosition >> m_vol->bytesPerSectorShift()); } else { sectorOfCluster = m_vol->sectorOfCluster(m_curPosition); if (offset == 0 && sectorOfCluster == 0) { @@ -826,8 +824,8 @@ int FatFile::read(void* buf, size_t nbyte) { } sector = m_vol->clusterStartSector(m_curCluster) + sectorOfCluster; } - if (offset != 0 || toRead < m_vol->bytesPerSector() - || sector == m_vol->cacheSectorNumber()) { + if (offset != 0 || toRead < m_vol->bytesPerSector() || + sector == m_vol->cacheSectorNumber()) { // amount to be read from current sector n = m_vol->bytesPerSector() - offset; if (n > toRead) { @@ -842,7 +840,7 @@ int FatFile::read(void* buf, size_t nbyte) { uint8_t* src = pc + offset; memcpy(dst, src, n); #if USE_MULTI_SECTOR_IO - } else if (toRead >= 2*m_vol->bytesPerSector()) { + } else if (toRead >= 2 * m_vol->bytesPerSector()) { uint32_t ns = toRead >> m_vol->bytesPerSectorShift(); if (!isRootFixed()) { uint32_t mb = m_vol->sectorsPerCluster() - sectorOfCluster; @@ -870,20 +868,19 @@ int FatFile::read(void* buf, size_t nbyte) { } return nbyte - toRead; - fail: +fail: m_error |= READ_ERROR; return -1; } //------------------------------------------------------------------------------ int8_t FatFile::readDir(DirFat_t* dir) { - int16_t n; // if not a directory file or miss-positioned return an error if (!isDir() || (0X1F & m_curPosition)) { return -1; } while (1) { - n = read(dir, sizeof(DirFat_t)); + int16_t n = read(dir, sizeof(DirFat_t)); if (n != sizeof(DirFat_t)) { return n == 0 ? 0 : -1; } @@ -910,7 +907,7 @@ DirFat_t* FatFile::readDirCache(bool skipReadOk) { if (i == 0 || !skipReadOk) { int8_t n = read(&n, 1); - if (n != 1) { + if (n != 1) { if (n != 0) { DBG_FAIL_MACRO; } @@ -923,7 +920,7 @@ DirFat_t* FatFile::readDirCache(bool skipReadOk) { // return pointer to entry return reinterpret_cast(m_vol->cacheAddress()) + i; - fail: +fail: return nullptr; } //------------------------------------------------------------------------------ @@ -935,7 +932,7 @@ bool FatFile::remove(const char* path) { } return file.remove(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -1031,7 +1028,7 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) { } // store new dot dot sector = m_vol->clusterStartSector(m_firstCluster); - uint8_t* pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE); + pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE); dir = reinterpret_cast(pc); if (!dir) { DBG_FAIL_MACRO; @@ -1049,7 +1046,7 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) { } return m_vol->cacheSync(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -1091,7 +1088,7 @@ bool FatFile::rmdir() { m_flags |= FILE_FLAG_WRITE; return remove(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -1105,7 +1102,7 @@ bool FatFile::rmRfStar() { rewind(); while (1) { // remember position - index = m_curPosition/FS_DIR_SIZE; + index = m_curPosition / FS_DIR_SIZE; DirFat_t* dir = readDirCache(); if (!dir) { @@ -1150,8 +1147,8 @@ bool FatFile::rmRfStar() { } } // position to next entry if required - if (m_curPosition != (32UL*(index + 1))) { - if (!seekSet(32UL*(index + 1))) { + if (m_curPosition != (32UL * (index + 1))) { + if (!seekSet(32UL * (index + 1))) { DBG_FAIL_MACRO; goto fail; } @@ -1166,7 +1163,7 @@ bool FatFile::rmRfStar() { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -1194,7 +1191,7 @@ bool FatFile::seekSet(uint32_t pos) { goto fail; } } else if (isRootFixed()) { - if (pos <= FS_DIR_SIZE*m_vol->rootDirEntryCount()) { + if (pos <= FS_DIR_SIZE * m_vol->rootDirEntryCount()) { goto done; } DBG_FAIL_MACRO; @@ -1225,12 +1222,12 @@ bool FatFile::seekSet(uint32_t pos) { } } - done: +done: m_curPosition = pos; m_flags &= ~FILE_FLAG_PREALLOCATE; return true; - fail: +fail: m_curCluster = tmp; return false; } @@ -1272,27 +1269,20 @@ bool FatFile::sync() { } DBG_FAIL_MACRO; - fail: +fail: m_error |= WRITE_ERROR; return false; } //------------------------------------------------------------------------------ bool FatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { + uint8_t day, uint8_t hour, uint8_t minute, + uint8_t second) { uint16_t dirDate; uint16_t dirTime; DirFat_t* dir; - if (!isFile() - || year < 1980 - || year > 2107 - || month < 1 - || month > 12 - || day < 1 - || day > 31 - || hour > 23 - || minute > 59 - || second > 59) { + if (!isFile() || year < 1980 || year > 2107 || month < 1 || month > 12 || + day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) { DBG_FAIL_MACRO; goto fail; } @@ -1323,7 +1313,7 @@ bool FatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, } return m_vol->cacheSync(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -1335,7 +1325,7 @@ bool FatFile::truncate() { goto fail; } if (m_firstCluster == 0) { - return true; + return true; } if (m_curCluster) { toFree = 0; @@ -1367,7 +1357,7 @@ bool FatFile::truncate() { m_flags |= FILE_FLAG_DIR_DIRTY; return sync(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -1414,7 +1404,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) { goto fail; } } -#else // USE_FAT_FILE_FLAG_CONTIGUOUS +#else // USE_FAT_FILE_FLAG_CONTIGUOUS int8_t fg = m_vol->fatGet(m_curCluster, &m_curCluster); if (fg < 0) { DBG_FAIL_MACRO; @@ -1442,8 +1432,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) { } } // sector for data write - uint32_t sector = m_vol->clusterStartSector(m_curCluster) - + sectorOfCluster; + uint32_t sector = m_vol->clusterStartSector(m_curCluster) + sectorOfCluster; if (sectorOffset != 0 || nToWrite < m_vol->bytesPerSector()) { // partial sector - must use cache @@ -1455,7 +1444,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) { } if (sectorOffset == 0 && - (m_curPosition >= m_fileSize || m_flags & FILE_FLAG_PREALLOCATE)) { + (m_curPosition >= m_fileSize || m_flags & FILE_FLAG_PREALLOCATE)) { // start of new sector don't need to read into cache cacheOption = FsCache::CACHE_RESERVE_FOR_WRITE; } else { @@ -1477,7 +1466,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) { } } #if USE_MULTI_SECTOR_IO - } else if (nToWrite >= 2*m_vol->bytesPerSector()) { + } else if (nToWrite >= 2 * m_vol->bytesPerSector()) { // use multiple sector write command uint32_t maxSectors = m_vol->sectorsPerCluster() - sectorOfCluster; uint32_t nSector = nToWrite >> m_vol->bytesPerSectorShift(); @@ -1512,7 +1501,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) { } return nbyte; - fail: +fail: // return for write error m_error |= WRITE_ERROR; return 0; diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.h b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.h index 19546f56..fa34d28e 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.h +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFile.h @@ -28,9 +28,10 @@ * \file * \brief FatFile class */ -#include -#include #include +#include +#include + #include "../common/FmtNumber.h" #include "../common/FsApiConstants.h" #include "../common/FsDateTime.h" @@ -38,28 +39,6 @@ #include "FatPartition.h" class FatVolume; //------------------------------------------------------------------------------ -// Stuff to store strings in AVR flash. -#ifdef __AVR__ -#include -#else // __AVR__ -#ifndef PSTR -/** store literal string in flash for ARM */ -#define PSTR(x) (x) -#endif // PSTR -#ifndef pgm_read_byte -/** read 8-bits from flash for ARM */ -#define pgm_read_byte(addr) (*(const unsigned char*)(addr)) -#endif // pgm_read_byte -#ifndef pgm_read_word -/** read 16-bits from flash for ARM */ -#define pgm_read_word(addr) (*(const uint16_t*)(addr)) -#endif // pgm_read_word -#ifndef PROGMEM -/** store in flash for ARM */ -#define PROGMEM -#endif // PROGMEM -#endif // __AVR__ -//------------------------------------------------------------------------------ /** * \struct FatPos_t * \brief Internal type for file position - do not use in user apps. @@ -105,7 +84,7 @@ class FatSfn_t { #if USE_LONG_FILE_NAMES /** Internal class for file names */ typedef FatLfn_t FatName_t; -#else // USE_LONG_FILE_NAMES +#else // USE_LONG_FILE_NAMES /** Internal class for file names */ typedef FatSfn_t FatName_t; #endif // USE_LONG_FILE_NAMES @@ -116,14 +95,11 @@ const uint8_t FNAME_FLAG_LOST_CHARS = 0X01; const uint8_t FNAME_FLAG_MIXED_CASE = 0X02; /** LFN entries are required for file name. */ const uint8_t FNAME_FLAG_NEED_LFN = - FNAME_FLAG_LOST_CHARS | FNAME_FLAG_MIXED_CASE; + FNAME_FLAG_LOST_CHARS | FNAME_FLAG_MIXED_CASE; /** Filename base-name is all lower case */ const uint8_t FNAME_FLAG_LC_BASE = FAT_CASE_LC_BASE; /** Filename extension is all lower case. */ const uint8_t FNAME_FLAG_LC_EXT = FAT_CASE_LC_EXT; -#if FNAME_FLAG_NEED_LFN & (FAT_CASE_LC_BASE || FAT_CASE_LC_EXT) -#error FNAME_FLAG_NEED_LFN & (FAT_CASE_LC_BASE || FAT_CASE_LC_EXT) -#endif // FNAME_FLAG_NEED_LFN & (FAT_CASE_LC_BASE || FAT_CASE_LC_EXT) //============================================================================== /** * \class FatFile @@ -140,9 +116,7 @@ class FatFile { * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive * OR of open flags. see FatFile::open(FatFile*, const char*, uint8_t). */ - FatFile(const char* path, oflag_t oflag) { - open(path, oflag); - } + FatFile(const char* path, oflag_t oflag) { open(path, oflag); } #if DESTRUCTOR_CLOSES_FILE /** Destructor */ ~FatFile() { @@ -155,7 +129,7 @@ class FatFile { * * \return true if a file is open. */ - operator bool() const {return isOpen();} + operator bool() const { return isOpen(); } /** * \return user settable file attributes for success else -1. */ @@ -190,13 +164,9 @@ class FatFile { return isFile() ? fileSize() - curPosition() : 0; } /** Clear all error bits. */ - void clearError() { - m_error = 0; - } + void clearError() { m_error = 0; } /** Set writeError to zero */ - void clearWriteError() { - m_error &= ~WRITE_ERROR; - } + void clearWriteError() { m_error &= ~WRITE_ERROR; } /** Close a file and force cached data and directory information * to be written to the storage device. * @@ -221,8 +191,7 @@ class FatFile { * * \return true for success or false for failure. */ - bool createContiguous(FatFile* dirFile, - const char* path, uint32_t size); + bool createContiguous(FatFile* dirFile, const char* path, uint32_t size); /** Create and open a new contiguous file of a specified size. * * \param[in] path A path with a valid file name. @@ -232,10 +201,10 @@ class FatFile { */ bool createContiguous(const char* path, uint32_t size); /** \return The current cluster number for a file or directory. */ - uint32_t curCluster() const {return m_curCluster;} + uint32_t curCluster() const { return m_curCluster; } /** \return The current position for a file or directory. */ - uint32_t curPosition() const {return m_curPosition;} + uint32_t curPosition() const { return m_curPosition; } /** Return a file's directory entry. * * \param[out] dir Location for return of the file's directory entry. @@ -244,7 +213,7 @@ class FatFile { */ bool dirEntry(DirFat_t* dir); /** \return Directory entry index. */ - uint16_t dirIndex() const {return m_dirIndex;} + uint16_t dirIndex() const { return m_dirIndex; } /** \return The number of bytes allocated to a directory or zero * if an error occurs. */ @@ -297,13 +266,13 @@ class FatFile { */ int fgets(char* str, int num, char* delim = nullptr); /** \return The total number of bytes in a file. */ - uint32_t fileSize() const {return m_fileSize;} + uint32_t fileSize() const { return m_fileSize; } /** \return first sector of file or zero for empty file. */ - uint32_t firstBlock() const {return firstSector();} + uint32_t firstBlock() const { return firstSector(); } /** \return Address of first sector or zero for empty file. */ uint32_t firstSector() const; /** Arduino name for sync() */ - void flush() {sync();} + void flush() { sync(); } /** set position for streams * \param[in] pos struct with value for new position */ @@ -340,7 +309,7 @@ class FatFile { */ bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime); /** \return All error bits. */ - uint8_t getError() const {return m_error;} + uint8_t getError() const { return m_error; } /** Get a file's modify date and time. * * \param[out] pdate Packed date for directory entry. @@ -388,9 +357,7 @@ class FatFile { */ size_t getSFN(char* name, size_t size); /** \return value of writeError */ - bool getWriteError() const { - return isOpen() ? m_error & WRITE_ERROR : true; - } + bool getWriteError() const { return isOpen() ? m_error & WRITE_ERROR : true; } /** * Check for device busy. * @@ -398,37 +365,37 @@ class FatFile { */ bool isBusy(); #if USE_FAT_FILE_FLAG_CONTIGUOUS - /** \return True if the file is contiguous. */ - bool isContiguous() const {return m_flags & FILE_FLAG_CONTIGUOUS;} + /** \return True if the file is contiguous. */ + bool isContiguous() const { return m_flags & FILE_FLAG_CONTIGUOUS; } #endif // USE_FAT_FILE_FLAG_CONTIGUOUS /** \return True if this is a directory. */ - bool isDir() const {return m_attributes & FILE_ATTR_DIR;} + bool isDir() const { return m_attributes & FILE_ATTR_DIR; } /** \return True if this is a normal file. */ - bool isFile() const {return m_attributes & FILE_ATTR_FILE;} + bool isFile() const { return m_attributes & FILE_ATTR_FILE; } /** \return True if this is a normal file or sub-directory. */ - bool isFileOrSubDir() const {return isFile() || isSubDir();} + bool isFileOrSubDir() const { return isFile() || isSubDir(); } /** \return True if this is a hidden file. */ - bool isHidden() const {return m_attributes & FS_ATTRIB_HIDDEN;} + bool isHidden() const { return m_attributes & FS_ATTRIB_HIDDEN; } /** \return true if this file has a Long File Name. */ - bool isLFN() const {return m_lfnOrd;} + bool isLFN() const { return m_lfnOrd; } /** \return True if this is an open file/directory. */ - bool isOpen() const {return m_attributes;} + bool isOpen() const { return m_attributes; } /** \return True file is readable. */ - bool isReadable() const {return m_flags & FILE_FLAG_READ;} + bool isReadable() const { return m_flags & FILE_FLAG_READ; } /** \return True if file is read-only */ - bool isReadOnly() const {return m_attributes & FS_ATTRIB_READ_ONLY;} + bool isReadOnly() const { return m_attributes & FS_ATTRIB_READ_ONLY; } /** \return True if this is the root directory. */ - bool isRoot() const {return m_attributes & FILE_ATTR_ROOT;} + bool isRoot() const { return m_attributes & FILE_ATTR_ROOT; } /** \return True if this is the FAT32 root directory. */ - bool isRoot32() const {return m_attributes & FILE_ATTR_ROOT32;} + bool isRoot32() const { return m_attributes & FILE_ATTR_ROOT32; } /** \return True if this is the FAT12 of FAT16 root directory. */ - bool isRootFixed() const {return m_attributes & FILE_ATTR_ROOT_FIXED;} + bool isRootFixed() const { return m_attributes & FILE_ATTR_ROOT_FIXED; } /** \return True if this is a sub-directory. */ - bool isSubDir() const {return m_attributes & FILE_ATTR_SUBDIR;} + bool isSubDir() const { return m_attributes & FILE_ATTR_SUBDIR; } /** \return True if this is a system file. */ - bool isSystem() const {return m_attributes & FS_ATTRIB_SYSTEM;} + bool isSystem() const { return m_attributes & FS_ATTRIB_SYSTEM; } /** \return True file is writable. */ - bool isWritable() const {return m_flags & FILE_FLAG_WRITE;} + bool isWritable() const { return m_flags & FILE_FLAG_WRITE; } /** List directory contents. * * \param[in] pr Print stream for list. @@ -553,7 +520,7 @@ class FatFile { * \return true for success or false for failure. */ bool open(const char* path, oflag_t oflag = O_RDONLY); - /** Open the current working directory. + /** Open the current working directory. * * \return true for success or false for failure. */ @@ -615,9 +582,7 @@ class FatFile { * * \return The number of characters printed. */ - size_t printAccessDateTime(print_t* pr) { - return printAccessDate(pr); - } + size_t printAccessDateTime(print_t* pr) { return printAccessDate(pr); } /** Print a file's creation date and time * * \param[in] pr Print stream for output. @@ -676,7 +641,7 @@ class FatFile { template size_t printField(Type value, char term) { char sign = 0; - char buf[3*sizeof(Type) + 3]; + char buf[3 * sizeof(Type) + 3]; char* str = buf + sizeof(buf); if (term) { @@ -819,9 +784,7 @@ class FatFile { */ bool rename(FatFile* dirFile, const char* newPath); /** Set the file's current position to zero. */ - void rewind() { - seekSet(0); - } + void rewind() { seekSet(0); } /** Remove a directory file. * * The directory file will be removed only if it is empty and is not the @@ -854,9 +817,7 @@ class FatFile { * \param[in] offset The new position in bytes from the current position. * \return true for success or false for failure. */ - bool seekCur(int32_t offset) { - return seekSet(m_curPosition + offset); - } + bool seekCur(int32_t offset) { return seekSet(m_curPosition + offset); } /** Set the files position to end-of-file + \a offset. See seekSet(). * Can't be used for directory files since file size is not defined. * \param[in] offset The new position in bytes from end-of-file. @@ -927,24 +888,18 @@ class FatFile { * * \return true for success or false for failure. */ - bool truncate(uint32_t length) { - return seekSet(length) && truncate(); - } + bool truncate(uint32_t length) { return seekSet(length) && truncate(); } /** Write a string to a file. Used by the Arduino Print class. * \param[in] str Pointer to the string. * Use getWriteError to check for errors. * \return count of characters written for success or -1 for failure. */ - size_t write(const char* str) { - return write(str, strlen(str)); - } + size_t write(const char* str) { return write(str, strlen(str)); } /** Write a single byte. * \param[in] b The byte to be written. * \return +1 for success or -1 for failure. */ - size_t write(uint8_t b) { - return write(&b, 1); - } + size_t write(uint8_t b) { return write(&b, 1); } /** Write data to an open file. * * \note Data is moved to the cache but may not be written to the @@ -973,16 +928,12 @@ class FatFile { * * \return true for success or false for failure. */ - bool ls(uint8_t flags = 0) { - return ls(&Serial, flags); - } + bool ls(uint8_t flags = 0) { return ls(&Serial, flags); } /** Print a file's name. * * \return length for success or zero for failure. */ - size_t printName() { - return FatFile::printName(&Serial); - } + size_t printName() { return FatFile::printName(&Serial); } #endif // ENABLE_ARDUINO_SERIAL private: @@ -1000,8 +951,7 @@ class FatFile { /** A FAT32 root directory */ static const uint8_t FILE_ATTR_ROOT32 = 0X80; /** Entry is for root. */ - static const uint8_t FILE_ATTR_ROOT = - FILE_ATTR_ROOT_FIXED | FILE_ATTR_ROOT32; + static const uint8_t FILE_ATTR_ROOT = FILE_ATTR_ROOT_FIXED | FILE_ATTR_ROOT32; /** Directory type bits */ static const uint8_t FILE_ATTR_DIR = FILE_ATTR_SUBDIR | FILE_ATTR_ROOT; @@ -1010,16 +960,16 @@ class FatFile { bool addCluster(); bool addDirCluster(); DirFat_t* cacheDir(uint16_t index) { - return seekSet(32UL*index) ? readDirCache() : nullptr; + return seekSet(32UL * index) ? readDirCache() : nullptr; } DirFat_t* cacheDirEntry(uint8_t action); bool cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd); bool createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd); uint16_t getLfnChar(DirLfn_t* ldir, uint8_t i); - uint8_t lfnChecksum(uint8_t* name) { + uint8_t lfnChecksum(const uint8_t* name) { uint8_t sum = 0; for (uint8_t i = 0; i < 11; i++) { - sum = (((sum & 1) << 7) | (sum >> 1)) + name[i]; + sum = (((sum & 1) << 7) | (sum >> 1)) + name[i]; } return sum; } @@ -1043,26 +993,26 @@ class FatFile { // treat curPosition as valid length. static const uint8_t FILE_FLAG_PREALLOCATE = 0X20; // file is contiguous - static const uint8_t FILE_FLAG_CONTIGUOUS = 0X40; + static const uint8_t FILE_FLAG_CONTIGUOUS = 0X40; // sync of directory entry required static const uint8_t FILE_FLAG_DIR_DIRTY = 0X80; // private data static const uint8_t WRITE_ERROR = 0X1; - static const uint8_t READ_ERROR = 0X2; + static const uint8_t READ_ERROR = 0X2; - uint8_t m_attributes = FILE_ATTR_CLOSED; - uint8_t m_error = 0; // Error bits. - uint8_t m_flags = 0; // See above for definition of m_flags bits - uint8_t m_lfnOrd; - uint16_t m_dirIndex; // index of directory entry in dir file - FatVolume* m_vol; // volume where file is located - uint32_t m_dirCluster; - uint32_t m_curCluster; // cluster for current file position - uint32_t m_curPosition; // current file position - uint32_t m_dirSector; // sector for this files directory entry - uint32_t m_fileSize; // file size in bytes - uint32_t m_firstCluster; // first cluster of file + uint8_t m_attributes = FILE_ATTR_CLOSED; + uint8_t m_error = 0; // Error bits. + uint8_t m_flags = 0; // See above for definition of m_flags bits + uint8_t m_lfnOrd; + uint16_t m_dirIndex; // index of directory entry in dir file + FatVolume* m_vol; // volume where file is located + uint32_t m_dirCluster; + uint32_t m_curCluster; // cluster for current file position + uint32_t m_curPosition; // current file position + uint32_t m_dirSector; // sector for this files directory entry + uint32_t m_fileSize; // file size in bytes + uint32_t m_firstCluster; // first cluster of file }; #include "../common/ArduinoFiles.h" @@ -1072,7 +1022,7 @@ class FatFile { */ class File32 : public StreamFile { public: - /** Opens the next file or folder in a directory. + /** Opens the next file or folder in a directory. * * \param[in] oflag open flags. * \return a FatStream object. diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileLFN.cpp b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileLFN.cpp index aa053353..54326dd4 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileLFN.cpp +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileLFN.cpp @@ -24,23 +24,17 @@ */ #define DBG_FILE "FatFileLFN.cpp" #include "../common/DebugMacros.h" -#include "../common/upcase.h" #include "../common/FsUtf.h" +#include "../common/upcase.h" #include "FatLib.h" #if USE_LONG_FILE_NAMES //------------------------------------------------------------------------------ -static bool isLower(char c) { - return 'a' <= c && c <= 'z'; -} +static bool isLower(char c) { return 'a' <= c && c <= 'z'; } //------------------------------------------------------------------------------ -static bool isUpper(char c) { - return 'A' <= c && c <= 'Z'; -} +static bool isUpper(char c) { return 'A' <= c && c <= 'Z'; } //------------------------------------------------------------------------------ // A bit smaller than toupper in AVR 328. -inline char toUpper(char c) { - return isLower(c) ? c - 'a' + 'A' : c; -} +inline char toUpper(char c) { return isLower(c) ? c - 'a' + 'A' : c; } //------------------------------------------------------------------------------ /** * Store a 16-bit long file name character. @@ -51,24 +45,13 @@ inline char toUpper(char c) { */ static void putLfnChar(DirLfn_t* ldir, uint8_t i, uint16_t c) { if (i < 5) { - setLe16(ldir->unicode1 + 2*i, c); + setLe16(ldir->unicode1 + 2 * i, c); } else if (i < 11) { - setLe16(ldir->unicode2 + 2*i -10, c); + setLe16(ldir->unicode2 + 2 * (i - 5), c); } else if (i < 13) { - setLe16(ldir->unicode3 + 2*i - 22, c); + setLe16(ldir->unicode3 + 2 * (i - 11), c); } } -//------------------------------------------------------------------------------ -// Daniel Bernstein University of Illinois at Chicago. -// Original had + instead of ^ -__attribute__((unused)) -static uint16_t Bernstein(const char* bgn, const char* end, uint16_t hash) { - while (bgn < end) { - // hash = hash * 33 ^ str[i]; - hash = ((hash << 5) + hash) ^ (*bgn++); - } - return hash; -} //============================================================================== bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) { FatFile dir = *this; @@ -95,7 +78,7 @@ bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) { if (toUpcase(u) != toUpcase(cp)) { return false; } -#else // USE_UTF8_LONG_NAMES +#else // USE_UTF8_LONG_NAMES if (u > 0X7F || toUpper(u) != toUpper(fname->getch())) { return false; } @@ -104,7 +87,7 @@ bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -141,13 +124,13 @@ bool FatFile::createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ bool FatFile::makeSFN(FatLfn_t* fname) { bool is83; -// char c; + // char c; uint8_t c; uint8_t bit = FAT_CASE_LC_BASE; uint8_t lc = 0; @@ -170,15 +153,17 @@ bool FatFile::makeSFN(FatLfn_t* fname) { // Not 8.3 if starts with dot. is83 = *ptr == '.' ? false : true; // Skip leading dots. - for (; *ptr == '.'; ptr++) {} + for (; *ptr == '.'; ptr++) { + } // Find last dot. - for (dot = end - 1; dot > ptr && *dot != '.'; dot--) {} + for (dot = end - 1; dot > ptr && *dot != '.'; dot--) { + } for (; ptr < end; ptr++) { c = *ptr; if (c == '.' && ptr == dot) { - in = 10; // Max index for full 8.3 name. - i = 8; // Place for extension. + in = 10; // Max index for full 8.3 name. + i = 8; // Place for extension. bit = FAT_CASE_LC_EXT; // bit for extension. } else { if (sfnReservedChar(c)) { @@ -192,7 +177,7 @@ bool FatFile::makeSFN(FatLfn_t* fname) { if (i > in) { is83 = false; if (in == 10 || ptr > dot) { - // Done - extension longer than three characters or no extension. + // Done - extension longer than three characters or no extension. break; } // Skip to dot. @@ -216,7 +201,7 @@ bool FatFile::makeSFN(FatLfn_t* fname) { goto fail; } if (is83) { - fname->flags = lc & uc ? FNAME_FLAG_MIXED_CASE : lc; + fname->flags = (lc & uc) ? FNAME_FLAG_MIXED_CASE : lc; } else { fname->flags = FNAME_FLAG_LOST_CHARS; fname->sfn[fname->seqPos] = '~'; @@ -224,7 +209,7 @@ bool FatFile::makeSFN(FatLfn_t* fname) { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -238,17 +223,13 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) { DBG_HALT_IF(fname->sfn[pos] != '~' && fname->sfn[pos + 1] != '1'); for (uint8_t seq = FIRST_HASH_SEQ; seq < 100; seq++) { - DBG_WARN_IF(seq > FIRST_HASH_SEQ); -#ifdef USE_LFN_HASH - hex = Bernstein(fname->begin, fname->end, seq); -#else + DBG_WARN_IF(seq > FIRST_HASH_SEQ); hex += millis(); -#endif if (pos > 3) { // Make space in name for ~HHHH. pos = 3; } - for (uint8_t i = pos + 4 ; i > pos; i--) { + for (uint8_t i = pos + 4; i > pos; i--) { uint8_t h = hex & 0XF; fname->sfn[i] = h < 10 ? h + '0' : h + 'A' - 10; hex >>= 4; @@ -277,25 +258,26 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) { // fall inti fail - too many tries. DBG_FAIL_MACRO; - fail: +fail: return false; - done: +done: return true; } //------------------------------------------------------------------------------ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { bool fnameFound = false; uint8_t lfnOrd = 0; - uint8_t freeNeed; uint8_t freeFound = 0; + uint8_t freeNeed; uint8_t order = 0; uint8_t checksum = 0; uint8_t ms10; uint8_t nameOrd; - uint16_t freeIndex = 0; uint16_t curIndex; uint16_t date; + uint16_t freeIndex = 0; + uint16_t freeTotal; uint16_t time; DirFat_t* dir; DirLfn_t* ldir; @@ -306,11 +288,11 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { goto fail; } // Number of directory entries needed. - nameOrd = (fname->len + 12)/13; - freeNeed = fname->flags & FNAME_FLAG_NEED_LFN ? 1 + nameOrd : 1; + nameOrd = (fname->len + 12) / 13; + freeNeed = (fname->flags & FNAME_FLAG_NEED_LFN) ? 1 + nameOrd : 1; dirFile->rewind(); while (1) { - curIndex = dirFile->m_curPosition/FS_DIR_SIZE; + curIndex = dirFile->m_curPosition / FS_DIR_SIZE; dir = dirFile->readDirCache(); if (!dir) { if (dirFile->getError()) { @@ -343,7 +325,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { if (!lfnOrd) { order = ldir->order & 0X1F; if (order != nameOrd || - (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) == 0) { + (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) == 0) { continue; } lfnOrd = nameOrd; @@ -376,7 +358,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { } } - found: +found: // Don't open if create only. if (oflag & O_EXCL) { DBG_FAIL_MACRO; @@ -384,7 +366,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { } goto open; - create: +create: // don't create unless O_CREAT and write mode if (!(oflag & O_CREAT) || !isWriteMode(oflag)) { DBG_WARN_MACRO; @@ -407,13 +389,16 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { } freeFound++; } - while (freeFound < freeNeed) { + // Loop handles the case of huge filename and cluster size one. + freeTotal = freeFound; + while (freeTotal < freeNeed) { // Will fail if FAT16 root. if (!dirFile->addDirCluster()) { DBG_FAIL_MACRO; goto fail; } - freeFound += vol->dirEntriesPerCluster(); + // 16-bit freeTotal needed for large cluster size. + freeTotal += vol->dirEntriesPerCluster(); } if (fnameFound) { if (!dirFile->makeUniqueSfn(fname)) { @@ -456,7 +441,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { // Force write of entry to device. vol->cacheDirty(); - open: +open: // open entry in cache. if (!openCachedEntry(dirFile, curIndex, oflag, lfnOrd)) { DBG_FAIL_MACRO; @@ -464,12 +449,12 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ -bool FatFile::parsePathName(const char* path, - FatLfn_t* fname, const char** ptr) { +bool FatFile::parsePathName(const char* path, FatLfn_t* fname, + const char** ptr) { size_t len = 0; // Skip leading spaces. while (*path == ' ') { @@ -491,7 +476,7 @@ bool FatFile::parsePathName(const char* path, DBG_FAIL_MACRO; goto fail; } -#else // USE_UTF8_LONG_NAMES +#else // USE_UTF8_LONG_NAMES uint8_t cp = *path++; if (cp >= 0X80 || lfnReservedChar(cp)) { DBG_FAIL_MACRO; @@ -510,11 +495,12 @@ bool FatFile::parsePathName(const char* path, goto fail; } // Advance to next path component. - for (; *path == ' ' || isDirSeparator(*path); path++) {} + for (; *path == ' ' || isDirSeparator(*path); path++) { + } *ptr = path; return makeSFN(fname); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -570,8 +556,7 @@ bool FatFile::remove() { goto fail; } if (ldir->attributes != FAT_ATTRIB_LONG_NAME || - order != (ldir->order & 0X1F) || - checksum != ldir->checksum) { + order != (ldir->order & 0X1F) || checksum != ldir->checksum) { DBG_FAIL_MACRO; goto fail; } @@ -589,7 +574,7 @@ bool FatFile::remove() { // Fall into fail. DBG_FAIL_MACRO; - fail: +fail: return false; } #endif // #if USE_LONG_FILE_NAMES diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFilePrint.cpp b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFilePrint.cpp index 99cb1797..34f65946 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFilePrint.cpp +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFilePrint.cpp @@ -67,7 +67,7 @@ bool FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) { } return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -99,7 +99,7 @@ size_t FatFile::printModifyDateTime(print_t* pr) { //------------------------------------------------------------------------------ size_t FatFile::printFileSize(print_t* pr) { char buf[11]; - char *ptr = buf + sizeof(buf); + char* ptr = buf + sizeof(buf); *--ptr = 0; ptr = fmtBase10(ptr, fileSize()); while (ptr > buf) { diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileSFN.cpp b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileSFN.cpp index 74798a9e..c8deef50 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileSFN.cpp +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatFileSFN.cpp @@ -46,7 +46,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) { while (true) { dir = dirFile->readDirCache(true); if (!dir) { - if (dirFile->getError()) { + if (dirFile->getError()) { DBG_FAIL_MACRO; goto fail; } @@ -143,7 +143,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) { // open entry in cache. return openCachedEntry(dirFile, index, oflag, 0); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -169,7 +169,7 @@ bool FatFile::openExistingSFN(const char* path) { } while (*path); return true; - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -192,9 +192,9 @@ bool FatFile::openSFN(FatSfn_t* fname) { goto fail; } if (isFatFileOrSubdir(&dir) && memcmp(fname->sfn, dir.name, 11) == 0) { - uint16_t dirIndex = (m_curPosition - 32) >> 5; - uint32_t dirCluster = m_firstCluster; - memset(this, 0 , sizeof(FatFile)); + uint16_t saveDirIndex = (m_curPosition - 32) >> 5; + uint32_t saveDirCluster = m_firstCluster; + memset(this, 0, sizeof(FatFile)); m_attributes = dir.attributes & FS_ATTRIB_COPY; m_flags = FILE_FLAG_READ; if (isFatFile(&dir)) { @@ -209,9 +209,9 @@ bool FatFile::openSFN(FatSfn_t* fname) { m_firstCluster |= getLe16(dir.firstClusterLow); m_fileSize = getLe32(dir.fileSize); m_vol = vol; - m_dirCluster = dirCluster; + m_dirCluster = saveDirCluster; m_dirSector = m_vol->cacheSectorNumber(); - m_dirIndex = dirIndex; + m_dirIndex = saveDirIndex; return true; } else if (isFatLongName(&dir)) { ldir = reinterpret_cast(&dir); @@ -223,7 +223,7 @@ bool FatFile::openSFN(FatSfn_t* fname) { } } - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -269,14 +269,14 @@ bool FatFile::parsePathName(const char* path, FatSfn_t* fname, goto fail; } // Set base-name and extension bits. - fname->flags = lc & uc ? 0 : lc; + fname->flags = (lc & uc) ? 0 : lc; while (isDirSeparator(*path)) { path++; } *ptr = path; return true; - fail: +fail: return false; } #if !USE_LONG_FILE_NAMES @@ -309,7 +309,7 @@ bool FatFile::remove() { // Write entry to device. return m_vol->cacheSync(); - fail: +fail: return false; } #endif // !USE_LONG_FILE_NAMES diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatLib.h b/trunk/Arduino/libraries/SdFat/src/FatLib/FatLib.h index 5da6708c..057d4041 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatLib.h +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatLib.h @@ -24,6 +24,6 @@ */ #ifndef FatLib_h #define FatLib_h -#include "FatVolume.h" #include "FatFormatter.h" +#include "FatVolume.h" #endif // FatLib_h diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.cpp b/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.cpp index 9e673f68..62537603 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.cpp +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.cpp @@ -27,7 +27,7 @@ #include "FatLib.h" FatVolume* FatVolume::m_cwv = nullptr; //------------------------------------------------------------------------------ -bool FatVolume::chdir(const char *path) { +bool FatVolume::chdir(const char* path) { FatFile dir; if (!dir.open(vwd(), path, O_RDONLY)) { DBG_FAIL_MACRO; @@ -40,6 +40,6 @@ bool FatVolume::chdir(const char *path) { m_vwd = dir; return true; - fail: +fail: return false; } diff --git a/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.h b/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.h index 4c950b10..daf64c39 100644 --- a/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.h +++ b/trunk/Arduino/libraries/SdFat/src/FatLib/FatVolume.h @@ -34,7 +34,7 @@ * \class FatVolume * \brief Integration class for the FatLib library. */ -class FatVolume : public FatPartition { +class FatVolume : public FatPartition { public: /** Get file's user settable attributes. * \param[in] path path to file. @@ -63,8 +63,8 @@ class FatVolume : public FatPartition { * \param[in] volStart Start sector of volume if part is zero. * \return true for success or false for failure. */ - bool begin(FsBlockDevice* dev, bool setCwv = true, - uint8_t part = 1, uint32_t volStart = 0) { + bool begin(FsBlockDevice* dev, bool setCwv = true, uint8_t part = 1, + uint32_t volStart = 0) { if (!init(dev, part, volStart)) { return false; } @@ -77,7 +77,7 @@ class FatVolume : public FatPartition { return true; } /** Change global current working volume to this volume. */ - void chvol() {m_cwv = this;} + void chvol() { m_cwv = this; } /** * Set volume working directory to root. @@ -92,7 +92,7 @@ class FatVolume : public FatPartition { * \param[in] path Path for volume working directory. * \return true for success or false for failure. */ - bool chdir(const char *path); + bool chdir(const char* path); //---------------------------------------------------------------------------- /** * Test for the existence of a file. @@ -120,9 +120,7 @@ class FatVolume : public FatPartition { * * \return true for success or false for failure. */ - bool ls(print_t* pr, uint8_t flags = 0) { - return m_vwd.ls(pr, flags); - } + bool ls(print_t* pr, uint8_t flags = 0) { return m_vwd.ls(pr, flags); } //---------------------------------------------------------------------------- /** List the contents of a directory. * @@ -164,7 +162,7 @@ class FatVolume : public FatPartition { * \param[in] oflag open flags. * \return a File32 object. */ - File32 open(const char *path, oflag_t oflag = O_RDONLY) { + File32 open(const char* path, oflag_t oflag = O_RDONLY) { File32 tmpFile; tmpFile.open(this, path, oflag); return tmpFile; @@ -195,7 +193,7 @@ class FatVolume : public FatPartition { * * \return true for success or false for failure. */ - bool rename(const char *oldPath, const char *newPath) { + bool rename(const char* oldPath, const char* newPath) { FatFile file; return file.open(vwd(), oldPath, O_RDONLY) && file.rename(vwd(), newPath); } @@ -226,7 +224,7 @@ class FatVolume : public FatPartition { return file.open(this, path, O_WRONLY) && file.truncate(length); } #if ENABLE_ARDUINO_SERIAL - /** List the directory contents of the root directory to Serial. + /** List the directory contents of the root directory to Serial. * * \param[in] flags The inclusive OR of * @@ -238,9 +236,7 @@ class FatVolume : public FatPartition { * * \return true for success or false for failure. */ - bool ls(uint8_t flags = 0) { - return ls(&Serial, flags); - } + bool ls(uint8_t flags = 0) { return ls(&Serial, flags); } /** List the directory contents of a directory to Serial. * * \param[in] path directory to list. @@ -266,19 +262,15 @@ class FatVolume : public FatPartition { * \param[in] path Path for volume working directory. * \return true for success or false for failure. */ - bool chdir(const String& path) { - return chdir(path.c_str()); - } - /** + bool chdir(const String& path) { return chdir(path.c_str()); } + /** * Test for the existence of a file. * * \param[in] path Path of the file to be tested for. * * \return true if the file exists else false. */ - bool exists(const String& path) { - return exists(path.c_str()); - } + bool exists(const String& path) { return exists(path.c_str()); } /** Make a subdirectory in the volume root directory. * * \param[in] path A path with a valid name for the subdirectory. @@ -297,7 +289,7 @@ class FatVolume : public FatPartition { * \return a File32 object. */ File32 open(const String& path, oflag_t oflag = O_RDONLY) { - return open(path.c_str(), oflag ); + return open(path.c_str(), oflag); } /** Remove a file from the volume root directory. * @@ -305,9 +297,7 @@ class FatVolume : public FatPartition { * * \return true for success or false for failure. */ - bool remove(const String& path) { - return remove(path.c_str()); - } + bool remove(const String& path) { return remove(path.c_str()); } /** Rename a file or subdirectory. * * \param[in] oldPath Path name to the file or subdirectory to be renamed. @@ -333,9 +323,7 @@ class FatVolume : public FatPartition { * * \return true for success or false for failure. */ - bool rmdir(const String& path) { - return rmdir(path.c_str()); - } + bool rmdir(const String& path) { return rmdir(path.c_str()); } /** Truncate a file to a specified length. The current file position * will be at the new EOF. * @@ -351,8 +339,8 @@ class FatVolume : public FatPartition { private: friend FatFile; - static FatVolume* cwv() {return m_cwv;} - FatFile* vwd() {return &m_vwd;} + static FatVolume* cwv() { return m_cwv; } + FatFile* vwd() { return &m_vwd; } static FatVolume* m_cwv; FatFile m_vwd; }; diff --git a/trunk/Arduino/libraries/SdFat/src/FreeStack.h b/trunk/Arduino/libraries/SdFat/src/FreeStack.h index c37da898..60729fac 100644 --- a/trunk/Arduino/libraries/SdFat/src/FreeStack.h +++ b/trunk/Arduino/libraries/SdFat/src/FreeStack.h @@ -34,7 +34,7 @@ /** Indicate FillStack() and UnusedStack() are available. */ #define HAS_UNUSED_STACK 1 /** boundary between stack and heap. */ -extern char *__brkval; +extern char* __brkval; /** End of bss section.*/ extern char __bss_end; /** Amount of free stack space. @@ -48,9 +48,7 @@ inline int FreeStack() { #define HAS_UNUSED_STACK 0 #elif defined(PLATFORM_ID) // Particle board #include "Arduino.h" -inline int FreeStack() { - return System.freeMemory(); -} +inline int FreeStack() { return System.freeMemory(); } #elif defined(__IMXRT1062__) #define HAS_UNUSED_STACK 1 extern uint8_t _ebss; @@ -69,9 +67,7 @@ inline int FreeStack() { #ifndef FREE_STACK_CPP #warning FreeStack is not defined for this system. #endif // FREE_STACK_CPP -inline int FreeStack() { - return 0; -} +inline int FreeStack() { return 0; } #endif // defined(__AVR__) || defined(DOXYGEN) #if defined(HAS_UNUSED_STACK) || defined(DOXYGEN) /** Fill stack with 0x55 pattern */ @@ -89,6 +85,6 @@ int UnusedStack(); #else // HAS_UNUSED_STACK #define HAS_UNUSED_STACK 0 inline void FillStack() {} -inline int UnusedStack() {return 0;} +inline int UnusedStack() { return 0; } #endif // defined(HAS_UNUSED_STACK) #endif // FreeStack_h diff --git a/trunk/Arduino/libraries/SdFat/src/MinimumSerial.cpp b/trunk/Arduino/libraries/SdFat/src/MinimumSerial.cpp index 6ea0ff0b..6a9259a9 100644 --- a/trunk/Arduino/libraries/SdFat/src/MinimumSerial.cpp +++ b/trunk/Arduino/libraries/SdFat/src/MinimumSerial.cpp @@ -22,14 +22,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include "common/SysCall.h" -#if defined(UDR0) || defined(DOXYGEN) #include "MinimumSerial.h" -const uint16_t MIN_2X_BAUD = F_CPU/(4*(2*0XFFF + 1)) + 1; +#if defined(UDR0) || defined(DOXYGEN) +const uint16_t MIN_2X_BAUD = F_CPU / (4 * (2 * 0XFFF + 1)) + 1; //------------------------------------------------------------------------------ -int MinimumSerial::available() { - return UCSR0A & (1 << RXC0) ? 1 : 0; -} +int MinimumSerial::available() { return UCSR0A & (1 << RXC0) ? 1 : 0; } //------------------------------------------------------------------------------ void MinimumSerial::begin(uint32_t baud) { uint16_t baud_setting; @@ -53,7 +50,8 @@ void MinimumSerial::begin(uint32_t baud) { } //------------------------------------------------------------------------------ void MinimumSerial::flush() { - while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {} + while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) { + } } //------------------------------------------------------------------------------ int MinimumSerial::read() { @@ -64,7 +62,8 @@ int MinimumSerial::read() { } //------------------------------------------------------------------------------ size_t MinimumSerial::write(uint8_t b) { - while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {} + while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) { + } UDR0 = b; return 1; } diff --git a/trunk/Arduino/libraries/SdFat/src/MinimumSerial.h b/trunk/Arduino/libraries/SdFat/src/MinimumSerial.h index e794c5b9..7e232a31 100644 --- a/trunk/Arduino/libraries/SdFat/src/MinimumSerial.h +++ b/trunk/Arduino/libraries/SdFat/src/MinimumSerial.h @@ -22,7 +22,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - /** +/** * \file * \brief Minimal AVR Serial driver. */ @@ -37,7 +37,7 @@ class MinimumSerial : public print_t { public: /** \return true for hardware serial */ - operator bool() {return true;} + operator bool() { return true; } /** * \return one if data is available. */ diff --git a/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.cpp b/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.cpp index 06412cf2..9d08a3cd 100644 --- a/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.cpp +++ b/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.cpp @@ -27,14 +27,11 @@ class Timeout { public: Timeout() {} - explicit Timeout(uint16_t ms) {set(ms);} - uint16_t millis16() {return millis();} - void set(uint16_t ms) { - m_endTime = ms + millis16(); - } - bool timedOut() { - return (int16_t)(m_endTime - millis16()) < 0; - } + explicit Timeout(uint16_t ms) { set(ms); } + uint16_t millis16() { return millis(); } + void set(uint16_t ms) { m_endTime = ms + millis16(); } + bool timedOut() { return (int16_t)(m_endTime - millis16()) < 0; } + private: uint16_t m_endTime; }; @@ -77,48 +74,44 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) { // uses the x^16,x^12,x^5,x^1 polynomial. #ifdef __AVR__ static const uint16_t crctab[] PROGMEM = { -#else // __AVR__ +#else // __AVR__ static const uint16_t crctab[] = { #endif // __AVR__ - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, + 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, + 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, + 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, + 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, + 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, + 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, + 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, + 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, + 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, + 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, + 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, + 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, + 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, + 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, + 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, + 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, + 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, + 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, + 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, + 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, + 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, + 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, + 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; static uint16_t CRC_CCITT(const uint8_t* data, size_t n) { uint16_t crc = 0; for (size_t i = 0; i < n; i++) { #ifdef __AVR__ crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0XFF]) ^ (crc << 8); -#else // __AVR__ +#else // __AVR__ crc = crctab[(crc >> 8 ^ data[i]) & 0XFF] ^ (crc << 8); #endif // __AVR__ } @@ -131,10 +124,9 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) { //------------------------------------------------------------------------------ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { Timeout timeout; - m_spiActive = false; - m_beginCalled = false; + // Restore state to creator. + initSharedSpiCard(); m_errorCode = SD_CARD_ERROR_NONE; - m_type = 0; m_csPin = spiConfig.csPin; #if SPI_DRIVER_SELECT >= 2 m_spiDriverPtr = spiConfig.spiPort; @@ -145,32 +137,28 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { #endif // SPI_DRIVER_SELECT sdCsInit(m_csPin); spiUnselect(); - spiSetSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ); + spiSetSckSpeed(1000UL * SD_MAX_INIT_RATE_KHZ); spiBegin(spiConfig); m_beginCalled = true; uint32_t arg; - m_state = IDLE_STATE; spiStart(); // must supply min of 74 clock cycles with CS high. spiUnselect(); for (uint8_t i = 0; i < 10; i++) { - spiSend(0XFF); + spiReceive(); } spiSelect(); - // command to go idle in SPI mode - for (uint8_t i = 1;; i++) { + timeout.set(SD_INIT_TIMEOUT); + while (true) { + // command to go idle in SPI mode if (cardCommand(CMD0, 0) == R1_IDLE_STATE) { break; } - if (i == SD_CMD0_RETRY) { + if (timeout.timedOut()) { error(SD_CARD_ERROR_CMD0); goto fail; } - // Force any active transfer to end for an already initialized card. - for (uint8_t j = 0; j < 0XFF; j++) { - spiSend(0XFF); - } } #if USE_SD_CRC if (cardCommand(CMD59, 1) != R1_IDLE_STATE) { @@ -179,21 +167,26 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { } #endif // USE_SD_CRC // check SD version - if (!(cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { - type(SD_CARD_TYPE_SD2); + while (true) { + if (cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND) { + type(SD_CARD_TYPE_SD1); + break; + } + // Skip first three bytes. for (uint8_t i = 0; i < 4; i++) { m_status = spiReceive(); } - if (m_status != 0XAA) { + if (m_status == 0XAA) { + type(SD_CARD_TYPE_SD2); + break; + } + if (timeout.timedOut()) { error(SD_CARD_ERROR_CMD8); goto fail; } - } else { - type(SD_CARD_TYPE_SD1); } // initialize card and send host supports SDHC if SD2 arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; - timeout.set(SD_INIT_TIMEOUT); while (cardAcmd(ACMD41, arg) != R1_READY_STATE) { // check for timeout if (timeout.timedOut()) { @@ -201,7 +194,6 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { goto fail; } } - // if SD2 read OCR register to check for SDHC card if (type() == SD_CARD_TYPE_SD2) { if (cardCommand(CMD58, 0)) { @@ -220,7 +212,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { spiSetSckSpeed(spiConfig.maxSck); return true; - fail: +fail: spiStop(); return false; } @@ -236,7 +228,7 @@ bool SharedSpiCard::cardCMD6(uint32_t arg, uint8_t* status) { spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -267,7 +259,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) { // send message spiSend(buf, 6); -#else // USE_SD_CRC +#else // USE_SD_CRC // send command spiSend(cmd | 0x40); @@ -285,7 +277,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) { spiReceive(); // there are 1-8 fill bytes before response. fill bytes should be 0XFF. - uint16_t n = 0; + uint8_t n = 0; do { m_status = spiReceive(); } while (m_status & 0X80 && ++n < 10); @@ -294,7 +286,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) { //------------------------------------------------------------------------------ void SharedSpiCard::end() { if (m_beginCalled) { - spiStop(); + syncDevice(); spiEnd(); m_beginCalled = false; } @@ -319,9 +311,8 @@ bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) { firstSector <<= 9; lastSector <<= 9; } - if (cardCommand(CMD32, firstSector) - || cardCommand(CMD33, lastSector) - || cardCommand(CMD38, 0)) { + if (cardCommand(CMD32, firstSector) || cardCommand(CMD33, lastSector) || + cardCommand(CMD38, 0)) { error(SD_CARD_ERROR_ERASE); goto fail; } @@ -332,7 +323,7 @@ bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) { spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -357,9 +348,7 @@ bool SharedSpiCard::isBusy() { return rtn; } //------------------------------------------------------------------------------ -bool SharedSpiCard::readData(uint8_t* dst) { - return readData(dst, 512); -} +bool SharedSpiCard::readData(uint8_t* dst) { return readData(dst, 512); } //------------------------------------------------------------------------------ bool SharedSpiCard::readData(uint8_t* dst, size_t count) { #if USE_SD_CRC @@ -391,14 +380,14 @@ bool SharedSpiCard::readData(uint8_t* dst, size_t count) { error(SD_CARD_ERROR_READ_CRC); goto fail; } -#else // USE_SD_CRC +#else // USE_SD_CRC // discard crc spiReceive(); spiReceive(); #endif // USE_SD_CRC return true; - fail: +fail: spiStop(); return false; } @@ -412,14 +401,14 @@ bool SharedSpiCard::readOCR(uint32_t* ocr) { for (uint8_t i = 0; i < 4; i++) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ p[3 - i] = spiReceive(); -#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ p[i] = spiReceive(); #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ } spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -437,7 +426,7 @@ bool SharedSpiCard::readRegister(uint8_t cmd, void* buf) { spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -454,7 +443,7 @@ bool SharedSpiCard::readSCR(scr_t* scr) { spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -474,7 +463,7 @@ bool SharedSpiCard::readSector(uint32_t sector, uint8_t* dst) { spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -489,7 +478,7 @@ bool SharedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) { } } return readStop(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -504,25 +493,25 @@ bool SharedSpiCard::readStart(uint32_t sector) { m_state = READ_STATE; return true; - fail: +fail: spiStop(); return false; } //------------------------------------------------------------------------------ -bool SharedSpiCard::readStatus(SdStatus* status) { - uint8_t* dst = reinterpret_cast(status); +bool SharedSpiCard::readSDS(sds_t* sds) { + uint8_t* dst = reinterpret_cast(sds); // retrun is R2 so read extra status byte. if (cardAcmd(ACMD13, 0) || spiReceive()) { error(SD_CARD_ERROR_ACMD13); goto fail; } - if (!readData(dst, 64)) { + if (!readData(dst, sizeof(sds_t))) { goto fail; } spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -536,7 +525,7 @@ bool SharedSpiCard::readStop() { spiStop(); return true; - fail: +fail: spiStop(); return false; } @@ -547,6 +536,7 @@ uint32_t SharedSpiCard::sectorCount() { } //------------------------------------------------------------------------------ void SharedSpiCard::spiStart() { + SPI_ASSERT_NOT_ACTIVE; if (!m_spiActive) { spiActivate(); m_spiActive = true; @@ -557,6 +547,7 @@ void SharedSpiCard::spiStart() { } //------------------------------------------------------------------------------ void SharedSpiCard::spiStop() { + SPI_ASSERT_ACTIVE; if (m_spiActive) { spiUnselect(); // Insure MISO goes to low Z. @@ -597,7 +588,7 @@ bool SharedSpiCard::writeData(const uint8_t* src) { } return true; - fail: +fail: spiStop(); return false; } @@ -606,7 +597,7 @@ bool SharedSpiCard::writeData(const uint8_t* src) { bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) { #if USE_SD_CRC uint16_t crc = CRC_CCITT(src, 512); -#else // USE_SD_CRC +#else // USE_SD_CRC uint16_t crc = 0XFFFF; #endif // USE_SD_CRC spiSend(token); @@ -621,7 +612,7 @@ bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) { } return true; - fail: +fail: spiStop(); return false; } @@ -655,13 +646,13 @@ bool SharedSpiCard::writeSector(uint32_t sector, const uint8_t* src) { spiStop(); return true; - fail: +fail: spiStop(); return false; } //------------------------------------------------------------------------------ -bool SharedSpiCard::writeSectors(uint32_t sector, - const uint8_t* src, size_t ns) { +bool SharedSpiCard::writeSectors(uint32_t sector, const uint8_t* src, + size_t ns) { if (!writeStart(sector)) { goto fail; } @@ -672,7 +663,7 @@ bool SharedSpiCard::writeSectors(uint32_t sector, } return writeStop(); - fail: +fail: spiStop(); return false; } @@ -689,7 +680,7 @@ bool SharedSpiCard::writeStart(uint32_t sector) { m_state = WRITE_STATE; return true; - fail: +fail: spiStop(); return false; } @@ -703,7 +694,7 @@ bool SharedSpiCard::writeStop() { m_state = IDLE_STATE; return true; - fail: +fail: error(SD_CARD_ERROR_STOP_TRAN); spiStop(); return false; @@ -721,8 +712,7 @@ bool DedicatedSpiCard::readSector(uint32_t sector, uint8_t* dst) { return readSectors(sector, dst, 1); } //------------------------------------------------------------------------------ -bool DedicatedSpiCard::readSectors( - uint32_t sector, uint8_t* dst, size_t ns) { +bool DedicatedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) { if (sdState() != READ_STATE || sector != m_curSector) { if (!readStart(sector)) { goto fail; @@ -737,7 +727,7 @@ bool DedicatedSpiCard::readSectors( m_curSector += ns; return m_dedicatedSpi ? true : readStop(); - fail: +fail: return false; } //------------------------------------------------------------------------------ @@ -756,8 +746,8 @@ bool DedicatedSpiCard::writeSector(uint32_t sector, const uint8_t* src) { return SharedSpiCard::writeSector(sector, src); } //------------------------------------------------------------------------------ -bool DedicatedSpiCard::writeSectors( - uint32_t sector, const uint8_t* src, size_t ns) { +bool DedicatedSpiCard::writeSectors(uint32_t sector, const uint8_t* src, + size_t ns) { if (sdState() != WRITE_STATE || m_curSector != sector) { if (!writeStart(sector)) { goto fail; diff --git a/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.h b/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.h index 784067ee..abaed59c 100644 --- a/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.h +++ b/trunk/Arduino/libraries/SdFat/src/SdCard/SdSpiCard.h @@ -24,25 +24,43 @@ */ /** * \file - * \brief SdSpiCard class for V2 SD/SDHC cards + * \brief Classes for SPI access to SD/SDHC cards. */ #ifndef SdSpiCard_h #define SdSpiCard_h #include + +#include "../SpiDriver/SdSpiDriver.h" #include "../common/SysCall.h" #include "SdCardInfo.h" #include "SdCardInterface.h" -#include "../SpiDriver/SdSpiDriver.h" /** Verify correct SPI active if non-zero. */ #define CHECK_SPI_ACTIVE 0 #if CHECK_SPI_ACTIVE /** Check SPI active. */ -#define SPI_ASSERT_ACTIVE {if (!m_spiActive) {\ - Serial.print(F("SPI_ASSERTACTIVE"));\ - Serial.println(__LINE__);}} +#define SPI_ASSERT_ACTIVE \ + { \ + if (!m_spiActive) { \ + Serial.print(F("SPI_ASSERT_ACTIVE")); \ + Serial.println(__LINE__); \ + while (true) \ + ; \ + } \ + } +#define SPI_ASSERT_NOT_ACTIVE \ + { \ + if (m_spiActive) { \ + Serial.print(F("SPI_ASSERT_NOT_ACTIVE")); \ + Serial.println(__LINE__); \ + while (true) \ + ; \ + } \ + } #else // CHECK_SPI_ACTIVE -/** Do not check SPI active. */ +/** Check for SPI active. */ #define SPI_ASSERT_ACTIVE +/** Check for SPI not active. */ +#define SPI_ASSERT_NOT_ACTIVE #endif // CHECK_SPI_ACTIVE //============================================================================== /** @@ -53,7 +71,7 @@ class SharedSpiCard : public SdCardInterface { #elif USE_BLOCK_DEVICE_INTERFACE class SharedSpiCard : public FsBlockDeviceInterface { -#else // HAS_SDIO_CLASS +#else // HAS_SDIO_CLASS class SharedSpiCard { #endif // HAS_SDIO_CLASS public: @@ -64,7 +82,7 @@ class SharedSpiCard { /** SD is in multi-sector write state. */ static const uint8_t WRITE_STATE = 2; /** Construct an instance of SharedSpiCard. */ - SharedSpiCard() {} + SharedSpiCard() { initSharedSpiCard(); } /** Initialize the SD card. * \param[in] spiConfig SPI card configuration. * \return true for success or false for failure. @@ -103,21 +121,18 @@ class SharedSpiCard { * \param[in] code value for error code. */ void error(uint8_t code) { -// (void)code; + // (void)code; m_errorCode = code; } /** - * \return code for the last error. See SdCardInfo.h for a list of error codes. + * \return code for the last error. See SdCardInfo.h for a list of error + * codes. */ - uint8_t errorCode() const { - return m_errorCode; - } + uint8_t errorCode() const { return m_errorCode; } /** \return error data for last error. */ - uint32_t errorData() const { - return m_status; - } + uint32_t errorData() const { return m_status; } /** \return false for shared class. */ - bool hasDedicatedSpi() {return false;} + bool hasDedicatedSpi() { return false; } /** * Check for busy. MISO low indicates the card is busy. * @@ -125,7 +140,7 @@ class SharedSpiCard { */ bool isBusy(); /** \return false, can't be in dedicated state. */ - bool isDedicatedSpi() {return false;} + bool isDedicatedSpi() { return false; } /** * Read a card's CID register. The CID contains card identification * information such as Manufacturer ID, Product name, Product serial @@ -135,9 +150,7 @@ class SharedSpiCard { * * \return true for success or false for failure. */ - bool readCID(cid_t* cid) { - return readRegister(CMD10, cid); - } + bool readCID(cid_t* cid) { return readRegister(CMD10, cid); } /** * Read a card's CSD register. The CSD contains Card-Specific Data that * provides information regarding access to the card's contents. @@ -146,9 +159,7 @@ class SharedSpiCard { * * \return true for success or false for failure. */ - bool readCSD(csd_t* csd) { - return readRegister(CMD9, csd); - } + bool readCSD(csd_t* csd) { return readRegister(CMD9, csd); } /** Read one data sector in a multiple sector read sequence * * \param[out] dst Pointer to the location for the data to be read. @@ -196,18 +207,18 @@ class SharedSpiCard { * \return true for success or false for failure. */ bool readStart(uint32_t sector); - /** Return the 64 byte card status + /** Return the 64 byte SD Status register. * \param[out] status location for 64 status bytes. * \return true for success or false for failure. */ - bool readStatus(SdStatus* status); + bool readSDS(sds_t* status); /** End a read multiple sectors sequence. * * \return true for success or false for failure. */ bool readStop(); /** \return SD multi-sector read/write state */ - uint8_t sdState() {return m_state;} + uint8_t sdState() { return m_state; } /** * Determine the size of an SD flash memory card. * @@ -237,9 +248,7 @@ class SharedSpiCard { /** Return the card type: SD V1, SD V2 or SDHC/SDXC * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC/SDXC. */ - uint8_t type() const { - return m_type; - } + uint8_t type() const { return m_type; } /** * Write a 512 byte sector to an SD card. * @@ -288,32 +297,18 @@ class SharedSpiCard { uint8_t cardCommand(uint8_t cmd, uint32_t arg); bool readData(uint8_t* dst, size_t count); bool readRegister(uint8_t cmd, void* buf); - void spiSelect() { - sdCsWrite(m_csPin, false); - } + void spiSelect() { sdCsWrite(m_csPin, false); } void spiStart(); void spiStop(); - void spiUnselect() { - sdCsWrite(m_csPin, true); - } - void type(uint8_t value) { - m_type = value; - } + void spiUnselect() { sdCsWrite(m_csPin, true); } + void type(uint8_t value) { m_type = value; } bool waitReady(uint16_t ms); bool writeData(uint8_t token, const uint8_t* src); #if SPI_DRIVER_SELECT < 2 - void spiActivate() { - m_spiDriver.activate(); - } - void spiBegin(SdSpiConfig spiConfig) { - m_spiDriver.begin(spiConfig); - } - void spiDeactivate() { - m_spiDriver.deactivate(); - } - void spiEnd() { - m_spiDriver.end(); - } + void spiActivate() { m_spiDriver.activate(); } + void spiBegin(SdSpiConfig spiConfig) { m_spiDriver.begin(spiConfig); } + void spiDeactivate() { m_spiDriver.deactivate(); } + void spiEnd() { m_spiDriver.end(); } uint8_t spiReceive() { SPI_ASSERT_ACTIVE; return m_spiDriver.receive(); @@ -330,23 +325,13 @@ class SharedSpiCard { SPI_ASSERT_ACTIVE; m_spiDriver.send(buf, n); } - void spiSetSckSpeed(uint32_t maxSck) { - m_spiDriver.setSckSpeed(maxSck); - } + void spiSetSckSpeed(uint32_t maxSck) { m_spiDriver.setSckSpeed(maxSck); } SdSpiDriver m_spiDriver; #else // SPI_DRIVER_SELECT < 2 - void spiActivate() { - m_spiDriverPtr->activate(); - } - void spiBegin(SdSpiConfig spiConfig) { - m_spiDriverPtr->begin(spiConfig); - } - void spiDeactivate() { - m_spiDriverPtr->deactivate(); - } - void spiEnd() { - m_spiDriverPtr->end(); - } + void spiActivate() { m_spiDriverPtr->activate(); } + void spiBegin(SdSpiConfig spiConfig) { m_spiDriverPtr->begin(spiConfig); } + void spiDeactivate() { m_spiDriverPtr->deactivate(); } + void spiEnd() { m_spiDriverPtr->end(); } uint8_t spiReceive() { SPI_ASSERT_ACTIVE; return m_spiDriverPtr->receive(); @@ -363,21 +348,27 @@ class SharedSpiCard { SPI_ASSERT_ACTIVE; m_spiDriverPtr->send(buf, n); } - void spiSetSckSpeed(uint32_t maxSck) { - m_spiDriverPtr->setSckSpeed(maxSck); - } + void spiSetSckSpeed(uint32_t maxSck) { m_spiDriverPtr->setSckSpeed(maxSck); } SdSpiDriver* m_spiDriverPtr; #endif // SPI_DRIVER_SELECT < 2 - bool m_beginCalled = false; + void initSharedSpiCard() { + m_beginCalled = false; + m_csPin = 0; + m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED; + m_spiActive = false; + m_state = IDLE_STATE; + m_status = 0; + m_type = 0; + } + bool m_beginCalled; SdCsPin_t m_csPin; - uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED; - bool m_spiActive; + uint8_t m_errorCode; + bool m_spiActive; uint8_t m_state; uint8_t m_status; - uint8_t m_type = 0; + uint8_t m_type; }; - //============================================================================== /** * \class DedicatedSpiCard @@ -386,16 +377,16 @@ class SharedSpiCard { class DedicatedSpiCard : public SharedSpiCard { public: /** Construct an instance of DedicatedSpiCard. */ - DedicatedSpiCard() {} + DedicatedSpiCard() = default; /** Initialize the SD card. * \param[in] spiConfig SPI card configuration. * \return true for success or false for failure. */ bool begin(SdSpiConfig spiConfig); /** \return true, can be in dedicaded state. */ - bool hasDedicatedSpi() {return true;} + bool hasDedicatedSpi() { return true; } /** \return true if in dedicated SPI state. */ - bool isDedicatedSpi() {return m_dedicatedSpi;} + bool isDedicatedSpi() { return m_dedicatedSpi; } /** * Read a 512 byte sector from an SD card. * @@ -437,7 +428,7 @@ class DedicatedSpiCard : public SharedSpiCard { bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns); private: - uint32_t m_curSector; + uint32_t m_curSector = 0; bool m_dedicatedSpi = false; }; //============================================================================== diff --git a/trunk/Arduino/libraries/SdFat/src/SdCard/SdioCard.h b/trunk/Arduino/libraries/SdFat/src/SdCard/SdioCard.h index ffedb46c..55859d79 100644 --- a/trunk/Arduino/libraries/SdFat/src/SdCard/SdioCard.h +++ b/trunk/Arduino/libraries/SdFat/src/SdCard/SdioCard.h @@ -22,12 +22,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +/** + * \file + * \brief Classes for SDIO cards. + */ #ifndef SdioCard_h #define SdioCard_h #include "../common/SysCall.h" #include "SdCardInterface.h" - +/** Use programmed I/O with FIFO. */ #define FIFO_SDIO 0 +/** Use programmed I/O with DMA. */ #define DMA_SDIO 1 /** * \class SdioConfig @@ -42,9 +47,10 @@ class SdioConfig { */ explicit SdioConfig(uint8_t opt) : m_options(opt) {} /** \return SDIO card options. */ - uint8_t options() {return m_options;} + uint8_t options() { return m_options; } /** \return true if DMA_SDIO. */ - bool useDma() {return m_options & DMA_SDIO;} + bool useDma() { return m_options & DMA_SDIO; } + private: uint8_t m_options = FIFO_SDIO; }; @@ -73,7 +79,7 @@ class SdioCard : public SdCardInterface { void end() {} #ifndef DOXYGEN_SHOULD_SKIP_THIS - uint32_t __attribute__((error("use sectorCount()"))) cardSize(); + uint32_t __attribute__((error("use sectorCount()"))) cardSize(); #endif // DOXYGEN_SHOULD_SKIP_THIS /** Erase a range of sectors. * @@ -89,7 +95,8 @@ class SdioCard : public SdCardInterface { */ bool erase(uint32_t firstSector, uint32_t lastSector); /** - * \return code for the last error. See SdCardInfo.h for a list of error codes. + * \return code for the last error. See SdCardInfo.h for a list of error + * codes. */ uint8_t errorCode() const; /** \return error data for last error. */ @@ -158,7 +165,12 @@ class SdioCard : public SdCardInterface { * \param[out] scr Value of SCR register. * \return true for success or false for failure. */ - bool readSCR(scr_t *scr); + bool readSCR(scr_t* scr); + /** Return the 64 byte SD Status register. + * \param[out] sds location for 64 status bytes. + * \return true for success or false for failure. + */ + bool readSDS(sds_t* sds); /** Start a read multiple sectors sequence. * * \param[in] sector Address of first sector in sequence. @@ -186,7 +198,7 @@ class SdioCard : public SdCardInterface { bool readStop(); /** \return SDIO card status. */ uint32_t status(); - /** + /** * Determine the size of an SD flash memory card. * * \return The number of 512 byte data sectors in the card diff --git a/trunk/Arduino/libraries/SdFat/src/SdCard/SdioTeensy.cpp b/trunk/Arduino/libraries/SdFat/src/SdCard/SdioTeensy.cpp index 1333dbfe..01818236 100644 --- a/trunk/Arduino/libraries/SdFat/src/SdCard/SdioTeensy.cpp +++ b/trunk/Arduino/libraries/SdFat/src/SdCard/SdioTeensy.cpp @@ -24,6 +24,7 @@ */ #if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) #include "SdioTeensy.h" + #include "SdCardInfo.h" #include "SdioCard.h" //============================================================================== @@ -36,39 +37,34 @@ const uint32_t CMD8_RETRIES = 3; const uint32_t BUSY_TIMEOUT_MICROS = 1000000; //============================================================================== const uint32_t SDHC_IRQSTATEN_MASK = - SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN | - SDHC_IRQSTATEN_DEBESEN | SDHC_IRQSTATEN_DCESEN | - SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN | - SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN | - SDHC_IRQSTATEN_CTOESEN | SDHC_IRQSTATEN_DINTSEN | - SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN; + SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN | SDHC_IRQSTATEN_DEBESEN | + SDHC_IRQSTATEN_DCESEN | SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN | + SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN | SDHC_IRQSTATEN_CTOESEN | + SDHC_IRQSTATEN_DINTSEN | SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN; const uint32_t SDHC_IRQSTAT_CMD_ERROR = - SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE | - SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CTOE; + SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE | SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CTOE; -const uint32_t SDHC_IRQSTAT_DATA_ERROR = - SDHC_IRQSTAT_AC12E | SDHC_IRQSTAT_DEBE | - SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE; +const uint32_t SDHC_IRQSTAT_DATA_ERROR = SDHC_IRQSTAT_AC12E | + SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE | + SDHC_IRQSTAT_DTOE; const uint32_t SDHC_IRQSTAT_ERROR = - SDHC_IRQSTAT_DMAE | SDHC_IRQSTAT_CMD_ERROR | - SDHC_IRQSTAT_DATA_ERROR; + SDHC_IRQSTAT_DMAE | SDHC_IRQSTAT_CMD_ERROR | SDHC_IRQSTAT_DATA_ERROR; const uint32_t SDHC_IRQSIGEN_MASK = - SDHC_IRQSIGEN_DMAEIEN | SDHC_IRQSIGEN_AC12EIEN | - SDHC_IRQSIGEN_DEBEIEN | SDHC_IRQSIGEN_DCEIEN | - SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN | - SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN | - SDHC_IRQSIGEN_CTOEIEN | SDHC_IRQSIGEN_TCIEN; + SDHC_IRQSIGEN_DMAEIEN | SDHC_IRQSIGEN_AC12EIEN | SDHC_IRQSIGEN_DEBEIEN | + SDHC_IRQSIGEN_DCEIEN | SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN | + SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN | SDHC_IRQSIGEN_CTOEIEN | + SDHC_IRQSIGEN_TCIEN; //============================================================================== const uint32_t CMD_RESP_NONE = SDHC_XFERTYP_RSPTYP(0); -const uint32_t CMD_RESP_R1 = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | - SDHC_XFERTYP_RSPTYP(2); +const uint32_t CMD_RESP_R1 = + SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(2); -const uint32_t CMD_RESP_R1b = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | - SDHC_XFERTYP_RSPTYP(3); +const uint32_t CMD_RESP_R1b = + SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(3); const uint32_t CMD_RESP_R2 = SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(1); @@ -86,26 +82,23 @@ const uint32_t DATA_READ_DMA = DATA_READ | SDHC_XFERTYP_DMAEN; const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN; -const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_XFERTYP_MSBSEL | - SDHC_XFERTYP_BCEN; +const uint32_t DATA_READ_MULTI_PGM = + DATA_READ | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_BCEN; const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DMAEN; const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN; -const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_MSBSEL | - SDHC_XFERTYP_BCEN; +const uint32_t DATA_WRITE_MULTI_PGM = + SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_BCEN; #elif defined(__IMXRT1062__) // Use low bits for SDHC_MIX_CTRL since bits 15-0 of SDHC_XFERTYP are reserved. -const uint32_t SDHC_MIX_CTRL_MASK = SDHC_MIX_CTRL_DMAEN | SDHC_MIX_CTRL_BCEN | - SDHC_MIX_CTRL_AC12EN | - SDHC_MIX_CTRL_DDR_EN | - SDHC_MIX_CTRL_DTDSEL | - SDHC_MIX_CTRL_MSBSEL | - SDHC_MIX_CTRL_NIBBLE_POS | - SDHC_MIX_CTRL_AC23EN; +const uint32_t SDHC_MIX_CTRL_MASK = + SDHC_MIX_CTRL_DMAEN | SDHC_MIX_CTRL_BCEN | SDHC_MIX_CTRL_AC12EN | + SDHC_MIX_CTRL_DDR_EN | SDHC_MIX_CTRL_DTDSEL | SDHC_MIX_CTRL_MSBSEL | + SDHC_MIX_CTRL_NIBBLE_POS | SDHC_MIX_CTRL_AC23EN; const uint32_t DATA_READ = SDHC_MIX_CTRL_DTDSEL | SDHC_XFERTYP_DPSEL; @@ -116,7 +109,6 @@ const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_MIX_CTRL_MSBSEL | const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_MIX_CTRL_MSBSEL; - const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_DMAEN; const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_MIX_CTRL_MSBSEL | @@ -128,10 +120,13 @@ const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_MSBSEL; const uint32_t ACMD6_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD6) | CMD_RESP_R1; +const uint32_t ACMD13_XFERTYP = + SDHC_XFERTYP_CMDINX(ACMD13) | CMD_RESP_R1 | DATA_READ_DMA; + const uint32_t ACMD41_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD41) | CMD_RESP_R3; -const uint32_t ACMD51_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD51) | CMD_RESP_R1 | - DATA_READ_DMA; +const uint32_t ACMD51_XFERTYP = + SDHC_XFERTYP_CMDINX(ACMD51) | CMD_RESP_R1 | DATA_READ_DMA; const uint32_t CMD0_XFERTYP = SDHC_XFERTYP_CMDINX(CMD0) | CMD_RESP_NONE; @@ -139,8 +134,8 @@ const uint32_t CMD2_XFERTYP = SDHC_XFERTYP_CMDINX(CMD2) | CMD_RESP_R2; const uint32_t CMD3_XFERTYP = SDHC_XFERTYP_CMDINX(CMD3) | CMD_RESP_R6; -const uint32_t CMD6_XFERTYP = SDHC_XFERTYP_CMDINX(CMD6) | CMD_RESP_R1 | - DATA_READ_DMA; +const uint32_t CMD6_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD6) | CMD_RESP_R1 | DATA_READ_DMA; const uint32_t CMD7_XFERTYP = SDHC_XFERTYP_CMDINX(CMD7) | CMD_RESP_R1b; @@ -152,28 +147,28 @@ const uint32_t CMD10_XFERTYP = SDHC_XFERTYP_CMDINX(CMD10) | CMD_RESP_R2; const uint32_t CMD11_XFERTYP = SDHC_XFERTYP_CMDINX(CMD11) | CMD_RESP_R1; -const uint32_t CMD12_XFERTYP = SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b | - SDHC_XFERTYP_CMDTYP(3); +const uint32_t CMD12_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b | SDHC_XFERTYP_CMDTYP(3); const uint32_t CMD13_XFERTYP = SDHC_XFERTYP_CMDINX(CMD13) | CMD_RESP_R1; -const uint32_t CMD17_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD17) | CMD_RESP_R1 | - DATA_READ_DMA; +const uint32_t CMD17_DMA_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD17) | CMD_RESP_R1 | DATA_READ_DMA; -const uint32_t CMD18_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | - DATA_READ_MULTI_DMA; +const uint32_t CMD18_DMA_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | DATA_READ_MULTI_DMA; -const uint32_t CMD18_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | - DATA_READ_MULTI_PGM; +const uint32_t CMD18_PGM_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | DATA_READ_MULTI_PGM; -const uint32_t CMD24_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD24) | CMD_RESP_R1 | - DATA_WRITE_DMA; +const uint32_t CMD24_DMA_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD24) | CMD_RESP_R1 | DATA_WRITE_DMA; -const uint32_t CMD25_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | - DATA_WRITE_MULTI_DMA; +const uint32_t CMD25_DMA_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | DATA_WRITE_MULTI_DMA; -const uint32_t CMD25_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | - DATA_WRITE_MULTI_PGM; +const uint32_t CMD25_PGM_XFERTYP = + SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | DATA_WRITE_MULTI_PGM; const uint32_t CMD32_XFERTYP = SDHC_XFERTYP_CMDINX(CMD32) | CMD_RESP_R1; @@ -212,12 +207,20 @@ static uint32_t m_ocr; static cid_t m_cid; static csd_t m_csd; static scr_t m_scr; +static sds_t m_sds; //============================================================================== -#define DBG_TRACE Serial.print("TRACE."); Serial.println(__LINE__); delay(200); +#define DBG_TRACE \ + Serial.print("TRACE."); \ + Serial.println(__LINE__); \ + delay(200); #define USE_DEBUG_MODE 0 #if USE_DEBUG_MODE -#define DBG_IRQSTAT() if (SDHC_IRQSTAT) {Serial.print(__LINE__);\ - Serial.print(" IRQSTAT "); Serial.println(SDHC_IRQSTAT, HEX);} +#define DBG_IRQSTAT() \ + if (SDHC_IRQSTAT) { \ + Serial.print(__LINE__); \ + Serial.print(" IRQSTAT "); \ + Serial.println(SDHC_IRQSTAT, HEX); \ + } static void printRegs(uint32_t line) { uint32_t blkattr = SDHC_BLKATTR; uint32_t xfertyp = SDHC_XFERTYP; @@ -234,36 +237,68 @@ static void printRegs(uint32_t line) { Serial.print(xfertyp >> 24); Serial.print(" TYP"); Serial.print((xfertyp >> 2) & 3); - if (xfertyp & SDHC_XFERTYP_DPSEL) {Serial.print(" DPSEL");} + if (xfertyp & SDHC_XFERTYP_DPSEL) { + Serial.print(" DPSEL"); + } Serial.println(); Serial.print("PRSSTAT "); Serial.print(prsstat, HEX); - if (prsstat & SDHC_PRSSTAT_BREN) {Serial.print(" BREN");} - if (prsstat & SDHC_PRSSTAT_BWEN) {Serial.print(" BWEN");} - if (prsstat & SDHC_PRSSTAT_RTA) {Serial.print(" RTA");} - if (prsstat & SDHC_PRSSTAT_WTA) {Serial.print(" WTA");} - if (prsstat & SDHC_PRSSTAT_SDOFF) {Serial.print(" SDOFF");} - if (prsstat & SDHC_PRSSTAT_PEROFF) {Serial.print(" PEROFF");} - if (prsstat & SDHC_PRSSTAT_HCKOFF) {Serial.print(" HCKOFF");} - if (prsstat & SDHC_PRSSTAT_IPGOFF) {Serial.print(" IPGOFF");} - if (prsstat & SDHC_PRSSTAT_SDSTB) {Serial.print(" SDSTB");} - if (prsstat & SDHC_PRSSTAT_DLA) {Serial.print(" DLA");} - if (prsstat & SDHC_PRSSTAT_CDIHB) {Serial.print(" CDIHB");} - if (prsstat & SDHC_PRSSTAT_CIHB) {Serial.print(" CIHB");} + if (prsstat & SDHC_PRSSTAT_BREN) { + Serial.print(" BREN"); + } + if (prsstat & SDHC_PRSSTAT_BWEN) { + Serial.print(" BWEN"); + } + if (prsstat & SDHC_PRSSTAT_RTA) { + Serial.print(" RTA"); + } + if (prsstat & SDHC_PRSSTAT_WTA) { + Serial.print(" WTA"); + } + if (prsstat & SDHC_PRSSTAT_SDOFF) { + Serial.print(" SDOFF"); + } + if (prsstat & SDHC_PRSSTAT_PEROFF) { + Serial.print(" PEROFF"); + } + if (prsstat & SDHC_PRSSTAT_HCKOFF) { + Serial.print(" HCKOFF"); + } + if (prsstat & SDHC_PRSSTAT_IPGOFF) { + Serial.print(" IPGOFF"); + } + if (prsstat & SDHC_PRSSTAT_SDSTB) { + Serial.print(" SDSTB"); + } + if (prsstat & SDHC_PRSSTAT_DLA) { + Serial.print(" DLA"); + } + if (prsstat & SDHC_PRSSTAT_CDIHB) { + Serial.print(" CDIHB"); + } + if (prsstat & SDHC_PRSSTAT_CIHB) { + Serial.print(" CIHB"); + } Serial.println(); Serial.print("PROCTL "); Serial.print(proctl, HEX); if (proctl & SDHC_PROCTL_SABGREQ) Serial.print(" SABGREQ"); Serial.print(" EMODE"); - Serial.print((proctl >>4) & 3); + Serial.print((proctl >> 4) & 3); Serial.print(" DWT"); - Serial.print((proctl >>1) & 3); + Serial.print((proctl >> 1) & 3); Serial.println(); Serial.print("IRQSTAT "); Serial.print(irqstat, HEX); - if (irqstat & SDHC_IRQSTAT_BGE) {Serial.print(" BGE");} - if (irqstat & SDHC_IRQSTAT_TC) {Serial.print(" TC");} - if (irqstat & SDHC_IRQSTAT_CC) {Serial.print(" CC");} + if (irqstat & SDHC_IRQSTAT_BGE) { + Serial.print(" BGE"); + } + if (irqstat & SDHC_IRQSTAT_TC) { + Serial.print(" TC"); + } + if (irqstat & SDHC_IRQSTAT_CC) { + Serial.print(" CC"); + } Serial.print("\nm_irqstat "); Serial.println(m_irqstat, HEX); } @@ -298,12 +333,12 @@ static void sdIrs() { //------------------------------------------------------------------------------ static void enableGPIO(bool enable) { const uint32_t PORT_CLK = PORT_PCR_MUX(4) | PORT_PCR_DSE; - const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS; + const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS; const uint32_t PORT_PUP = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; PORTE_PCR0 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D1 PORTE_PCR1 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D0 - PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK + PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK PORTE_PCR3 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_CMD PORTE_PCR4 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D3 PORTE_PCR5 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D2 @@ -317,7 +352,7 @@ static void initClock() { // Enable SDHC clock. SIM_SCGC3 |= SIM_SCGC3_SDHC; } -static uint32_t baseClock() { return F_CPU;} +static uint32_t baseClock() { return F_CPU; } #elif defined(__IMXRT1062__) //------------------------------------------------------------------------------ @@ -335,13 +370,13 @@ static void enableGPIO(bool enable) { const uint32_t CLOCK_MASK = IOMUXC_SW_PAD_CTL_PAD_PKE | #if defined(ARDUINO_TEENSY41) IOMUXC_SW_PAD_CTL_PAD_DSE(7) | -#else // defined(ARDUINO_TEENSY41) +#else // defined(ARDUINO_TEENSY41) IOMUXC_SW_PAD_CTL_PAD_DSE(4) | ///// WHG #endif // defined(ARDUINO_TEENSY41) IOMUXC_SW_PAD_CTL_PAD_SPEED(2); - const uint32_t DATA_MASK = CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE | - IOMUXC_SW_PAD_CTL_PAD_PUS(1); + const uint32_t DATA_MASK = + CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE | IOMUXC_SW_PAD_CTL_PAD_PUS(1); if (enable) { gpioMux(0); IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_04 = DATA_MASK; // DAT2 @@ -365,20 +400,20 @@ static void initClock() { /* Enable USDHC clock. */ CCM_CCGR6 |= CCM_CCGR6_USDHC1(CCM_CCGR_ON); CCM_CSCDR1 &= ~(CCM_CSCDR1_USDHC1_CLK_PODF_MASK); - CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL; // PLL2PFD0 -// CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7 WHG + CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL; // PLL2PFD0 + // CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7 WHG CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((1)); } //------------------------------------------------------------------------------ static uint32_t baseClock() { uint32_t divider = ((CCM_CSCDR1 >> 11) & 0x7) + 1; - return (528000000U * 3)/((CCM_ANALOG_PFD_528 & 0x3F)/6)/divider; + return (528000000U * 3) / ((CCM_ANALOG_PFD_528 & 0x3F) / 6) / divider; } #endif // defined(__MK64FX512__) || defined(__MK66FX1M0__) //============================================================================== // Static functions. static bool cardAcmd(uint32_t rca, uint32_t xfertyp, uint32_t arg) { - return cardCommand(CMD55_XFERTYP, rca) && cardCommand (xfertyp, arg); + return cardCommand(CMD55_XFERTYP, rca) && cardCommand(xfertyp, arg); } //------------------------------------------------------------------------------ static bool cardCommand(uint32_t xfertyp, uint32_t arg) { @@ -402,8 +437,25 @@ static bool cardCommand(uint32_t xfertyp, uint32_t arg) { m_irqstat = SDHC_IRQSTAT; SDHC_IRQSTAT = m_irqstat; - return (m_irqstat & SDHC_IRQSTAT_CC) && - !(m_irqstat & SDHC_IRQSTAT_CMD_ERROR); + return (m_irqstat & SDHC_IRQSTAT_CC) && !(m_irqstat & SDHC_IRQSTAT_CMD_ERROR); +} +//------------------------------------------------------------------------------ +static bool cardACMD13(sds_t* scr) { + // ACMD13 returns 64 bytes. + if (waitTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + enableDmaIrs(); + SDHC_DSADDR = (uint32_t)scr; + SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64); + SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK; + if (!cardAcmd(m_rca, ACMD13_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_ACMD13); + } + if (!waitDmaStatus()) { + return sdError(SD_CARD_ERROR_DMA); + } + return true; } //------------------------------------------------------------------------------ static bool cardACMD51(scr_t* scr) { @@ -412,7 +464,7 @@ static bool cardACMD51(scr_t* scr) { return sdError(SD_CARD_ERROR_CMD13); } enableDmaIrs(); - SDHC_DSADDR = (uint32_t)scr; + SDHC_DSADDR = (uint32_t)scr; SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(8); SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK; if (!cardAcmd(m_rca, ACMD51_XFERTYP, 0)) { @@ -435,7 +487,7 @@ static void initSDHC() { // Disable GPIO clock. enableGPIO(false); -#if defined (__IMXRT1062__) +#if defined(__IMXRT1062__) SDHC_MIX_CTRL |= 0x80000000; #endif // (__IMXRT1062__) @@ -454,7 +506,7 @@ static void initSDHC() { SDHC_IRQSTATEN = SDHC_IRQSTATEN_MASK; attachInterruptVector(IRQ_SDHC, sdIrs); - NVIC_SET_PRIORITY(IRQ_SDHC, 6*16); + NVIC_SET_PRIORITY(IRQ_SDHC, 6 * 16); NVIC_ENABLE_IRQ(IRQ_SDHC); // Send 80 clocks to card. @@ -475,32 +527,22 @@ static bool isBusyCommandComplete() { return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_CC | SDHC_IRQSTAT_CMD_ERROR)); } //------------------------------------------------------------------------------ -static bool isBusyCommandInhibit() { - return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB; -} +static bool isBusyCommandInhibit() { return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB; } //------------------------------------------------------------------------------ -static bool isBusyDat() { - return SDHC_PRSSTAT & (1 << 24) ? false : true; -} +static bool isBusyDat() { return SDHC_PRSSTAT & (1 << 24) ? false : true; } //------------------------------------------------------------------------------ -static bool isBusyDMA() { - return m_dmaBusy; -} +static bool isBusyDMA() { return m_dmaBusy; } //------------------------------------------------------------------------------ -static bool isBusyFifoRead() { - return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN); -} +static bool isBusyFifoRead() { return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN); } //------------------------------------------------------------------------------ -static bool isBusyFifoWrite() { - return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN); -} +static bool isBusyFifoWrite() { return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN); } //------------------------------------------------------------------------------ static bool isBusyTransferComplete() { return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_ERROR)); } //------------------------------------------------------------------------------ -static bool rdWrSectors(uint32_t xfertyp, - uint32_t sector, uint8_t* buf, size_t n) { +static bool rdWrSectors(uint32_t xfertyp, uint32_t sector, uint8_t* buf, + size_t n) { if ((3 & (uint32_t)buf) || n == 0) { return sdError(SD_CARD_ERROR_DMA); } @@ -508,10 +550,10 @@ static bool rdWrSectors(uint32_t xfertyp, return sdError(SD_CARD_ERROR_CMD13); } enableDmaIrs(); - SDHC_DSADDR = (uint32_t)buf; + SDHC_DSADDR = (uint32_t)buf; SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(n) | SDHC_BLKATTR_BLKSIZE(512); SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK; - if (!cardCommand(xfertyp, m_highCapacity ? sector : 512*sector)) { + if (!cardCommand(xfertyp, m_highCapacity ? sector : 512 * sector)) { return false; } return waitDmaStatus(); @@ -525,7 +567,7 @@ static bool readReg16(uint32_t xfertyp, void* data) { } uint32_t sr[] = {SDHC_CMDRSP0, SDHC_CMDRSP1, SDHC_CMDRSP2, SDHC_CMDRSP3}; for (int i = 0; i < 15; i++) { - d[14 - i] = sr[i/4] >> 8*(i%4); + d[14 - i] = sr[i / 4] >> 8 * (i % 4); } d[15] = 0; return true; @@ -536,16 +578,17 @@ static void setSdclk(uint32_t kHzMax) { const uint32_t SDCLKFS_LIMIT = 0X100; uint32_t dvs = 1; uint32_t sdclkfs = 1; - uint32_t maxSdclk = 1000*kHzMax; + uint32_t maxSdclk = 1000 * kHzMax; uint32_t base = baseClock(); - while ((base/(sdclkfs*DVS_LIMIT) > maxSdclk) && (sdclkfs < SDCLKFS_LIMIT)) { + while ((base / (sdclkfs * DVS_LIMIT) > maxSdclk) && + (sdclkfs < SDCLKFS_LIMIT)) { sdclkfs <<= 1; } - while ((base/(sdclkfs*dvs) > maxSdclk) && (dvs < DVS_LIMIT)) { + while ((base / (sdclkfs * dvs) > maxSdclk) && (dvs < DVS_LIMIT)) { dvs++; } - m_sdClkKhz = base/(1000*sdclkfs*dvs); + m_sdClkKhz = base / (1000 * sdclkfs * dvs); sdclkfs >>= 1; dvs--; #if defined(__MK64FX512__) || defined(__MK66FX1M0__) @@ -554,11 +597,12 @@ static void setSdclk(uint32_t kHzMax) { #endif // defined(__MK64FX512__) || defined(__MK66FX1M0__) // Change dividers. - uint32_t sysctl = SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK - | SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK); + uint32_t sysctl = + SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK | SDHC_SYSCTL_DVS_MASK | + SDHC_SYSCTL_SDCLKFS_MASK); - SDHC_SYSCTL = sysctl | SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_DVS(dvs) - | SDHC_SYSCTL_SDCLKFS(sdclkfs); + SDHC_SYSCTL = sysctl | SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_DVS(dvs) | + SDHC_SYSCTL_SDCLKFS(sdclkfs); // Wait until the SDHC clock is stable. while (!(SDHC_PRSSTAT & SDHC_PRSSTAT_SDSTB)) { @@ -667,14 +711,15 @@ bool SdioCard::begin(SdioConfig sdioConfig) { break; } SDHC_SYSCTL |= SDHC_SYSCTL_RSTA; - while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) {} + while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) { + } } // Must support 3.2-3.4 Volts arg = m_version2 ? 0X40300000 : 0x00300000; int m = micros(); do { if (!cardAcmd(0, ACMD41_XFERTYP, arg) || - ((micros() - m) > BUSY_TIMEOUT_MICROS)) { + ((micros() - m) > BUSY_TIMEOUT_MICROS)) { return sdError(SD_CARD_ERROR_ACMD41); } } while ((SDHC_CMDRSP0 & 0x80000000) == 0); @@ -713,11 +758,13 @@ bool SdioCard::begin(SdioConfig sdioConfig) { if (!cardACMD51(&m_scr)) { return false; } + if (!cardACMD13(&m_sds)) { + return false; + } // Determine if High Speed mode is supported and set frequency. // Check status[16] for error 0XF or status[16] for new mode 0X1. uint8_t status[64]; - if (m_scr.sdSpec() > 0 && - cardCMD6(0X00FFFFFF, status) && (2 & status[13]) && + if (m_scr.sdSpec() > 0 && cardCMD6(0X00FFFFFF, status) && (2 & status[13]) && cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) { kHzSdClk = 50000; } else { @@ -741,7 +788,7 @@ bool SdioCard::cardCMD6(uint32_t arg, uint8_t* status) { return sdError(SD_CARD_ERROR_CMD13); } enableDmaIrs(); - SDHC_DSADDR = (uint32_t)status; + SDHC_DSADDR = (uint32_t)status; SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64); SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK; if (!cardCommand(CMD6_XFERTYP, arg)) { @@ -774,7 +821,7 @@ bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) { return sdError(SD_CARD_ERROR_CMD32); } if (!cardCommand(CMD33_XFERTYP, lastSector)) { - return sdError(SD_CARD_ERROR_CMD33); + return sdError(SD_CARD_ERROR_CMD33); } if (!cardCommand(CMD38_XFERTYP, 0)) { return sdError(SD_CARD_ERROR_CMD38); @@ -785,17 +832,11 @@ bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) { return true; } //------------------------------------------------------------------------------ -uint8_t SdioCard::errorCode() const { - return m_errorCode; -} +uint8_t SdioCard::errorCode() const { return m_errorCode; } //------------------------------------------------------------------------------ -uint32_t SdioCard::errorData() const { - return m_irqstat; -} +uint32_t SdioCard::errorData() const { return m_irqstat; } //------------------------------------------------------------------------------ -uint32_t SdioCard::errorLine() const { - return m_errorLine; -} +uint32_t SdioCard::errorLine() const { return m_errorLine; } //------------------------------------------------------------------------------ bool SdioCard::isBusy() { if (m_sdioConfig.useDma()) { @@ -812,7 +853,7 @@ bool SdioCard::isBusy() { m_transferActive = false; stopTransmission(false); return true; -#else // defined(__MK64FX512__) || defined(__MK66FX1M0__) +#else // defined(__MK64FX512__) || defined(__MK66FX1M0__) return false; #endif // defined(__MK64FX512__) || defined(__MK66FX1M0__) } @@ -821,17 +862,15 @@ bool SdioCard::isBusy() { } } //------------------------------------------------------------------------------ -uint32_t SdioCard::kHzSdClk() { - return m_sdClkKhz; -} +uint32_t SdioCard::kHzSdClk() { return m_sdClkKhz; } //------------------------------------------------------------------------------ bool SdioCard::readCID(cid_t* cid) { - memcpy(cid, &m_cid, 16); + memcpy(cid, &m_cid, sizeof(cid_t)); return true; } //------------------------------------------------------------------------------ bool SdioCard::readCSD(csd_t* csd) { - memcpy(csd, &m_csd, 16); + memcpy(csd, &m_csd, sizeof(csd_t)); return true; } //------------------------------------------------------------------------------ @@ -849,7 +888,7 @@ bool SdioCard::readData(uint8_t* dst) { if (waitTimeout(isBusyFifoRead)) { return sdError(SD_CARD_ERROR_READ_FIFO); } - for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) { + for (uint32_t iw = 0; iw < 512 / (4 * FIFO_WML); iw++) { while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BREN)) { } for (uint32_t i = 0; i < FIFO_WML; i++) { @@ -871,7 +910,12 @@ bool SdioCard::readOCR(uint32_t* ocr) { } //------------------------------------------------------------------------------ bool SdioCard::readSCR(scr_t* scr) { - memcpy(scr, &m_scr, 8); + memcpy(scr, &m_scr, sizeof(scr_t)); + return true; +} +//------------------------------------------------------------------------------ +bool SdioCard::readSDS(sds_t* sds) { + memcpy(sds, &m_sds, sizeof(sds_t)); return true; } //------------------------------------------------------------------------------ @@ -931,7 +975,7 @@ bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n) { } } else { for (size_t i = 0; i < n; i++) { - if (!readSector(sector + i, dst + i*512UL)) { + if (!readSector(sector + i, dst + i * 512UL)) { return false; } } @@ -949,28 +993,22 @@ bool SdioCard::readStart(uint32_t sector) { #if defined(__IMXRT1062__) // Infinite transfer. SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512); -#else // defined(__IMXRT1062__) +#else // defined(__IMXRT1062__) // Errata - can't do infinite transfer. SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(MAX_BLKCNT) | SDHC_BLKATTR_BLKSIZE(512); #endif // defined(__IMXRT1062__) - if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) { + if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? sector : 512 * sector)) { return sdError(SD_CARD_ERROR_CMD18); } return true; } //------------------------------------------------------------------------------ -bool SdioCard::readStop() { - return transferStop(); -} +bool SdioCard::readStop() { return transferStop(); } //------------------------------------------------------------------------------ -uint32_t SdioCard::sectorCount() { - return m_csd.capacity(); -} +uint32_t SdioCard::sectorCount() { return m_csd.capacity(); } //------------------------------------------------------------------------------ -uint32_t SdioCard::status() { - return statusCMD13(); -} +uint32_t SdioCard::status() { return statusCMD13(); } //------------------------------------------------------------------------------ bool SdioCard::stopTransmission(bool blocking) { m_curState = IDLE_STATE; @@ -998,8 +1036,8 @@ bool SdioCard::syncDevice() { } //------------------------------------------------------------------------------ uint8_t SdioCard::type() const { - return m_version2 ? m_highCapacity ? - SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 : SD_CARD_TYPE_SD1; + return m_version2 ? m_highCapacity ? SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 + : SD_CARD_TYPE_SD1; } //------------------------------------------------------------------------------ bool SdioCard::writeData(const uint8_t* src) { @@ -1016,7 +1054,7 @@ bool SdioCard::writeData(const uint8_t* src) { if (waitTimeout(isBusyFifoWrite)) { return sdError(SD_CARD_ERROR_WRITE_FIFO); } - for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) { + for (uint32_t iw = 0; iw < 512 / (4 * FIFO_WML); iw++) { while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN)) { } for (uint32_t i = 0; i < FIFO_WML; i++) { @@ -1057,7 +1095,7 @@ bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) { if (!syncDevice()) { return false; } - if (!writeStart(sector )) { + if (!writeStart(sector)) { return false; } m_curSector = sector; @@ -1087,7 +1125,7 @@ bool SdioCard::writeSectors(uint32_t sector, const uint8_t* src, size_t n) { } } else { for (size_t i = 0; i < n; i++) { - if (!writeSector(sector + i, src + i*512UL)) { + if (!writeSector(sector + i, src + i * 512UL)) { return false; } } @@ -1104,17 +1142,15 @@ bool SdioCard::writeStart(uint32_t sector) { #if defined(__IMXRT1062__) // Infinite transfer. SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512); -#else // defined(__IMXRT1062__) +#else // defined(__IMXRT1062__) // Errata - can't do infinite transfer. SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(MAX_BLKCNT) | SDHC_BLKATTR_BLKSIZE(512); #endif // defined(__IMXRT1062__) - if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) { + if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? sector : 512 * sector)) { return sdError(SD_CARD_ERROR_CMD25); } return true; } //------------------------------------------------------------------------------ -bool SdioCard::writeStop() { - return transferStop(); -} +bool SdioCard::writeStop() { return transferStop(); } #endif // defined(__MK64FX512__) defined(__MK66FX1M0__) defined(__IMXRT1062__) diff --git a/trunk/Arduino/libraries/SdFat/src/SdFat.h b/trunk/Arduino/libraries/SdFat/src/SdFat.h index c43ec804..d906ea5f 100644 --- a/trunk/Arduino/libraries/SdFat/src/SdFat.h +++ b/trunk/Arduino/libraries/SdFat/src/SdFat.h @@ -28,19 +28,19 @@ * \file * \brief main SdFs include file. */ -#include "common/SysCall.h" -#include "SdCard/SdCard.h" #include "ExFatLib/ExFatLib.h" #include "FatLib/FatLib.h" #include "FsLib/FsLib.h" +#include "SdCard/SdCard.h" +#include "common/SysCall.h" #if INCLUDE_SDIOS #include "sdios.h" #endif // INCLUDE_SDIOS //------------------------------------------------------------------------------ /** SdFat version for cpp use. */ -#define SD_FAT_VERSION 20200 +#define SD_FAT_VERSION 20202 /** SdFat version as string. */ -#define SD_FAT_VERSION_STR "2.2.0" +#define SD_FAT_VERSION_STR "2.2.2" //============================================================================== /** * \class SdBase @@ -93,7 +93,7 @@ class SdBase : public Vol { } //---------------------------------------------------------------------------- /** \return Pointer to SD card object. */ - SdCard* card() {return m_card;} + SdCard* card() { return m_card; } //---------------------------------------------------------------------------- /** Initialize SD card in SPI mode. * @@ -136,7 +136,8 @@ class SdBase : public Vol { } else if (!Vol::fatType()) { pr->println(F("Check SD format.")); } - while (true) {} + while (true) { + } } //---------------------------------------------------------------------------- /** %Print error info and halt. @@ -197,7 +198,7 @@ class SdBase : public Vol { } //---------------------------------------------------------------------------- /** \return true if can be in dedicated SPI state */ - bool hasDedicatedSpi() {return m_card ? m_card->hasDedicatedSpi() : false;} + bool hasDedicatedSpi() { return m_card ? m_card->hasDedicatedSpi() : false; } //---------------------------------------------------------------------------- /** %Print error info and halt. * @@ -205,7 +206,8 @@ class SdBase : public Vol { */ void initErrorHalt(print_t* pr) { initErrorPrint(pr); - while (true) {} + while (true) { + } } //---------------------------------------------------------------------------- /** %Print error info and halt. @@ -244,7 +246,7 @@ class SdBase : public Vol { } //---------------------------------------------------------------------------- /** \return true if in dedicated SPI state. */ - bool isDedicatedSpi() {return m_card ? m_card->isDedicatedSpi() : false;} + bool isDedicatedSpi() { return m_card ? m_card->isDedicatedSpi() : false; } //---------------------------------------------------------------------------- /** %Print volume FAT/exFAT type. * @@ -325,7 +327,7 @@ class SdBase : public Vol { } //---------------------------------------------------------------------------- /** \return SD card error data. */ - uint8_t sdErrorData() {return m_card ? m_card->errorData() : 0;} + uint8_t sdErrorData() { return m_card ? m_card->errorData() : 0; } //---------------------------------------------------------------------------- /** Set SPI sharing state * \param[in] value desired state. @@ -339,57 +341,51 @@ class SdBase : public Vol { } //---------------------------------------------------------------------------- /** \return pointer to base volume */ - Vol* vol() {return reinterpret_cast(this);} + Vol* vol() { return reinterpret_cast(this); } //---------------------------------------------------------------------------- /** Initialize file system after call to cardBegin. * * \return true for success or false for failure. */ - bool volumeBegin() { - return Vol::begin(m_card); - } + bool volumeBegin() { return Vol::begin(m_card); } #if ENABLE_ARDUINO_SERIAL /** Print error details after begin() fails. */ - void initErrorPrint() { - initErrorPrint(&Serial); - } + void initErrorPrint() { initErrorPrint(&Serial); } //---------------------------------------------------------------------------- /** %Print msg to Serial and halt. * * \param[in] msg Message to print. */ - void errorHalt(const __FlashStringHelper* msg) { - errorHalt(&Serial, msg); - } + void errorHalt(const __FlashStringHelper* msg) { errorHalt(&Serial, msg); } //---------------------------------------------------------------------------- /** %Print error info to Serial and halt. */ - void errorHalt() {errorHalt(&Serial);} + void errorHalt() { errorHalt(&Serial); } //---------------------------------------------------------------------------- /** %Print error info and halt. * * \param[in] msg Message to print. */ - void errorHalt(const char* msg) {errorHalt(&Serial, msg);} + void errorHalt(const char* msg) { errorHalt(&Serial, msg); } //---------------------------------------------------------------------------- /** %Print error info and halt. */ - void initErrorHalt() {initErrorHalt(&Serial);} + void initErrorHalt() { initErrorHalt(&Serial); } //---------------------------------------------------------------------------- /** %Print msg, any SD error code. * * \param[in] msg Message to print. */ - void errorPrint(const char* msg) {errorPrint(&Serial, msg);} - /** %Print msg, any SD error code. + void errorPrint(const char* msg) { errorPrint(&Serial, msg); } + /** %Print msg, any SD error code. * * \param[in] msg Message to print. */ - void errorPrint(const __FlashStringHelper* msg) {errorPrint(&Serial, msg);} + void errorPrint(const __FlashStringHelper* msg) { errorPrint(&Serial, msg); } //---------------------------------------------------------------------------- /** %Print error info and halt. * * \param[in] msg Message to print. */ - void initErrorHalt(const char* msg) {initErrorHalt(&Serial, msg);} + void initErrorHalt(const char* msg) { initErrorHalt(&Serial, msg); } //---------------------------------------------------------------------------- /** %Print error info and halt. * @@ -473,9 +469,7 @@ class SdFile : public PrintFile { * \param[in] path path for file. * \param[in] oflag open flags. */ - SdFile(const char* path, oflag_t oflag) { - open(path, oflag); - } + SdFile(const char* path, oflag_t oflag) { open(path, oflag); } /** Set the date/time callback function * * \param[in] dateTime The user's call back function. The callback @@ -502,13 +496,11 @@ class SdFile : public PrintFile { * sync() maintains the last access date and last modify date/time. * */ - static void dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)) { + static void dateTimeCallback(void (*dateTime)(uint16_t* date, + uint16_t* time)) { FsDateTime::setCallback(dateTime); } /** Cancel the date/time callback function. */ - static void dateTimeCallbackCancel() { - FsDateTime::clearCallback(); - } + static void dateTimeCallbackCancel() { FsDateTime::clearCallback(); } }; #endif // SdFat_h diff --git a/trunk/Arduino/libraries/SdFat/src/SdFatConfig.h b/trunk/Arduino/libraries/SdFat/src/SdFatConfig.h index bd71b46d..946bab19 100644 --- a/trunk/Arduino/libraries/SdFat/src/SdFatConfig.h +++ b/trunk/Arduino/libraries/SdFat/src/SdFatConfig.h @@ -122,14 +122,28 @@ #define SPI_DRIVER_SELECT 0 #endif // SPI_DRIVER_SELECT /** - * If USE_SPI_ARRAY_TRANSFER is non-zero and the standard SPI library is - * use, the array transfer function, transfer(buf, size), will be used. - * This option will allocate up to a 512 byte temporary buffer for send. + * If USE_SPI_ARRAY_TRANSFER is one and the standard SPI library is + * use, the array transfer function, transfer(buf, count), will be used. + * This option will allocate a 512 byte temporary buffer for send. * This may be faster for some boards. Do not use this with AVR boards. + * + * Warning: the next options are often fastest but only available for some + * non-Arduino board packages. + * + * If USE_SPI_ARRAY_TRANSFER is two use transfer(nullptr, buf, count) for + * receive and transfer(buf, nullptr, count) for send. + * + * If USE_SPI_ARRAY_TRANSFER is three use transfer(nullptr, buf, count) for + * receive and transfer(buf, rxTmp, count) for send. Try this with Adafruit + * SAMD51. + * + * If USE_SPI_ARRAY_TRANSFER is four use transfer(txTmp, buf, count) for + * receive and transfer(buf, rxTmp, count) for send. Try this with STM32. */ #ifndef USE_SPI_ARRAY_TRANSFER #define USE_SPI_ARRAY_TRANSFER 0 #endif // USE_SPI_ARRAY_TRANSFER +//------------------------------------------------------------------------------ /** * SD maximum initialization clock rate. */ @@ -161,7 +175,8 @@ #ifndef USE_BLOCK_DEVICE_INTERFACE #define USE_BLOCK_DEVICE_INTERFACE 0 #endif // USE_BLOCK_DEVICE_INTERFACE - /** +//------------------------------------------------------------------------------ +/** * SD_CHIP_SELECT_MODE defines how the functions * void sdCsInit(SdCsPin_t pin) {pinMode(pin, OUTPUT);} * and @@ -346,8 +361,8 @@ typedef uint8_t SdCsPin_t; * Set USE_SIMPLE_LITTLE_ENDIAN nonzero for little endian processors * with no memory alignment restrictions. */ -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\ - && (defined(__AVR__) || defined(__ARM_FEATURE_UNALIGNED)) +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && \ + (defined(__AVR__) || defined(__ARM_FEATURE_UNALIGNED)) #define USE_SIMPLE_LITTLE_ENDIAN 1 #else // __BYTE_ORDER_ #define USE_SIMPLE_LITTLE_ENDIAN 0 @@ -394,11 +409,11 @@ typedef uint8_t SdCsPin_t; #endif // BUILTIN_SDCARD // SPI for built-in card. #ifndef SDCARD_SPI -#define SDCARD_SPI SPI1 +#define SDCARD_SPI SPI1 #define SDCARD_MISO_PIN 59 #define SDCARD_MOSI_PIN 61 -#define SDCARD_SCK_PIN 60 -#define SDCARD_SS_PIN 62 +#define SDCARD_SCK_PIN 60 +#define SDCARD_SS_PIN 62 #endif // SDCARD_SPI #define HAS_SDIO_CLASS 1 #endif // defined(__MK64FX512__) || defined(__MK66FX1M0__) @@ -409,15 +424,13 @@ typedef uint8_t SdCsPin_t; /** * Determine the default SPI configuration. */ -#if defined(ARDUINO_ARCH_APOLLO3)\ - || (defined(__AVR__) && defined(SPDR) && defined(SPSR) && defined(SPIF))\ - || (defined(__AVR__) && defined(SPI0) && defined(SPI_RXCIF_bm))\ - || defined(ESP8266) || defined(ESP32)\ - || defined(PLATFORM_ID)\ - || defined(ARDUINO_SAM_DUE)\ - || defined(STM32_CORE_VERSION)\ - || defined(__STM32F1__) || defined(__STM32F4__)\ - || (defined(CORE_TEENSY) && defined(__arm__)) +#if defined(ARDUINO_ARCH_APOLLO3) || \ + (defined(__AVR__) && defined(SPDR) && defined(SPSR) && defined(SPIF)) || \ + (defined(__AVR__) && defined(SPI0) && defined(SPI_RXCIF_bm)) || \ + defined(ESP8266) || defined(ESP32) || defined(PLATFORM_ID) || \ + defined(ARDUINO_SAM_DUE) || defined(STM32_CORE_VERSION) || \ + defined(__STM32F1__) || defined(__STM32F4__) || \ + (defined(CORE_TEENSY) && defined(__arm__)) #define SD_HAS_CUSTOM_SPI 1 #else // SD_HAS_CUSTOM_SPI // Use standard SPI library. diff --git a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiDriver.h b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiDriver.h index 463e4fc5..c43055b7 100644 --- a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiDriver.h +++ b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiDriver.h @@ -52,19 +52,24 @@ const uint8_t DEDICATED_SPI = 1; * \param[in] opt option field of SdSpiConfig. * \return true for dedicated SPI. */ -inline bool spiOptionDedicated(uint8_t opt) {return opt & DEDICATED_SPI;} -#else // ENABLE_DEDICATED_SPI +inline bool spiOptionDedicated(uint8_t opt) { return opt & DEDICATED_SPI; } +#else // ENABLE_DEDICATED_SPI /** * \param[in] opt option field of SdSpiConfig. * \return true for dedicated SPI. */ -inline bool spiOptionDedicated(uint8_t opt) {(void)opt; return false;} +inline bool spiOptionDedicated(uint8_t opt) { + (void)opt; + return false; +} #endif // ENABLE_DEDICATED_SPI +/** The user will call begin. Useful for custom SPI configurations. */ +const uint8_t USER_SPI_BEGIN = 2; //------------------------------------------------------------------------------ /** SPISettings for SCK frequency in Hz. */ #define SD_SCK_HZ(maxSpeed) (maxSpeed) /** SPISettings for SCK frequency in MHz. */ -#define SD_SCK_MHZ(maxMhz) (1000000UL*(maxMhz)) +#define SD_SCK_MHZ(maxMhz) (1000000UL * (maxMhz)) // SPI divisor constants - obsolete. /** Set SCK to max rate. */ #define SPI_FULL_SPEED SD_SCK_MHZ(50) @@ -93,8 +98,8 @@ typedef SdSpiSoftDriver SpiPort_t; class SdSpiBaseClass; /** Port type for extrernal SPI driver. */ typedef SdSpiBaseClass SpiPort_t; -#else // SPI_DRIVER_SELECT -typedef void* SpiPort_t; +#else // SPI_DRIVER_SELECT +typedef void* SpiPort_t; #endif // SPI_DRIVER_SELECT //------------------------------------------------------------------------------ /** @@ -103,15 +108,15 @@ typedef void* SpiPort_t; */ class SdSpiConfig { public: - /** SdSpiConfig constructor. + /** SdSpiConfig constructor. * * \param[in] cs Chip select pin. * \param[in] opt Options. * \param[in] maxSpeed Maximum SCK frequency. * \param[in] port The SPI port to use. */ - SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed, SpiPort_t* port) : - csPin(cs), options(opt), maxSck(maxSpeed), spiPort(port) {} + SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed, SpiPort_t* port) + : csPin(cs), options(opt), maxSck(maxSpeed), spiPort(port) {} /** SdSpiConfig constructor. * @@ -119,8 +124,8 @@ class SdSpiConfig { * \param[in] opt Options. * \param[in] maxSpeed Maximum SCK frequency. */ - SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed) : - csPin(cs), options(opt), maxSck(maxSpeed) {} + SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed) + : csPin(cs), options(opt), maxSck(maxSpeed) {} /** SdSpiConfig constructor. * * \param[in] cs Chip select pin. diff --git a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiParticle.cpp b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiParticle.cpp index b921f3d4..ecf6f52e 100644 --- a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiParticle.cpp +++ b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiParticle.cpp @@ -30,9 +30,7 @@ static void SD_SPI_DMA_TransferComplete_Callback() { SPI_DMA_TransferCompleted = true; } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::activate() { - m_spi->beginTransaction(m_spiSettings); -} +void SdSpiArduinoDriver::activate() { m_spi->beginTransaction(m_spiSettings); } //------------------------------------------------------------------------------ void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { if (spiConfig.spiPort) { @@ -43,36 +41,29 @@ void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { m_spi->begin(); } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::deactivate() { - m_spi->endTransaction(); -} +void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::end() { - m_spi->end(); -} +void SdSpiArduinoDriver::end() { m_spi->end(); } //------------------------------------------------------------------------------ -uint8_t SdSpiArduinoDriver::receive() { - return m_spi->transfer(0XFF); -} +uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } //------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) { SPI_DMA_TransferCompleted = false; m_spi->transfer(nullptr, buf, count, SD_SPI_DMA_TransferComplete_Callback); - while (!SPI_DMA_TransferCompleted) {} + while (!SPI_DMA_TransferCompleted) { + } return 0; } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::send(uint8_t data) { - m_spi->transfer(data); -} +void SdSpiArduinoDriver::send(uint8_t data) { m_spi->transfer(data); } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::send(const uint8_t* buf , size_t count) { +void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) { SPI_DMA_TransferCompleted = false; m_spi->transfer(const_cast(buf), nullptr, count, - SD_SPI_DMA_TransferComplete_Callback); + SD_SPI_DMA_TransferComplete_Callback); - while (!SPI_DMA_TransferCompleted) {} + while (!SPI_DMA_TransferCompleted) { + } } #endif // defined(SD_USE_CUSTOM_SPI) && defined(PLATFORM_ID) - diff --git a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiSTM32.cpp b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiSTM32.cpp index 629775ee..544c2dfb 100644 --- a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiSTM32.cpp +++ b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiSTM32.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2018 Bill Greiman + * Copyright (c) 2011-2022 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -22,8 +22,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#if defined(__STM32F1__) || defined(__STM32F4__) +// Driver for: https://github.com/rogerclarkmelbourne/Arduino_STM32 #include "SdSpiDriver.h" +#if defined(SD_USE_CUSTOM_SPI) && (defined(__STM32F1__) || defined(__STM32F4__)) #if defined(__STM32F1__) #define USE_STM32_DMA 1 #elif defined(__STM32F4__) @@ -32,74 +33,39 @@ #error Unknown STM32 type #endif // defined(__STM32F1__) //------------------------------------------------------------------------------ -/** Set SPI options for access to SD/SDHC cards. - * - * \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock. - */ -void SdSpiAltDriver::activate() { - m_spi->beginTransaction(m_spiSettings); -} +void SdSpiArduinoDriver::activate() { m_spi->beginTransaction(m_spiSettings); } //------------------------------------------------------------------------------ -/** Initialize the SPI bus. - * - * \param[in] chipSelectPin SD card chip select pin. - */ -void SdSpiAltDriver::begin(uint8_t csPin) { - m_csPin = csPin; - pinMode(m_csPin, OUTPUT); - digitalWrite(m_csPin, HIGH); +void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { + if (spiConfig.spiPort) { + m_spi = spiConfig.spiPort; + } else { + m_spi = &SPI; + } m_spi->begin(); } //------------------------------------------------------------------------------ -/** - * End SPI transaction. - */ -void SdSpiAltDriver::deactivate() { - m_spi->endTransaction(); -} +void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ -/** Receive a byte. - * - * \return The byte. - */ -uint8_t SdSpiAltDriver::receive() { - return m_spi->transfer(0XFF); -} +void SdSpiArduinoDriver::end() { m_spi->end(); } //------------------------------------------------------------------------------ -/** Receive multiple bytes. - * - * \param[out] buf Buffer to receive the data. - * \param[in] n Number of bytes to receive. - * - * \return Zero for no error or nonzero error code. - */ -uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) { +uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } +//------------------------------------------------------------------------------ +uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) { #if USE_STM32_DMA - return m_spi->dmaTransfer(nullptr, buf, n); -#else // USE_STM32_DMA - m_spi->read(buf, n); + return m_spi->dmaTransfer(nullptr, buf, count); +#else // USE_STM32_DMA + m_spi->read(buf, count); return 0; #endif // USE_STM32_DMA } //------------------------------------------------------------------------------ -/** Send a byte. - * - * \param[in] b Byte to send - */ -void SdSpiAltDriver::send(uint8_t b) { - m_spi->transfer(b); -} +void SdSpiArduinoDriver::send(uint8_t data) { m_spi->transfer(data); } //------------------------------------------------------------------------------ -/** Send multiple bytes. - * - * \param[in] buf Buffer for data to be sent. - * \param[in] n Number of bytes to send. - */ -void SdSpiAltDriver::send(const uint8_t* buf , size_t n) { +void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) { #if USE_STM32_DMA - m_spi->dmaTransfer(const_cast(buf), nullptr, n); -#else // USE_STM32_DMA - m_spi->write(const_cast(buf), n); + m_spi->dmaTransfer(const_cast(buf), nullptr, count); +#else // USE_STM32_DMA + m_spi->write(const_cast(buf), count); #endif // USE_STM32_DMA } -#endif // defined(__STM32F1__) || defined(__STM32F4__) +#endif // defined(SD_USE_CUSTOM_SPI) && defined(__STM32F1__) diff --git a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiTeensy3.cpp b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiTeensy3.cpp index c0a5b2c3..6c8e045b 100644 --- a/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiTeensy3.cpp +++ b/trunk/Arduino/libraries/SdFat/src/SpiDriver/SdSpiTeensy3.cpp @@ -23,12 +23,10 @@ * DEALINGS IN THE SOFTWARE. */ #include "SdSpiDriver.h" -#if defined(SD_USE_CUSTOM_SPI) && defined(__arm__) && defined(CORE_TEENSY) +#if defined(SD_USE_CUSTOM_SPI) && defined(__arm__) && defined(CORE_TEENSY) #define USE_BLOCK_TRANSFER 1 //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::activate() { - m_spi->beginTransaction(m_spiSettings); -} +void SdSpiArduinoDriver::activate() { m_spi->beginTransaction(m_spiSettings); } //------------------------------------------------------------------------------ void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { if (spiConfig.spiPort) { @@ -46,23 +44,17 @@ void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { m_spi->begin(); } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::deactivate() { - m_spi->endTransaction(); -} +void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::end() { - m_spi->end(); -} +void SdSpiArduinoDriver::end() { m_spi->end(); } //------------------------------------------------------------------------------ -uint8_t SdSpiArduinoDriver::receive() { - return m_spi->transfer(0XFF); -} +uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } //------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) { #if USE_BLOCK_TRANSFER memset(buf, 0XFF, count); m_spi->transfer(buf, count); -#else // USE_BLOCK_TRANSFER +#else // USE_BLOCK_TRANSFER for (size_t i = 0; i < count; i++) { buf[i] = m_spi->transfer(0XFF); } @@ -70,11 +62,9 @@ uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) { return 0; } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::send(uint8_t data) { - m_spi->transfer(data); -} +void SdSpiArduinoDriver::send(uint8_t data) { m_spi->transfer(data); } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::send(const uint8_t* buf , size_t count) { +void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) { #if USE_BLOCK_TRANSFER uint32_t tmp[128]; if (0 < count && count <= 512) { diff --git a/trunk/Arduino/libraries/SdFat/src/sdios.h b/trunk/Arduino/libraries/SdFat/src/sdios.h index cf9da22c..d86a0b01 100644 --- a/trunk/Arduino/libraries/SdFat/src/sdios.h +++ b/trunk/Arduino/libraries/SdFat/src/sdios.h @@ -29,6 +29,6 @@ * \brief C++ IO Streams features. */ #include "iostream/ArduinoStream.h" -#include "iostream/fstream.h" #include "iostream/StdioStream.h" +#include "iostream/fstream.h" #endif // sdios_h diff --git a/trunk/Arduino/libraries/Servo/docs/api.md b/trunk/Arduino/libraries/Servo/docs/api.md index e03b87c3..fc54c9df 100644 --- a/trunk/Arduino/libraries/Servo/docs/api.md +++ b/trunk/Arduino/libraries/Servo/docs/api.md @@ -4,7 +4,7 @@ ### `attach()` -Attach the Servo variable to a pin. Note that in Arduino 0016 and earlier, the Servo library supports only servos on only two pins: 9 and 10. +Attach the Servo variable to a pin. Note that in Arduino 0016 and earlier, the Servo library supports servos on only two pins: 9 and 10. #### Syntax @@ -17,8 +17,8 @@ servo.attach(pin, min, max) * _servo_: a variable of type `Servo` * _pin_: the number of the pin that the servo is attached to -* _min_ (optional): the pulse width, in microseconds, corresponding to the minimum (0-degree) angle on the servo (defaults to 544) -* _max_ (optional): the pulse width, in microseconds, corresponding to the maximum (180-degree) angle on the servo (defaults to 2400) +* _min_ (optional): the pulse width, in microseconds, corresponding to the minimum (0 degree) angle on the servo (defaults to 544) +* _max_ (optional): the pulse width, in microseconds, corresponding to the maximum (180 degree) angle on the servo (defaults to 2400) #### Example @@ -77,7 +77,7 @@ void loop() {} ### `writeMicroseconds()` -Writes a value in microseconds (uS) to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft. On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle. +Writes a value in microseconds (us) to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft. On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle. Note that some manufactures do not follow this standard very closely so that servos often respond to values between 700 and 2300. Feel free to increase these endpoints until the servo no longer continues to increase its range. Note however that attempting to drive a servo past its endpoints (often indicated by a growling sound) is a high-current state, and should be avoided. @@ -86,13 +86,13 @@ Continuous-rotation servos will respond to the writeMicrosecond function in an a #### Syntax ```` -servo.writeMicroseconds(uS) +servo.writeMicroseconds(us) ```` #### Parameters * _servo_: a variable of type Servo -* _uS_: the value of the parameter in microseconds (int) +* _us_: the value of the parameter in microseconds (int) #### Example @@ -163,7 +163,7 @@ servo.attached() ### `detach()` -Detach the Servo variable from its pin. If all Servo variables are detached, then pins 9 and 10 can be used for PWM output with [analogWrite()](#analogwrite). +Detach the Servo variable from its pin. If all Servo variables are detached, then pins 9 and 10 can be used for PWM output with [analogWrite()](https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/). #### Syntax diff --git a/trunk/Arduino/libraries/Servo/docs/readme.md b/trunk/Arduino/libraries/Servo/docs/readme.md index 29a83a30..b986b140 100644 --- a/trunk/Arduino/libraries/Servo/docs/readme.md +++ b/trunk/Arduino/libraries/Servo/docs/readme.md @@ -13,9 +13,9 @@ To use this library: ## Circuit -Servo motors have three wires: power, ground, and signal. The power wire is typically red, and should be connected to the 5V pin on the Arduino board. The ground wire is typically black or brown and should be connected to a ground pin on the Arduino board. The signal pin is typically yellow, orange or white and should be connected to a digital pin on the Arduino board. Note that servos draw considerable power, so if you need to drive more than one or two, you'll probably need to power them from a separate supply (i.e. not the +5V pin on your Arduino). Be sure to connect the grounds of the Arduino and external power supply together. +Servo motors have three wires: power, ground, and signal. The power wire is typically red, and should be connected to the 5V pin on the Arduino board. The ground wire is typically black or brown and should be connected to a ground pin on the Arduino board. The signal pin is typically yellow, orange or white and should be connected to a digital pin on the Arduino board. Note that servos draw considerable power, so if you need to drive more than one or two, you'll probably need to power them from a separate supply (i.e. not the 5V pin on your Arduino). Be sure to connect the grounds of the Arduino and external power supply together. ## Examples * [Knob](https://www.arduino.cc/en/Tutorial/Knob): control the shaft of a servo motor by turning a potentiometer -* [Sweep](https://www.arduino.cc/en/Tutorial/Sweep): sweeps the shaft of a servo motor back and forth +* [Sweep](https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep): sweeps the shaft of a servo motor back and forth diff --git a/trunk/Arduino/libraries/Servo/examples/Knob/readme.md b/trunk/Arduino/libraries/Servo/examples/Knob/readme.md index d1d71084..7dc37ddb 100644 --- a/trunk/Arduino/libraries/Servo/examples/Knob/readme.md +++ b/trunk/Arduino/libraries/Servo/examples/Knob/readme.md @@ -13,7 +13,7 @@ This example makes use of the Arduino `Servo` library. ## Circuit -Servo motors have three wires: power, ground, and signal. The power wire is typically red, and should be connected to the 5V pin on the Arduino or Genuino board. The ground wire is typically black or brown and should be connected to a ground pin on the board. The signal pin is typically yellow or orange and should be connected to pin 9 on the board. +Servo motors have three wires: power, ground, and signal. The power wire is typically red, and should be connected to the 5V pin on the Arduino board. The ground wire is typically black or brown and should be connected to a ground pin on the board. The signal pin is typically yellow or orange and should be connected to pin 9 on the board. The potentiometer should be wired so that its two outer pins are connected to power (+5V) and ground, and its middle pin is connected to analog input 0 on the board. diff --git a/trunk/Arduino/libraries/Servo/examples/Sweep/images/sweep_schem.png b/trunk/Arduino/libraries/Servo/examples/Sweep/images/sweep_schem.png index beac2fe44dee986ce5ad8fbf4fb69282da543291..48dd188dc76bf46396d34b07016deff95beb56c1 100644 GIT binary patch literal 11238 zcmbt)cT^P5mv7H77bGy2$x=x*QZ&iKzem);G)D#HusPO;*AXHM6)dB$UeG!bn zxwpVjUe+xDFak=lQm?#c_Pzuu8g49}FS0LQGwv?ccwmYPj%Xev>1BlRKQ%Y=$*3_1 ziOHdwQ#HW;6PaVk?toMBvd2N{HRZfRq;QVfnB@A`SDdxnYBrB;e_n*BB@MqxUHtk% z+I}Zkyk;Xjb0b!^gkPyvUcBeBW!tL1C)Vxzj>mV?4WmhgM~X4!BRfe;Ae|I9ot zx`6sLVz%Tau-tc4j9_AC(Z0;cBS94Z&-?!W4Nei{nh`}DZ2}--Osg6#X>j94g%ic& z)uStwj~F;e81oy)1leJex%eV(?x0NwWvhsk^*Ghi_?AP3K@py!qr5=A6ADe~)g!TO z>VI~khx9A5uZdPq`gs9eTQ&Rx+>-QfYXT5F%7NuEYKx99oopCf&%xU1^w(2UUjaa$ z6bDepJkN!YhDb)eM37l)VXQ7M6f(SB8 zAPfYgdg<&i9vqRO=A9E4L-OY0%K#N@v}wW%*YDsP^8}%BtpDuE)yD{}^Y(-nPbrWG z)P3Lj<12xey;P~mK*FseJ!4jnWwGzYkIUwO^E~hCo*pj;lhngx$Ck*H(=yc%5Iynh69n?>ATdiJ zw8AQd>?+5JQ40Kk3HTRNO6=TPDfhrN18|T(p^lbOt{2(a*>RMPfx?vkinRCGV4%hc zso3+FnGhPDs1rp_?F9_vZO`!ZSk^1=WQVqAUMLumb|4|lYfYqmn^Y8$IlAo3o@f4; zCDbk~*Sfa+lOEl+d@BuT|LkE8fblJ49P<%cth<3CQI*{Q;v8OYgQe^>KLu!u)13I zJ+b({T#*VpQfIj>2DW;rXMe3}{sOWyxKlwU(}_;0rE>9uQbwAGoJv3$7kY%72eH}q zO7EGi9N21Vw+cl-rr++|h&66NfdSBq&p9_qApo3UY0(Zq^*>Bcb~Fyk!T|b0@FkhP z4&(pl&{G7=l;Z*~F0PaqcMPe2-N)+Z{0NtVU0&+0L`QOTyvgFKA0)kUAD&PTiCN8@_fc1o@1ca*{N`O|0x5n@G8DFOktuztW?2f zlOXe70&yiS_)m-%H-_>~x+02+dOOCU@L>RG12cZPo4Pf`oeMlQ0${k7SzHjDoU~!{ zDy_YGubfI+AD`F4?B}aYNFVJL0-_v$y=d)4l#M>ijFa|Rj}*dL0svCHB!0JaqUQJu zv7>U@0to9TTB4uwonrEF-3S6ecUY#TA*ceY7e@6F<3B`pyx2Svl_W$cs1IaJtH(L9Pgj*ua=q^(Uhd5q;JPySSxU{?amFxjbqD{3<|t$;1js< z-)+1uARWrGpUsj?Hqt~dPaKavr60UfL;BT~m0YuuFlt(I_EjZ%i~mD7ZK~ zixIVEjAZ2SV)=5OtQGCAtGGdZ_AH6v;?-#NaUa7El3fS^*2b45 zw#g)xh|Il@x8*5`c>slJMl`W$G5`g1MH?h(iFXUIK3lci)+Y*OHgTA>HWaJJ=pa}Y zy80)XkyBGst=g1ne0tq!-(OyCMo8k-8@BqElsR%As3cpG4?{CzEAtx}c0b*c$Ki`n zQdu(5c`4g;=Ae5dXCk)Pg7HcM-=CVOC4mu!oi4oY-&;+icPAh>pIYso5DqU89h6Rg z?{l5a%h)JtZyUxUfb97YApCBKM7M9R#R)M`lU__-b8~Kt(YWGf$e1Qgq;!k}0w93$ zJfUheXTYT1jT`cLw0rl757UkLOBt*TA?4=->qMapkamKpC(Z;hq6M9u)kma=%gdLgs(}n=++uAd zX;|*96ct>012v(<3$qNFmruy#Z9(*~al1#dja;k|Y370}AC@zp73U(k z(geh*Qq6gp`eeTAQ@GiXbN4zeGn)s_@0s5s!zp!s3WMKRnnKO6@qY?G+iJ20km|cy zqOAQ~q0M6s>;R*1VqaK2@|r369jWgE|3Fgs{x)6=8lPDA+)}-=$*_Re3qj|K8|Yvs|<_nM_`1kjZJDutoB4lF^TRF4JHmOD31g zohohMip<^Acons*Bp1tO#YsDj7bfkZO(s{VpL5@4pyaL!@mSO_e(!;tCYLXJq}lNR zId5aB#(i%J)ok~VO7|P62+v}FX1U3M3kO*wrC}QR#In_s91awR$_3e%91&ztaWT6x z+p!KIk)3*{_fM$-6r7w3Ffh=OT(sA%tt(yHxlIe4@Q&+_8^QE8G|1}o*6+{+Y=kkQ z=`geCtEv~BjPUv&J1@P7;!zNSWSc+*wjG*G025>J2c<)}j*6`$aFZOI_h#|S-`FDQ z!$_%``pZb2q=`Dw1_t$yIOmye1=O&aMfFcAo)Shg}gp9uok- zfe(nbVIl>7rNp^n0eOe2E|Z$wAk?;q!XLpqzMV(?9j{^K^$PP6MhrV&x&_SwE=fHn z538fCC}jTX1fciZ;efw)ztq}M@klh*_|**erg)&B%NSSw69io$_WJNpHIM+Hh*g>W zdAmfi`pvUfc)n9poZo*c7K{VJz#rk%=bw#Or1vN8#TQ*T>#@gog{oFK6G&!nu+j zMI9J*)6VUO*(x!Bg=c0Q_oOhsNwbEJo->`kL~srZ0*Jih-kqZXRz4t!-f_H8XKSgz znnEVIECkAX`=UUMYy&eD@rTTQrJKehy?N>8Pzk8(jE~s^#to9INwc`OGQMR3^EP}K zFxvvohGEIcra50mvbksd?>0BKF))CS+3-`-28_b1Q^M(#c1&d~Fwviu z-Exyt7ob6x0Kv~*YO+*Xe_B_wED)1h+qqS9%HzcUGt3;&4clH=cq;JCLSEKJ*cUWmre=W%aiaga@m z=dzvMgTi}o$VL(7S2q#qph?yVi~T{JCh~dE`{U-n!!KtST4^c$xq zTHUapn|WH}C&T4imy+nmh&GzOqi6xYZsI+W*4YB)2`AsqF4m+Gk%-`bRVy zS?B724y*_hc13IGe-?|IFz)%B)m#0wtR{*Miv<4Dr^yr(`5il(#uDXlk{kr}V04<4 z01ExXMXDqvT^!T;GX(4J# zU=XjCnojQ^AXiHArkscCc57zYBJLCx*C_!HOu|MIK9i`IeaN^@IWH2iXIjq$EeFD| z(T;6R}4-h$r^4<$XZ2T>G+uU!PQ#)EQ+e)-wY&nA!10#-|`2B+{R zAi;bF^x#g>n@)-HD>a`4hlR*&O@|P_V5yeAIDm7SFwyFb9p$xK>S&PUX_v@1dT%ff zU@(Ro4$(6qYBxChZA3No`K4xbMv&x5!_P7Ua(^D(bYpe!FK#bwrUy)t{QMHQv;>x| zEY6F5m|Wi7n3ElTzW4vYxVL`3{-X>MJGJ^g*AhltV|qVxctuo4x+xS935DC%tWbHf z+Dj^iHJ(%!axtOZvAQi$7UK<(``W&%MTT$#AK+E*4aN&jt59^91kwX-?KXKk$UsHH z7=|{X(f{qMYGNfNbt2zCDdDL5r}IyBR?*KA$2g#z1<}zM1g~&+EA> z|H(xrSZ~JPTAu9ht~$p{ULcJt1SQ6TyMhMEX!ByeUC_uIJ-J)^VXo}SFtEzw2#6w~ zK}_C0ao=`VS({vt!JvykrIfBWzZ?nU)^R)e9$g7tz1HH`j|flB!JNo^r)(zN!E#%& zrh1PaJFy>8H9{@Ak`x(>KaqbvY?c^(1`MP5f%bq?PGaoXJn@XXg#%V&#LMFzYZqpe zFpjDF@&;wprXs5eVjQQ8JWB*A`w&uZN=fiU%`awF}TQHGu#nrUD%->BgAdG*l>2+{fq8mF~ z+qQCg_$^5o-?-SX^3U5Rpaogmi22)*UuMIFnZK~3Np=ZK0{1WlDgl((W{K}yjx}iT z>De<8)yhRP(ao`iSpDuez}f6;+pkw*O~F!m5bZz3$$BSEXmS9eTDW6KdoFZWv>i*% zC08gJ_HATJs3IP4etg%gi65n@x`6Ed{foEr!%$G^Ezyd7p*aYZQEs4nC+VQ1jOV2fCuOC*{O9RD zoU%K38T(U*+96DDnS z461*Gb_oa}pbSq7K{|wWXHpMEzZK)nVolCCx|pZ$-1V>{mdQOt)f zej|nhfX{+`r~;4q(k?If?1@z_bHZIUktKI8i zi-%2D<%qhS0cD%d0C0opJ3Dcb_P!DB@=pFzXUAarIX?NjoUHdfISL(bdMY$5!#3Q0 zHW=1F)*BuBeb(zB+wxWC)g2R3+Mb4*^$LDtaXFTXs3ZHG0eWg3_u_c5TQJP)b)-ed9d(1IT1hMzauX4G%%j~Ztx`T1= z3`byWq9HtmJ9xa$t>D%o-w(>@R{NuC{nAYVATNvt;27bSO){IAydH0sTtGQP+@HU# zHpl8DU>4ww#8bb4ej!j$Ico!N<|Ym|EJX z@Jxr>{UU_<3#_|X`56gJ%cib-@w@J2H~?D=jhwXqh^=f?9G3IOI!C!S$(aenB)6DO z4UKMK1Q4~j-5xm;nD4lojf-cOgl34YYV6ZC)aH?^%d+V^toVT5`4>fs zi!ff1k#PtKqsJQu@&f4*(t$*1bHM$6CPL?Q=x1+yG2K!ZX03!^`l(URHCbqe`-+JlrT$j?f!%A5~vnP4Q;!;>+$^Ien5{n(Cv>X*g)?Gs0?<5-IFTv?er zy9c_qM^E+9E1!8_mVSK`nD~n$bx|ULmmJ;-9*-DWFj&`ODbNps zsZuf1Jh)sG!4A*c2P_QiN}Y8GQb^IKM-Lgj=fP-bnbs^XK5+eKFVO)~5#7`s{Gxsp z@*q>K?2Qv6F8WVEf!H~S(KQj`%ngj;VlCJU7cYFGa}&Bcq{ppTO1ZS5y7}eYeG_&_ zd+YqJ~vO!YHBqn1qo2*i`}pCYlFhi<-A!cT-wDfSGA3L#V8XLDHSfSUBb zFZK=?>ZegLRqxgMIZHkm8ZLyV?#q+FSKf>RBCffD;LE+<5t|`r#o@x=V|P;Pj?Zx` zaLe|f088%R#vwGL?*R7qyf1l-KK9(!nL&WV)wQsrBERP`1BiYPJKHYS0LPwZ4Mf$) z8i7YcF7R?gALbp@UjIgtiu{WF{vU6zsRgT92D3^iOaJZc%Tmr#?luznF%TUfhES!Y)Oe43Nojuf zX^k^qsRHf4b#wkXzN5(;+qve;OiG1|h$QV@ExLR3cg_&$D}EeXZ#iZp-ZufOw{$OP zCbJB=dC03C`gyX|f&|}(07E}Y5|Eh}h?Hs>A-c;s5(@Oe@Yb130e(oFIc|k@PW&Cw zT9a5e$X5gbKc!r26vHfJI3vW+&`Roig?N?-Z31?4xRQ&2ZSh7}!bGhiFkJ)c1ujUu z$YUXjb&uiH$YDh2d4-S|$?x)WA>0R~@8o`ndPTlOM29j=T@n!IHwQ_IlAP;zG9h2y zHi8)Ed8Yq9a~|jvxWqyJc+}*1svRK^#iy7juMcWxO5cY_h&?ADa;#Z?w3v3( z^Egi~SH9nFM;Dqbsn3VwzzYwa6Z}m&jWfJM8Hm$Q#4A}a9TqHAt8#2A0evT3-(xW) z^}8BUf$ly@n0Ix;fKY=N+ut1-eFN{>Vyu^2X(aXO0P@7BVH3`K@6iN5qQ7M8TQdNA zpJTvCEgKzXfg#XW{)DwEM+`ALqU;mSr2B6jfwt1GB?H>Z`aF{)$ecpN{vs@=XVmk0;g=0fsg zhT`PFOt!qJ0Jh-L=j9JR1?|&O+^04c-2P8$LlLoRAx&i&CR~6E8_?yth^od`lci(s zMFFcmDKGnC)irD{-$4|$Jmq+somZ6d3e<(Q417Q%NyO|^n1DjCjNmu;Bt4B^8bnd8 z3Ve#KxBD@JwiwH453SY_IagGuiY<7<(FG)hf$p*Ki%V996_|X&bVupgdBkNG?A9yp z(Nlv*Obe~B>YrzG+vU0~k3EMAn}|pli{6H_-pV#JtDxIA*e3IqdXEZLu%frcy5oT! zStkrn37Hc;uCn2~01R)+k(VF+&h^L@m|?Cu0RQ^!wL5x6kfVIuS{4#5&7yH`UOJ?l zdW~mMr?DETwjh2#V65Fu-kSiPu;Wz7d!pvyBJ=*Is=84n{=L(=K~*WG3Q11Au8nva zDEi*(1*I1}h9JG`>TsnopMTyWhteA>CE2>yM2PrKvYQ{KYzb;-_Gu%q=|5srXx^^^ z0Ox^s34b=qqau+Mb6103^rYiGm47*N{-_*}BVhekQuiN#Xj$f*K|Qe4p7|Ch31pNa zLjMa!lL+)E?pJzAU?cYI1FbV32^+k%_KVIFV9?PmB_hO)`}mfYq4yePaIm(0hME;m zep}=7m6AEnznHmS9``}$xKkQ_ioZd-`i`B!3g!|uC*VEKtQ+`6dSSAgXG9ojCo^+#7kr@VAk*(mF>af` z^XNo9cc)yKdIdY~GTYv1Pk!VH@)g|2Zi{<^i=2z~k(nTep0(cg?KE{RSM(IOI=K{o z)qG7&;7x9CSfb@@K9DkCczXhZ8H%I_7fME0QVB#x`LH`)R#8nB>%lOrbyMegQ%iVT zg>t#cs57aPv=85UdRuBJ;ZdJ@>VXicShv0j%!$wP0~^*!15f_W_ThgG@yqeZBZw_O zxK>Ll`R%l;!S^J!uB!f+A6sv`-Bd!{-^Gs7I#?{eZvt7QVT3gQ%xJ+5E9O2(X3{}~ z;t+t47`-lyctF%>`3YwcV_Xq{l}5^TEcma);XUQ@Pu@4wf4a~fBr|&oFe>^tuAw}D z9K)6{C|4rzL3s*~6v(dCnTe3}u=DqK58?&m4SzCzk?)U>B4E}F&tyD&}iV8(e9(OMENLCKJM zq^yP-{zRR%rr>Wzn{k6;K*HqK+^T2Ao~`I~9+NMbwkU2aEwS(V$+w7ZVrue)d!Gn) z8re)l+ZrKVFC} z(wecIT5=#88^aBi+)|?%kb^S&;6M6E5w|->q+wTPt{{@6?KgEc3phe36)Q0@>!lG1!^dE1u$8<>GXlP|&YWz-i5%s+9uYB4tVA1~;%1$bPx4fOI`zz0bdKam5|5#&Cnj$RGYS)dU5<4VXZP;NWWM&Pl*`TntH%JxXkm;)bZ2kkNFp{ z$*leNW8zN3Y*{Mr=Wg3l%uH12VPxJ+EMRlFLe<)+oU`^&R#?;tK?hFJ&HXQ)-CMMH9;7a0B

9)TQWqE zQZ0y;m^QVnCaBVNWwKeuC;@p`Qu=zQRl6fzhb^9tr>x6^RhetvB!-b}=)IFO*Xm1<0V~={_HhoU`Nn1j1Iv8=(D)R%vS^&jl%D6m9Il9_ z!rq*4g{`@;MKhnV9ZvYt0U`%VOK7i&=qD?g^qoZ56|Rq!eS24r*YVJY-N2OJtTUn5 z&H8Zfz`-G~uapaDcySdaTJ(hDJg{5b0lAHTw{YSCaPAX^y?76jrIFZ)#FArca34Ir zXbJ)Tj%{N0!+hjxBSKnRI5IUb?^kjOaJk_P*?aL%sGyn~>1I8XsoDPVF)$^uBu9M; zTIEF4zW`7)9N<+BnB$f$fcZ~TfRL8CC4(lIaKq+xTq)*T_x-7R65pBR+iN^|k-10? zR5t^NX+Wz)MmPB6C1plXx{KvkRdsM_I+O^|J(hSG{$FzbPzt=cG$!t%ffqf?M3-i}}jxKKBE z2Kr2hsODOa;-cm9-QF&`9DsHF@JC1!z+ftYG$L9oBdq!nJSp*9JH!0=@UR{|lONb*`d#Sa9QbY(X3q2kV9pW?r77U=ZAd85qa^6L5BO7PT@x?+#;Ke8Y z#TodaFzBbLD!Zr6({gZV0aDbt!MX_F2KJrW_zr-V5^fYi^e_ik-y>HSjP)91HZXlX zn)KX&aiF^hBq%_R*tz%!@qTjC@e~-mmy2wD4Y(=Z+JatMhMYT0mOGa0Ef$O$tJ#-; zU$@q&J15Q-b<2+FD#bziWBum6dMDW0Kf99Nk#Hl6-^q6@#Ca*iruKg@-e%&1y;x!g zJr(1u(-smvP0I97dx(2~4IH8X&NaZ8!9^`w#Z zgvrqhm#e_VziM0cSU!^xThEXxzOswF3x2Cq0>ydeiHR~^0}|N^pZkKfRh61a9-vS9 zI6Mv$Sw8w#`zznC2#z1U91F5FU9J&rELaDrCcE_atg06)mA@@a2P)C58B&@UMUh_; zzwPiIAXO#E)>R`gKu9SiCtm3;dBU@xMOoA7EHE1hG$r2`vG|5IErT4#M`N&-GELVh0(h2*ZQ26x72=QyLKV*3NSc6+()a ztfZif`SY?Q{sB3dJqZBZFXiTIrdqc>U-25W2SJ+{aB4?mqc0o%ftmTV31L7cNp|Nu zF;2A1(ny%~If{V<#^Q*eLZMl==m8`1y&s>|4~ZH8Af_KQ+X|G7H8NYJmbZO}pNDJjH^9gnFR+RZ)s? z@v|acgtST(ohSV-@qnrY z1dnTfXO8=xA%X4`~Q9WIQDxSZ?9L+dY=2a@9RFV^E$8dUVcgnH;<8=Awdx2n2fZ9 z3W8waM=YKQ{f}Y#T|4-nc@uGQB^hyXdLXWw73lr{-L2w3I7Mnyzkg|1-q*+s(>;7&&Isc5MYu@blPLl>~AVb5}9bZC@lH zfmrm~1-1TJ1*XHIPi;3`CVHGtJkh%I$z{tS*C8vStuW$<*A8yvW<)Q0&Tr~RBpN5N zzJkN?Y+oM}4UhFK%?933aB{3EIKd%QtHI!k5k0ti0$H8NK)8 z-LG07p|huWme=+FDLRw3&hwE{k4&B=;r63mu49XD-|yU6lJ&F>x?XQ^4{xg}t=KJR zxnBB=(2cp9B74-~j`9zuKnkOwj=|rOec0?v$7zqAIT~?HT8T`O;NIIDC7h4onakI5 zZA2I|4%57Lxnjp;TK4$9#0OCq-T|Q^<#&UEyQ~b4Lc|M*UTur+vS)u&9CzAi(9Y?( zvlfyS8Bw}4BJg=UyyOgBcYEEKt-P*lXovmlyEnr!ot(=fX3vPs-hFfVmnTnPt!>WM zBBx&H_cv@WC_j&>{h7YyWv6+WZ#dT6LqKShtC_2y%QnmJIp3YgH%2?A(p&TC<*$FK zZ7AxlEN&Y$);<_zyUc9wKXKmg&1bH~S3S2fNJsT8z7j=;`mnWG1aC5R>gz|8uW;*# zXgO9$c^q9)4mth3?Y7^V$47R9Ytbdgtu_Puziw0iT=SoZWyNxvkJN>iTBttyO%`vM zWNG^zOI_9Kwoqtkmgs(cn?PMKgDOjfCzie(bJqTuGuA@tS#+=J?)&Xf#SBAnd*!~4 z?oxDLA{h7=kN$u||DZ?zAVdEkLjNE@|M>swGJ5o8|Brj$w!|zMS@r`1o)4KktHTPqSS-nV!RN9ga)a5 zO@`p^9YUN=Vi8tzgkDh$IruOUa`0iy!H3Ty2OlOtKfJ`W#Ps(EJbD*g48i_g>R!W0 z;4V%lVNBk~_D2GDK}Q02*&hkq1s%!3UC@#2-|p{_;4b?^La+xz!W|6h-}m|NhV;6p8oRnYf)ZvrbeEMii+1sc{w>@kKKXY8YjV+z`(%F%!}yT z(H@OYLUtXM5sPQl1GCqbuY~Yu1%nvNz$T zs;Vj+tC*2LGCpqj@ZlYG_4S1xpYDC~k&n10qo)^3aLILjp|4M~>4>@A_qUgACz@z) z*!*0cYNt7KCPv8Rp|P>CzP|Nj%lUc6RPQH$?@fLCc?yw2yvNFPXKQO~h}eg%rf30k zj?c^M>yCZ0XV$}z$=|P86eA*BymE7Mzc)6VLDH_ToNJhdB@Ak%g5)i{}ScEv17+bNl2z=X6zn6CLpBmxk%3^ z=(74^H9k&HO^xti1fxWf_Wo0p%QsF-NJYJL%)(Bm{{#HyxZLZfe z5-Tky_wI{VWu?2mKK+^~8SFNC1Va1&7M*A);EL)R8fXL^7k++wEveoUa#OZ7gWJ{R zoQV5b{>P~wK0MOVpr#**-JBw|gQ>cD2ai&oBAaxeC{flTO6wRwVel zFWnRouMNxSd#g5oj>`*aO>i#`(;fUBcHQGt)0uh#`o&HUqW$elKz|V#4^{~n;zhSI zdW-#~`JXrY`?B!s|LX+@m%>6EJQrOO-wNbQ_I8yXc6eua?+JP+Nk)@6U#aDiRYDv$j_rNUbX}J3c>u9K95;PBb#S zx68+MX+3y*&0~*m|5|j4(7_$N(f|8^|36%SyGR%m6Epwwr-6w{iQCpH>{GhHl#C1- zYU;0ZIY!NN{GDIEd>QuG8?3K4U7hXavl^PM3r6Fm?PI+7v&j)nO-(;Pzk%Zd_Ot3a z`l8vDzFl2iqN1V$(}QIWH(#70|K}e=Gc(ftbtf~!baZx_n3~dEx5hKs5$m|{x;kmua6YS; zloXbtr!g_Q5)u;dL?%fJ3JS~4-d?Bi`p|#=`6pYq!gGK1eG8DbwzluzzxON+Rk#>^ ze_LZZ4@d}mH-CF`#q7q7lKOgCl7aa6cE%CSGhd>TwPa}i-SW;NeS1`;iz)wPBOECtLt`K(k(V`&081@X7li7UtizN zKsxV(=LaLFD62kx{K$&JY4{yB+|1-;?UyfYOMqr<0k$q*YHQ8=@=bo$1>gR*Gk@>v zi_=#P>qBau9#M=D4F4#Uw6NjI!^6`>D)IG^on0t?#`wX5yx&D`a#o+7ok+3z{pBT1 zd$N2Y<)K4|w6wI^CMsOk>g*4;)CY>{=hWQV+S;jMrEXjHVPdV}E7;SgPY;&b-MVD0 zuBByWVse3n#bYgplpP9hTgpnUuO6u+HH4kT>g49w_P>>%L9-j98{qA%pM|w_P zPH1qjvaW8^Dih!J8#nB>Rbd4thrfUO7C%1G9DCyQ6{ZUpyw9A@UVq zRarT{N(}3`*{#ae_4hH-2qXf^ck1*Cva+v2L&rTk-d=uik&`p+V^j1Tgkn!_i_R$T z`Fn38BfGo1^QaEfhNpQ8KcC)xY+!02{XOa3D#gxC3T8R|jQt71>(V2_u~z2h=J)Q2 zKG9WGwQY_O8c5#RT5B&+_KwbiY^i$8p*Ppi_Sg6LhnQ~5bt=l)FMMM^e#9pw{X<4p zZLzet7|&>AXejeN>4l$P{2nV46T$w@Y%wFiDSh6q59PRb?;aZ)o97g)A;b^mY?9NT zUyX}nUz?)^?%ui670jqwUgo~TPaCd@cuuLQsfCA!zk19Dd2zDrzWmvQ+}tZ7BC&1{ zmU(g|;<+jIZ;sc)9y&m>zgYDzo}tr(!Y~T4=uhbXpg$e_8W8cnT+m`>ZDVuAq^7H@ zknvCeuo1XDJt9+GS7+Q`XaRuau{J;0nQ=EGEv>V&^M~1!{fJ&B##mpKSlZae96D@Z zWW>kIdzg?gJTg*%pC7=mZTh1(smRVBztvs{#S+_zh=>%PWJ68g=g$+9pL%-}x+Ucs z-Me?*&&!jRuNm_f&B#?_X6>Aw-Oml=POjJo*=TYc&yVYO-hL<=bBa&-E^ietw=N8WbLG0vu*xL{zh| zpr8Uc5pT)cmoFRF7sqI|dh(1;5aW4&JV!ABrg<_H3;QiHCgv1i=1Uqr)~*w@{EwG@ zev^@rd56(dFSfp?`p5i}R-ySl6dwl498T;n4f@f~*z2zAIRJdd#;l(m#KpyV)4FmE z8$v=uA!q>VCP~X}#z`(bG&BU1Rmr2jbSa2R`ow-SEA%x9hQ}g3-<4*lq^ya4T+_Xsz-4My?9v%qvZOATz|49 z-W>S}9Lvba2vC=tQL66Sw;R{5yKXFfZf;gg{wFjvv`(nPJ0XFg{=}ifM}uCynjWs& zD}FSlqN+-`GBPUmF+Sj3> zS!rp0FJ5$XbtO~wJ<~)WnVmm>p7Kmj42&(mK8($jer=fxqqGtmHr1zW(B0CKnx1ZI z8Z)iGIQn^@3rO=n|Aam}aW47YyUFQkIzdOW{U;Gq;ypdFMY5t#R`(Wuh$|_zq$($_ zy9(c`g2=G^Zt$_TmSF84=Q2b+R8LXyH-v3|IiULc_wNU~%(~w@IXmYLQe9Nfu^i;z zpJV5+)YR18JfnVJB6)fFu#JzOKJ}9$Y8$<$*7z(3tnKZ2`S?~t!ivM zS?2JYV3-gi?SuFN=r}n!xtYxXAMVQ56EW|}nVp?|Ppl6yM=eo1-teZRCW0QJe}Yv~ zRh{WRl&M=$N{f+}k&!q40?AKTcW8Jx*6bMMTKMF>ws$g+mlN2}6VL}^N4^wWR`76f z1rS_vTo?iHbeMjcD%47GBfL`q?ih~EDJYopyH9cIR8I|8+>sM>N>A}rsfCi>vA0rA zomU6W<~N0H>+CdqszYkg`2D*9W6a5Xaig0R!j232ia!nR-n~nNNM|CcxL?11J$z0? zO8UHM=n#ZN{La+1)KSG_*!kYTe>m>+^!JM+ubA+qrTpC7-2Srz4@5k*0?*#KZ)o_r z&BST8=Y!4+*2db}k%M7!*;!8=zziQNNo|RxrlM-wg|ryEy8#&SE-8rz@IILF=5ac~ z>lZE%VuOxi>UghOk5of2!QU37J!_5?2|RWA{&Ytg5FK`Qc5{0#E+T~Q32;7~DIz@E@~RE$wKtqv_L{Jor8zm5fa2HGj*i|pV7u(qxH&U1K}|+BGB=l%l?7z`I~p}1 zVPOw#v9C`-GXD}ld+Uvsj*i>!p^AOHl8!@C6H=0r>;MyP+_+(xtQT)GOiN2Eb5ahW z9QF>tVc%Z5hh0*#B1cFU%|p31+pA*Qt`zjYd-tw5tHUR;xcQf7fS;f8?b}``e8(BZ z=TcKsJM1-YF*rfGwv#|UeE7hGq%Q)J&%;j6B3xJ;yXofU2BZxexA{Pp6rL)FBuc#; zJ(-u67aZ&Cjrg9v`f#?dAY;0f1<0Iyyq^j=e^%UAyK}g!^rXjT)cc$0{sbnRo8z&z~LHMo@M>LGT8J$nMT>556)faQFrrlZ@4+saW%$iWv|JXWV)EF8X8kpYQ+0tO8K8c5<4osDzI)qI%jA&tg zP=F}Tfmr{O&oKz!1bta$JD@if(?8}1%P6hI2_`#^{9wKWxeHiA>Zk|gpCYSa8#btL zde-`dg=0OS=viKV%q7Im4qIL|AJ@5u&yHty($wtR_%jjwtTq+^!OHlFmVE66G5E+Hl4t{9kU*|04vD4nbbMerBa4W1u>(Wm<2ZDv=>=Yj#A4^Niu&^+fwRxQ?_noIl zPE1Canwh=Uj*MVoOlV+-Vo6z9G^5CJ@YS0)&-T%4`$&48?Prszwj>c1M61XW*ky&& zALe=)2Z9{a&h+G88q%<*Su20{6>ta%4SxIPmkGu8Lko-OprA`8ZA`pR27z>?$c1Au z`NRd`{?DJ^x^*kKogQDwfR}tu)w-8!{X=XsBO&4A<}vpd2ws}tl6lXiBS)SQQ!t+u zu+PlRZEI?>1Y$|KY++&X?a0>J@04*`0sHTfe1S}&_vtU-5HSNoLk$fLWdT3hu)f+l zb29u-(zy5U6=Y=mcHi91)_r;Ust*;b0nt1pOk02g2!WJwqvn{o!Lm1vmd)u=u!)k@ zDX6HVR+!IYevXf~(h#OdGNy{j`oX5sPD|{Bg~{mzElV@W8_FS4YOdL#iY?gg5WHE6 zk;iY<1lY%EW?df;8~L+wgR|Ua?Y%&eN+~^(KGogTW%Da}UD##SoIeTpIXrt05R?h= z@bI`Iw+0Qu?s6JNu78+Qj@6cnj+!i;!?=|_ykT(E%XkX zW?EX>qnpXHr)L@-0_-?CIRSNjBp`k37F_0F5n!iW^Kge&&@l%B1Bja2RnI)Jwi0&BT)kjRNl97mz7xUon{_$Qr#q6*D%Gz#ruF{Z z4I=#0N;!T?wTpcNntFPQy+a^TKu|#G;<3GWq{!sQM{f{QlMZ`jWpQ%OZdnWiET#6= z&*2)mWgk6y^h5J~M|n$odtxbe&SS2R2QvG*iIO(J`xMYx;05X=GlZqqKRkmFU#R(Q z{U}FRKQ}c6Ja3>hOZD=VKsq+51TWrtw=S9Sd$=lvBJA~R3fG`uPwpE}`!M-xX9=n= zUAty*ez(?-f`-rXXCZ{m3-&QNeFk#exvabXw~;4Lo@8dpe28qGAhj^uP39d~8gEFm zkRA7a*Tg$DGsD5g79J7NcKqjI(+8~|eaRV%*Hp${s1#Zb$~FLP%1o3Q#>M&*(>@Ce zJST!mS0c}Xg2*^SL{&+N%;ooo2VadtUo6?Wa6@o$AYqIk*ff5|b}>p6%q}h2h+YL@!mfVaC4$jycwo;SlZdi{XNmfJU8m!|x$O`6FE$;th~jJTYpZDT%I8rrrt+xy3s5U7sW%A}{Kr#C6}nNz2%hZPkcV_LmQDakwBVa}%;bZ}y4 zg`7hQUYPXO*ZYSN#)?yT5#uH`j7qPCoT8ve1Tqm9S524Z8xW8z!N|y1Bh+hgH6I<; zF*U{I<>g5|{i@^tcnOh8*tyy(7C;E~#?`VY#t<>jZ&~P>VE}8jtYcyO+ucNF-_CSp zQS?0Z*sC(=bIlF5NCHem-BB<6p zQCL{0J(QK6e&&jSZych2nas7YG&A$XAj3>9DpjhxL~YHT0s*3@%EQCXZUs1y-w9VT zoFWlE{WupFSI7g!X#VjZKST@ZF6ko~itkcV00@Ir3e9_$CR-WnpF#Pm9bln~jE|4s z&h44{;M#DBk8iJ;5x2QX$(Op5l9eT&0ikiyJ&7K<3`8nga)Gx9sL-3T#r|Xj%9+C_ z=)T7gR6L$)3%_b4_43STPXQLhnbD=iqA`M}J6kX1g@VQLRnlxO(zvwoU{rVm>{R_E zNKcO!(sTgWt0Y^e$H$N%F24AuHXWb=6=#JMKnf&u7@1zNAi>8upD25M@hx;<>LQv3 zUOE85`&OkwhA*xeTU4h{?iu`bd}Cu{_M9uUA0n~FrYpDfN#-5q2guKm`Y!R=BHb49 zA1WiU`iZ?nVNx0zy-;+n1y>)zEPElqHqHq;T5m2-jeQMN{j9gZ*RTEZ8T;k@70}`U zt+btGW$U49q{%1r{P}aX=p9E%GSkbdR~ZBa1sNDTX;cWIz;eD|evzJ}GB`LGV9R3u z&*lnRH>(_bULQ&n>%h#}dT%Q6+dVhaSt+787U)8Nc!6>~JpA-OYc%>aEVOE#hdj2i zwS~eEy#jw}R)+VRl(_hzzf~L&BMZyTo9p9m^pbBe%o-hms`@~+#vvA@ap~!@3{?rB z8XnwyvlM|_xw*PZ1=4X|3%Iy1?g3%8#$3OCy|}E5=JaX8BS*v!#22(N;!{#`0$|n%b*LDg68`DaFF!8pOmz8aSWDGJ~kJ8zEJDA14f=^sG z>By9x;@vDwNm3AxD8~ZMiO^9|txm-%N=ZrW?(PcGS%H*5OiT=j1=WyzIq8H^zeTh!%+Q~46x6jR1vP}>?0P99R$m8qw&QrthY#`I3k%kO zlDSw4oV9h1pWip&5?c{SrKA9s-VNSzzcfcGPeiWjfYN^R=1mQa@Q?FAcZ;)Jg*_nb z2d*&!rKI684T*^8D|h&i3hF-%u>!e78pZ}pi^#|ljcd@aEpfze}Tv@D=Qnu zsU?-c^mJ&~`$XOwRXR3F5ApfKx>M}tqhENrMQv8+NJt z<^)BSZn&{1b+HeBdzmLE9ve|er zhYV!Mr@FdH;F|g9PT|xlwALCM8v_>J>sFVV%4&M~u{;tG5HQY=&`8vyMR2LXDl;ik zLm)eR_~A(PlPoRd*>Tzg(sv07Vp^S%PFt&-2Lq(QzJ=xVIYy&tC1gMQHZ5&xk1+SU zod1>R&A4a*ht=A+8Y(KPfxOEgb2#j+d9ZG_59itK=5JMJ>dr$WUI{Cm>s znwooCt8-aJ@UjXK*Zh(|40O1IC@3fhU9;W>z0LV9Bfg^4mTX@g!%q@ck1Yajxx#0< zw6b-|zDR}vwdUl^QgCa54zv0YRIgza^Q3Gs7mCzB1FTrJ*r3J)LV5 z>jhFvYfDQIC?6T(K1ZFFeiFmnA&Xdu^S*e{(Rq1Sp}6L_llhk4j(x`gP?Fkz1t zGcyNDO}QBv#W8~rYyJIOfF#_y1)4-Rf}1ig4pHc<$n*9i2E&b0b}H+ zrxB(43z*yVsmEiYqFf z>gXD%RuBlFj$MZ_!SrTiWVnplPN`0g(Fr+sJgkSYn1mlQIq(SJ5eYfy1ih1a-NU1H z`}Sjd`%1eRDzz^j-&68-&#mT394MgXFr(c8BJbvuhL0=JvF#H0oDYNLNq~rw< z&b&mbrs6NZMuU^GfDOSp;{0b+t`VT|IVN9D_G0iTQ{tR1bOXh16ddu zpSlrutdGne-rC%3OaAy#44PG^PlsFb-h^C+#w4P+&CtVuC_?{_VzY(k>iEKVlUv^Qxx+iJ>~~W?CrrF08Fl3~mokL;>vJ7%xZP>L>mIE-GIhTK> zF4b{D&-qc{OTKH@TAJLZZ#6VDJRrRlc5wp|ulsuhtRqw6ASCt)DnjvE)9NyLG%db5 z%hc4==h?Hhff8sHgui{8gJDvLx_2Q7Xcrm)JRn+fz8y@)AQwv6v&Fa zj4z>E>gp=!eUkTAH{f3C;Xb~q3P=@o@WFva$>qrM&9TpU0t;?KnPZhK-w4)dkhzd1J#Nc23N)c3($Ujejh%}nPX-BD9ZI$?-~E|U**CV9v= zBM_iTKF4X#(9tOnhV9xU&qg2$vBDN6CcWdkvB088n1QI+pO46Uw*2kv;D)B z|Iz(scha*;SLk>t-+%BRt$>c4{1H@2BP06k520|hFm>;FN)iJ&l#-GX5TKA!stx%l zKmT^>a@!(X<~5!*=e+o{&|+od;K-<~6z1oTxC8#5ffO#Uxo+zd5_a-PhyO{}kkql9 z6cHe~gcKF!g(+{YLrX^f*gBvj>L1J2@pvj$3wHNXcJiOlS4;TB(282 zyo5=A=m*}edsXGXbCJ!9;oG&AbfVHo$NjNIM@SE#I2p0!vk3@9a=uRK#cz3H*Vh*r zZ-n;8HcyB+FZ=dsWeM1(rhSc>q?R=b)X}YQF34la&fbglqX};nAT-0~vh0A_K+@&v zX)F?Ffw{(WBFBB{r;O>5i&}**lFa)HU*@V(6U14?{cgo*2WW5(3GHcd_wj$%4bZJ; zOxj#w@43-F97p4BR8}7+`jmhW;2w8BdF1-z$rdOnRqA&{e$$*fm6KIwKX>0R3b7n2 zPlLMWjSbY^@{JCvkbPjMP7%Qhi5;hxX)#hhOja6~Nx>{4Qk7R?HdOAkEM=-;Kdl37 z89wqLFaf2xcooR6L?e4~#bhT>+H9>_KSNbg_bBSOUYRKU5PCd#&s!o z2=|_wU`)T?8+LYEGoC&2SPpghgzs&mboi*+mdE_KX|UV*7vq+&?nC%`&&KFR_*n9-F7vKS~n@OwB53&?W3 z6VsppT9}*fu4H=v%3HQ3NYaY@g0ja&44LhuA=EGH?&y1Iph?Qg%Ai;LX<6Yh5jCb9Pw@~+YCgkbdOLDZNyl+{sJAzK z=oEDGf}_)Jh*>_Ux}3bwDc;_ILl9S01akUaH8oUAl#@H!y;)dPBmyma>QX!uE%4%Z zBpS8t9$7|m_vMfN2+{4pj#PTdxsML+?Zg5RoaN4PpOF;E|6@opcqlHedHOTB{&I72 zf(US-hJ~T#oJ>fek-GZZ{QSq3mhVC4GQ;H)ms#BMA(I8M{(2G%6Vqc}hYvFSP%~{0 z3c(gJ0aYUZDsdpqENY#=1(M?K+_A6mB&0m^@cUcQtlvOCl%2J;qe@FR0W6Cw`a$>W zPLnB;bfI`l8d9-1Gq)RFM1=$NFf<$okB>&x0PO6^^nWNRgNW3o&d&U_ z&sJ}^ZRP_u(8gC*#_TRR3f43ys4dmvF^9Zj`r~J$CvqN*eNl*Z0u+4l;;6=SSs=M; zq|dSC?1Y3iZ-FmprBx~ob1zLwNoyS1{}>wXP$U84BW2!o#4JD3B*opm+g)9)4~~?9 z*TEpVhg^p;2Rb@A$Jb!JOUlaHKLXc%{P;0wY+O2}we~~Mzc3AN-38X2HR0IG*D~=? z>t``2?H69@@UP%l)P7FsKu>4xHx(US)5Eh@d3oJ|Kr3#%0_2xCOwf{uoov-g1O^!w z_#p7;BOo^cXL$VEz>C#ZGe${GooDn+nr^u78BJ$+oX;)AqjX20PC;9g{OAVE>qo=_ zhoDdbH1(*)V=|xRxK+AtT(KOu&fk=8(%xs{oEu9`2AYS++ASXh>SyOC2-tb5cuuBB z#}#L1Wexs{);f3Y952Zp)RdG5r8T~oXr$o{ z_iT6+9*^(R`t<3O#)Pnou@U&PW*t7m);AxZyAO>yfLZgMAxOya%F$DKXfcIDaM}bo z?K1n9pU0u=Q?}Bzw6p}&)Wq1BXy@>KsFt8>ZEjrE1$5@rnKQY{(NH2bd^>zF=vryS z3zWo}#OB7voi1Sjn>SoKn_#|Wt5X`7_>y6Kj4%BUXqiyK5^B+)5kim9>ta*EoG0Qg z=$2nt$V<4%buQ(@ht{uOpRF8ke0y2k__onLsY1vE09FIPeUF)d&gBbV-^q{U{{H^S z@{v+E=`rTLxk)RjO@D70fTd5*$mlKJ_Nu6G6BrZ~TW~Cgbj17e(oO{kh>>Mzm4ip{ zZ%Odvl$5nnW>9p*2sq3`Mc)^G`mO1X`8ILbkyOH#CMBpX_ea?Ux=oCGb!%(zOL=+d z25P9QXKEGA!^?o!y9ckhv%NiOgJSez6frdU;!C^_cy!zvF+Mmpw(8NC6!fX=57#DB z05$0XpzSk(z6?5!>ODpQfvxH%htLi|3!7u!?M#B|;5Tm^R%bQ%wZJf7dKzqIS(*j@ znukD)h(6PP>|nlk+nXz)=mF15du!|B($Yy=j4uf~TZ5y3yOaXOoo#I@V0j^myE}vG z_vpJ|@W07Uosy>31W8|p6llHpv*X@~Gc9z=ii_7lH-il*2>v9v5{HZkM2UE~gG>e$ z0ERQ@WU)4(~#=kQlqp2AYg+Ox+BvGAtY{D8?I^KRA z>+R`*@b|vZ_7S+SfV&)Y&EEG3<0PPY1s=B5_qVQo*Hv(OM_Ga0t(yCxBPk_?ZdZDw zg)sBuG?|Q?U5#uU((i3*SnOA7Pq8DVzj*QDPcwc)V>EnEiYY6Td%Ks`1A&Fyr(I|c zMR#wr&;=q~D(R$ow8+MYR(9FmmdM;$f;D&(BE*#ZA9F89>;5su%6A+mfE?h8QfljxlxSuE@au+!Yk3^H{0{CZP?CfFykRa25vHB@Ls)o%j7&rC`K#W2dj+1pVRTmtpetDZhw{FAwjML z6NjM1kicPSVuBt8*dNX^=NTFrn4Q_5KM63>Z;?q3A$GsB!mg*#L9r^Us(#{razP3K ziD-w3_SIQ*=f4L(ihHFuESd$R0&qJRW29doP-*UFyo1*6VYqc1$IoBCnkWJ279mIZ zAWTyG2@vN3>5=8a1t@&&Tp2E*iv&8+Ac*ymP)h1{K+HpLUAx?o9G;G%jP!Mg1ehg| zr=U%ruL=H@&1DnWjj7{k=%Jq%x}~n(<3&v2Rq8fBRFPp7cLE-d&M4DqMa5>wIm8#b zIy+ZDiW&=i0?T%$08SZ9kBy1nj9cz6vf3iGp6$83zXXs(xYjo}xxneix(L7r^oF*I z<}3|OMrLMIP|yOZ8r^;W0#bb=w>@BL5f!+ML4ZTEJ35uM-r)X$;yeZVL~OSg_418_ zU%r(8dO{4_($X?==efT>iZfTP6o-KC8JtwWDG$U`408D+7|Eu$KwJc74kBqDi0p-h z_9=&-Qk?u3X)HshcPE;nXF4<3i5ndqZHfuir*4r#%`y98tpx;|s)`D$Y{1zYxvGk@L8t*WSuqx9o5G@|hQ#9UUMx?(-V^-~y3LHvx+XYAH11%(T>tENRt#{wq`c1Z#E8 zO5bzhzngUA<^s61$Fggps`q;scwtd!dx()jQ}x}6Tq|F_Qu#VT z-~+#h*BydJ`Ug<)_Ch^VN6o(~VQBH1opq@+M4*EA^E5);QjXnXqfDM~4QvQNQ; zgQ#N+rmJhhlz zaJ&F|9sd3#fOB461g7;ZCheB6l1YQ;tDqbL)G9!K)gZ%c=w!ya2wRX;1MLUDX@}Ge z#|3&x*ZNq<{DCiDg3&%nsu~_IgP>ICju^<2J4sZ)MbP)lzX?SP5H3*Oj%mi37Mvof z?(8gp&M9cyNlLB`*4877j`Q>L`BO00`{ohn1~@YW*3$ET2cop%R3E~oL$~zm$utSgl*!gUJN^^5(!xn4*2wFrbBVKXO zHG#i!L>L|=bL&>3H?)@k%dQTWyKdyZe;*K1t#A}YRsy6i5voEkd4eVl&CPp_5>it3 z2fT+}a$5B1;R>*vL4E-vh9T$|eyE!+0NFG~ZJ;n!%dA$zm3G?^P&eCaAYP!vgF%27 zn&Z|#K0*_8nr5=Btjtz%^52FQaeM&+{)WfPlgdChp-T&b8;IKAlX$QGAz|$6^4gk_ zQ?|$6?jZ>;DE3N@9Sm~!6RJxTNTy(uf{=CBN`HS@F)>fAs~3ZF$!H75zCO0GnFb=W zzJNKnJ_3?aQ_*LD=rU$JsEg;$#oqhm1G=*kqdtJ&MK?G+16tPX`ehT3;Aifpay@;0 z34{m1ol7bW+E!1GBOJJ!z1IRg{p4S1K9KIyxPDJfrKP8DLR1HwdtG(}XO&GsK6C7^uFQ2r+>jp7hLR5p;@_>Be(;> z`mezKsu^S`u$;|IPai#cG?frUm(jVo9a}|I%|@TUO@wM{5Aor=7JX2br_N_5C3&MA zB=}3*640r{^z>jU(lHQ zPi7Yu)4`46%rI!de3)eX3jiE=<-o?|Qc5G`U>59Y3bh72G8=g*%%n7S5Tu!m`v zJ~pwmoL|n?D6vT@CPq83pzkCkBpA0t2LW6n^5j);WDs}>-J)6UJ! zfj7Ypbi9-J*w}O9{g9)(^+vG&%Vfh$LXs zqWtF{wsQY_q_|5S5V$R#RaI4felnt>7-D=FxZEe_=jkXY4gt`Pd?k*{&4t5PVfT-` zQPI^^I1)c{1zIgY5Elq#2w2^KczSaJ3GiC&_1u)T7~-4EdP>0 zT@Yw#?z`LJ7JX0{rBg{?9i*%VR~q3O*z8XbI%|Uay|uG5iST4Kq$8-n3-a?}b)5$( z7XWWso)hBAUY--tg-i}jl%(R)(xynhY=ETtKVXq^pP$5zXrU*_nxbwDn1VfDE!Ct3 zOk2~f!)|Cr2WJQr6yOt9(uY-(yJ-Qdn)w%(@IwrEz+)dTuZ!Bn)}TXY za;2rFzKx2KYxs!=NPBc2x&Ikjp{Yyo8XI7yfqsh3Dx3vLomX6$gzx}o^0K{UsOHJX zSyQDRn-j0$)JV6&{_epm{P}v$<9oEgT9pJr=w1M6Tuu&po{_}k_HD|7uWXyD>hWu! zd4HhwIeOX#d>96li$7ZvZ-QXj;hf071@Q-Ssu0az03a7oepec)h0OWskG>6HI~^%X;xbu8J;>k?#=LffAFG3xNx&W!!1i zf_hXc^rmK9sYw5mOfclq2-0PjmPRyB+;u;8!G4=Qi|`UGGng@?ZrIPS|c>{&!hLWV@IGoe++*)5>e>@!?W!Mn5BB78h z#XbdK{;HSoHni%X4e9Zm$h6KOht!wBSHHE?cH+1sf$36YcsLv?+E<~0<&QAuNHDM> zrL{vtL+GKsjNcOz4%_RG!scgZ2h#MYZFO+a`=Vp;j7V8rT%5#WPjVowZHtlB==mR2 z*++IbdHF`jlh9iuId(hxwyG*HY%wl!aaNV~m1sDX07pxtdq4r?WMiAkL=GQ63#X}Z zHE0O|=NF-&7vetC#c8^#{8K02m^^8WjUJ#oNDh-P4#Khb)1l7!c~zxB?OV6ZV6T9M z4O|@IH*A@Ep&`&sEAkOwJr6(E~|)bb|47LF=Xuqfm#_U-3@Ni8fgDhCyyr{_lq zMgoe#fdO~t9u&mkF^EtDxH`b8%MjuS%^1k4V*g1F3=H>S0>%7*=D}H;e>vVq!b_$d zsUnpR0fGMWJMa)SEfl^La^d|;BKLDXpfdUp9D=e>fSCQHgFY0^Oz7XBBiIM;{jvO? zTyT)ia8@U)fz6DKj(VNka1{>xDoz!A8*(vLlj!(y_m%0;mgAsgL`Oe7iQXQs%Zvw) zE2wu+4aa{QhNN6((a&o@E^~pG7uc))w^tV+J;AZCP|&RFFG14~DrWTEFw(im>inRY zkx@!wBE`9L%_@MHpwRK^S3?HNC5(%YugMw$T^>Da{N)au8N9iFbP=Ol3V1tt^Az+jS;hiY%HxV8ft287UPLLp#yy@xb_vZvpX9NP* zjx!$0o!{<{O-<7i5=H?(Pf}1o+mt|HXX1PKA#_J*LrmAjkem;;Qu#ELmv<^d8dy<$C4iN<) z61TouVO3kGXIEupWfQt!V;v)Cxk(V0nkpU6Bq-<#-VLTh@ePCCT=esFNGDUhgal|H zzezb@wdi-Tu=+r@`HEyiGa*TcfF(m~5QsgH<6udqP?){Gq8zX{0huT6%%wPa5{_C8 z^MG~m5-c?wEQh?hYsF0Vy>E&RSEDk>SdA!0Hek z@f0mJ@YhLjL7>Ol+Wvu4UIxX&tO#@x{imR?00x$oogK?#Ms;HZKo5ML0G%TCv!{rw zo0|idIL9eWFTkm5ad@?$vlud$2vMJzJWk{|oYW!Nfe*u3(6?6%Wfc^T6ITxpgB84> zzbC}Pf;i#G)Rc_m-Af?Gjl-nOe$nYxU<4gZ3Km5h_3f0>U5Q$U?xNNn6;J^v z%uD2fuu+D9SjjICr+SlMWM-xePRnYpgK+}5Ohm*)%sbmSHK_IJ0*@S!DtvtjeD(kc zito!^XdfJOgS7&`B>18xKboNC^?WK&F)AS&a+MJ*699HY5P+xwdpQ>1ne(bR7!u(7 zJiube4I=n$@f6MGq}%ztTI}Bf$%plGz7~QSdvg1IvZs%=xk^Y zoEEd(nuDsBv=h*0g<7!6pNN(=I)D^!x(0TOfalNqK`)PvroDBPh)91$m;}Rw2W+wX z5nJlK!p?J%)pMZS36v`vNIs|NHKPb|M``(&q45W~>p{`XaHZR=M$f3IC@vy>K*J{t z3~C}Cg%=!oh3l-pPHtpU!He+l=Z%_kERI7DJs(kBcO7o1!oIR`Ev z`9?*|#^xr&C%-&o`Pg!aB`*C96oqhT6$s|z?YH2EnevO0<6&COy9ZdQPpt&bFJOFu zzP>;)9s|QMRf7~52(C7ZFU`%(0|QZQa7K?8TmqIg$g{O!IoY9HAJceKx&S zkjM3AY4E-|ff6;vJ zM_++if8QuHa{m491sN)w>K`Ns!ibcV)CH`0?ts-OvQKhgZP)p}7p5 zCHz6=d;}TE$bu9Yx91@{7#@844jfLa$j_&QD?pi`0>Sqa;AnJobO|N9DYqHPdHaI!@sb=eN0|Yow>!L+G;5h9SNQp_{GwEw>MKuX}Je>h_Gl2R5 zBD$|7vN3S5qE=HlsT;+^vmU*O)FT6NV0DgN3WVwv fx; sentence=Allows Arduino boards to control a variety of servo motors. paragraph=This library can control a great number of servos.
It makes careful use of timers: the library can control 12 servos using only 1 timer.
On the Arduino Due you can control up to 60 servos. category=Device Control url=https://www.arduino.cc/reference/en/libraries/servo/ -architectures=avr,megaavr,sam,samd,nrf52,stm32f4,mbed,mbed_nano,mbed_portenta,mbed_rp2040 +architectures=avr,megaavr,sam,samd,nrf52,stm32f4,mbed,mbed_nano,mbed_portenta,mbed_rp2040,renesas,renesas_portenta,renesas_uno diff --git a/trunk/Arduino/libraries/Servo/src/Servo.h b/trunk/Arduino/libraries/Servo/src/Servo.h index 1f52912b..aab9c16a 100644 --- a/trunk/Arduino/libraries/Servo/src/Servo.h +++ b/trunk/Arduino/libraries/Servo/src/Servo.h @@ -73,6 +73,8 @@ #include "megaavr/ServoTimers.h" #elif defined(ARDUINO_ARCH_MBED) #include "mbed/ServoTimers.h" +#elif defined(ARDUINO_ARCH_RENESAS) +#include "renesas/ServoTimers.h" #else #error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor." #endif @@ -105,7 +107,7 @@ class Servo { public: Servo(); - uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure + uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or INVALID_SERVO if failure uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. void detach(); void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds diff --git a/trunk/Arduino/libraries/Servo/src/mbed/Servo.cpp b/trunk/Arduino/libraries/Servo/src/mbed/Servo.cpp index d2212d45..efb67f97 100644 --- a/trunk/Arduino/libraries/Servo/src/mbed/Servo.cpp +++ b/trunk/Arduino/libraries/Servo/src/mbed/Servo.cpp @@ -4,6 +4,12 @@ #include #include +#if defined __has_include +# if __has_include ("pinDefinitions.h") +# include "pinDefinitions.h" +# endif +#endif + class ServoImpl { mbed::DigitalOut *pin; mbed::Timeout timeout; // calls a callback once when a timeout expires @@ -40,10 +46,10 @@ public: static ServoImpl* servos[MAX_SERVOS]; // static array of servo structures uint8_t ServoCount = 0; // the total number of attached servos -#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min) // minimum value in uS for this servo -#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max) // maximum value in uS for this servo +#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min) // minimum value in us for this servo +#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max) // maximum value in us for this servo -#define TRIM_DURATION 15 //callback overhead (35 uS) -> 15uS if toggle() is called after starting the timeout +#define TRIM_DURATION 15 //callback overhead (35 us) -> 15 us if toggle() is called after starting the timeout Servo::Servo() { @@ -130,4 +136,4 @@ bool Servo::attached() return servos[this->servoIndex] != NULL; } -#endif \ No newline at end of file +#endif diff --git a/trunk/Arduino/libraries/Servo/src/mbed/ServoTimers.h b/trunk/Arduino/libraries/Servo/src/mbed/ServoTimers.h index fc52bf5e..47f226f0 100644 --- a/trunk/Arduino/libraries/Servo/src/mbed/ServoTimers.h +++ b/trunk/Arduino/libraries/Servo/src/mbed/ServoTimers.h @@ -1 +1 @@ -#define _Nbr_16timers 32 \ No newline at end of file +#define _Nbr_16timers 32 diff --git a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Button.h b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Button.h index 7e0c5097..3a0e2d56 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Button.h +++ b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Button.h @@ -6,8 +6,8 @@ // within button ***************************************************************************************/ -class TFT_eSPI_Button : public TFT_eSPI { - +class TFT_eSPI_Button +{ public: TFT_eSPI_Button(void); // "Classic" initButton() uses centre & size diff --git a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Smooth_font.cpp b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Smooth_font.cpp index d1915a48..c67204ac 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Smooth_font.cpp +++ b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Smooth_font.cpp @@ -48,7 +48,7 @@ void TFT_eSPI::loadFont(String fontName, bool flash) 6. Descent in pixels from baseline to bottom of "p" Next are gCount sets of values for each glyph, each set comprises 7 int32t parameters (28 bytes): - 1. Glyph Unicode stored as a 32 bit value + 1. Glyph Unicode stored as a 32-bit value 2. Height of bitmap bounding box 3. Width of bitmap bounding box 4. gxAdvance for cursor (setWidth in Processing) @@ -57,7 +57,7 @@ void TFT_eSPI::loadFont(String fontName, bool flash) 7. padding value, typically 0 The bitmaps start next at 24 + (28 * gCount) bytes from the start of the file. - Each pixel is 1 byte, an 8 bit Alpha value which represents the transparency from + Each pixel is 1 byte, an 8-bit Alpha value which represents the transparency from 0xFF foreground colour, 0x00 background. The library uses a linear interpolation between the foreground and background RGB component colours. e.g. pixelRed = ((fgRed * alpha) + (bgRed * (255 - alpha))/255 @@ -158,7 +158,7 @@ void TFT_eSPI::loadMetrics(void) #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) if ( psramFound() ) { - gUnicode = (uint16_t*)ps_malloc( gFont.gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF) + gUnicode = (uint16_t*)ps_malloc( gFont.gCount * 2); // Unicode 16-bit Basic Multilingual Plane (0-FFFF) gHeight = (uint8_t*)ps_malloc( gFont.gCount ); // Height of glyph gWidth = (uint8_t*)ps_malloc( gFont.gCount ); // Width of glyph gxAdvance = (uint8_t*)ps_malloc( gFont.gCount ); // xAdvance - to move x cursor @@ -169,7 +169,7 @@ void TFT_eSPI::loadMetrics(void) else #endif { - gUnicode = (uint16_t*)malloc( gFont.gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF) + gUnicode = (uint16_t*)malloc( gFont.gCount * 2); // Unicode 16-bit Basic Multilingual Plane (0-FFFF) gHeight = (uint8_t*)malloc( gFont.gCount ); // Height of glyph gWidth = (uint8_t*)malloc( gFont.gCount ); // Width of glyph gxAdvance = (uint8_t*)malloc( gFont.gCount ); // xAdvance - to move x cursor @@ -308,7 +308,7 @@ void TFT_eSPI::unloadFont( void ) /*************************************************************************************** ** Function name: readInt32 -** Description: Get a 32 bit integer from the font file +** Description: Get a 32-bit integer from the font file *************************************************************************************x*/ uint32_t TFT_eSPI::readInt32(void) { @@ -316,18 +316,18 @@ uint32_t TFT_eSPI::readInt32(void) #ifdef FONT_FS_AVAILABLE if (fs_font) { - val = fontFile.read() << 24; - val |= fontFile.read() << 16; - val |= fontFile.read() << 8; - val |= fontFile.read(); + val = (uint32_t)fontFile.read() << 24; + val |= (uint32_t)fontFile.read() << 16; + val |= (uint32_t)fontFile.read() << 8; + val |= (uint32_t)fontFile.read(); } else #endif { - val = pgm_read_byte(fontPtr++) << 24; - val |= pgm_read_byte(fontPtr++) << 16; - val |= pgm_read_byte(fontPtr++) << 8; - val |= pgm_read_byte(fontPtr++); + val = (uint32_t)pgm_read_byte(fontPtr++) << 24; + val |= (uint32_t)pgm_read_byte(fontPtr++) << 16; + val |= (uint32_t)pgm_read_byte(fontPtr++) << 8; + val |= (uint32_t)pgm_read_byte(fontPtr++); } return val; diff --git a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.cpp b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.cpp index 80dadfec..af841cc1 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.cpp +++ b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.cpp @@ -47,7 +47,7 @@ TFT_eSprite::TFT_eSprite(TFT_eSPI *tft) ** Function name: createSprite ** Description: Create a sprite (bitmap) of defined width and height ***************************************************************************************/ -// cast returned value to (uint8_t*) for 8 bit or (uint16_t*) for 16 bit colours +// cast returned value to (uint8_t*) for 8-bit or (uint16_t*) for 16-bit colours void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) { @@ -88,8 +88,6 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) _img8_2 = _img8 + (w * h + 1); } - if ( (_bpp == 4) && (_colorMap == nullptr)) createPalette(default_4bit_palette); - // This is to make it clear what pointer size is expected to be used // but casting in the user sketch is needed due to the use of void* if ( (_bpp == 1) && (frames > 1) ) @@ -101,6 +99,8 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) if (_img8) { _created = true; + if ( (_bpp == 4) && (_colorMap == nullptr)) createPalette(default_4bit_palette); + rotation = 0; setViewport(0, 0, _dwidth, _dheight); setPivot(_iwidth/2, _iheight/2); @@ -223,10 +223,7 @@ void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) ***************************************************************************************/ void TFT_eSprite::createPalette(uint16_t colorMap[], uint8_t colors) { - if (_colorMap != nullptr) - { - free(_colorMap); - } + if (!_created) return; if (colorMap == nullptr) { @@ -236,7 +233,7 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], uint8_t colors) } // Allocate and clear memory for 16 color map - _colorMap = (uint16_t *)calloc(16, sizeof(uint16_t)); + if (_colorMap == nullptr) _colorMap = (uint16_t *)calloc(16, sizeof(uint16_t)); if (colors > 16) colors = 16; @@ -254,6 +251,8 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], uint8_t colors) ***************************************************************************************/ void TFT_eSprite::createPalette(const uint16_t colorMap[], uint8_t colors) { + if (!_created) return; + if (colorMap == nullptr) { // Create a color map using the default FLASH map @@ -261,7 +260,7 @@ void TFT_eSprite::createPalette(const uint16_t colorMap[], uint8_t colors) } // Allocate and clear memory for 16 color map - _colorMap = (uint16_t *)calloc(16, sizeof(uint16_t)); + if (_colorMap == nullptr) _colorMap = (uint16_t *)calloc(16, sizeof(uint16_t)); if (colors > 16) colors = 16; @@ -310,13 +309,9 @@ void* TFT_eSprite::setColorDepth(int8_t b) else if ( b > 1 ) _bpp = 4; else _bpp = 1; - // Can't change an existing sprite's colour depth so delete it - if (_created) free(_img8_1); - - // If it existed, re-create the sprite with the new colour depth - if (_created) - { - _created = false; + // Can't change an existing sprite's colour depth so delete and create a new one + if (_created) { + deleteSprite(); return createSprite(_dwidth, _dheight); } @@ -380,7 +375,7 @@ void TFT_eSprite::deleteSprite(void) if (_colorMap != nullptr) { free(_colorMap); - _colorMap = nullptr; + _colorMap = nullptr; } if (_created) @@ -781,7 +776,7 @@ bool TFT_eSprite::pushToSprite(TFT_eSprite *dspr, int32_t x, int32_t y, uint16_t if (transp == rp) { if (pixel_count) { - dspr->pushImage(ox, y, pixel_count, 1, sline_buffer, _bpp); + dspr->pushImage(ox, y, pixel_count, 1, sline_buffer); ox += pixel_count; pixel_count = 0; } @@ -1109,7 +1104,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_ } else if (_bpp == 4) { - // The image is assumed to be 4 bit, where each byte corresponds to two pixels. + // The image is assumed to be 4-bit, where each byte corresponds to two pixels. // much faster when aligned to a byte boundary, because the alternative is slower, requiring // tedious bit operations. @@ -1360,10 +1355,10 @@ void TFT_eSprite::writeColor(uint16_t color) { if (!_created ) return; - // Write 16 bit RGB 565 encoded colour to RAM + // Write 16-bit RGB 565 encoded colour to RAM if (_bpp == 16) _img [_xptr + _yptr * _iwidth] = color; - // Write 8 bit RGB 332 encoded colour to RAM + // Write 8-bit RGB 332 encoded colour to RAM else if (_bpp == 8) _img8[_xptr + _yptr * _iwidth] = (uint8_t) color; else if (_bpp == 4) @@ -1990,10 +1985,6 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uin { if ( _vpOoB || !_created ) return; - if ((x >= _vpW - _xDatum) || // Clip right - (y >= _vpH - _yDatum)) // Clip bottom - return; - if (c < 32) return; #ifdef LOAD_GLCD //>>>>>>>>>>>>>>>>>> @@ -2002,10 +1993,17 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uin #endif //>>>>>>>>>>>>>>>>>> + if ((x >= _vpW - _xDatum) || // Clip right + (y >= _vpH - _yDatum)) // Clip bottom + return; + if (((x + 6 * size - 1) < (_vpX - _xDatum)) || // Clip left ((y + 8 * size - 1) < (_vpY - _yDatum))) // Clip top return; + if (c > 255) return; + if (!_cp437 && c > 175) c++; + bool fillbg = (bg != color); if ((size==1) && fillbg) @@ -2140,7 +2138,7 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uin /*************************************************************************************** ** Function name: drawChar -** Description: draw a unicode glyph into the sprite +** Description: draw a Unicode glyph into the sprite ***************************************************************************************/ // TODO: Rationalise with TFT_eSPI // Any UTF-8 decoding must be done before calling drawChar() @@ -2292,7 +2290,7 @@ int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t fo uint8_t tnp = 0; // Temporary copy of np for while loop uint8_t ts = textsize - 1; // Temporary copy of textsize - // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area + // 16-bit pixel count so maximum font size is equivalent to 180x180 pixels in area // w is total number of pixels to plot to fill character block while (pc < w) { line = pgm_read_byte((uint8_t *)flash_address); diff --git a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.h b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.h index 5f3e59ef..67e29de7 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.h +++ b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Sprite.h @@ -13,12 +13,12 @@ class TFT_eSprite : public TFT_eSPI { ~TFT_eSprite(void); // Create a sprite of width x height pixels, return a pointer to the RAM area - // Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed + // Sketch can cast returned value to (uint16_t*) for 16-bit depth if needed // RAM required is: // - 1 bit per pixel for 1 bit colour depth - // - 1 nibble per pixel for 4 bit colour (with palette table) - // - 1 byte per pixel for 8 bit colour (332 RGB format) - // - 2 bytes per pixel for 16 bit color depth (565 RGB format) + // - 1 nibble per pixel for 4-bit colour (with palette table) + // - 1 byte per pixel for 8-bit colour (332 RGB format) + // - 2 bytes per pixel for 16-bit color depth (565 RGB format) void* createSprite(int16_t width, int16_t height, uint8_t frames = 1); // Returns a pointer to the sprite or nullptr if not created, user must cast to pointer type @@ -39,7 +39,7 @@ class TFT_eSprite : public TFT_eSPI { void* setColorDepth(int8_t b); int8_t getColorDepth(void); - // Set the palette for a 4 bit depth sprite. Only the first 16 colours in the map are used. + // Set the palette for a 4-bit depth sprite. Only the first 16 colours in the map are used. void createPalette(uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in RAM void createPalette(const uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in FLASH @@ -61,14 +61,14 @@ class TFT_eSprite : public TFT_eSPI { // Fill Sprite with a colour fillSprite(uint32_t color), - // Define a window to push 16 bit colour pixels into in a raster order + // Define a window to push 16-bit colour pixels into in a raster order // Colours are converted to the set Sprite colour bit depth setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1), // Push a color (aka singe pixel) to the sprite's set window area pushColor(uint16_t color), // Push len colors (pixels) to the sprite's set window area pushColor(uint16_t color, uint32_t len), - // Push a pixel pre-formatted as a 1, 4, 8 or 16 bit colour (avoids conversion overhead) + // Push a pixel pre-formatted as a 1, 4, 8 or 16-bit colour (avoids conversion overhead) writeColor(uint16_t color), // Set the scroll zone, top left corner at x,y with defined width and height @@ -139,7 +139,7 @@ class TFT_eSprite : public TFT_eSPI { height(void); // Functions associated with anti-aliased fonts - // Draw a single unicode character using the loaded font + // Draw a single Unicode character using the loaded font void drawGlyph(uint16_t code); // Print string to sprite using loaded font at cursor position void printToSprite(String string); @@ -162,13 +162,13 @@ class TFT_eSprite : public TFT_eSPI { protected: uint8_t _bpp; // bits per pixel (1, 4, 8 or 16) - uint16_t *_img; // pointer to 16 bit sprite - uint8_t *_img8; // pointer to 1 and 8 bit sprite frame 1 or frame 2 - uint8_t *_img4; // pointer to 4 bit sprite (uses color map) + uint16_t *_img; // pointer to 16-bit sprite + uint8_t *_img8; // pointer to 1 and 8-bit sprite frame 1 or frame 2 + uint8_t *_img4; // pointer to 4-bit sprite (uses color map) uint8_t *_img8_1; // pointer to frame 1 uint8_t *_img8_2; // pointer to frame 2 - uint16_t *_colorMap; // color map pointer: 16 entries, used with 4 bit color map. + uint16_t *_colorMap; // color map pointer: 16 entries, used with 4-bit color map. int32_t _sinra; // Sine of rotation angle in fixed point int32_t _cosra; // Cosine of rotation angle in fixed point diff --git a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.cpp b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.cpp index 0c3ee017..3d3ed825 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.cpp +++ b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.cpp @@ -10,6 +10,11 @@ // See license in root directory. +// Define a default pressure threshold +#ifndef Z_THRESHOLD + #define Z_THRESHOLD 350 // Touch pressure threshold for validating touches +#endif + /*************************************************************************************** ** Function name: begin_touch_read_write - was spi_begin_touch ** Description: Start transaction and select touch controller @@ -161,7 +166,6 @@ uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ ** Function name: getTouch ** Description: read callibrated position. Return false if not pressed. ***************************************************************************************/ -#define Z_THRESHOLD 350 // Touch pressure threshold for validating touches uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ uint16_t x_tmp, y_tmp; diff --git a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.h b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.h index d6916972..9bb81fc8 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.h +++ b/trunk/Arduino/libraries/TFT_eSPI/Extensions/Touch.h @@ -11,7 +11,10 @@ // Get the screen touch coordinates, returns true if screen has been touched // if the touch coordinates are off screen then x and y are not updated // The returned value can be treated as a bool type, false or 0 means touch not detected - // In future the function may return an 8 "quality" (jitter) value. + // In future the function may return an 8-bit "quality" (jitter) value. + // The threshold value is optional, this must be higher than the bias level for z (pressure) + // reported by Test_Touch_Controller when the screen is NOT touched. When touched the z value + // must be higher than the threshold for a touch to be detected. uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); // Run screen calibration and test, report calibration values to the serial port diff --git a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font32rle.c b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font32rle.c index f163986c..7a8119b0 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font32rle.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font32rle.c @@ -1,6 +1,6 @@ // Font 4 // -// This font has been 8 bit Run Length Encoded to save FLASH space +// This font has been 8-bit Run Length Encoded to save FLASH space // // This font contains 96 ASCII characters diff --git a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font64rle.c b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font64rle.c index 9d1415b0..a80e6ea7 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font64rle.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font64rle.c @@ -1,6 +1,6 @@ // Font 6 is intended to display numbers and time // -// This font has been 8 bit Run Length Encoded to save FLASH space +// This font has been 8-bit Run Length Encoded to save FLASH space // // This font only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : - . a p m // The Pipe character | is a narrow space to aid formatting diff --git a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72rle.c b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72rle.c index 7f5da5df..478411aa 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72rle.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72rle.c @@ -1,6 +1,6 @@ // Font 8 // -// This font has been 8 bit Run Length Encoded to save FLASH space +// This font has been 8-bit Run Length Encoded to save FLASH space // // It is a Arial 75 pixel height font intended to display large numbers // This font only contains characters [space] 0 1 2 3 4 5 6 7 8 9 0 : - . diff --git a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72x53rle.c b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72x53rle.c index 71c2c4f6..ae8d00cb 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72x53rle.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font72x53rle.c @@ -1,6 +1,6 @@ // Font 8 // -// This font has been 8 bit Run Length Encoded to save FLASH space +// This font has been 8-bit Run Length Encoded to save FLASH space // // It is a Arial 75 pixel height font intended to display large numbers // Width for numerals reduced from 55 to 53 (to fit in 160 pixel screens) diff --git a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font7srle.c b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font7srle.c index 7c6f929b..7d54a6fa 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font7srle.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Fonts/Font7srle.c @@ -1,6 +1,6 @@ // Font 7 // -// This font has been 8 bit Run Length Encoded to save FLASH space +// This font has been 8-bit Run Length Encoded to save FLASH space // // This is a 7 segment font intended to display numbers and time // This font only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : . - diff --git a/trunk/Arduino/libraries/TFT_eSPI/Fonts/glcdfont.c b/trunk/Arduino/libraries/TFT_eSPI/Fonts/glcdfont.c index 882a133b..95c1c98a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Fonts/glcdfont.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Fonts/glcdfont.c @@ -182,8 +182,9 @@ static const unsigned char font[] PROGMEM = { 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, - 0xAA, 0x00, 0x55, 0x00, 0xAA, - 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block 0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, 0x14, 0xFF, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.c b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.c index 30d3d518..faf30343 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.c @@ -8,50 +8,91 @@ // Select the SPI port to use, ESP32 has 2 options #if !defined (TFT_PARALLEL_8_BIT) - #ifdef USE_HSPI_PORT - SPIClass spi = SPIClass(HSPI); - #else // use default VSPI port - //SPIClass& spi = SPI; - SPIClass spi = SPIClass(VSPI); + #ifdef CONFIG_IDF_TARGET_ESP32 + #ifdef USE_HSPI_PORT + SPIClass spi = SPIClass(HSPI); + #elif defined(USE_FSPI_PORT) + SPIClass spi = SPIClass(FSPI); + #else // use default VSPI port + SPIClass spi = SPIClass(VSPI); + #endif + #else + #ifdef USE_HSPI_PORT + SPIClass spi = SPIClass(HSPI); + #elif defined(USE_FSPI_PORT) + SPIClass spi = SPIClass(FSPI); + #else // use FSPI port + SPIClass& spi = SPI; + #endif #endif #endif #ifdef ESP32_DMA // DMA SPA handle spi_device_handle_t dmaHAL; - #ifdef USE_HSPI_PORT - spi_host_device_t spi_host = HSPI_HOST; + #ifdef CONFIG_IDF_TARGET_ESP32 + #define DMA_CHANNEL 1 + #ifdef USE_HSPI_PORT + spi_host_device_t spi_host = HSPI_HOST; + #elif defined(USE_FSPI_PORT) + spi_host_device_t spi_host = SPI_HOST; + #else // use VSPI port + spi_host_device_t spi_host = VSPI_HOST; + #endif #else - spi_host_device_t spi_host = VSPI_HOST; + #ifdef USE_HSPI_PORT + #define DMA_CHANNEL SPI_DMA_CH_AUTO + spi_host_device_t spi_host = (spi_host_device_t) SPI3_HOST; // Draws once then freezes + #else // use FSPI port + #define DMA_CHANNEL SPI_DMA_CH_AUTO + spi_host_device_t spi_host = (spi_host_device_t) SPI2_HOST; // Draws once then freezes + #endif #endif #endif +#if !defined (TFT_PARALLEL_8_BIT) + // Volatile for register reads: + volatile uint32_t* _spi_cmd = (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT)); + volatile uint32_t* _spi_user = (volatile uint32_t*)(SPI_USER_REG(SPI_PORT)); + // Register writes only: + volatile uint32_t* _spi_mosi_dlen = (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT)); + volatile uint32_t* _spi_w = (volatile uint32_t*)(SPI_W0_REG(SPI_PORT)); +#endif + //////////////////////////////////////////////////////////////////////////////////////// #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** -** Function name: beginSDA -** Description: Detach SPI from pin to permit software SPI +** Function name: beginSDA - VSPI port only, FPSI port only for S2 +** Description: Detach MOSI and attach MISO to SDA for reads ***************************************************************************************/ void TFT_eSPI::begin_SDA_Read(void) { - pinMatrixOutDetach(TFT_MOSI, false, false); - pinMode(TFT_MOSI, INPUT); - pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false); + gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_INPUT); + #ifdef CONFIG_IDF_TARGET_ESP32 + pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false); + #else // S2 + pinMatrixInAttach(TFT_MOSI, FSPIQ_IN_IDX, false); + #endif + SET_BUS_READ_MODE; } /*************************************************************************************** -** Function name: endSDA -** Description: Attach SPI pins after software SPI +** Function name: endSDA - VSPI port only, FPSI port only for S2 +** Description: Attach MOSI to SDA and detach MISO for writes ***************************************************************************************/ void TFT_eSPI::end_SDA_Read(void) { - pinMode(TFT_MOSI, OUTPUT); - pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false); - pinMode(TFT_MISO, INPUT); - pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false); + gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_OUTPUT); + #ifdef CONFIG_IDF_TARGET_ESP32 + pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false); + #else // S2 + pinMatrixOutAttach(TFT_MOSI, FSPID_OUT_IDX, false, false); + #endif + SET_BUS_WRITE_MODE; } + //////////////////////////////////////////////////////////////////////////////////////// #endif // #if defined (TFT_SDA_READ) //////////////////////////////////////////////////////////////////////////////////////// @@ -59,7 +100,7 @@ void TFT_eSPI::end_SDA_Read(void) /*************************************************************************************** ** Function name: read byte - supports class functions -** Description: Read a byte from ESP32 8 bit data port +** Description: Read a byte from ESP32 8-bit data port ***************************************************************************************/ // Parallel bus MUST be set to input before calling this function! uint8_t TFT_eSPI::readByte(void) @@ -98,17 +139,7 @@ uint8_t TFT_eSPI::readByte(void) ***************************************************************************************/ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) { - gpioMode(TFT_D0, mode); - gpioMode(TFT_D1, mode); - gpioMode(TFT_D2, mode); - gpioMode(TFT_D3, mode); - gpioMode(TFT_D4, mode); - gpioMode(TFT_D5, mode); - gpioMode(TFT_D6, mode); - gpioMode(TFT_D7, mode); - return; - /* - // Arduino generic native function, but slower + // Arduino generic native function pinMode(TFT_D0, mode); pinMode(TFT_D1, mode); pinMode(TFT_D2, mode); @@ -117,7 +148,6 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) pinMode(TFT_D5, mode); pinMode(TFT_D6, mode); pinMode(TFT_D7, mode); - return; //*/ } /*************************************************************************************** @@ -126,14 +156,8 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) ***************************************************************************************/ void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode) { - if(mode == INPUT) GPIO.enable_w1tc = ((uint32_t)1 << gpio); - else GPIO.enable_w1ts = ((uint32_t)1 << gpio); - - ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[gpio].reg) // Register lookup - = ((uint32_t)2 << FUN_DRV_S) // Set drive strength 2 - | (FUN_IE) // Input enable - | ((uint32_t)2 << MCU_SEL_S); // Function select 2 - GPIO.pin[gpio].val = 1; // Set pin HIGH + pinMode(gpio, mode); + digitalWrite(gpio, HIGH); } //////////////////////////////////////////////////////////////////////////////////////// #endif // #ifdef TFT_PARALLEL_8_BIT @@ -173,54 +197,96 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) } //////////////////////////////////////////////////////////////////////////////////////// -#elif !defined (ILI9488_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most displays +#elif !defined (SPI_18BIT_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most SPI displays //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** ** Function name: pushBlock - for ESP32 ** Description: Write a block of pixels of the same colour ***************************************************************************************/ +/* void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ - - uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); + uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); + bool empty = true; + volatile uint32_t* spi_w = (volatile uint32_t*)_spi_w; if (len > 31) { - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); + *_spi_mosi_dlen = 511; + spi_w[0] = color32; + spi_w[1] = color32; + spi_w[2] = color32; + spi_w[3] = color32; + spi_w[4] = color32; + spi_w[5] = color32; + spi_w[6] = color32; + spi_w[7] = color32; + spi_w[8] = color32; + spi_w[9] = color32; + spi_w[10] = color32; + spi_w[11] = color32; + spi_w[12] = color32; + spi_w[13] = color32; + spi_w[14] = color32; + spi_w[15] = color32; while(len>31) { - while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); - WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color32); - WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color32); - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); + while ((*_spi_cmd)&SPI_USR); + *_spi_cmd = SPI_USR; len -= 32; } - while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + empty = false; } if (len) { - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1); - for (uint32_t i=0; i <= (len<<1); i+=4) WRITE_PERI_REG(SPI_W0_REG(SPI_PORT) + i, color32); - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); - while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + if(empty) { + for (uint32_t i=0; i <= len; i+=2) *spi_w++ = color32; + } + len = (len << 4) - 1; + while (*_spi_cmd&SPI_USR); + *_spi_mosi_dlen = len; + *_spi_cmd = SPI_USR; } + while ((*_spi_cmd)&SPI_USR); // Move to later in code to use transmit time usefully? } +//*/ +//* +void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ + volatile uint32_t* spi_w = _spi_w; + uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8); + uint32_t i = 0; + uint32_t rem = len & 0x1F; + len = len - rem; + + // Start with partial buffer pixels + if (rem) + { + while (*_spi_cmd&SPI_USR); + for (i=0; i < rem; i+=2) *spi_w++ = color32; + *_spi_mosi_dlen = (rem << 4) - 1; + *_spi_cmd = SPI_USR; + if (!len) return; //{while (*_spi_cmd&SPI_USR); return; } + i = i>>1; while(i++<16) *spi_w++ = color32; + } + + while (*_spi_cmd&SPI_USR); + if (!rem) while (i++<16) *spi_w++ = color32; + *_spi_mosi_dlen = 511; + + // End with full buffer to maximise useful time for downstream code + while(len) + { + while (*_spi_cmd&SPI_USR); + *_spi_cmd = SPI_USR; + len -= 32; + } + + // Do not wait here + //while (*_spi_cmd&SPI_USR); +} +//*/ /*************************************************************************************** ** Function name: pushSwapBytePixels - for ESP32 ** Description: Write a sequence of pixels with swapped bytes @@ -242,7 +308,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ data+=4; } while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); - WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color[1]); WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color[2]); WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color[3]); @@ -273,7 +339,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ } while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 255); - WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color[1]); WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color[2]); WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color[3]); @@ -349,7 +415,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ } //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (ILI9488_DRIVER) && !defined (TFT_PARALLEL_8_BIT)// Now code for ILI9488 +#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -362,7 +428,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) uint32_t r = (color & 0xF800)>>8; uint32_t g = (color & 0x07E0)<<5; uint32_t b = (color & 0x001F)<<19; - // Concatenate 4 pixels into three 32 bit blocks + // Concatenate 4 pixels into three 32-bit blocks uint32_t r0 = r<<24 | b | g | r; uint32_t r1 = r0>>8 | g<<16; uint32_t r2 = r1>>8 | b<<8; @@ -446,7 +512,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ } //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (TFT_PARALLEL_8_BIT) // Now the code for ESP32 8 bit parallel +#elif defined (TFT_PARALLEL_8_BIT) // Now the code for ESP32 8-bit parallel //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -454,10 +520,22 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ ** Description: Write a block of pixels of the same colour ***************************************************************************************/ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ + #if defined (SSD1963_DRIVER) + if ( ((color & 0xF800)>> 8) == ((color & 0x07E0)>> 3) && ((color & 0xF800)>> 8)== ((color & 0x001F)<< 3) ) + #else if ( (color >> 8) == (color & 0x00FF) ) + #endif { if (!len) return; tft_Write_16(color); - while (--len) {WR_L; WR_H; WR_L; WR_H;} + #if defined (SSD1963_DRIVER) + while (--len) {WR_L; WR_H; WR_L; WR_H; WR_L; WR_H;} + #else + #ifdef PSEUDO_16_BIT + while (--len) {WR_L; WR_H;} + #else + while (--len) {WR_L; WR_H; WR_L; WR_H;} + #endif + #endif } else while (len--) {tft_Write_16(color);} } @@ -489,7 +567,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ //////////////////////////////////////////////////////////////////////////////////////// -#if defined ESP32_DMA && !defined (TFT_PARALLEL_8_BIT) // DMA FUNCTIONS +#if defined (ESP32_DMA) && !defined (TFT_PARALLEL_8_BIT) // DMA FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -534,13 +612,14 @@ void TFT_eSPI::dmaWait(void) /*************************************************************************************** -** Function name: pushImageDMA +** Function name: pushPixelsDMA ** Description: Push pixels to TFT (len must be less than 32767) ***************************************************************************************/ // This will byte swap the original image if setSwapBytes(true) was called by sketch. void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) { if ((len == 0) || (!DMA_Enabled)) return; + dmaWait(); if(_swapBytes) { @@ -564,6 +643,38 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) } +/*************************************************************************************** +** Function name: pushImageDMA +** Description: Push image to a window (w*h must be less than 65536) +***************************************************************************************/ +// Fixed const data assumed, will NOT clip or swap bytes +void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* image) +{ + if ((w == 0) || (h == 0) || (!DMA_Enabled)) return; + + uint32_t len = w*h; + + dmaWait(); + + setAddrWindow(x, y, w, h); + + esp_err_t ret; + static spi_transaction_t trans; + + memset(&trans, 0, sizeof(spi_transaction_t)); + + trans.user = (void *)1; + trans.tx_buffer = image; //Data pointer + trans.length = len * 16; //Data length, in bits + trans.flags = 0; //SPI_TRANS_USE_TXDATA flag + + ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); + assert(ret == ESP_OK); + + spiBusyCheck++; +} + + /*************************************************************************************** ** Function name: pushImageDMA ** Description: Push image to a window (w*h must be less than 65536) @@ -571,24 +682,27 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) // This will clip and also swap bytes if setSwapBytes(true) was called by sketch void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer) { - if ((x >= _width) || (y >= _height) || (!DMA_Enabled)) return; + if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return; int32_t dx = 0; int32_t dy = 0; int32_t dw = w; int32_t dh = h; - if (x < 0) { dw += x; dx = -x; x = 0; } - if (y < 0) { dh += y; dy = -y; y = 0; } + if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } + if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } - if ((x + dw) > _width ) dw = _width - x; - if ((y + dh) > _height) dh = _height - y; + if ((x + dw) > _vpW ) dw = _vpW - x; + if ((y + dh) > _vpH ) dh = _vpH - y; if (dw < 1 || dh < 1) return; uint32_t len = dw*dh; - if (buffer == nullptr) { buffer = image; dmaWait(); } + if (buffer == nullptr) { + buffer = image; + dmaWait(); + } // If image is clipped, copy pixels into a contiguous block if ( (dw != w) || (dh != h) ) { @@ -616,7 +730,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t } } - if (spiBusyCheck) dmaWait(); // Incase we did not wait earlier + if (spiBusyCheck) dmaWait(); // In case we did not wait earlier setAddrWindow(x, y, dw, dh); @@ -649,15 +763,26 @@ extern "C" void dc_callback(); void IRAM_ATTR dc_callback(spi_transaction_t *spi_tx) { - if ((bool)spi_tx->user) DC_D; - else DC_C; + if ((bool)spi_tx->user) {DC_D;} + else {DC_C;} +} + +/*************************************************************************************** +** Function name: dma_end_callback +** Description: Clear DMA run flag to stop retransmission loop +***************************************************************************************/ +extern "C" void dma_end_callback(); + +void IRAM_ATTR dma_end_callback(spi_transaction_t *spi_tx) +{ + WRITE_PERI_REG(SPI_DMA_CONF_REG(spi_host), 0); } /*************************************************************************************** ** Function name: initDMA ** Description: Initialise the DMA engine - returns true if init OK ***************************************************************************************/ -bool TFT_eSPI::initDMA(void) +bool TFT_eSPI::initDMA(bool ctrl_cs) { if (DMA_Enabled) return false; @@ -668,10 +793,20 @@ bool TFT_eSPI::initDMA(void) .sclk_io_num = TFT_SCLK, .quadwp_io_num = -1, .quadhd_io_num = -1, + #ifdef xCONFIG_IDF_TARGET_ESP32S2 + .data4_io_num = -1, + .data5_io_num = -1, + .data6_io_num = -1, + .data7_io_num = -1, + #endif .max_transfer_sz = TFT_WIDTH * TFT_HEIGHT * 2 + 8, // TFT screen size .flags = 0, .intr_flags = 0 }; + + int8_t pin = -1; + if (ctrl_cs) pin = TFT_CS; + spi_device_interface_config_t devcfg = { .command_bits = 0, .address_bits = 0, @@ -682,13 +817,17 @@ bool TFT_eSPI::initDMA(void) .cs_ena_posttrans = 0, .clock_speed_hz = SPI_FREQUENCY, .input_delay_ns = 0, - .spics_io_num = TFT_CS, - .flags = 0, - .queue_size = 7, - .pre_cb = dc_callback, //Callback to handle D/C line - .post_cb = 0 + .spics_io_num = pin, + .flags = SPI_DEVICE_NO_DUMMY, //0, + .queue_size = 1, + .pre_cb = 0, //dc_callback, //Callback to handle D/C line + #ifdef CONFIG_IDF_TARGET_ESP32 + .post_cb = 0 + #else + .post_cb = dma_end_callback + #endif }; - ret = spi_bus_initialize(spi_host, &buscfg, 1); + ret = spi_bus_initialize(spi_host, &buscfg, DMA_CHANNEL); ESP_ERROR_CHECK(ret); ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL); ESP_ERROR_CHECK(ret); @@ -711,5 +850,5 @@ void TFT_eSPI::deInitDMA(void) } //////////////////////////////////////////////////////////////////////////////////////// -#endif // End of DMA FUNCTIONS +#endif // End of DMA FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////// diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.h b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.h index fd56dce3..ad60e3dd 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32.h @@ -11,21 +11,71 @@ // Include processor specific header #include "soc/spi_reg.h" #include "driver/spi_master.h" +#include "hal/gpio_ll.h" -// Processor specific code used by SPI bus transaction startWrite and endWrite functions -#define SET_BUS_WRITE_MODE // Not used -#define SET_BUS_READ_MODE // Not used +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32) + #define CONFIG_IDF_TARGET_ESP32 +#endif + +// Fix IDF problems with ESP32C3 +#if CONFIG_IDF_TARGET_ESP32C3 + // Fix ESP32C3 IDF bug for missing definition + #ifndef REG_SPI_BASE + #define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 ))) + #endif + + // Fix ESP32C3 IDF bug for name change + #ifndef SPI_MOSI_DLEN_REG + #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) + #endif + + // Fix ESP32C3 specific register reference + #define out_w1tc out_w1tc.val + #define out_w1ts out_w1ts.val +#endif // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled #if !defined (SUPPORT_TRANSACTIONS) #define SUPPORT_TRANSACTIONS #endif +/* +ESP32: +FSPI not defined +HSPI = 2, uses SPI2 +VSPI = 3, uses SPI3 + +ESP32-S2: +FSPI = 1, uses SPI2 +HSPI = 2, uses SPI3 +VSPI not defined + +ESP32 C3: +FSPI = 0, uses SPI2 ???? To be checked +HSPI = 1, uses SPI3 ???? To be checked +VSPI not defined + +For ESP32/S2/C3: +SPI1_HOST = 0 +SPI2_HOST = 1 +SPI3_HOST = 2 +*/ + // ESP32 specific SPI port selection #ifdef USE_HSPI_PORT - #define SPI_PORT HSPI + #ifdef CONFIG_IDF_TARGET_ESP32 + #define SPI_PORT HSPI //HSPI is port 2 on ESP32 + #else + #define SPI_PORT 3 //HSPI is port 3 on ESP32 S2 + #endif +#elif defined(USE_FSPI_PORT) + #define SPI_PORT 2 //FSPI(ESP32 S2) #else - #define SPI_PORT VSPI + #ifdef CONFIG_IDF_TARGET_ESP32 + #define SPI_PORT VSPI + #else + #define SPI_PORT 2 //FSPI(ESP32 S2) + #endif #endif #ifdef RPI_DISPLAY_TYPE @@ -37,22 +87,37 @@ // Initialise processor specific SPI functions, used by init() #define INIT_TFT_DATA_BUS // Not used -// Define a generic flag for 8 bit parallel +// Define a generic flag for 8-bit parallel #if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility #if !defined (TFT_PARALLEL_8_BIT) #define TFT_PARALLEL_8_BIT // Generic parallel flag #endif #endif -// Ensure ESP32 specific flag is defined for 8 bit parallel +// Ensure ESP32 specific flag is defined for 8-bit parallel #if defined (TFT_PARALLEL_8_BIT) #if !defined (ESP32_PARALLEL) #define ESP32_PARALLEL #endif #endif +// Processor specific code used by SPI bus transaction startWrite and endWrite functions +#if !defined (ESP32_PARALLEL) + #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) + #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE + #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE + #else + #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI + #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN + #endif +#else + // Not applicable to parallel bus + #define SET_BUS_WRITE_MODE + #define SET_BUS_READ_MODE +#endif + // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions -#if !defined(TFT_PARALLEL_8_BIT) && !defined(ILI9488_DRIVER) && !defined (RPI_DISPLAY_TYPE) +#if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER) #define ESP32_DMA // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions #define DMA_BUSY_CHECK dmaWait() @@ -60,6 +125,12 @@ #define DMA_BUSY_CHECK #endif +#if defined(TFT_PARALLEL_8_BIT) + #define SPI_BUSY_CHECK +#else + #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR) +#endif + // If smooth font is used then it is likely SPIFFS will be needed #ifdef SMOOTH_FONT // Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts @@ -69,6 +140,7 @@ #define FONT_FS_AVAILABLE #endif + //////////////////////////////////////////////////////////////////////////////////////// // Define the DC (TFT Data/Command or Register Select (RS))pin drive code //////////////////////////////////////////////////////////////////////////////////////// @@ -77,10 +149,19 @@ #define DC_D // No macro allocated so it generates no code #else #if defined (TFT_PARALLEL_8_BIT) - #define DC_C GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts = (1 << TFT_DC) + // TFT_DC, by design, must be in range 0-31 for single register parallel write + #if (TFT_DC >= 0) && (TFT_DC < 32) + #define DC_C GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC) + #elif (TFT_DC >= 32) + #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC- 32)) + #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC- 32)) + #else + #define DC_C + #define DC_D + #endif #else - #if TFT_DC >= 32 + #if (TFT_DC >= 32) #ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) @@ -90,16 +171,20 @@ #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #endif - #elif TFT_DC >= 0 - #ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower DC change - #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1ts = (1 << TFT_DC) - #elif defined (RPI_DISPLAY_TYPE) // Other RPi displays need a slower C->D change - #define DC_C GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1ts = (1 << TFT_DC) + #elif (TFT_DC >= 0) + #if defined (RPI_DISPLAY_TYPE) + #if defined (ILI9486_DRIVER) + // RPi ILI9486 display needs a slower DC change + #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1ts = (1 << TFT_DC) + #else + // Other RPi displays need a slower C->D change + #define DC_C GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1ts = (1 << TFT_DC) + #endif #else #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC) #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC) @@ -115,8 +200,9 @@ // Define the CS (TFT chip select) pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TFT_CS - #define CS_L // No macro allocated so it generates no code - #define CS_H // No macro allocated so it generates no code + #define TFT_CS -1 // Keep DMA code happy + #define CS_L // No macro allocated so it generates no code + #define CS_H // No macro allocated so it generates no code #else #if defined (TFT_PARALLEL_8_BIT) #if TFT_CS >= 32 @@ -130,8 +216,8 @@ #define CS_H #endif #else - #if TFT_CS >= 32 - #ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower CS change + #if (TFT_CS >= 32) + #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ @@ -140,12 +226,12 @@ #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #endif - #elif TFT_CS >= 0 - #ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower CS change + #elif (TFT_CS >= 0) + #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) #else - #define CS_L GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) + #define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS) #endif #else @@ -158,9 +244,22 @@ //////////////////////////////////////////////////////////////////////////////////////// // Define the WR (TFT Write) pin drive code //////////////////////////////////////////////////////////////////////////////////////// -#ifdef TFT_WR - #define WR_L GPIO.out_w1tc = (1 << TFT_WR) - #define WR_H GPIO.out_w1ts = (1 << TFT_WR) +#if defined (TFT_WR) + #if (TFT_WR >= 32) + // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32 + #define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32)) + #define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32)) + #elif (TFT_WR >= 0) + // TFT_WR, for best performance, should be in range 0-31 for single register parallel write + #define WR_L GPIO.out_w1tc = (1 << TFT_WR) + #define WR_H GPIO.out_w1ts = (1 << TFT_WR) + #else + #define WR_L + #define WR_H + #endif +#else + #define WR_L + #define WR_H #endif //////////////////////////////////////////////////////////////////////////////////////// @@ -182,11 +281,7 @@ #ifdef USE_HSPI_PORT #ifndef TFT_MISO - #define TFT_MISO 12 - #endif - #if (TFT_MISO == -1) - #undef TFT_MISO - #define TFT_MISO 12 + #define TFT_MISO -1 #endif #ifndef TFT_MOSI @@ -208,11 +303,7 @@ #else // VSPI port #ifndef TFT_MISO - #define TFT_MISO 19 - #endif - #if (TFT_MISO == -1) - #undef TFT_MISO - #define TFT_MISO 19 + #define TFT_MISO -1 #endif #ifndef TFT_MOSI @@ -231,6 +322,13 @@ #define TFT_SCLK 18 #endif + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) + #if (TFT_MISO == -1) + #undef TFT_MISO + #define TFT_MISO TFT_MOSI + #endif + #endif + #endif #endif @@ -242,7 +340,7 @@ // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically // can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF - #define CONSTRUCTOR_INIT_TFT_DATA_BUS \ + #define PARALLEL_INIT_TFT_DATA_BUS \ for (int32_t c = 0; c<256; c++) \ { \ xset_mask[c] = 0; \ @@ -257,10 +355,17 @@ } \ // Mask for the 8 data bits to set pin directions - #define dir_mask ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) + #define GPIO_DIR_MASK ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) - // Data bits and the write line are cleared to 0 in one step - #define clr_mask (dir_mask | (1 << TFT_WR)) + #if (TFT_WR >= 32) + // Data bits and the write line are cleared sequentially + #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L + #elif (TFT_WR >= 0) + // Data bits and the write line are cleared to 0 in one step (1.25x faster) + #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) + #else + #define GPIO_OUT_CLR_MASK + #endif // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time @@ -271,56 +376,91 @@ //*/ // Write 8 bits to TFT - #define tft_Write_8(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C)); WR_H + #define tft_Write_8(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t)(C)); WR_H - // Write 16 bits to TFT - #define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); WR_H + #if defined (SSD1963_DRIVER) - // 16 bit write with swapped bytes - #define tft_Write_16S(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H + // Write 18-bit color to TFT + #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0xF800)>> 8)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H + + // 18-bit color write with swapped bytes + #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) + + #else + + #ifdef PSEUDO_16_BIT + // One write strobe for both bytes + #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H + #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H + #else + // Write 16 bits to TFT + #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H + + // 16-bit write with swapped bytes + #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H + #endif + + #endif // Write 32 bits to TFT - #define tft_Write_32(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 24)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 16)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H + #define tft_Write_32(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 24)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 16)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H - // Write two concatenated 16 bit values to TFT - #define tft_Write_32C(C,D) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 8)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 0)); WR_H + // Write two concatenated 16-bit values to TFT + #define tft_Write_32C(C,D) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 8)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 0)); WR_H - // Write 16 bit value twice to TFT - used by drawPixel() - #define tft_Write_32D(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H + // Write 16-bit value twice to TFT - used by drawPixel() + #define tft_Write_32D(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H // Read pin #ifdef TFT_RD - #define RD_L GPIO.out_w1tc = (1 << TFT_RD) - //#define RD_L digitalWrite(TFT_WR, LOW) - #define RD_H GPIO.out_w1ts = (1 << TFT_RD) - //#define RD_H digitalWrite(TFT_WR, HIGH) + #if (TFT_RD >= 32) + #define RD_L GPIO.out1_w1tc.val = (1 << (TFT_RD - 32)) + #define RD_H GPIO.out1_w1ts.val = (1 << (TFT_RD - 32)) + #elif (TFT_RD >= 0) + #define RD_L GPIO.out_w1tc = (1 << TFT_RD) + //#define RD_L digitalWrite(TFT_WR, LOW) + #define RD_H GPIO.out_w1ts = (1 << TFT_RD) + //#define RD_H digitalWrite(TFT_WR, HIGH) + #else + #define RD_L + #define RD_H + #endif + #else + #define TFT_RD -1 + #define RD_L + #define RD_H #endif //////////////////////////////////////////////////////////////////////////////////////// -// Macros to write commands/pixel colour data to an ILI9488 TFT +// Macros to write commands/pixel colour data to a SPI ILI948x TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB +#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour // Write 8 bits to TFT #define tft_Write_8(C) spi.transfer(C) - // Convert 16 bit colour to 18 bit and write in 3 bytes + // Convert 16-bit colour to 18-bit and write in 3 bytes #define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \ spi.transfer(((C) & 0x07E0)>>3); \ spi.transfer(((C) & 0x001F)<<3) - // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes + // Future option for transfer without wait + #define tft_Write_16N(C) tft_Write_16(C) + + // Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ spi.transfer(((C) & 0x1F00)>>5) @@ -328,10 +468,10 @@ // Write 32 bits to TFT #define tft_Write_32(C) spi.write32(C) - // Write two concatenated 16 bit values to TFT + // Write two concatenated 16-bit values to TFT #define tft_Write_32C(C,D) spi.write32((C)<<16 | (D)) - // Write 16 bit value twice to TFT + // Write 16-bit value twice to TFT #define tft_Write_32D(C) spi.write32((C)<<16 | (C)) //////////////////////////////////////////////////////////////////////////////////////// @@ -339,7 +479,7 @@ //////////////////////////////////////////////////////////////////////////////////////// #elif defined (RPI_DISPLAY_TYPE) - // ESP32 low level SPI writes for 8, 16 and 32 bit values + // ESP32 low level SPI writes for 8, 16 and 32-bit values // to avoid the function call overhead #define TFT_WRITE_BITS(D, B) \ WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ @@ -350,9 +490,12 @@ // Write 8 bits #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16) - // Write 16 bits with corrected endianess for 16 bit colours + // Write 16 bits with corrected endianness for 16-bit colours #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) + // Future option for transfer without wait + #define tft_Write_16N(C) tft_Write_16(C) + // Write 16 bits #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) @@ -370,8 +513,8 @@ // Macros for all other SPI displays //////////////////////////////////////////////////////////////////////////////////////// #else - - // ESP32 low level SPI writes for 8, 16 and 32 bit values +/* Old macros + // ESP32 low level SPI writes for 8, 16 and 32-bit values // to avoid the function call overhead #define TFT_WRITE_BITS(D, B) \ WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ @@ -382,7 +525,7 @@ // Write 8 bits #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) - // Write 16 bits with corrected endianess for 16 bit colours + // Write 16 bits with corrected endianness for 16-bit colours #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) // Write 16 bits @@ -391,12 +534,46 @@ // Write 32 bits #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) + // Write two address coordinates + #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) + + // Write same value twice + #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) +//*/ +//* Replacement slimmer macros + #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \ + *_spi_w = D; \ + *_spi_cmd = SPI_USR; \ + while (*_spi_cmd & SPI_USR); + + // Write 8 bits + #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) + + // Write 16 bits with corrected endianness for 16-bit colours + #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) + + // Future option for transfer without wait + #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \ + *_spi_w = ((C)<<8 | (C)>>8); \ + *_spi_cmd = SPI_USR; + + // Write 16 bits + #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) + + // Write 32 bits + #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) + // Write two address coordinates #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) // Write same value twice #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) +//*/ +#endif + +#ifndef tft_Write_16N + #define tft_Write_16N tft_Write_16 #endif //////////////////////////////////////////////////////////////////////////////////////// diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.c b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.c index 7a7287cb..b49380a9 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.c @@ -109,7 +109,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){ } //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (ILI9488_DRIVER) +#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -122,7 +122,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) uint8_t r = (color & 0xF800)>>8; uint8_t g = (color & 0x07E0)>>3; uint8_t b = (color & 0x001F)<<3; - // Concatenate 4 pixels into three 32 bit blocks + // Concatenate 4 pixels into three 32-bit blocks uint32_t r0 = r<<24 | b<<16 | g<<8 | r; uint32_t r1 = g<<24 | r<<16 | b<<8 | g; uint32_t r2 = b<<24 | g<<16 | r<<8 | b; @@ -304,7 +304,7 @@ return; SPI1U1 = (511 << SPILMOSI); while(len>31) { -#if defined SPI_FREQUENCY && (SPI_FREQUENCY == 80000000) +#if (defined (SPI_FREQUENCY) && (SPI_FREQUENCY == 80000000)) if(SPI1CMD & SPIBUSY) // added to sync with flag change #endif while(SPI1CMD & SPIBUSY) {} diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.h b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.h index f3065f18..1aacc1ee 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.h +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP8266.h @@ -19,7 +19,7 @@ #define DMA_BUSY_CHECK // DMA not available, leave blank // Initialise processor specific SPI functions, used by init() -#if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266) +#if (!defined (SUPPORT_TRANSACTIONS) && defined (ARDUINO_ARCH_ESP8266)) #define INIT_TFT_DATA_BUS \ spi.setBitOrder(MSBFIRST); \ spi.setDataMode(TFT_SPI_MODE); \ @@ -115,19 +115,19 @@ #endif //////////////////////////////////////////////////////////////////////////////////////// -// Macros to write commands/pixel colour data to an ILI9488 TFT +// Macros to write commands/pixel colour data to a SPI ILI948x TFT //////////////////////////////////////////////////////////////////////////////////////// -#if defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB +#if defined (SPI_18BIT_DRIVER) // SPI 18-bit colour // Write 8 bits to TFT #define tft_Write_8(C) spi.transfer(C) - // Convert 16 bit colour to 18 bit and write in 3 bytes + // Convert 16-bit colour to 18-bit and write in 3 bytes #define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \ spi.transfer(((C) & 0x07E0)>>3); \ spi.transfer(((C) & 0x001F)<<3) - // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes + // Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ spi.transfer(((C) & 0x1F00)>>5) @@ -148,7 +148,7 @@ // Command is 16 bits #define CMD_BITS 16 - // ESP8266 low level SPI writes for 8, 16 and 32 bit values + // ESP8266 low level SPI writes for 8, 16 and 32-bit values // to avoid the function call overhead #define TFT_WRITE_BITS(D, B) \ SPI1U1 = ((B-1) << SPILMOSI); \ @@ -191,6 +191,11 @@ SPI1CMD |= SPIBUSY; \ while(SPI1CMD & SPIBUSY) {;} + #define tft_Write_16N(C) \ + SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \ + SPI1W0 = ((C)<<8 | (C)>>8); \ + SPI1CMD |= SPIBUSY + #define tft_Write_16S(C) \ SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \ SPI1W0 = C; \ @@ -217,6 +222,10 @@ #endif +#ifndef tft_Write_16N + #define tft_Write_16N tft_Write_16 +#endif + //////////////////////////////////////////////////////////////////////////////////////// // Macros to read from display using SPI or software SPI //////////////////////////////////////////////////////////////////////////////////////// diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.c b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.c index fbc6f667..1c2287b3 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.c @@ -7,7 +7,11 @@ //////////////////////////////////////////////////////////////////////////////////////// // Select the SPI port to use -SPIClass& spi = SPI; +#ifdef TFT_SPI_PORT + SPIClass& spi = TFT_SPI_PORT; +#else + SPIClass& spi = SPI; +#endif //////////////////////////////////////////////////////////////////////////////////////// #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) @@ -168,7 +172,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) } //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (ILI9488_DRIVER) // For 24 bit SPI colour TFT +#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -212,7 +216,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ } //////////////////////////////////////////////////////////////////////////////////////// -#else // Standard SPI 16 bit colour TFT +#else // Standard SPI 16-bit colour TFT //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.h b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.h index ecf69deb..df7981d3 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.h +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_Generic.h @@ -3,7 +3,7 @@ //////////////////////////////////////////////////// // This is a generic driver for Arduino boards, it supports SPI interface displays -// 8 bit parallel interface to TFT is not supported for generic processors +// 8-bit parallel interface to TFT is not supported for generic processors #ifndef _TFT_eSPI_GENERICH_ #define _TFT_eSPI_GENERICH_ @@ -58,6 +58,13 @@ #define CS_H digitalWrite(TFT_CS, HIGH) #endif +//////////////////////////////////////////////////////////////////////////////////////// +// Make sure TFT_RD is defined if not used to avoid an error message +//////////////////////////////////////////////////////////////////////////////////////// +#ifndef TFT_RD + #define TFT_RD -1 +#endif + //////////////////////////////////////////////////////////////////////////////////////// // Define the WR (TFT Write) pin drive code //////////////////////////////////////////////////////////////////////////////////////// @@ -85,19 +92,19 @@ #endif //////////////////////////////////////////////////////////////////////////////////////// -// Macros to write commands/pixel colour data to an ILI9488 TFT +// Macros to write commands/pixel colour data to a SPI ILI948x TFT //////////////////////////////////////////////////////////////////////////////////////// -#if defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB +#if defined (SPI_18BIT_DRIVER) // SPI 18-bit colour // Write 8 bits to TFT #define tft_Write_8(C) spi.transfer(C) - // Convert 16 bit colour to 18 bit and write in 3 bytes + // Convert 16-bit colour to 18-bit and write in 3 bytes #define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \ spi.transfer(((C) & 0x07E0)>>3); \ spi.transfer(((C) & 0x001F)<<3) - // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes + // Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ spi.transfer(((C) & 0x1F00)>>5) @@ -114,10 +121,29 @@ // Macros to write commands/pixel colour data to other displays //////////////////////////////////////////////////////////////////////////////////////// #else - #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers - #define tft_Write_8(C) spi.transfer(0); spi.transfer(C) + #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16-bit transfers + #define tft_Write_8(C) spi.transfer(C); spi.transfer(C) + #define tft_Write_16(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0)) + #define tft_Write_16S(C) spi.transfer((uint8_t)((C)>>0));spi.transfer((uint8_t)((C)>>8)) + + #define tft_Write_32(C) \ + tft_Write_16((uint16_t) ((C)>>16)); \ + tft_Write_16((uint16_t) ((C)>>0)) + + #define tft_Write_32C(C,D) \ + spi.transfer(0); spi.transfer((C)>>8); \ + spi.transfer(0); spi.transfer((C)>>0); \ + spi.transfer(0); spi.transfer((D)>>8); \ + spi.transfer(0); spi.transfer((D)>>0) + + #define tft_Write_32D(C) \ + spi.transfer(0); spi.transfer((C)>>8); \ + spi.transfer(0); spi.transfer((C)>>0); \ + spi.transfer(0); spi.transfer((C)>>8); \ + spi.transfer(0); spi.transfer((C)>>0) + #else - #ifdef __AVR__ // AVR processors do not have 16 bit transfer + #ifdef __AVR__ // AVR processors do not have 16-bit transfer #define tft_Write_8(C) {SPDR=(C); while (!(SPSR&_BV(SPIF)));} #define tft_Write_16(C) tft_Write_8((uint8_t)((C)>>8));tft_Write_8((uint8_t)((C)>>0)) #define tft_Write_16S(C) tft_Write_8((uint8_t)((C)>>0));tft_Write_8((uint8_t)((C)>>8)) @@ -126,19 +152,23 @@ #define tft_Write_16(C) spi.transfer16(C) #define tft_Write_16S(C) spi.transfer16(((C)>>8) | ((C)<<8)) #endif // AVR + + #define tft_Write_32(C) \ + tft_Write_16((uint16_t) ((C)>>16)); \ + tft_Write_16((uint16_t) ((C)>>0)) + + #define tft_Write_32C(C,D) \ + tft_Write_16((uint16_t) (C)); \ + tft_Write_16((uint16_t) (D)) + + #define tft_Write_32D(C) \ + tft_Write_16((uint16_t) (C)); \ + tft_Write_16((uint16_t) (C)) #endif // RPI_DISPLAY_TYPE +#endif - #define tft_Write_32(C) \ - tft_Write_16((uint16_t) ((C)>>16)); \ - tft_Write_16((uint16_t) ((C)>>0)) - - #define tft_Write_32C(C,D) \ - tft_Write_16((uint16_t) (C)); \ - tft_Write_16((uint16_t) (D)) - - #define tft_Write_32D(C) \ - tft_Write_16((uint16_t) (C)); \ - tft_Write_16((uint16_t) (C)) +#ifndef tft_Write_16N + #define tft_Write_16N tft_Write_16 #endif //////////////////////////////////////////////////////////////////////////////////////// diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.c b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.c index 162e7328..a74dcbc2 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.c +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.c @@ -24,9 +24,6 @@ DMA_HandleTypeDef dmaHal; #endif - // Buffer for SPI transmit byte padding and byte order manipulation - uint8_t spiBuffer[8]; - //////////////////////////////////////////////////////////////////////////////////////// #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) //////////////////////////////////////////////////////////////////////////////////////// @@ -76,7 +73,7 @@ void TFT_eSPI::end_SDA_Read(void) //////////////////////////////////////////////////////////////////////////////////////// -#if defined (TFT_PARALLEL_8_BIT) // Code for STM32 8 bit parallel +#if defined (TFT_PARALLEL_8_BIT) // Code for STM32 8-bit parallel //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -84,24 +81,42 @@ void TFT_eSPI::end_SDA_Read(void) ** Description: Write a block of pixels of the same colour ***************************************************************************************/ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ - // Loop unrolling improves speed dramtically graphics test 0.634s => 0.374s - while (len>31) { - // 32D macro writes 16 bits twice - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - len-=32; - } - while (len>7) { - tft_Write_32D(color); tft_Write_32D(color); - tft_Write_32D(color); tft_Write_32D(color); - len-=8; - } + // Loop unrolling improves speed dramatically graphics test 0.634s => 0.374s + while (len>31) { + #if !defined (SSD1963_DRIVER) + // 32D macro writes 16 bits twice + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + #else + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + #endif + len-=32; + } + + while (len>7) { + #if !defined (SSD1963_DRIVER) + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + #else + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + #endif + len-=8; + } + while (len--) {tft_Write_16(color);} } @@ -131,7 +146,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){ ***************************************************************************************/ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) { -#ifdef STM_PORTA_DATA_BUS +#if defined (STM_PORTA_DATA_BUS) #if defined (STM32F1xx) if (mode == OUTPUT) GPIOA->CRL = 0x33333333; else GPIOA->CRL = 0x88888888; @@ -139,7 +154,7 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) if (mode == OUTPUT) GPIOA->MODER = (GPIOA->MODER & 0xFFFF0000) | 0x00005555; else GPIOA->MODER &= 0xFFFF0000; #endif -#elif STM_PORTB_DATA_BUS +#elif defined (STM_PORTB_DATA_BUS) #if defined (STM32F1xx) if (mode == OUTPUT) GPIOB->CRL = 0x33333333; else GPIOB->CRL = 0x88888888; @@ -147,6 +162,22 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode) if (mode == OUTPUT) GPIOB->MODER = (GPIOB->MODER & 0xFFFF0000) | 0x00005555; else GPIOB->MODER &= 0xFFFF0000; #endif +#elif defined (STM_PORTC_DATA_BUS) + #if defined (STM32F1xx) + if (mode == OUTPUT) GPIOC->CRL = 0x33333333; + else GPIOC->CRL = 0x88888888; + #else + if (mode == OUTPUT) GPIOC->MODER = (GPIOC->MODER & 0xFFFF0000) | 0x00005555; + else GPIOC->MODER &= 0xFFFF0000; + #endif +#elif defined (STM_PORTD_DATA_BUS) + #if defined (STM32F1xx) + if (mode == OUTPUT) GPIOD->CRL = 0x33333333; + else GPIOD->CRL = 0x88888888; + #else + if (mode == OUTPUT) GPIOD->MODER = (GPIOD->MODER & 0xFFFF0000) | 0x00005555; + else GPIOD->MODER &= 0xFFFF0000; + #endif #else if (mode == OUTPUT) { LL_GPIO_SetPinMode(D0_PIN_PORT, D0_PIN_MASK, LL_GPIO_MODE_OUTPUT); @@ -194,16 +225,26 @@ uint8_t TFT_eSPI::readByte(void) uint8_t b = 0; RD_L; -#ifdef STM_PORTA_DATA_BUS +#if defined (STM_PORTA_DATA_BUS) b = GPIOA->IDR; b = GPIOA->IDR; b = GPIOA->IDR; b = (GPIOA->IDR) & 0xFF; -#elif STM_PORTB_DATA_BUS +#elif defined (STM_PORTB_DATA_BUS) b = GPIOB->IDR; b = GPIOB->IDR; b = GPIOB->IDR; b = (GPIOB->IDR) & 0xFF; +#elif defined (STM_PORTC_DATA_BUS) + b = GPIOC->IDR; + b = GPIOC->IDR; + b = GPIOC->IDR; + b = (GPIOC->IDR) & 0xFF; +#elif defined (STM_PORTD_DATA_BUS) + b = GPIOD->IDR; + b = GPIOD->IDR; + b = GPIOD->IDR; + b = (GPIOD->IDR) & 0xFF; #else b = RD_TFT_D0 | RD_TFT_D0 | RD_TFT_D0 | RD_TFT_D0; //Delay for bits to settle @@ -242,7 +283,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) } //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (ILI9488_DRIVER) // For 24 bit colour TFT ############# UNTESTED ################### +#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -252,34 +293,19 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) #define BUF_SIZE 240*3 void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) { - uint8_t col[BUF_SIZE]; + //uint8_t col[BUF_SIZE]; // Always using swapped bytes is a peculiarity of this function... //color = color>>8 | color<<8; uint8_t r = (color & 0xF800)>>8; // Red uint8_t g = (color & 0x07E0)>>3; // Green uint8_t b = (color & 0x001F)<<3; // Blue - if (len=BUF_SIZE/3 ) ; - // Send remaining pixels - if (len) HAL_SPI_Transmit(&spiHal, col, len*3, HAL_MAX_DELAY); //*/ + SPI_BUSY_CHECK; } /*************************************************************************************** ** Function name: pushPixels - for STM32 and 3 byte RGB display @@ -289,30 +315,29 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) { uint16_t *data = (uint16_t*)data_in; - if(_swapBytes) { + if(!_swapBytes) { while ( len-- ) { // Split out the colours - spiBuffer[0] = (*data & 0xF8); // Red - spiBuffer[1] = (*data & 0xE000)>>11 | (*data & 0x07)<<5; // Green - spiBuffer[2] = (*data & 0x1F00)>>5; // Blue + TX_FIFO = (*data & 0xF8); // Red + TX_FIFO = (*data & 0xE000)>>11 | (*data & 0x07)<<5; // Green + TX_FIFO = (*data & 0x1F00)>>5; // Blue data++; - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, HAL_MAX_DELAY); } } else { while ( len-- ) { // Split out the colours - spiBuffer[0] = (*data & 0xF800)>>8; // Red - spiBuffer[1] = (*data & 0x07E0)>>3; // Green - spiBuffer[2] = (*data & 0x001F)<<3; // Blue + TX_FIFO = (*data & 0xF800)>>8; // Red + TX_FIFO = (*data & 0x07E0)>>3; // Green + TX_FIFO = (*data & 0x001F)<<3; // Blue data++; - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, HAL_MAX_DELAY); } } + SPI_BUSY_CHECK; } //////////////////////////////////////////////////////////////////////////////////////// -#else // Standard SPI 16 bit colour TFT All Tested +#else // Standard SPI 16-bit colour TFT All Tested //////////////////////////////////////////////////////////////////////////////////////// /*************************************************************************************** @@ -320,6 +345,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) ** Description: Write a block of pixels of the same colour ***************************************************************************************/ #define BUF_SIZE 480 +/* void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) { uint16_t col[BUF_SIZE]; @@ -337,7 +363,47 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) len -= BUF_SIZE; } while ( len>=BUF_SIZE ) ; // Send remaining pixels - if (len) HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY); //*/ + if (len) HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY); +} + //*/ +void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ + // Loop unrolling improves speed dramatically graphics test 0.634s => 0.374s + while (len>31) { + #if !defined (SSD1963_DRIVER) + // 32D macro writes 16 bits twice + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + #else + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + #endif + len-=32; + } + + while (len>7) { + #if !defined (SSD1963_DRIVER) + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + #else + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + #endif + len-=8; + } + + while (len--) {tft_Write_16(color);} } @@ -348,26 +414,23 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) { uint16_t *data = (uint16_t*)data_in; + if(_swapBytes) { - uint16_t col[BUF_SIZE]; // Buffer for swapped bytes - while ( len>=BUF_SIZE ) { - for (uint32_t i = 0; i < BUF_SIZE; i++) { col[i] = (*data>>8) | (*data<<8); data++; } - HAL_SPI_Transmit(&spiHal, (uint8_t*)col, BUF_SIZE<<1, HAL_MAX_DELAY); - len -= BUF_SIZE; + while ( len-- ) { + TX_FIFO = (uint8_t)(*data>>8); + TX_FIFO = (uint8_t)(*data); + data++; } - for (uint32_t i = 0; i < len; i++) { col[i] = (*data>>8) | (*data<<8); data++; } - HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY); } else { - // HAL byte count for transmit is only 16 bits maximum so to avoid this constraint - // transfers of small blocks are performed until HAL capacity is reached. - while(len>0x7FFF) { // Transfer 16 bit pixels in blocks if len*2 over 65534 bytes - HAL_SPI_Transmit(&spiHal, (uint8_t*)data, 0x800<<1, HAL_MAX_DELAY); - len -= 0x800; data+= 0x800; // Arbitrarily use 2KByte blocks + while ( len-- ) { + // Split out the colours + TX_FIFO = (uint8_t)(*data); + TX_FIFO = (uint8_t)(*data>>8); + data++; } - // Send remaining pixels (max 65534 bytes) - HAL_SPI_Transmit(&spiHal, (uint8_t*)data, len<<1, HAL_MAX_DELAY); } + SPI_BUSY_CHECK; } //////////////////////////////////////////////////////////////////////////////////////// @@ -383,8 +446,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) ** Function name: dmaBusy ** Description: Check if DMA is busy (usefully non-blocking!) ***************************************************************************************/ -// Use "while(tft.dmaBusy());" in sketch for a blocking wait for DMA to complete -// or "while( tft.dmaBusy() ) {Do-something-useful;}" +// Use while( tft.dmaBusy() ) {Do-something-useful;}" bool TFT_eSPI::dmaBusy(void) { //return (dmaHal.State == HAL_DMA_STATE_BUSY); // Do not use, SPI may still be busy @@ -393,7 +455,18 @@ bool TFT_eSPI::dmaBusy(void) /*************************************************************************************** -** Function name: pushImageDMA +** Function name: dmaWait +** Description: Wait until DMA is over (blocking!) +***************************************************************************************/ +void TFT_eSPI::dmaWait(void) +{ + //return (dmaHal.State == HAL_DMA_STATE_BUSY); // Do not use, SPI may still be busy + while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy +} + + +/*************************************************************************************** +** Function name: pushPixelsDMA ** Description: Push pixels to TFT (len must be less than 32767) ***************************************************************************************/ // This will byte swap the original image if setSwapBytes(true) was called by sketch. @@ -419,26 +492,27 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) // This will clip and also swap bytes if setSwapBytes(true) was called by sketch void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer) { - if ((x >= _width) || (y >= _height)) return; + if ((x >= _vpW) || (y >= _vpH)) return; int32_t dx = 0; int32_t dy = 0; int32_t dw = w; int32_t dh = h; - if (x < 0) { dw += x; dx = -x; x = 0; } - if (y < 0) { dh += y; dy = -y; y = 0; } + if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } + if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } - if ((x + dw) > _width ) dw = _width - x; - if ((y + dh) > _height) dh = _height - y; + if ((x + dw) > _vpW ) dw = _vpW - x; + if ((y + dh) > _vpH ) dh = _vpH - y; if (dw < 1 || dh < 1) return; - if (buffer == nullptr) buffer = image; - uint32_t len = dw*dh; - while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy + if (buffer == nullptr) { + buffer = image; + while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy + } // If image is clipped, copy pixels into a contiguous block if ( (dw != w) || (dh != h) ) { @@ -472,7 +546,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t // small transfers are performed using a blocking call until DMA capacity is reached. // User sketch can prevent blocking by managing pixel count and splitting into blocks // of 32767 pixels maximum. (equivalent to an area of ~320 x 100 pixels) - while(len>0x7FFF) { // Transfer 16 bit pixels in blocks if len*2 over 65534 bytes + while(len>0x7FFF) { // Transfer 16-bit pixels in blocks if len*2 over 65534 bytes HAL_SPI_Transmit(&spiHal, (uint8_t*)buffer, 0x800<<1, HAL_MAX_DELAY); len -= 0x800; buffer+= 0x800; // Arbitrarily send 1K pixel blocks (2Kbytes) } @@ -496,6 +570,9 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t #elif (TFT_SPI_PORT == 2) extern "C" void DMA1_Stream4_IRQHandler(); void DMA1_Stream4_IRQHandler(void) + #elif (TFT_SPI_PORT == 3) + extern "C" void DMA1_Stream5_IRQHandler(); + void DMA1_Stream5_IRQHandler(void) #endif { // Call the default end of buffer handler @@ -509,14 +586,20 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t // This initialisation is for STM32F2xx/4xx/7xx processors and may not work on others // Dual core H7xx series not supported yet, they are different and have a DMA MUX: // https://electronics.stackexchange.com/questions/379813/configuring-the-dma-request-multiplexer-on-a-stm32h7-mcu -bool TFT_eSPI::initDMA(void) +bool TFT_eSPI::initDMA(bool ctrl_cs) { + ctrl_cs = ctrl_cs; // Not used for STM32, so stop compiler warning + #if (TFT_SPI_PORT == 1) __HAL_RCC_DMA2_CLK_ENABLE(); // Enable DMA2 clock dmaHal.Init.Channel = DMA_CHANNEL_3; // DMA channel 3 is for SPI1 TX #elif (TFT_SPI_PORT == 2) - __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA2 clock + __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock dmaHal.Init.Channel = DMA_CHANNEL_0; // DMA channel 0 is for SPI2 TX + #elif (TFT_SPI_PORT == 3) + __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock + dmaHal.Init.Channel = DMA_CHANNEL_0; // DMA channel 0 is for SPI3 TX + #endif dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once @@ -534,6 +617,8 @@ bool TFT_eSPI::initDMA(void) HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); // Enable DMA end interrupt handler #elif (TFT_SPI_PORT == 2) HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn); // Enable DMA end interrupt handler + #elif (TFT_SPI_PORT == 3) + HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); #endif __HAL_LINKDMA(&spiHal, hdmatx, dmaHal); // Attach DMA engine to SPI peripheral @@ -563,8 +648,10 @@ bool TFT_eSPI::initDMA(void) ** Function name: initDMA ** Description: Initialise the DMA engine - returns true if init OK ***************************************************************************************/ -bool TFT_eSPI::initDMA(void) +bool TFT_eSPI::initDMA(bool ctrl_cs) { + ctrl_cs = ctrl_cs; // Not used for STM32, so stop compiler warning + __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once diff --git a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.h b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.h index 6fcab87b..73a22cbf 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_STM32.h @@ -45,7 +45,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // Write strobe timing setup //////////////////////////////////////////////////////////////////////////////////////// - #if defined (ILI9341_DRIVER) || defined (ST7796_DRIVER) || defined (ILI9486_DRIVER) // WRX twc spec is <=66ns = 15.15MHz + #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ST7796_DRIVER) || defined (ILI9486_DRIVER) // WRX twc spec is <=66ns = 15.15MHz // Extra write pulse low time (delay for data setup) #if defined (STM32F1xx) @@ -151,6 +151,15 @@ #define TFT_SPI_PORT 1 #endif + #if (TFT_SPI_PORT == 1) + #define SPIX SPI1 + #elif (TFT_SPI_PORT == 2) + #define SPIX SPI2 + #elif (TFT_SPI_PORT == 3) + #define SPIX SPI3 + #elif (TFT_SPI_PORT == 4) + #define SPIX SPI4 + #endif // Global define is _VARIANT_ARDUINO_STM32_, see board package stm32_def.h for specific variants #if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) @@ -161,15 +170,22 @@ #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ dmaHal.Instance = DMA2_Stream3 // The DMA hard-coding for SPI1 is in TFT_eSPI_STM32.c as follows: - // DMA_CHANNEL_3 + // DMA_CHANNEL_3 // DMA2_Stream3_IRQn and DMA2_Stream3_IRQHandler() #elif (TFT_SPI_PORT == 2) // Initialise processor specific SPI and DMA instances - used by init() #define INIT_TFT_DATA_BUS spiHal.Instance = SPI2; \ dmaHal.Instance = DMA1_Stream4 // The DMA hard-coding for SPI2 is in TFT_eSPI_STM32.c as follows: - // DMA_CHANNEL_4 + // DMA_CHANNEL_4 // DMA1_Stream4_IRQn and DMA1_Stream4_IRQHandler() + #elif (TFT_SPI_PORT == 3) + // Initialise processor specific SPI and DMA instances - used by init() + #define INIT_TFT_DATA_BUS spiHal.Instance = SPI3; \ + dmaHal.Instance = DMA1_Stream5 + // The DMA hard-coding for SPI3 is in TFT_eSPI_STM32.c as follows: + // DMA_CHANNEL_4 + // DMA1_Stream5_IRQn and DMA1_Stream5_IRQHandler() #endif #elif defined (STM32F1xx) @@ -219,8 +235,8 @@ #define DC_PORT digitalPinToPort(TFT_DC) #define DC_PIN_MASK digitalPinToBitMask(TFT_DC) // Use bit set reset register - #define DC_C DC_PORT->BSRR = DC_PIN_MASK<<16 - #define DC_D DC_PORT->BSRR = DC_PIN_MASK + #define DC_C DC_DELAY; DC_PORT->BSRR = DC_PIN_MASK<<16 + #define DC_D DC_DELAY; DC_PORT->BSRR = DC_PIN_MASK #endif //////////////////////////////////////////////////////////////////////////////////////// @@ -243,12 +259,21 @@ // Define the RD (TFT Read) pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifdef TFT_RD - // Convert Arduino pin reference Dx or STM pin reference PXn to port and mask - #define RD_PORT digitalPinToPort(TFT_RD) - #define RD_PIN_MASK digitalPinToBitMask(TFT_RD) - // Use bit set reset register - #define RD_L RD_PORT->BSRR = RD_PIN_MASK<<16 - #define RD_H RD_PORT->BSRR = RD_PIN_MASK + #if (TFT_RD >= 0) + // Convert Arduino pin reference Dx or STM pin reference PXn to port and mask + #define RD_PORT digitalPinToPort(TFT_RD) + #define RD_PIN_MASK digitalPinToBitMask(TFT_RD) + // Use bit set reset register + #define RD_L RD_PORT->BSRR = RD_PIN_MASK<<16 + #define RD_H RD_PORT->BSRR = RD_PIN_MASK + #else + #define RD_L + #define RD_H + #endif +#else + #define TFT_RD -1 + #define RD_L + #define RD_H #endif //////////////////////////////////////////////////////////////////////////////////////// @@ -290,9 +315,9 @@ #if defined (TFT_PARALLEL_8_BIT) // Mask for the 8 data bits to set pin directions (not used) - #define dir_mask 0 + #define GPIO_DIR_MASK 0 - #define CONSTRUCTOR_INIT_TFT_DATA_BUS // None + #define PARALLEL_INIT_TFT_DATA_BUS // None #define INIT_TFT_DATA_BUS // Setup built into TFT_eSPI.cpp @@ -385,7 +410,7 @@ #define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10)) #define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10)) #define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10)) - // Create bit set/reset mask for top byte of 16 bit value B + // Create bit set/reset mask for top byte of 16-bit value B #define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10)) #define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10)) #define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10)) @@ -402,29 +427,54 @@ GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ WR_STB // Need to slow down strobe - // Write 16 bits to TFT - #define tft_Write_16(C) GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ - WR_L; \ - GPIOC->BSRR = D9_BSR_MASK(C); \ - GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ - WR_STB; \ - GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ - WR_L; \ - GPIOC->BSRR = D1_BSR_MASK(C); \ - GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ - WR_STB // Need to slow down strobe + #if defined (SSD1963_DRIVER) - // 16 bit write with swapped bytes - #define tft_Write_16S(C) GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ - WR_L; \ - GPIOC->BSRR = D1_BSR_MASK(C); \ - GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ - WR_STB; \ - GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ - WR_L; \ - GPIOC->BSRR = D9_BSR_MASK(C); \ - GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ - WR_STB + // Write 18-bit color to TFT (untested) + #define tft_Write_16(C) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ + GPIOA->BSRR = D0_BSR_MASK(r6) | D2_BSR_MASK(r6) | D7_BSR_MASK(r6); \ + WR_L; \ + GPIOC->BSRR = D1_BSR_MASK(r6); \ + GPIOB->BSRR = D3_BSR_MASK(r6) | D4_BSR_MASK(r6) | D5_BSR_MASK(r6) | D6_BSR_MASK(r6); \ + WR_STB; \ + GPIOA->BSRR = D0_BSR_MASK(g6) | D2_BSR_MASK(g6) | D7_BSR_MASK(g6); \ + WR_L; \ + GPIOC->BSRR = D1_BSR_MASK(g6); \ + GPIOB->BSRR = D3_BSR_MASK(g6) | D4_BSR_MASK(g6) | D5_BSR_MASK(g6) | D6_BSR_MASK(g6); \ + WR_STB; \ + GPIOA->BSRR = D0_BSR_MASK(b6) | D2_BSR_MASK(b6) | D7_BSR_MASK(b6); \ + WR_L; \ + GPIOC->BSRR = D1_BSR_MASK(b6); \ + GPIOB->BSRR = D3_BSR_MASK(b6) | D4_BSR_MASK(b6) | D5_BSR_MASK(b6) | D6_BSR_MASK(b6); \ + WR_STB // Need to slow down strobe + + // 18-bit color write with swapped bytes + #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) + + #else + // Write 16 bits to TFT + #define tft_Write_16(C) GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ + WR_L; \ + GPIOC->BSRR = D9_BSR_MASK(C); \ + GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ + WR_STB; \ + GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ + WR_L; \ + GPIOC->BSRR = D1_BSR_MASK(C); \ + GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ + WR_STB // Need to slow down strobe + + // 16-bit write with swapped bytes + #define tft_Write_16S(C) GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \ + WR_L; \ + GPIOC->BSRR = D1_BSR_MASK(C); \ + GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ + WR_STB; \ + GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \ + WR_L; \ + GPIOC->BSRR = D9_BSR_MASK(C); \ + GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ + WR_STB + #endif #define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) @@ -500,7 +550,7 @@ #define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10)) #define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10)) #define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10)) - // Create bit set/reset mask for top byte of 16 bit value B + // Create bit set/reset mask for top byte of 16-bit value B #define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10)) #define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10)) #define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10)) @@ -518,29 +568,56 @@ GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ WR_STB - // Write 16 bits to TFT - #define tft_Write_16(C) GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ - WR_L; \ - GPIOD->BSRR = D9_BSR_MASK(C); \ - GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ - WR_STB;\ - GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ - WR_L; \ - GPIOD->BSRR = D1_BSR_MASK(C); \ - GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ - WR_STB + #if defined (SSD1963_DRIVER) - // 16 bit write with swapped bytes - #define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ - WR_L; \ - GPIOD->BSRR = D1_BSR_MASK(C); \ - GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ - WR_STB; \ - GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ - WR_L; \ - GPIOD->BSRR = D9_BSR_MASK(C); \ - GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ - WR_STB + // Write 18-bit color to TFT (untested) + #define tft_Write_16(C) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ + GPIOF->BSRR = D0_BSR_MASK(r6) | D2_BSR_MASK(r6) | D4_BSR_MASK(r6) | D7_BSR_MASK(r6); \ + WR_L; \ + GPIOD->BSRR = D1_BSR_MASK(r6); \ + GPIOE->BSRR = D3_BSR_MASK(r6) | D5_BSR_MASK(r6) | D6_BSR_MASK(r6); \ + WR_STB; \ + GPIOF->BSRR = D0_BSR_MASK(g6) | D2_BSR_MASK(g6) | D4_BSR_MASK(g6) | D7_BSR_MASK(g6); \ + WR_L; \ + GPIOD->BSRR = D1_BSR_MASK(g6); \ + GPIOE->BSRR = D3_BSR_MASK(g6) | D5_BSR_MASK(g6) | D6_BSR_MASK(g6); \ + WR_STB; \ + GPIOF->BSRR = D0_BSR_MASK(b6) | D2_BSR_MASK(b6) | D4_BSR_MASK(b6) | D7_BSR_MASK(b6); \ + WR_L; \ + GPIOD->BSRR = D1_BSR_MASK(b6); \ + GPIOE->BSRR = D3_BSR_MASK(b6) | D5_BSR_MASK(b6) | D6_BSR_MASK(b6); \ + WR_STB // Need to slow down strobe + + // 18-bit color write with swapped bytes + #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) + + #else + + // Write 16 bits to TFT + #define tft_Write_16(C) GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ + WR_L; \ + GPIOD->BSRR = D9_BSR_MASK(C); \ + GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ + WR_STB;\ + GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ + WR_L; \ + GPIOD->BSRR = D1_BSR_MASK(C); \ + GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ + WR_STB + + // 16-bit write with swapped bytes + #define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \ + WR_L; \ + GPIOD->BSRR = D1_BSR_MASK(C); \ + GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ + WR_STB; \ + GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \ + WR_L; \ + GPIOD->BSRR = D9_BSR_MASK(C); \ + GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \ + WR_STB + + #endif #define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) @@ -591,7 +668,7 @@ #define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10)) #define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10)) #define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10)) - // Create bit set/reset mask for top byte of 16 bit value B + // Create bit set/reset mask for top byte of 16-bit value B #define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10)) #define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10)) #define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10)) @@ -624,7 +701,7 @@ GPIOE->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \ WR_STB - // 16 bit write with swapped bytes + // 16-bit write with swapped bytes #define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C); \ GPIOG->BSRR = D2_BSR_MASK(C) | D7_BSR_MASK(C); \ WR_L; \ @@ -659,18 +736,42 @@ // Support for other STM32 boards (not optimised!) //////////////////////////////////////////////////////////////////////////////////////// #else - #if defined (STM_PORTA_DATA_BUS) - - // Write 8 bits to TFT - #define tft_Write_8(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB - - // Write 16 bits to TFT - #define tft_Write_16(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \ - GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB + #if defined (STM_PORTA_DATA_BUS) || defined (STM_PORTB_DATA_BUS) || defined (STM_PORTC_DATA_BUS) || defined (STM_PORTD_DATA_BUS) + #if defined (STM_PORTA_DATA_BUS) + #define GPIOX GPIOA + #elif defined (STM_PORTB_DATA_BUS) + #define GPIOX GPIOB + #elif defined (STM_PORTC_DATA_BUS) + #define GPIOX GPIOC + #elif defined (STM_PORTD_DATA_BUS) + #define GPIOX GPIOD + #endif - // 16 bit write with swapped bytes - #define tft_Write_16S(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \ - GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB + // Write 8 bits to TFT + #define tft_Write_8(C) GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB + + #if defined (SSD1963_DRIVER) + + // Write 18-bit color to TFT (untested) + + #define tft_Write_16(C) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ + GPIOX->BSRR = (0x00FF0000 | (uint8_t)(r6)); WR_L; WR_STB; \ + GPIOX->BSRR = (0x00FF0000 | (uint8_t)(g6)); WR_L; WR_STB; \ + GPIOX->BSRR = (0x00FF0000 | (uint8_t)(b6)); WR_L; WR_STB + + // 18-bit color write with swapped bytes + #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) + + #else + + // Write 16 bits to TFT + #define tft_Write_16(C) GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \ + GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB + + // 16-bit write with swapped bytes + #define tft_Write_16S(C) GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \ + GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB + #endif #define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) @@ -679,43 +780,14 @@ #define tft_Write_32D(C) tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(C)) // Read a data bit - #define RD_TFT_D0 ((GPIOA->IDR) & 0x01) // Read pin TFT_D0 - #define RD_TFT_D1 ((GPIOA->IDR) & 0x02) // Read pin TFT_D1 - #define RD_TFT_D2 ((GPIOA->IDR) & 0x04) // Read pin TFT_D2 - #define RD_TFT_D3 ((GPIOA->IDR) & 0x08) // Read pin TFT_D3 - #define RD_TFT_D4 ((GPIOA->IDR) & 0x10) // Read pin TFT_D4 - #define RD_TFT_D5 ((GPIOA->IDR) & 0x20) // Read pin TFT_D5 - #define RD_TFT_D6 ((GPIOA->IDR) & 0x40) // Read pin TFT_D6 - #define RD_TFT_D7 ((GPIOA->IDR) & 0x80) // Read pin TFT_D7 - - #elif defined (STM_PORTB_DATA_BUS) - - // Write 8 bits to TFT - #define tft_Write_8(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB - - // Write 16 bits to TFT - #define tft_Write_16(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \ - GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB - - // 16 bit write with swapped bytes - #define tft_Write_16S(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \ - GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB - - #define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) - - #define tft_Write_32C(C,D) tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(D)) - - #define tft_Write_32D(C) tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(C)) - - // Read a data bit - #define RD_TFT_D0 ((GPIOB->IDR) & 0x80) // Read pin TFT_D0 - #define RD_TFT_D1 ((GPIOB->IDR) & 0x40) // Read pin TFT_D1 - #define RD_TFT_D2 ((GPIOB->IDR) & 0x20) // Read pin TFT_D2 - #define RD_TFT_D3 ((GPIOB->IDR) & 0x10) // Read pin TFT_D3 - #define RD_TFT_D4 ((GPIOB->IDR) & 0x08) // Read pin TFT_D4 - #define RD_TFT_D5 ((GPIOB->IDR) & 0x04) // Read pin TFT_D5 - #define RD_TFT_D6 ((GPIOB->IDR) & 0x02) // Read pin TFT_D6 - #define RD_TFT_D7 ((GPIOB->IDR) & 0x01) // Read pin TFT_D7 + #define RD_TFT_D0 ((GPIOX->IDR) & 0x01) // Read pin TFT_D0 + #define RD_TFT_D1 ((GPIOX->IDR) & 0x02) // Read pin TFT_D1 + #define RD_TFT_D2 ((GPIOX->IDR) & 0x04) // Read pin TFT_D2 + #define RD_TFT_D3 ((GPIOX->IDR) & 0x08) // Read pin TFT_D3 + #define RD_TFT_D4 ((GPIOX->IDR) & 0x10) // Read pin TFT_D4 + #define RD_TFT_D5 ((GPIOX->IDR) & 0x20) // Read pin TFT_D5 + #define RD_TFT_D6 ((GPIOX->IDR) & 0x40) // Read pin TFT_D6 + #define RD_TFT_D7 ((GPIOX->IDR) & 0x80) // Read pin TFT_D7 #else // This will work with any STM32 to parallel TFT pin mapping but will be slower @@ -769,7 +841,7 @@ #define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10)) #define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10)) #define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10)) - // Create bit set/reset mask for top byte of 16 bit value B + // Create bit set/reset mask for top byte of 16-bit value B #define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10)) #define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10)) #define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10)) @@ -792,49 +864,90 @@ D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ WR_STB - // Write 16 bits to TFT - #define tft_Write_16(C) D0_PIN_PORT->BSRR = D8_BSR_MASK(C); \ - D1_PIN_PORT->BSRR = D9_BSR_MASK(C); \ - D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ - D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ - WR_L; \ - D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ - D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ - D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ - D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ - WR_STB;\ - D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ - D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ - D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ - D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ - WR_L; \ - D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ - D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ - D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ - D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ - WR_STB + #if defined (SSD1963_DRIVER) - // 16 bit write with swapped bytes - #define tft_Write_16S(C) D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ - D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ - D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ - D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ - WR_L; \ - D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ - D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ - D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ - D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ - WR_STB; \ - D0_PIN_PORT->BSRR = D8_BSR_MASK(C); \ - D1_PIN_PORT->BSRR = D9_BSR_MASK(C); \ - D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ - D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ - WR_L; \ - D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ - D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ - D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ - D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ - WR_STB + // Write 18-bit color to TFT (untested) + #define tft_Write_16(C) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \ + D0_PIN_PORT->BSRR = D8_BSR_MASK(r6); \ + D1_PIN_PORT->BSRR = D9_BSR_MASK(r6); \ + D2_PIN_PORT->BSRR = D10_BSR_MASK(r6); \ + D3_PIN_PORT->BSRR = D11_BSR_MASK(r6); \ + WR_L; \ + D4_PIN_PORT->BSRR = D12_BSR_MASK(r6); \ + D5_PIN_PORT->BSRR = D13_BSR_MASK(r6); \ + D6_PIN_PORT->BSRR = D14_BSR_MASK(r6); \ + D7_PIN_PORT->BSRR = D15_BSR_MASK(r6); \ + WR_STB;\ + D0_PIN_PORT->BSRR = D8_BSR_MASK(g6); \ + D1_PIN_PORT->BSRR = D9_BSR_MASK(g6); \ + D2_PIN_PORT->BSRR = D10_BSR_MASK(g6); \ + D3_PIN_PORT->BSRR = D11_BSR_MASK(g6); \ + WR_L; \ + D4_PIN_PORT->BSRR = D12_BSR_MASK(g6); \ + D5_PIN_PORT->BSRR = D13_BSR_MASK(g6); \ + D6_PIN_PORT->BSRR = D14_BSR_MASK(g6); \ + D7_PIN_PORT->BSRR = D15_BSR_MASK(g6); \ + WR_STB;\ + D0_PIN_PORT->BSRR = D0_BSR_MASK(b6); \ + D1_PIN_PORT->BSRR = D1_BSR_MASK(b6); \ + D2_PIN_PORT->BSRR = D2_BSR_MASK(b6); \ + D3_PIN_PORT->BSRR = D3_BSR_MASK(b6); \ + WR_L; \ + D4_PIN_PORT->BSRR = D4_BSR_MASK(b6); \ + D5_PIN_PORT->BSRR = D5_BSR_MASK(b6); \ + D6_PIN_PORT->BSRR = D6_BSR_MASK(b6); \ + D7_PIN_PORT->BSRR = D7_BSR_MASK(b6); \ + WR_STB + + // 18-bit color write with swapped bytes + #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) + + #else + + // Write 16 bits to TFT + #define tft_Write_16(C) D0_PIN_PORT->BSRR = D8_BSR_MASK(C); \ + D1_PIN_PORT->BSRR = D9_BSR_MASK(C); \ + D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ + D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ + WR_L; \ + D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ + D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ + D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ + D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ + WR_STB;\ + D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ + D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ + D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ + D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ + WR_L; \ + D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ + D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ + D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ + D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ + WR_STB + + // 16-bit write with swapped bytes + #define tft_Write_16S(C) D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \ + D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \ + D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \ + D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \ + WR_L; \ + D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \ + D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \ + D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \ + D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \ + WR_STB; \ + D0_PIN_PORT->BSRR = D8_BSR_MASK(C); \ + D1_PIN_PORT->BSRR = D9_BSR_MASK(C); \ + D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \ + D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \ + WR_L; \ + D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \ + D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \ + D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \ + D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \ + WR_STB + #endif #define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C)) @@ -854,68 +967,60 @@ #endif #endif //////////////////////////////////////////////////////////////////////////////////////// -// Macros to write commands/pixel colour data to a SPI ILI9488 TFT +// Macros to write commands/pixel colour data to a SPI ILI948x TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB +#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour - // Write 8 bits to TFT - #define tft_Write_8(C) \ - { spiBuffer[0] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); } + #define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){} + //BSY check must allow for APB clock delay by checking TXE flag first + #define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){} + #define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR) - // Convert 16 bit colour to 18 bit and write in 3 bytes - #define tft_Write_16(C) \ - { spiBuffer[0] = ((C) & 0xF800)>>8; spiBuffer[1] = ((C) & 0x07E0)>>3; spiBuffer[2] = ((C) & 0x001F)<<3; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, 10); } + //#define tft_Write_8(C) spi.transfer(C) + #define tft_Write_8(C) TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16(C) TX_FIFO = ((C) & 0xF800)>>8; TX_FIFO = ((C) & 0x07E0)>>3; TX_FIFO = ((C) & 0x001F)<<3; SPI_BUSY_CHECK + #define tft_Write_16S(C) TX_FIFO = (C) & 0xF8; TX_FIFO = ((C) & 0xE000)>>11 | ((C) & 0x07)<<5; TX_FIFO = ((C) & 0x1F00)>>5; SPI_BUSY_CHECK + #define tft_Write_16N(C) TX_FIFO = ((C) & 0xF800)>>8; TX_FIFO = ((C) & 0x07E0)>>3; TX_FIFO = ((C) & 0x001F)<<3 - // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes - #define tft_Write_16S(C) \ - { spiBuffer[0] = (C) & 0xF8; spiBuffer[1] = ((C) & 0xE000)>>11 | ((C) & 0x07)<<5; spiBuffer[2] = ((C) & 0x1F00)>>5; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, 10); } - - // Write 32 bits to TFT #define tft_Write_32(C) \ - { spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \ + TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK - // Write two address coordinates #define tft_Write_32C(C,D) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; spiBuffer[2] = (D)>>8; spiBuffer[3] = D; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + TX_FIFO = (D)>>8; TX_FIFO = (D); SPI_BUSY_CHECK - // Write same value twice #define tft_Write_32D(C) \ - { spiBuffer[0] = spiBuffer[2] = (C)>>8; spiBuffer[1] = spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to a SPI Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// #elif defined (RPI_DISPLAY_TYPE) - #define tft_Write_8(C) \ - { spiBuffer[0] = 0; spiBuffer[1] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + #define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){} + //BSY check must allow for APB clock delay by checking TXE flag first + #define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){} + #define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR) - #define tft_Write_16(C) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } - - #define tft_Write_16S(C) \ - { spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + //#define tft_Write_8(C) spi.transfer(C) + #define tft_Write_8(C) TX_FIFO = (0); TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16(C) TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16S(C) TX_FIFO = (C); TX_FIFO = (C)>>8; SPI_BUSY_CHECK + #define tft_Write_16N(C) TX_FIFO = (C)>>8; TX_FIFO = (C) #define tft_Write_32(C) \ - { spiBuffer[1] = ((C)>>24); spiBuffer[3] = ((C)>>16); spiBuffer[5] = ((C)>>8); spiBuffer[7] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); } + TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \ + TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK #define tft_Write_32C(C,D) \ - { spiBuffer[1] = ((C)>>8); spiBuffer[3] = (C); spiBuffer[5] = ((D)>>8); spiBuffer[7] = D; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); } + TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); \ + TX_FIFO = (0); TX_FIFO = (D)>>8; TX_FIFO = (0); TX_FIFO = (D); SPI_BUSY_CHECK #define tft_Write_32D(C) \ - { spiBuffer[1] = ((C)>>8); spiBuffer[3] = (C); spiBuffer[5] = ((C)>>8); spiBuffer[7] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); } + TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); \ + TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); SPI_BUSY_CHECK //////////////////////////////////////////////////////////////////////////////////////// // Macros for all other SPI displays @@ -923,37 +1028,41 @@ #else - #if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) - // Temporary workaround for issue #510 part 2 - #define tft_Write_8(C) spi.transfer(C) - #else - #define tft_Write_8(C) \ - { spiBuffer[0] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); delayMicroseconds(1);} - #endif + //#define DC_DELAY delayMicroseconds(1) // Premature BSY clear Hardware bug? - #define tft_Write_16(C) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + #define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){} + //BSY check must allow for APB clock delay by checking TXE flag first + #define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){} + #define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR) - #define tft_Write_16S(C) \ - { spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + #define tft_Write_8(C) TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16(C) TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16S(C) TX_FIFO = (C); TX_FIFO = (C)>>8; SPI_BUSY_CHECK + #define tft_Write_16N(C) TX_FIFO = (C)>>8; TX_FIFO = (C) #define tft_Write_32(C) \ - { spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \ + tft_Write_16((uint16_t) ((C)>>0)) #define tft_Write_32C(C,D) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; spiBuffer[2] = (D)>>8; spiBuffer[3] = D; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + tft_Write_16((uint16_t) (D)) #define tft_Write_32D(C) \ - { spiBuffer[0] = spiBuffer[2] = (C)>>8; spiBuffer[1] = spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + tft_Write_16((uint16_t) (C)) #endif +#ifndef DC_DELAY + //#define DC_DELAY delayMicroseconds(1) // Premature BSY clear hardware bug? + #define DC_DELAY +#endif + +#ifndef tft_Write_16N + #define tft_Write_16N tft_Write_16 +#endif + //////////////////////////////////////////////////////////////////////////////////////// // Macros to read from display using SPI or software SPI //////////////////////////////////////////////////////////////////////////////////////// diff --git a/trunk/Arduino/libraries/TFT_eSPI/README.md b/trunk/Arduino/libraries/TFT_eSPI/README.md index 9f0bff1c..0c0c15bc 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/README.md +++ b/trunk/Arduino/libraries/TFT_eSPI/README.md @@ -1,27 +1,28 @@ A ["Discussions"](https://github.com/Bodmer/TFT_eSPI/discussions) facility has been added for Q&A etc. Use the ["Issues"](https://github.com/Bodmer/TFT_eSPI/issues) tab only for problems with the library. Thanks! # News -1. New functions have been added to draw smooth (antialiased) arcs, circles, and rounded rectangle outlines. New sketches are provided in the "Smooth Graphics" examples folder. Arcs can be drawn with or without anti-aliasing (which will then render faster). The arc ends can be straight or rounded. The arc drawing algorithm uses an optimised fixed point sqrt() function to improve performance on processors that do not have a hardware Floating Point Unit (e.g. RP2040). Here's a demo image of smooth (anti-aliased) arcs with rounded ends and increasing sweep angle: +1. The Create_font Processing sketch has been updated to automatically create a complete C header file. The automatic opening of the font folder can also be disabled within the Processing sketch. (Thanks to Pierre-Loup Martin). - ![arcs](https://github.com/Bodmer/Github-images/blob/main/smooth_arcs.png) - - Here is the same resolution image (grabbed from the same TFT) with the smoothing diasbled (no anti-aliasing): - - ![pixelated_arcs](https://github.com/Bodmer/Github-images/blob/main/pixelated_arcs.png) +2. New board setup files have been added for the Seeed XIAO with round display, LilyGo T-Embed S3, LilyGo_T_QT_Pro_S3, ESP32 S3 Box and ESP32_S3_Box_Lite. The "RPi" interface style boards are now supported with the ESP32 S3. -2. An excellent new compatible library is available which can render TrueType fonts on a TFT screen (or into a sprite). This has been developed by [takkaO](https://github.com/takkaO/OpenFontRender), I have created a branch with some bug fixes [here](https://github.com/Bodmer/OpenFontRender). The library provides access to compact font files, with fully scaleable anti-aliased glyphs. Left, middle and right justified text can also be printed to the screen. I have added TFT_eSPI specific examples to the OpenFontRender library and tested on RP2040 and ESP32 processors, the ESP8266 does not have sufficient RAM due to the glyph render complexity. Here is a demo screen where a single 12kbyte font file binary was used to render fully anti-aliased glyphs of gradually increasing size on a 320x480 TFT screen: +3. New functions have been added to draw smooth (antialiased) arcs, circles, and rounded rectangle outlines. New sketches are provided in the "Smooth Graphics" examples folder. Arcs can be drawn with or without anti-aliasing (which will then render faster). The arc ends can be straight or rounded. The arc drawing algorithm uses an optimised fixed point sqrt() function to improve performance on processors that do not have a hardware Floating Point Unit (e.g. RP2040). Here are two demo images, on the left smooth (anti-aliased) arcs with rounded ends, the image to the right is the same resolution (grabbed from the same 240x240 TFT) with the smoothing diasbled (no anti-aliasing): + + ![arcs](https://github.com/Bodmer/Github-images/blob/main/aa_arc_240x240.png) ![pixelated_arcs](https://github.com/Bodmer/Github-images/blob/main/no_aa_arc_240x240.png) + + Here the smooth arcs have been used to create anti-aliased meter gauges on a 320x240 TFT: + + ![arcs](https://github.com/Bodmer/Github-images/blob/main/xarc_meters_320x240.png) + +4. An excellent new compatible library is available which can render TrueType fonts on a TFT screen (or into a sprite). This has been developed by [takkaO](https://github.com/takkaO/OpenFontRender). The library provides access to compact font files, with fully scaleable anti-aliased glyphs. Left, middle and right justified text can also be printed to the screen. I have added TFT_eSPI specific examples to the OpenFontRender library and tested on RP2040 and ESP32 processors, the ESP8266 does not have sufficient RAM due to the glyph render complexity. Here is a demo screen where a single 12kbyte font file binary was used to render fully anti-aliased glyphs of gradually increasing size on a 320x480 TFT screen: ![ttf_font_demo](https://i.imgur.com/bKkilIb.png) -3. The following is now deprecated due to the number of issues it can cause in certain circumstances. For ESP32 ONLY, the TFT configuration (user setup) can now be included inside an Arduino IDE sketch providing the instructions in the example Generic->Sketch_with_tft_setup are followed. See ReadMe tab in that sketch for the instructions. If the setup is not in the sketch then the library settings will be used. This means that "per project" configurations are possible without modifying the library setup files. Please note that ALL the other examples in the library will use the library settings unless they are adapted and the "tft_setup.h" header file included. Note: there are issues with this approach, [#2007](https://github.com/Bodmer/TFT_eSPI/discussions/2007#discussioncomment-3834755) proposes an alternative method. - -4. New GUI examples have been added for sliders, buttons, graphs and meters. These examples require a new support library here: +5. New GUI examples have been added for sliders, buttons, graphs and meters. These examples require a new support library here: [TFT_eWidget](https://github.com/Bodmer/TFT_eWidget) -5. Support has been added in v2.4.70 for the RP2040 with 16 bit parallel displays. This has been tested and the screen update performance is very good (4ms to clear 320 x 480 screen with HC8357C). The use of the RP2040 PIO makes it easy to change the write cycle timing for different displays. DMA with 16 bit transfers is also supported. +6. Support has been added in v2.4.70 for the RP2040 with 16-bit parallel displays. This has been tested and the screen update performance is very good (4ms to clear 320 x 480 screen with HC8357C). The use of the RP2040 PIO makes it easy to change the write cycle timing for different displays. DMA with 16-bit transfers is also supported. -6. Support for HX8357B and HX8357C screens has been added (only tested with RP2040 and 16 bit parallel interface) -7. Support for the ESP32-S2, ESP32-S3 and ESP32-C3 has been added (DMA not supported at the moment). Tested with v2.0.3 RC1 of the ESP32 board package. Example setups: +7. Support for the ESP32-S2, ESP32-S3 and ESP32-C3 has been added (DMA only on ESP32 S3 at the moment). Tested with v2.0.3 RC1 of the ESP32 board package. Example setups: [Setup70_ESP32_S2_ILI9341.h](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup70_ESP32_S2_ILI9341.h) @@ -40,11 +41,9 @@ Note: background rendering for Smooth fonts is also now available when using the 9. New anti-aliased graphics functions to draw lines, wedge shaped lines, circles and rounded rectangles. [Examples are included](https://github.com/Bodmer/TFT_eSPI/tree/master/examples/Smooth%20Graphics). Examples have also been added to [display PNG compressed images](https://github.com/Bodmer/TFT_eSPI/tree/master/examples/PNG%20Images) (note: requires ~40kbytes RAM). -10. Frank Boesing has created an extension library for TFT_eSPI that allows a large range of ready-built fonts to be used. Frank's library (adapted to permit rendering in sprites as well as TFT) can be [downloaded here](https://github.com/Bodmer/TFT_eSPI_ext). More than 3300 additional Fonts are [available here](https://github.com/FrankBoesing/fonts/tree/master/ofl). The TFT_eSPI_ext library contains examples that demonstrate the use of the fonts. +10. Users of PowerPoint experienced with running macros may be interested in the [pptm sketch generator here](https://github.com/Bodmer/PowerPoint_to_sketch), this converts graphics and tables drawn in PowerPoint slides into an Arduino sketch that renders the graphics on a 480x320 TFT. This is based on VB macros [created by Kris Kasprzak here](https://github.com/KrisKasprzak/Powerpoint-ILI9341_t3). -11. Users of PowerPoint experienced with running macros may be interested in the [pptm sketch generator here](https://github.com/Bodmer/PowerPoint_to_sketch), this converts graphics and tables drawn in PowerPoint slides into an Arduino sketch that renders the graphics on a 480x320 TFT. This is based on VB macros [created by Kris Kasprzak here](https://github.com/KrisKasprzak/Powerpoint-ILI9341_t3). - -12. The library contains two new functions for rectangles filled with a horizontal or vertical coloured gradient: +11. The library contains two new functions for rectangles filled with a horizontal or vertical coloured gradient: tft.fillRectHGradient(x, y, w, h, color1, color2); @@ -52,19 +51,20 @@ Note: background rendering for Smooth fonts is also now available when using the ![Gradient](https://i.imgur.com/atR0DmP.png) -13. The RP2040 8 bit parallel interface uses the PIO. The PIO now manages the "setWindow" and "block fill" actions, releasing the processor for other tasks when areas of the screen are being filled with a colour. The PIO can optionally be used for SPI interface displays if #define RP2040_PIO_SPI is put in the setup file. Touch screens and pixel read operations are not supported when the PIO interface is used. +12. The RP2040 8-bit parallel interface uses the PIO. The PIO now manages the "setWindow" and "block fill" actions, releasing the processor for other tasks when areas of the screen are being filled with a colour. The PIO can optionally be used for SPI interface displays if #define RP2040_PIO_SPI is put in the setup file. Touch screens and pixel read operations are not supported when the PIO interface is used. The RP2040 PIO features only work with [Earle Philhower's board package](https://github.com/earlephilhower/arduino-pico), NOT the Arduino Mbed version. The use of PIO for SPI allows the RP2040 to be over-clocked (up to 250MHz works on my boards) in Earle's board package whilst still maintaining high SPI clock rates. -14. DMA can now be used with the Raspberry Pi Pico (RP2040) when used with both 8 bit parallel and 16 bit colour SPI displays. See "Bouncy_Circles" sketch. - - ["Bouncing circles"](https://www.youtube.com/watch?v=njFXIzCTQ_Q&lc=UgymaUIwOIuihvYh-Qt4AaABAg) - - # TFT_eSPI -An Arduino IDE compatible graphics and fonts library for 32 bit processors. The library is targeted at 32 bit processors, it has been performance optimised for RP2040, STM32, ESP8266 and ESP32 types, other processors may be used but will use the slower generic Arduino interface calls. The library can be loaded using the Arduino IDE's Library Manager. Direct Memory Access (DMA) can be used with the ESP32, RP2040 and STM32 processors with SPI interface displays to improve rendering performance. DMA with a parallel interface (8 and 16 bit parallel) is only supported with the RP2040. +A feature rich Arduino IDE compatible graphics and fonts library for 32-bit processors. The library is targeted at 32-bit processors, it has been performance optimised for RP2040, STM32, ESP8266 and ESP32 types, other 32-bit processors may be used but will use the slower generic Arduino interface calls. The library can be loaded using the Arduino IDE's Library Manager. Direct Memory Access (DMA) can be used with the ESP32, RP2040 and STM32 processors with SPI interface displays to improve rendering performance. DMA with a parallel interface (8 and 16-bit) is only supported with the RP2040. + +The updates for the ESP32 S2/C3/S3 means that the library requires the ESP32 Arduino board package 2.x.x or later. + +The screen controller, interface pins and library configuration settings must be defined inside the library. They can NOT be defined in the Arduino sketch. See the User_Setup_Select.h file for details. This approach has significant advantages, it keeps the examples clean from long configuration options and once the setup is defined any example can be run without modification. PlatformIO users can define these settings on a per project basis within a platformio.ini file, see Docs folder in library. + +Lots of example sketches are provided which demonstrate using the functions in the library. Due to the popularity of the library there are lots of online tutorials for TFT_eSPI that have been created by enthusiastic users. Optimised drivers have been tested with the following processors: @@ -73,9 +73,26 @@ Optimised drivers have been tested with the following processors: * ESP8266 * STM32F1xx, STM32F2xx, STM32F4xx, STM32F767 (higher RAM processors recommended) -For other processors only SPI interface displays are supported and the slower Arduino SPI library functions are used by the library. Higher clock speed processors such as used for the Teensy 3.x and 4.x boards will still provide a very good performance with the generic Arduino SPI functions. +The library supports the following interface types for these processors: -"Four wire" SPI and 8 bit parallel interfaces are supported. Due to lack of GPIO pins the 8 bit parallel interface is NOT supported on the ESP8266. 8 bit parallel interface TFTs (e.g. UNO format mcufriend shields) can used with the STM32 Nucleo 64/144 range or the UNO format ESP32 (see below for ESP32). +| Processor | 4 wire SPI | 8-bit parallel | 16-bit parallel | DMA support | +|-----------| :---: | :---: | :---: | :---: | +| RP2040 | Yes | Yes | Yes | Yes (all) | +| ESP32 | Yes | Yes | No | Yes (SPI only) | +| ESP32 C3 | Yes | No | No | No | +| ESP32 S2 | Yes | No | No | No | +| ESP32 S3 | Yes | Yes | No | Yes (SPI only) | +| ESP8266 | Yes | No | No | No | +| STM32Fxxx | Yes | Yes | No | Yes (SPI only) | +| Other | Yes | No | No | No | + +For other (generic) processors only SPI interface displays are supported and the slower Arduino SPI library functions are used by the library. Higher clock speed processors such as used for the Teensy 3.x and 4.x boards will still provide a very good performance with the generic Arduino SPI functions. + +4 wire SPI means the display must have SPI interface comaptible signals and a "Data/Command" control signal, this signal line is sometimes labelled DC, RS or A0. + +Due to lack of GPIO pins the 8-bit parallel interface is NOT supported on the ESP8266. 8-bit parallel interface TFTs (e.g. UNO format mcufriend shields) can used with the STM32Fxxx Nucleo 64/144 range or the UNO format ESP32 (see below for ESP32). + +Support for the XPT2046 touch screen controller is built into the library and can be used with SPI interface displays. Third party touch support libraries are also available when using a display parallel interface. Displays using the following controllers are supported: @@ -87,42 +104,40 @@ Displays using the following controllers are supported: * ILI9481 (DMA not supported with SPI) * ILI9486 (DMA not supported with SPI) * ILI9488 (DMA not supported with SPI) -* HX8357B (16 bit parallel tested with RP2040) -* HX8357C (16 bit parallel tested with RP2040) +* HX8357B (16-bit parallel tested with RP2040) +* HX8357C (16-bit parallel tested with RP2040) * HX8357D * R61581 * RM68120 (support files added but untested) * RM68140 * S6D02A1 * SSD1351 -* SSD1963 +* SSD1963 (this controller only has a parallel interface option) * ST7735 * ST7789 * ST7796 ILI9341 and ST7796 SPI based displays are recommended as starting point for experimenting with this library. -The library supports some TFT displays designed for the Raspberry Pi (RPi) that are based on a ILI9486 or ST7796 driver chip with a 480 x 320 pixel screen. The ILI9486 RPi display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. Note that due to design variations between these displays not all RPi displays will work with this library, so purchasing a RPi display of these types solely for use with this library is NOT recommended. +The library supports some TFT displays designed for the Raspberry Pi (RPi) that are based on a ILI9486 or ST7796 driver chip with a 480 x 320 pixel screen. The ILI9486 RPi display must be of the Waveshare design and use a 16-bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. Note that due to design variations between these displays not all RPi displays will work with this library, so purchasing a RPi display of these types solely for use with this library is NOT recommended. A "good" RPi display is the [MHS-4.0 inch Display-B type ST7796](http://www.lcdwiki.com/MHS-4.0inch_Display-B) which provides good performance. This has a dedicated controller and can be clocked at up to 80MHz with the ESP32 (125MHz with overclocked RP2040, 55MHz with STM32 and 40MHz with ESP8266). The [MHS-3.5 inch RPi ILI9486](http://www.lcdwiki.com/MHS-3.5inch_RPi_Display) based display is also supported, however the MHS ILI9341 based display of the same type does NOT work with this library. Some displays permit the internal TFT screen RAM to be read, a few of the examples use this feature. The TFT_Screen_Capture example allows full screens to be captured and sent to a PC, this is handy to create program documentation. -The library supports Waveshare 2 and 3 colour ePaper displays using full frame buffers. This addition is relatively immature and thus only one example has been provided. - The library includes a "Sprite" class, this enables flicker free updates of complex graphics. Direct writes to the TFT with graphics functions are still available, so existing sketches do not need to be changed. # Sprites -A Sprite is notionally an invisible graphics screen that is kept in the processors RAM. Graphics can be drawn into the Sprite just as they can be drawn directly to the screen. Once the Sprite is completed it can be plotted onto the screen in any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. Sprites by default use 16 bit colours, the bit depth can be set to 8 bits (256 colours) , or 1 bit (any 2 colours) to reduce the RAM needed. On an ESP8266 the largest 16 bit colour Sprite that can be created is about 160x128 pixels, this consumes 40Kbytes of RAM. On an ESP32 the workspace RAM is more limited than the datasheet implies so a 16 bit colour Sprite is limited to about 200x200 pixels (~80Kbytes), an 8 bit sprite to 320x240 pixels (~76kbytes). A 1 bit per pixel Sprite requires only 9600 bytes for a full 320 x 240 screen buffer, this is ideal for supporting use with 2 colour bitmap fonts. +A Sprite is notionally an invisible graphics screen that is kept in the processors RAM. Graphics can be drawn into the Sprite just as they can be drawn directly to the screen. Once the Sprite is completed it can be plotted onto the screen in any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. Sprites by default use 16-bit colours, the bit depth can be set to 8 bits (256 colours) , or 1 bit (any 2 colours) to reduce the RAM needed. On an ESP8266 the largest 16-bit colour Sprite that can be created is about 160x128 pixels, this consumes 40Kbytes of RAM. On an ESP32 the workspace RAM is more limited than the datasheet implies so a 16-bit colour Sprite is limited to about 200x200 pixels (~80Kbytes), an 8-bit sprite to 320x240 pixels (~76kbytes). A 1 bit per pixel Sprite requires only 9600 bytes for a full 320 x 240 screen buffer, this is ideal for supporting use with 2 colour bitmap fonts. -One or more sprites can be created, a sprite can be any pixel width and height, limited only by available RAM. The RAM needed for a 16 bit colour depth Sprite is (2 x width x height) bytes, for a Sprite with 8 bit colour depth the RAM needed is (width x height) bytes. Sprites can be created and deleted dynamically as needed in the sketch, this means RAM can be freed up after the Sprite has been plotted on the screen, more RAM intensive WiFi based code can then be run and normal graphics operations still work. +One or more sprites can be created, a sprite can be any pixel width and height, limited only by available RAM. The RAM needed for a 16-bit colour depth Sprite is (2 x width x height) bytes, for a Sprite with 8-bit colour depth the RAM needed is (width x height) bytes. Sprites can be created and deleted dynamically as needed in the sketch, this means RAM can be freed up after the Sprite has been plotted on the screen, more RAM intensive WiFi based code can then be run and normal graphics operations still work. Drawing graphics into a sprite is very fast, for those familiar with the Adafruit "graphicstest" example, this whole test completes in 18ms in a 160x128 sprite. Examples of sprite use can be found in the "examples/Sprite" folder. Sprites can be plotted to the TFT with one colour being specified as "transparent", see Transparent_Sprite_Demo example. -If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind. +If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16-bit Sprite), so bear that in mind. The "Animated_dial" example shows how dials can be created using a rotated Sprite for the needle. To run this example the TFT interface must support reading from the screen RAM (not all do). The dial rim and scale is a jpeg image, created using a paint program. @@ -142,7 +157,7 @@ The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI # Fonts -The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-aliased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. +The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-aliased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16-bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for the different processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions. @@ -151,7 +166,7 @@ Configuration of the library font selections, pins used to interface with the TF # Anti-aliased Fonts -Anti-aliased (smooth) font files in "vlw" format are generated by the free [Processing IDE](https://processing.org/) using a sketch included in the library Tools folder. This sketch with the Processing IDE can be used to generate font files from your computer's font set or any TrueType (.ttf) font, the font file can include **any** combination of 16 bit Unicode characters. This means Greek, Japanese and any other UCS-2 glyphs can be used. Character arrays and Strings in UTF-8 format are supported. +Anti-aliased (smooth) font files in "vlw" format are generated by the free [Processing IDE](https://processing.org/) using a sketch included in the library Tools folder. This sketch with the Processing IDE can be used to generate font files from your computer's font set or any TrueType (.ttf) font, the font file can include **any** combination of 16-bit Unicode characters. This means Greek, Japanese and any other UCS-2 glyphs can be used. Character arrays and Strings in UTF-8 format are supported. The .vlw files must be uploaded to the processors FLASH filing system (SPIFFS, LittleFS or SD card) for use. Alternatively the .vlw files can be converted to C arrays (see "Smooth Font -> FLASH_Array" examples) and stored directly in FLASH as part of the compile process. The array based approach is convenient, provides performance improvements and is suitable where: either use of a filing system is undesirable, or the processor type (e.g. STM32) does not support a FLASH based filing system. @@ -173,9 +188,9 @@ Anti-aliased fonts can also be drawn over a gradient background with a callback Anti-aliased fonts cannot be scaled with setTextSize so you need to create a font for each size you need. See examples. -# 8 bit parallel support +# 8-bit parallel support -The common 8 bit "Mcufriend" shields are supported for the STM Nucleo 64/144 boards and ESP32 UNO style board. The STM32 "Blue/Black Pill" boards can also be used with 8 bit parallel displays. +The common 8-bit "Mcufriend" shields are supported for the STM Nucleo 64/144 boards and ESP32 UNO style board. The STM32 "Blue/Black Pill" boards can also be used with 8-bit parallel displays. The ESP32 board I have been using for testing has the following pinout: @@ -210,10 +225,3 @@ You can take this one step further and have your own setup select file and then #include <../TFT_eSPI_Setups/my_setup_select.h> ``` To select a new setup you then edit your own my_setup_select.h file (which will not get overwritten during an upgrade). - -# ePaper displays - -The library was intended to support only TFT displays but using a Sprite as a 1 bit per pixel screen buffer permits support for the Waveshare 2 and 3 colour SPI ePaper displays. This addition to the library is experimental and only one example is provided. Further examples will be added. - -![Example](https://i.imgur.com/L2tV129.jpg?1) - diff --git a/trunk/Arduino/libraries/TFT_eSPI/README.txt b/trunk/Arduino/libraries/TFT_eSPI/README.txt index 0b738e6e..45eb4fbd 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/README.txt +++ b/trunk/Arduino/libraries/TFT_eSPI/README.txt @@ -3,5 +3,5 @@ and the TFT chip driver library. It supports the ESP8266, ESP32, STM32 and RP2040 processors with performance optimised code. Other Arduino IDE compatible boards are also supported but the library then uses generic functions which will be slower. The library uses -32 bit variables extensively so this will affect performance on 8 -and 16 bit processors. +32-bit variables extensively so this will affect performance on 8 +and 16-bit processors. diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/HX8357D_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/HX8357D_Init.h index 9b5f05a9..0e49d3f7 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/HX8357D_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/HX8357D_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the HX8357D driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format @@ -94,7 +94,7 @@ writedata(0x01); writecommand(HX8357_COLMOD); - writedata(0x55); // 16 bit + writedata(0x55); // 16-bit writecommand(HX8357_MADCTL); writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9163_Defines.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9163_Defines.h index 4abaa1dc..f1c63396 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9163_Defines.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9163_Defines.h @@ -42,6 +42,12 @@ #define TFT_NOP 0x00 #define TFT_SWRST 0x01 +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + #define TFT_CASET 0x2A #define TFT_PASET 0x2B #define TFT_RAMWR 0x2C @@ -57,6 +63,3 @@ #define TFT_MAD_BGR 0x08 #define TFT_MAD_MH 0x04 #define TFT_MAD_RGB 0x00 - -#define TFT_INVOFF 0x20 -#define TFT_INVON 0x21 diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Defines.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Defines.h index 70e17624..94ce1ef5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Defines.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Defines.h @@ -40,6 +40,12 @@ #define TFT_NOP 0x00 #define TFT_SWRST 0x01 +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + #define TFT_CASET 0x2A #define TFT_PASET 0x2B #define TFT_RAMWR 0x2C @@ -66,10 +72,6 @@ #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR #endif -#define TFT_INVOFF 0x20 -#define TFT_INVON 0x21 - - // All ILI9341 specific commands some are used by init() #define ILI9341_NOP 0x00 #define ILI9341_SWRESET 0x01 diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Init.h index 05a703ef..05a5dda3 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9341_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the ILI9341 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9481_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9481_Init.h index 3ac9965b..a5f19b89 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9481_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9481_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the ILI9481 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format @@ -64,9 +64,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) @@ -153,9 +153,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) @@ -242,9 +242,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) @@ -327,9 +327,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) @@ -415,9 +415,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) @@ -527,9 +527,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) @@ -605,9 +605,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) @@ -700,9 +700,9 @@ writecommand(0x3a); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Defines.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Defines.h index 31996e41..fcec0b86 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Defines.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Defines.h @@ -39,6 +39,12 @@ #define TFT_NOP 0x00 #define TFT_SWRST 0x01 +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + #define TFT_CASET 0x2A #define TFT_PASET 0x2B #define TFT_RAMWR 0x2C @@ -56,6 +62,3 @@ #define TFT_MAD_SS 0x02 #define TFT_MAD_GS 0x01 #define TFT_MAD_RGB 0x00 - -#define TFT_INVOFF 0x20 -#define TFT_INVON 0x21 diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Init.h index e96c4e43..db0f7aa3 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9486_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the ILI9486 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format @@ -16,9 +16,9 @@ writecommand(0x3A); #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour interface + writedata(0x55); // 16-bit colour interface #else - writedata(0x66); // 18 bit colour interface + writedata(0x66); // 18-bit colour interface #endif writecommand(0xC0); // 1100.0000 Power Control 1 diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9488_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9488_Init.h index d487187d..c1b20b6d 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9488_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ILI9488_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the ILI9488 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format @@ -59,9 +59,9 @@ writecommand(0x3A); // Pixel Interface Format #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) - writedata(0x55); // 16 bit colour for parallel + writedata(0x55); // 16-bit colour for parallel #else - writedata(0x66); // 18 bit colour for SPI + writedata(0x66); // 18-bit colour for SPI #endif writecommand(0xB0); // Interface Mode Control diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/R61581_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/R61581_Init.h index 929d680a..1e9adeee 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/R61581_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/R61581_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the R61581 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/RM68140_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/RM68140_Init.h index e5df339f..cc447195 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/RM68140_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/RM68140_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the RM68140 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/S6D02A1_Defines.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/S6D02A1_Defines.h index 96aea859..7806eb8b 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/S6D02A1_Defines.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/S6D02A1_Defines.h @@ -35,6 +35,12 @@ #define TFT_NOP 0x00 #define TFT_SWRST 0x01 +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + #define TFT_CASET 0x2A #define TFT_PASET 0x2B #define TFT_RAMWR 0x2C @@ -50,6 +56,3 @@ #define TFT_MAD_BGR 0x08 #define TFT_MAD_MH 0x04 #define TFT_MAD_RGB 0x00 - -#define TFT_INVOFF 0x20 -#define TFT_INVON 0x21 diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7735_Defines.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7735_Defines.h index 1c5c12f6..b02ee15e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7735_Defines.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7735_Defines.h @@ -95,6 +95,12 @@ #define TFT_NOP 0x00 #define TFT_SWRST 0x01 +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + #define TFT_CASET 0x2A #define TFT_PASET 0x2B #define TFT_RAMWR 0x2C @@ -125,9 +131,6 @@ #endif #endif -#define TFT_INVOFF 0x20 -#define TFT_INVON 0x21 - // ST7735 specific commands used in init #define ST7735_NOP 0x00 #define ST7735_SWRESET 0x01 diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7789_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7789_Init.h index 9fa2918b..b2ed7ebf 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7789_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7789_Init.h @@ -1,12 +1,13 @@ // This is the command sequence that initialises the ST7789 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format #ifndef INIT_SEQUENCE_3 { + fillScreen(TFT_RED); writecommand(ST7789_SLPOUT); // Sleep out delay(120); @@ -24,7 +25,7 @@ writecommand(ST7789_RAMCTRL); writedata(0x00); - writedata(0xE0); // 5 to 6 bit conversion: r0 = r5, b0 = b5 + writedata(0xE0); // 5 to 6-bit conversion: r0 = r5, b0 = b5 writecommand(ST7789_COLMOD); writedata(0x55); @@ -143,7 +144,7 @@ // writecommand(ST7789_RAMCTRL); // writedata(0x00); - // writedata(0xE0); // 5 to 6 bit conversion: r0 = r5, b0 = b5 + // writedata(0xE0); // 5 to 6-bit conversion: r0 = r5, b0 = b5 writecommand(ST7789_COLMOD); writedata(0x55); diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Defines.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Defines.h index ab75c485..d7009ac8 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Defines.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Defines.h @@ -1,12 +1,23 @@ // Change the width and height if required (defined in portrait mode) // or use the constructor to over-ride defaults +#ifndef TFT_WIDTH #define TFT_WIDTH 320 +#endif + +#ifndef TFT_HEIGHT #define TFT_HEIGHT 480 +#endif // Generic commands used by TFT_eSPI.cpp #define TFT_NOP 0x00 #define TFT_SWRST 0x01 +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + #define TFT_CASET 0x2A #define TFT_PASET 0x2B #define TFT_RAMWR 0x2C @@ -31,10 +42,6 @@ #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR #endif -#define TFT_INVOFF 0x20 -#define TFT_INVON 0x21 - - // ST7796 specific commands #define ST7796_NOP 0x00 #define ST7796_SWRESET 0x01 diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Init.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Init.h index a112815e..c1d84210 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Init.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Init.h @@ -1,7 +1,7 @@ // This is the command sequence that initialises the ST7796 driver // -// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// This setup information uses simple 8-bit SPI writecommand() and writedata() functions // // See ST7735_Setup.h file for an alternative format diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Rotation.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Rotation.h index 4788538a..c5f6ad69 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Rotation.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_Drivers/ST7796_Rotation.h @@ -9,21 +9,49 @@ writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER); _width = _init_width; _height = _init_height; +#ifdef CGRAM_OFFSET + if (_init_width == 222) + { + colstart = 49; + rowstart = 0; + } +#endif break; case 1: writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER); _width = _init_height; _height = _init_width; +#ifdef CGRAM_OFFSET + if (_init_width == 222) + { + colstart = 0; + rowstart = 49; + } +#endif break; case 2: writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER); _width = _init_width; _height = _init_height; +#ifdef CGRAM_OFFSET + if (_init_width == 222) + { + colstart = 49; + rowstart = 0; + } +#endif break; case 3: writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); _width = _init_height; _height = _init_width; +#ifdef CGRAM_OFFSET + if (_init_width == 222) + { + colstart = 0; + rowstart = 49; + } +#endif break; // These next rotations are for bottom up BMP drawing case 4: diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.cpp b/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.cpp index ca45ee77..d537faeb 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.cpp +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.cpp @@ -1,5 +1,5 @@ /*************************************************** - Arduino TFT graphics library targeted at 32 bit + Arduino TFT graphics library targeted at 32-bit processors such as ESP32, ESP8266 and STM32. This is a stand-alone library that contains the @@ -17,9 +17,9 @@ #if defined (ESP32) #if defined(CONFIG_IDF_TARGET_ESP32S3) - #include "Processors/TFT_eSPI_ESP32_S3.c" // Tested with SPI and 8 bit parallel + #include "Processors/TFT_eSPI_ESP32_S3.c" // Tested with SPI and 8-bit parallel #elif defined(CONFIG_IDF_TARGET_ESP32C3) - #include "Processors/TFT_eSPI_ESP32_C3.c" // Tested with SPI (8 bit parallel will probably work too!) + #include "Processors/TFT_eSPI_ESP32_C3.c" // Tested with SPI (8-bit parallel will probably work too!) #else #include "Processors/TFT_eSPI_ESP32.c" #endif @@ -467,7 +467,7 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) lockTransaction = false; // start/endWrite lock flag to allow sketch to keep SPI bus access open _booted = true; // Default attributes - _cp437 = true; // Legacy GLCD font bug fix + _cp437 = false; // Legacy GLCD font bug fix disabled by default _utf8 = true; // UTF8 decoding enabled #if defined (FONT_FS_AVAILABLE) && defined (SMOOTH_FONT) @@ -533,25 +533,33 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) void TFT_eSPI::initBus(void) { #ifdef TFT_CS - pinMode(TFT_CS, OUTPUT); - digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) + if (TFT_CS >= 0) { + pinMode(TFT_CS, OUTPUT); + digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) + } #endif // Configure chip select for touchscreen controller if present #ifdef TOUCH_CS - pinMode(TOUCH_CS, OUTPUT); - digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive) + if (TOUCH_CS >= 0) { + pinMode(TOUCH_CS, OUTPUT); + digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive) + } #endif // In parallel mode and with the RP2040 processor, the TFT_WR line is handled in the PIO #if defined (TFT_WR) && !defined (ARDUINO_ARCH_RP2040) && !defined (ARDUINO_ARCH_MBED) - pinMode(TFT_WR, OUTPUT); - digitalWrite(TFT_WR, HIGH); // Set write strobe high (inactive) + if (TFT_WR >= 0) { + pinMode(TFT_WR, OUTPUT); + digitalWrite(TFT_WR, HIGH); // Set write strobe high (inactive) + } #endif #ifdef TFT_DC - pinMode(TFT_DC, OUTPUT); - digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode + if (TFT_DC >= 0) { + pinMode(TFT_DC, OUTPUT); + digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode + } #endif #ifdef TFT_RST @@ -564,8 +572,10 @@ void TFT_eSPI::initBus(void) { #if defined (TFT_PARALLEL_8_BIT) // Make sure read is high before we set the bus to output - pinMode(TFT_RD, OUTPUT); - digitalWrite(TFT_RD, HIGH); + if (TFT_RD >= 0) { + pinMode(TFT_RD, OUTPUT); + digitalWrite(TFT_RD, HIGH); + } #if !defined (ARDUINO_ARCH_RP2040) && !defined (ARDUINO_ARCH_MBED)// PIO manages pins // Set TFT data bus lines to output @@ -649,8 +659,10 @@ void TFT_eSPI::init(uint8_t tc) #if defined (TFT_CS) && !defined(RP2040_PIO_INTERFACE) // Set to output once again in case MISO is used for CS - pinMode(TFT_CS, OUTPUT); - digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) + if (TFT_CS >= 0) { + pinMode(TFT_CS, OUTPUT); + digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) + } #elif defined (ARDUINO_ARCH_ESP8266) && !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_SPI) spi.setHwCs(1); // Use hardware SS toggling #endif @@ -658,8 +670,10 @@ void TFT_eSPI::init(uint8_t tc) // Set to output once again in case MISO is used for DC #if defined (TFT_DC) && !defined(RP2040_PIO_INTERFACE) + if (TFT_DC >= 0) { pinMode(TFT_DC, OUTPUT); digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode + } #endif _booted = false; @@ -670,7 +684,9 @@ void TFT_eSPI::init(uint8_t tc) #ifdef TFT_RST #if !defined(RP2040_PIO_INTERFACE) // Set to output once again in case MISO is used for TFT_RST - pinMode(TFT_RST, OUTPUT); + if (TFT_RST >= 0) { + pinMode(TFT_RST, OUTPUT); + } #endif if (TFT_RST >= 0) { writecommand(0x00); // Put SPI bus in known state for TFT with CS tied low @@ -768,13 +784,17 @@ void TFT_eSPI::init(uint8_t tc) setRotation(rotation); #if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON) - pinMode(TFT_BL, OUTPUT); - digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); + if (TFT_BL >= 0) { + pinMode(TFT_BL, OUTPUT); + digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); + } #else #if defined (TFT_BL) && defined (M5STACK) // Turn on the back-light LED - pinMode(TFT_BL, OUTPUT); - digitalWrite(TFT_BL, HIGH); + if (TFT_BL >= 0) { + pinMode(TFT_BL, OUTPUT); + digitalWrite(TFT_BL, HIGH); + } #endif #endif } @@ -922,7 +942,7 @@ void TFT_eSPI::commandList (const uint8_t *addr) { writecommand(pgm_read_byte(addr++)); // Read, issue command numArgs = pgm_read_byte(addr++); // Number of args to follow - ms = numArgs & TFT_INIT_DELAY; // If hibit set, delay follows args + ms = numArgs & TFT_INIT_DELAY; // If high bit set, delay follows args numArgs &= ~TFT_INIT_DELAY; // Mask out delay bit while (numArgs--) // For each argument... @@ -954,7 +974,7 @@ void TFT_eSPI::spiwrite(uint8_t c) /*************************************************************************************** ** Function name: writecommand -** Description: Send an 8 bit command to the TFT +** Description: Send an 8-bit command to the TFT ***************************************************************************************/ #ifndef RM68120_DRIVER void TFT_eSPI::writecommand(uint8_t c) @@ -968,7 +988,6 @@ void TFT_eSPI::writecommand(uint8_t c) DC_D; end_tft_write(); - } #else void TFT_eSPI::writecommand(uint16_t c) @@ -984,7 +1003,7 @@ void TFT_eSPI::writecommand(uint16_t c) end_tft_write(); } -void TFT_eSPI::writeRegister(uint16_t c, uint8_t d) +void TFT_eSPI::writeRegister8(uint16_t c, uint8_t d) { begin_tft_write(); @@ -999,11 +1018,27 @@ void TFT_eSPI::writeRegister(uint16_t c, uint8_t d) end_tft_write(); } +void TFT_eSPI::writeRegister16(uint16_t c, uint16_t d) +{ + begin_tft_write(); + + DC_C; + + tft_Write_16(c); + + DC_D; + + tft_Write_16(d); + + end_tft_write(); + +} + #endif /*************************************************************************************** ** Function name: writedata -** Description: Send a 8 bit data value to the TFT +** Description: Send a 8-bit data value to the TFT ***************************************************************************************/ void TFT_eSPI::writedata(uint8_t d) { @@ -1021,7 +1056,7 @@ void TFT_eSPI::writedata(uint8_t d) /*************************************************************************************** ** Function name: readcommand8 -** Description: Read a 8 bit data value from an indexed command register +** Description: Read a 8-bit data value from an indexed command register ***************************************************************************************/ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) { @@ -1064,7 +1099,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) /*************************************************************************************** ** Function name: readcommand16 -** Description: Read a 16 bit data value from an indexed command register +** Description: Read a 16-bit data value from an indexed command register ***************************************************************************************/ uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index) { @@ -1079,7 +1114,7 @@ uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index) /*************************************************************************************** ** Function name: readcommand32 -** Description: Read a 32 bit data value from an indexed command register +** Description: Read a 32-bit data value from an indexed command register ***************************************************************************************/ uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index) { @@ -1122,12 +1157,12 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) readByte(); #endif - // Fetch the 16 bit BRG pixel + // Fetch the 16-bit BRG pixel //uint16_t rgb = (readByte() << 8) | readByte(); #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9488_DRIVER) || defined (SSD1963_DRIVER)// Read 3 bytes - // Read window pixel 24 bit RGB values and fill in LS bits + // Read window pixel 24-bit RGB values and fill in LS bits uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3); if (!inTransaction) { CS_H; } // CS_H can be multi-statement @@ -1137,9 +1172,9 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) return rgb; - #else // ILI9481 or ILI9486 16 bit read + #else // ILI9481 or ILI9486 16-bit read - // Fetch the 16 bit BRG pixel + // Fetch the 16-bit BRG pixel uint16_t bgr = (readByte() << 8) | readByte(); if (!inTransaction) { CS_H; } // CS_H can be multi-statement @@ -1147,7 +1182,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) // Set masked pins D0- D7 to output busDir(GPIO_DIR_MASK, OUTPUT); - #ifdef ILI9486_DRIVER + #if defined (ILI9486_DRIVER) || defined (ST7796_DRIVER) return bgr; #else // Swap Red and Blue (could check MADCTL setting to see if this is needed) @@ -1181,6 +1216,13 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) #if defined (ST7796_DRIVER) // Read the 2 bytes color = ((tft_Read_8()) << 8) | (tft_Read_8()); + #elif defined (ST7735_DRIVER) + // Read the 3 RGB bytes, colour is in LS 6 bits of the top 7 bits of each byte + // as the TFT stores colours as 18 bits + uint8_t r = tft_Read_8()<<1; + uint8_t g = tft_Read_8()<<1; + uint8_t b = tft_Read_8()<<1; + color = color565(r, g, b); #else // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits @@ -1247,12 +1289,12 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da // Dummy read to throw away don't care value readByte(); - // Fetch the 24 bit RGB value + // Fetch the 24-bit RGB value while (dh--) { int32_t lw = dw; uint16_t* line = data; while (lw--) { - // Assemble the RGB 16 bit colour + // Assemble the RGB 16-bit colour uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3); // Swapped byte order for compatibility with pushRect() @@ -1262,7 +1304,7 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da } #elif defined (SSD1963_DRIVER) - // Fetch the 18 bit BRG pixels + // Fetch the 18-bit BRG pixels while (dh--) { int32_t lw = dw; uint16_t* line = data; @@ -1282,16 +1324,16 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da // Dummy read to throw away don't care value readByte(); - // Fetch the 16 bit BRG pixels + // Fetch the 16-bit BRG pixels while (dh--) { int32_t lw = dw; uint16_t* line = data; while (lw--) { - #ifdef ILI9486_DRIVER - // Read the RGB 16 bit colour + #if defined (ILI9486_DRIVER) || defined (ST7796_DRIVER) + // Read the RGB 16-bit colour *line++ = readByte() | (readByte() << 8); #else - // Read the BRG 16 bit colour + // Read the BRG 16-bit colour uint16_t bgr = (readByte() << 8) | readByte(); // Swap Red and Blue (could check MADCTL setting to see if this is needed) uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0); @@ -1330,7 +1372,7 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da // Dummy read to throw away don't care value tft_Read_8(); - // Read window pixel 24 bit RGB values + // Read window pixel 24-bit RGB values while (dh--) { int32_t lw = dw; uint16_t* line = data; @@ -1341,6 +1383,13 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da #if defined (ST7796_DRIVER) // Read the 2 bytes color = ((tft_Read_8()) << 8) | (tft_Read_8()); + #elif defined (ST7735_DRIVER) + // Read the 3 RGB bytes, colour is in LS 6 bits of the top 7 bits of each byte + // as the TFT stores colours as 18 bits + uint8_t r = tft_Read_8()<<1; + uint8_t g = tft_Read_8()<<1; + uint8_t b = tft_Read_8()<<1; + color = color565(r, g, b); #else // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits @@ -1394,7 +1443,7 @@ void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da /*************************************************************************************** ** Function name: pushImage -** Description: plot 16 bit colour sprite or image onto TFT +** Description: plot 16-bit colour sprite or image onto TFT ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { @@ -1424,7 +1473,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d /*************************************************************************************** ** Function name: pushImage -** Description: plot 16 bit sprite or image with 1 colour being transparent +** Description: plot 16-bit sprite or image with 1 colour being transparent ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp) { @@ -1483,11 +1532,11 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d /*************************************************************************************** ** Function name: pushImage - for FLASH (PROGMEM) stored images -** Description: plot 16 bit image +** Description: plot 16-bit image ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) { - // Requires 32 bit aligned access, so use PROGMEM 16 bit word functions + // Requires 32-bit aligned access, so use PROGMEM 16-bit word functions PI_CLIP; begin_tft_write(); @@ -1513,11 +1562,11 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 /*************************************************************************************** ** Function name: pushImage - for FLASH (PROGMEM) stored images -** Description: plot 16 bit image with 1 colour being transparent +** Description: plot 16-bit image with 1 colour being transparent ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp) { - // Requires 32 bit aligned access, so use PROGMEM 16 bit word functions + // Requires 32-bit aligned access, so use PROGMEM 16-bit word functions PI_CLIP; begin_tft_write(); @@ -1569,7 +1618,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 /*************************************************************************************** ** Function name: pushImage -** Description: plot 8 bit or 4 bit or 1 bit image or sprite using a line buffer +** Description: plot 8-bit or 4-bit or 1 bit image or sprite using a line buffer ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap) { @@ -1588,7 +1637,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8 { _swapBytes = false; - uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5-bit colour lookup table _lastColor = -1; // Set to illegal value @@ -1702,7 +1751,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8 /*************************************************************************************** ** Function name: pushImage -** Description: plot 8 bit or 4 bit or 1 bit image or sprite using a line buffer +** Description: plot 8-bit or 4-bit or 1 bit image or sprite using a line buffer ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8, uint16_t *cmap) { @@ -1721,7 +1770,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da { _swapBytes = false; - uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5-bit colour lookup table _lastColor = -1; // Set to illegal value @@ -1854,7 +1903,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da data += dx + dy * w; - uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5-bit colour lookup table _lastColor = -1; // Set to illegal value @@ -2040,7 +2089,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da /*************************************************************************************** ** Function name: pushMaskedImage -** Description: Render a 16 bit colour image with a 1bpp mask +** Description: Render a 16-bit colour image to TFT with a 1bpp mask ***************************************************************************************/ // Can be used with a 16bpp sprite and a 1bpp sprite for the mask void TFT_eSPI::pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask) @@ -2048,7 +2097,7 @@ void TFT_eSPI::pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint1 if (_vpOoB || w < 1 || h < 1) return; // To simplify mask handling the window clipping is done by the pushImage function - // Each mask image line assumed to be padded to and integer number of bytes & padding bits are 0 + // Each mask image line assumed to be padded to an integer number of bytes & padding bits are 0 begin_tft_write(); inTransaction = true; @@ -2109,7 +2158,7 @@ void TFT_eSPI::pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint1 xp += clearCount; clearCount = 0; pushImage(x + xp, y, setCount, 1, iptr + xp); // pushImage handles clipping - //pushImageDMA(x + xp, y, setCount, 1, iptr + xp); + if (mptr >= eptr) break; xp += setCount; } } while (setCount || mptr < eptr); @@ -2126,7 +2175,7 @@ void TFT_eSPI::pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint1 /*************************************************************************************** ** Function name: setSwapBytes -** Description: Used by 16 bit pushImage() to swap byte order in colours +** Description: Used by 16-bit pushImage() to swap byte order in colours ***************************************************************************************/ void TFT_eSPI::setSwapBytes(bool swap) { @@ -2182,7 +2231,7 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ // Dummy read to throw away don't care value tft_Read_8(); - // Read window pixel 24 bit RGB values, buffer must be set in sketch to 3 * w * h + // Read window pixel 24-bit RGB values, buffer must be set in sketch to 3 * w * h uint32_t len = w * h; while (len--) { @@ -2304,7 +2353,7 @@ void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t rr, uint8_t cor //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; - while (xe < rr--) + do { while (f < 0) { ++xe; @@ -2350,7 +2399,8 @@ void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t rr, uint8_t cor } } xs = xe; - } + } while (xe < rr--); + inTransaction = lockTransaction; end_tft_write(); // Does nothing if Sprite class uses this function } @@ -2817,7 +2867,7 @@ void TFT_eSPI::setCursor(int16_t x, int16_t y) ***************************************************************************************/ void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font) { - textfont = font; + setTextFont(font); cursor_x = x; cursor_y = y; } @@ -3090,7 +3140,7 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) /*************************************************************************************** ** Function name: fontsLoaded -** Description: return an encoded 16 bit value showing the fonts loaded +** Description: return an encoded 16-bit value showing the fonts loaded ***************************************************************************************/ // Returns a value showing which fonts are loaded (bit N set = Font N loaded) uint16_t TFT_eSPI::fontsLoaded(void) @@ -3103,8 +3153,10 @@ uint16_t TFT_eSPI::fontsLoaded(void) ** Function name: fontHeight ** Description: return the height of a font (yAdvance for free fonts) ***************************************************************************************/ -int16_t TFT_eSPI::fontHeight(int16_t font) +int16_t TFT_eSPI::fontHeight(uint8_t font) { + if (font > 8) return 0; + #ifdef SMOOTH_FONT if(fontLoaded) return gFont.yAdvance; #endif @@ -3132,11 +3184,10 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 { if (_vpOoB) return; - if (c < 32) return; #ifdef LOAD_GLCD //>>>>>>>>>>>>>>>>>> #ifdef LOAD_GFXFF - if(!gfxFont) { // 'Classic' built-in font + if(!gfxFont) { // 'Classic' built-in GLCD font #endif //>>>>>>>>>>>>>>>>>> @@ -3149,6 +3200,9 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 ((yd + 8 * size - 1) < _vpY)) // Clip top return; + if (c > 255) return; + if (!_cp437 && c > 175) c++; + bool fillbg = (bg != color); bool clip = xd < _vpX || xd + 6 * textsize >= _vpW || yd < _vpY || yd + 8 * textsize >= _vpH; @@ -3159,7 +3213,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 setWindow(xd, yd, xd+5, yd+7); - for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); + for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(&font[0] + (c * 5) + i); column[5] = 0; for (int8_t j = 0; j < 8; j++) { @@ -3182,7 +3236,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 if (i == 5) line = 0x0; else - line = pgm_read_byte(font + (c * 5) + i); + line = pgm_read_byte(&font[0] + (c * 5) + i); if (size == 1 && !fillbg) { // default size for (int8_t j = 0; j < 8; j++) { @@ -3332,7 +3386,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; // Temporary solution is to include the RP2040 code here #if (defined(ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined(RP2040_PIO_INTERFACE) - // For ILI9225 and RP2040 the slower Arduino SPI transfer calls were used, so need to swap back to 16 bit mode + // For ILI9225 and RP2040 the slower Arduino SPI transfer calls were used, so need to swap back to 16-bit mode while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); #endif @@ -3363,12 +3417,12 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) // Temporary solution is to include the RP2040 optimised code here #if (defined(ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) #if !defined(RP2040_PIO_INTERFACE) - // Use hardware SPI port, this code does not swap from 8 to 16 bit + // Use hardware SPI port, this code does not swap from 8 to 16-bit // to avoid the spi_set_format() call overhead while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; DC_C; #if !defined (SPI_18BIT_DRIVER) - #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers + #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16-bit transfers hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); #else hw_write_masked(&spi_get_hw(SPI_X)->cr0, (8 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); @@ -3403,6 +3457,18 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); #endif DC_D; + #elif defined (RM68120_DRIVER) + DC_C; tft_Write_16(TFT_CASET+0); DC_D; tft_Write_16(x0 >> 8); + DC_C; tft_Write_16(TFT_CASET+1); DC_D; tft_Write_16(x0 & 0xFF); + DC_C; tft_Write_16(TFT_CASET+2); DC_D; tft_Write_16(x1 >> 8); + DC_C; tft_Write_16(TFT_CASET+3); DC_D; tft_Write_16(x1 & 0xFF); + DC_C; tft_Write_16(TFT_PASET+0); DC_D; tft_Write_16(y0 >> 8); + DC_C; tft_Write_16(TFT_PASET+1); DC_D; tft_Write_16(y0 & 0xFF); + DC_C; tft_Write_16(TFT_PASET+2); DC_D; tft_Write_16(y1 >> 8); + DC_C; tft_Write_16(TFT_PASET+3); DC_D; tft_Write_16(y1 & 0xFF); + + DC_C; tft_Write_16(TFT_RAMWR); + DC_D; #else // This is for the RP2040 and PIO interface (SPI or parallel) WAIT_FOR_STALL; @@ -3454,7 +3520,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) // Temporary solution is to include the RP2040 optimised code here #if (defined(ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined(RP2040_PIO_INTERFACE) - // Use hardware SPI port, this code does not swap from 8 to 16 bit + // Use hardware SPI port, this code does not swap from 8 to 16-bit // to avoid the spi_set_format() call overhead while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; DC_C; @@ -3577,7 +3643,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #if !defined(RP2040_PIO_INTERFACE) while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; - #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers + #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16-bit transfers hw_write_masked(&spi_get_hw(SPI_X)->cr0, (16 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); #else hw_write_masked(&spi_get_hw(SPI_X)->cr0, (8 - 1) << SPI_SSPCR0_DSS_LSB, SPI_SSPCR0_DSS_BITS); @@ -3612,7 +3678,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_C; spi_get_hw(SPI_X)->dr = (uint32_t)TFT_RAMWR; - #if defined (SPI_18BIT_DRIVER) // SPI 18 bit colour + #if defined (SPI_18BIT_DRIVER) // SPI 18-bit colour uint8_t r = (color & 0xF800)>>8; uint8_t g = (color & 0x07E0)>>3; uint8_t b = (color & 0x001F)<<3; @@ -3622,7 +3688,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #else while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; DC_D; - #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers + #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16-bit transfers spi_get_hw(SPI_X)->dr = (uint32_t)color; #else spi_get_hw(SPI_X)->dr = (uint32_t)color>>8; @@ -3630,6 +3696,24 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #endif #endif while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; + #elif defined (RM68120_DRIVER) + if (addr_col != x) { + DC_C; tft_Write_16(TFT_CASET+0); DC_D; tft_Write_16(x >> 8); + DC_C; tft_Write_16(TFT_CASET+1); DC_D; tft_Write_16(x & 0xFF); + DC_C; tft_Write_16(TFT_CASET+2); DC_D; tft_Write_16(x >> 8); + DC_C; tft_Write_16(TFT_CASET+3); DC_D; tft_Write_16(x & 0xFF); + addr_col = x; + } + if (addr_row != y) { + DC_C; tft_Write_16(TFT_PASET+0); DC_D; tft_Write_16(y >> 8); + DC_C; tft_Write_16(TFT_PASET+1); DC_D; tft_Write_16(y & 0xFF); + DC_C; tft_Write_16(TFT_PASET+2); DC_D; tft_Write_16(y >> 8); + DC_C; tft_Write_16(TFT_PASET+3); DC_D; tft_Write_16(y & 0xFF); + addr_row = y; + } + DC_C; tft_Write_16(TFT_RAMWR); DC_D; + + TX_FIFO = color; #else // This is for the RP2040 and PIO interface (SPI or parallel) WAIT_FOR_STALL; @@ -3761,7 +3845,7 @@ void TFT_eSPI::writeColor(uint16_t color, uint32_t len) /*************************************************************************************** ** Function name: pushColors -** Description: push an array of pixels for 16 bit raw image drawing +** Description: push an array of pixels for 16-bit raw image drawing ***************************************************************************************/ // Assumed that setAddrWindow() has previously been called // len is number of bytes, not pixels @@ -3795,7 +3879,7 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) ** Function name: drawLine ** Description: draw a line between 2 arbitrary points ***************************************************************************************/ -// Bresenham's algorithm - thx wikipedia - speed enhanced by Bodmer to use +// Bresenham's algorithm - thx Wikipedia - speed enhanced by Bodmer to use // an efficient FastH/V Line draw routine for line segments of 2 pixels or more void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { @@ -3875,7 +3959,7 @@ constexpr float deg2rad = 3.14159265359/180.0; uint16_t TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color) { if (bg_color == 0x00FFFFFF) bg_color = readPixel(x, y); - color = alphaBlend(alpha, color, bg_color); + color = fastBlend(alpha, color, bg_color); drawPixel(x, y, color); return color; } @@ -3885,7 +3969,7 @@ uint16_t TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha ** Function name: drawSmoothArc ** Description: Draw a smooth arc clockwise from 6 o'clock ***************************************************************************************/ -void TFT_eSPI::drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t startAngle, int32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds) +void TFT_eSPI::drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds) // Centre at x,y // r = arc outer radius, ir = arc inner radius. Inclusive so arc thickness = r - ir + 1 // Angles in range 0-360 @@ -3946,7 +4030,7 @@ void TFT_eSPI::drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, int32_ ***************************************************************************************/ // Compute the fixed point square root of an integer and // return the 8 MS bits of fractional part. -// Quicker than sqrt() for processors that do not have and FPU (e.g. RP2040) +// Quicker than sqrt() for processors that do not have an FPU (e.g. RP2040) inline uint8_t TFT_eSPI::sqrt_fraction(uint32_t num) { if (num > (0x40000000)) return 0; uint32_t bsh = 0x00004000; @@ -3980,39 +4064,35 @@ inline uint8_t TFT_eSPI::sqrt_fraction(uint32_t num) { // smooth is optional, default is true, smooth=false means no antialiasing // Note: Arc ends are not anti-aliased (use drawSmoothArc instead for that) void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, - int32_t startAngle, int32_t endAngle, + uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smooth) { - if (endAngle < startAngle) { - // Arc sweeps through 6 o'clock so draw in two parts - drawArc(x, y, r, ir, startAngle, 360, fg_color, bg_color, smooth); - startAngle = 0; - } - + if (endAngle > 360) endAngle = 360; + if (startAngle > 360) startAngle = 360; if (_vpOoB || startAngle == endAngle) return; if (r < ir) transpose(r, ir); // Required that r > ir if (r <= 0 || ir < 0) return; // Invalid r, ir can be zero (circle sector) - if (startAngle < 0) startAngle = 0; - if (endAngle > 360) endAngle = 360; + if (endAngle < startAngle) { + // Arc sweeps through 6 o'clock so draw in two parts + if (startAngle < 360) drawArc(x, y, r, ir, startAngle, 360, fg_color, bg_color, smooth); + if (endAngle == 0) return; + startAngle = 0; + } inTransaction = true; - int32_t xs = 0; // x start position for quadrant scan - uint8_t alpha = 0; // alpha value for blending pixels + int32_t xs = 0; // x start position for quadrant scan + uint8_t alpha = 0; // alpha value for blending pixels uint32_t r2 = r * r; // Outer arc radius^2 - if (smooth) r++; // Outer AA zone radius + if (smooth) r++; // Outer AA zone radius uint32_t r1 = r * r; // Outer AA radius^2 - int16_t w = r - ir; // Width of arc (r - ir + 1) + int16_t w = r - ir; // Width of arc (r - ir + 1) uint32_t r3 = ir * ir; // Inner arc radius^2 - if (smooth) ir--; // Inner AA zone radius + if (smooth) ir--; // Inner AA zone radius uint32_t r4 = ir * ir; // Inner AA radius^2 - // Float variants of adjusted inner and outer arc radii - //float irf = ir; - //float rf = r; - // 1 | 2 // ---¦--- Arc quadrant index // 0 | 3 @@ -4028,7 +4108,7 @@ void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, float fabssin = fabsf(sinf(startAngle * deg2rad)); // U16.16 slope of arc start - uint32_t slope = (fabscos/(fabssin + minDivisor)) * (float)(1<<16); + uint32_t slope = (fabscos/(fabssin + minDivisor)) * (float)(1UL<<16); // Update slope table, add slope for arc start if (startAngle <= 90) { @@ -4052,7 +4132,7 @@ void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, fabssin = fabsf(sinf(endAngle * deg2rad)); // U16.16 slope of arc end - slope = (uint32_t)((fabscos/(fabssin + minDivisor)) * (float)(1<<16)); + slope = (uint32_t)((fabscos/(fabssin + minDivisor)) * (float)(1UL<<16)); // Work out which quadrants will need to be drawn and add slope for arc end if (endAngle <= 90) { @@ -4088,45 +4168,39 @@ void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, // If in outer zone calculate alpha if (hyp > r2) { - //alpha = (uint8_t)((rf - sqrtf(hyp)) * 255); alpha = ~sqrt_fraction(hyp); // Outer AA zone } // If within arc fill zone, get line start and lengths for each quadrant else if (hyp >= r3) { - do { - // Calculate U16.16 slope - slope = ((r - cy) << 16)/(r - cx); - if (slope <= startSlope[0] && slope >= endSlope[0]) { // slope hi -> lo - xst[0] = cx; // Bottom left line end - len[0]++; - } - if (slope >= startSlope[1] && slope <= endSlope[1]) { // slope lo -> hi - xst[1] = cx; // Top left line end - len[1]++; - } - if (slope <= startSlope[2] && slope >= endSlope[2]) { // slope hi -> lo - xst[2] = cx; // Bottom right line start - len[2]++; - } - if (slope <= endSlope[3] && slope >= startSlope[3]) { // slope lo -> hi - xst[3] = cx; // Top right line start - len[3]++; - } - cx++; - } while ((r - cx) * (r - cx) + dy2 >= r3 && cx < r); - cx--; + // Calculate U16.16 slope + slope = ((r - cy) << 16)/(r - cx); + if (slope <= startSlope[0] && slope >= endSlope[0]) { // slope hi -> lo + xst[0] = cx; // Bottom left line end + len[0]++; + } + if (slope >= startSlope[1] && slope <= endSlope[1]) { // slope lo -> hi + xst[1] = cx; // Top left line end + len[1]++; + } + if (slope <= startSlope[2] && slope >= endSlope[2]) { // slope hi -> lo + xst[2] = cx; // Bottom right line start + len[2]++; + } + if (slope <= endSlope[3] && slope >= startSlope[3]) { // slope lo -> hi + xst[3] = cx; // Top right line start + len[3]++; + } continue; // Next x } else { if (hyp <= r4) break; // Skip inner pixels - //alpha = (uint8_t)((sqrtf(hyp) - irf) * 255.0); alpha = sqrt_fraction(hyp); // Inner AA zone } if (alpha < 16) continue; // Skip low alpha pixels // If background is read it must be done in each quadrant - uint16_t pcol = alphaBlend(alpha, fg_color, bg_color); + uint16_t pcol = fastBlend(alpha, fg_color, bg_color); // Check if an AA pixels need to be drawn slope = ((r - cy)<<16)/(r - cx); if (slope <= startSlope[0] && slope >= endSlope[0]) // BL @@ -4191,19 +4265,12 @@ void TFT_eSPI::fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, int32_t hyp2 = (r - cx) * (r - cx) + dy2; if (hyp2 <= r1) break; if (hyp2 >= r2) continue; -//* + uint8_t alpha = ~sqrt_fraction(hyp2); if (alpha > 246) break; xs = cx; if (alpha < 9) continue; - //*/ -/* - float alphaf = (float)r - sqrtf(hyp2); - if (alphaf > HiAlphaTheshold) break; - xs = cx; - if (alphaf < LoAlphaTheshold) continue; - uint8_t alpha = alphaf * 255; -//*/ + if (bg_color == 0x00FFFFFF) { drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color); drawPixel(x - cx + r, y + cy - r, color, alpha, bg_color); @@ -4243,7 +4310,7 @@ void TFT_eSPI::drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, { if (_vpOoB) return; if (r < ir) transpose(r, ir); // Required that r > ir - if (r <= 0 || ir < 0) return; // Invalid + if (r <= 0 || ir < 0) return; // Invalid w -= 2*r; h -= 2*r; @@ -4255,13 +4322,7 @@ void TFT_eSPI::drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, x += r; y += r; -/* - float alphaGain = 1.0; - if (w != 0 || h != 0) { - if (r - ir < 2) alphaGain = 1.5; // Boost brightness for thin lines - if (r - ir < 1) alphaGain = 1.7; - } -*/ + uint16_t t = r - ir + 1; int32_t xs = 0; int32_t cx = 0; @@ -4274,8 +4335,6 @@ void TFT_eSPI::drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, ir--; int32_t r4 = ir * ir; // Inner AA zone radius^2 - //float irf = ir; - //float rf = r; uint8_t alpha = 0; // Scan top left quadrant x y r ir fg_color bg_color @@ -4296,8 +4355,7 @@ void TFT_eSPI::drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, // If in outer zone calculate alpha if (hyp > r2) { - alpha = ~sqrt_fraction(hyp); - //alpha = (uint8_t)((rf - sqrtf(hyp)) * 255); // Outer AA zone + alpha = ~sqrt_fraction(hyp); // Outer AA zone } // If within arc fill zone, get line lengths for each quadrant else if (hyp >= r3) { @@ -4307,14 +4365,13 @@ void TFT_eSPI::drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, } else { if (hyp <= r4) break; // Skip inner pixels - //alpha = (uint8_t)((sqrtf(hyp) - irf) * 255); // Inner AA zone - alpha = sqrt_fraction(hyp); + alpha = sqrt_fraction(hyp); // Inner AA zone } if (alpha < 16) continue; // Skip low alpha pixels // If background is read it must be done in each quadrant - TODO - uint16_t pcol = alphaBlend(alpha, fg_color, bg_color); + uint16_t pcol = fastBlend(alpha, fg_color, bg_color); if (quadrants & 0x8) drawPixel(x + cx - r, y - cy + r + h, pcol); // BL if (quadrants & 0x1) drawPixel(x + cx - r, y + cy - r, pcol); // TL if (quadrants & 0x2) drawPixel(x - cx + r + w, y + cy - r, pcol); // TR @@ -4379,13 +4436,7 @@ void TFT_eSPI::fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, i if (alpha > 246) break; xs = cx; if (alpha < 9) continue; -/* - float alphaf = (float)r - sqrtf(hyp2); - if (alphaf > HiAlphaTheshold) break; - xs = cx; - if (alphaf < LoAlphaTheshold) continue; - uint8_t alpha = alphaf * 255; -*/ + drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color); drawPixel(x - cx + r + w, y + cy - r, color, alpha, bg_color); drawPixel(x - cx + r + w, y - cy + r + h, color, alpha, bg_color); @@ -4463,16 +4514,26 @@ void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, f // Track edge to minimise calculations if (!endX) { endX = true; xs = xp; } if (alpha > HiAlphaTheshold) { - if (swin) { setWindow(xp, yp, width()-1, yp); swin = false; } - pushColor(fg_color); + #ifdef GC9A01_DRIVER + drawPixel(xp, yp, fg_color); + #else + if (swin) { setWindow(xp, yp, x1, yp); swin = false; } + pushColor(fg_color); + #endif continue; } //Blend color with background and plot if (bg_color == 0x00FFFFFF) { bg = readPixel(xp, yp); swin = true; } - if (swin) { setWindow(xp, yp, width()-1, yp); swin = false; } - pushColor(alphaBlend((uint8_t)(alpha * PixelAlphaGain), fg_color, bg)); + #ifdef GC9A01_DRIVER + uint16_t pcol = fastBlend((uint8_t)(alpha * PixelAlphaGain), fg_color, bg); + drawPixel(xp, yp, pcol); + swin = swin; + #else + if (swin) { setWindow(xp, yp, x1, yp); swin = false; } + pushColor(fastBlend((uint8_t)(alpha * PixelAlphaGain), fg_color, bg)); + #endif } } @@ -4491,16 +4552,26 @@ void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, f // Track line boundary if (!endX) { endX = true; xs = xp; } if (alpha > HiAlphaTheshold) { - if (swin) { setWindow(xp, yp, width()-1, yp); swin = false; } - pushColor(fg_color); + #ifdef GC9A01_DRIVER + drawPixel(xp, yp, fg_color); + #else + if (swin) { setWindow(xp, yp, x1, yp); swin = false; } + pushColor(fg_color); + #endif continue; } //Blend colour with background and plot if (bg_color == 0x00FFFFFF) { bg = readPixel(xp, yp); swin = true; } - if (swin) { setWindow(xp, yp, width()-1, yp); swin = false; } - pushColor(alphaBlend((uint8_t)(alpha * PixelAlphaGain), fg_color, bg)); + #ifdef GC9A01_DRIVER + uint16_t pcol = fastBlend((uint8_t)(alpha * PixelAlphaGain), fg_color, bg); + drawPixel(xp, yp, pcol); + swin = swin; + #else + if (swin) { setWindow(xp, yp, x1, yp); swin = false; } + pushColor(fastBlend((uint8_t)(alpha * PixelAlphaGain), fg_color, bg)); + #endif } } @@ -4653,7 +4724,7 @@ void TFT_eSPI::fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uin while (h--) { drawFastHLine(x, y++, w, color); alpha += delta; - color = alphaBlend((uint8_t)alpha, color1, color2); + color = fastBlend((uint8_t)alpha, color1, color2); } end_nin_write(); @@ -4691,7 +4762,7 @@ void TFT_eSPI::fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uin while (w--) { drawFastVLine(x++, y, h, color); alpha += delta; - color = alphaBlend((uint8_t)alpha, color1, color2); + color = fastBlend((uint8_t)alpha, color1, color2); } end_nin_write(); @@ -4700,7 +4771,7 @@ void TFT_eSPI::fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uin /*************************************************************************************** ** Function name: color565 -** Description: convert three 8 bit RGB levels to a 16 bit colour value +** Description: convert three 8-bit RGB levels to a 16-bit colour value ***************************************************************************************/ uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b) { @@ -4710,7 +4781,7 @@ uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b) /*************************************************************************************** ** Function name: color16to8 -** Description: convert 16 bit colour to an 8 bit 332 RGB colour value +** Description: convert 16-bit colour to an 8-bit 332 RGB colour value ***************************************************************************************/ uint8_t TFT_eSPI::color16to8(uint16_t c) { @@ -4720,11 +4791,11 @@ uint8_t TFT_eSPI::color16to8(uint16_t c) /*************************************************************************************** ** Function name: color8to16 -** Description: convert 8 bit colour to a 16 bit 565 colour value +** Description: convert 8-bit colour to a 16-bit 565 colour value ***************************************************************************************/ uint16_t TFT_eSPI::color8to16(uint8_t color) { - uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5-bit colour lookup table uint16_t color16 = 0; // =====Green===== ===============Red============== @@ -4737,7 +4808,7 @@ uint16_t TFT_eSPI::color8to16(uint8_t color) /*************************************************************************************** ** Function name: color16to24 -** Description: convert 16 bit colour to a 24 bit 888 colour value +** Description: convert 16-bit colour to a 24-bit 888 colour value ***************************************************************************************/ uint32_t TFT_eSPI::color16to24(uint16_t color565) { @@ -4750,7 +4821,7 @@ uint32_t TFT_eSPI::color16to24(uint16_t color565) /*************************************************************************************** ** Function name: color24to16 -** Description: convert 24 bit colour to a 16 bit 565 colour value +** Description: convert 24-bit colour to a 16-bit 565 colour value ***************************************************************************************/ uint32_t TFT_eSPI::color24to16(uint32_t color888) { @@ -4831,26 +4902,26 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t c) { if (!_utf8) return c; - // 7 bit Unicode Code Point + // 7-bit Unicode Code Point if ((c & 0x80) == 0x00) { decoderState = 0; return c; } if (decoderState == 0) { - // 11 bit Unicode Code Point + // 11-bit Unicode Code Point if ((c & 0xE0) == 0xC0) { decoderBuffer = ((c & 0x1F)<<6); decoderState = 1; return 0; } - // 16 bit Unicode Code Point + // 16-bit Unicode Code Point if ((c & 0xF0) == 0xE0) { decoderBuffer = ((c & 0x0F)<<12); decoderState = 2; return 0; } - // 21 bit Unicode Code Point not supported so fall-back to extended ASCII + // 21-bit Unicode Code Point not supported so fall-back to extended ASCII // if ((c & 0xF8) == 0xF0) return c; } else { @@ -4883,21 +4954,24 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) if (!_utf8) return c; - // 7 bit Unicode + // 7-bit Unicode if ((c & 0x80) == 0x00) return c; - // 11 bit Unicode + // 11-bit Unicode if (((c & 0xE0) == 0xC0) && (remaining > 1)) return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F); - // 16 bit Unicode + // 16-bit Unicode if (((c & 0xF0) == 0xE0) && (remaining > 2)) { c = ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6); return c | ((buf[(*index)++]&0x3F)); } - // 21 bit Unicode not supported so fall-back to extended ASCII - // if ((c & 0xF8) == 0xF0) return c; + // 21-bit Unicode not supported so fall-back to extended ASCII + // if (((c & 0xF8) == 0xF0) && (remaining > 3)) { + // c = ((c & 0x07) << 18) | ((buf[(*index)++] & 0x03F) << 12); + // c |= ((buf[(*index)++] & 0x3F) << 6); + // return c | ((buf[(*index)++] & 0x3F)); return c; // fall-back to extended ASCII } @@ -4907,12 +4981,12 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) ** Function name: alphaBlend ** Description: Blend 16bit foreground and background *************************************************************************************x*/ -inline uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc) +uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc) { - // Split out and blend 5 bit red and blue channels + // Split out and blend 5-bit red and blue channels uint32_t rxb = bgc & 0xF81F; rxb += ((fgc & 0xF81F) - rxb) * (alpha >> 2) >> 6; - // Split out and blend 6 bit green channel + // Split out and blend 6-bit green channel uint32_t xgx = bgc & 0x07E0; xgx += ((fgc & 0x07E0) - xgx) * alpha >> 8; // Recombine channels @@ -4952,9 +5026,9 @@ uint32_t TFT_eSPI::alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8 uint32_t rxx = bgc & 0xFF0000; rxx += ((fgc & 0xFF0000) - rxx) * alpha >> 8; uint32_t xgx = bgc & 0x00FF00; - xgx += ((fgc & 0xFF0000) - xgx) * alpha >> 8; + xgx += ((fgc & 0x00FF00) - xgx) * alpha >> 8; uint32_t xxb = bgc & 0x0000FF; - xxb += ((fgc & 0xFF0000) - xxb) * alpha >> 8; + xxb += ((fgc & 0x0000FF) - xxb) * alpha >> 8; return (rxx & 0xFF0000) | (xgx & 0x00FF00) | (xxb & 0x0000FF); } @@ -5002,7 +5076,6 @@ size_t TFT_eSPI::write(uint8_t utf8) #endif if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors - else if (uniCode < 32) return 1; uint16_t cwidth = 0; uint16_t cheight = 0; @@ -5021,7 +5094,7 @@ size_t TFT_eSPI::write(uint8_t utf8) #ifdef LOAD_FONT2 if (textfont == 2) { - if (uniCode > 127) return 1; + if (uniCode < 32 || uniCode > 127) return 1; cwidth = pgm_read_byte(widtbl_f16 + uniCode-32); cheight = chr_hgt_f16; @@ -5037,7 +5110,7 @@ size_t TFT_eSPI::write(uint8_t utf8) #ifdef LOAD_RLE { if ((textfont>2) && (textfont<9)) { - if (uniCode > 127) return 1; + if (uniCode < 32 || uniCode > 127) return 1; // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements cwidth = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); cheight= pgm_read_byte( &fontdata[textfont].height ); @@ -5284,7 +5357,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) uint8_t tnp = 0; // Temporary copy of np for while loop uint8_t ts = textsize - 1; // Temporary copy of textsize - // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area + // 16-bit pixel count so maximum font size is equivalent to 180x180 pixels in area // w is total number of pixels to plot to fill character block while (pc < w) { line = pgm_read_byte((uint8_t *)flash_address); @@ -5430,6 +5503,8 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY) // With font number. Note: font number is over-ridden if a smooth font is loaded int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font) { + if (font > 8) return 0; + int16_t sumX = 0; uint8_t padding = 1, baseline = 0; uint16_t cwidth = textWidth(string, font); // Find the pixel width of the string in the font @@ -5835,6 +5910,7 @@ void TFT_eSPI::setFreeFont(const GFXfont *f) void TFT_eSPI::setTextFont(uint8_t f) { textfont = (f > 0) ? f : 1; // Don't allow font 0 + textfont = (f > 8) ? 1 : f; // Don't allow font > 8 gfxFont = NULL; } @@ -5860,6 +5936,7 @@ void TFT_eSPI::setFreeFont(uint8_t font) void TFT_eSPI::setTextFont(uint8_t f) { textfont = (f > 0) ? f : 1; // Don't allow font 0 + textfont = (f > 8) ? 1 : f; // Don't allow font > 8 } #endif @@ -5868,7 +5945,7 @@ void TFT_eSPI::setTextFont(uint8_t f) ** Function name: getSPIinstance ** Description: Get the instance of the SPI class ***************************************************************************************/ -#if !defined (TFT_PARALLEL_8_BIT) && ! defined (RP2040_PIO_INTERFACE) +#if !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_INTERFACE) SPIClass& TFT_eSPI::getSPIinstance(void) { return spi; @@ -5931,10 +6008,12 @@ void TFT_eSPI::getSetup(setup_t &tft_settings) #ifdef SPI_READ_FREQUENCY tft_settings.tft_rd_freq = SPI_READ_FREQUENCY/100000; #endif - #ifdef TFT_SPI_PORT - tft_settings.port = TFT_SPI_PORT; - #else - tft_settings.port = 255; + #ifndef GENERIC_PROCESSOR + #ifdef TFT_SPI_PORT + tft_settings.port = TFT_SPI_PORT; + #else + tft_settings.port = 255; + #endif #endif #ifdef RP2040_PIO_SPI tft_settings.interface = 0x10; diff --git a/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.h b/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.h index 94cfb80e..8ae23427 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.h +++ b/trunk/Arduino/libraries/TFT_eSPI/TFT_eSPI.h @@ -12,11 +12,11 @@ Last review/edit by Bodmer: 04/02/22 ****************************************************/ -// Stop fonts etc being loaded multiple times +// Stop fonts etc. being loaded multiple times #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "2.5.0" +#define TFT_ESPI_VERSION "2.5.43" // Bit level feature flags // Bit 0 set: viewport capability @@ -29,13 +29,14 @@ //Standard support #include #include -#include - +#if !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_INTERFACE) + #include +#endif /*************************************************************************************** ** Section 2: Load library and processor specific header files ***************************************************************************************/ // Include header file that defines the fonts loaded, the TFT drivers -// available and the pins to be used, etc, etc +// available and the pins to be used, etc. etc. #ifdef CONFIG_TFT_eSPI_ESPIDF #include "TFT_config.h" #endif @@ -106,6 +107,7 @@ #include "Processors/TFT_eSPI_RP2040.h" #else #include "Processors/TFT_eSPI_Generic.h" + #define GENERIC_PROCESSOR #endif /*************************************************************************************** @@ -143,6 +145,17 @@ #define SPI_BUSY_CHECK #endif +// If half duplex SDA mode is defined then MISO pin should be -1 +#ifdef TFT_SDA_READ + #ifdef TFT_MISO + #if TFT_MISO != -1 + #undef TFT_MISO + #define TFT_MISO -1 + #warning TFT_MISO set to -1 + #endif + #endif +#endif + /*************************************************************************************** ** Section 4: Setup fonts ***************************************************************************************/ @@ -314,12 +327,12 @@ const PROGMEM fontinfo fontdata [] = { #define TFT_SKYBLUE 0x867D /* 135, 206, 235 */ #define TFT_VIOLET 0x915C /* 180, 46, 226 */ -// Next is a special 16 bit colour value that encodes to 8 bits -// and will then decode back to the same 16 bit value. -// Convenient for 8 bit and 16 bit transparent sprites. +// Next is a special 16-bit colour value that encodes to 8 bits +// and will then decode back to the same 16-bit value. +// Convenient for 8-bit and 16-bit transparent sprites. #define TFT_TRANSPARENT 0x0120 // This is actually a dark green -// Default palette for 4 bit colour sprites +// Default palette for 4-bit colour sprites static const uint16_t default_4bit_palette[] PROGMEM = { TFT_BLACK, // 0 ^ TFT_BROWN, // 1 | @@ -355,7 +368,9 @@ uint32_t setup_id; // ID available to use in a user setup int32_t esp; // Processor code uint8_t trans; // SPI transaction support uint8_t serial; // Serial (SPI) or parallel +#ifndef GENERIC_PROCESSOR uint8_t port; // SPI port +#endif uint8_t overlap; // ESP8266 overlap mode uint8_t interface; // Interface type @@ -490,7 +505,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input #ifdef TFT_SDA_READ #if defined (TFT_eSPI_ENABLE_8_BIT_READ) - uint8_t tft_Read_8(void); // Read 8 bit value from TFT command register + uint8_t tft_Read_8(void); // Read 8-bit value from TFT command register #endif void begin_SDA_Read(void); // Begin a read on a half duplex (bi-directional SDA) SPI bus - sets MOSI to input void end_SDA_Read(void); // Restore MOSI to output @@ -528,12 +543,12 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // By default the arc is drawn with square ends unless the "roundEnds" parameter is included and set true // Angle = 0 is at 6 o'clock position, 90 at 9 o'clock etc. The angles must be in range 0-360 or they will be clipped to these limits // The start angle may be larger than the end angle. Arcs are always drawn clockwise from the start angle. - void drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t startAngle, int32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds = false); + void drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds = false); // As per "drawSmoothArc" except the ends of the arc are NOT anti-aliased, this facilitates dynamic arc length changes with // arc segments and ensures clean segment joints. // The sides of the arc are anti-aliased by default. If smoothArc is false sides will NOT be anti-aliased - void drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t startAngle, int32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smoothArc = true); + void drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smoothArc = true); // Draw an anti-aliased filled circle at x, y with radius r // Note: The thickness of line is 3 pixels to reduce the visible "braiding" effect of anti-aliasing narrow lines @@ -583,7 +598,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac getPivotY(void); // Get pivot y // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location - // Read a block of pixels to a data buffer, buffer is 16 bit and the size must be at least w * h + // Read a block of pixels to a data buffer, buffer is 16-bit and the size must be at least w * h void readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); // Write a block of pixels to the screen which have been read by readRect() void pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); @@ -604,11 +619,11 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // FLASH version void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap = nullptr); - // Render a 16 bit colour image with a 1bpp mask + // Render a 16-bit colour image with a 1bpp mask void pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask); // This next function has been used successfully to dump the TFT screen to a PC for documentation purposes - // It reads a screen area and returns the 3 RGB 8 bit colour values of each pixel in the buffer + // It reads a screen area and returns the 3 RGB 8-bit colour values of each pixel in the buffer // Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data); @@ -635,7 +650,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString() - // Text rendering and font handling support funtions + // Text rendering and font handling support functions void setCursor(int16_t x, int16_t y), // Set cursor for tft.print() setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print() @@ -648,7 +663,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac void setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height - void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 6 above + void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 5 above uint8_t getTextDatum(void); void setTextPadding(uint16_t x_width); // Set text padding (background blanking/over-write) width in pixels @@ -666,8 +681,8 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac textWidth(const char *string), // Returns pixel width of string in current font textWidth(const String& string, uint8_t font), // As above for String types textWidth(const String& string), - fontHeight(int16_t font), // Returns pixel height of string in specified font - fontHeight(void); // Returns pixel width of string in current font + fontHeight(uint8_t font), // Returns pixel height of specified font + fontHeight(void); // Returns pixel height of current font // Used by library and Smooth font class to extract Unicode point codes from a UTF8 encoded string uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining), @@ -685,11 +700,12 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Low level read/write void spiwrite(uint8_t); // legacy support only -#ifndef RM68120_DRIVER - void writecommand(uint8_t c); // Send a command, function resets DC/RS high ready for data +#ifdef RM68120_DRIVER + void writecommand(uint16_t c); // Send a 16-bit command, function resets DC/RS high ready for data + void writeRegister8(uint16_t c, uint8_t d); // Write 8-bit data data to 16-bit command register + void writeRegister16(uint16_t c, uint16_t d); // Write 16-bit data data to 16-bit command register #else - void writecommand(uint16_t c); // Send a command, function resets DC/RS high ready for data - void writeRegister(uint16_t c, uint8_t d); // Write data to 16 bit command register + void writecommand(uint8_t c); // Send an 8-bit command, function resets DC/RS high ready for data #endif void writedata(uint8_t d); // Send data with DC/RS set high @@ -701,30 +717,31 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Colour conversion - // Convert 8 bit red, green and blue to 16 bits + // Convert 8-bit red, green and blue to 16 bits uint16_t color565(uint8_t red, uint8_t green, uint8_t blue); - // Convert 8 bit colour to 16 bits + // Convert 8-bit colour to 16 bits uint16_t color8to16(uint8_t color332); - // Convert 16 bit colour to 8 bits + // Convert 16-bit colour to 8 bits uint8_t color16to8(uint16_t color565); - // Convert 16 bit colour to/from 24 bit, R+G+B concatenated into LS 24 bits + // Convert 16-bit colour to/from 24-bit, R+G+B concatenated into LS 24 bits uint32_t color16to24(uint16_t color565); uint32_t color24to16(uint32_t color888); // Alpha blend 2 colours, see generic "alphaBlend_Test" example // alpha = 0 = 100% background colour // alpha = 255 = 100% foreground colour - inline uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); - // 16 bit colour alphaBlend with alpha dither (dither reduces colour banding) + uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); + + // 16-bit colour alphaBlend with alpha dither (dither reduces colour banding) uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither); - // 24 bit colour alphaBlend with optional alpha dither + // 24-bit colour alphaBlend with optional alpha dither uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0); // Direct Memory Access (DMA) support functions // These can be used for SPI writes when using the ESP32 (original) or STM32 processors. - // DMA also works on a RP2040 processor with PIO based SPI and parallel (8 and 16 bit) interfaces + // DMA also works on a RP2040 processor with PIO based SPI and parallel (8 and 16-bit) interfaces // Bear in mind DMA will only be of benefit in particular circumstances and can be tricky // to manage by noobs. The functions have however been designed to be noob friendly and // avoid a few DMA behaviour "gotchas". @@ -803,8 +820,9 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac bool verifySetupID(uint32_t id); // Global variables +#if !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_INTERFACE) static SPIClass& getSPIinstance(void); // Get SPI class handle - +#endif uint32_t textcolor, textbgcolor; // Text foreground and background colours uint32_t bitmap_fg, bitmap_bg; // Bitmap foreground (bit=1) and background (bit=0) colours @@ -921,7 +939,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac bool _booted; // init() or begin() has already run once // User sketch manages these via set/getAttribute() - bool _cp437; // If set, use correct CP437 charset (default is ON) + bool _cp437; // If set, use correct CP437 charset (default is OFF) bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON) bool _psram_enable; // Enable PSRAM use for library functions (TBD) and Sprites @@ -945,7 +963,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac #ifdef TOUCH_CS #if defined (TFT_PARALLEL_8_BIT) || defined (RP2040_PIO_INTERFACE) #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) - #error >>>>------>> Touch functions not supported in 8/16 bit parallel mode or with RP2040 PIO. + #error >>>>------>> Touch functions not supported in 8/16-bit parallel mode or with RP2040 PIO. #endif #else #include "Extensions/Touch.h" // Loaded if TOUCH_CS is defined by user @@ -967,6 +985,20 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac template static inline void transpose(T& a, T& b) { T t = a; a = b; b = t; } +// Fast alphaBlend +template static inline uint16_t +fastBlend(A alpha, F fgc, B bgc) +{ + // Split out and blend 5-bit red and blue channels + uint32_t rxb = bgc & 0xF81F; + rxb += ((fgc & 0xF81F) - rxb) * (alpha >> 2) >> 6; + // Split out and blend 6-bit green channel + uint32_t xgx = bgc & 0x07E0; + xgx += ((fgc & 0x07E0) - xgx) * alpha >> 8; + // Recombine channels + return (rxb & 0xF81F) | (xgx & 0x07E0); +} + /*************************************************************************************** ** Section 10: Additional extension classes ***************************************************************************************/ diff --git a/trunk/Arduino/libraries/TFT_eSPI/Tools/Create_Smooth_Font/Create_font/Create_font.pde b/trunk/Arduino/libraries/TFT_eSPI/Tools/Create_Smooth_Font/Create_font/Create_font.pde index c8e55609..1a07c5cb 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Tools/Create_Smooth_Font/Create_font/Create_font.pde +++ b/trunk/Arduino/libraries/TFT_eSPI/Tools/Create_Smooth_Font/Create_font/Create_font.pde @@ -48,13 +48,13 @@ Software License Agreement (FreeBSD License) // >>>>>>>>>>>>>>>>>>>> INSTRUCTIONS <<<<<<<<<<<<<<<<<<<< // See comments below in code for specifying the font parameters (point size, -// unicode blocks to include etc). Ranges of characters (glyphs) and specific +// unicode blocks to include etc.). Ranges of characters (glyphs) and specific // individual glyphs can be included in the created "*.vlw" font file. // Created fonts are saved in the sketches "FontFiles" folder. Press Ctrl+K to // see that folder location. -// 16 bit Unicode point codes in the range 0x0000 - 0xFFFF are supported. +// 16-bit Unicode point codes in the range 0x0000 - 0xFFFF are supported. // Codes 0-31 are control codes such as "tab" and "carraige return" etc. // and 32 is a "space", these should NOT be included. @@ -134,11 +134,17 @@ String fontType = ".ttf"; // Define the font size in points for the TFT_eSPI font file -int fontSize = 20; +int fontSize = 28; // Font size to use in the Processing sketch display window that pops up (can be different to above) int displayFontSize = 28; +// Create a C header (.h file) ready to be used or copied in your sketch folder +boolean createHeaderFile = true; + +// Automaticely open the folder with created files when done +boolean openFolder = true; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Next we specify which unicode blocks from the the Basic Multilingual Plane (BMP) are included in the final font file. // // Note: The ttf/otf font file MAY NOT contain all possible Unicode characters, refer to the fonts online documentation. // @@ -363,7 +369,7 @@ static final int[] specificUnicodes = { //////////////////////////////////////////////////////////////////////////////////////////////// -// Variable to hold the inclusive Unicode range (16 bit values only for this sketch) +// Variable to hold the inclusive Unicode range (16-bit values only for this sketch) int firstUnicode = 0; int lastUnicode = 0; @@ -392,7 +398,7 @@ void setup() { // Set the fontName from the array number or the defined fontName if (fontNumber >= 0) { - fontName = fontList[fontNumber]; +// fontName = fontList[fontNumber]; fontType = ""; } @@ -499,11 +505,13 @@ void setup() { println("Created font " + fontName + str(fontSize) + ".vlw"); + String fontFileName = "FontFiles/" + fontName + str(fontSize) + ".vlw"; + // creating file try { print("Saving to sketch FontFiles folder... "); - OutputStream output = createOutput("FontFiles/" + fontName + str(fontSize) + ".vlw"); + OutputStream output = createOutput(fontFileName); font.save(output); output.close(); @@ -513,11 +521,50 @@ void setup() { // Open up the FontFiles folder to access the saved file String path = sketchPath(); - Desktop.getDesktop().open(new File(path+"/FontFiles")); + if(openFolder){ + Desktop.getDesktop().open(new File(path+"/FontFiles")); + } System.err.println("All done! Note: Rectangles are displayed for non-existant characters."); } catch(IOException e) { println("Doh! Failed to create the file"); } + + if(!createHeaderFile) return; + // Now creating header file if the option was specified. + try{ + print("saving header file to FontFile folder..."); + + InputStream input = createInputRaw(fontFileName); + PrintWriter output = createWriter("FontFiles/" + fontName + str(fontSize) + ".h"); + + output.println("#include "); + output.println(); + output.println("const uint8_t " + fontName + str(fontSize) + "[] PROGMEM = {"); + + int i = 0; + int data = input.read(); + while(data != -1){ + output.print("0x"); + output.print(hex(data, 2)); + if(i++ < 15){ + output.print(", "); + } else { + output.println(","); + i = 0; + } + data = input.read(); + } +// font.save(output); + output.println("\n};"); + + output.close(); + input.close(); + + println("C header file created."); + + } catch(IOException e){ + println("Failed to create C header file"); + } } diff --git a/trunk/Arduino/libraries/TFT_eSPI/Tools/Screenshot_client/Screenshot_client.pde b/trunk/Arduino/libraries/TFT_eSPI/Tools/Screenshot_client/Screenshot_client.pde index 537b108c..03c9eefd 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/Tools/Screenshot_client/Screenshot_client.pde +++ b/trunk/Arduino/libraries/TFT_eSPI/Tools/Screenshot_client/Screenshot_client.pde @@ -55,7 +55,7 @@ int max_allowed = 1000; // Maximum number of save images allowed before a resta // These are default values, this sketch obtains the actual values from the Arduino board int tft_width = 480; // default TFT width (automatic - sent by Arduino) int tft_height = 480; // default TFT height (automatic - sent by Arduino) -int color_bytes = 2; // 2 for 16 bit, 3 for three RGB bytes (automatic - sent by Arduino) +int color_bytes = 2; // 2 for 16-bit, 3 for three RGB bytes (automatic - sent by Arduino) import processing.serial.*; diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setup.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setup.h index d1c85aa2..a0123318 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setup.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setup.h @@ -1,5 +1,5 @@ // USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc +// Set driver type, fonts to be loaded, pins used and SPI control method etc. // // See the User_Setup_Select.h file if you wish to be able to define multiple // setups and then easily select which setup file is used by the compiler. @@ -28,15 +28,15 @@ //#define NUCLEO_64_TFT //#define NUCLEO_144_TFT -// STM32 8 bit parallel only: -// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7 +// STM32 8-bit parallel only: +// If STN32 Port A or B pins 0-7 are used for 8-bit parallel data bus bits 0-7 // then this will improve rendering performance by a factor of ~8x //#define STM_PORTA_DATA_BUS //#define STM_PORTB_DATA_BUS // Tell the library to use parallel mode (otherwise SPI is assumed) //#define TFT_PARALLEL_8_BIT -//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor **** +//#defined TFT_PARALLEL_16_BIT // **** 16-bit parallel ONLY for RP2040 processor **** // Display type - only define if RPi display //#define RPI_DISPLAY_TYPE // 20MHz maximum SPI @@ -84,6 +84,7 @@ // #define TFT_WIDTH 80 // #define TFT_WIDTH 128 // #define TFT_WIDTH 172 // ST7789 172 x 320 +// #define TFT_WIDTH 170 // ST7789 170 x 320 // #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 // #define TFT_HEIGHT 160 // #define TFT_HEIGHT 128 @@ -104,7 +105,7 @@ // #define ST7735_GREENTAB3 // #define ST7735_GREENTAB128 // For 128 x 128 display // #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) -// #define ST7735_ROBOTLCD // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT) +// #define ST7735_ROBOTLCD // For some RobotLCD Arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT) // #define ST7735_REDTAB // #define ST7735_BLACKTAB // #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset @@ -166,10 +167,15 @@ // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -#define TFT_CS PIN_D8 // Chip select control pin D8 -#define TFT_DC PIN_D3 // Data Command control pin -#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +#define TFT_MISO PIN_D6 // Automatically assigned with ESP8266 if not defined +#define TFT_MOSI PIN_D7 // Automatically assigned with ESP8266 if not defined +#define TFT_SCLK PIN_D5 // Automatically assigned with ESP8266 if not defined + +#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + //#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) @@ -236,7 +242,7 @@ // ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### -// The library supports 8 bit parallel TFTs with the ESP32, the pin +// The library supports 8-bit parallel TFTs with the ESP32, the pin // selection below is compatible with ESP32 boards in UNO format. // Wemos D32 boards need to be modified, see diagram in Tools folder. // Only ILI9481 and ILI9341 based displays have been tested! @@ -244,7 +250,7 @@ // Parallel bus is only supported for the STM32 and ESP32 // Example below is for ESP32 Parallel interface with UNO displays -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed) //#define TFT_PARALLEL_8_BIT // The ESP32 and TFT the pins used for testing are: @@ -324,11 +330,11 @@ // For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface. //#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface -// For RP2040 processor and 8 or 16 bit parallel displays: +// For RP2040 processor and 8 or 16-bit parallel displays: // The parallel interface write cycle period is derived from a division of the CPU clock // speed so scales with the processor clock. This means that the divider ratio may need -// to be increased when overclocking. I may also need to be adjusted dependant on the -// display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined +// to be increased when overclocking. It may also need to be adjusted dependant on the +// display controller type (ILI94341, HX8357C etc.). If RP2040_PIO_CLK_DIV is not defined // the library will set default values which may not suit your display. // The display controller data sheet will specify the minimum write cycle period. The // controllers often work reliably for shorter periods, however if the period is too short diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setup_Select.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setup_Select.h index 8477297a..6a516399 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setup_Select.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setup_Select.h @@ -12,11 +12,8 @@ // Create a shortcut to this file on your desktop to permit quick access for editing. // Re-compile and upload after making and saving any changes to this file. -// Customised User_Setup files are stored in the "User_Setups" folder. - -// It is also possible for the user tft settings to be included with the sketch, see -// the "Sketch_with_tft_setup" generic example. This may be more convenient for -// multiple projects. +// Example User_Setup files are stored in the "User_Setups" folder. These can be used +// unmodified or adapted for a particular hardware configuration. #ifndef USER_SETUP_LOADED // Lets PlatformIO users define settings in // platformio.ini, see notes in "Tools" folder. @@ -89,9 +86,11 @@ //#include // Setup file for LilyGo LilyPi with ILI9481 display //#include // Setup file for LilyGo LilyPi with ST7796 display -//#include // Setup file for RP2040 with SPI ILI9341 -//#include // Setup file for RP2040 with PIO SPI ILI9341 -//#include // Setup file for RP2040 with SPI ILI9341 +//#include // Setup file for RP2040 with SPI ILI9341 +//#include // Setup file for RP2040 with PIO SPI ILI9341 +//#include // Setup file for RP2040 with SPI ILI9341 + +//#include // Setup file for Seeed XIAO with GC9A01 240x240 //#include // Setup file for ESP32 S2 with SPI ILI9341 //#include // Setup file for ESP32 S3 with SPI ILI9341 @@ -101,21 +100,24 @@ //#include // Setup file for ESP32 S2 with ST7789 //#include // Setup file for ESP32 with ST7789 1.47" 172x320 -//#include // Setup file for Pico/RP2040 with 8 bit parallel ILI9488 -//#include // Setup file for Pico/RP2040 with 8 bit parallel ILI9481 -//#include // Setup file for Pico/RP2040 with 8 bit parallel ILI9341 -//#include // Setup file for Pico/RP2040 with 8 bit parallel ILI9486 -//#include // Setup file for Pico/RP2040 with 8 bit parallel ST7796 +//#include // Setup file for Pico/RP2040 with 8-bit parallel ILI9488 +//#include // Setup file for Pico/RP2040 with 8-bit parallel ILI9481 +//#include // Setup file for Pico/RP2040 with 8-bit parallel ILI9341 +//#include // Setup file for Pico/RP2040 with 8-bit parallel ILI9486 +//#include // Setup file for Pico/RP2040 with 8-bit parallel ST7796 -//#include // Setup file for RP2040 16 bit parallel display -//#include // Setup file for RP2040 16 bit parallel display -//#include // Setup file for RP2040 16 bit parallel display +//#include // Setup file for RP2040 16-bit parallel display +//#include // Setup file for RP2040 16-bit parallel display +//#include // Setup file for RP2040 16-bit parallel display +//#include // Setup file for Waveshare RP2040 board with onboard ST7735 0.96" 160x80 display //#include // Setup file for ESP8266 and ST7789 135 x 240 TFT //#include // Setup file for ESP32 and Lilygo TTV ST7789 SPI bus TFT 135x240 //#include // Setup file for Lilygo T-Display RP2040 (ST7789 on SPI bus with 135x240 TFT) +//#include // Setup file for Pico Explorer Base by Pimoroni for RP2040 (ST7789 on SPI bus with 240x240 TFT) + //#include // Setup file for ESP32 and GC9A01 240 x 240 TFT //#include // Setup file for ESP32 based WT32_SC01 from Seeed @@ -128,22 +130,31 @@ //#include // Setup file for the ESP32 TouchDown S3 based on ILI9488 480 x 320 TFT -//#include -//#include +//#include // For the LilyGo T-Display S3 based ESP32S3 with ST7789 170 x 320 TFT +//#include // For the LilyGo T-HMI S3 based ESP32S3 with ST7789 240 x 320 TFT +//#include // For the LilyGo T-Dongle S3 based ESP32 with ST7735 80 x 160 TFT +//#include // For the LilyGo T-Embed S3 based ESP32S3 with ST7789 170 x 320 TFT +//#include // For the LilyGo T-QT Pro S3 based ESP32S3 with GC9A01 128 x 128 TFT +// #include // For the LilyGo T-PICO-Pro with ST7796 222 x 480 TFT +// #include // For the LilyGo T-BEAM V1.x with ST7796 222 x 480 TFT + +//#include // For the ESP32 S3 Box Lite +//#include // For the ESP32 S3 Box //#include // Setup file for Bw16-based boards with ST7735 160 x 80 TFT +//#include // Setup file for Waveshare ESP32-S3-Touch-LCD-1.28 board with GC9A01 240*240 TFT //#include // Template file for a setup -//#include // Setup file for Dustin Watts PCB with ILI9488 +//#include // Setup file for Dustin Watts PCB with ILI9488 //#include // Setup file for Dustin Watts PCB with ST7796 -//#include // Setup file for Dustin Watts Pico PCB with ST7796 -//#include // Setup file for Dustin Watts PCB with ST7789 240 x 240 on 3.3V adapter board -//#include // Setup file for Dustin Watts PCB with GC9A01 240 x 240 on 3.3V adapter board -//#include // Setup file for Dustin Watts PCB with GC9A01 240 x 240 on 3.3V adapter board -//#include // Setup file for Dustin Watts PCB with ST7789 240 x 240 on 3.3V adapter board -//#include // Setup file for Dustin Watts PCB with ILI9341 +//#include // Setup file for Dustin Watts Pico PCB with ST7796 +//#include // Setup file for Dustin Watts PCB with ST7789 240 x 240 on 3.3V adapter board +//#include // Setup file for Dustin Watts PCB with GC9A01 240 x 240 on 3.3V adapter board +//#include // Setup file for Dustin Watts PCB with GC9A01 240 x 240 on 3.3V adapter board +//#include // Setup file for Dustin Watts PCB with ST7789 240 x 240 on 3.3V adapter board +//#include // Setup file for Dustin Watts PCB with ILI9341 //#include #endif // USER_SETUP_LOADED @@ -158,7 +169,7 @@ ///////////////////////////////////////////////////////////////////////////////////// -// Identical looking TFT displays may have a different colour ordering in the 16 bit colour +// Identical looking TFT displays may have a different colour ordering in the 16-bit colour #define TFT_BGR 0 // Colour order Blue-Green-Red #define TFT_RGB 1 // Colour order Red-Green-Blue @@ -180,7 +191,7 @@ #endif #endif -// Invoke 18 bit colour for selected displays +// Invoke 18-bit colour for selected displays #if !defined (RPI_DISPLAY_TYPE) && !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) && !defined (ESP32_PARALLEL) #if defined (ILI9481_DRIVER) || defined (ILI9486_DRIVER) || defined (ILI9488_DRIVER) #define SPI_18BIT_DRIVER diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup13_ILI9481_Parallel.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup13_ILI9481_Parallel.h index cf3e412f..f8881ea2 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup13_ILI9481_Parallel.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup13_ILI9481_Parallel.h @@ -1,7 +1,7 @@ // See SetupX_Template.h for all options available #define USER_SETUP_ID 13 -#define ESP32_PARALLEL +#define TFT_PARALLEL_8_BIT #define ILI9481_DRIVER diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup17_ePaper.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup17_ePaper.h index c86b08a0..5671a151 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup17_ePaper.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup17_ePaper.h @@ -1,34 +1,9 @@ -// See SetupX_Template.h for all options available -#define USER_SETUP_ID 17 - #define EPD_DRIVER // ePaper driver - -// READ THIS READ THIS READ THIS READ THIS READ THIS READ THIS -// Install the ePaper library for your own display size and type -// from here: -// https://github.com/Bodmer/EPD_Libraries - -// Note: Pin allocations for the ePaper signals are defined in -// the ePaper library's epdif.h file. There follows the default -// pins already included in epdif.h file for the ESP8266: - -/////////////////////////////////////////////////////////////////// -// For ESP8266 connect as follows: // -// Display 3.3V to NodeMCU 3V3 // -// Display GND to NodeMCU GND // -// // -// Display GPIO NodeMCU pin // -// BUSY 5 D1 // -// RESET 4 D2 // -// DC 0 D3 // -// CS 2 D4 // -// CLK 14 D5 // -// D6 (MISO not connected to display) // -// DIN 13 D7 // -// // -/////////////////////////////////////////////////////////////////// - +#define TFT_MISO -1 +#define TFT_MOSI -1 +#define TFT_SCLK -1 +#define TFT_RST -1 #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup22_TTGO_T4_v1.3.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup22_TTGO_T4_v1.3.h index 46f1680b..6658d740 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup22_TTGO_T4_v1.3.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup22_TTGO_T4_v1.3.h @@ -1,4 +1,7 @@ // Setup for the TTGO T4 v1.3 ESP32 board with 2.2" ILI9341 display +#define USER_SETUP_ID 99922 + +// See SetupX_Template.h for all options available #define ILI9341_DRIVER @@ -10,7 +13,7 @@ #define TFT_SCLK 18 #define TFT_CS 27 -#define TFT_DC 32 +#define TFT_DC 32 // pin 26 for TTGO T4 v1.3 #define TFT_RST 5 #define LOAD_GLCD diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup26_TTGO_T_Wristband.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup26_TTGO_T_Wristband.h index bd356857..3cda1a5c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup26_TTGO_T_Wristband.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup26_TTGO_T_Wristband.h @@ -1,3 +1,5 @@ +#define USER_SETUP_ID 26 + #define ST7735_DRIVER #define TFT_WIDTH 80 diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup27_RPi_ST7796_ESP32.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup27_RPi_ST7796_ESP32.h index eee4fbc2..ed053a41 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup27_RPi_ST7796_ESP32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup27_RPi_ST7796_ESP32.h @@ -1,5 +1,5 @@ // USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc +// Set driver type, fonts to be loaded, pins used and SPI control method etc. // // See the User_Setup_Select.h file if you wish to be able to define multiple // setups and then easily select which setup file is used by the compiler. @@ -7,6 +7,8 @@ // If this file is edited correctly then all the library example sketches should // run without the need to make any more changes for a particular hardware setup! +#define USER_SETUP_ID 27 + // ################################################################################## // // Section 0. Call up the right driver file and any options for it diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup28_RPi_ST7796_ESP8266.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup28_RPi_ST7796_ESP8266.h index 207baa53..e4ba57c6 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup28_RPi_ST7796_ESP8266.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup28_RPi_ST7796_ESP8266.h @@ -1,11 +1,12 @@ // USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc +// Set driver type, fonts to be loaded, pins used and SPI control method etc. // // See the User_Setup_Select.h file if you wish to be able to define multiple // setups and then easily select which setup file is used by the compiler. // // If this file is edited correctly then all the library example sketches should // run without the need to make any more changes for a particular hardware setup! +#define USER_SETUP_ID 28 // ################################################################################## // diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup29_ILI9341_STM32.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup29_ILI9341_STM32.h index e7ccae4f..61043a94 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup29_ILI9341_STM32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup29_ILI9341_STM32.h @@ -2,6 +2,7 @@ /////////////////////////////////////////////////// // Setup for STM32 Nucleo and ILI9341 display // /////////////////////////////////////////////////// +#define USER_SETUP_ID 29 // Last update by Bodmer: 28/11/19 @@ -23,17 +24,35 @@ // - Arduino SCK to TFT SCK // - Arduino MOSI to TFT SDI(may be marked SDA or MOSI) // Typical Arduino SPI port 1 pins are (SCK=D13, MISO=D12, MOSI=D11) this is port pins PA5, PA6 and PA7 on Nucleo-F767ZI -// SPI port 2 pins are (SCK=D18, MISO=A7, MOSI=D17) this is typically port pins PB13, PB14 and PB15 +// SPI port 2 pins are (SCK=D18, MISO=A7, MOSI=D17) this is port pins PB13, PC2 and PB15 on Nucleo-F767ZI +/* #define TFT_SPI_PORT 1 // SPI 1 maximum clock rate is 55MHz #define TFT_MOSI PA7 #define TFT_MISO PA6 #define TFT_SCLK PA5 +//*/ -//#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz -//#define TFT_MOSI PB15 -//#define TFT_MISO PB14 -//#define TFT_SCLK PB13 +/* +#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz +#define TFT_MOSI D17 +#define TFT_MISO A7 +#define TFT_SCLK D18 +//*/ + +/* +#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz +#define TFT_MOSI PB15 +#define TFT_MISO PC2 +#define TFT_SCLK PB13 +//*/ + +/* +#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz +#define TFT_MOSI PB15 +#define TFT_MISO PB14 +#define TFT_SCLK PB13 +//*/ // Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select #define TFT_CS D5 // Chip select control pin to TFT CS @@ -63,8 +82,8 @@ // STM32 support for smooth fonts via program memory (FLASH) arrays #define SMOOTH_FONT - -// Nucleo-F767ZI has a ~216MHZ CPU clock, this is divided by 4, 8, 16 etc + +// Nucleo-F767ZI has a ~216MHZ CPU clock, this is divided by 4, 8, 16 etc. #define SPI_FREQUENCY 27000000 // 27MHz SPI clock //#define SPI_FREQUENCY 55000000 // 55MHz is over-clocking ILI9341 but seems to work reliably! diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup30_ILI9341_Parallel_STM32.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup30_ILI9341_Parallel_STM32.h index fbf28476..5b1b26df 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup30_ILI9341_Parallel_STM32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup30_ILI9341_Parallel_STM32.h @@ -1,7 +1,9 @@ //////////////////////////////////////////////////// // Setup for Nucleo 64 or 144 and ILI9341 display // //////////////////////////////////////////////////// - + +#define USER_SETUP_ID 30 + // See SetupX_Template.h for all options available // Define STM32 to invoke optimised processor support @@ -12,7 +14,7 @@ #define NUCLEO_64_TFT //#define NUCLEO_144_TFT -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed) #define TFT_PARALLEL_8_BIT // Define the display driver chip type @@ -29,7 +31,7 @@ #define TFT_WR A1 // Write strobe control pin #define TFT_RD A0 // Read pin -#define TFT_D0 D8 // 8 bit parallel bus to TFT +#define TFT_D0 D8 // 8-bit parallel bus to TFT #define TFT_D1 D9 #define TFT_D2 D2 #define TFT_D3 D3 diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup31_ST7796_Parallel_STM32.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup31_ST7796_Parallel_STM32.h index 25675d4c..0e26eaa3 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup31_ST7796_Parallel_STM32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup31_ST7796_Parallel_STM32.h @@ -1,7 +1,7 @@ //////////////////////////////////////////////////// // Setup for Nucleo 64 or 144 and ILI9341 display // //////////////////////////////////////////////////// - +#define USER_SETUP_ID 31 // See SetupX_Template.h for all options available @@ -13,7 +13,7 @@ #define NUCLEO_64_TFT //#define NUCLEO_144_TFT -// Tell the library to use 8 bit parallel mode(otherwise SPI is assumed) +// Tell the library to use 8-bit parallel mode(otherwise SPI is assumed) #define TFT_PARALLEL_8_BIT // Define the display driver chip type @@ -30,7 +30,7 @@ #define TFT_WR A1 // Write strobe control pin #define TFT_RD A0 // Read pin -#define TFT_D0 D8 // 8 bit parallel bus to TFT +#define TFT_D0 D8 // 8-bit parallel bus to TFT #define TFT_D1 D9 #define TFT_D2 D2 #define TFT_D3 D3 diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup32_ILI9341_STM32F103.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup32_ILI9341_STM32F103.h index 0be32f77..38a662ad 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup32_ILI9341_STM32F103.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup32_ILI9341_STM32F103.h @@ -1,6 +1,7 @@ ////////////////////////////////////////////////////////////// // Setup for STM32F103 (e.g. Blue Pill) and ILI9341 display // ////////////////////////////////////////////////////////////// +#define USER_SETUP_ID 32 // Last update by Bodmer: 14/1/20 diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup33_RPi_ILI9486_STM32.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup33_RPi_ILI9486_STM32.h index f7a70381..5a1a8c8b 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup33_RPi_ILI9486_STM32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup33_RPi_ILI9486_STM32.h @@ -1,7 +1,7 @@ - /////////////////////////////////////////////////// // Setup for STM32 Nucleo and ILI9341 display // /////////////////////////////////////////////////// +#define USER_SETUP_ID 33 // Last update by Bodmer: 28/11/19 @@ -54,7 +54,7 @@ #define SMOOTH_FONT -// Nucleo-F767ZI has a ~216MHZ CPU clock, this is divided by 4, 8, 16 etc +// Nucleo-F767ZI has a ~216MHZ CPU clock, this is divided by 4, 8, 16 etc. #define SPI_FREQUENCY 20000000 // 27MHz SPI clock //#define SPI_FREQUENCY 55000000 // 55MHz is over-clocking ILI9341 but seems to work reliably! diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup34_ILI9481_Parallel_STM32.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup34_ILI9481_Parallel_STM32.h index 74e4e199..467a001c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup34_ILI9481_Parallel_STM32.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup34_ILI9481_Parallel_STM32.h @@ -1,7 +1,7 @@ //////////////////////////////////////////////////// // Setup for Nucleo 64 or 144 and ILI9341 display // //////////////////////////////////////////////////// - +#define USER_SETUP_ID 34 // See SetupX_Template.h for all options available // Define STM32 to invoke optimised processor support @@ -12,7 +12,7 @@ #define NUCLEO_64_TFT //#define NUCLEO_144_TFT -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed) #define TFT_PARALLEL_8_BIT // Define the display driver chip type @@ -29,7 +29,7 @@ #define TFT_WR A1 // Write strobe control pin #define TFT_RD A0 // Read pin -#define TFT_D0 D8 // 8 bit parallel bus to TFT +#define TFT_D0 D8 // 8-bit parallel bus to TFT #define TFT_D1 D9 #define TFT_D2 D2 #define TFT_D3 D3 diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup35_ILI9341_STM32_Port_Bus.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup35_ILI9341_STM32_Port_Bus.h index ded0dc6a..894948cb 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup35_ILI9341_STM32_Port_Bus.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup35_ILI9341_STM32_Port_Bus.h @@ -1,18 +1,20 @@ ////////////////////////////////////////////////////////////// // Setup for STM32 and ILI9341 display // ////////////////////////////////////////////////////////////// - +#define USER_SETUP_ID 35 // Last update by Bodmer: 28/3/20 // Define STM32 to invoke STM32 optimised driver #define STM32 -// Define if Port A (or B) pins 0-7 are used for data bus bits 0-7 +// Define if Port A (B, C or D) pins 0-7 are used for data bus bits 0-7 // this will improve rendering performance by a factor of ~8x #define STM_PORTA_DATA_BUS //#define STM_PORTB_DATA_BUS // Pins below must re re-allocated to use this option +//#define STM_PORTC_DATA_BUS // Pins below must re re-allocated to use this option +//#define STM_PORTD_DATA_BUS // Pins below must re re-allocated to use this option -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed) #define TFT_PARALLEL_8_BIT // Define ONE of the the TFT display drivers @@ -28,7 +30,7 @@ #define TFT_WR PB9 // Write strobe control pin #define TFT_RD PB1 // Read pin -#define TFT_D0 PA0 // 8 bit Port A parallel bus to TFT +#define TFT_D0 PA0 // 8-bit Port A parallel bus to TFT #define TFT_D1 PA1 #define TFT_D2 PA2 #define TFT_D3 PA3 diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup44_TTGO_CameraPlus.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup44_TTGO_CameraPlus.h index e45dc7da..07869187 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup44_TTGO_CameraPlus.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup44_TTGO_CameraPlus.h @@ -1,3 +1,4 @@ +#define USER_SETUP_ID 44 #define ST7789_DRIVER @@ -10,6 +11,7 @@ #define TFT_CS 12 #define TFT_DC 15 #define TFT_RST -1 +#define TFT_BL 2 #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup45_TTGO_T_Watch.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup45_TTGO_T_Watch.h index f4c243e5..9a901055 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup45_TTGO_T_Watch.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/Setup45_TTGO_T_Watch.h @@ -1,3 +1,5 @@ +#define USER_SETUP_ID 45 + #define ST7789_DRIVER #define TFT_WIDTH 240 diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/SetupX_Template.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/SetupX_Template.h index 4a42c840..00bf9a5d 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/SetupX_Template.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/SetupX_Template.h @@ -1,5 +1,5 @@ // USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc +// Set driver type, fonts to be loaded, pins used and SPI control method etc. // // See the User_Setup_Select.h file if you wish to be able to define multiple // setups and then easily select which setup file is used by the compiler. @@ -27,15 +27,15 @@ //#define NUCLEO_64_TFT //#define NUCLEO_144_TFT -// STM32 8 bit parallel only: -// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7 +// STM32 8-bit parallel only: +// If STN32 Port A or B pins 0-7 are used for 8-bit parallel data bus bits 0-7 // then this will improve rendering performance by a factor of ~8x //#define STM_PORTA_DATA_BUS //#define STM_PORTB_DATA_BUS -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed) //#define TFT_PARALLEL_8_BIT -//#define TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY with RP2040 processor **** +//#define TFT_PARALLEL_16_BIT // **** 16-bit parallel ONLY with RP2040 processor **** // Display type - only define if RPi display //#define RPI_DISPLAY_TYPE // 20MHz maximum SPI @@ -236,7 +236,7 @@ // ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### -// The library supports 8 bit parallel TFTs with the ESP32, the pin +// The library supports 8-bit parallel TFTs with the ESP32, the pin // selection below is compatible with ESP32 boards in UNO format. // Wemos D32 boards need to be modified, see diagram in Tools folder. // Only ILI9481 and ILI9341 based displays have been tested! @@ -244,7 +244,7 @@ // Parallel bus is only supported for the STM32 and ESP32 // Example below is for ESP32 Parallel interface with UNO displays -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed) //#define TFT_PARALLEL_8_BIT // The ESP32 and TFT the pins used for testing are: diff --git a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/User_Custom_Fonts.h b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/User_Custom_Fonts.h index f2dc3d35..004ac54e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/User_Setups/User_Custom_Fonts.h +++ b/trunk/Arduino/libraries/TFT_eSPI/User_Setups/User_Custom_Fonts.h @@ -6,7 +6,7 @@ */ // Note: At the time of writing there is a last character code definition bug in the -// Squix font file format so do NOT try and print the tilda (~) symbol (ASCII 0x7E) +// Squix font file format so do NOT try and print the tilde (~) symbol (ASCII 0x7E) // Alternatively look at the end of the font header file and edit: 0x7E to read 0x7D /* e.g. vvvv (uint8_t *)Orbitron_Light_32Bitmaps,(GFXglyph *)Orbitron_Light_32Glyphs,0x20, 0x7D, 32}; @@ -16,7 +16,7 @@ // When font files are placed in the Custom folder (TFT_eSPI\Fonts\Custom) then they must // also be #included here: -// The CF_OL24 etc are a shorthand reference, but this is not essential to use the fonts +// The CF_OL24 etc. are a shorthand reference, but this is not essential to use the fonts #ifdef LOAD_GFXFF diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Ellipse/TFT_Ellipse.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Ellipse/TFT_Ellipse.ino index 1e8b86c3..f28bab94 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Ellipse/TFT_Ellipse.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Ellipse/TFT_Ellipse.ino @@ -20,7 +20,7 @@ void loop() { tft.fillScreen(TFT_BLACK); - // Draw some random filled elipses + // Draw some random filled ellipses for (int i = 0; i < 20; i++) { int rx = random(40); @@ -33,7 +33,7 @@ void loop() { delay(2000); tft.fillScreen(TFT_BLACK); - // Draw some random outline elipses + // Draw some random outline ellipses for (int i = 0; i < 20; i++) { int rx = random(40); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Meter_5/TFT_Meter_5.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Meter_5/TFT_Meter_5.ino index 1f9c8eb3..0d4541ae 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Meter_5/TFT_Meter_5.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Meter_5/TFT_Meter_5.ino @@ -73,7 +73,7 @@ void analogMeter() // Long scale tick length int tl = 15; - // Coodinates of tick to draw + // Coordinates of tick to draw float sx = cos((i - 90) * 0.0174532925); float sy = sin((i - 90) * 0.0174532925); uint16_t x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120; diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Print_Test/TFT_Print_Test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Print_Test/TFT_Print_Test.ino index 8563c0d3..f6974587 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Print_Test/TFT_Print_Test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Print_Test/TFT_Print_Test.ino @@ -1,5 +1,5 @@ /* - Test the tft.print() viz embedded tft.write() function + Test the tft.print() viz. embedded tft.write() function This sketch used font 2, 4, 7 diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Rainbow/TFT_Rainbow.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Rainbow/TFT_Rainbow.ino index ce2bb161..3ac49770 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Rainbow/TFT_Rainbow.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_Rainbow/TFT_Rainbow.ino @@ -96,7 +96,7 @@ void loop() { // The new larger fonts do not use the .setCursor call, coords are embedded tft.setTextColor(TFT_BLACK, TFT_BLACK); // Do not plot the background colour - // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) + // Overlay the black text on top of the rainbow plot (the advantage of not drawing the background colour!) tft.drawCentreString("Font size 2", 80, 14, 2); // Draw text centre at position 80, 12 using font 2 //tft.drawCentreString("Font size 2",81,12,2); // Draw text centre at position 80, 12 using font 2 diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino index 7179945d..d4482d61 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino @@ -1,7 +1,7 @@ // Sketch to display images on a 160 x 128 TFT // Renders images stored in an array in program (FLASH) -// The JPEG images are stored in header files (see jpeg1.h etc) +// The JPEG images are stored in header files (see jpeg1.h etc.) // As well as the TFT_eSPI library: // https://github.com/Bodmer/TFT_eSPI @@ -95,7 +95,7 @@ void drawArrayJpeg(const uint8_t arrayname[], uint32_t array_size, int xpos, int // fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders. void renderJPEG(int xpos, int ypos) { - // retrieve infomration about the image + // retrieve information about the image uint16_t *pImg; uint16_t mcu_w = JpegDec.MCUWidth; uint16_t mcu_h = JpegDec.MCUHeight; @@ -193,7 +193,7 @@ void jpegInfo() { // Show the execution time (optional) //#################################################################################################### // WARNING: for UNO/AVR legacy reasons printing text to the screen with the Mega might not work for -// sketch sizes greater than ~70KBytes because 16 bit address pointers are used in some libraries. +// sketch sizes greater than ~70KBytes because 16-bit address pointers are used in some libraries. // The Due will work fine with the HX8357_Due library. diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/All_Free_Fonts_Demo/All_Free_Fonts_Demo.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/All_Free_Fonts_Demo/All_Free_Fonts_Demo.ino index dbbd6d45..7bb38589 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/All_Free_Fonts_Demo/All_Free_Fonts_Demo.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/All_Free_Fonts_Demo/All_Free_Fonts_Demo.ino @@ -376,7 +376,7 @@ void loop() { } // There follows a crude way of flagging that this example sketch needs fonts which -// have not been enbabled in the User_Setup.h file inside the TFT_HX8357 library. +// have not been enabled in the User_Setup.h file inside the TFT_HX8357 library. // // These lines produce errors during compile time if settings in User_Setup are not correct // diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Free_Font_Demo/Free_Font_Demo.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Free_Font_Demo/Free_Font_Demo.ino index 2a4c63af..c0c3c083 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Free_Font_Demo/Free_Font_Demo.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Free_Font_Demo/Free_Font_Demo.ino @@ -280,7 +280,7 @@ void drawDatumMarker(int x, int y) // There follows a crude way of flagging that this example sketch needs fonts which -// have not been enbabled in the User_Setup.h file inside the TFT_HX8357 library. +// have not been enabled in the User_Setup.h file inside the TFT_HX8357 library. // // These lines produce errors during compile time if settings in User_Setup are not correct // diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Keypad_240x320/Keypad_240x320.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Keypad_240x320/Keypad_240x320.ino index e38e6f4a..0866844c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Keypad_240x320/Keypad_240x320.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Keypad_240x320/Keypad_240x320.ino @@ -3,8 +3,8 @@ button handling class, this sketch is based on the Arduin-o-phone example. - This example diplays a keypad where numbers can be entered and - send to the Serial Monitor window. + This example displays a keypad where numbers can be entered and + sent to the Serial Monitor window. The sketch has been tested on the ESP8266 (which supports SPIFFS) @@ -164,7 +164,7 @@ void loop(void) { // Update the number display field tft.setTextDatum(TL_DATUM); // Use top left corner as text coord datum - tft.setFreeFont(&FreeSans18pt7b); // Choose a nicefont that fits box + tft.setFreeFont(&FreeSans18pt7b); // Choose a nice font that fits box tft.setTextColor(DISP_TCOLOR); // Set the font colour // Draw the string, the value returned is the width in pixels @@ -209,7 +209,7 @@ void touch_calibrate() // check file system exists if (!SPIFFS.begin()) { - Serial.println("Formating file system"); + Serial.println("formatting file system"); SPIFFS.format(); SPIFFS.begin(); } diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino index 599d3546..51f4ea2f 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino @@ -11,7 +11,7 @@ // Change the pin settings to suit your hardware -// UNO etc +// UNO etc. //#define TFT_MOSI 11 //#define TFT_SCK 13 //#define TFT_CS 9 @@ -116,7 +116,7 @@ void setup() { uint32_t ID = 0; Serial.begin(115200); - delay(4000); // Delay to allow USB to connect to a Leonardo etc + delay(4000); // Delay to allow USB to connect to a Leonardo etc. Serial.println("TFT driver register values:"); Serial.println("==========================="); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_ArcFill/TFT_ArcFill.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_ArcFill/TFT_ArcFill.ino index 4ad06caf..cfeeab02 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_ArcFill/TFT_ArcFill.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_ArcFill/TFT_ArcFill.ino @@ -11,7 +11,7 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library byte inc = 0; unsigned int col = 0; -byte red = 31; // Red is the top 5 bits of a 16 bit colour value +byte red = 31; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits byte state = 0; @@ -56,7 +56,7 @@ void loop() { // rx = x axis outer radius // ry = y axis outer radius // w = width (thickness) of arc in pixels -// colour = 16 bit colour value +// colour = 16-bit colour value // Note if rx and ry are the same then an arc of a circle is drawn void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour) @@ -87,7 +87,7 @@ void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w tft.fillTriangle(x0, y0, x1, y1, x2, y2, colour); tft.fillTriangle(x1, y1, x2, y2, x3, y3, colour); - // Copy segment end to sgement start for next segment + // Copy segment end to segment start for next segment x0 = x2; y0 = y2; x1 = x3; @@ -96,7 +96,7 @@ void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w } // ######################################################################### -// Return the 16 bit colour with brightness 0-100% +// Return the 16-bit colour with brightness 0-100% // ######################################################################### unsigned int brightness(unsigned int colour, int brightness) { @@ -112,7 +112,7 @@ unsigned int brightness(unsigned int colour, int brightness) } // ######################################################################### -// Return a 16 bit rainbow colour +// Return a 16-bit rainbow colour // ######################################################################### unsigned int rainbow(byte value) { diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Custom_Fonts/TFT_Custom_Fonts.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Custom_Fonts/TFT_Custom_Fonts.ino index 6485e755..b6051234 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Custom_Fonts/TFT_Custom_Fonts.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Custom_Fonts/TFT_Custom_Fonts.ino @@ -19,7 +19,7 @@ ######################################################################### */ -// Note the the tilda symbol ~ does not exist in some fonts at the moment +// Note the the tilde symbol ~ does not exist in some fonts at the moment #define TEXT "abc MWy 123 |" // Text that will be printed on screen in any font #include "SPI.h" diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_FillArcSpiral/TFT_FillArcSpiral.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_FillArcSpiral/TFT_FillArcSpiral.ino index 83b8f609..9ea0d7cb 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_FillArcSpiral/TFT_FillArcSpiral.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_FillArcSpiral/TFT_FillArcSpiral.ino @@ -13,7 +13,7 @@ int segment = 0; unsigned int col = 0; int delta = -1; - byte red = 31; // Red is the top 5 bits of a 16 bit colour value + byte red = 31; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits byte state = 0; @@ -48,7 +48,7 @@ void loop() { // rx = x axis radius // yx = y axis radius // w = width (thickness) of arc in pixels -// colour = 16 bit colour value +// colour = 16-bit colour value // Note if rx and ry are the same an arc of a circle is drawn void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour) @@ -82,7 +82,7 @@ void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w } // ######################################################################### -// Return a 16 bit colour with brightness 0 - 100% +// Return a 16-bit colour with brightness 0 - 100% // ######################################################################### unsigned int brightness(unsigned int colour, int brightness) { @@ -98,7 +98,7 @@ unsigned int brightness(unsigned int colour, int brightness) } // ######################################################################### -// Return a 16 bit rainbow colour +// Return a 16-bit rainbow colour // ######################################################################### unsigned int rainbow(byte value) { diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino index 2a04556b..c4911922 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino @@ -62,7 +62,7 @@ unsigned int rainbow(int value) // Value is expected to be in range 0-127 // The value is converted to a spectrum colour from 0 = blue through to red = blue - byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte red = 0; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meter_linear/TFT_Meter_linear.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meter_linear/TFT_Meter_linear.ino index 9d624855..aa9521da 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meter_linear/TFT_Meter_linear.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meter_linear/TFT_Meter_linear.ino @@ -47,7 +47,7 @@ void setup(void) { void loop() { if (updateTime <= millis()) { - updateTime = millis() + 35; // Update emter every 35 milliseconds + updateTime = millis() + 35; // Update meter every 35 milliseconds // Create a Sine wave for testing d += 4; if (d >= 360) d = 0; @@ -75,7 +75,7 @@ void analogMeter() // Long scale tick length int tl = 15; - // Coodinates of tick to draw + // Coordinates of tick to draw float sx = cos((i - 90) * 0.0174532925); float sy = sin((i - 90) * 0.0174532925); uint16_t x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120; @@ -175,7 +175,7 @@ void plotNeedle(int value, byte ms_delay) if (ms_delay == 0) old_analog = value; // Update immediately if delay is 0 float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle - // Calcualte tip of needle coords + // Calculate tip of needle coords float sx = cos(sdeg * 0.0174532925); float sy = sin(sdeg * 0.0174532925); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meters/TFT_Meters.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meters/TFT_Meters.ino index 419b1f5c..094f476e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meters/TFT_Meters.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Meters/TFT_Meters.ino @@ -95,7 +95,7 @@ void analogMeter() // Long scale tick length int tl = 15; - // Coodinates of tick to draw + // Coordinates of tick to draw float sx = cos((i - 90) * 0.0174532925); float sy = sin((i - 90) * 0.0174532925); uint16_t x0 = sx * (100 + tl) + 120; @@ -195,7 +195,7 @@ void plotNeedle(int value, byte ms_delay) if (ms_delay == 0) old_analog = value; // Update immediately id delay is 0 float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle - // Calcualte tip of needle coords + // Calculate tip of needle coords float sx = cos(sdeg * 0.0174532925); float sy = sin(sdeg * 0.0174532925); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Pie_Chart/TFT_Pie_Chart.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Pie_Chart/TFT_Pie_Chart.ino index b2390494..cd4fdb2c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Pie_Chart/TFT_Pie_Chart.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Pie_Chart/TFT_Pie_Chart.ino @@ -44,7 +44,7 @@ void loop() { // start_angle = 0 - 359 // sub_angle = 0 - 360 = subtended angle // r = radius -// colour = 16 bit colour value +// colour = 16-bit colour value int fillSegment(int x, int y, int start_angle, int sub_angle, int r, unsigned int colour) { @@ -63,7 +63,7 @@ int fillSegment(int x, int y, int start_angle, int sub_angle, int r, unsigned in tft.fillTriangle(x1, y1, x2, y2, x, y, colour); - // Copy segment end to sgement start for next segment + // Copy segment end to segment start for next segment x1 = x2; y1 = y2; } @@ -71,7 +71,7 @@ int fillSegment(int x, int y, int start_angle, int sub_angle, int r, unsigned in // ######################################################################### -// Return the 16 bit colour with brightness 0-100% +// Return the 16-bit colour with brightness 0-100% // ######################################################################### unsigned int brightness(unsigned int colour, int brightness) { diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Print_Test/TFT_Print_Test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Print_Test/TFT_Print_Test.ino index 9caecbb1..03af064d 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Print_Test/TFT_Print_Test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Print_Test/TFT_Print_Test.ino @@ -1,5 +1,5 @@ /* - Test the tft.print() viz embedded tft.write() function + Test the tft.print() viz. embedded tft.write() function This sketch used font 2, 4, 7 diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Rainbow_one_lib/TFT_Rainbow_one_lib.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Rainbow_one_lib/TFT_Rainbow_one_lib.ino index 88180fd3..55cc3656 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Rainbow_one_lib/TFT_Rainbow_one_lib.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Rainbow_one_lib/TFT_Rainbow_one_lib.ino @@ -53,7 +53,7 @@ void loop() { // The new larger fonts do not need to use the .setCursor call, coords are embedded tft.setTextColor(TFT_BLACK); // Do not plot the background colour - // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) + // Overlay the black text on top of the rainbow plot (the advantage of not drawing the background colour!) tft.drawCentreString("Font size 2", 120, 14, 2); // Draw text centre at position 120, 14 using font 2 tft.drawCentreString("Font size 4", 120, 30, 4); // Draw text centre at position 120, 30 using font 4 tft.drawCentreString("12.34", 120, 54, 6); // Draw text centre at position 120, 54 using font 6 @@ -98,7 +98,7 @@ void loop() { // Fill screen with a rainbow pattern void rainbow_fill() { - // The colours and state are not initialised so the start colour changes each time the funtion is called + // The colours and state are not initialised so the start colour changes each time the function is called for (int i = 319; i > 0; i--) { // Draw a vertical line 1 pixel wide in the selected colour diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Read_Reg/TFT_Read_Reg.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Read_Reg/TFT_Read_Reg.ino index d622e44e..4a433d6c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Read_Reg/TFT_Read_Reg.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Read_Reg/TFT_Read_Reg.ino @@ -56,7 +56,7 @@ void loop() { printSubset(); // Print a useful subset of the readable registers - readTest(); // Test 8, 16 and 32 bit reads and index on the ID register + readTest(); // Test 8, 16 and 32-bit reads and index on the ID register //printRange32(0x00, 0xFF); // Print a range of registers (32 bits, index = 0) @@ -70,8 +70,8 @@ void loop() { void readTest(void) { - Serial.println(); Serial.println("Test 8, 16 and 32 bit reads and the index..."); - // Test 8, 16 and 32 bit reads and index + Serial.println(); Serial.println("Test 8, 16 and 32-bit reads and the index..."); + // Test 8, 16 and 32-bit reads and index // Note at index 0 the register values are typically undefined (Bxxxxxxxx) Serial.println(tft.readcommand8(ILI9341_RDID4, 2), HEX); Serial.println(tft.readcommand16(ILI9341_RDID4, 2), HEX); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Spiro/TFT_Spiro.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Spiro/TFT_Spiro.ino index 3e7f8d7d..fddf0af5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Spiro/TFT_Spiro.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Spiro/TFT_Spiro.ino @@ -1,5 +1,5 @@ // Spiro -// Rainbow patern generator +// Rainbow pattern generator #include // Hardware-specific library #include @@ -67,7 +67,7 @@ unsigned int rainbow(int value) // Value is expected to be in range 0-127 // The value is converted to a spectrum colour from 0 = blue through to red = blue //int value = random (128); - byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte red = 0; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Starfield/TFT_Starfield.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Starfield/TFT_Starfield.ino index 1e721979..f8891f2c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Starfield/TFT_Starfield.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Starfield/TFT_Starfield.ino @@ -59,7 +59,7 @@ void loop() int old_screen_x = ((int)sx[i] - 160) * 256 / sz[i] + 160; int old_screen_y = ((int)sy[i] - 120) * 256 / sz[i] + 120; - // This is a faster pixel drawing function for occassions where many single pixels must be drawn + // This is a faster pixel drawing function for occasions where many single pixels must be drawn tft.drawPixel(old_screen_x, old_screen_y,TFT_BLACK); sz[i] -= 2; @@ -82,7 +82,7 @@ void loop() unsigned long t1 = micros(); //static char timeMicros[8] = {}; - // Calcualte frames per second + // Calculate frames per second Serial.println(1.0/((t1 - t0)/1000000.0)); } diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Terminal/TFT_Terminal.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Terminal/TFT_Terminal.ino index 27fb4f16..bd6b69ea 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Terminal/TFT_Terminal.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/320 x 240/TFT_Terminal/TFT_Terminal.ino @@ -7,7 +7,7 @@ Connect GND to target board GND Connect RX line to TX line of target board Make sure the target and terminal have the same baud rate - and serial stettings! + and serial settings! The sketch works with the ILI9341 TFT 240x320 display and the called up libraries. diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Free_Font_Demo/Free_Font_Demo.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Free_Font_Demo/Free_Font_Demo.ino index 50c09c13..569d4844 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Free_Font_Demo/Free_Font_Demo.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Free_Font_Demo/Free_Font_Demo.ino @@ -249,7 +249,7 @@ void drawDatum(int x, int y) // There follows a crude way of flagging that this example sketch needs fonts which -// have not been enbabled in the User_Setup.h file inside the TFT_HX8357 library. +// have not been enabled in the User_Setup.h file inside the TFT_HX8357 library. // // These lines produce errors during compile time if settings in User_Setup are not correct // diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Keypad_480x320/Keypad_480x320.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Keypad_480x320/Keypad_480x320.ino index 9614d6a7..b2844aaa 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Keypad_480x320/Keypad_480x320.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Keypad_480x320/Keypad_480x320.ino @@ -3,8 +3,8 @@ button handling class, this sketch is based on the Arduin-o-phone example. - This example diplays a keypad where numbers can be entered and - send to the Serial Monitor window. + This example displays a keypad where numbers can be entered and + sent to the Serial Monitor window. The sketch has been tested on the ESP8266 (which supports SPIFFS) @@ -167,7 +167,7 @@ void loop(void) { // Update the number display field tft.setTextDatum(TL_DATUM); // Use top left corner as text coord datum - tft.setFreeFont(&FreeSans18pt7b); // Choose a nicefont that fits box + tft.setFreeFont(&FreeSans18pt7b); // Choose a nice font that fits box tft.setTextColor(DISP_TCOLOR); // Set the font colour // Draw the string, the value returned is the width in pixels @@ -212,7 +212,7 @@ void touch_calibrate() // check file system exists if (!SPIFFS.begin()) { - Serial.println("Formating file system"); + Serial.println("formatting file system"); SPIFFS.format(); SPIFFS.begin(); } diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meter_4/TFT_Meter_4.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meter_4/TFT_Meter_4.ino index 11d00d21..77a82cb5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meter_4/TFT_Meter_4.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meter_4/TFT_Meter_4.ino @@ -49,7 +49,7 @@ void setup(void) { void loop() { if (updateTime <= millis()) { - updateTime = millis() + 35; // Update emter every 35 milliseconds + updateTime = millis() + 35; // Update meter every 35 milliseconds // Create a Sine wave for testing d += 4; if (d >= 360) d = 0; @@ -77,7 +77,7 @@ void analogMeter() // Long scale tick length int tl = 15; - // Coodinates of tick to draw + // Coordinates of tick to draw float sx = cos((i - 90) * 0.0174532925); float sy = sin((i - 90) * 0.0174532925); uint16_t x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120; @@ -177,7 +177,7 @@ void plotNeedle(int value, byte ms_delay) if (ms_delay == 0) old_analog = value; // Update immediately if delay is 0 float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle - // Calcualte tip of needle coords + // Calculate tip of needle coords float sx = cos(sdeg * 0.0174532925); float sy = sin(sdeg * 0.0174532925); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meters/TFT_Meters.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meters/TFT_Meters.ino index 339fc329..007e9548 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meters/TFT_Meters.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meters/TFT_Meters.ino @@ -97,7 +97,7 @@ void analogMeter() // Long scale tick length int tl = 15; - // Coodinates of tick to draw + // Coordinates of tick to draw float sx = cos((i - 90) * 0.0174532925); float sy = sin((i - 90) * 0.0174532925); uint16_t x0 = sx * (100 + tl) + 120; @@ -197,7 +197,7 @@ void plotNeedle(int value, byte ms_delay) if (ms_delay == 0) old_analog = value; // Update immediately id delay is 0 float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle - // Calcualte tip of needle coords + // Calculate tip of needle coords float sx = cos(sdeg * 0.0174532925); float sy = sin(sdeg * 0.0174532925); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Print_Test/TFT_Print_Test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Print_Test/TFT_Print_Test.ino index 14f75b32..f1ee3f99 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Print_Test/TFT_Print_Test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Print_Test/TFT_Print_Test.ino @@ -1,5 +1,5 @@ /* - Test the tft.print() viz the libraries embedded write() function + Test the tft.print() viz. the libraries embedded write() function This sketch used font 2, 4, 7 diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Rainbow480/TFT_Rainbow480.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Rainbow480/TFT_Rainbow480.ino index a2e1aa1c..e1d5f4c3 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Rainbow480/TFT_Rainbow480.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Rainbow480/TFT_Rainbow480.ino @@ -50,7 +50,7 @@ void loop() { // The new larger fonts do not need to use the .setCursor call, coords are embedded tft.setTextColor(TFT_BLACK); // Do not plot the background colour - // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) + // Overlay the black text on top of the rainbow plot (the advantage of not drawing the background colour!) tft.drawCentreString("Font size 2", 160, 14, 2); // Draw text centre at position 120, 14 using font 2 tft.drawCentreString("Font size 4", 160, 30, 4); // Draw text centre at position 120, 30 using font 4 tft.drawCentreString("12.34", 160, 54, 6); // Draw text centre at position 120, 54 using font 6 @@ -100,7 +100,7 @@ void loop() { // Fill screen with a rainbow pattern void rainbow_fill() { - // The colours and state are not initialised so the start colour changes each time the funtion is called + // The colours and state are not initialised so the start colour changes each time the function is called for (int i = 479; i > 0; i--) { // Draw a vertical line 1 pixel wide in the selected colour diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino index f8ebcb14..c00611b4 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino @@ -1,8 +1,8 @@ // Sketch to display images on a 480 x 320 ILI9486 Raspberry Pi 3.5" TFT (Waveshare design) -// which has a 16 bit serial interface based on 74HC04, 74HC4040 and 2 x 74HC4094 logic chips +// which has a 16-bit serial interface based on 74HC04, 74HC4040 and 2 x 74HC4094 logic chips // Renders images stored in an array in program (FLASH)JPEG images are stored in header files -// (see jpeg1.h etc) +// (see jpeg1.h etc.) // The sketch does not need the SD or sdFat libraries since it does not access an SD Card. @@ -108,7 +108,7 @@ void drawArrayJpeg(const uint8_t arrayname[], uint32_t array_size, int xpos, int // fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders. void renderJPEG(int xpos, int ypos) { - // retrieve infomration about the image + // retrieve information about the image uint16_t *pImg; uint16_t mcu_w = JpegDec.MCUWidth; uint16_t mcu_h = JpegDec.MCUHeight; @@ -222,7 +222,7 @@ void jpegInfo() { // Show the execution time (optional) //#################################################################################################### // WARNING: for UNO/AVR legacy reasons printing text to the screen with the Mega might not work for -// sketch sizes greater than ~70KBytes because 16 bit address pointers are used in some libraries. +// sketch sizes greater than ~70KBytes because 16-bit address pointers are used in some libraries. // The Due will work fine with the HX8357_Due library. diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino index 923cb39e..bdd9bb37 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino @@ -13,9 +13,9 @@ #define GREEN2RED 4 #define RED2GREEN 5 -#define TFT_GREY 0x2104 // Dark grey 16 bit colour +#define TFT_GREY 0x2104 // Dark grey 16-bit colour -#include "alert.h" // Out of range alert icon +#include "Alert.h" // Out of range alert icon #include // Hardware-specific library #include @@ -127,8 +127,8 @@ int ringMeter(int value, int vmin, int vmax, int x, int y, int r, const char *un case 1: colour = TFT_GREEN; break; // Fixed colour case 2: colour = TFT_BLUE; break; // Fixed colour case 3: colour = rainbow(map(i, -angle, angle, 0, 127)); break; // Full spectrum blue to red - case 4: colour = rainbow(map(i, -angle, angle, 70, 127)); break; // Green to red (high temperature etc) - case 5: colour = rainbow(map(i, -angle, angle, 127, 63)); break; // Red to green (low battery etc) + case 4: colour = rainbow(map(i, -angle, angle, 70, 127)); break; // Green to red (high temperature etc.) + case 5: colour = rainbow(map(i, -angle, angle, 127, 63)); break; // Red to green (low battery etc.) default: colour = TFT_BLUE; break; // Fixed colour } tft.fillTriangle(x0, y0, x1, y1, x2, y2, colour); @@ -193,14 +193,14 @@ void drawAlert(int x, int y , int side, bool draw) } // ######################################################################### -// Return a 16 bit rainbow colour +// Return a 16-bit rainbow colour // ######################################################################### unsigned int rainbow(byte value) { // Value is expected to be in range 0-127 // The value is converted to a spectrum colour from 0 = blue through to 127 = red - byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte red = 0; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino index f0b14d8a..e339a329 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino @@ -23,7 +23,7 @@ void setup(void) { // check file system if (!SPIFFS.begin()) { - Serial.println("formating file system"); + Serial.println("formatting file system"); SPIFFS.format(); SPIFFS.begin(); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/Flash_Jpg_DMA/panda.h b/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/Flash_Jpg_DMA/panda.h index b4b5653a..977b62ad 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/Flash_Jpg_DMA/panda.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/Flash_Jpg_DMA/panda.h @@ -2,15 +2,14 @@ http://tomeko.net/online_tools/file_to_hex.php?lang=en If needed, first resize and crop to an appropriate width and height - to suit your display with an image editting program such as IrfanView. + to suit your display with an image editing program such as IrfanView. - You can also change the image "guality" to reduce the file size. + You can also change the image "quality" to reduce the file size. - Paste the array into a new tabe, top and tail the array from the + Paste the array into a new tab, top and tail the array from the tool to look like the one below with: - #include - const uint8_t name[] PROGMEM = { + const uint8_t name[] PROGMEM = { to start and and end with: @@ -22,7 +21,6 @@ */ -#include const uint8_t panda[] PROGMEM = { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0xB4, 0x00, 0xB4, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/SpriteRotatingCube/SpriteRotatingCube.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/SpriteRotatingCube/SpriteRotatingCube.ino index 30f46b3e..a57ed6bb 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/SpriteRotatingCube/SpriteRotatingCube.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/SpriteRotatingCube/SpriteRotatingCube.ino @@ -2,7 +2,7 @@ // https://en.wikipedia.org/wiki/Direct_memory_access // Tested with ESP32, Nucleo 64 STM32F446RE and Nucleo 144 STM32F767ZI -// TFT's with SPI can use DMA, the sketch also works with 8 bit +// TFT's with SPI can use DMA, the sketch also works with 8-bit // parallel TFT's (tested with ILI9341 and ILI9481) // The sketch will run on processors without DMA and also parallel @@ -36,7 +36,7 @@ // Color depth has to be 16 bits if DMA is used to render image #define COLOR_DEPTH 16 -// 128x128 for a 16 bit colour Sprite (32Kbytes RAM) +// 128x128 for a 16-bit colour Sprite (32Kbytes RAM) // Maximum is 181x181 (64Kbytes) for DMA - restricted by processor design #define IWIDTH 128 #define IHEIGHT 128 @@ -56,7 +56,7 @@ TFT_eSprite spr[2] = {TFT_eSprite(&tft), TFT_eSprite(&tft) }; // Toggle buffer selection bool sprSel = 0; -// Pointers to start of Sprties in RAM +// Pointers to start of Sprites in RAM uint16_t* sprPtr[2]; // Define the cube face colors @@ -305,7 +305,7 @@ void drawCube() p2y[i] = IHEIGHT / 2 + ay[i] * CUBE_SIZE / az[i]; } - // Fill the buffer with color 0 (Black) + // Fill the buffer with colour 0 (Black) spr[sprSel].fillSprite(TFT_BLACK); for (int i = 0; i < 12; i++) { @@ -353,7 +353,7 @@ void drawCube() uint32_t computePrimeNumbers(int32_t n) { if (n<2) return 1; - int32_t i, fact, j, p; + int32_t i, fact, j, p = 0; //Serial.print("\nPrime Numbers are: \n"); for (i = 1; i <= n; i++) diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/boing_ball/boing_ball.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/boing_ball/boing_ball.ino index 0d9a9c82..a6e5e707 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/boing_ball/boing_ball.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/DMA test/boing_ball/boing_ball.ino @@ -19,7 +19,7 @@ // Blue Pill overclocked to 128MHz *no* DMA - 32MHz SPI 64 fps // Blue Pill overclocked to 128MHz with DMA - 32MHz SPI 116 fps -// ESP32 - 8 bit parallel 110 fps (no DMA) +// ESP32 - 8-bit parallel 110 fps (no DMA) // ESP32 - 40MHz SPI *no* DMA 93 fps // ESP32 - 40MHz SPI with DMA 112 fps @@ -39,7 +39,7 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library #define RED 0xF800 #define WHITE 0xFFFF -#define YBOTTOM 123 // Ball Y coord at bottom +#define YBOTTOM 123 // Ball Y coordinate at bottom #define YBOUNCE -3.5 // Upward velocity on ball bounce // Ball coordinates are stored floating-point because screen refresh @@ -49,7 +49,7 @@ float ballx = 20.0, bally = YBOTTOM, // Current ball position ballframe = 3; // Ball animation frame # int balloldx = ballx, balloldy = bally; // Prior ball position -// Working buffer for ball rendering...2 scanlines that alternate, +// Working buffer for ball rendering...2 scan lines that alternate, // one is rendered while the other is transferred via DMA. uint16_t renderbuf[2][SCREENWIDTH]; @@ -64,7 +64,7 @@ void setup() { tft.begin(); tft.setRotation(3); // Landscape orientation, USB at bottom right tft.setSwapBytes(false); - // Draw initial framebuffer contents: + // Draw initial frame buffer contents: //tft.setBitmapColor(GRIDCOLOR, BGCOLOR); tft.fillScreen(BGCOLOR); @@ -144,7 +144,7 @@ void loop() { (by >= 0) && (by < BALLHEIGHT)) { // inside the ball bitmap area? // Yes, do ball compositing math... p = ball[by][bx1 / 2]; // Get packed value (2 pixels) - c = (bx1 & 1) ? (p & 0xF) : (p >> 4); // Unpack high or low nybble + c = (bx1 & 1) ? (p & 0xF) : (p >> 4); // Unpack high or low nibble if(c == 0) { // Outside ball - just draw grid c = background[bgy][bgx1 / 8] & (0x80 >> (bgx1 & 7)) ? GRIDCOLOR : BGCOLOR; } else if(c > 1) { // In ball area... @@ -155,7 +155,7 @@ void loop() { } else { // Outside ball bitmap, just draw background bitmap... c = background[bgy][bgx1 / 8] & (0x80 >> (bgx1 & 7)) ? GRIDCOLOR : BGCOLOR; } - *destPtr++ = c<<8 | c>>8; // Store pixel color + *destPtr++ = c<<8 | c>>8; // Store pixel colour bx1++; // Increment bitmap position counters (X axis) bgx1++; } diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino index 3c30f1d7..d64775c8 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino @@ -36,7 +36,7 @@ void setup() { tft.begin(); - if (!SD.begin()) { + if (!SD.begin(5, tft.getSPIinstance())) { Serial.println("Card Mount Failed"); return; } @@ -249,7 +249,7 @@ void jpegInfo() { // Show the execution time (optional) //#################################################################################################### // WARNING: for UNO/AVR legacy reasons printing text to the screen with the Mega might not work for -// sketch sizes greater than ~70KBytes because 16 bit address pointers are used in some libraries. +// sketch sizes greater than ~70KBytes because 16-bit address pointers are used in some libraries. // The Due will work fine with the HX8357_Due library. diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino index c78e0bff..7cc3db2c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino @@ -120,7 +120,7 @@ void setup(void) { // EYE-RENDERING FUNCTION -------------------------------------------------- #define BUFFER_SIZE 256 // 64 to 512 seems optimum = 30 fps for default eye void drawEye( // Renders one eye. Inputs must be pre-clipped & valid. - // Use native 32 bit variables where possible as this is 10% faster! + // Use native 32-bit variables where possible as this is 10% faster! uint8_t e, // Eye array index; 0 or 1 for left/right uint32_t iScale, // Scale factor for iris uint32_t scleraX, // First pixel X offset into sclera image @@ -134,7 +134,7 @@ void drawEye( // Renders one eye. Inputs must be pre-clipped & valid. uint32_t d; uint32_t pixels = 0; - uint16_t pbuffer[BUFFER_SIZE]; // This one needs to be 16 bit + uint16_t pbuffer[BUFFER_SIZE]; // This one needs to be 16-bit // Set up raw pixel dump to entire screen. Although such writes can wrap // around automatically from end of rect back to beginning, the region is diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/screenshotToConsole.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/screenshotToConsole.ino index daa60ac6..9dd98f3a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/screenshotToConsole.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/ESP8266_uncannyEyes/screenshotToConsole.ino @@ -58,7 +58,7 @@ void screenshotToConsole() // Get first pixel to prime the Run Length Encoded // Function format is: tft.readRectRGB( x, y, width, height, buffer); - // color is a pointer to a buffer that the RGB 8 bit values are piped into + // color is a pointer to a buffer that the RGB 8-bit values are piped into // the buffer size must be >= (width * height * 3) bytes eye[e].tft.readRectRGB(0, 0, 1, 1, color); // 1 x 1 so reading 1 pixel at 0,0 diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Button_Label_Datum/TFT_Button_Label_Datum.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Button_Label_Datum/TFT_Button_Label_Datum.ino index 256e2b35..494faafa 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Button_Label_Datum/TFT_Button_Label_Datum.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Button_Label_Datum/TFT_Button_Label_Datum.ino @@ -73,7 +73,7 @@ void loop() { uint16_t t_x = 0, t_y = 0; // To store the touch coordinates // Get current touch state and coordinates - boolean pressed = tft.getTouch(&t_x, &t_y); + bool pressed = tft.getTouch(&t_x, &t_y); // Adjust press state of each key appropriately for (uint8_t b = 0; b < NUM_KEYS; b++) { @@ -133,7 +133,7 @@ void touch_calibrate() // check file system exists if (!SPIFFS.begin()) { - Serial.println("Formating file system"); + Serial.println("Formatting file system"); SPIFFS.format(); SPIFFS.begin(); } diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino index cde4ecb9..14d52db9 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino @@ -1,4 +1,4 @@ -// Icon images are stored in tabs ^ e.g. Alert.h etc above this line +// Icon images are stored in tabs ^ e.g. Alert.h etc.above this line // more than one icon can be in a header file // Arrays containing FLASH images can be created with UTFT library tool: diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_SPIFFS_BMP/BMP_functions.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_SPIFFS_BMP/BMP_functions.ino index b3905e9d..1d9de1e8 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_SPIFFS_BMP/BMP_functions.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_SPIFFS_BMP/BMP_functions.ino @@ -46,7 +46,7 @@ void drawBmp(const char *filename, int16_t x, int16_t y) { bmpFS.read(lineBuffer, sizeof(lineBuffer)); uint8_t* bptr = lineBuffer; uint16_t* tptr = (uint16_t*)lineBuffer; - // Convert 24 to 16 bit colours + // Convert 24 to 16-bit colours for (uint16_t col = 0; col < w; col++) { b = *bptr++; diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/processing_sketch.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/processing_sketch.ino index 3e71f41f..d657a080 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/processing_sketch.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/processing_sketch.ino @@ -63,7 +63,7 @@ int max_allowed = 1000; // Maximum number of save images allowed before a resta // These are default values, this sketch obtains the actual values from the Arduino board int tft_width = 480; // default TFT width (automatic - sent by Arduino) int tft_height = 480; // default TFT height (automatic - sent by Arduino) -int color_bytes = 2; // 2 for 16 bit, 3 for three RGB bytes (automatic - sent by Arduino) +int color_bytes = 2; // 2 for 16-bit, 3 for three RGB bytes (automatic - sent by Arduino) import processing.serial.*; diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/screenServer.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/screenServer.ino index 82bbbd7d..733c4ffc 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/screenServer.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/TFT_Screen_Capture/screenServer.ino @@ -2,8 +2,8 @@ // over the serial port. Use a high baud rate, e.g. for an ESP8266: // Serial.begin(921600); -// At 921600 baud a 320 x 240 image with 16 bit colour transfers can be sent to the -// PC client in ~1.67s and 24 bit colour in ~2.5s which is close to the theoretical +// At 921600 baud a 320 x 240 image with 16-bit colour transfers can be sent to the +// PC client in ~1.67s and 24-bit colour in ~2.5s which is close to the theoretical // minimum transfer time. // This sketch has been created to work with the TFT_eSPI library here: @@ -40,7 +40,7 @@ // Number of pixels to send in a burst (minimum of 1), no benefit above 8 // NPIXELS values and render times: -// NPIXELS 1 = use readPixel() = >5s and 16 bit pixels only +// NPIXELS 1 = use readPixel() = >5s and 16-bit pixels only // NPIXELS >1 using rectRead() 2 = 1.75s, 4 = 1.68s, 8 = 1.67s #define NPIXELS 8 // Must be integer division of both TFT width and TFT height @@ -104,7 +104,7 @@ bool serialScreenServer(String filename) wait = false; // No need to wait anymore lastCmdTime = millis(); // Set last received command time - // Send screen size etc using a simple header with delimiters for client checks + // Send screen size etc.using a simple header with delimiters for client checks sendParameters(filename); } } @@ -169,7 +169,7 @@ bool serialScreenServer(String filename) } //==================================================================================== -// Send screen size etc using a simple header with delimiters for client checks +// Send screen size etc.using a simple header with delimiters for client checks //==================================================================================== void sendParameters(String filename) { @@ -183,7 +183,7 @@ void sendParameters(String filename) Serial.write('Y'); // Bits per pixel (16 or 24) if (NPIXELS > 1) Serial.write(BITS_PER_PIXEL); - else Serial.write(16); // readPixel() only provides 16 bit values + else Serial.write(16); // readPixel() only provides 16-bit values Serial.write('?'); // Filename next Serial.print(filename); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/alphaBlend_Test/alphaBlend_Test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/alphaBlend_Test/alphaBlend_Test.ino index f3f4cdf4..a436dcc5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/alphaBlend_Test/alphaBlend_Test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Generic/alphaBlend_Test/alphaBlend_Test.ino @@ -1,12 +1,12 @@ /* - This tests the alpha blending function that is used with the antialiased + This tests the alpha blending function that is used with the anti-aliased fonts: Alpha = 0 = 100% background, alpha = 255 = 100% foreground colour blendedColor = tft.alphaBlend(alpha, fg_color, bg_color); - The alphaBlend() function operates on 16 bit colours only + The alphaBlend() function operates on 16-bit colours only A test is included where the colours are mapped to 8 bits after blending Information on alpha blending is here @@ -43,7 +43,7 @@ void setup(void) { // ------------------------------------------------------------------------- void loop() { - // 16 bit colours (5 bits red, 6 bits green, 5 bits blue) + // 16-bit colours (5 bits red, 6 bits green, 5 bits blue) // Blend from white to full spectrum for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground { @@ -79,18 +79,18 @@ void loop() delay(4000); //* - // Decrease to 8 bit colour (3 bits red, 3 bits green, 2 bits blue) + // Decrease to 8-bit colour (3 bits red, 3 bits green, 2 bits blue) // Blend from white to full spectrum for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground { - // Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying + // Convert blended 16-bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0xFFFF)))); } // Blend from full spectrum to black for (int a = 255; a > 2; a-=2) { - // Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying + // Convert blended 16-bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0)))); } @@ -108,7 +108,7 @@ void loop() //*/ /* - // 16 bit colours (5 bits red, 6 bits green, 5 bits blue) + // 16-bit colours (5 bits red, 6 bits green, 5 bits blue) for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground { for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.alphaBlend(a, rainbow(c), TFT_CYAN)); @@ -137,7 +137,7 @@ void loop() // ######################################################################### -// Return a 16 bit rainbow colour +// Return a 16-bit rainbow colour // ######################################################################### unsigned int rainbow(byte value) { @@ -147,7 +147,7 @@ unsigned int rainbow(byte value) value = value%192; - byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte red = 0; // Red is the top 5 bits of a 16-bit colour value byte green = 0; // Green is the middle 6 bits, but only top 5 bits used here byte blue = 0; // Blue is the bottom 5 bits diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/Font_Demo_1_Array.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/Font_Demo_1_Array.ino index 089dd2cf..4efff446 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/Font_Demo_1_Array.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/Font_Demo_1_Array.ino @@ -119,20 +119,22 @@ void loop() { //tft.fillScreen(TFT_BLACK); // Draw changing numbers - does not work unless a filled rectangle is drawn over the old text - for (int i = 0; i <= 20; i++) + for (int i = 0; i <= 99; i++) { tft.setCursor(50, 50); + tft.setTextColor(TFT_GREEN, TFT_BLACK); // TFT_BLACK is used for anti-aliasing only + // By default background fill is off tft.print(" "); // Overprinting old number with spaces DOES NOT WORK! - tft.setTextColor(TFT_GREEN, TFT_BLACK); tft.setCursor(50, 50); tft.print(i / 10.0, 1); - tft.fillRect (50, 90, 60, 40, TFT_BLACK); // Overprint with a filled rectangle - tft.setTextColor(TFT_GREEN, TFT_BLACK); + // Adding a parameter "true" to the setTextColor() function fills character background + // This extra parameter is only for smooth fonts! + tft.setTextColor(TFT_GREEN, TFT_BLACK, true); tft.setCursor(50, 90); tft.print(i / 10.0, 1); - //delay (200); + delay (200); } delay(5000); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold15.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold15.h index c3563707..aa777b8e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold15.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold15.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold15.h" */ -#include const uint8_t NotoSansBold15[] PROGMEM = { 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold36.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold36.h index 25df964b..0105766a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold36.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_1_Array/NotoSansBold36.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold36.h" */ -#include const uint8_t NotoSansBold36[] PROGMEM = { 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/Font_Demo_2_Array.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/Font_Demo_2_Array.ino index f8fc2340..135c6e6d 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/Font_Demo_2_Array.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/Font_Demo_2_Array.ino @@ -89,7 +89,8 @@ void loop() { tft.fillScreen(TFT_BLACK); - tft.setTextColor(TFT_GREEN, TFT_BLUE); // Change the font colour and the background colour + // The "true" parameter forces background drawing for smooth fonts + tft.setTextColor(TFT_GREEN, TFT_BLUE, true); // Change the font colour and the background colour tft.drawString("36pt font", xpos, ypos); @@ -99,11 +100,14 @@ void loop() { tft.setTextPadding(100); // Draw changing numbers - likely to flicker using this plot method! - for (int i = 0; i <= 20; i++) { + for (int i = 0; i <= 99; i++) { tft.drawFloat(i / 10.0, 1, xpos, ypos); delay (200); } + // Turn off text padding by setting value to 0 + tft.setTextPadding(0); + tft.unloadFont(); // Remove the font to recover memory used delay(5000); @@ -119,7 +123,7 @@ void loop() { tft.fillScreen(TFT_BLACK); - tft.setTextColor(TFT_DARKGREY, TFT_BLACK); + tft.setTextColor(TFT_DARKGREY, TFT_BLACK, false); // Use middle of screen as datum xpos = tft.width() /2; diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold15.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold15.h index c3563707..aa777b8e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold15.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold15.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold15.h" */ -#include const uint8_t NotoSansBold15[] PROGMEM = { 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold36.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold36.h index 25df964b..0105766a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold36.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_2_Array/NotoSansBold36.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold36.h" */ -#include const uint8_t NotoSansBold36[] PROGMEM = { 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/Font_Demo_3_Array.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/Font_Demo_3_Array.ino index e8d84ce9..038cfd42 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/Font_Demo_3_Array.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/Font_Demo_3_Array.ino @@ -10,8 +10,8 @@ This sketch uses method 3, the font characters are first plotted in a Sprite, then the Sprite is pushed to the screen. This method is very flexible and the Sprite can be - created, deleted, resized as needed. To render anit-aliased fonts well the Sprite - needs to be 16 bit. The fonts will render in 1 bit per pixel sprites but there + created, deleted, resized as needed. To render anti-aliased fonts well the Sprite + needs to be 16-bit. The fonts will render in 1 bit per pixel sprites but there will then be no anti-aliasing. Using 1 bit per pixel Sprites is however useful to use the extended Unicode range in fonts on mono displays like ePaper. @@ -50,7 +50,7 @@ void setup(void) { tft.setRotation(1); - spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + spr.setColorDepth(16); // 16-bit colour needed to show antialiased fonts } void loop() { @@ -93,7 +93,7 @@ void loop() { tft.fillScreen(TFT_BLACK); - // Beware: Sprites are a differerent "class" to TFT, so different fonts can be loaded + // Beware: Sprites are a different "class" to TFT, so different fonts can be loaded // in the tft and sprite instances, so load the font in the class instance you use! // In this example this means the spr. instance. @@ -144,7 +144,7 @@ void loop() { // Mono spaced font // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - spr.loadFont(AA_FONT_MONO); // Mono spaced fonts have fixed intercharacter gaps to + spr.loadFont(AA_FONT_MONO); // Mono spaced fonts have fixed inter-character gaps to // aid formatting int bnum = 1; @@ -181,7 +181,7 @@ void button(int x, int y, int num ) #define IWIDTH 40 #define IHEIGHT 25 - // Create a 16 bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed) + // Create a 16-bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed) spr.setColorDepth(16); spr.createSprite(IWIDTH, IHEIGHT); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold15.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold15.h index c3563707..aa777b8e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold15.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold15.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold15.h" */ -#include const uint8_t NotoSansBold15[] PROGMEM = { 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold36.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold36.h index 25df964b..0105766a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold36.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansBold36.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold36.h" */ -#include const uint8_t NotoSansBold36[] PROGMEM = { 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansMonoSCB20.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansMonoSCB20.h index 27a25445..f54a1cb6 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansMonoSCB20.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_3_Array/NotoSansMonoSCB20.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansMonoSCB20.h" */ -#include const uint8_t NotoSansMonoSCB20[] PROGMEM = { 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/Font_Demo_4_Array.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/Font_Demo_4_Array.ino index cae0b22f..de2eab99 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/Font_Demo_4_Array.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/Font_Demo_4_Array.ino @@ -58,7 +58,7 @@ void setup(void) { tft.setRotation(1); - spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + spr.setColorDepth(16); // 16-bit colour needed to show anti-aliased fonts } void loop() { diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold15.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold15.h index c3563707..aa777b8e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold15.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold15.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold15.h" */ -#include const uint8_t NotoSansBold15[] PROGMEM = { 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold36.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold36.h index 25df964b..0105766a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold36.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Font_Demo_4_Array/NotoSansBold36.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold36.h" */ -#include const uint8_t NotoSansBold36[] PROGMEM = { 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Final_Frontier_28.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Final_Frontier_28.h index f739df22..4b1a18ef 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Final_Frontier_28.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Final_Frontier_28.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t Final_Frontier_28[] PROGMEM = { 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Print_Smooth_Font.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Print_Smooth_Font.ino index 230bb19a..4af307f6 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Print_Smooth_Font.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Print_Smooth_Font/Print_Smooth_Font.ino @@ -8,14 +8,14 @@ sketch in the library Tools folder. The Processing sketch can convert TrueType fonts in *.ttf or *.otf files. - The library supports 16 bit unicode characters: + The library supports 16-bit Unicode characters: https://en.wikipedia.org/wiki/Unicode_font - The characters supported are in the in the Basic Multilingal Plane: + The characters supported are in the in the Basic Multilingual Plane: https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane - Make sure all the display driver and pin connenctions are correct by - editting the User_Setup.h file in the TFT_eSPI library folder. + Make sure all the display driver and pin connections are correct by + editing the User_Setup.h file in the TFT_eSPI library folder. */ // The font is stored in an array within a sketch tab. diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold15.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold15.h index af6d6fab..90e40ac0 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold15.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold15.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t NotoSansBold15[] PROGMEM = { 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold36.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold36.h index 0e3339c4..3f400cc8 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold36.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/NotoSansBold36.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t NotoSansBold36[] PROGMEM = { 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/Smooth_font_gradient.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/Smooth_font_gradient.ino index d6f0f148..dc28874f 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/Smooth_font_gradient.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_gradient/Smooth_font_gradient.ino @@ -1,6 +1,6 @@ /* This sketch uses Smooth fonts stored in FLASH program memory. It uses a method - for rendering anti-aliased fonts on a graded background. This is acheived by + for rendering anti-aliased fonts on a graded background. This is achieved by telling the TFT_eSPI library the pixel color at each point on the screen. In this sketch a background colour gradient is drawn, the color of each pixel can therefore be determined by a function. The TFT does not need to support reading @@ -74,7 +74,7 @@ void setup(void) { void loop() { - // Select a font size comensurate with screen size + // Select a font size commensurate with screen size if (tft.width()>= 320) tft.loadFont(AA_FONT_LARGE); else diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold15.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold15.h index de10585e..6ffd6912 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold15.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold15.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t NotoSansBold15[] PROGMEM = { 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold36.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold36.h index e72a6686..04195523 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold36.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/NotoSansBold36.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t NotoSansBold36[] PROGMEM = { 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino index 7359a692..669e9371 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino @@ -1,9 +1,9 @@ /* This sketch uses Smooth fonts stored in FLASH program memory. It uses a method - for rendering anti-aliased fonts on an arbitrary background. This is acheived + for rendering anti-aliased fonts on an arbitrary background. This is achieved by reading the pixel color at each point on the screen. The TFT must support reading the graphics RAM of the screen memory. This sketch has been tested with - ILI9241 and ILI9481 serial and parallel screens. + ILI9341 and ILI9481 serial and parallel screens. The TFT_eSPI library must be given the name of the function in the sketch that will return the pixel color at a position x,y on the TFT. In this @@ -83,7 +83,7 @@ unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each void rainbow_fill() { - // The colours and state are not initialised so the start colour changes each time the funtion is called + // The colours and state are not initialised so the start colour changes each time the function is called for (int i = 319; i >= 0; i--) { // Draw a vertical line 1 pixel wide in the selected colour diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Final_Frontier_28.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Final_Frontier_28.h index ea240fcb..474fe5cc 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Final_Frontier_28.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Final_Frontier_28.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t Final_Frontier_28[] PROGMEM = { 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Latin_Hiragana_24.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Latin_Hiragana_24.h index aeb29f34..5e7f8e63 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Latin_Hiragana_24.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Latin_Hiragana_24.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t Latin_Hiragana_24[] PROGMEM = { 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_Test_72.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_Test_72.h index a88ef62e..d76aa67d 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_Test_72.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_Test_72.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name and }; at the end: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { Insert byte array here @@ -17,7 +16,6 @@ #include "fontName.h" */ -#include const uint8_t Unicode_Test_72[] PROGMEM = { 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_test.ino index a8f6beaa..9b523813 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/FLASH_Array/Unicode_test/Unicode_test.ino @@ -8,14 +8,14 @@ The library expects strings to be in UTF-8 encoded format: https://www.fileformat.info/info/unicode/utf8.htm - Creating varaibles needs to be done with care when using character arrays: + Creating variables needs to be done with care when using character arrays: char c = 'µ'; // Wrong char bad[4] = "5µA"; // Wrong char good[] = "5µA"; // Good String okay = "5µA"; // Good This is because UTF-8 characters outside the basic Latin set occupy more than - 1 byte per character! A 16 bit unicode character occupies 3 bytes! + 1 byte per character! A 16-bit Unicode character occupies 3 bytes! */ @@ -89,7 +89,7 @@ void loop() //---------------------------------------------------------------------------- // We can have any random mix of characters in the font - String test2 = "仝倀"; // Unicodes 0x4EDD, 0x5000 + String test2 = "仝倀"; // Unicode 0x4EDD, 0x5000 tft.loadFont(Unicode_Test_72); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SD_Card/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SD_Card/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino index c6dbb197..5f3b961f 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SD_Card/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SD_Card/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino @@ -10,14 +10,14 @@ Load the font file onto the root directory of the SD Card. The font files used by this sketch can be found in the Data folder, press Ctrl+K to see it. - The library supports 16 bit unicode characters: + The library supports 16-bit Unicode characters: https://en.wikipedia.org/wiki/Unicode_font - The characters supported are in the in the Basic Multilingal Plane: + The characters supported are in the in the Basic Multilingual Plane: https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane - Make sure all the display driver and pin connenctions are correct by - editting the User_Setup.h file in the TFT_eSPI library folder. + Make sure all the display driver and pin connections are correct by + editing the User_Setup.h file in the TFT_eSPI library folder. ######################################################################### ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_1/Font_Demo_1.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_1/Font_Demo_1.ino index e38a5ee0..5b8c781f 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_1/Font_Demo_1.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_1/Font_Demo_1.ino @@ -37,7 +37,7 @@ #define AA_FONT_SMALL "NotoSansBold15" #define AA_FONT_LARGE "NotoSansBold36" -// Font files are stored in SPIFFS, so load the linbrary +// Font files are stored in SPIFFS, so load the library #include #include @@ -141,13 +141,15 @@ void loop() { for (int i = 0; i <= 20; i++) { tft.setCursor(50, 50); + tft.setTextColor(TFT_GREEN, TFT_BLACK); // TFT_BLACK is used for anti-aliasing only + // By default background fill is off tft.print(" "); // Overprinting old number with spaces DOES NOT WORK! - tft.setTextColor(TFT_GREEN, TFT_BLACK); tft.setCursor(50, 50); tft.print(i / 10.0, 1); - tft.fillRect (50, 90, 60, 40, TFT_BLACK); // Overprint with a filled rectangle - tft.setTextColor(TFT_GREEN, TFT_BLACK); + // Adding a parameter "true" to the setTextColor() function fills character background + // This extra parameter is only for smooth fonts! + tft.setTextColor(TFT_GREEN, TFT_BLACK, true); tft.setCursor(50, 90); tft.print(i / 10.0, 1); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_2/Font_Demo_2.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_2/Font_Demo_2.ino index 6dbf769f..d3d17dee 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_2/Font_Demo_2.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_2/Font_Demo_2.ino @@ -32,7 +32,7 @@ #define AA_FONT_SMALL "NotoSansBold15" #define AA_FONT_LARGE "NotoSansBold36" -// Font files are stored in SPIFFS, so load the linbrary +// Font files are stored in SPIFFS, so load the library #include #include @@ -109,7 +109,8 @@ void loop() { tft.fillScreen(TFT_BLACK); - tft.setTextColor(TFT_GREEN, TFT_BLUE); // Change the font colour and the background colour + // The "true" parameter forces background drawing for smooth fonts + tft.setTextColor(TFT_GREEN, TFT_BLUE, true); // Change the font colour and the background colour tft.drawString("36pt font", xpos, ypos); @@ -124,6 +125,9 @@ void loop() { delay (200); } + // Turn off text padding by setting value to 0 + tft.setTextPadding(0); + tft.unloadFont(); // Remove the font to recover memory used delay(5000); @@ -139,7 +143,7 @@ void loop() { tft.fillScreen(TFT_BLACK); - tft.setTextColor(TFT_DARKGREY, TFT_BLACK); + tft.setTextColor(TFT_DARKGREY, TFT_BLACK, false); // Use middle of screen as datum xpos = tft.width() /2; diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_3/Font_Demo_3.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_3/Font_Demo_3.ino index ebc20555..6d18100a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_3/Font_Demo_3.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_3/Font_Demo_3.ino @@ -3,8 +3,8 @@ This sketch uses method 3, the font characters are first plotted in a Sprite, then the Sprite is pushed to the screen. This method is very flexible and the Sprite can be - created, deleted, resized as needed. To render anit-aliased fonts well the Sprite - needs to be 16 bit. The fonts will render in 1 bit per pixel sprites but there + created, deleted, resized as needed. To render anti-aliased fonts well the Sprite + needs to be 16-bit. The fonts will render in 1 bit per pixel sprites but there will then be no anti-aliasing. Using 1 bit per pixel Sprites is however useful to use the extended Unicode range in fonts on mono displays like ePaper. @@ -33,7 +33,7 @@ #define AA_FONT_SMALL "NotoSansBold15" #define AA_FONT_LARGE "NotoSansBold36" #define AA_FONT_MONO "NotoSansMonoSCB20" // NotoSansMono-SemiCondensedBold 20pt -// Font files are stored in SPIFFS, so load the linbrary +// Font files are stored in SPIFFS, so load the library #include #include @@ -50,7 +50,7 @@ void setup(void) { tft.setRotation(1); - spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + spr.setColorDepth(16); // 16-bit colour needed to show anti aliased fonts if (!SPIFFS.begin()) { Serial.println("SPIFFS initialisation failed!"); @@ -112,7 +112,7 @@ void loop() { tft.fillScreen(TFT_BLACK); - // Beware: Sprites are a differerent "class" to TFT, so different fonts can be loaded + // Beware: Sprites are a different "class" to TFT, so different fonts can be loaded // in the tft and sprite instances, so load the font in the class instance you use! // In this example this means the spr. instance. @@ -163,7 +163,7 @@ void loop() { // Mono spaced font // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - spr.loadFont(AA_FONT_MONO); // Mono spaced fonts have fixed intercharacter gaps to + spr.loadFont(AA_FONT_MONO); // Mono spaced fonts have fixed inter-character gaps to // aid formatting int bnum = 1; @@ -200,7 +200,7 @@ void button(int x, int y, int num ) #define IWIDTH 40 #define IHEIGHT 25 - // Create a 16 bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed) + // Create a 16-bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed) spr.setColorDepth(16); spr.createSprite(IWIDTH, IHEIGHT); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_4/Font_Demo_4.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_4/Font_Demo_4.ino index edad83c2..e86fa888 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_4/Font_Demo_4.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Font_Demo_4/Font_Demo_4.ino @@ -44,7 +44,7 @@ #define AA_FONT_SMALL "NotoSansBold15" #define AA_FONT_LARGE "NotoSansBold36" -// Font files are stored in SPIFFS, so load the linbrary +// Font files are stored in SPIFFS, so load the library #include #include @@ -61,7 +61,7 @@ void setup(void) { tft.setRotation(1); - spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + spr.setColorDepth(16); // 16-bit colour needed to show anti-aliased fonts if (!SPIFFS.begin()) { Serial.println("SPIFFS initialisation failed!"); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Print_Smooth_Font/Print_Smooth_Font.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Print_Smooth_Font/Print_Smooth_Font.ino index 10f9197c..007da700 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Print_Smooth_Font/Print_Smooth_Font.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Print_Smooth_Font/Print_Smooth_Font.ino @@ -1,7 +1,7 @@ /* Sketch to demonstrate using the print class with smooth fonts - Sketch is writtent for a 240 x 320 display + Sketch is written for a 240 x 320 display Load the font file into SPIFFS first by using the Arduino IDE Sketch Data Upload menu option. Font files must be stored in the @@ -15,14 +15,14 @@ Note: SPIFFS does not accept an underscore _ in filenames! - The library supports 16 bit unicode characters: + The library supports 16-bit Unicode characters: https://en.wikipedia.org/wiki/Unicode_font - The characters supported are in the in the Basic Multilingal Plane: + The characters supported are in the in the Basic Multilingual Plane: https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane - Make sure all the display driver and pin connenctions are correct by - editting the User_Setup.h file in the TFT_eSPI library folder. + Make sure all the display driver and pin connections are correct by + editing the User_Setup.h file in the TFT_eSPI library folder. ######################################################################### ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_gradient/Smooth_font_gradient.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_gradient/Smooth_font_gradient.ino index b545ab3c..9efe983f 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_gradient/Smooth_font_gradient.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_gradient/Smooth_font_gradient.ino @@ -1,13 +1,13 @@ /* This sketch is based on Font Demo 1. It introduces a method for rendering - anti-aliased fonts on a graded background. This is acheived by telling the + anti-aliased fonts on a graded background. This is achieved by telling the TFT_eSPI library the pixel color at each point on the screen. In this sketch a graded background is drawn, the color of each pixel can therefore be determined. The TFT does not need to support reading of the graphics memory. The sketch could be adapted so only part of the screen is gas a color gradient. The TFT_eSPI library must be given the name of the function in the sketch - that will return the pixel xolor at a position x,y on the TFT. In this + that will return the pixel color at a position x,y on the TFT. In this sketch that function is called gradientColor, so this line is included: tft.setCallback(gradientColor); @@ -100,7 +100,7 @@ void setup(void) { void loop() { - // Select a font size comensurate with screen size + // Select a font size commensurate with screen size if (tft.width()>= 320) tft.loadFont(AA_FONT_LARGE); else diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino index c4d499cd..99c6e628 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Smooth_font_reading_TFT/Smooth_font_reading_TFT.ino @@ -1,6 +1,6 @@ /* This sketch is based on Font Demo 1. It introduces a method for rendering - anti-aliased fonts on an arbitrary background. This is acheived by reading + anti-aliased fonts on an arbitrary background. This is achieved by reading the pixel color at each point on the screen. The TFT must support reading the graphics RAM of the screen memory. This sketch has been tested with ILI9241 and ILI9481 serial and parallel screens. Other screens may or may @@ -52,7 +52,7 @@ void setup(void) { tft.begin(); - tft.setCallback(pixelColor); // The callback is only used durung font rendering + tft.setCallback(pixelColor); // The callback is only used during font rendering //tft.setCallback(nullptr); // Switch off callback (off by default) tft.setRotation(1); @@ -81,7 +81,7 @@ void loop() { rainbow_fill(); // Fill the screen with rainbow colours - // Select a font size comensurate with screen size + // Select a font size commensurate with screen size if (tft.width()>= 320) tft.loadFont(AA_FONT_LARGE); else @@ -110,7 +110,7 @@ unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each void rainbow_fill() { - // The colours and state are not initialised so the start colour changes each time the funtion is called + // The colours and state are not initialised so the start colour changes each time the function is called for (int i = 319; i >= 0; i--) { // Draw a vertical line 1 pixel wide in the selected colour diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Unicode_test/Unicode_test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Unicode_test/Unicode_test.ino index aac4926e..5f97248a 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Unicode_test/Unicode_test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Smooth Fonts/SPIFFS/Unicode_test/Unicode_test.ino @@ -8,14 +8,14 @@ The library expects strings to be in UTF-8 encoded format: https://www.fileformat.info/info/unicode/utf8.htm - Creating varaibles needs to be done with care when using character arrays: + Creating variables needs to be done with care when using character arrays: char c = 'µ'; // Wrong char bad[4] = "5µA"; // Wrong char good[] = "5µA"; // Good String okay = "5µA"; // Good This is because UTF-8 characters outside the basic Latin set occupy more than - 1 byte per character! A 16 bit unicode character occupies 3 bytes! + 1 byte per character! A 16-bit Unicode character occupies 3 bytes! */ diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/Animated_dial.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/Animated_dial.ino index 33b7d502..ed71e867 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/Animated_dial.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/Animated_dial.ino @@ -6,10 +6,10 @@ // The sketch operates by creating a copy of the screen block where // the needle will be drawn, the needle is then drawn on the screen. -// When the needle moves, the original copy of the sreen area is +// When the needle moves, the original copy of the screen area is // pushed to the screen to over-write the needle graphic. A copy // of the screen where the new position will be drawn is then made -// before drawing the needle in the new postion. This technique +// before drawing the needle in the new position. This technique // allows the needle to move over other screen graphics. // The sketch calculates the size of the buffer memory required and @@ -44,7 +44,7 @@ TFT_eSprite spr = TFT_eSprite(&tft); // Sprite for meter reading uint16_t* tft_buffer; bool buffer_loaded = false; uint16_t spr_width = 0; - +uint16_t bg_color =0; // ======================================================================================= // This function will be called during decoding of the jpeg file // ======================================================================================= @@ -82,14 +82,14 @@ void setup() { // Load the font and create the Sprite for reporting the value spr.loadFont(AA_FONT_LARGE); - spr_width = spr.textWidth("277"); + spr_width = spr.textWidth("777"); // 7 is widest numeral in this font spr.createSprite(spr_width, spr.fontHeight()); - uint16_t bg_color = tft.readPixel(120, 120); // Get colour from dial centre + bg_color = tft.readPixel(120, 120); // Get colour from dial centre spr.fillSprite(bg_color); - spr.setTextColor(TFT_WHITE, bg_color); + spr.setTextColor(TFT_WHITE, bg_color, true); spr.setTextDatum(MC_DATUM); spr.setTextPadding(spr_width); - spr.drawNumber(0, spr_width/2, 0); + spr.drawNumber(0, spr_width/2, spr.fontHeight()/2); spr.pushSprite(DIAL_CENTRE_X - spr_width / 2, DIAL_CENTRE_Y - spr.fontHeight() / 2); // Plot the label text @@ -195,7 +195,7 @@ void plotNeedle(int16_t angle, uint16_t ms_delay) buffer_loaded = true; } - // Draw the needle in the new postion, black in needle image is transparent + // Draw the needle in the new position, black in needle image is transparent needle.pushRotated(old_angle, TFT_BLACK); // Wait before next update @@ -203,7 +203,8 @@ void plotNeedle(int16_t angle, uint16_t ms_delay) } // Update the number at the centre of the dial - spr.drawNumber(old_angle+120, spr_width/2, 0); + spr.setTextColor(TFT_WHITE, bg_color, true); + spr.drawNumber(old_angle+120, spr_width/2, spr.fontHeight()/2); spr.pushSprite(120 - spr_width / 2, 120 - spr.fontHeight() / 2); // Slow needle down slightly as it approaches the new position diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/NotoSansBold36.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/NotoSansBold36.h index d892788f..8c92b19e 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/NotoSansBold36.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/NotoSansBold36.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab and add two lines at the start with a unique font name: - #include - const uint8_t fontName[] PROGMEM = { + const uint8_t fontName[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "NotoSansBold36.h" */ -#include // Digits 0-9 and . const uint8_t NotoSansBold36[] PROGMEM = { 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/dial.h b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/dial.h index 2321f57b..e026bb00 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/dial.h +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Animated_dial/dial.h @@ -5,8 +5,7 @@ Paste the byte array into a sketch tab "jpeg_name" and add two lines at the start with a unique array name: - #include - const uint8_t jpeg_name[] PROGMEM = { + const uint8_t jpeg_name[] PROGMEM = { At the end add: @@ -17,7 +16,6 @@ #include "jpeg_name.h" */ -#include const uint8_t dial[] PROGMEM = { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0xFF, 0xE1, 0x00, 0x5A, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x4D, 0x4D, diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino index dacf64fe..33ce9bb5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino @@ -12,7 +12,7 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 1 bit Sprite occupies (width * height)/8 bytes in RAM. So, + A 1-bit Sprite occupies (width * height)/8 bytes in RAM. So, for example, a 320 x 240 pixel Sprite occupies 9600 bytes. */ // A new setBitmapColor(fg_color, bg_color) function allows diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino index a6a0a6a1..83ded139 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino @@ -10,7 +10,7 @@ // screen very simple. The rotation is clockwise with increasing angle. The angle is in // degrees, an angle of 0 means no Sprite rotation. -// The pushRotated() function works with 1, 4, 8 and 16 bit per pixel (bpp) Sprites. +// The pushRotated() function works with 1, 4, 8 and 16-bit per pixel (bpp) Sprites. // The original Sprite is unchanged so can be plotted again at a different angle. @@ -20,7 +20,7 @@ // For 1 bpp Sprites the foreground and background colours are defined with the // function spr.setBitmapColor(foregroundColor, backgroundColor). -// For 4 bpp Sprites the colour map index is used instead of the 16 bit colour +// For 4 bpp Sprites the colour map index is used instead of the 16-bit colour // e.g. spr.setTextColor(5); // Green text in default colour map // See "Transparent_Sprite_Demo_4bit" example for default colour map details diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino index bb27922e..e9fccb30 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino @@ -14,7 +14,7 @@ // The rotation angle is in degrees, an angle of 0 means no Sprite rotation. -// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites. +// The pushRotated() function works with 1, 8 and 16-bit per pixel (bpp) Sprites. // For 1 bpp Sprites the foreground and background colours are defined with the // member function setBitmapColor(foregroundColor, backgroundColor). diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino index 2b93dc9f..5341be95 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino @@ -80,7 +80,7 @@ void setup() // Send jpeg info to serial port fex.jpegInfo("/Eye_80x64.jpg"); - // Draw jpeg iamge in Sprite spr at 0,0 + // Draw jpeg image in Sprite spr at 0,0 fex.drawJpeg("/Eye_80x64.jpg", 0 , 0, &spr); } @@ -105,7 +105,7 @@ void loop() delay(1000); // Push copies of Sprite rotated through increasing angles 0-360 degrees - // with 45 fegree increments + // with 45 degree increments for (int16_t angle = 0; angle <= 360; angle += 45) { spr.pushRotated(angle); delay(500); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino index 9d6cf8e8..406f0c08 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino @@ -9,7 +9,7 @@ ######################################################################### */ -// Specify sprite 160 x 128 pixels (needs 40Kbytes of RAM for 16 bit colour) +// Specify sprite 160 x 128 pixels (needs 40Kbytes of RAM for 16-bit colour) #define IWIDTH 160 #define IHEIGHT 128 diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw/Sprite_draw.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw/Sprite_draw.ino index 78e02f29..ce3b06b5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw/Sprite_draw.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw/Sprite_draw.ino @@ -14,12 +14,12 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 16 bit Sprite occupies (2 * width * height) bytes in RAM. + A 16-bit Sprite occupies (2 * width * height) bytes in RAM. - On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated, - this size requires 40kBytes of RAM for a 16 bit colour depth. + On a ESP8266 Sprite sizes up to 126 x 160 can be accommodated, + this size requires 40kBytes of RAM for a 16-bit colour depth. - When 8 bit colour depth sprites are created they occupy + When 8-bit colour depth sprites are created they occupy (width * height) bytes in RAM, so larger sprites can be created, or the RAM required is halved. @@ -46,7 +46,7 @@ void setup() // Initialise the TFT registers tft.init(); - // Optionally set colour depth to 8 or 16 bits, default is 16 if not spedified + // Optionally set colour depth to 8 or 16 bits, default is 16 if not specified // spr.setColorDepth(8); // Create a sprite of defined size @@ -123,7 +123,7 @@ void loop(void) { if (updateTime <= millis()) { - // Use time delay so sprtie does not move fast when not all on screen + // Use time delay so sprite does not move fast when not all on screen updateTime = millis() + wait; // Push the sprite to the TFT screen diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw_4bit/Sprite_draw_4bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw_4bit/Sprite_draw_4bit.ino index ca3ebe4b..e4b27433 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw_4bit/Sprite_draw_4bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_draw_4bit/Sprite_draw_4bit.ino @@ -1,9 +1,9 @@ /* - Sketch to show how a 4 bit Sprite is created, how to draw pixels + Sketch to show how a 4-bit Sprite is created, how to draw pixels and text within the Sprite and then push the Sprite onto the display screen. - The advantage of 4 bit sprites is: + The advantage of 4-bit sprites is: 1. Small memory footprint 2. Any set of 16 colours can be specified 3. Colours can be changed without redrawing in Sprite @@ -21,7 +21,7 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 4 bit Sprite occupies (width * height)/2 bytes in RAM. + A 4-bit Sprite occupies (width * height)/2 bytes in RAM. */ @@ -64,7 +64,7 @@ void loop(void) // Fill the whole sprite with color 0 (Sprite is in memory so not visible yet) spr.fillSprite(0); - // create a color map with known colors (16 maximum for 4 bit Sprite + // create a color map with known colors (16 maximum for 4-bit Sprite uint16_t cmap[16]; diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino index bdf53900..63fa854b 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino @@ -14,12 +14,12 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 16 bit Sprite occupies (2 * width * height) bytes in RAM. + A 16-bit Sprite occupies (2 * width * height) bytes in RAM. - On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated, - this size requires 40kBytes of RAM for a 16 bit color depth. + On a ESP8266 Sprite sizes up to 126 x 160 can be accommodated, + this size requires 40kBytes of RAM for a 16-bit color depth. - When 8 bit color depth sprites are created they occupy + When 8-bit color depth sprites are created they occupy (width * height) bytes in RAM, so larger sprites can be created, or the RAM required is halved. @@ -39,7 +39,7 @@ TFT_eSPI tft = TFT_eSPI(); // Declare object "tft" TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object -byte red = 31; // Red is the top 5 bits of a 16 bit colour value +byte red = 31; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits byte state = 0; @@ -99,7 +99,7 @@ void loop(void) } // ######################################################################### -// Return a 16 bit rainbow colour +// Return a 16-bit rainbow colour // ######################################################################### unsigned int rainbow() { diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll/Sprite_scroll.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll/Sprite_scroll.ino index 1968849a..61166be5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll/Sprite_scroll.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll/Sprite_scroll.ino @@ -14,9 +14,9 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 16 bit Sprite occupies (2 * width * height) bytes in RAM. + A 16-bit Sprite occupies (2 * width * height) bytes in RAM. - An 8 bit Sprite occupies (width * height) bytes in RAM. + An 8-bit Sprite occupies (width * height) bytes in RAM. */ diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_16bit/Sprite_scroll_16bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_16bit/Sprite_scroll_16bit.ino index 2ffbc531..f0cf1f42 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_16bit/Sprite_scroll_16bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_16bit/Sprite_scroll_16bit.ino @@ -126,7 +126,7 @@ void numberBox(int num, int x, int y) // Fill it with black img.fillSprite(TFT_BLACK); - // Draw a backgorund of 2 filled triangles + // Draw a background of 2 filled triangles img.fillTriangle( 0, 0, 0, 49, 40, 25, TFT_RED); img.fillTriangle( 79, 0, 79, 49, 40, 25, TFT_DARKGREEN); @@ -150,14 +150,14 @@ void numberBox(int num, int x, int y) // ######################################################################### -// Return a 16 bit rainbow colour +// Return a 16-bit rainbow colour // ######################################################################### unsigned int rainbow(byte value) { // Value is expected to be in range 0-127 // The value is converted to a spectrum colour from 0 = red through to 127 = blue - byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte red = 0; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino index dfdee88c..d79e4b8b 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino @@ -3,7 +3,7 @@ This sketch scrolls a 1 bit per pixel (1 bpp) Sprite. - In a 1 bit Sprite any colour except TFT_BLACK turns a pixel "ON" + In a 1-bit Sprite any colour except TFT_BLACK turns a pixel "ON" TFT_BLACK turns a pixel "OFF". ON and OFF pixels can be set to any two colours before @@ -24,7 +24,7 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 1 bit Sprite occupies (width * height)/8 bytes in RAM. + A 1-bit Sprite occupies (width * height)/8 bytes in RAM. */ diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_4bit/Sprite_scroll_4bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_4bit/Sprite_scroll_4bit.ino index eb063cae..b198c859 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_4bit/Sprite_scroll_4bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_4bit/Sprite_scroll_4bit.ino @@ -1,5 +1,5 @@ /* - Sketch to show scrolling of the graphics in 4 bit sprites. + Sketch to show scrolling of the graphics in 4-bit sprites. Scrolling in this way moves the pixels in a defined rectangle within the Sprite. By default the whole sprite is scrolled. The gap left by scrolling is filled with a defined colour. @@ -14,7 +14,7 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 4 bit Sprite occupies (width * height)/2 bytes in RAM. + A 4-bit Sprite occupies (width * height)/2 bytes in RAM. */ #include @@ -41,7 +41,7 @@ void setup() { tft.init(); tft.fillScreen(TFT_BLACK); - // Populate the palette table, table must have 16 entires + // Populate the palette table, table must have 16 entries palette[0] = TFT_BLACK; palette[1] = TFT_ORANGE; palette[2] = TFT_DARKGREEN; diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_8bit/Sprite_scroll_8bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_8bit/Sprite_scroll_8bit.ino index a843589f..551f8755 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_8bit/Sprite_scroll_8bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_8bit/Sprite_scroll_8bit.ino @@ -1,7 +1,7 @@ /* Display "flicker free" scrolling text and updating number - This sketch uses 8 bit colour sprites to save RAM. + This sketch uses 8-bit colour sprites to save RAM. Example for library: https://github.com/Bodmer/TFT_eSPI @@ -16,15 +16,15 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 16 bit colour Sprite occupies (2 * width * height) bytes. + A 16-bit colour Sprite occupies (2 * width * height) bytes. - An 8 bit colour Sprite occupies (width * height) bytes. + An 8-bit colour Sprite occupies (width * height) bytes. - On a ESP8266, 16 bit Sprite sizes up to 128 x 160 can be accommodated, + On a ESP8266, 16-bit Sprite sizes up to 128 x 160 can be accommodated, this size requires 128*160*2 bytes (40kBytes) of RAM. This sketch sets the colour depth to 8 bits so larger sprites can be - created. 8 bit colour sprites use half amount of RAM. If the colour + created. 8-bit colour sprites use half amount of RAM. If the colour depth is not specified then 16 bits is assumed. You need to make the sprite small enough to fit, with RAM spare for @@ -137,7 +137,7 @@ void numberBox(int num, int x, int y) // Fill it with black img.fillSprite(TFT_BLACK); - // Draw a backgorund of 2 filled triangles + // Draw a background of 2 filled triangles img.fillTriangle( 0, 0, 0, 49, 40, 25, TFT_RED); img.fillTriangle( 79, 0, 79, 49, 40, 25, TFT_DARKGREEN); @@ -161,14 +161,14 @@ void numberBox(int num, int x, int y) // ######################################################################### -// Return a 16 bit rainbow colour +// Return a 16-bit rainbow colour // ######################################################################### unsigned int rainbow(byte value) { // Value is expected to be in range 0-127 // The value is converted to a spectrum colour from 0 = red through to 127 = blue - byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte red = 0; // Red is the top 5 bits of a 16-bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino index 76fcfc63..d97d58b5 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino @@ -1,5 +1,5 @@ // This **ONLY** works for 1 bpp Sprites due to lack of bounds checking in the -// Sprite pushImage() function for 8 and 16 bit Sprites (it is on the TO DO list) +// Sprite pushImage() function for 8 and 16-bit Sprites (it is on the TO DO list) // Wrapping scroll example by Bodmer for the TFT_eSPI library diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo/Transparent_Sprite_Demo.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo/Transparent_Sprite_Demo.ino index 37615acd..e492ab68 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo/Transparent_Sprite_Demo.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo/Transparent_Sprite_Demo.ino @@ -12,12 +12,12 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 16 bit Sprite occupies (2 * width * height) bytes in RAM. + A 16-bit Sprite occupies (2 * width * height) bytes in RAM. On a ESP8266 Sprite sizes up to 126 x 160 can be accommodated, - this size requires 40kBytes of RAM for a 16 bit colour depth. + this size requires 40kBytes of RAM for a 16-bit colour depth. - When 8 bit colour depth sprites are created they occupy + When 8-bit colour depth sprites are created they occupy (width * height) bytes in RAM, so larger sprites can be created, or the RAM required is halved. */ @@ -76,7 +76,7 @@ void loop() { // ######################################################################### void drawStar(int x, int y, int star_color) { - // Create an 8 bit sprite 70x 80 pixels (uses 5600 bytes of RAM) + // Create an 8-bit sprite 70x 80 pixels (uses 5600 bytes of RAM) img.setColorDepth(8); img.createSprite(70, 80); @@ -113,7 +113,7 @@ void numberBox(int x, int y, float num ) #define IWIDTH 80 #define IHEIGHT 35 - // Create a 8 bit sprite 80 pixels wide, 35 high (2800 bytes of RAM needed) + // Create a 8-bit sprite 80 pixels wide, 35 high (2800 bytes of RAM needed) img.setColorDepth(8); img.createSprite(IWIDTH, IHEIGHT); diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo_4bit/Transparent_Sprite_Demo_4bit.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo_4bit/Transparent_Sprite_Demo_4bit.ino index c116ed4b..0840648c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo_4bit/Transparent_Sprite_Demo_4bit.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Sprite/Transparent_Sprite_Demo_4bit/Transparent_Sprite_Demo_4bit.ino @@ -1,5 +1,5 @@ /* - Sketch to show creation of a 4 bit sprite with a transparent + Sketch to show creation of a 4-bit sprite with a transparent background, then plot it on the TFT. The palette setup and palette update functions are also shown in this example. @@ -13,11 +13,11 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 4 bit Sprite occupies (width * height)/2 bytes in RAM. + A 4-bit Sprite occupies (width * height)/2 bytes in RAM. For example the "star" 70x80 Sprite uses 2800 bytes. */ -// This is the default palette for 4 bit colour sprites +// This is the default palette for 4-bit colour sprites // which is built into the library. You can create your // own palette (use a different array name!). The palette // is captured and stored in RAM by the Sprite class so a @@ -80,25 +80,25 @@ void loop() { // spr.createPalette(default_4bit_palette, 12); // After rendering a Sprite you can change the palette to increase the range of colours - // plotted to the screen to the full 16 bit set. + // plotted to the screen to the full 16-bit set. // Change palette colour 11 to violet spr.setPaletteColor(11, TFT_VIOLET); - uint16_t color15 = spr.getPaletteColor(15); // The 16 bit colour in a palette can be read back + uint16_t color15 = spr.getPaletteColor(15); // The 16-bit colour in a palette can be read back // Draw 50 sprites containing a "transparent" colour for (int i = 0; i < 50; i++) { int x = random(tft.width() - 70); int y = random(tft.height() - 80); - int c = random(15); // Random colour 0-14 (4 bit index into color map). Leave 15 for transparent. + int c = random(15); // Random colour 0-14 (4-bit index into color map). Leave 15 for transparent. drawStar(x, y, c); } delay(2000); - // Change the palette to a 16 bit grey scale colour + // Change the palette to a 16-bit grey scale colour for (uint8_t i = 0; i < 16; i++) { // (i*16+i) produces a value in range 0-255 for the RGB colours // Red Green Blue diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Colour_Test/Colour_Test.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Colour_Test/Colour_Test.ino index 185df6de..bdae2c5b 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Colour_Test/Colour_Test.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Colour_Test/Colour_Test.ino @@ -58,25 +58,26 @@ void setup(void) { tft.init(); tft.fillScreen(TFT_BLACK); - + tft.drawRect(0, 0, tft.width(), tft.height(), TFT_GREEN); + // Set "cursor" at top left corner of display (0,0) and select font 4 - tft.setCursor(0, 0, 4); + tft.setCursor(0, 4, 4); // Set the font colour to be white with a black background - tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.setTextColor(TFT_WHITE); // We can now plot text on screen using the "print" class - tft.println("Initialised default\n"); - tft.println("White text"); + tft.println(" Initialised default\n"); + tft.println(" White text"); - tft.setTextColor(TFT_RED, TFT_BLACK); - tft.println("Red text"); + tft.setTextColor(TFT_RED); + tft.println(" Red text"); - tft.setTextColor(TFT_GREEN, TFT_BLACK); - tft.println("Green text"); + tft.setTextColor(TFT_GREEN); + tft.println(" Green text"); - tft.setTextColor(TFT_BLUE, TFT_BLACK); - tft.println("Blue text"); + tft.setTextColor(TFT_BLUE); + tft.println(" Blue text"); delay(5000); @@ -87,22 +88,23 @@ void loop() { tft.invertDisplay( false ); // Where i is true or false tft.fillScreen(TFT_BLACK); - - tft.setCursor(0, 0, 4); + tft.drawRect(0, 0, tft.width(), tft.height(), TFT_GREEN); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.println("Invert OFF\n"); + tft.setCursor(0, 4, 4); - tft.println("White text"); + tft.setTextColor(TFT_WHITE); + tft.println(" Invert OFF\n"); + + tft.println(" White text"); - tft.setTextColor(TFT_RED, TFT_BLACK); - tft.println("Red text"); + tft.setTextColor(TFT_RED); + tft.println(" Red text"); - tft.setTextColor(TFT_GREEN, TFT_BLACK); - tft.println("Green text"); + tft.setTextColor(TFT_GREEN); + tft.println(" Green text"); - tft.setTextColor(TFT_BLUE, TFT_BLACK); - tft.println("Blue text"); + tft.setTextColor(TFT_BLUE); + tft.println(" Blue text"); delay(5000); @@ -111,22 +113,23 @@ void loop() { tft.invertDisplay( true ); // Where i is true or false tft.fillScreen(TFT_BLACK); - - tft.setCursor(0, 0, 4); + tft.drawRect(0, 0, tft.width(), tft.height(), TFT_GREEN); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.println("Invert ON\n"); + tft.setCursor(0, 4, 4); - tft.println("White text"); + tft.setTextColor(TFT_WHITE); + tft.println(" Invert ON\n"); + + tft.println(" White text"); - tft.setTextColor(TFT_RED, TFT_BLACK); - tft.println("Red text"); + tft.setTextColor(TFT_RED); + tft.println(" Red text"); - tft.setTextColor(TFT_GREEN, TFT_BLACK); - tft.println("Green text"); + tft.setTextColor(TFT_GREEN); + tft.println(" Green text"); - tft.setTextColor(TFT_BLUE, TFT_BLACK); - tft.println("Blue text"); + tft.setTextColor(TFT_BLUE); + tft.println(" Blue text"); delay(5000); } diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino index 93479f60..8b5c9f59 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -184,5 +184,5 @@ int8_t getPinName(int8_t pin) if (user.esp == 0x32F) return pin; - return -1; // Invalid pin + return pin; // Invalid pin } diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino index a856d696..4c8adbba 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino @@ -106,7 +106,7 @@ void loop() { frame.fillSprite(PAPER); - // Draw 8 bit grey-scale bitmap using Floyd-Steinberg dithering at x,y + // Draw 8-bit grey-scale bitmap using Floyd-Steinberg dithering at x,y // /File name x y //drawFSBmp("/TestCard.bmp", 0, 0); // 176 x 264 pixels diff --git a/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino b/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino index e52dbe07..414365d3 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino +++ b/trunk/Arduino/libraries/TFT_eSPI/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino @@ -27,14 +27,14 @@ SOFTWARE. Note: drawFSBmp() is a simplified function and does not handle all possible - BMP file header variants. It works OK with 8 bit per pixel grey-scale images + BMP file header variants. It works OK with 8-bit per pixel grey-scale images generated by MS Paint and IrfanView. */ // https://github.com/Bodmer/TFT_eSPI //==================================================================================== -// Draw an 8 bit grey-scale bitmap (*.BMP) on a Monochrome display using dithering +// Draw an 8-bit grey-scale bitmap (*.BMP) on a Monochrome display using dithering //==================================================================================== // Uses RAM for buffers (3 * width + 4) ( 532 bytes for 176 pixels) @@ -102,10 +102,10 @@ void drawFSBmp(const char *filename, int16_t x, int16_t y) { uint16_t padding = (4 - (w & 3)) & 3; // Calculate the BMP line padding - // Create an zero an 8 bit pixel line buffer + // Create an zero an 8-bit pixel line buffer uint8_t* lineBuffer = ( uint8_t*) calloc(w , sizeof(uint8_t)); - // Create a 16 bit signed line buffer for the quantisation error + // Create a 16-bit signed line buffer for the quantisation error // Diffusion spreads to x-1 and x+1 so w + 2 avoids a bounds check int16_t* qerrBuffer = ( int16_t*) calloc((w + 2)<<1, sizeof(uint8_t)); @@ -174,7 +174,7 @@ void drawFSBmp(const char *filename, int16_t x, int16_t y) { } //==================================================================================== -// Read a 16 bit value from the filing system +// Read a 16-bit value from the filing system //==================================================================================== uint16_t read16(fs::File &f) { uint16_t result; @@ -184,7 +184,7 @@ uint16_t read16(fs::File &f) { } //==================================================================================== -// Read a 32 bit value from the filing system +// Read a 32-bit value from the filing system //==================================================================================== uint32_t read32(fs::File &f) { uint32_t result; diff --git a/trunk/Arduino/libraries/TFT_eSPI/library.json b/trunk/Arduino/libraries/TFT_eSPI/library.json index 5bfa71cd..f590f3ec 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/library.json +++ b/trunk/Arduino/libraries/TFT_eSPI/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "2.5.0", + "version": "2.5.43", "keywords": "Arduino, tft, display, ttgo, LilyPi, WT32-SC01, ePaper, display, Pico, RP2040 Nano Connect, RP2040, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9481, ILI9486, ILI9488, ST7789, ST7796, RM68140, SSD1351, SSD1963, ILI9225, HX8357D, GC9A01, R61581", "description": "A TFT and ePaper (SPI or parallel interface) graphics library with optimisation for Raspberry Pi Pico, RP2040, ESP8266, ESP32 and STM32 processors", "repository": diff --git a/trunk/Arduino/libraries/TFT_eSPI/library.properties b/trunk/Arduino/libraries/TFT_eSPI/library.properties index 4b2db403..319d4ec6 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/library.properties +++ b/trunk/Arduino/libraries/TFT_eSPI/library.properties @@ -1,9 +1,9 @@ name=TFT_eSPI -version=2.5.0 +version=2.5.43 author=Bodmer maintainer=Bodmer sentence=TFT graphics library for Arduino processors with performance optimisation for RP2040, STM32, ESP8266 and ESP32 -paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI or 8/16 bit parallel. +paragraph=Supports TFT displays using drivers (ILI9341 etc.) that operate with hardware SPI or 8/16-bit parallel. category=Display url=https://github.com/Bodmer/TFT_eSPI architectures=* diff --git a/trunk/Arduino/libraries/TFT_eSPI/license.txt b/trunk/Arduino/libraries/TFT_eSPI/license.txt index 87db4c9d..e0b40d2c 100644 --- a/trunk/Arduino/libraries/TFT_eSPI/license.txt +++ b/trunk/Arduino/libraries/TFT_eSPI/license.txt @@ -94,9 +94,9 @@ graphics. In 2018 anti-aliased fonts were added along with a Processing font conversion sketch. -In 2019 the library was adapted to be able to use it with any 32 bit Arduino -compatible processor. It will run on 8 bit and 16 bit processors but will be -slow due to extensive use of 32 bit variables. +In 2019 the library was adapted to be able to use it with any 32-bit Arduino +compatible processor. It will run on 8-bit and 16-bit processors but will be +slow due to extensive use of 32-bit variables. Many of the example sketches are original work that contain code created for my own projects. For all the original code the FreeBSD licence applies @@ -105,7 +105,7 @@ and is compatible with the GNU GPL. vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvStartvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Software License Agreement (FreeBSD License) -Copyright (c) 2022 Bodmer (https://github.com/Bodmer) +Copyright (c) 2023 Bodmer (https://github.com/Bodmer) All rights reserved. diff --git a/trunk/Arduino/libraries/Ticker/README.md b/trunk/Arduino/libraries/Ticker/README.md index 51d25feb..08a5ee65 100644 --- a/trunk/Arduino/libraries/Ticker/README.md +++ b/trunk/Arduino/libraries/Ticker/README.md @@ -1,15 +1,15 @@ -# Arduino Ticker Library v3.1.x +# Arduino Ticker Library v4.x.x +**Advice: for use with ESP boards and mbed based Arduino boards like Arduino Nano RP2040 Connect and Raspberry Pi Pico (using the official Arduino core) the TickTwo library [https://github.com/sstaub/TickTwo](https://github.com/sstaub/TickTwo) is recommanded** The **Arduino Ticker Library** allows you to create easily Ticker callbacks, which can call a function in a predetermined interval. You can change the number of repeats of the callbacks, if repeats is 0 the ticker runs in endless mode. Works like a "thread", where a secondary function will run when necessary. The library use no interupts of the hardware timers and works with the **micros() / millis()** function. You are not (really) limited in the number of Tickers. -## New in v2.0 -- You can determine the number of repeats, instead of modes. -- The internal resolution is now **micros()**, this works with intervals up to 70 minutes. For longer intervals you can change the resolution to **millis()**. ``` Ticker tickerObject(callbackFunction, 1000, 0, MILLIS) ``` -- unified data types and smaller improvments +## New in v4.0 +- added get interval function +- added remaining function +- added support for functional callbacks, only for ARM and ESP devices, e.g.
"Examples/FunctionalARM/FunctionalARM.ino" -## New in v2.1 -- You can change the interval time to microseconds. ``` Ticker tickerObject(callbackFunction, 100, 0, MICROS_MICROS) // interval is now 100us``` -- smaller improvments +## New in v3.1 +- added set interval function ## New in v3.0 - radical simplified API @@ -17,8 +17,20 @@ The **Arduino Ticker Library** allows you to create easily Ticker callbacks, whi - deleted many set and get functions - if you need former functionality please use the version 2.1 -## New in v3.1 -- added interval function +## New in v2.1 +- You can change the interval time to microseconds. +```cpp +Ticker tickerObject(callbackFunction, 100, 0, MICROS_MICROS) // interval is now 100us +``` +- smaller improvments + +## New in v2.0 +- You can determine the number of repeats, instead of modes. +- The internal resolution is now **micros()**, this works with intervals up to 70 minutes. For longer intervals you can change the resolution to **millis()**. +```cpp +Ticker tickerObject(callbackFunction, 1000, 0, MILLIS) +``` +- unified data types and smaller improvments ## Installation @@ -31,22 +43,21 @@ The **Arduino Ticker Library** allows you to create easily Ticker callbacks, whi First, include the TimerObject to your project: -``` +```cpp #include "Ticker.h" ``` Now, you can create a new object in setup(): -``` +```cpp Ticker tickerObject(callbackFunction, 1000); tickerObject.start(); //start the ticker. ``` In your loop(), add: -``` -tickerObject.update(); //it will check the Ticker -and if necessary, it will run the callback function. +```cpp +tickerObject.update(); //it will check the Ticker and if necessary, it will run the callback function. ``` @@ -57,7 +68,7 @@ If you use delay(), the Ticker will be ignored! You cannot use delay() command w Complete example. Here we created five timers, you can run it and test the result in the Serial monitor and the on board LED. -``` +```cpp #include "Ticker.h" void printMessage(); @@ -70,7 +81,7 @@ bool ledState; int counterUS; Ticker timer1(printMessage, 0, 1); // once, immediately -Ticker timer2(printCounter, 1000, MILLIS); // internal resolution is milli seconds +Ticker timer2(printCounter, 1000, 0, MILLIS); // internal resolution is milli seconds Ticker timer3(printCountdown, 1000, 5); // 5 times, every second Ticker timer4(blink, 500); // changing led every 500ms Ticker timer5(printCountUS, 100, 0, MICROS_MICROS); // the interval time is 100us and the internal resolution is micro seconds @@ -128,48 +139,206 @@ void printCountUS() { ## Documentation ### States -STOPPED / RUNNING / PAUSED -### Constructors / Destructor +```cpp +enum status_t { + STOPPED, + RUNNING, + PAUSED + }; +``` + +### Constructors + +```cpp +Ticker::Ticker(fptr callback, uint32_t timer, uint16_t repeats, interval_t mode) +``` -**Ticker(fptr callback, uint32_t timer, uint32_t repeats = 0, resolution_t resolution = MICROS)**
Creates a Ticker object -- parameter callback for the function name you want to call -- parameter timer sets the interval time in ms or us when using MICROS_MICROS with the resolution parameter -- parameter repeats sets the number of repeats the callback should executed, 0 is endless -- parameter resolution sets the internal resolution of the Ticker, it can MICROS, MICROS_MICROS or MILLIS -**~Ticker()**
+- **callback** for the function name you want to call +- **timer** set the interval time in ms or us depending from mode +- **repeats** set the number of repeats the callback should executed, 0 is endless (default) +- **mode** set the interval resolution to MILLIS, MICROS_MICROS or MICROS (default) + +**Example** + +```cpp +Ticker timer(blink, 1000); // calls function blink() every second, internal resolution is micros, running endless +Ticker timer(blink, 1000, 5); // calls function blink() every second, internal resolution is micros, only 5 repeats +Ticker timer(blink, 1000, 0, MILLIS); // calls function blink() every second, internal resolution is millis, running endless +Ticker timer(blink, 1000, 0, MICROS_MICROS); // calls function blink() every 1000 microsecond, internal resolution is micros, running endless +``` + +### Destructor + +```cpp +Ticker::~Ticker() +``` Destructor for Ticker object - -### Functions -**void start()**
+## Class Functions + +### Ticker Start + +```cpp +void Ticker::start() +``` + Start the Ticker. Will count the interval from the moment that you start it. If it is paused, it will restart the Ticker. -**void resume()**
-Resume the Ticker. If not started, it will start it. If paused, it will resume it. For example, in a Ticker of 5 seconds, if it was paused at 3 seconds, the resume continues at 3 seconds. Start will set passed time to 0 and restart until it get 5 seconds. +**Example** + +```cpp +timer.start(); +``` + +### Ticker Resume + +```cpp +void Ticker::resume() +``` + +Resume the Ticker. If not started, it will start it. If paused, it will resume it. For example, in a Ticker of 5 seconds, if it was paused in 3 seconds, the resume in continue in 3 seconds. Start will set passed time to 0 and restart until get 5 seconds. + +**Example** + +```cpp +timer.resume(); +``` + +### Ticker Pause + +```cpp +void Ticker::pause() +``` -**void pause()**
Pause the Ticker, so you can resume it. -**void stop()**
+**Example** + +```cpp +timer.pause(); +``` + +### Ticker Stop + +```cpp +void Ticker::stop() +``` + Stop the Ticker. -**void update()**
-Must called in the loop(), it will check the Ticker, and if necessary, will run the callback +**Example** -**void interval(uint32_t timer)**
-Changes the interval time of the Ticker. +```cpp +timer.stop(); +``` + +### Ticker Update + +```cpp +void Ticker::update() +``` + +Must to be called in the main while() loop, it will check the Ticker, and if necessary, will run the callback. + +**Example** + +```cpp +while(1) { + timer.update(); +1. } +``` + +### Ticker set Interval Time + +```cpp +void Ticker::interval(uint32_t timer) +``` + +Changes the interval time of the Ticker. Depending from the mode it can millis or micro seconds. + +- **timer** set the interval time in ms or us depending from mode + + +**Example** + +```cpp +timer.interval(500); // new interval time +``` + +### Ticker get Interval Time + +```cpp +uint32_t Ticker::interval() +``` + +Get the interval time of the Ticker. Depending from the mode it can millis or micro seconds. + +**Example** + +```cpp +uint32_t intervalTime; +intervalTime = timer.interval(); // get the interval time +``` + +### Ticker State + +```cpp +status_t Ticker::state() +``` -**status_t state()**
Returns the state of the Ticker. -**uint32_t elapsed()**
-Returns the time passed since the last tick, ms or us depending from the resolution. +**Example** -**uint32_t counter()**
-Returns the number of executed callbacks. +```cpp +status_t status; +status = timer.state(); +``` +### Ticker Elapsed Time +```cpp +uint32_t Ticker::elapsed() +``` +Returns the time passed since the last tick in ms or us depending on mode. + +**Example** + +```cpp +uint32_t elapse; +elapse = timer.elapsed(); +``` + +### Ticker Remaining Time + +```cpp +uint32_t Ticker::remaining() +``` + +Returns the remaining time to the next tick in ms or us depending on mode. + +**Example** + +```cpp +uint32_t remain; +remain = timer.remaining(); +``` + +### Ticker Counter + +```cpp +uint32_t Ticker::counter() +``` + +Get the number of executed callbacks. + +**Example** + +```cpp +uint32_t count; +count = timer.counter(); +``` diff --git a/trunk/Arduino/libraries/Ticker/Ticker.cpp b/trunk/Arduino/libraries/Ticker/Ticker.cpp index 5b359c6e..10469793 100644 --- a/trunk/Arduino/libraries/Ticker/Ticker.cpp +++ b/trunk/Arduino/libraries/Ticker/Ticker.cpp @@ -73,36 +73,39 @@ void Ticker::update() { } bool Ticker::tick() { - if (!enabled) return false; - if (resolution == MILLIS) { - if ((millis() - lastTime) >= timer) { - lastTime = millis(); - if (repeat - counts == 1) enabled = false; - counts++; - return true; + if (!enabled) return false; + uint32_t currentTime = (resolution == MILLIS) ? millis() : micros(); + if ((currentTime - lastTime) >= timer) { + lastTime = currentTime; + if (repeat - counts == 1 && counts != 0xFFFFFFFF) { + enabled = false; + status = STOPPED; } - } - else { - if ((micros() - lastTime) >= timer) { - lastTime = micros(); - if (repeat - counts == 1) enabled = false; - counts++; - return true; - } - } + counts++; + return true; + } return false; } void Ticker::interval(uint32_t timer) { - if (resolution == MICROS) timer = timer * 1000; + if (resolution == MICROS) timer *= 1000; this->timer = timer; } +uint32_t Ticker::interval() { + if (resolution == MILLIS) return timer / 1000; + else return timer; + } + uint32_t Ticker::elapsed() { if (resolution == MILLIS) return millis() - lastTime; else return micros() - lastTime; } +uint32_t Ticker::remaining() { + return timer - elapsed(); + } + status_t Ticker::state() { return status; } diff --git a/trunk/Arduino/libraries/Ticker/Ticker.h b/trunk/Arduino/libraries/Ticker/Ticker.h index 654d97bf..3e77a63c 100644 --- a/trunk/Arduino/libraries/Ticker/Ticker.h +++ b/trunk/Arduino/libraries/Ticker/Ticker.h @@ -33,7 +33,11 @@ * @param MILLIS set the resolution to millis, for longer cycles over 70 minutes * */ -enum resolution_t {MICROS, MILLIS, MICROS_MICROS}; +enum resolution_t { + MICROS, + MILLIS, + MICROS_MICROS + }; /** Ticker status * @@ -42,9 +46,18 @@ enum resolution_t {MICROS, MILLIS, MICROS_MICROS}; * @param PAUSED ticker is paused * */ -enum status_t {STOPPED, RUNNING, PAUSED}; +enum status_t { + STOPPED, + RUNNING, + PAUSED}; +#if defined(__arm__) || defined(ESP8266) || defined(ESP32) +#include +using fptr = std::function; +#else typedef void (*fptr)(); +#endif + class Ticker { @@ -97,6 +110,13 @@ public: */ void interval(uint32_t timer); + /** + * @brief get the interval time + * + * @returns the interval time + */ + uint32_t interval(); + /** actual ellapsed time * * @returns the elapsed time after the last tick @@ -104,6 +124,13 @@ public: */ uint32_t elapsed(); + /** time remaining to the next tick + * + * @returns the remaining time to the next tick in ms or us depending from mode + * + */ + uint32_t remaining(); + /** get the state of the ticker * * @returns the state of the ticker: STOPPED, RUNNING or PAUSED diff --git a/trunk/Arduino/libraries/Ticker/examples/Ticker/Ticker.ino b/trunk/Arduino/libraries/Ticker/examples/Ticker/Ticker.ino index 348c795d..e7706a72 100644 --- a/trunk/Arduino/libraries/Ticker/examples/Ticker/Ticker.ino +++ b/trunk/Arduino/libraries/Ticker/examples/Ticker/Ticker.ino @@ -10,7 +10,7 @@ bool ledState; int counterUS; Ticker timer1(printMessage, 0, 1); -Ticker timer2(printCounter, 1000, MILLIS); +Ticker timer2(printCounter, 1000, 0, MILLIS); Ticker timer3(printCountdown, 1000, 5); Ticker timer4(blink, 500); Ticker timer5(printCountUS, 100, 0, MICROS_MICROS); diff --git a/trunk/Arduino/libraries/Ticker/keywords.txt b/trunk/Arduino/libraries/Ticker/keywords.txt index 41252b3f..c9aca803 100644 --- a/trunk/Arduino/libraries/Ticker/keywords.txt +++ b/trunk/Arduino/libraries/Ticker/keywords.txt @@ -8,3 +8,4 @@ interval KEYWORD2 state KEYWORD2 counter KEYWORD2 elapsed KEYWORD2 +remaining KEYWORD2 diff --git a/trunk/Arduino/libraries/Ticker/library.json b/trunk/Arduino/libraries/Ticker/library.json index 797ccda9..ee1bc10c 100644 --- a/trunk/Arduino/libraries/Ticker/library.json +++ b/trunk/Arduino/libraries/Ticker/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/sstaub/Ticker" }, - "version": "3.2.0", + "version": "4.4.0", "frameworks": "arduino", "platforms": "*" } diff --git a/trunk/Arduino/libraries/Ticker/library.properties b/trunk/Arduino/libraries/Ticker/library.properties index 54b3473d..97e14444 100644 --- a/trunk/Arduino/libraries/Ticker/library.properties +++ b/trunk/Arduino/libraries/Ticker/library.properties @@ -1,5 +1,5 @@ name=Ticker -version=3.2.0 +version=4.4.0 author=Stefan Staub maintainer=Stefan Staub sentence=A library for creating Tickers which can call repeating functions. Replaces delay() with non-blocking functions. diff --git a/trunk/Arduino/libraries/TimerOne/README.md b/trunk/Arduino/libraries/TimerOne/README.md index bbc3e03c..0066032d 100644 --- a/trunk/Arduino/libraries/TimerOne/README.md +++ b/trunk/Arduino/libraries/TimerOne/README.md @@ -1,9 +1,9 @@ -#TimerOne Library# +#TimerOne Library Paul Stoffregen's modified TimerOne. This version provides 2 main benefits: -1: Optimized inline functions - much faster for the most common usage -2: Support for more boards +1: Optimized inline functions - much faster for the most common usage +2: Support for more boards (including ATTiny85 except for the PWM functionality) http://www.pjrc.com/teensy/td_libs_TimerOne.html diff --git a/trunk/Arduino/libraries/TimerOne/TimerOne.cpp b/trunk/Arduino/libraries/TimerOne/TimerOne.cpp index e8c286f3..3c283902 100644 --- a/trunk/Arduino/libraries/TimerOne/TimerOne.cpp +++ b/trunk/Arduino/libraries/TimerOne/TimerOne.cpp @@ -6,6 +6,7 @@ * Modified Oct 2009 by Dan Clemens to work with timer1 of the ATMega1280 or Arduino Mega * Modified April 2012 by Paul Stoffregen * Modified again, June 2014 by Paul Stoffregen + * Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality * * This is free software. You can redistribute it and/or modify it under * the terms of Creative Commons Attribution 3.0 United States License. @@ -20,16 +21,20 @@ TimerOne Timer1; // preinstatiate unsigned short TimerOne::pwmPeriod = 0; unsigned char TimerOne::clockSelectBits = 0; -void (*TimerOne::isrCallback)() = NULL; +void (*TimerOne::isrCallback)() = TimerOne::isrDefaultUnused; // interrupt service routine that wraps a user defined function supplied by attachInterrupt -#if defined(__AVR__) +#if defined (__AVR_ATtiny85__) +ISR(TIMER1_COMPA_vect) +{ + Timer1.isrCallback(); +} +#elif defined(__AVR__) ISR(TIMER1_OVF_vect) { Timer1.isrCallback(); } - -#elif defined(__arm__) && defined(CORE_TEENSY) +#elif defined(__arm__) && defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL)) void ftm1_isr(void) { uint32_t sc = FTM1_SC; @@ -40,5 +45,15 @@ void ftm1_isr(void) #endif Timer1.isrCallback(); } +#elif defined(__arm__) && defined(TEENSYDUINO) && defined(__IMXRT1062__) +void TimerOne::isr(void) +{ + FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF; + Timer1.isrCallback(); +} #endif + +void TimerOne::isrDefaultUnused() +{ +} diff --git a/trunk/Arduino/libraries/TimerOne/TimerOne.h b/trunk/Arduino/libraries/TimerOne/TimerOne.h index bcd144be..99e4502a 100644 --- a/trunk/Arduino/libraries/TimerOne/TimerOne.h +++ b/trunk/Arduino/libraries/TimerOne/TimerOne.h @@ -5,6 +5,7 @@ * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop * Modified April 2012 by Paul Stoffregen - portable to other AVR chips, use inline functions * Modified again, June 2014 by Paul Stoffregen - support Teensy 3.x & even more AVR chips + * Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality * * * This is free software. You can redistribute it and/or modify it under @@ -24,9 +25,13 @@ #endif #include "config/known_16bit_timers.h" - +#if defined (__AVR_ATtiny85__) +#define TIMER1_RESOLUTION 256UL // Timer1 is 8 bit +#elif defined(__AVR__) #define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit - +#else +#define TIMER1_RESOLUTION 65536UL // assume 16 bits for non-AVR chips +#endif // Placing nearly all the code in this .h file allows the functions to be // inlined by the compiler. In the very common case with constant values @@ -37,8 +42,140 @@ class TimerOne { +#if defined (__AVR_ATtiny85__) + public: + //**************************** + // Configuration + //**************************** + void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { + TCCR1 = _BV(CTC1); //clear timer1 when it matches the value in OCR1C + TIMSK |= _BV(OCIE1A); //enable interrupt when OCR1A matches the timer value + setPeriod(microseconds); + } + void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { + const unsigned long cycles = microseconds * ratio; + if (cycles < TIMER1_RESOLUTION) { + clockSelectBits = _BV(CS10); + pwmPeriod = cycles; + } else + if (cycles < TIMER1_RESOLUTION * 2UL) { + clockSelectBits = _BV(CS11); + pwmPeriod = cycles / 2; + } else + if (cycles < TIMER1_RESOLUTION * 4UL) { + clockSelectBits = _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 4; + } else + if (cycles < TIMER1_RESOLUTION * 8UL) { + clockSelectBits = _BV(CS12); + pwmPeriod = cycles / 8; + } else + if (cycles < TIMER1_RESOLUTION * 16UL) { + clockSelectBits = _BV(CS12) | _BV(CS10); + pwmPeriod = cycles / 16; + } else + if (cycles < TIMER1_RESOLUTION * 32UL) { + clockSelectBits = _BV(CS12) | _BV(CS11); + pwmPeriod = cycles / 32; + } else + if (cycles < TIMER1_RESOLUTION * 64UL) { + clockSelectBits = _BV(CS12) | _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 64UL; + } else + if (cycles < TIMER1_RESOLUTION * 128UL) { + clockSelectBits = _BV(CS13); + pwmPeriod = cycles / 128; + } else + if (cycles < TIMER1_RESOLUTION * 256UL) { + clockSelectBits = _BV(CS13) | _BV(CS10); + pwmPeriod = cycles / 256; + } else + if (cycles < TIMER1_RESOLUTION * 512UL) { + clockSelectBits = _BV(CS13) | _BV(CS11); + pwmPeriod = cycles / 512; + } else + if (cycles < TIMER1_RESOLUTION * 1024UL) { + clockSelectBits = _BV(CS13) | _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 1024; + } else + if (cycles < TIMER1_RESOLUTION * 2048UL) { + clockSelectBits = _BV(CS13) | _BV(CS12); + pwmPeriod = cycles / 2048; + } else + if (cycles < TIMER1_RESOLUTION * 4096UL) { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS10); + pwmPeriod = cycles / 4096; + } else + if (cycles < TIMER1_RESOLUTION * 8192UL) { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11); + pwmPeriod = cycles / 8192; + } else + if (cycles < TIMER1_RESOLUTION * 16384UL) { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 16384; + } else { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10); + pwmPeriod = TIMER1_RESOLUTION - 1; + } + OCR1A = pwmPeriod; + OCR1C = pwmPeriod; + TCCR1 = _BV(CTC1) | clockSelectBits; + } + + //**************************** + // Run Control + //**************************** + void start() __attribute__((always_inline)) { + TCCR1 = 0; + TCNT1 = 0; + resume(); + } + void stop() __attribute__((always_inline)) { + TCCR1 = _BV(CTC1); + } + void restart() __attribute__((always_inline)) { + start(); + } + void resume() __attribute__((always_inline)) { + TCCR1 = _BV(CTC1) | clockSelectBits; + } + + //**************************** + // PWM outputs + //**************************** + //Not implemented yet for ATTiny85 + //TO DO + + //**************************** + // Interrupt Function + //**************************** + void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { + isrCallback = isr; + TIMSK |= _BV(OCIE1A); + } + void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) { + if(microseconds > 0) setPeriod(microseconds); + attachInterrupt(isr); + } + void detachInterrupt() __attribute__((always_inline)) { + //TIMSK = 0; // Timer 0 and Timer 1 both use TIMSK register so setting it to 0 will override settings for Timer1 as well + TIMSK &= ~_BV(OCIE1A); + } + static void (*isrCallback)(); + static void isrDefaultUnused(); -#if defined(__AVR__) + private: + static unsigned short pwmPeriod; + static unsigned char clockSelectBits; + static const byte ratio = (F_CPU)/ ( 1000000 ); + +#elif defined(__AVR__) + +#if defined (__AVR_ATmega8__) + //in some io definitions for older microcontrollers TIMSK is used instead of TIMSK1 + #define TIMSK1 TIMSK +#endif + public: //**************************** // Configuration @@ -49,7 +186,7 @@ class TimerOne setPeriod(microseconds); } void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { - const unsigned long cycles = (F_CPU / 2000000) * microseconds; + const unsigned long cycles = ((F_CPU/100000 * microseconds) / 20); if (cycles < TIMER1_RESOLUTION) { clockSelectBits = _BV(CS10); pwmPeriod = cycles; @@ -138,6 +275,7 @@ class TimerOne //**************************** // Interrupt Function //**************************** + void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { isrCallback = isr; TIMSK1 = _BV(TOIE1); @@ -150,6 +288,7 @@ class TimerOne TIMSK1 = 0; } static void (*isrCallback)(); + static void isrDefaultUnused(); private: // properties @@ -161,7 +300,7 @@ class TimerOne -#elif defined(__arm__) && defined(CORE_TEENSY) +#elif defined(__arm__) && defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL)) #if defined(KINETISK) #define F_TIMER F_BUS @@ -169,6 +308,14 @@ class TimerOne #define F_TIMER (F_PLL/2) #endif +// Use only 15 bit resolution. From K66 reference manual, 45.5.7 page 1200: +// The CPWM pulse width (duty cycle) is determined by 2 x (CnV - CNTIN) and the +// period is determined by 2 x (MOD - CNTIN). See the following figure. MOD must be +// kept in the range of 0x0001 to 0x7FFF because values outside this range can produce +// ambiguous results. +#undef TIMER1_RESOLUTION +#define TIMER1_RESOLUTION 32768 + public: //**************************** // Configuration @@ -178,6 +325,53 @@ class TimerOne } void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { const unsigned long cycles = (F_TIMER / 2000000) * microseconds; + // A much faster if-else + // This is like a binary serch tree and no more than 3 conditions are evaluated. + // I haven't checked if this becomes significantly longer ASM than the simple ladder. + // It looks very similar to the ladder tho: same # of if's and else's + + /* + // This code does not work properly in all cases :( + // https://github.com/PaulStoffregen/TimerOne/issues/17 + if (cycles < TIMER1_RESOLUTION * 16) { + if (cycles < TIMER1_RESOLUTION * 4) { + if (cycles < TIMER1_RESOLUTION) { + clockSelectBits = 0; + pwmPeriod = cycles; + }else{ + clockSelectBits = 1; + pwmPeriod = cycles >> 1; + } + }else{ + if (cycles < TIMER1_RESOLUTION * 8) { + clockSelectBits = 3; + pwmPeriod = cycles >> 3; + }else{ + clockSelectBits = 4; + pwmPeriod = cycles >> 4; + } + } + }else{ + if (cycles > TIMER1_RESOLUTION * 64) { + if (cycles > TIMER1_RESOLUTION * 128) { + clockSelectBits = 7; + pwmPeriod = TIMER1_RESOLUTION - 1; + }else{ + clockSelectBits = 7; + pwmPeriod = cycles >> 7; + } + } + else{ + if (cycles > TIMER1_RESOLUTION * 32) { + clockSelectBits = 6; + pwmPeriod = cycles >> 6; + }else{ + clockSelectBits = 5; + pwmPeriod = cycles >> 5; + } + } + } + */ if (cycles < TIMER1_RESOLUTION) { clockSelectBits = 0; pwmPeriod = cycles; @@ -213,6 +407,7 @@ class TimerOne clockSelectBits = 7; pwmPeriod = TIMER1_RESOLUTION - 1; } + uint32_t sc = FTM1_SC; FTM1_SC = 0; FTM1_MOD = pwmPeriod; @@ -287,6 +482,7 @@ class TimerOne NVIC_DISABLE_IRQ(IRQ_FTM1); } static void (*isrCallback)(); + static void isrDefaultUnused(); private: // properties @@ -295,6 +491,129 @@ class TimerOne #undef F_TIMER +#elif defined(__arm__) && defined(TEENSYDUINO) && defined(__IMXRT1062__) + + public: + //**************************** + // Configuration + //**************************** + void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { + setPeriod(microseconds); + } + void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { + uint32_t period = (float)F_BUS_ACTUAL * (float)microseconds * 0.0000005f; + uint32_t prescale = 0; + while (period > 32767) { + period = period >> 1; + if (++prescale > 7) { + prescale = 7; // when F_BUS is 150 MHz, longest + period = 32767; // period is 55922 us (~17.9 Hz) + break; + } + } + //Serial.printf("setPeriod, period=%u, prescale=%u\n", period, prescale); + FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8); // logic high = fault + FLEXPWM1_FSTS0 = 0x0008; // clear fault status + FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8); + FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP; + FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale); + FLEXPWM1_SM3INIT = -period; + FLEXPWM1_SM3VAL0 = 0; + FLEXPWM1_SM3VAL1 = period; + FLEXPWM1_SM3VAL2 = 0; + FLEXPWM1_SM3VAL3 = 0; + FLEXPWM1_SM3VAL4 = 0; + FLEXPWM1_SM3VAL5 = 0; + FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8); + pwmPeriod = period; + } + //**************************** + // Run Control + //**************************** + void start() __attribute__((always_inline)) { + stop(); + // TODO: how to force counter back to zero? + resume(); + } + void stop() __attribute__((always_inline)) { + FLEXPWM1_MCTRL &= ~FLEXPWM_MCTRL_RUN(8); + } + void restart() __attribute__((always_inline)) { + start(); + } + void resume() __attribute__((always_inline)) { + FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_RUN(8); + } + + //**************************** + // PWM outputs + //**************************** + void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) { + if (duty > 1023) duty = 1023; + int dutyCycle = (pwmPeriod * duty) >> 10; + //Serial.printf("setPwmDuty, period=%u\n", dutyCycle); + if (pin == TIMER1_A_PIN) { + FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8); + FLEXPWM1_SM3VAL5 = dutyCycle; + FLEXPWM1_SM3VAL4 = -dutyCycle; + FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8); + } else if (pin == TIMER1_B_PIN) { + FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8); + FLEXPWM1_SM3VAL3 = dutyCycle; + FLEXPWM1_SM3VAL2 = -dutyCycle; + FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8); + } + } + void pwm(char pin, unsigned int duty) __attribute__((always_inline)) { + setPwmDuty(pin, duty); + if (pin == TIMER1_A_PIN) { + FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMB_EN(8); + IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01 = 6; // pin 7 FLEXPWM1_PWM3_B + } else if (pin == TIMER1_B_PIN) { + FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(8); + IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 6; // pin 8 FLEXPWM1_PWM3_A + } + } + void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) { + if (microseconds > 0) setPeriod(microseconds); + pwm(pin, duty); + } + void disablePwm(char pin) __attribute__((always_inline)) { + if (pin == TIMER1_A_PIN) { + IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01 = 5; // pin 7 FLEXPWM1_PWM3_B + FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMB_EN(8); + } else if (pin == TIMER1_B_PIN) { + IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 5; // pin 8 FLEXPWM1_PWM3_A + FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMA_EN(8); + } + } + //**************************** + // Interrupt Function + //**************************** + void attachInterrupt(void (*f)()) __attribute__((always_inline)) { + isrCallback = f; + attachInterruptVector(IRQ_FLEXPWM1_3, &isr); + FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF; + FLEXPWM1_SM3INTEN = FLEXPWM_SMINTEN_RIE; + NVIC_ENABLE_IRQ(IRQ_FLEXPWM1_3); + } + void attachInterrupt(void (*f)(), unsigned long microseconds) __attribute__((always_inline)) { + if(microseconds > 0) setPeriod(microseconds); + attachInterrupt(f); + } + void detachInterrupt() __attribute__((always_inline)) { + NVIC_DISABLE_IRQ(IRQ_FLEXPWM1_3); + FLEXPWM1_SM3INTEN = 0; + } + static void isr(void); + static void (*isrCallback)(); + static void isrDefaultUnused(); + + private: + // properties + static unsigned short pwmPeriod; + static unsigned char clockSelectBits; + #endif }; diff --git a/trunk/Arduino/libraries/TimerOne/config/known_16bit_timers.h b/trunk/Arduino/libraries/TimerOne/config/known_16bit_timers.h index 397381d2..ec93a45b 100644 --- a/trunk/Arduino/libraries/TimerOne/config/known_16bit_timers.h +++ b/trunk/Arduino/libraries/TimerOne/config/known_16bit_timers.h @@ -39,7 +39,7 @@ #define TIMER1_B_PIN 4 #define TIMER1_ICP_PIN 4 -// Teensy 3.1 +// Teensy 3.1 / Teensy 3.2 // #elif defined(__MK20DX256__) #define TIMER1_A_PIN 3 @@ -48,7 +48,17 @@ #define TIMER3_A_PIN 32 #define TIMER3_B_PIN 25 #define TIMER3_ICP_PIN 32 - + +// Teensy 3.5 / Teensy 3.6 +// +#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) + #define TIMER1_A_PIN 3 + #define TIMER1_B_PIN 4 + #define TIMER1_ICP_PIN 4 + #define TIMER3_A_PIN 29 + #define TIMER3_B_PIN 30 + #define TIMER3_ICP_PIN 29 + // Teensy-LC // #elif defined(__MKL26Z64__) @@ -59,12 +69,19 @@ #define TIMER3_B_PIN 4 #define TIMER3_ICP_PIN 4 +// Teensy 4.0 +// +#elif defined(__IMXRT1062__) + #define TIMER1_A_PIN 7 + #define TIMER1_B_PIN 8 + #define TIMER3_A_PIN 9 + #define TIMER3_B_PIN 6 + // Arduino Mega // #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #define TIMER1_A_PIN 11 #define TIMER1_B_PIN 12 - #define TIMER1_C_PIN 13 #define TIMER3_A_PIN 5 #define TIMER3_B_PIN 2 #define TIMER3_C_PIN 3 @@ -91,12 +108,41 @@ // Uno, Duemilanove, LilyPad, etc // -#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega328P__) +#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega8__) #define TIMER1_A_PIN 9 #define TIMER1_B_PIN 10 #define TIMER1_ICP_PIN 8 #define TIMER1_CLK_PIN 5 +// Minicore generic +// +#elif defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168PB__) + #define TIMER1_A_PIN 9 + #define TIMER1_B_PIN 10 + #define TIMER1_ICP_PIN 8 + #define TIMER1_CLK_PIN 5 +#elif defined(__AVR_ATmega328PB__) + #define TIMER1_A_PIN 9 + #define TIMER1_B_PIN 10 + #define TIMER1_ICP_PIN 8 + #define TIMER1_CLK_PIN 5 + #define TIMER3_A_PIN 0 + #define TIMER3_B_PIN 2 + #define TIMER3_ICP_PIN 25 + #define TIMER3_CLK_PIN 26 + #define TIMER4_A_PIN 1 + #define TIMER4_B_PIN 2 + #define TIMER4_ICP_PIN 23 + #define TIMER4_CLK_PIN 24 + +// attiny167 +// +#elif defined (__AVR_ATtiny167__) + #define TIMER1_A_PIN 14 + #define TIMER1_B_PIN 11 + //#define TIMER1_ICP_PIN 8 + //#define TIMER1_CLK_PIN 5 + // Sanguino // #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) @@ -128,7 +174,7 @@ // Mighty-1284 - Maniacbug // -#elif defined(__AVR_ATmega1284P__) +#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__) #define TIMER1_A_PIN 12 // PD5 #define TIMER1_B_PIN 13 // PD4 #define TIMER1_ICP_PIN 14 // PD6 diff --git a/trunk/Arduino/libraries/TimerOne/library.json b/trunk/Arduino/libraries/TimerOne/library.json index 2a928d38..fac69fe4 100644 --- a/trunk/Arduino/libraries/TimerOne/library.json +++ b/trunk/Arduino/libraries/TimerOne/library.json @@ -1,7 +1,7 @@ { "name": "TimerOne", "keywords": "timer", - "description": "Allow to use the built-in 16 bit Timer1", + "description": "Allow to use the built-in Timer1", "repository": { "type": "git", diff --git a/trunk/Arduino/libraries/TimerOne/library.properties b/trunk/Arduino/libraries/TimerOne/library.properties index 6cf2c425..cae8a9ae 100644 --- a/trunk/Arduino/libraries/TimerOne/library.properties +++ b/trunk/Arduino/libraries/TimerOne/library.properties @@ -1,6 +1,6 @@ name=TimerOne -version=1.1 -author=Jesse Tane, Jérôme Despatis, Michael Polli, Dan Clemens, Paul Stoffregen +version=1.1.1 +author=Stoyko Dimitrov, Jesse Tane, Jérôme Despatis, Michael Polli, Dan Clemens, Paul Stoffregen maintainer=Paul Stoffregen sentence=Use hardware Timer1 for finer PWM control and/or running an periodic interrupt function paragraph=