diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..df83677 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,24 @@ +name: PlatformIO CI + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/cache@v3 + with: + path: | + ~/.cache/pip + ~/.platformio/.cache + key: ${{ runner.os }}-pio + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + - name: Install PlatformIO Core + run: pip install --upgrade platformio + + - name: Build PlatformIO Project + run: pio run diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d9d673 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +.pio +.cache diff --git a/.scripts/commands.sh b/.scripts/commands.sh new file mode 100755 index 0000000..e16838f --- /dev/null +++ b/.scripts/commands.sh @@ -0,0 +1,207 @@ +#! /bin/bash + +# A helper script to help build and upload firmware projects based on PlatformIO + +function list_environments(){ + pio project config|grep ^env:|sed "s,env:,," +} + + + +function generate_vscode_tasks() { + # Lists all environments, and creates a vscode build and upload tasks for each environment + # This is useful for creating a vscode task.json file + + for env in $(list_environments); do + echo " + // Upload ${env} + { + \"label\": \"upload ${env}\", + \"type\": \"shell\", + \"command\": \"pio run -t upload -e ${env}\", + }, + // Build ${env} + { + \"label\": \"build ${env}\", + \"type\": \"shell\", + \"command\": \"pio run -e ${env}\", + }," +done +} + +function update_vscode_tasks_json () { + # Updates the vscode tasks.json file with the tasks generated by generate_vscode_tasks + + if [ ! -f .vscode/tasks.json ]; then + echo "tasks.json file not found. Please run this command from the root of the project" + exit 1 + fi + + # Backup the tasks.json file + cp .vscode/tasks.json .vscode/tasks.json.bak + + # Create the top part + echo ' { + // This file is auto generated by the commands.sh script. Any edits will be overwritten automatically. + "version": "2.0.0", + "tasks": [ + + // Build all + { + "label": "Build all", + "type": "shell", + "command": "pio run", + "group": { + "kind": "build", + "isDefault": true + } + }, + + // Make compiledb to allow LSP to work + { + "label": "Build compiledb database for LSP / clangd", + "type": "shell", + "command": "pio run -t compiledb", + }, + ' > .vscode/tasks.json + + + + # Generate the tasks + generate_vscode_tasks >> .vscode/tasks.json + + # Close the tasks.json file + echo "] }" >> .vscode/tasks.json + + echo "tasks.json updated successfully" +} + +function print_help() { + echo "Usage: $0 " + echo "Commands:" + echo " list" + echo " show" + echo " build-all" + echo " build " + echo " upload " + echo " add_board" + echo " fzf_boards" + echo " update_vscode_tasks" + exit 1 +} + +function build() { + if [ $# -ne 1 ]; then + echo "Usage: $0 build " + echo "See list of available environments by running $0 list" + exit 1 + fi + + pio run -e $1 +} + +function build_all() { + pio run +} + +function upload() { + if [ $# -ne 1 ]; then + echo "Usage: $0 upload " + echo "See list of available environments by running $0 list" + exit 1 + fi + + pio run -e $1 --target upload +} + +function show() { + pio project --list-targets +} + +function fzf_boards() { + # Fuzzy search boards and return the board id + + # Check if fzf installed + if ! command -v fzf &> /dev/null; then + echo "fzf is not installed. Please install fzf to use this feature." + exit 1 + fi + + pio boards --json-output | jq -r '.[] | "id:" + .id + ", name:" + .name + ", platform:" + .platform' | fzf + +} + +# Gets new environemnt using fzf and adds it to the platformio.ini file +function add_new_board() { + new_env=$(fzf_boards) + if [ -z "$new_env" ]; then + echo "No board selected. Exiting" + exit 1 + fi + echo "Adding new environment $new_env" + + # Get the board id + board_id=$(echo $new_env | awk -F',' '{print $1}' | awk -F':' '{print $2}' | xargs) + board_name=$(echo $new_env | awk -F',' '{print $2}' | awk -F':' '{print $2}' | xargs) + board_platform=$(echo $new_env | awk -F',' '{print $3}' | awk -F':' '{print $2}' | xargs) + + # Add the new environment to the platformio.ini file + echo "Adding new environment to platformio.ini" + echo " +; $board_name +[env:$board_id] +platform = $board_platform +board = $board_id +; Additional build flags for $board_name here +build_flags = + \${env.build_flags} +; Additional libraries for $board_name here +lib_deps = + \${env.lib_deps}" >> platformio.ini + + update_vscode_tasks_json +} + +function main() { + # parse the command line arguments + if [ $# -eq 0 ]; then + print_help + exit 1 + fi + + case $1 in + list) + list_environments + ;; + show) + show + ;; + upload) + shift + upload $@ + ;; + build-all) + build_all + ;; + build) + shift + build $@ + ;; + + add_board) + add_new_board + ;; + fzf_boards) + fzf_boards + ;; + update_vscode_tasks) + update_vscode_tasks_json + ;; + *) + print_help + exit 1 + ;; + esac +} + +main $@ diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..da229aa --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,141 @@ + { + // This file is auto generated by the commands.sh script. Any edits will be overwritten automatically. + "version": "2.0.0", + "tasks": [ + + // Build all + { + "label": "Build all", + "type": "shell", + "command": "pio run", + "group": { + "kind": "build", + "isDefault": true + } + }, + + // Make compiledb to allow LSP to work + { + "label": "Build compiledb database for LSP / clangd", + "type": "shell", + "command": "pio run -t compiledb", + }, + + + // Upload raspberrypi-pico + { + "label": "upload raspberrypi-pico", + "type": "shell", + "command": "pio run -t upload -e raspberrypi-pico", + }, + // Build raspberrypi-pico + { + "label": "build raspberrypi-pico", + "type": "shell", + "command": "pio run -e raspberrypi-pico", + }, + + // Upload raspberrypi-picow + { + "label": "upload raspberrypi-picow", + "type": "shell", + "command": "pio run -t upload -e raspberrypi-picow", + }, + // Build raspberrypi-picow + { + "label": "build raspberrypi-picow", + "type": "shell", + "command": "pio run -e raspberrypi-picow", + }, + + // Upload esp32dev + { + "label": "upload esp32dev", + "type": "shell", + "command": "pio run -t upload -e esp32dev", + }, + // Build esp32dev + { + "label": "build esp32dev", + "type": "shell", + "command": "pio run -e esp32dev", + }, + + // Upload nodemcuv2-esp8266 + { + "label": "upload nodemcuv2-esp8266", + "type": "shell", + "command": "pio run -t upload -e nodemcuv2-esp8266", + }, + // Build nodemcuv2-esp8266 + { + "label": "build nodemcuv2-esp8266", + "type": "shell", + "command": "pio run -e nodemcuv2-esp8266", + }, + + // Upload teensy41 + { + "label": "upload teensy41", + "type": "shell", + "command": "pio run -t upload -e teensy41", + }, + // Build teensy41 + { + "label": "build teensy41", + "type": "shell", + "command": "pio run -e teensy41", + }, + + // Upload teensy40 + { + "label": "upload teensy40", + "type": "shell", + "command": "pio run -t upload -e teensy40", + }, + // Build teensy40 + { + "label": "build teensy40", + "type": "shell", + "command": "pio run -e teensy40", + }, + + // Upload teensylc + { + "label": "upload teensylc", + "type": "shell", + "command": "pio run -t upload -e teensylc", + }, + // Build teensylc + { + "label": "build teensylc", + "type": "shell", + "command": "pio run -e teensylc", + }, + + // Upload adafruit_feather_esp32s2 + { + "label": "upload adafruit_feather_esp32s2", + "type": "shell", + "command": "pio run -t upload -e adafruit_feather_esp32s2", + }, + // Build adafruit_feather_esp32s2 + { + "label": "build adafruit_feather_esp32s2", + "type": "shell", + "command": "pio run -e adafruit_feather_esp32s2", + }, + + // Upload featheresp32 + { + "label": "upload featheresp32", + "type": "shell", + "command": "pio run -t upload -e featheresp32", + }, + // Build featheresp32 + { + "label": "build featheresp32", + "type": "shell", + "command": "pio run -e featheresp32", + }, +] } diff --git a/.vscode/tasks.json.bak b/.vscode/tasks.json.bak new file mode 100644 index 0000000..179e499 --- /dev/null +++ b/.vscode/tasks.json.bak @@ -0,0 +1,128 @@ + { + // This file is auto generated by the commands.sh script. Any edits will be overwritten automatically. + "version": "2.0.0", + "tasks": [ + + // Build all + { + "label": "Build all", + "type": "shell", + "command": "pio run", + "group": { + "kind": "build", + "isDefault": true + } + }, + + // Make compiledb to allow LSP to work + { + "label": "Build compiledb database for LSP / clangd", + "type": "shell", + "command": "pio run -t compiledb", + }, + + + // Upload raspberrypi-pico + { + "label": "upload raspberrypi-pico", + "type": "shell", + "command": "pio run -t upload -e raspberrypi-pico", + }, + // Build raspberrypi-pico + { + "label": "build raspberrypi-pico", + "type": "shell", + "command": "pio run -e raspberrypi-pico", + }, + + // Upload raspberrypi-picow + { + "label": "upload raspberrypi-picow", + "type": "shell", + "command": "pio run -t upload -e raspberrypi-picow", + }, + // Build raspberrypi-picow + { + "label": "build raspberrypi-picow", + "type": "shell", + "command": "pio run -e raspberrypi-picow", + }, + + // Upload esp32dev + { + "label": "upload esp32dev", + "type": "shell", + "command": "pio run -t upload -e esp32dev", + }, + // Build esp32dev + { + "label": "build esp32dev", + "type": "shell", + "command": "pio run -e esp32dev", + }, + + // Upload nodemcuv2-esp8266 + { + "label": "upload nodemcuv2-esp8266", + "type": "shell", + "command": "pio run -t upload -e nodemcuv2-esp8266", + }, + // Build nodemcuv2-esp8266 + { + "label": "build nodemcuv2-esp8266", + "type": "shell", + "command": "pio run -e nodemcuv2-esp8266", + }, + + // Upload teensy41 + { + "label": "upload teensy41", + "type": "shell", + "command": "pio run -t upload -e teensy41", + }, + // Build teensy41 + { + "label": "build teensy41", + "type": "shell", + "command": "pio run -e teensy41", + }, + + // Upload teensy40 + { + "label": "upload teensy40", + "type": "shell", + "command": "pio run -t upload -e teensy40", + }, + // Build teensy40 + { + "label": "build teensy40", + "type": "shell", + "command": "pio run -e teensy40", + }, + + // Upload teensylc + { + "label": "upload teensylc", + "type": "shell", + "command": "pio run -t upload -e teensylc", + }, + // Build teensylc + { + "label": "build teensylc", + "type": "shell", + "command": "pio run -e teensylc", + }, + + // Upload adafruit_feather_esp32s2 + { + "label": "upload adafruit_feather_esp32s2", + "type": "shell", + "command": "pio run -t upload -e adafruit_feather_esp32s2", + }, + // Build adafruit_feather_esp32s2 + { + "label": "build adafruit_feather_esp32s2", + "type": "shell", + "command": "pio run -e adafruit_feather_esp32s2", + }, +] } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..36b89f4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Mads Kjeldgaard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8401545 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +[![PlatformIO CI](https://github.com/madskjeldgaard/platformio-arduino-template/actions/workflows/build.yml/badge.svg)](https://github.com/madskjeldgaard/platformio-arduino-template/actions/workflows/build.yml) + +# The ⚑ULTIMATE⚑ Arduino starter template for Platformio 🐩 + +This template sets up a nice skeleton to create a project for an arduino-supported microcontroller board using [platformio](https://platformio.org/). + +It has a lot of common things set up for most common boards used in the art/music/maker world, including a few optimizations and weird fixes. + +It includes suggestions for libraries to use so you don't have to dig around too much for the common stuff. Just uncomment in the platformio.ini file and recompile. + +## Features + +- 🐩 Platformio-based – easy to compile and upload, gets dependencies automatically, also easy to extend with new boards +- 🐩 Includes a lot of common libraries. Just comment/uncomment in [platformio.ini](platformio.ini) to your project's liking. +- 🐩 Set up for C++17, allowing a lot of modern C++ tricks. +- 🐩 A helper script is included in [.scripts/commands.sh](.scripts/commands.sh) to make tedious processes simpler. +- 🐩 VSCode tasks are included making building easy in VSCode and in NeoVim (using the Overseer plugin) +- 🐩 A Github Action which runs every time you push code to test if your firmware still compiles. + +## Supported boards + +- βœ… Raspberry Pi Pico +- βœ… Raspberry Pi PicoW +- βœ… Teensy 4.1 +- βœ… Teensy 4.0 +- βœ… Teensy LC +- βœ… NodeMCUV2 ESP8266 +- βœ… ESP32 dev boards +- βœ… Adafruit Feather ESP32 +- βœ… Adafruit Feather ESP32 S2 + +... And it's very easy to add more boards: + +### Adding new boards + +The included script has a command to fuzzy search through available boards and automatically insert it into `platformio.ini` and auto update the vscode tasks as well. + +Add new board using this command: +```bash +.scripts/commands.sh add_board +``` + +Then open `platformio.ini` and make any additional adjustments. + +## Usage + +### Compiling and uploading + +To compile and upload your sketch, simply run this command, adjusted to one of the supported boards, eg for Teensy 4.0: + +```bash +.scripts/commands.sh build teensy40 +``` + +Or to build and then upload in one command: +```bash +.scripts/commands.sh upload teensy40 +``` + +Finally, the project includes vscode tasks, which are the recommended way of running these commands. Either using vscode as an editor, or in neovim using the [overseer.nvim](https://github.com/stevearc/overseer.nvim) for NeoVim. + +### Installing dependencies + +You need to have platformio installed to make use of this. + +Install it on MacOS by running homebrew: + +```bash +brew install platformio +``` +If you want to use all the helper scripts' features for adding new boards to your project, you also need `fzf` and `jq`: + +```bash +brew install fzf jq +``` diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..fda7bb1 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,150 @@ +; The configuration file for PlatformIO +; +; This file is setup with a lot of suggestions for libraries etc. +; +; You can delete them as you wish :) +[env] +framework = arduino + +; Use C++ version 17 +build_unflags = -std=gnu++11 +build_flags = -std=gnu++17 -fconcepts + +# Common global libraries. Uncomment any of these to include them in the build. +lib_deps = + # USB support + # Adafruit TinyUSB Library + + # MIDI communication – send MIDI messages over USB or physical MIDI ports + # https://github.com/FortySevenEffects/arduino_midi_library + + # OSC communication – senc control messages over the network + # cnmat/OSC + + # Smooth reading of analog signals, eg potentiometers, analog sensors, etc. + # dxinteractive/ResponsiveAnalogRead + + # Debounce buttons – removes noise from button presses + # thomasfredericks/Bounce2 + + # SPI + SPI + + # I2C + #Wire + + # DNSServer + # DNSServer + + # Send commands to this board over serial + # ppedro74/SerialCommands + + # Schedule tasks, timers, etc. + # arkhipenko/TaskScheduler + +[env:raspberrypi-pico] +; The Raspberry Pi Pico +; Link: https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html +; For more information about the platformio support: +; https://arduino-pico.readthedocs.io/en/latest/platformio.html +platform = https://github.com/maxgerhardt/platform-raspberrypi.git +board_build.core = earlephilhower +board = pico +board_build.mcu = rp2040 +board_build.f_cpu = 133000000L +upload_protocol = picotool +; in reference to a board = pico config (2MB flash) +; Flash Size: 2MB (Sketch: 1MB, FS:1MB) +; board_build.filesystem_size = 1m +; Flash Size: 2MB (No FS) +; board_build.filesystem_size = 0m +; Flash Size: 2MB (Sketch: 0.5MB, FS:1.5MB) +; board_build.filesystem_size = 1.5m + +; Extend build flags from the global section to enable TinyUSB support +build_flags = ${env.build_flags} -DUSE_TINYUSB +lib_deps = + ${env.lib_deps} + + # USB support + Adafruit TinyUSB Library + +[env:raspberrypi-picow] +; Extends the above to use picow instead of pico board +extends = env:raspberrypi-pico +; BTC and BLE +build_flags = ${env.build_flags} -DUSE_TINYUSB -DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH +lib_deps = + ${env.lib_deps} + + # USB support + Adafruit TinyUSB Library + + # WIFI support + # WiFi + +[env:esp32dev] +platform = espressif32 +board = esp32dev + +[env:nodemcuv2-esp8266] +; The NodeMCU v3 board based on the ESP8266 +; Commonly found on Ebay, Aliexpress, etc. + +# build_flags = ${env.build_flags} +platform = espressif8266 +board = nodemcuv2 +lib_deps = + ${env.lib_deps} + + # Enable WIFI on ESP8266 + # ESP8266WiFi + + # Webserver on ESP8266 + # ESP8266WebServer + + # WIFI Manager + # https://github.com/tzapu/WiFiManager + +[env:teensy41] +platform = teensy +board = teensy41 +build_flags = ${env.build_flags} -DUSB_MIDI_SERIAL + +[env:teensy40] +platform = teensy +board = teensy40 +build_flags = ${env.build_flags} -DUSB_MIDI_SERIAL + +; Teensy LC +[env:teensylc] +platform = teensy +board = teensylc +; Additional build flags for Teensy LC here +build_flags = + ${env.build_flags} +; Additional libraries for Teensy LC here +lib_deps = + ${env.lib_deps} + +; Adafruit Feather ESP32-S2 +[env:adafruit_feather_esp32s2] +platform = espressif32 +board = adafruit_feather_esp32s2 +; Additional build flags for Adafruit Feather ESP32-S2 here +build_flags = + ${env.build_flags} +; Additional libraries for Adafruit Feather ESP32-S2 here +lib_deps = + ${env.lib_deps} + +; Adafruit ESP32 Feather +[env:featheresp32] +platform = espressif32 +board = featheresp32 +; Additional build flags for Adafruit ESP32 Feather here +build_flags = + ${env.build_flags} +; Additional libraries for Adafruit ESP32 Feather here +lib_deps = + ${env.lib_deps} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..3c6211a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,11 @@ +#include + +void setup() { + // Setup here + Serial.begin(115200); + // Serial.println("Hello World!"); +} + +void loop() { + // Loop code here +} diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html