├── .gitattributes ├── .github └── workflows │ └── tg-send.yml ├── LICENSE ├── README.md ├── README_EN.md ├── examples └── test │ └── test.ino ├── keywords.txt ├── library.properties └── src ├── GyverIO.h ├── GyverIO_SPI.h ├── gio ├── gio.h ├── gio_arduino.h ├── gio_avr.h ├── gio_defs.h ├── gio_esp32.h └── gio_esp8266.h └── utils ├── PinIO.h ├── PinT.h ├── shift.cpp └── shift.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/tg-send.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Telegram Message 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | name: Send Message 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: send telegram message on push 12 | uses: appleboy/telegram-action@master 13 | with: 14 | to: ${{ secrets.TELEGRAM_TO }} 15 | token: ${{ secrets.TELEGRAM_TOKEN }} 16 | disable_web_page_preview: true 17 | message: | 18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }} 19 | ${{ github.event.release.body }} 20 | https://github.com/${{ github.repository }} 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 GyverLibs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![latest](https://img.shields.io/github/v/release/GyverLibs/GyverIO.svg?color=brightgreen)](https://github.com/GyverLibs/GyverIO/releases/latest/download/GyverIO.zip) 2 | [![PIO](https://badges.registry.platformio.org/packages/gyverlibs/library/GyverIO.svg)](https://registry.platformio.org/libraries/gyverlibs/GyverIO) 3 | [![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/) 4 | [![Foo](https://img.shields.io/badge/%E2%82%BD%24%E2%82%AC%20%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%82%D1%8C-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B0-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/) 5 | [![Foo](https://img.shields.io/badge/README-ENGLISH-blueviolet.svg?style=flat-square)](https://github-com.translate.goog/GyverLibs/GyverIO?_x_tr_sl=ru&_x_tr_tl=en) 6 | 7 | [![Foo](https://img.shields.io/badge/ПОДПИСАТЬСЯ-НА%20ОБНОВЛЕНИЯ-brightgreen.svg?style=social&logo=telegram&color=blue)](https://t.me/GyverLibs) 8 | 9 | # GyverIO 10 | Быстрые функции для работы с пинами AVR (полный список смотри в gio_avr.h), ESP8266, ESP32 11 | - Ускорение в среднем в 20-30 раз, итоговое время для всех архитектур практически одинаковое 12 | - Классы для быстрого управления пином 13 | - Отдельная обработка случаев константных и неконстантных пинов для AVR 14 | - Быстрая реализация функций shiftIn/shiftOut 15 | - Универсальный класс hard SPI / soft SPI для использования в библиотеках 16 | 17 | ## Скорость 18 | ### Условия измерения 19 | | | Версия | Частота | 20 | |---------|--------|---------| 21 | | AVR | 1.8.19 | 16 | 22 | | ESP8266 | 3.1.2 | 80 | 23 | | ESP32 | 2.0.11 | 240 | 24 | | ESP32C3 | 2.0.11 | 80 | 25 | 26 | ### GPIO (us) 27 | | | write NC | write | read NC | read | mode NC | mode | 28 | |--------------|----------|-------------|-----------|-------------|---------|-------------| 29 | | AVR Ardu | **5.3** | 5.3 | **4.8** | 4.8 | **3.3** | 3.3 | 30 | | AVR gio | 1.6 | ***0.125*** | 1.75 | ***0.075*** | 1.8 | ***0.125*** | 31 | | | | | | | | | 32 | | ESP8266 Ardu | **1.5** | 1.5 | **0.54** | 0.54 | **1.4** | 1.4 | 33 | | ESP8266 gio | 0.29 | ***0.08*** | 0.5 | ***0.17*** | 1.29 | ***0.58*** | 34 | | | | | | | | | 35 | | ESP32 Ardu | **0.33** | 0.33 | **0.124** | 0.124 | **16** | 16 | 36 | | ESP32 gio | 0.04 | ***0.04*** | 0.085 | ***0.085*** | 0.126 | ***0.08*** | 37 | | | | | | | | | 38 | | ESP32C3 Ardu | **0.91** | 0.91 | **0.25** | 0.25 | **21** | 21 | 39 | | ESP32C3 gio | 0.05 | ***0.05*** | 0.4 | ***0.08*** | 0.49 | ***0.08*** | 40 | 41 | > *NC* - пины не константы 42 | 43 | > **Жирным** выделено худшее время (Arduino не константы), ***жирным курсивом*** - лучшее (gio константы) 44 | 45 | ### Shift (MHz) 46 | | | shiftOut | gio::shift | 47 | |---------|----------|------------| 48 | | AVR NC | 0.06 | 0.66 | 49 | | AVR | 0.06 | 1.3 | 50 | | ESP8266 | 0.2 | 1.1 | 51 | | ESP32 | 0.96 | 6 | 52 | | ESP32C3 | 0.35 | 2.6 | 53 | 54 | > *NC* - пины не константы 55 | 56 | ### Совместимость 57 | Совместима со всеми Arduino платформами (используются Arduino-функции) 58 | - Для esp8266 и esp32 быстрый `pinMode()` (`mode()`) работает только на режимы `INPUT`/`OUTPUT`! В остальных режимах вызывается штатный `pinMode()` 59 | 60 | ## Содержание 61 | - [Документация](#docs) 62 | - [Использование](#usage) 63 | - [Версии](#versions) 64 | - [Установка](#install) 65 | - [Баги и обратная связь](#feedback) 66 | 67 | 68 | ## Документация 69 | ### gio 70 | Быстые функции для работы с пинами 71 | 72 | ```cpp 73 | int gio::read(int P); 74 | void gio::high(int P); 75 | void gio::low(int P) 76 | void gio::write(int P, int V); 77 | 78 | // 79 | void gio::toggle(int P); 80 | 81 | // режим пина. Для esp8266/esp32 только INPUT/OUTPUT! 82 | void gio::mode(int P, int V); 83 | 84 | // нужно вызывать для esp8266/esp32 при инициализации пина 85 | // иначе mode() не будет работать! 86 | void gio::init(int P); 87 | ``` 88 | > У esp8266/esp32 нужно обязательно вызвать `gio::init` перед использованием! 89 | 90 | ### gio::shift 91 | Быстрый аналог shiftIn/shiftOut (отправка данных с клоком) 92 | 93 | ```cpp 94 | // прочитать пакет. Вернёт true, если хотя бы один бит отличается 95 | bool gio::shift::read(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 96 | 97 | // прочитать байт 98 | uint8_t gio::shift::read_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t delay = 0); 99 | 100 | // прочитать пакет + cs пин. Вернёт true, если хотя бы один бит отличается 101 | bool gio::shift::read_cs(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 102 | 103 | // прочитать байт + cs пин 104 | uint8_t gio::shift::read_cs_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t delay = 0); 105 | 106 | // отправить пакет 107 | void gio::shift::send(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 108 | 109 | // отправить байт 110 | void gio::shift::send_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t data, uint8_t delay = 0); 111 | 112 | // отправить пакет + cs пин 113 | void gio::shift::send_cs(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 114 | 115 | // отправить байт + cs пин 116 | void gio::shift::send_cs_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t data, uint8_t delay = 0); 117 | ``` 118 | 119 | Параметр `order` может быть: 120 | - `LSBFIRST`/`LSB_NORMAL` - LSB, прямой порядок байтов 121 | - `MSBFIRST`/`MSB_NORMAL` - MSB, прямой порядок байтов 122 | - `LSB_REVERSE` - LSB, обратный порядок байтов 123 | - `MSB_REVERSE` - MSB, обратный порядок байтов 124 | 125 | #### Примечание 126 | - `delay` в микросекундах, позволяет уменьшить скорость передачи. Например `1` мкс ограничит скорость до ~1 МГц, 2 мкс до ~500 кГц 127 | - Пины нужно сконфигурировать как `OUTPUT` самостоятельно до отправки (при запуске программы например) 128 | 129 | ### gio::SSPI 130 | Универсальный класс программно-аппаратного SPI с оптимизацией количества переменных для пинов 131 | 132 | ```cpp 133 | SSPI<0, freq> spi; // аппаратный без пина CS 134 | SSPI<0, freq, cs> spi; // аппаратный с пином CS в шаблоне 135 | SSPI<0, freq> spi(cs); // аппаратный с пином CS в классе 136 | SSPI<1, freq, cs, dt, clk> spi; // программный с пинами в шаблоне 137 | SSPI<1, freq> spi(cs, dt, clk); // программный с пинами в классе 138 | ``` 139 | 140 | ### Настройки компиляции 141 | ```cpp 142 | #define GIO_USE_ARDUINO // отключить быстрые функции (заменить на стандартные) 143 | #define GIO_NO_MASK // отключить быстрый IO на основе маски для AVR (в классе PinIO и всех shift) 144 | ``` 145 | 146 | 147 | ## Использование 148 | 149 | ```cpp 150 | #include 151 | 152 | gio::write(3, 1); // включить пин 3 153 | 154 | // отправить данные по пинам 3 и 4 155 | uint8_t data[] = {34, 63, 231, 9}; 156 | gio::shift::send(3, 4, MSBFIRST, data, 4); 157 | 158 | SSPI<0, f, cs> spi; 159 | spi.send(0x12); 160 | ``` 161 | 162 | 163 | ## Версии 164 | - v1.0 165 | - v1.1 - в 3 раза ускорен AVR non-const, обновлены таблицы 166 | - v1.2 - исправлена ошибка! 167 | - v1.2.1 - небольшая оптимизация 168 | - v1.2.2 - добавлена инверсия в shift 169 | - v1.2.4 - исправлен баг в gio::shift::read для AVR NC 170 | - v1.2.5 - добавлен возврат true в gio::shift::read при изменении буфера 171 | - v1.3.0 - исправлена критическая ошибка AVR/mode/NC 172 | - v1.3.1 - добавлен дополнительный delay в shift для симметричности клока 173 | - v1.3.2 - SSPI вынесен в отдельный файл, чтобы не мешать компиляции на некоторых платформах 174 | - v1.3.4 - поддержка ESP32C6 175 | 176 | 177 | ## Установка 178 | - Библиотеку можно найти по названию **GyverIO** и установить через менеджер библиотек в: 179 | - Arduino IDE 180 | - Arduino IDE v2 181 | - PlatformIO 182 | - [Скачать библиотеку](https://github.com/GyverLibs/GyverIO/archive/refs/heads/main.zip) .zip архивом для ручной установки: 183 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 184 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) 185 | - Распаковать и положить в *Документы/Arduino/libraries/* 186 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив 187 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 188 | ### Обновление 189 | - Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи 190 | - Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить" 191 | - Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам! 192 | 193 | 194 | ## Баги и обратная связь 195 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 196 | Библиотека открыта для доработки и ваших **Pull Request**'ов! 197 | 198 | При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать: 199 | - Версия библиотеки 200 | - Какой используется МК 201 | - Версия SDK (для ESP) 202 | - Версия Arduino IDE 203 | - Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде 204 | - Какой код загружался, какая работа от него ожидалась и как он работает в реальности 205 | - В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код 206 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | This is an automatic translation, may be incorrect in some places. See sources and examples! 2 | 3 | # Gyverio 4 | Fast functions for working with AVR Pin (a full list look at Gio_avr.h), ESP8266, ESP32 5 | - acceleration on average by 20-30 times, the final time for all architectures is almost the same 6 | - Classes for quick PIN control 7 | - Separate processing of cases of constant and uncontrolled pins for AVR 8 | - Fast implementation of Shiftin/Shiftout 9 | - Universal class Hard Spi / Soft SPI for use in libraries 10 | 11 | ## Speed 12 | ### measurement conditions 13 | ||Version |Frequency | 14 | | --------- | -------- | -------- | 15 | |AVR |1.8.19 |16 | 16 | |ESP8266 |3.1.2 |80 | 17 | |ESP32 |2.0.11 |240 | 18 | |ESP32C3 |2.0.11 |80 | 19 | 20 | ### GPIO (US) 21 | ||Write NC |Write |Read NC |Read |Mode NC |Mode | 22 | | ------------- | ---------- | ----------------- | ------------------------------| ------------ | --------- | ------------ 23 | |AVR Ardu |** 5.3 ** |5.3 |** 4.8 ** |4.8 |** 3.3 ** |3.3 | 24 | |AVR Gio |1.6 |*** 0.125 *** |1.75 |*** 0.075 *** |1.8 |*** 0.125 *** | 25 | |||||||| 26 | |ESP8266 Ardu |** 1.5 ** |1.5 |** 0.54 ** |0.54 |** 1.4 ** |1.4 | 27 | |ESP8266 Gio |0.29 |*** 0.08 *** |0.5 |*** 0.17 *** |1.29 |*** 0.58 *** | 28 | |||||||| 29 | |ESP32 Ardu |** 0.33 ** |0.33 |** 0.124 ** |0.124 |** 16 ** |16 | 30 | |ESP32 Gio |0.04 |*** 0.04 *** |0.085 |*** 0.085 *** |0.126 |*** 0.08 *** | 31 | |||||||| 32 | |ESP32C3 Ardu |** 0.91 ** |0.91 |** 0.25 ** |0.25 |** 21 ** |21 | 33 | |ESP32C3 Gio |0.05 |*** 0.05 *** |0.4 |*** 0.08 *** |0.49 |*** 0.08 *** | 34 | 35 | > * Nc * - Pins are not constants 36 | 37 | > ** Fat ** highlighted the worst time (Arduino not constants), *** with a fat italics *** - the best (gio constants) 38 | 39 | ### Shift (MHZ) 40 | ||Shiftout |Gio :: Shift | 41 | | -------- | ---------- | ----------------------------------- 42 | |AVR NC |0.06 |0.66 | 43 | |AVR |0.06 |1.3 | 44 | |ESP8266 |0.2 |1.1 | 45 | |ESP32 |0.96 |6 | 46 | |ESP32C3 |0.35 |2.6 | 47 | 48 | > * Nc * - Pins are not constants 49 | 50 | ## compatibility 51 | Compatible with all arduino platforms (used arduino functions) 52 | - For ESP8266 and ESP32, fast `pinmode ()` (`mode ()`) works only on `Input`/` output`!In other modes, the standard `pinmode ()` is called 53 | 54 | ## Content 55 | - [documentation] (#docs) 56 | - [use] (#usage) 57 | - [versions] (#varsions) 58 | - [installation] (# Install) 59 | - [bugs and feedback] (#fedback) 60 | 61 | 62 | ## Documentation 63 | ## Gio 64 | Squeezing pins 65 | 66 | `` `CPP 67 | int Gio :: read (int p); 68 | Void Gio :: High (int p); 69 | Void Gio :: Low (int p) 70 | Void Gio :: Write (int p, int v); 71 | 72 | // 73 | Void Gio :: Toggle (int p); 74 | 75 | // Pin mode.For ESP8266/ESP32 only Input/Output! 76 | Void Gio :: Mode (int p, int v); 77 | 78 | // you need to call for ESP8266/ESP32 when initializing the PIN 79 | // Otherwise, mod () will not work! 80 | Void Gio :: Init (int p); 81 | `` ` 82 | 83 | ### Gio :: Shift 84 | Fast analogue Shiftin/Shiftout (sending data with a clock) 85 | 86 | `` `CPP 87 | // Read the package 88 | vOID GIO :: Shift :: Read (uint8_t data_pin, uint8_t clk_pin, uint8_t Order, uint8_t* Data, Uint16_t Len, Uint8_t Delay = 0); 89 | 90 | // Read the byte 91 | uint8_t Gio :: Shift :: read_byte (uint8_t dat_pin, uint8_t clak_pin, uint8_t Order, uint8_t demely = 0); 92 | 93 | // Read the package + cs pin 94 | VOID GIO :: Shift :: Read_cs (uint8_t data_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t Order, uint8_t* data, uint16_t Len, uint8_t Delay = 0); 95 | 96 | // read byte + cs pin 97 | Uint8_t Gio :: Shift :: Read_cs_byte (uint8_t data_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t dlavay = 0); 98 | 99 | // Send a package 100 | VOID Gio :: Shift :: Send (uint8_t data_pin, uint8_t clk_pin, uint8_t Order, uint8_t* data, uint16_t len, uint8_t dlavay = 0); 101 | 102 | // Send byte 103 | VOID Gio :: Shift :: Send_byte (uint8_t data_pin, uint8_t clk_pin, uint8_t order, uint8_t data, uint8_t demelavy = 0); 104 | 105 | // Send package + cs pin 106 | VOID Gio :: Shift :: Send_cs (uint8_t data_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t Order, uint8_t* data, uint16_t Len, uint8_t demelavy = 0); 107 | 108 | // Send byte + cs pin 109 | VOID GIO :: Shift :: Send_cs_byte (uint8_t data_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t ORDER, UINT8_T DATA, UINT8_T DELAY = 0); 110 | `` ` 111 | 112 | The `order` parameter can be: 113 | - `lsbfirst`/` lsb_normal` - lsb, direct bytes directly 114 | - `MSBFIRST`/` MSB_Normal` - MSB, direct bytes direct 115 | - `lsb_reverse` - lsb, reverse byte order 116 | - `MSB_Reverse` - MSB, reverse bytes 117 | 118 | #### Note 119 | - `Delay` in microseconds, allows you to reduce the speed of transmission.For example, `1` μs will limit speed up to ~ 1 MHz, 2 μs up to ~ 500 kHz 120 | - Pins should be configured as `output` yourself before sending (when starting a program for example) 121 | 122 | ### Gio :: SSPI 123 | Universal class of software and hardware SPI with optimization of the number of variables for Pin 124 | 125 | `` `CPP 126 | SSPI <0, Freq> Spi;// hardware without PIN CS 127 | SSPI <0, Freq, CS> SPI;// Hardware with PIN CS in the template 128 | SSPI <0, Freq> Spi (CS);// Hardware with PIN CS in the classroom 129 | SSPI <1, Freq, CS, DT, CLK> Spi;// Program with pines in the template 130 | SSPI <1, FreQ> Spi (CS, DT, CLK);// Program with pins in class 131 | `` ` 132 | 133 | ### compilation settings 134 | `` `CPP 135 | #define gio_use_arduino // Disable quick functions (replace with standard) 136 | #define gio_no_mask // Disable a quick IO based on AVR mask (in the Pinio class and all Shift) 137 | `` ` 138 | 139 | 140 | ## Usage 141 | 142 | `` `CPP 143 | Gio :: Write (3, 1);// Turn on PIN 3 144 | 145 | // Send data on pins 3 and 4 146 | uint8_t data [] = {34, 63, 231, 9}; 147 | Gio :: Shift :: Send (3, 4, MSBFIRST, DATA, 4); 148 | `` ` 149 | 150 | 151 | ## versions 152 | - V1.0 153 | - V1.1 - AVR Non -Const is 3 times accelerated, the tables are updated 154 | - V1.2 - Fixed a mistake! 155 | - V1.2.1 - Small optimization 156 | - v1.2.2 - added inversion to Shift 157 | 158 | 159 | ## Installation 160 | - The library can be found by the name ** gyverio ** and installed through the library manager in: 161 | - Arduino ide 162 | - Arduino ide v2 163 | - Platformio 164 | - [download the library] (https://github.com/gyverlibs/gyverio/archive/refs/heads/main.zip) .Zip archive for manual installation: 165 | - unpack and put in * C: \ Program Files (X86) \ Arduino \ Libraries * (Windows X64) 166 | - unpack and put in * C: \ Program Files \ Arduino \ Libraries * (Windows X32) 167 | - unpack and put in *documents/arduino/libraries/ * 168 | - (Arduino id) Automatic installation from. Zip: * sketch/connect the library/add .Zip library ... * and specify downloaded archive 169 | - Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 170 | ### Update 171 | - I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added 172 | - through the IDE library manager: find the library how to install and click "update" 173 | - Manually: ** remove the folder with the old version **, and then put a new one in its place.“Replacement” cannot be done: sometimes files are deleted in new versions,Cranberries that remain when replacing and can lead to errors! 174 | 175 | 176 | ## bugs and feedback 177 | Create ** Issue ** when you find the bugs, and better immediately write to the mail [alex@alexgyver.ru] (mailto: alex@alexgyver.ru) 178 | The library is open for refinement and your ** pull Request ** 'ow! 179 | 180 | When reporting about bugs or incorrect work of the library, it is necessary to indicate: 181 | - The version of the library 182 | - What is MK used 183 | - SDK version (for ESP) 184 | - version of Arduino ide 185 | - whether the built -in examples work correctly, in which the functions and designs are used, leading to a bug in your code 186 | - what code has been loaded, what work was expected from it and how it works in reality 187 | - Ideally, attach the minimum code in which the bug is observed.Not a canvas of a thousand lines, but a minimum code -------------------------------------------------------------------------------- /examples/test/test.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "GyverIO.h" 4 | 5 | // gio::SSPI spi0; 6 | // gio::SSPI spi1; 7 | // gio::SSPI spi2(9); 8 | // gio::SSPI spi3; 9 | // gio::SSPI spi4(9, 11, 13); 10 | 11 | #define PIN_DAT 7 12 | #define PIN_CLK 6 13 | byte datNC, clkNC; 14 | 15 | void setup() { 16 | pinMode(PIN_DAT, OUTPUT); 17 | pinMode(PIN_CLK, OUTPUT); 18 | // gio::shift::send_byte(PIN_DAT, PIN_CLK, MSBFIRST, 0b10100101); 19 | } 20 | 21 | void loop() { 22 | datNC = digitalRead(5); 23 | clkNC = digitalRead(5); 24 | datNC = PIN_DAT; 25 | clkNC = PIN_CLK; 26 | digitalWrite(PIN_DAT, 1); 27 | delayMicroseconds(50); 28 | digitalWrite(PIN_DAT, 0); 29 | delayMicroseconds(50); 30 | noInterrupts(); 31 | 32 | shiftOut(datNC, clkNC, MSBFIRST, 0b10100101); 33 | shiftOut(PIN_DAT, PIN_CLK, MSBFIRST, 0b10100101); 34 | gio::shift::send_byte(datNC, clkNC, MSBFIRST, 0b10100101); 35 | gio::shift::send_byte(PIN_DAT, PIN_CLK, MSBFIRST, 0b10100101); 36 | delayMicroseconds(50); 37 | 38 | // ardu write nc 39 | digitalWrite(datNC, 1); 40 | digitalWrite(datNC, 0); 41 | digitalWrite(datNC, 1); 42 | digitalWrite(datNC, 0); 43 | digitalWrite(datNC, 1); 44 | digitalWrite(datNC, 0); 45 | digitalWrite(datNC, 1); 46 | digitalWrite(datNC, 0); 47 | digitalWrite(datNC, 1); 48 | digitalWrite(datNC, 0); 49 | delayMicroseconds(10); 50 | 51 | // ardu write 52 | digitalWrite(PIN_DAT, 1); 53 | digitalWrite(PIN_DAT, 0); 54 | digitalWrite(PIN_DAT, 1); 55 | digitalWrite(PIN_DAT, 0); 56 | digitalWrite(PIN_DAT, 1); 57 | digitalWrite(PIN_DAT, 0); 58 | digitalWrite(PIN_DAT, 1); 59 | digitalWrite(PIN_DAT, 0); 60 | digitalWrite(PIN_DAT, 1); 61 | digitalWrite(PIN_DAT, 0); 62 | delayMicroseconds(10); 63 | 64 | // ardu read nc 65 | gio::write(PIN_DAT, 1); 66 | gio::write(PIN_DAT, 0); 67 | gio::write(PIN_DAT, 1); 68 | gio::write(PIN_DAT, 0); 69 | gio::write(PIN_DAT, 1); 70 | 71 | digitalRead(datNC); 72 | 73 | gio::write(PIN_DAT, 0); 74 | gio::write(PIN_DAT, 1); 75 | gio::write(PIN_DAT, 0); 76 | gio::write(PIN_DAT, 1); 77 | gio::write(PIN_DAT, 0); 78 | delayMicroseconds(10); 79 | 80 | // ardu read 81 | gio::write(PIN_DAT, 1); 82 | gio::write(PIN_DAT, 0); 83 | gio::write(PIN_DAT, 1); 84 | gio::write(PIN_DAT, 0); 85 | gio::write(PIN_DAT, 1); 86 | 87 | digitalRead(PIN_DAT); 88 | 89 | gio::write(PIN_DAT, 0); 90 | gio::write(PIN_DAT, 1); 91 | gio::write(PIN_DAT, 0); 92 | gio::write(PIN_DAT, 1); 93 | gio::write(PIN_DAT, 0); 94 | delayMicroseconds(10); 95 | 96 | // ardu mode nc 97 | gio::write(PIN_DAT, 1); 98 | gio::write(PIN_DAT, 0); 99 | gio::write(PIN_DAT, 1); 100 | gio::write(PIN_DAT, 0); 101 | gio::write(PIN_DAT, 1); 102 | 103 | pinMode(datNC, OUTPUT); 104 | 105 | gio::write(PIN_DAT, 0); 106 | gio::write(PIN_DAT, 1); 107 | gio::write(PIN_DAT, 0); 108 | gio::write(PIN_DAT, 1); 109 | gio::write(PIN_DAT, 0); 110 | delayMicroseconds(10); 111 | 112 | // ardu mode 113 | gio::write(PIN_DAT, 1); 114 | gio::write(PIN_DAT, 0); 115 | gio::write(PIN_DAT, 1); 116 | gio::write(PIN_DAT, 0); 117 | gio::write(PIN_DAT, 1); 118 | 119 | pinMode(PIN_DAT, OUTPUT); 120 | 121 | gio::write(PIN_DAT, 0); 122 | gio::write(PIN_DAT, 1); 123 | gio::write(PIN_DAT, 0); 124 | gio::write(PIN_DAT, 1); 125 | gio::write(PIN_DAT, 0); 126 | delayMicroseconds(50); 127 | 128 | // gio write nc 129 | gio::write(datNC, 1); 130 | gio::write(datNC, 0); 131 | gio::write(datNC, 1); 132 | gio::write(datNC, 0); 133 | gio::write(datNC, 1); 134 | gio::write(datNC, 0); 135 | gio::write(datNC, 1); 136 | gio::write(datNC, 0); 137 | gio::write(datNC, 1); 138 | gio::write(datNC, 0); 139 | delayMicroseconds(10); 140 | 141 | // gio write 142 | gio::write(PIN_DAT, 1); 143 | gio::write(PIN_DAT, 0); 144 | gio::write(PIN_DAT, 1); 145 | gio::write(PIN_DAT, 0); 146 | gio::write(PIN_DAT, 1); 147 | gio::write(PIN_DAT, 0); 148 | gio::write(PIN_DAT, 1); 149 | gio::write(PIN_DAT, 0); 150 | gio::write(PIN_DAT, 1); 151 | gio::write(PIN_DAT, 0); 152 | delayMicroseconds(10); 153 | 154 | // gio read nc 155 | gio::write(PIN_DAT, 1); 156 | gio::write(PIN_DAT, 0); 157 | gio::write(PIN_DAT, 1); 158 | gio::write(PIN_DAT, 0); 159 | gio::write(PIN_DAT, 1); 160 | 161 | gio::read(datNC); 162 | 163 | gio::write(PIN_DAT, 0); 164 | gio::write(PIN_DAT, 1); 165 | gio::write(PIN_DAT, 0); 166 | gio::write(PIN_DAT, 1); 167 | gio::write(PIN_DAT, 0); 168 | delayMicroseconds(10); 169 | 170 | // gio read 171 | gio::write(PIN_DAT, 1); 172 | gio::write(PIN_DAT, 0); 173 | gio::write(PIN_DAT, 1); 174 | gio::write(PIN_DAT, 0); 175 | gio::write(PIN_DAT, 1); 176 | 177 | gio::read(PIN_DAT); 178 | 179 | gio::write(PIN_DAT, 0); 180 | gio::write(PIN_DAT, 1); 181 | gio::write(PIN_DAT, 0); 182 | gio::write(PIN_DAT, 1); 183 | gio::write(PIN_DAT, 0); 184 | delayMicroseconds(10); 185 | 186 | // gio mode nc 187 | gio::write(PIN_DAT, 1); 188 | gio::write(PIN_DAT, 0); 189 | gio::write(PIN_DAT, 1); 190 | gio::write(PIN_DAT, 0); 191 | gio::write(PIN_DAT, 1); 192 | 193 | gio::mode(datNC, OUTPUT); 194 | 195 | gio::write(PIN_DAT, 0); 196 | gio::write(PIN_DAT, 1); 197 | gio::write(PIN_DAT, 0); 198 | gio::write(PIN_DAT, 1); 199 | gio::write(PIN_DAT, 0); 200 | delayMicroseconds(10); 201 | 202 | // gio mode 203 | gio::write(PIN_DAT, 1); 204 | gio::write(PIN_DAT, 0); 205 | gio::write(PIN_DAT, 1); 206 | gio::write(PIN_DAT, 0); 207 | gio::write(PIN_DAT, 1); 208 | 209 | gio::mode(PIN_DAT, OUTPUT); 210 | 211 | gio::write(PIN_DAT, 0); 212 | gio::write(PIN_DAT, 1); 213 | gio::write(PIN_DAT, 0); 214 | gio::write(PIN_DAT, 1); 215 | gio::write(PIN_DAT, 0); 216 | delayMicroseconds(10); 217 | 218 | interrupts(); 219 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For GyverIO 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | GyverIO KEYWORD1 10 | Pin KEYWORD1 11 | PinIO KEYWORD1 12 | PinT KEYWORD1 13 | SSPI KEYWORD1 14 | 15 | GIO_USE_ARDUINO KEYWORD1 16 | GIO_NO_MASK KEYWORD1 17 | 18 | ####################################### 19 | # Methods and Functions (KEYWORD2) 20 | ####################################### 21 | 22 | init KEYWORD2 23 | toggle KEYWORD2 24 | write KEYWORD2 25 | high KEYWORD2 26 | low KEYWORD2 27 | read KEYWORD2 28 | mode KEYWORD2 29 | 30 | read KEYWORD2 31 | read_byte KEYWORD2 32 | read_cs KEYWORD2 33 | read_cs_byte KEYWORD2 34 | send KEYWORD2 35 | send_byte KEYWORD2 36 | send_cs KEYWORD2 37 | send_cs_byte KEYWORD2 38 | 39 | ####################################### 40 | # Constants (LITERAL1) 41 | ####################################### 42 | 43 | gio LITERAL1 44 | shift LITERAL1 45 | LSB_NORMAL LITERAL1 46 | MSB_NORMAL LITERAL1 47 | LSB_REVERSE LITERAL1 48 | MSB_REVERSE LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=GyverIO 2 | version=1.3.11 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Fast GPIO operation functions for AVR, ESP8266, ESP32 6 | paragraph=Fast GPIO operation functions for AVR, ESP8266, ESP32 7 | category=Signal Input/Output 8 | url=https://github.com/GyverLibs/GyverIO 9 | architectures=* -------------------------------------------------------------------------------- /src/GyverIO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "gio/gio.h" 4 | #include "utils/PinIO.h" 5 | #include "utils/PinT.h" 6 | #include "utils/shift.h" -------------------------------------------------------------------------------- /src/GyverIO_SPI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "utils/shift.h" 7 | 8 | namespace gio { 9 | 10 | template 11 | class SSPI { 12 | public: 13 | SSPI(int8_t cs = -1, int8_t dat = -1, int8_t clk = -1) { 14 | if (_softT) { 15 | if (_datT >= 0) { 16 | gio::init(_datT, OUTPUT); 17 | gio::init(_clkT, OUTPUT); 18 | } else { 19 | _pins[1] = dat; 20 | _pins[2] = clk; 21 | gio::init(_pins[1], OUTPUT); 22 | gio::init(_pins[2], OUTPUT); 23 | } 24 | } 25 | 26 | if (_csT >= 0) { 27 | gio::init(_csT, OUTPUT); 28 | gio::high(_csT); 29 | } else { 30 | _pins[0] = cs; 31 | if (cs >= 0) { 32 | gio::init(cs, OUTPUT); 33 | gio::high(cs); 34 | } 35 | } 36 | } 37 | void send(uint8_t data) { 38 | _begin(); 39 | if (_softT) { 40 | if (_datT >= 0) gio::shift::send_byte(_datT, _clkT, MSBFIRST, data, 1000000ul / _freqT); 41 | else gio::shift::send_byte(_pins[1], _pins[2], MSBFIRST, data, 1000000ul / _freqT); 42 | } else { 43 | SPI.transfer(data); 44 | } 45 | _end(); 46 | } 47 | void send(uint8_t* data, uint16_t len) { 48 | _begin(); 49 | if (_softT) { 50 | if (_datT >= 0) gio::shift::send(_datT, _clkT, MSBFIRST, data, len, 1000000ul / _freqT); 51 | else gio::shift::send(_pins[1], _pins[2], MSBFIRST, data, len, 1000000ul / _freqT); 52 | } else { 53 | for (uint16_t i = 0; i < len; i++) SPI.transfer(data[i]); 54 | } 55 | _end(); 56 | } 57 | 58 | private: 59 | void _begin() { 60 | if (_csT >= 0) gio::low(_csT); 61 | else if (_pins[0] >= 0) gio::low(_pins[0]); 62 | 63 | if (!_softT) SPI.beginTransaction(SPISettings(_freqT, MSBFIRST, SPI_MODE0)); 64 | } 65 | void _end() { 66 | if (!_softT) SPI.endTransaction(); 67 | 68 | if (_csT >= 0) gio::high(_csT); 69 | else if (_pins[0] >= 0) gio::high(_pins[0]); 70 | } 71 | 72 | int8_t _pins[(_csT < 0) + ((_softT && _datT < 0) ? 2 : 0)]; // CS, DAT, CLK 73 | 74 | /* 75 | SSPI<0, f, cs> spi; 0 76 | SSPI<0, f, -1> spi(?); 1 77 | SSPI<1, f, cs, dat, clk> spi; 0 78 | SSPI<1, f> spi(cs, dat, clk); 1+2 79 | */ 80 | }; 81 | 82 | } // namespace gio -------------------------------------------------------------------------------- /src/gio/gio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // быстрые функции пинов 3 | // #define GIO_USE_ARDUINO 4 | 5 | #ifdef GIO_USE_ARDUINO 6 | #include "gio_arduino.h" 7 | #else 8 | 9 | #if defined(__AVR__) || defined(ARDUINO_ARCH_AVR) 10 | #include "gio_avr.h" 11 | #elif defined(ESP8266) || defined(ARDUINO_ARCH_ESP8266) 12 | #include "gio_esp8266.h" 13 | #elif defined(ESP32) || defined(ARDUINO_ARCH_ESP32) 14 | #include "gio_esp32.h" 15 | #else 16 | #include "gio_arduino.h" 17 | #endif 18 | 19 | #endif // GIO_USE_ARDUINO 20 | 21 | /* 22 | us (MHz) 23 | | | digitalWrite | gio_write | gio_toggle | digitalRead | gio_read | pinMode | gio_mode | 24 | |---------|--------------|-----------|------------|-------------|------------|--------------|------------| 25 | | AVR | 1.47 (0.68) | 0.06 (16) | 0.06 (16) | 3.23 (0.31) | 0.13 (8) | 3.33 (0.3) | 0.13 (8) | 26 | | ESP8266 | 1.56 (0.64) | 0.08 (12) | 0.5 (2) | 0.56 (1.8) | 0.21 (4.8) | 1.43 (0.7) | 0.67 (1.5) | 27 | | ESP32 | 0.33 (3) | 0.04 (24) | 0.13 (8) | 1.67 (0.6) | 0.08 (12) | 16.67 (0.06) | 0.08 (12) | 28 | | ESP32C3 | 0.92 (1) | 0.06 (16) | 0.19 (5.2) | 0.25 (4) | 0.04 (24) | 20 (0.05) | 0.04 (24) | 29 | */ -------------------------------------------------------------------------------- /src/gio/gio_arduino.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "gio_defs.h" 5 | 6 | namespace gio { 7 | 8 | // mode 9 | _GIO_INLINE void mode(int P, int V) { 10 | pinMode(P, V); 11 | } 12 | 13 | // read 14 | _GIO_INLINE int read(int P) { 15 | return digitalRead(P); 16 | } 17 | 18 | // high 19 | _GIO_INLINE void high(int P) { 20 | digitalWrite(P, 1); 21 | } 22 | 23 | // low 24 | _GIO_INLINE void low(int P) { 25 | digitalWrite(P, 0); 26 | } 27 | 28 | // write 29 | _GIO_INLINE void write(int P, int V) { 30 | digitalWrite(P, V); 31 | } 32 | 33 | // toggle 34 | _GIO_INLINE void toggle(int P) { 35 | digitalWrite(P, !digitalRead(P)); 36 | } 37 | 38 | // init 39 | _GIO_INLINE void init(int P, int V = INPUT) { 40 | mode(P, V); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/gio/gio_avr.h: -------------------------------------------------------------------------------- 1 | /* 2 | Optimized digital functions for AVR microcontrollers 3 | by Watterott electronic (www.watterott.com) 4 | based on https://code.google.com/p/digitalwritefast 5 | based on https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/digitalWriteFast.h 6 | 7 | License: BSD 3-Clause License (https://opensource.org/licenses/BSD-3-Clause) 8 | */ 9 | 10 | #pragma once 11 | #if defined(__AVR__) || defined(ARDUINO_ARCH_AVR) 12 | 13 | #include 14 | 15 | #include "gio_defs.h" 16 | 17 | // ===================================================================== 18 | // ============================== PINOUT =============================== 19 | // ===================================================================== 20 | 21 | // --- Arduino Mega and ATmega128x/256x based boards --- 22 | #if (defined(ARDUINO_AVR_MEGA) || \ 23 | defined(ARDUINO_AVR_MEGA1280) || \ 24 | defined(ARDUINO_AVR_MEGA2560) || \ 25 | defined(__AVR_ATmega1280__) || \ 26 | defined(__AVR_ATmega1281__) || \ 27 | defined(__AVR_ATmega2560__) || \ 28 | defined(__AVR_ATmega2561__)) 29 | 30 | #define __avr_pin_to_port(P) \ 31 | (((P) >= 22 && (P) <= 29) ? &PORTA : ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PORTB : (((P) >= 30 && (P) <= 37) ? &PORTC : ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PORTD : ((((P) <= 3) || (P) == 5) ? &PORTE : (((P) >= 54 && (P) <= 61) ? &PORTF : ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PORTG : ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PORTH : (((P) == 14 || (P) == 15) ? &PORTJ : (((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL)))))))))) 32 | 33 | #define __avr_pin_to_ddr(P) \ 34 | (((P) >= 22 && (P) <= 29) ? &DDRA : ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &DDRB : (((P) >= 30 && (P) <= 37) ? &DDRC : ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &DDRD : ((((P) <= 3) || (P) == 5) ? &DDRE : (((P) >= 54 && (P) <= 61) ? &DDRF : ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &DDRG : ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &DDRH : (((P) == 14 || (P) == 15) ? &DDRJ : (((P) >= 62 && (P) <= 69) ? &DDRK : &DDRL)))))))))) 35 | 36 | #define __avr_pin_to_pin(P) \ 37 | (((P) >= 22 && (P) <= 29) ? &PINA : ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : (((P) >= 30 && (P) <= 37) ? &PINC : ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : ((((P) <= 3) || (P) == 5) ? &PINE : (((P) >= 54 && (P) <= 61) ? &PINF : ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : (((P) == 14 || (P) == 15) ? &PINJ : (((P) >= 62 && (P) <= 69) ? &PINK : &PINL)))))))))) 38 | 39 | #define __avr_pin_to_bit(P) \ 40 | (((P) >= 7 && (P) <= 9) ? (P)-3 : (((P) >= 10 && (P) <= 13) ? (P)-6 : (((P) >= 22 && (P) <= 29) ? (P)-22 : (((P) >= 30 && (P) <= 37) ? 37 - (P) : (((P) >= 39 && (P) <= 41) ? 41 - (P) : (((P) >= 42 && (P) <= 49) ? 49 - (P) : (((P) >= 50 && (P) <= 53) ? 53 - (P) : (((P) >= 54 && (P) <= 61) ? (P)-54 : (((P) >= 62 && (P) <= 69) ? (P)-62 : (((P) == 0 || (P) == 15 || (P) == 17 || (P) == 21) ? 0 : (((P) == 1 || (P) == 14 || (P) == 16 || (P) == 20) ? 1 : (((P) == 19) ? 2 : (((P) == 5 || (P) == 6 || (P) == 18) ? 3 : (((P) == 2) ? 4 : (((P) == 3 || (P) == 4) ? 5 : 7))))))))))))))) 41 | 42 | // --- Arduino MightyCore standard pinout --- 43 | #elif (defined(__AVR_ATmega1284P__) || \ 44 | defined(__AVR_ATmega1284__) || \ 45 | defined(__AVR_ATmega644P__) || \ 46 | defined(__AVR_ATmega644A__) || \ 47 | defined(__AVR_ATmega644__) || \ 48 | defined(__AVR_ATmega324PB__) || \ 49 | defined(__AVR_ATmega324PA__) || \ 50 | defined(__AVR_ATmega324P__) || \ 51 | defined(__AVR_ATmega324A__) || \ 52 | defined(__AVR_ATmega164P__) || \ 53 | defined(__AVR_ATmega164A__) || \ 54 | defined(__AVR_ATmega32__) || \ 55 | defined(__AVR_ATmega16__) || \ 56 | defined(__AVR_ATmega8535__)) && \ 57 | !defined(BOBUINO_PINOUT) 58 | 59 | #if defined(__AVR_ATmega324PB__) 60 | #define __avr_pin_to_port(P) \ 61 | (((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : (((P) >= 24 && (P) <= 31) ? &PORTA : &PORTE)))) 62 | #define __avr_pin_to_ddr(P) \ 63 | (((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : (((P) >= 24 && (P) <= 31) ? &DDRA : &DDRE)))) 64 | #define __avr_pin_to_pin(P) \ 65 | (((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : (((P) >= 24 && (P) <= 31) ? &PINA : &PINE)))) 66 | #define __avr_pin_to_bit(P) \ 67 | (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P)-8 : (((P) >= 16 && (P) <= 23) ? (P)-16 : (((P) >= 16 && (P) <= 23) ? (P)-24 : (P)-32)))) 68 | #elif defined(PORTA) 69 | #define __avr_pin_to_port(P) \ 70 | (((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : &PORTA))) 71 | #define __avr_pin_to_ddr(P) \ 72 | (((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : &DDRA))) 73 | #define __avr_pin_to_pin(P) \ 74 | (((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : &PINA))) 75 | #define __avr_pin_to_bit(P) \ 76 | (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P)-8 : (((P) >= 16 && (P) <= 23) ? (P)-16 : (P)-24))) 77 | #else 78 | #define __avr_pin_to_port(P) \ 79 | (((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : &PORTC)) 80 | #define __avr_pin_to_ddr(P) \ 81 | (((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : &DDRC)) 82 | #define __avr_pin_to_pin(P) \ 83 | (((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : &PINC)) 84 | #define __avr_pin_to_bit(P) \ 85 | (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P)-8 : (((P) >= 16 && (P) <= 23) ? (P)-16 : (P)-24))) 86 | #endif 87 | 88 | // --- Arduino Leonardo and ATmega16U4/32U4 based boards --- 89 | #elif (defined(ARDUINO_AVR_LEONARDO) || \ 90 | defined(__AVR_ATmega16U4__) || \ 91 | defined(__AVR_ATmega32U4__)) 92 | #if defined(TEENSYDUINO) 93 | 94 | #define __avr_pin_to_port(P) \ 95 | ((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &PORTB : (((P) == 9 || (P) == 10) ? &PORTC : (((P) >= 16 && (P) <= 21)) ? &PORTF \ 96 | : &PORTD)) 97 | #define __avr_pin_to_ddr(P) \ 98 | ((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &DDRB : (((P) == 9 || (P) == 10) ? &DDRC : (((P) >= 16 && (P) <= 21)) ? &DDRF \ 99 | : &DDRD)) 100 | #define __avr_pin_to_pin(P) \ 101 | ((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &PINB : (((P) == 9 || (P) == 10) ? &PINC : (((P) >= 16 && (P) <= 21)) ? &PINF \ 102 | : &PIND)) 103 | #define __avr_pin_to_bit(P) \ 104 | (((P) <= 3) ? (P) : (((P) == 4 || (P) == 12) ? 7 : (((P) <= 8) ? (P)-5 : (((P) <= 10) ? (P)-3 : (((P) == 11) ? 6 : (((P) <= 15) ? (P)-9 : (((P) <= 19) ? 23 - (P) : (((P) <= 21) ? 21 - (P) : (P)-18)))))))) 105 | #else 106 | 107 | #define __avr_pin_to_port(P) \ 108 | ((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PORTD : (((P) == 5 || (P) == 13) ? &PORTC : (((P) >= 18 && (P) <= 23)) ? &PORTF \ 109 | : (((P) == 7) ? &PORTE : &PORTB))) 110 | #define __avr_pin_to_ddr(P) \ 111 | ((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &DDRD : (((P) == 5 || (P) == 13) ? &DDRC : (((P) >= 18 && (P) <= 23)) ? &DDRF \ 112 | : (((P) == 7) ? &DDRE : &DDRB))) 113 | #define __avr_pin_to_pin(P) \ 114 | ((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PIND : (((P) == 5 || (P) == 13) ? &PINC : (((P) >= 18 && (P) <= 23)) ? &PINF \ 115 | : (((P) == 7) ? &PINE : &PINB))) 116 | #define __avr_pin_to_bit(P) \ 117 | (((P) >= 8 && (P) <= 11) ? (P)-4 : (((P) >= 18 && (P) <= 21) ? 25 - (P) : (((P) == 0) ? 2 : (((P) == 1) ? 3 : (((P) == 2) ? 1 : (((P) == 3) ? 0 : (((P) == 4) ? 4 : (((P) == 6) ? 7 : (((P) == 13) ? 7 : (((P) == 14) ? 3 : (((P) == 15) ? 1 : (((P) == 16) ? 2 : (((P) == 17) ? 0 : (((P) == 22) ? 1 : (((P) == 23) ? 0 : (((P) == 24) ? 4 : (((P) == 25) ? 7 : (((P) == 26) ? 4 : (((P) == 27) ? 5 : 6))))))))))))))))))) 118 | #endif 119 | 120 | // --- Arduino Uno and ATmega168/328 based boards --- 121 | #elif (defined(ARDUINO_AVR_UNO) || \ 122 | defined(ARDUINO_AVR_DUEMILANOVE) || \ 123 | defined(__AVR_ATmega8__) || \ 124 | defined(__AVR_ATmega48__) || \ 125 | defined(__AVR_ATmega48P__) || \ 126 | defined(__AVR_ATmega48PB__) || \ 127 | defined(__AVR_ATmega88P__) || \ 128 | defined(__AVR_ATmega88PB__) || \ 129 | defined(__AVR_ATmega168__) || \ 130 | defined(__AVR_ATmega168PA__) || \ 131 | defined(__AVR_ATmega168PB__) || \ 132 | defined(__AVR_ATmega328__) || \ 133 | defined(__AVR_ATmega328P__) || \ 134 | defined(__AVR_ATmega328PB__)) 135 | 136 | #if defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328PB__) 137 | #define __avr_pin_to_port(P) \ 138 | (((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : (((P) >= 14 && (P) <= 19) ? &PORTC : &PORTE))) 139 | #define __avr_pin_to_ddr(P) \ 140 | (((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : (((P) >= 14 && (P) <= 19) ? &DDRC : &DDRE))) 141 | #define __avr_pin_to_pin(P) \ 142 | (((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : (((P) >= 14 && (P) <= 19) ? &PINC : &PINE))) 143 | #define __avr_pin_to_bit(P) \ 144 | (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P)-8 : (((P) >= 14 && (P) <= 19) ? (P)-14 : (((P) >= 20 && (P) <= 21) ? (P)-18 : (P)-22)))) 145 | #else 146 | #define __avr_pin_to_port(P) \ 147 | (((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : &PORTC)) 148 | #define __avr_pin_to_ddr(P) \ 149 | (((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : &DDRC)) 150 | #define __avr_pin_to_pin(P) \ 151 | (((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : &PINC)) 152 | #define __avr_pin_to_bit(P) \ 153 | (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P)-8 : (P)-14)) 154 | #endif 155 | 156 | // --- Arduino Uno WiFi Rev 2, Nano Every --- 157 | #elif defined(__AVR_ATmega4809__) 158 | 159 | #define __avr_pin_to_port(P) \ 160 | (((P) == 2 || (P) == 7) ? &VPORTA.OUT : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.OUT \ 161 | : ((P) == 4) ? &VPORTC.OUT \ 162 | : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.OUT \ 163 | : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.OUT \ 164 | : &VPORTF.OUT) 165 | #define __avr_pin_to_ddr(P) \ 166 | (((P) == 2 || (P) == 7) ? &VPORTA.DIR : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.DIR \ 167 | : ((P) == 4) ? &VPORTC.DIR \ 168 | : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.DIR \ 169 | : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.DIR \ 170 | : &VPORTF.DIR) 171 | #define __avr_pin_to_pin(P) \ 172 | (((P) == 2 || (P) == 7) ? &VPORTA.IN : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.IN \ 173 | : ((P) == 4) ? &VPORTC.IN \ 174 | : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.IN \ 175 | : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.IN \ 176 | : &VPORTF.IN) 177 | #define __avr_pin_to_bit(P) \ 178 | (((P) == 2 || (P) == 9 || (P) == 11 || (P) == 17) ? 0 : ((P) == 7 || (P) == 10 || (P) == 12 || (P) == 16) ? 1 \ 179 | : ((P) == 5 || (P) == 13 || (P) == 15 || (P) == 18) ? 2 \ 180 | : ((P) == 9 || (P) == 14 || (P) == 19) ? 3 \ 181 | : ((P) == 6 || (P) == 20) ? 4 \ 182 | : ((P) == 3 || (P) == 21) ? 5 \ 183 | : 6) 184 | 185 | // TinyCore 186 | // https://raw.githubusercontent.com/xukangmin/TinyCore/master/avr/package/package_tinycore_index.json 187 | // https://docs.tinycore.dev/en/latest/ 188 | #elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) 189 | #define __avr_pin_to_port(P) ((P) <= 5 ? &VPORTB.OUT : ((P) <= 9 ? &VPORTC.OUT : ((P) <= 16 ? &VPORTA.OUT : ((P) <= 18 ? &VPORTB.OUT : &VPORTC.OUT)))) 190 | #define __avr_pin_to_ddr(P) ((P) <= 5 ? &VPORTB.DIR : ((P) <= 9 ? &VPORTC.DIR : ((P) <= 16 ? &VPORTA.DIR : ((P) <= 18 ? &VPORTB.DIR : &VPORTC.DIR)))) 191 | #define __avr_pin_to_pin(P) ((P) <= 5 ? &VPORTB.IN : ((P) <= 9 ? &VPORTC.IN : ((P) <= 16 ? &VPORTA.IN : ((P) <= 18 ? &VPORTB.IN : &VPORTC.IN)))) 192 | #define __avr_pin_to_bit(P) ((P) <= 3 ? (3 - P) : ((P) <= 5 ? (P) : ((P) <= 9 ? (P - 6) : ((P) <= 16 ? ((P)-9) : ((P) <= 18 ? ((P)-11) : ((P)-15)))))) 193 | 194 | #elif defined(__AVR_ATtiny1614__) 195 | #define __avr_pin_to_port(P) ((P) <= 3 ? &VPORTA.OUT : ((P) <= 7 ? &VPORTB.OUT : &VPORTA.OUT)) 196 | #define __avr_pin_to_ddr(P) ((P) <= 3 ? &VPORTA.DIR : ((P) <= 7 ? &VPORTB.DIR : &VPORTA.DIR)) 197 | #define __avr_pin_to_pin(P) ((P) <= 3 ? &VPORTA.IN : ((P) <= 7 ? &VPORTB.IN : &VPORTA.IN)) 198 | #define __avr_pin_to_bit(P) ((P) <= 3 ? (P + 4) : ((P) <= 7 ? (7 - P) : ((P) <= 10 ? (P - 7) : (P)-11))) 199 | 200 | #elif defined(__AVR_ATtiny816__) 201 | // https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1029 202 | #define __avr_pin_to_port(P) ((P) <= 3 ? &VPORTA.OUT : ((P) <= 9 ? &VPORTB.OUT : ((P) <= 13 ? &VPORTC.OUT : ((P) <= 17 ? &VPORTA.OUT : &VPORTC.OUT)))) 203 | #define __avr_pin_to_ddr(P) ((P) <= 3 ? &VPORTA.DIR : ((P) <= 9 ? &VPORTB.DIR : ((P) <= 13 ? &VPORTC.DIR : ((P) <= 17 ? &VPORTA.DIR : &VPORTC.DIR)))) 204 | #define __avr_pin_to_pin(P) ((P) <= 3 ? &VPORTA.IN : ((P) <= 9 ? &VPORTB.IN : ((P) <= 13 ? &VPORTC.IN : ((P) <= 17 ? &VPORTA.IN : &VPORTC.IN)))) 205 | #define __avr_pin_to_bit(P) ((P) <= 3 ? (P + 4) : ((P) <= 9 ? (9 - P) : ((P) <= 13 ? (P - 10) : ((P) <= 16 ? (P - 13) : ((P)-17))))) 206 | 207 | // --- ATtinyX5 --- 208 | #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) 209 | // we have only PORTB 210 | #define __avr_pin_to_port(P) (&PORTB) 211 | #define __avr_pin_to_ddr(P) (&DDRB) 212 | #define __avr_pin_to_pin(P) (&PINB) 213 | #define __avr_pin_to_bit(P) (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P)-8 : (P)-14)) 214 | 215 | // --- ATtiny88 --- 216 | #elif defined(__AVR_ATtiny88__) 217 | #if defined(ARDUINO_AVR_DIGISPARKPRO) 218 | #define __avr_pin_to_port(P) ((P) <= 7 ? &PORTD : ((P) <= 14 ? &PORTB : ((P) <= 18 ? &PORTA : &PORTC))) 219 | #define __avr_pin_to_ddr(P) ((P) <= 7 ? &DDRD : ((P) <= 14 ? &DDRB : ((P) <= 18 ? &DDRA : &DDRC))) 220 | #define __avr_pin_to_pin(P) ((P) <= 7 ? &PIND : ((P) <= 14 ? &PINB : ((P) <= 18 ? &PINA : &PINC))) 221 | #define __avr_pin_to_bit(P) ((P) <= 7 ? (P) : ((P) <= 13 ? ((P)-8) : ((P) == 14 ? 7 : ((P) <= 16 ? ((P)-14) : ((P) <= 18 ? ((P)-17) : ((P) == 25 ? 7 : ((P)-19))))))) 222 | #else 223 | #define __avr_pin_to_port(P) ((P) <= 7 ? &PORTD : ((P) <= 15 ? &PORTB : ((P) <= 22 ? &PORTC : ((P) <= 26 ? &PORTA : &PORTC)))) 224 | #define __avr_pin_to_ddr(P) ((P) <= 7 ? &DDRD : ((P) <= 15 ? &DDRB : ((P) <= 22 ? &DDRC : ((P) <= 26 ? &DDRA : &DDRC)))) 225 | #define __avr_pin_to_pin(P) ((P) <= 7 ? &PIND : ((P) <= 15 ? &PINB : ((P) <= 22 ? &PINC : ((P) <= 26 ? &PINA : &PINC)))) 226 | #define __avr_pin_to_bit(P) ((P) <= 15 ? ((P)&0x7) : ((P) == 16 ? (7) : ((P) <= 22 ? ((P)-17) : ((P) == 27 ? (6) : ((P)-23))))) 227 | #endif 228 | 229 | // --- ATtinyX4 + ATtinyX7 --- 230 | #elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 231 | #if defined(ARDUINO_AVR_DIGISPARKPRO) || PIN_PA7 == 5 232 | // Strange enumeration of pins on Digispark board and core library 233 | #define __avr_pin_to_port(P) (((P) <= 4) ? &PORTB : &PORTA) 234 | #define __avr_pin_to_ddr(P) (((P) <= 4) ? &DDRB : &DDRA) 235 | #define __avr_pin_to_pin(P) (((P) <= 4) ? &PINB : &PINA) 236 | #define __avr_pin_to_bit(P) (((P) <= 2) ? (P) : (((P) == 3) ? 6 : (((P) == 4) ? 3 : (((P) == 5) ? 7 : (P)-6)))) 237 | #else 238 | // ATtinyX4: PORTA for 0 to 7, PORTB for 8 to 11 239 | // ATtinyX7: PORTA for 0 to 7, PORTB for 8 to 15 240 | #define __avr_pin_to_port(P) (((P) <= 7) ? &PORTA : &PORTB) 241 | #define __avr_pin_to_ddr(P) (((P) <= 7) ? &DDRA : &DDRB) 242 | #define __avr_pin_to_pin(P) (((P) <= 7) ? &PINA : &PINB) 243 | #endif 244 | #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) 245 | // https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/variants/tinyx41_cw/pins_arduino.h#L334 246 | // Clockwise layout 247 | #define __avr_pin_to_bit(P) (((P) <= 7) ? (P) : ((P) == 11 ? (3) : 10 - (P))) 248 | #else 249 | #define __avr_pin_to_bit(P) (((P) <= 7) ? (P) : (P)-8) 250 | #endif 251 | 252 | #endif 253 | 254 | // ===================================================================== 255 | // ============================== IO FUNC ============================== 256 | // ===================================================================== 257 | 258 | namespace gio { 259 | 260 | // mode 261 | _GIO_INLINE void mode(int P, int V) { 262 | #if defined(__avr_pin_to_port) 263 | if (__builtin_constant_p(P) && __builtin_constant_p(V)) { 264 | switch (V) { 265 | case INPUT: 266 | bitClear(*__avr_pin_to_ddr(P), __avr_pin_to_bit(P)); 267 | bitClear(*__avr_pin_to_port(P), __avr_pin_to_bit(P)); 268 | break; 269 | case INPUT_PULLUP: 270 | bitClear(*__avr_pin_to_ddr(P), __avr_pin_to_bit(P)); 271 | bitSet(*__avr_pin_to_port(P), __avr_pin_to_bit(P)); 272 | break; 273 | case OUTPUT: 274 | bitSet(*__avr_pin_to_ddr(P), __avr_pin_to_bit(P)); 275 | break; 276 | } 277 | } else 278 | #endif 279 | { 280 | switch (V) { 281 | case INPUT: 282 | greg_clr(portModeRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 283 | greg_clr(portOutputRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 284 | break; 285 | case INPUT_PULLUP: 286 | greg_clr(portModeRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 287 | greg_set(portOutputRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 288 | break; 289 | case OUTPUT: 290 | greg_set(portModeRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 291 | break; 292 | } 293 | } 294 | } 295 | 296 | // read 297 | _GIO_INLINE int read(int P) { 298 | #if defined(__avr_pin_to_pin) 299 | if (__builtin_constant_p(P)) { 300 | return (bitRead(*__avr_pin_to_pin(P), __avr_pin_to_bit(P))) ? 1 : 0; 301 | } else 302 | #endif 303 | { 304 | return greg_read(portInputRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 305 | } 306 | } 307 | 308 | // high 309 | _GIO_INLINE void high(int P) { 310 | #if defined(__avr_pin_to_port) 311 | if (__builtin_constant_p(P)) { 312 | bitSet(*__avr_pin_to_port(P), __avr_pin_to_bit(P)); 313 | } else 314 | #endif 315 | { 316 | greg_set(portOutputRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 317 | } 318 | } 319 | 320 | // low 321 | _GIO_INLINE void low(int P) { 322 | #if defined(__avr_pin_to_port) 323 | if (__builtin_constant_p(P)) { 324 | bitClear(*__avr_pin_to_port(P), __avr_pin_to_bit(P)); 325 | } else 326 | #endif 327 | { 328 | greg_clr(portOutputRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 329 | } 330 | } 331 | 332 | // write 333 | _GIO_INLINE void write(int P, int V) { 334 | V ? high(P) : low(P); 335 | } 336 | 337 | // toggle 338 | _GIO_INLINE void toggle(int P) { 339 | #if defined(__avr_pin_to_pin) 340 | if (__builtin_constant_p(P)) { 341 | bitSet(*__avr_pin_to_pin(P), __avr_pin_to_bit(P)); 342 | } else 343 | #endif 344 | { 345 | greg_set(portInputRegister(digitalPinToPort(P)), digitalPinToBitMask(P)); 346 | } 347 | } 348 | 349 | // init 350 | _GIO_INLINE void init(int P, int V = INPUT) { 351 | mode(P, V); 352 | } 353 | 354 | } // namespace gio 355 | 356 | #endif -------------------------------------------------------------------------------- /src/gio/gio_defs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _GIO_INLINE static inline __attribute__((always_inline)) 4 | #define greg_set(reg, mask) *reg |= mask 5 | #define greg_clr(reg, mask) *reg &= ~mask 6 | #define greg_write(reg, mask, val) (val) ? greg_set(reg, mask) : greg_clr(reg, mask) 7 | #define greg_read(reg, mask) (bool)(*reg & mask) -------------------------------------------------------------------------------- /src/gio/gio_esp32.h: -------------------------------------------------------------------------------- 1 | // based on https://github.com/PaulStoffregen/OneWire/blob/master/util/OneWire_direct_gpio.h 2 | 3 | #pragma once 4 | #if defined(ESP32) || defined(ARDUINO_ARCH_ESP32) 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "gio_defs.h" 11 | 12 | #if ESP_IDF_VERSION_MAJOR < 4 13 | #define _ESP32_IDF_V3_REG() \ 14 | uint32_t rtc_reg(rtc_gpio_desc[pin].reg); \ 15 | if (rtc_reg) { \ 16 | ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); \ 17 | ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); \ 18 | } 19 | #else 20 | #define _ESP32_IDF_V3_REG() 21 | #endif 22 | 23 | #define _IS_ESP_Cx_ defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) 24 | 25 | namespace gio { 26 | 27 | // mode 28 | _GIO_INLINE void mode(uint8_t pin, uint8_t mode) { 29 | switch (mode) { 30 | case INPUT: 31 | #if _IS_ESP_Cx_ 32 | GPIO.enable_w1tc.val = (1ul << (pin)); 33 | #else 34 | if (digitalPinIsValid(pin)) { 35 | _ESP32_IDF_V3_REG(); 36 | if (pin < 32) GPIO.enable_w1tc = (1ul << pin); 37 | else GPIO.enable1_w1tc.val = (1ul << (pin - 32)); 38 | } 39 | #endif 40 | break; 41 | 42 | case OUTPUT: 43 | #if _IS_ESP_Cx_ 44 | GPIO.enable_w1ts.val = (1ul << (pin)); 45 | #else 46 | if (digitalPinIsValid(pin)) { 47 | _ESP32_IDF_V3_REG(); 48 | if (pin < 32) GPIO.enable_w1ts = (1ul << pin); 49 | else GPIO.enable1_w1ts.val = (1ul << (pin - 32)); 50 | } 51 | #endif 52 | break; 53 | 54 | default: 55 | pinMode(pin, mode); 56 | break; 57 | } 58 | } 59 | 60 | // read 61 | _GIO_INLINE int read(uint8_t pin) { 62 | #if _IS_ESP_Cx_ 63 | return (GPIO.in.val >> pin) & 0x1; 64 | #else 65 | if (digitalPinIsValid(pin)) { 66 | if (pin < 32) return (GPIO.in >> pin) & 0x1; 67 | else return (GPIO.in1.val >> (pin - 32)) & 0x1; 68 | } 69 | #endif 70 | return 0; 71 | } 72 | 73 | // low 74 | _GIO_INLINE void low(uint8_t pin) { 75 | #if _IS_ESP_Cx_ 76 | GPIO.out_w1tc.val = (1ul << pin); 77 | #else 78 | if (digitalPinIsValid(pin)) { 79 | if (pin < 32) GPIO.out_w1tc = (1ul << pin); 80 | else GPIO.out1_w1tc.val = (1ul << (pin - 32)); 81 | } 82 | #endif 83 | } 84 | 85 | // high 86 | _GIO_INLINE void high(uint8_t pin) { 87 | #if _IS_ESP_Cx_ 88 | GPIO.out_w1ts.val = (1ul << pin); 89 | #else 90 | if (digitalPinIsValid(pin)) { 91 | if (pin < 32) GPIO.out_w1ts = (1ul << pin); 92 | else GPIO.out1_w1ts.val = (1ul << (pin - 32)); 93 | } 94 | #endif 95 | } 96 | 97 | // write 98 | _GIO_INLINE void write(uint8_t pin, uint8_t val) { 99 | val ? high(pin) : low(pin); 100 | } 101 | 102 | // toggle 103 | _GIO_INLINE void toggle(uint8_t pin) { 104 | write(pin, !read(pin)); 105 | } 106 | 107 | // init 108 | _GIO_INLINE void init(int P, int V = INPUT) { 109 | pinMode(P, V); 110 | } 111 | 112 | } // namespace gio 113 | 114 | #endif -------------------------------------------------------------------------------- /src/gio/gio_esp8266.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #if defined(ESP8266) || defined(ARDUINO_ARCH_ESP8266) 3 | 4 | #include 5 | 6 | #include "gio_defs.h" 7 | 8 | namespace gio { 9 | 10 | // mode 11 | _GIO_INLINE void mode(uint8_t pin, uint8_t mode) { 12 | // dsnt work 13 | // if (mode == INPUT) GPE &= ~(1 << pin); 14 | // else if (mode == OUTPUT) GPE |= (1 << pin); 15 | 16 | switch (mode) { 17 | case INPUT: 18 | case INPUT_PULLUP: 19 | if (pin < 16) { 20 | GPF(pin) = GPFFS(GPFFS_GPIO(pin)); 21 | GPEC = (1 << pin); 22 | GPC(pin) = (GPC(pin) & (0xF << GPCI)) | (1 << GPCD); 23 | if (mode == INPUT_PULLUP) GPF(pin) |= (1 << GPFPU); 24 | } else if (pin == 16) { 25 | GPF16 = GP16FFS(GPFFS_GPIO(pin)); 26 | GPC16 = 0; 27 | GP16E &= ~1; 28 | } 29 | break; 30 | 31 | case OUTPUT: 32 | if (pin < 16) { 33 | GPF(pin) = GPFFS(GPFFS_GPIO(pin)); 34 | GPC(pin) = (GPC(pin) & (0xF << GPCI)); 35 | GPES = (1 << pin); 36 | } else if (pin == 16) { 37 | GPF16 = GP16FFS(GPFFS_GPIO(pin)); 38 | GPC16 = 0; 39 | GP16E |= 1; 40 | } 41 | break; 42 | 43 | default: 44 | pinMode(pin, mode); 45 | break; 46 | } 47 | } 48 | 49 | // read 50 | _GIO_INLINE int read(uint8_t pin) { 51 | return (pin < 16) ? GPIP(pin) : (GP16I & 0x01); 52 | } 53 | 54 | // low 55 | _GIO_INLINE void low(uint8_t pin) { 56 | if (pin < 16) GPOC = (1 << pin); 57 | else if (pin == 16) GP16O &= ~1; 58 | } 59 | 60 | // high 61 | _GIO_INLINE void high(uint8_t pin) { 62 | if (pin < 16) GPOS = (1 << pin); 63 | else if (pin == 16) GP16O |= 1; 64 | } 65 | 66 | // write 67 | _GIO_INLINE void write(uint8_t pin, uint8_t val) { 68 | val ? high(pin) : low(pin); 69 | } 70 | 71 | // toggle 72 | _GIO_INLINE void toggle(uint8_t pin) { 73 | if (pin < 16) { 74 | if (GPIP(pin)) GPOC = (1 << pin); 75 | else GPOS = (1 << pin); 76 | } else if (pin == 16) { 77 | if (GP16I & 0x01) GP16O &= ~1; 78 | else GP16O |= 1; 79 | } 80 | } 81 | 82 | // init 83 | _GIO_INLINE void init(int P, int V = INPUT) { 84 | mode(P, V); 85 | } 86 | 87 | } // namespace gio 88 | 89 | #endif -------------------------------------------------------------------------------- /src/utils/PinIO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../gio/gio.h" 6 | 7 | // #define GIO_NO_MASK 8 | 9 | namespace gio { 10 | 11 | // single mode pin (output/input) 12 | class PinIO { 13 | public: 14 | PinIO() {} 15 | PinIO(uint8_t npin, uint8_t mode = INPUT) { 16 | init(npin, mode); 17 | } 18 | 19 | void init(uint8_t npin, uint8_t mode = INPUT) { 20 | gio::init(npin, mode); 21 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 22 | if (mode == OUTPUT) reg = portOutputRegister(digitalPinToPort(npin)); 23 | else reg = portInputRegister(digitalPinToPort(npin)); 24 | mask = digitalPinToBitMask(npin); 25 | #else 26 | pin = npin; 27 | #endif 28 | } 29 | 30 | void write(uint8_t val) { 31 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 32 | greg_write(reg, mask, val); 33 | #else 34 | gio::write(pin, val); 35 | #endif 36 | } 37 | 38 | void high() { 39 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 40 | greg_set(reg, mask); 41 | #else 42 | gio::high(pin); 43 | #endif 44 | } 45 | 46 | void low() { 47 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 48 | greg_clr(reg, mask); 49 | #else 50 | gio::low(pin); 51 | #endif 52 | } 53 | 54 | void toggle() { 55 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 56 | *reg ^= mask; 57 | #else 58 | gio::toggle(pin); 59 | #endif 60 | } 61 | 62 | int read() { 63 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 64 | return greg_read(reg, mask); 65 | #else 66 | return gio::read(pin); 67 | #endif 68 | } 69 | 70 | private: 71 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 72 | volatile uint8_t *reg; 73 | uint8_t mask = 0xff; 74 | #else 75 | uint8_t pin; 76 | #endif 77 | }; 78 | 79 | } // namespace gio -------------------------------------------------------------------------------- /src/utils/PinT.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../gio/gio.h" 6 | #include "../gio/gio_defs.h" 7 | 8 | namespace gio { 9 | 10 | template 11 | class PinT { 12 | public: 13 | PinT(uint8_t mode = INPUT) { 14 | gio::init(pin, mode); 15 | } 16 | _GIO_INLINE void mode(uint8_t mode) { 17 | gio::mode(pin, mode); 18 | } 19 | _GIO_INLINE void write(uint8_t val) { 20 | gio::write(pin, val); 21 | } 22 | _GIO_INLINE void high() { 23 | gio::high(pin); 24 | } 25 | _GIO_INLINE void low() { 26 | gio::low(pin); 27 | } 28 | _GIO_INLINE void toggle() { 29 | gio::toggle(pin); 30 | } 31 | _GIO_INLINE int read() { 32 | return gio::read(pin); 33 | } 34 | }; 35 | 36 | } // namespace gio -------------------------------------------------------------------------------- /src/utils/shift.cpp: -------------------------------------------------------------------------------- 1 | #include "shift.h" 2 | 3 | namespace gio { 4 | namespace shift { 5 | 6 | bool read(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay) { 7 | bool dif = 0; 8 | if (order & 0b10) data += len - 1; 9 | 10 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 11 | if (!__builtin_constant_p(dat_pin) || !__builtin_constant_p(clk_pin)) { 12 | volatile uint8_t* c_reg = portOutputRegister(digitalPinToPort(clk_pin)); 13 | volatile uint8_t* d_reg = portInputRegister(digitalPinToPort(dat_pin)); 14 | uint8_t c_mask = digitalPinToBitMask(clk_pin); 15 | uint8_t d_mask = digitalPinToBitMask(dat_pin); 16 | uint8_t val = 0; 17 | while (len--) { 18 | val = 0; 19 | for (uint8_t i = 0; i < 8; i++) { 20 | if (order & 0b01) { // MSBFIRST 21 | val <<= 1; 22 | if (greg_read(d_reg, d_mask)) val |= 1; 23 | } else { 24 | val >>= 1; 25 | if (greg_read(d_reg, d_mask)) val |= (1 << 7); 26 | } 27 | if (delay) delayMicroseconds(delay); 28 | greg_set(c_reg, c_mask); 29 | if (delay) delayMicroseconds(delay); 30 | greg_clr(c_reg, c_mask); 31 | } 32 | if (!dif && *data != val) dif = 1; 33 | *data = val; 34 | data += (order & 0b10) ? -1 : 1; 35 | } 36 | } else 37 | #endif 38 | { 39 | uint8_t val = 0; 40 | while (len--) { 41 | val = 0; 42 | for (uint8_t i = 0; i < 8; i++) { 43 | if (order & 0b01) { // MSBFIRST 44 | val <<= 1; 45 | if (gio::read(dat_pin)) val |= 1; 46 | } else { 47 | val >>= 1; 48 | if (gio::read(dat_pin)) val |= (1 << 7); 49 | } 50 | if (delay) delayMicroseconds(delay); 51 | gio::high(clk_pin); 52 | if (delay) delayMicroseconds(delay); 53 | gio::low(clk_pin); 54 | } 55 | if (!dif && *data != val) dif = 1; 56 | *data = val; 57 | data += (order & 0b10) ? -1 : 1; 58 | } 59 | } 60 | return dif; 61 | } 62 | 63 | uint8_t read_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t delay) { 64 | uint8_t value; 65 | read(dat_pin, clk_pin, order, &value, 1, delay); 66 | return value; 67 | } 68 | 69 | bool read_cs(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay) { 70 | gio::low(cs_pin); 71 | bool res = read(dat_pin, clk_pin, order, data, len, delay); 72 | gio::high(cs_pin); 73 | return res; 74 | } 75 | 76 | uint8_t read_cs_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t delay) { 77 | uint8_t value; 78 | read_cs(dat_pin, clk_pin, cs_pin, order, &value, 1, delay); 79 | return value; 80 | } 81 | 82 | void send(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay) { 83 | #if defined(__AVR__) && !defined(GIO_NO_MASK) 84 | if (!__builtin_constant_p(dat_pin) || !__builtin_constant_p(clk_pin)) { 85 | volatile uint8_t* c_reg = portOutputRegister(digitalPinToPort(clk_pin)); 86 | volatile uint8_t* d_reg = portOutputRegister(digitalPinToPort(dat_pin)); 87 | uint8_t c_mask = digitalPinToBitMask(clk_pin); 88 | uint8_t d_mask = digitalPinToBitMask(dat_pin); 89 | uint8_t val; 90 | for (uint16_t b = 0; b < len; b++) { 91 | val = data[(order & 0b10) ? (len - b - 1) : b]; 92 | for (uint8_t i = 0; i < 8; i++) { 93 | if (order & 0b01) { // MSBFIRST 94 | greg_write(d_reg, d_mask, val & (1 << 7)); 95 | val <<= 1; 96 | } else { 97 | greg_write(d_reg, d_mask, val & 1); 98 | val >>= 1; 99 | } 100 | if (delay) delayMicroseconds(delay); 101 | greg_set(c_reg, c_mask); 102 | if (delay) delayMicroseconds(delay); 103 | greg_clr(c_reg, c_mask); 104 | } 105 | } 106 | greg_clr(d_reg, d_mask); 107 | } else 108 | #endif 109 | { 110 | for (uint16_t b = 0; b < len; b++) { 111 | uint8_t val = data[(order & 0b10) ? (len - b - 1) : b]; 112 | for (uint8_t i = 0; i < 8; i++) { 113 | if (order & 0b01) { // MSBFIRST 114 | gio::write(dat_pin, val & (1 << 7)); 115 | val <<= 1; 116 | } else { 117 | gio::write(dat_pin, val & 1); 118 | val >>= 1; 119 | } 120 | if (delay) delayMicroseconds(delay); 121 | gio::high(clk_pin); 122 | if (delay) delayMicroseconds(delay); 123 | gio::low(clk_pin); 124 | } 125 | gio::low(dat_pin); 126 | } 127 | } 128 | } 129 | 130 | void send_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t data, uint8_t delay) { 131 | send(dat_pin, clk_pin, order, &data, 1, delay); 132 | } 133 | 134 | void send_cs(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay) { 135 | gio::low(cs_pin); 136 | send(dat_pin, clk_pin, order, data, len, delay); 137 | gio::high(cs_pin); 138 | } 139 | 140 | void send_cs_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t data, uint8_t delay) { 141 | send_cs(dat_pin, clk_pin, cs_pin, order, &data, 1, delay); 142 | } 143 | 144 | } // namespace shift 145 | } // namespace gio -------------------------------------------------------------------------------- /src/utils/shift.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../gio/gio.h" 6 | 7 | #define LSB_NORMAL 0b00 8 | #define MSB_NORMAL 0b01 9 | #define LSB_REVERSE 0b10 10 | #define MSB_REVERSE 0b11 11 | 12 | namespace gio { 13 | namespace shift { 14 | 15 | // read 16 | // прочитать пакет. Вернёт true, если хотя бы один бит отличается 17 | bool read(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 18 | 19 | // прочитать байт 20 | uint8_t read_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t delay = 0); 21 | 22 | // прочитать пакет + cs пин. Вернёт true, если хотя бы один бит отличается 23 | bool read_cs(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 24 | 25 | // прочитать байт + cs пин 26 | uint8_t read_cs_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t delay = 0); 27 | 28 | // send 29 | // отправить пакет 30 | void send(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 31 | 32 | // отправить байт 33 | void send_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t order, uint8_t data, uint8_t delay = 0); 34 | 35 | // отправить пакет + cs пин 36 | void send_cs(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t* data, uint16_t len, uint8_t delay = 0); 37 | 38 | // отправить байт + cs пин 39 | void send_cs_byte(uint8_t dat_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t order, uint8_t data, uint8_t delay = 0); 40 | 41 | } // namespace shift 42 | } // namespace gio 43 | 44 | /* 45 | us byte (MHz) 46 | | | shiftOut | gio_send | gio_send (non-const) | 47 | |---------|--------------|----------|----------------------| 48 | | AVR | 100 (0.075) | 6 (1.3) | 11 (0.7) | 49 | */ --------------------------------------------------------------------------------