{"id":13893881,"url":"https://github.com/RobTillaart/FastShiftOut","last_synced_at":"2025-07-17T08:31:20.621Z","repository":{"id":45366383,"uuid":"255623939","full_name":"RobTillaart/FastShiftOut","owner":"RobTillaart","description":"Arduino library for (AVR) optimized shiftOut  - e.g. 74HC595","archived":false,"fork":false,"pushed_at":"2024-11-01T13:04:31.000Z","size":47,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T22:02:49.299Z","etag":null,"topics":["74hc595","arduino","shift"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobTillaart.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"RobTillaart","custom":"https://www.paypal.me/robtillaart"}},"created_at":"2020-04-14T13:57:30.000Z","updated_at":"2025-03-29T22:11:10.000Z","dependencies_parsed_at":"2023-02-12T17:30:26.921Z","dependency_job_id":"c8e756ff-b37c-4fd1-8f26-50670d16fb91","html_url":"https://github.com/RobTillaart/FastShiftOut","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/RobTillaart/FastShiftOut","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastShiftOut","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastShiftOut/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastShiftOut/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastShiftOut/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobTillaart","download_url":"https://codeload.github.com/RobTillaart/FastShiftOut/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastShiftOut/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265585295,"owners_count":23792714,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["74hc595","arduino","shift"],"created_at":"2024-08-06T18:01:18.894Z","updated_at":"2025-07-17T08:31:20.323Z","avatar_url":"https://github.com/RobTillaart.png","language":"C++","funding_links":["https://github.com/sponsors/RobTillaart","https://www.paypal.me/robtillaart"],"categories":["C++"],"sub_categories":[],"readme":"\n[![Arduino CI](https://github.com/RobTillaart/FastShiftOut/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)\n[![Arduino-lint](https://github.com/RobTillaart/FastShiftOut/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/FastShiftOut/actions/workflows/arduino-lint.yml)\n[![JSON check](https://github.com/RobTillaart/FastShiftOut/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/FastShiftOut/actions/workflows/jsoncheck.yml)\n[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/FastShiftOut.svg)](https://github.com/RobTillaart/FastShiftOut/issues)\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/FastShiftOut/blob/master/LICENSE)\n[![GitHub release](https://img.shields.io/github/release/RobTillaart/FastShiftOut.svg?maxAge=3600)](https://github.com/RobTillaart/FastShiftOut/releases)\n[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/FastShiftOut.svg)](https://registry.platformio.org/libraries/robtillaart/FastShiftOut)\n\n\n# FastShiftOut\n\nArduino library for **AVR** optimized shiftOut - e.g. 74HC595.\n\n\n## Description\n\nFastShiftOut is a class that has optimized code (**AVR** only) to shift out data faster \nthan the default provided **shiftOut()** function.\nIt speeds up the shift using low level ports and masks. These are predetermined\nin the constructor of the FastShiftOut object.\n\nIf not an **ARDUINO_ARCH_AVR** or **ARDUINO_ARCH_MEGAAVR** the class falls back \nto the default shiftOut() implementation. \n\nThe library allows to set (and get) the bitOrder and apply this to multiple write()\ncalls. It also provide access to **writeLSBFIRST()** and **writeMSBFIRST()** which \nare the low level workers and most optimized code (so far).\n\nThe library provides wrapper functions to write multi-byte variables. \nThese are write16(), write24(), write32() and write(array, size).\nThe latter is used to shift out any size object.\n\n\n### 0.4.0 breaking changes\n\nThe 0.4.0 version has a flag to unroll the inner loop in **writeLSBFIRST()**\nand **writeMSBFIRST()**. The AVR optimized code blocks the interrupts per byte.\n\nNote: this optimization is new and thus experimental.\nFeedback, including improvements, is welcome.\n\n\n### Performance\n\nThe performance of **write()** is substantially faster for **AVR** than the default \nArduino **shiftOut()**, but not as fast as HW SPI (need test?). \nExact how large the performance gain is can be seen with the example **FastShiftOut_test.ino**.\nIt does a measurement of different functions and shows how the class is to be used.\nSee also table below.\n\n\n#### Measurements\n\nNumbers may vary depending on bit-order flag.\n\nIndicative time in microseconds, Arduino UNO, IDE 1.8.19, measured over 1000 calls.  \n(delta between 2 calls and 1 call to eliminate overhead)\n\n|  function                |  0.2.4  |   0.3.1  |   0.3.3  |   0.4.0  |  0.4.0L  |   0.4.1  |  0.4.1L  |\n|:-------------------------|--------:|---------:|---------:|---------:|---------:|---------:|---------:|\n|  write()                 |  21.66  |   22.48  |   22.27  |   14.10  |   11.51  |   12.83  |    9.12  |\n|  writeLSBFIRST()         |  22.94  |   23.37  |   22.25  |   14.09  |   11.50  |   12.82  |    9.12  |\n|  writeMSBFIRST()         |  20.30  |   21.86  |   22.26  |   14.08  |   11.50  |   12.82  |    9.12  |\n|  reference shiftOut()    |  89.74  |   89.74  |   89.59  |   89.60  |   89.60  |   89.59  |   89.60  |\n|  write16()               |   na    |    na    |   45.39  |   29.06  |   23.89  |   26.34  |   19.11  |\n|  write24()               |   na    |    na    |   67.66  |   43.12  |   35.40  |   39.36  |   28.23  |\n|  write32()               |   na    |    na    |   89.91  |   57.22  |   46.90  |   52.18  |   37.34  |\n|  println(\"Hello world\")  |   na    |  328.92  |  328.92  |  222.68  |  189.20  |  206.32  |  158.12  |\n|  println(1357)           |   na    |  313.56  |  311.60  |  262.60  |  247.12  |  255.04  |  232.80  |\n|  println(3.14159265, 4)  |   na    |  717.36  |  716.04  |  650.68  |  629.96  |  640.52  |  610.92  |\n\n- Note: 0.3.3 has improved the measurement, not the code sec.\n- Note: 0.3.3 numbers fixed when implementing 0.4.0. (error in test sketch).\n- Note: 0.4.0 measured with loop unroll flag disabled.\n- Note: 0.4.0L measured with loop unrolled flag enabled.\n- Note: 0.4.1 / 0.4.1L idem.\n- Note: Loop unrolled is (8046 - 7818 = 128) bytes larger in size.\n\n\n### Related\n\n- https://github.com/RobTillaart/FastShiftIn\n- https://github.com/RobTillaart/FastShiftInOut\n- https://github.com/RobTillaart/FastShiftOut\n- https://github.com/RobTillaart/ShiftInSlow\n- https://github.com/RobTillaart/ShiftOutSlow\n- https://github.com/RobTillaart/SWSPI (experimental)\n\n\n## Interface\n\n```cpp\n#include \"FastShiftOut.h\"\n```\n\n### Constructor\n\nbitOrder = { LSBFIRST, MSBFIRST };\n\n- **FastShiftOut(uint8_t dataOut, uint8_t clockPin, uint8_t bitOrder = LSBFIRST)** Constructor.\n\n\n### Functions\n\n- **size_t write(uint8_t data)** send a byte, also the workhorse of the **Print** interface.\n- **size_t write16(uint16_t data)** send 2 bytes. Wrapper around 8 bit calls.\n- **size_t write24(uint32_t data)** send 3 bytes. Wrapper around 8 bit calls.\n- **size_t write32(uint32_t data)** send 4 bytes. Wrapper around 8 bit calls.\n- **size_t write(uint8_t \\*array, size_t size)** send array of size bytes.\n- **uint8_t lastWritten()** returns last byte written.\n- **size_t writeLSBFIRST(uint8_t data)** lowest level function, optimized for LSB.\n- **size_t writeMSBFIRST(uint8_t data)** lowest level function, optimized for MSB.\n\n\n### BitOrder\n\n- **bool setBitOrder(uint8_t bitOrder)** set LSBFIRST or MSBFIRST. \nReturns false for other values ==\u003e no change.\n- **uint8_t getBitOrder(void)** returns LSBFIRST or MSBFIRST as set in constructor \nor latest set from **setBitOrder()**.\n\n\n### Print interface\n\nAs the FastShiftOut library implements the Print interface, one can also call\n\n- **size_t FSO.print(any type)** or \n- **size_t FSO.println(any type)** \n\nto send e.g. a float with 4 digits over the line, or some text string. \n\nNote: **FSO.print()** and **FSO.println()** return the number of characters printed, \nincluding an optional \\\\r and \\\\n.\n\n\n### Byte order\n\nThe functions **write16()**, **write24()** and **write32()** of this library assume\nthat the BIT-order is also the BYTE-order.\nThis is not always the case as an n-byte element can have n! == factorial(n)\ndistinct byte orders.\n\nSo **write16()** can have two, **write24()** can have six and **write32()** can even have \n(in theory) 24 distinct byte orders. Although LSB and MSB are the most common,\nother byte orders exist, and sometimes one explicitly wants to reorder the bytes.\n\nIf the BIT-order is not the BYTE-order, the user has two options\n- call **write()** multiple times and merge the bytes in the order needed.\n- call **write32()** (a.o) and reorder the bytes in a separate function.\n\nThe library will not support such functionality.\n\n\n## Notes\n\n- The optimizations are AVR only for now, other platforms may follow.\n- The 74HC595 needs 0.1uF caps and the data and clock lines may need  \npull up resistors, especially if wires are exceeding 10 cm (4\").\n\n\n## Future\n\n\n#### Must\n\n- keep in sync with FastShiftIn()\n\n#### Should\n\n- extend unit tests\n\n#### Could\n\n- investigate ESP32 optimization readLSBFIRST readMSBFIRST\n- performance ESP32\n- example schema\n- add invert flag?\n  - if ((value \u0026 m) == 0) ==\u003e if ((value \u0026 m) == invertFlag...\n  - derived class?\n\n#### Wont\n\n- investigate separate **BYTE**-order, \n  - only MSBFirst and LSBFirst\n  - **void setByteOrder()** + **uint8_t getByteOrder()**\n\n\n## Support\n\nIf you appreciate my libraries, you can support the development and maintenance.\nImprove the quality of the libraries by providing issues and Pull Requests, or\ndonate through PayPal or GitHub sponsors.\n\nThank you,\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FFastShiftOut","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRobTillaart%2FFastShiftOut","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FFastShiftOut/lists"}