diff --git a/README.md b/README.md index 42386e2..c2e0773 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,34 @@ # Macrolev -Custom analog keyboard based on Hall Effect switches. +Macrolev is a custom analog keyboard powered by Hall Effect switches + +![keyboard - picture from above](assets/keyboard-top.png) +[bottom picture](assets/keyboard-bot.png) - [pcb picture](assets/pcb-bot.png) + +I use the two prototypes shown above as my daily drivers for both coding and gaming. They work well, and the current state of the web configurator is sufficient for seamlessly switching between coding and gaming modes. The current layout of my prototypes is Mac ISO azerty (FR). + +## Features + +- **Analog Input:** Each key detects varying levels of pressure thanks to Hall Effect technology, allowing for a more responsive and sensitive typing experience. +- **Rapid Trigger Support:** Enables keys to actuate without fully releasing, allowing for faster response times during intense usage (e.g., gaming or rapid typing). +- **Continuous Rapid Trigger:** For keys that require repeated pressing (e.g., in gaming), this feature allows automatic repeated key input with a single press. +- **Tap and Hold Functionality:** Each key can be assigned two functions. A tap function for quick presses and a hold function for longer presses. This is ideal for combining shortcuts or creating multi-functional keys, such as assigning the right Shift key to act as an arrow up when tapped. +- **Web-Based Configurator:** Allows customization of key sensitivity and rapid trigger settings, with future updates planned to enable key mapping and expanded functionality. (see [screenshot](assets/web-configurator-screenshot.png)) + +## Links - [keyboard layout](http://www.keyboard-layout-editor.com/#/gists/9dc992fd631d9f29cc5bdf738b10b4e4) -- [Onshape project](https://cad.onshape.com/documents/2af2025c576c4f084cb26625/w/9564bb1d9dfbd4b4af4294c8/e/e2406b8294380372b9116245) +- [Onshape - Case](https://cad.onshape.com/documents/2af2025c576c4f084cb26625/w/9564bb1d9dfbd4b4af4294c8/e/e2406b8294380372b9116245) +- [Onshape - Low profile MX keycaps](https://cad.onshape.com/documents/93ff700fd3fbb6e9cde6f6e3) - [Rev 1.0 Schema](https://kicanvas.org/?github=https%3A%2F%2Fgithub.com%2Fheiso%2Fmacrolev%2Fblob%2Frev-1.0%2Fkicad%2Fmacrolev.kicad_sch) - [Rev 1.0 Pcb](https://kicanvas.org/?github=https%3A%2F%2Fgithub.com%2Fheiso%2Fmacrolev%2Fblob%2Frev-1.0%2Fkicad%2Fmacrolev.kicad_pcb) - [WIP Rev 1.1 Schema](https://kicanvas.org/?github=https%3A%2F%2Fgithub.com%2Fheiso%2Fmacrolev%2Fblob%2Fmain%2Fkicad%2Fmacrolev.kicad_sch) - [WIP Rev 1.1 Pcb](https://kicanvas.org/?github=https%3A%2F%2Fgithub.com%2Fheiso%2Fmacrolev%2Fblob%2Fmain%2Fkicad%2Fmacrolev.kicad_pcb) - [Web Configurator](https://heiso.github.io/macrolev/) - ![web configurator screenshot](assets/web-configurator-screenshot.png) - -## Todo - -### Must Have - -- ~~Move from RP2040 to STM32F4 mcu~~ -- ~~debug adc values~~ -- ~~change keyboard descriptor~~ - -### Should Have - -- ~~Rapid trigger~~ -- web configurator -- haptic feedback - -### Could Have -- Trackpad -- C to Rust -- jtag +## Misc -## Ref +### References - ~~[RP2040 Datasheet](https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf)~~ - ~~[RP2040 Hardware Design](https://datasheets.raspberrypi.com/rp2040/hardware-design-with-rp2040.pdf)~~ @@ -53,14 +50,14 @@ Custom analog keyboard based on Hall Effect switches. - [Connecting to uncommon HID devices](https://developer.chrome.com/articles/hid) - [HID Descriptor parser](https://eleccelerator.com/usbdescreqparser/) -## Tooling +### Tooling - [QMK keyboard test](https://config.qmk.fm/#/test) - [Keyboard ghosting interactive demonstration](https://www.microsoft.com/applied-sciences/projects/anti-ghosting-demo) - [JLC2KiCad_lib](https://github.com/TousstNicolas/JLC2KiCad_lib) - [Debug HardFault](https://interrupt.memfault.com/blog/cortex-m-hardfault-debug) -## PCB reviews +### PCB reviews -[Review request on PrintedCircuitBoard](https://www.reddit.com/r/PrintedCircuitBoard/comments/17hjp88/review_request_analog_keyboard) -[Second review request on PrintedCircuitBoard](https://www.reddit.com/r/PrintedCircuitBoard/comments/17kqc2j/review_request_analog_keyboard_2/) +- [Review request on PrintedCircuitBoard](https://www.reddit.com/r/PrintedCircuitBoard/comments/17hjp88/review_request_analog_keyboard) +- [Second review request on PrintedCircuitBoard](https://www.reddit.com/r/PrintedCircuitBoard/comments/17kqc2j/review_request_analog_keyboard_2/) diff --git a/assets/keyboard-bot.png b/assets/keyboard-bot.png new file mode 100644 index 0000000..5186e70 Binary files /dev/null and b/assets/keyboard-bot.png differ diff --git a/assets/keyboard-top.png b/assets/keyboard-top.png new file mode 100644 index 0000000..d6ac0b5 Binary files /dev/null and b/assets/keyboard-top.png differ diff --git a/assets/mcu-zoomed.png b/assets/mcu-zoomed.png deleted file mode 100644 index 213d3e1..0000000 Binary files a/assets/mcu-zoomed.png and /dev/null differ diff --git a/assets/pcb-bot.png b/assets/pcb-bot.png new file mode 100644 index 0000000..9d1d669 Binary files /dev/null and b/assets/pcb-bot.png differ diff --git a/assets/pcb.png b/assets/pcb.png deleted file mode 100644 index dde023a..0000000 Binary files a/assets/pcb.png and /dev/null differ diff --git a/assets/schema.pdf b/assets/schema.pdf deleted file mode 100644 index 561adaa..0000000 Binary files a/assets/schema.pdf and /dev/null differ diff --git a/assets/schema.png b/assets/schema.png deleted file mode 100644 index 161b15e..0000000 Binary files a/assets/schema.png and /dev/null differ diff --git a/assets/usbc.png b/assets/usbc.png index 4f9823e..5162c43 100644 Binary files a/assets/usbc.png and b/assets/usbc.png differ diff --git a/assets/web-configurator-screenshot.png b/assets/web-configurator-screenshot.png index 5dd8923..850f29f 100644 Binary files a/assets/web-configurator-screenshot.png and b/assets/web-configurator-screenshot.png differ diff --git a/firmware-old/.vscode/arduino.json b/firmware-old/.vscode/arduino.json deleted file mode 100644 index 8b5da41..0000000 --- a/firmware-old/.vscode/arduino.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "port": "/dev/tty.usbmodem2101" -} \ No newline at end of file diff --git a/firmware-old/.vscode/c_cpp_properties.json b/firmware-old/.vscode/c_cpp_properties.json deleted file mode 100644 index 8ebf037..0000000 --- a/firmware-old/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "${workspaceFolder}/firmware/**" - ], - "defines": [], - "macFrameworkPath": [], - "compilerPath": "/opt/homebrew/bin/arm-none-eabi-gcc", - "cStandard": "gnu17", - "cppStandard": "gnu++14", - "intelliSenseMode": "macos-gcc-arm", - "configurationProvider": "ms-vscode.cmake-tools" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/firmware-old/.vscode/settings.json b/firmware-old/.vscode/settings.json deleted file mode 100644 index de71218..0000000 --- a/firmware-old/.vscode/settings.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "typescript.preferences.importModuleSpecifier": "relative", - "typescript.tsdk": "./node_modules/typescript/lib", - "cmake.configureOnOpen": true, - "cmake.sourceDirectory": "${workspaceFolder}/firmware", - "cmake.buildDirectory": "${workspaceFolder}/firmware/build", - "files.associations": { - "usb_descriptors.h": "c", - "board.h": "c", - "tusb.h": "c", - "stdlib.h": "c", - "clocks.h": "c", - "cstdlib": "c", - "void_switches.h": "c", - "config.h": "c", - "*.tcc": "c", - "cmath": "c", - "functional": "c" - } -} diff --git a/firmware-old/CMakeLists.txt b/firmware-old/CMakeLists.txt deleted file mode 100644 index fee9e66..0000000 --- a/firmware-old/CMakeLists.txt +++ /dev/null @@ -1,120 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -# initialize pico-sdk from GIT -# (note this can come from environment, CMake cache etc) -set(PICO_SDK_FETCH_FROM_GIT on) - -# pico_sdk_import.cmake is a single file copied from this SDK -# note: this must happen before project() -include(pico_sdk_import.cmake) - -project(macrolev) - -# initialize the Raspberry Pi Pico SDK -pico_sdk_init() - -############################## -# Main -############################## - -add_executable(main) - -target_sources(main PUBLIC - src/main.c - src/usb_descriptors.c - src/rotary_encoder.c - src/void_switches.c - src/DRV2605L.c -) - -target_include_directories(main PUBLIC src) - -# pull in common dependencies -target_link_libraries(main PUBLIC pico_stdlib hardware_pio hardware_i2c hardware_adc hardware_dma tinyusb_device tinyusb_board) - -# create map/bin/hex/uf2 file etc. -pico_add_extra_outputs(main) - -add_custom_command(TARGET main POST_BUILD COMMAND cp main.uf2 /Volumes/RPI-RP2/NEW.uf2) - -############################## -# Rotary test -############################## - -add_executable(test_rotary) - -target_sources(test_rotary PUBLIC tests/rotary.c src/rotary_encoder.c) - -target_include_directories(main PUBLIC src) - -# pull in common dependencies -target_link_libraries(test_rotary PUBLIC pico_stdlib hardware_pio) - -# enable usb output, disable uart output -pico_enable_stdio_usb(test_rotary 1) -pico_enable_stdio_uart(test_rotary 0) - -# create map/bin/hex/uf2 file etc. -pico_add_extra_outputs(test_rotary) - -add_custom_command(TARGET test_rotary POST_BUILD COMMAND cp test_rotary.uf2 /Volumes/RPI-RP2/NEW.uf2) - -############################## -# Usb test -############################## - -add_executable(test_usb) - -target_sources(test_usb PUBLIC tests/usb.c) - -# pull in common dependencies -target_link_libraries(test_usb PUBLIC pico_stdlib) - -# enable usb output, disable uart output -pico_enable_stdio_usb(test_usb 1) -pico_enable_stdio_uart(test_usb 0) - -# create map/bin/hex/uf2 file etc. -pico_add_extra_outputs(test_usb) - -add_custom_command(TARGET test_usb POST_BUILD COMMAND cp test_usb.uf2 /Volumes/RPI-RP2/NEW.uf2) - -############################## -# Void switches test -############################## - -add_executable(test_void_switches) - -target_sources(test_void_switches PUBLIC tests/void_switches.c src/void_switches.c src/utils.c) - -# pull in common dependencies -target_link_libraries(test_void_switches PUBLIC pico_stdlib hardware_adc hardware_clocks) - -# enable usb output, disable uart output -pico_enable_stdio_usb(test_void_switches 1) -pico_enable_stdio_uart(test_void_switches 0) - -# create map/bin/hex/uf2 file etc. -pico_add_extra_outputs(test_void_switches) - -add_custom_command(TARGET test_void_switches POST_BUILD COMMAND cp test_void_switches.uf2 /Volumes/RPI-RP2/NEW.uf2) - -############################## -# drv2605L test -############################## - -add_executable(test_drv2605L) - -target_sources(test_drv2605L PUBLIC tests/drv2605L.c src/DRV2605L.c) - -# pull in common dependencies -target_link_libraries(test_drv2605L PUBLIC pico_stdlib hardware_i2c) - -# enable usb output, disable uart output -pico_enable_stdio_usb(test_drv2605L 1) -pico_enable_stdio_uart(test_drv2605L 0) - -# create map/bin/hex/uf2 file etc. -pico_add_extra_outputs(test_drv2605L) - -add_custom_command(TARGET test_drv2605L POST_BUILD COMMAND cp test_drv2605L.uf2 /Volumes/RPI-RP2/NEW.uf2) \ No newline at end of file diff --git a/firmware-old/pico_sdk_import.cmake b/firmware-old/pico_sdk_import.cmake deleted file mode 100644 index 65f8a6f..0000000 --- a/firmware-old/pico_sdk_import.cmake +++ /dev/null @@ -1,73 +0,0 @@ -# This is a copy of /external/pico_sdk_import.cmake - -# This can be dropped into an external project to help locate this SDK -# It should be include()ed prior to project() - -if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) - set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) - message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") -endif () - -if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) - set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) - message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") -endif () - -if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) - set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) - message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") -endif () - -set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") -set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") -set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") - -if (NOT PICO_SDK_PATH) - if (PICO_SDK_FETCH_FROM_GIT) - include(FetchContent) - set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) - if (PICO_SDK_FETCH_FROM_GIT_PATH) - get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") - endif () - # GIT_SUBMODULES_RECURSE was added in 3.17 - if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") - FetchContent_Declare( - pico_sdk - GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk - GIT_TAG master - GIT_SUBMODULES_RECURSE FALSE - ) - else () - FetchContent_Declare( - pico_sdk - GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk - GIT_TAG master - ) - endif () - - if (NOT pico_sdk) - message("Downloading Raspberry Pi Pico SDK") - FetchContent_Populate(pico_sdk) - set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) - endif () - set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) - else () - message(FATAL_ERROR - "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." - ) - endif () -endif () - -get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") -if (NOT EXISTS ${PICO_SDK_PATH}) - message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") -endif () - -set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) -if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) - message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") -endif () - -set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) - -include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/firmware-old/src/DRV2605L.c b/firmware-old/src/DRV2605L.c deleted file mode 100644 index 4a0fc4d..0000000 --- a/firmware-old/src/DRV2605L.c +++ /dev/null @@ -1,159 +0,0 @@ -#include "DRV2605L.h" -#include "config.h" -#include "hardware/i2c.h" -#include "pico/stdlib.h" -#include - -/**************************************************************************/ -/*! - @brief Read an 8-bit register. - @param reg The register to read. - @return 8-bit value of the register. -*/ -/**************************************************************************/ -uint8_t readRegister8(uint8_t reg) { - uint8_t buffer[1] = {reg}; - i2c_write_blocking(I2C_INSTANCE, DRV2605_ADDR, buffer, 1, true); - i2c_read_blocking(I2C_INSTANCE, DRV2605_ADDR, buffer, 1, false); - return buffer[0]; -} - -/**************************************************************************/ -/*! - @brief Write an 8-bit register. - @param reg The register to write. - @param val The value to write. -*/ -/**************************************************************************/ -void writeRegister8(uint8_t reg, uint8_t val) { - uint8_t buffer[2] = {reg, val}; - i2c_write_blocking(I2C_INSTANCE, DRV2605_ADDR, buffer, 2, false); -} - -/**************************************************************************/ -/*! - @brief Select the haptic waveform to use. - @param slot The waveform slot to set, from 0 to 7 - @param w The waveform sequence value, refers to an index in the ROM library. - - Playback starts at slot 0 and continues through to slot 7, stopping if it - encounters a value of 0. A list of available waveforms can be found in - section 11.2 of the datasheet: http://www.adafruit.com/datasheets/DRV2605.pdf -*/ -/**************************************************************************/ -void drv2605l_setWaveform(uint8_t slot, uint8_t w) { - writeRegister8(DRV2605_REG_WAVESEQ1 + slot, w); -} - -/**************************************************************************/ -/*! - @brief Select the waveform library to use. - @param lib Library to use, 0 = Empty, 1-5 are ERM, 6 is LRA. - - See section 7.6.4 in the datasheet for more details: - http://www.adafruit.com/datasheets/DRV2605.pdf -*/ -/**************************************************************************/ -void drv2605l_selectLibrary(uint8_t lib) { - writeRegister8(DRV2605_REG_LIBRARY, lib); -} - -/**************************************************************************/ -/*! - @brief Start playback of the waveforms (start moving!). -*/ -/**************************************************************************/ -void drv2605l_go() { writeRegister8(DRV2605_REG_GO, 1); } - -/**************************************************************************/ -/*! - @brief Stop playback. -*/ -/**************************************************************************/ -void drv2605l_stop() { writeRegister8(DRV2605_REG_GO, 0); } - -/**************************************************************************/ -/*! - @brief Set the device mode. - @param mode Mode value, see datasheet section 7.6.2: - http://www.adafruit.com/datasheets/DRV2605.pdf - - 0: Internal trigger, call go() to start playback\n - 1: External trigger, rising edge on IN pin starts playback\n - 2: External trigger, playback follows the state of IN pin\n - 3: PWM/analog input\n - 4: Audio\n - 5: Real-time playback\n - 6: Diagnostics\n - 7: Auto calibration -*/ -/**************************************************************************/ -void drv2605l_setMode(uint8_t mode) { - writeRegister8(DRV2605_REG_MODE, mode); -} - -/**************************************************************************/ -/*! - @brief Set the realtime value when in RTP mode, used to directly drive the - haptic motor. - @param rtp 8-bit drive value. -*/ -/**************************************************************************/ -void drv2605l_setRealtimeValue(uint8_t rtp) { - writeRegister8(DRV2605_REG_RTPIN, rtp); -} - -/**************************************************************************/ -/*! - @brief Use ERM (Eccentric Rotating Mass) mode. -*/ -/**************************************************************************/ -void drv2605l_useERM() { - writeRegister8(DRV2605_REG_FEEDBACK, - readRegister8(DRV2605_REG_FEEDBACK) & 0x7F); -} - -/**************************************************************************/ -/*! - @brief Use LRA (Linear Resonance Actuator) mode. -*/ -/**************************************************************************/ -void drv2605l_useLRA() { - writeRegister8(DRV2605_REG_FEEDBACK, - readRegister8(DRV2605_REG_FEEDBACK) | 0x80); -} - -void drv2605l_init() { - i2c_init(I2C_INSTANCE, 100 * 1000); - gpio_set_function(PIN_I2C_SDA, GPIO_FUNC_I2C); - gpio_set_function(PIN_I2C_SCL, GPIO_FUNC_I2C); - gpio_pull_up(PIN_I2C_SDA); - gpio_pull_up(PIN_I2C_SCL); - - sleep_us(250); - uint8_t id = readRegister8(DRV2605_REG_STATUS); - // Serial.print("Status 0x"); Serial.println(id, HEX); - - writeRegister8(DRV2605_REG_MODE, 0x00); // out of standby - - writeRegister8(DRV2605_REG_RTPIN, 0x00); // no real-time-playback - - writeRegister8(DRV2605_REG_WAVESEQ1, 1); // strong click - writeRegister8(DRV2605_REG_WAVESEQ2, 0); // end sequence - - writeRegister8(DRV2605_REG_OVERDRIVE, 0); // no overdrive - - writeRegister8(DRV2605_REG_SUSTAINPOS, 0); - writeRegister8(DRV2605_REG_SUSTAINNEG, 0); - writeRegister8(DRV2605_REG_BREAK, 0); - writeRegister8(DRV2605_REG_AUDIOMAX, 0x64); - - // ERM open loop - - // turn off N_ERM_LRA - writeRegister8(DRV2605_REG_FEEDBACK, - readRegister8(DRV2605_REG_FEEDBACK) & 0x7F); - // turn on ERM_OPEN_LOOP - writeRegister8(DRV2605_REG_CONTROL3, - readRegister8(DRV2605_REG_CONTROL3) | 0x20); -} diff --git a/firmware-old/src/DRV2605L.h b/firmware-old/src/DRV2605L.h deleted file mode 100644 index 1116e28..0000000 --- a/firmware-old/src/DRV2605L.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef _DRV2605_H -#define _DRV2605_H - -#include - -#define DRV2605_ADDR 0x5A ///< Device I2C address - -#define DRV2605_REG_STATUS 0x00 ///< Status register -#define DRV2605_REG_MODE 0x01 ///< Mode register -#define DRV2605_MODE_INTTRIG 0x00 ///< Internal trigger mode -#define DRV2605_MODE_EXTTRIGEDGE 0x01 ///< External edge trigger mode -#define DRV2605_MODE_EXTTRIGLVL 0x02 ///< External level trigger mode -#define DRV2605_MODE_PWMANALOG 0x03 ///< PWM/Analog input mode -#define DRV2605_MODE_AUDIOVIBE 0x04 ///< Audio-to-vibe mode -#define DRV2605_MODE_REALTIME 0x05 ///< Real-time playback (RTP) mode -#define DRV2605_MODE_DIAGNOS 0x06 ///< Diagnostics mode -#define DRV2605_MODE_AUTOCAL 0x07 ///< Auto calibration mode - -#define DRV2605_REG_RTPIN 0x02 ///< Real-time playback input register -#define DRV2605_REG_LIBRARY 0x03 ///< Waveform library selection register -#define DRV2605_REG_WAVESEQ1 0x04 ///< Waveform sequence register 1 -#define DRV2605_REG_WAVESEQ2 0x05 ///< Waveform sequence register 2 -#define DRV2605_REG_WAVESEQ3 0x06 ///< Waveform sequence register 3 -#define DRV2605_REG_WAVESEQ4 0x07 ///< Waveform sequence register 4 -#define DRV2605_REG_WAVESEQ5 0x08 ///< Waveform sequence register 5 -#define DRV2605_REG_WAVESEQ6 0x09 ///< Waveform sequence register 6 -#define DRV2605_REG_WAVESEQ7 0x0A ///< Waveform sequence register 7 -#define DRV2605_REG_WAVESEQ8 0x0B ///< Waveform sequence register 8 - -#define DRV2605_REG_GO 0x0C ///< Go register -#define DRV2605_REG_OVERDRIVE 0x0D ///< Overdrive time offset register -#define DRV2605_REG_SUSTAINPOS 0x0E ///< Sustain time offset, positive register -#define DRV2605_REG_SUSTAINNEG 0x0F ///< Sustain time offset, negative register -#define DRV2605_REG_BREAK 0x10 ///< Brake time offset register -#define DRV2605_REG_AUDIOCTRL 0x11 ///< Audio-to-vibe control register -#define DRV2605_REG_AUDIOLVL 0x12 ///< Audio-to-vibe minimum input level register -#define DRV2605_REG_AUDIOMAX 0x13 ///< Audio-to-vibe maximum input level register -#define DRV2605_REG_AUDIOOUTMIN 0x14 ///< Audio-to-vibe minimum output drive register -#define DRV2605_REG_AUDIOOUTMAX 0x15 ///< Audio-to-vibe maximum output drive register -#define DRV2605_REG_RATEDV 0x16 ///< Rated voltage register -#define DRV2605_REG_CLAMPV 0x17 ///< Overdrive clamp voltage register -#define DRV2605_REG_AUTOCALCOMP 0x18 ///< Auto-calibration compensation result register -#define DRV2605_REG_AUTOCALEMP 0x19 ///< Auto-calibration back-EMF result register -#define DRV2605_REG_FEEDBACK 0x1A ///< Feedback control register -#define DRV2605_REG_CONTROL1 0x1B ///< Control1 Register -#define DRV2605_REG_CONTROL2 0x1C ///< Control2 Register -#define DRV2605_REG_CONTROL3 0x1D ///< Control3 Register -#define DRV2605_REG_CONTROL4 0x1E ///< Control4 Register -#define DRV2605_REG_VBAT 0x21 ///< Vbat voltage-monitor register -#define DRV2605_REG_LRARESON 0x22 ///< LRA resonance-period register - -// Effects: -// 1 − Strong Click - 100% -// 2 − Strong Click - 60% -// 3 − Strong Click - 30% -// 4 − Sharp Click - 100% -// 5 − Sharp Click - 60% -// 6 − Sharp Click - 30% -// 7 − Soft Bump - 100% -// 8 − Soft Bump - 60% -// 9 − Soft Bump - 30% -// 10 − Double Click - 100% -// 11 − Double Click - 60% -// 12 − Triple Click - 100% -// 13 − Soft Fuzz - 60% -// 14 − Strong Buzz - 100% -// 15 − 750 ms Alert 100% -// 16 − 1000 ms Alert 100% -// 17 − Strong Click 1 - 100% -// 18 − Strong Click 2 - 80% -// 19 − Strong Click 3 - 60% -// 20 − Strong Click 4 - 30% -// 21 − Medium Click 1 - 100% -// 22 − Medium Click 2 - 80% -// 23 − Medium Click 3 - 60% -// 24 − Sharp Tick 1 - 100% -// 25 − Sharp Tick 2 - 80% -// 26 − Sharp Tick 3 – 60% -// 27 − Short Double Click Strong 1 – 100% -// 28 − Short Double Click Strong 2 – 80% -// 29 − Short Double Click Strong 3 – 60% -// 30 − Short Double Click Strong 4 – 30% -// 31 − Short Double Click Medium 1 – 100% -// 32 − Short Double Click Medium 2 – 80% -// 33 − Short Double Click Medium 3 – 60% -// 34 − Short Double Sharp Tick 1 – 100% -// 35 − Short Double Sharp Tick 2 – 80% -// 36 − Short Double Sharp Tick 3 – 60% -// 37 − Long Double Sharp Click Strong 1 – 100% -// 38 − Long Double Sharp Click Strong 2 – 80% -// 39 − Long Double Sharp Click Strong 3 – 60% -// 40 − Long Double Sharp Click Strong 4 – 30% -// 41 − Long Double Sharp Click Medium 1 – 100% -// 42 − Long Double Sharp Click Medium 2 – 80% -// 43 − Long Double Sharp Click Medium 3 – 60% -// 44 − Long Double Sharp Tick 1 – 100% -// 45 − Long Double Sharp Tick 2 – 80% -// 46 − Long Double Sharp Tick 3 – 60% -// 47 − Buzz 1 – 100% -// 48 − Buzz 2 – 80% -// 49 − Buzz 3 – 60% -// 50 − Buzz 4 – 40% -// 51 − Buzz 5 – 20% -// 52 − Pulsing Strong 1 – 100% -// 53 − Pulsing Strong 2 – 60% -// 54 − Pulsing Medium 1 – 100% -// 55 − Pulsing Medium 2 – 60% -// 56 − Pulsing Sharp 1 – 100% -// 57 − Pulsing Sharp 2 – 60% -// 58 − Transition Click 1 – 100% -// 59 − Transition Click 2 – 80% -// 60 − Transition Click 3 – 60% -// 61 − Transition Click 4 – 40% -// 62 − Transition Click 5 – 20% -// 63 − Transition Click 6 – 10% -// 64 − Transition Hum 1 – 100% -// 65 − Transition Hum 2 – 80% -// 66 − Transition Hum 3 – 60% -// 67 − Transition Hum 4 – 40% -// 68 − Transition Hum 5 – 20% -// 69 − Transition Hum 6 – 10% -// 70 − Transition Ramp Down Long Smooth 1 – 100 to 0% -// 71 − Transition Ramp Down Long Smooth 2 – 100 to 0% -// 72 − Transition Ramp Down Medium Smooth 1 – 100 to 0% -// 73 − Transition Ramp Down Medium Smooth 2 – 100 to 0% -// 74 − Transition Ramp Down Short Smooth 1 – 100 to 0% -// 75 − Transition Ramp Down Short Smooth 2 – 100 to 0% -// 76 − Transition Ramp Down Long Sharp 1 – 100 to 0% -// 77 − Transition Ramp Down Long Sharp 2 – 100 to 0% -// 78 − Transition Ramp Down Medium Sharp 1 – 100 to 0% -// 79 − Transition Ramp Down Medium Sharp 2 – 100 to 0% -// 80 − Transition Ramp Down Short Sharp 1 – 100 to 0% -// 81 − Transition Ramp Down Short Sharp 2 – 100 to 0% -// 82 − Transition Ramp Up Long Smooth 1 – 0 to 100% -// 83 − Transition Ramp Up Long Smooth 2 – 0 to 100% -// 84 − Transition Ramp Up Medium Smooth 1 – 0 to 100% -// 85 − Transition Ramp Up Medium Smooth 2 – 0 to 100% -// 86 − Transition Ramp Up Short Smooth 1 – 0 to 100% -// 87 − Transition Ramp Up Short Smooth 2 – 0 to 100% -// 88 − Transition Ramp Up Long Sharp 1 – 0 to 100% -// 89 − Transition Ramp Up Long Sharp 2 – 0 to 100% -// 90 − Transition Ramp Up Medium Sharp 1 – 0 to 100% -// 91 − Transition Ramp Up Medium Sharp 2 – 0 to 100% -// 92 − Transition Ramp Up Short Sharp 1 – 0 to 100% -// 93 − Transition Ramp Up Short Sharp 2 – 0 to 100% -// 94 − Transition Ramp Down Long Smooth 1 – 50 to 0% -// 95 − Transition Ramp Down Long Smooth 2 – 50 to 0% -// 96 − Transition Ramp Down Medium Smooth 1 – 50 to 0% -// 97 − Transition Ramp Down Medium Smooth 2 – 50 to 0% -// 98 − Transition Ramp Down Short Smooth 1 – 50 to 0% -// 99 − Transition Ramp Down Short Smooth 2 – 50 to 0% -// 100 − Transition Ramp Down Long Sharp 1 – 50 to 0% -// 101 − Transition Ramp Down Long Sharp 2 – 50 to 0% -// 102 − Transition Ramp Down Medium Sharp 1 – 50 to 0% -// 103 − Transition Ramp Down Medium Sharp 2 – 50 to 0% -// 104 − Transition Ramp Down Short Sharp 1 – 50 to 0% -// 105 − Transition Ramp Down Short Sharp 2 – 50 to 0% -// 106 − Transition Ramp Up Long Smooth 1 – 0 to 50% -// 107 − Transition Ramp Up Long Smooth 2 – 0 to 50% -// 108 − Transition Ramp Up Medium Smooth 1 – 0 to 50% -// 109 − Transition Ramp Up Medium Smooth 2 – 0 to 50% -// 110 − Transition Ramp Up Short Smooth 1 – 0 to 50% -// 111 − Transition Ramp Up Short Smooth 2 – 0 to 50% -// 112 − Transition Ramp Up Long Sharp 1 – 0 to 50% -// 113 − Transition Ramp Up Long Sharp 2 – 0 to 50% -// 114 − Transition Ramp Up Medium Sharp 1 – 0 to 50% -// 115 − Transition Ramp Up Medium Sharp 2 – 0 to 50% -// 116 − Transition Ramp Up Short Sharp 1 – 0 to 50% -// 117 − Transition Ramp Up Short Sharp 2 – 0 to 50% -// 118 − Long buzz for programmatic stopping – 100% -// 119 − Smooth Hum 1 (No kick or brake pulse) – 50% -// 120 − Smooth Hum 2 (No kick or brake pulse) – 40% -// 121 − Smooth Hum 3 (No kick or brake pulse) – 30% -// 122 − Smooth Hum 4 (No kick or brake pulse) – 20% -// 123 − Smooth Hum 5 (No kick or brake pulse) – 10% - -/**************************************************************************/ -/*! - @brief The DRV2605 driver class. -*/ -/**************************************************************************/ -void drv2605l_init(); -void writeRegister8(uint8_t reg, uint8_t val); -uint8_t readRegister8(uint8_t reg); -void drv2605l_setWaveform(uint8_t slot, uint8_t w); -void drv2605l_selectLibrary(uint8_t lib); -void drv2605l_go(void); -void drv2605l_stop(void); -void drv2605l_setMode(uint8_t mode); -void drv2605l_setRealtimeValue(uint8_t rtp); -// Select ERM (Eccentric Rotating Mass) or LRA (Linear Resonant Actuator) -// vibration motor The default is ERM, which is more common -void drv2605l_useERM(); -void drv2605l_useLRA(); - -#endif diff --git a/firmware-old/src/config.h b/firmware-old/src/config.h deleted file mode 100644 index e2dcfb1..0000000 --- a/firmware-old/src/config.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef CONFIG_H_ -#define CONFIG_H_ - -#include "pico/stdlib.h" -#include "tusb.h" - -// KB2040 -#define I2C_INSTANCE i2c0 -#define PIN_ENC_DT 2 -#define PIN_ENC_CLK 3 -#define PIN_ENC_SW 4 -#define PIN_FIRST_COLUMN 26 // Must be an ADC pin -#define PIN_FIRST_ROW 2 -#define PIN_I2C_SDA 12 -#define PIN_I2C_SCL 13 - -// QT py 2040 -// #define I2C_INSTANCE i2c1 -// #define PIN_ENC_DT 3 -// #define PIN_ENC_CLK 4 -// #define PIN_ENC_SW 6 -// #define PIN_FIRST_COLUMN 26 -// #define PIN_FIRST_ROW 24 -// #define PIN_I2C_SDA 22 -// #define PIN_I2C_SCL 23 - -// Pico -// #define I2C_INSTANCE i2c1 -// #define PIN_ENC_DT 6 -// #define PIN_ENC_CLK 7 -// #define PIN_ENC_SW 8 -// #define PIN_FIRST_COLUMN 26 -// #define PIN_FIRST_ROW 21 -// #define PIN_I2C_SDA 18 -// #define PIN_I2C_SCL 19 - -#define COLUMNS 1 // One adc per column -#define ROWS 1 - -// static uint8_t KEYMAP_CONSUMER[ROWS][COLUMNS] = { -// {HID_USAGE_CONSUMER_VOLUME_DECREMENT, HID_USAGE_CONSUMER_PLAY_PAUSE, HID_USAGE_CONSUMER_VOLUME_INCREMENT}, -// {HID_USAGE_CONSUMER_MUTE, HID_KEY_NONE, HID_KEY_NONE}}; - -// static uint8_t KEYMAP[ROWS][COLUMNS] = { -// {HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE}, -// {HID_KEY_NONE, HID_KEY_SEMICOLON, HID_KEY_D}}; - -// static uint8_t KEYMAP_MODIFIERS[ROWS][COLUMNS] = { -// {HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE}, -// {HID_KEY_NONE, KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_LEFTSHIFT, KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_LEFTSHIFT}}; - -#endif \ No newline at end of file diff --git a/firmware-old/src/main.c b/firmware-old/src/main.c deleted file mode 100644 index ed3a088..0000000 --- a/firmware-old/src/main.c +++ /dev/null @@ -1,154 +0,0 @@ -#include "DRV2605L.h" -#include "bsp/board.h" -#include "config.h" -#include "hardware/adc.h" -#include "hardware/gpio.h" -#include "hardware/pio.h" -#include "pico/stdlib.h" -#include "rotary_encoder.h" -#include "stdlib.h" -#include "usb_descriptors.h" -#include "void_switches.h" - -/** - * MUST HAVE - * - understand how keyup hid report should be sent, we might keep the same order - * - consumer descriptor - * - keyboard descriptor - * - keymap and macro (multiple keycodes in one keypress) - * - * NICE TO HAVE - * - rewrite in rust - * - set keymap trough usb - * - NKRO and custom hid descriptor - * - * NOTES - * https://github.com/qmk/qmk_firmware/blob/master/docs/usb_nkro.txt - * https://www.devever.net/~hl/usbnkro - * https://www.microsoft.com/applied-sciences/projects/anti-ghosting-demo - * https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/ - * - * - * usbhid-dump - */ - -static bool can_send_report; -static bool report_sent; -static uint8_t modifiers = 0; -static uint8_t keycodes[6] = {HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE, HID_KEY_NONE}; -static uint16_t consumer_report = HID_KEY_NONE; -static REPORT_ID current_report_id = REPORT_ID_KEYBOARD; - -#define SET_BIT(BITFIELD, INDEX) BITFIELD |= ((uint8_t)1 << INDEX) -#define CLR_BIT(BITFIELD, INDEX) BITFIELD &= ~((uint8_t)1 << INDEX) -#define IS_BIT_SET(BITFIELD, INDEX) ((BITFIELD >> INDEX) & 1) - -void volume_down() { - consumer_report = HID_USAGE_CONSUMER_VOLUME_DECREMENT; - report_sent = false; -} - -void volume_up() { - consumer_report = HID_USAGE_CONSUMER_VOLUME_INCREMENT; - report_sent = false; -} - -void play_pause() { - consumer_report = HID_USAGE_CONSUMER_PLAY_PAUSE; - report_sent = false; -} - -void irq_callback(uint gpio, uint32_t events) { - rotary_encoder_irq_callback(gpio, events, &volume_up, &volume_down, &play_pause); -} - -// Invoked when usb bus is suspended -// remote_wakeup_en : if host allow us to perform remote wakeup -// Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) { -} - -// Invoked when sent REPORT successfully to host -// Application can use this to send the next report -// Note: For composite reports, report[0] is report ID -void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint8_t len) { - current_report_id = current_report_id == REPORT_ID_KEYBOARD ? REPORT_ID_CONSUMER_CONTROL : REPORT_ID_KEYBOARD; - can_send_report = true; -} - -// Invoked when received GET_REPORT control request -// Application must fill buffer report's content and return its length. -// Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { - return reqlen; -} - -// Invoked when received SET_REPORT control request or -// received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { -} - -void void_switches_on_triggered(struct void_switch *vswitch) { - drv2605l_setWaveform(0, 1); - drv2605l_setWaveform(1, 0); - drv2605l_go(); - if (KEYMAP[vswitch->row][vswitch->column] != HID_KEY_NONE) { - uint8_t index = vswitch->row * COLUMNS + vswitch->column; - keycodes[index] = KEYMAP[vswitch->row][vswitch->column]; - modifiers |= KEYMAP_MODIFIERS[vswitch->row][vswitch->column]; - report_sent = false; - } else if (KEYMAP_CONSUMER[vswitch->row][vswitch->column]) { - consumer_report = KEYMAP_CONSUMER[vswitch->row][vswitch->column]; - report_sent = false; - } -} - -void void_switches_on_reset(struct void_switch *vswitch) { - drv2605l_setWaveform(0, 1); - drv2605l_setWaveform(1, 0); - drv2605l_go(); - if (KEYMAP[vswitch->row][vswitch->column] != HID_KEY_NONE) { - uint8_t index = vswitch->row * COLUMNS + vswitch->column; - modifiers &= ~(KEYMAP_MODIFIERS[vswitch->row][vswitch->column]); - keycodes[index] = HID_KEY_NONE; - report_sent = false; - } else if (KEYMAP_CONSUMER[vswitch->row][vswitch->column]) { - consumer_report = HID_KEY_NONE; - report_sent = false; - } -} - -void void_switches_on_change(struct void_switch *vswitch) {} - -int main() { - board_init(); - // init_rotary_encoder(&irq_callback); - tusb_init(); - drv2605l_init(); - drv2605l_selectLibrary(1); - drv2605l_setMode(DRV2605_MODE_INTTRIG); - void_switches_init(25, 0, 0); - - can_send_report = true; - report_sent = true; - - while (1) { - tud_task(); - void_switches_loop(); - - if (tud_hid_ready() && !report_sent && can_send_report) { - if (tud_suspended()) { - tud_remote_wakeup(); - } else { - can_send_report = false; - if (current_report_id == REPORT_ID_KEYBOARD) { - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, modifiers, keycodes); - } else { - tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &consumer_report, sizeof(consumer_report)); - report_sent = true; - } - } - } - } - return 0; -} \ No newline at end of file diff --git a/firmware-old/src/rotary_encoder.c b/firmware-old/src/rotary_encoder.c deleted file mode 100644 index 56c4260..0000000 --- a/firmware-old/src/rotary_encoder.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "rotary_encoder.h" -#include "hardware/gpio.h" -#include "hardware/pio.h" -#include "pico/stdlib.h" -#include "stdlib.h" -#include - -static enum ENCODER_STATE encoder_state = IDLE; -unsigned long last_sw_trigger_time; -const int debounce_time = 250; // Delay for every push button may vary - -void init_rotary_encoder(gpio_irq_callback_t irq_callback) { - last_sw_trigger_time = to_ms_since_boot(get_absolute_time()); - - gpio_init(PIN_ENC_SW); - gpio_set_dir(PIN_ENC_SW, GPIO_IN); - gpio_disable_pulls(PIN_ENC_SW); - - gpio_init(PIN_ENC_DT); - gpio_set_dir(PIN_ENC_DT, GPIO_IN); - gpio_disable_pulls(PIN_ENC_DT); - - gpio_init(PIN_ENC_CLK); - gpio_set_dir(PIN_ENC_CLK, GPIO_IN); - gpio_disable_pulls(PIN_ENC_CLK); - - gpio_set_irq_enabled_with_callback(PIN_ENC_SW, GPIO_IRQ_EDGE_FALL, true, irq_callback); - gpio_set_irq_enabled(PIN_ENC_DT, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true); - gpio_set_irq_enabled(PIN_ENC_CLK, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true); -} - -void rotary_encoder_irq_callback(uint gpio, uint32_t events, cw_callback_t cw_callback, ccw_callback_t ccw_callback, sw_callback_t sw_callback) { - if (gpio == PIN_ENC_CLK || gpio == PIN_ENC_DT) { - bool clk = gpio_get(PIN_ENC_CLK); - bool dt = gpio_get(PIN_ENC_DT); - - switch (encoder_state) { - case IDLE: { - if (!clk && dt) { - encoder_state = CW_1; - } else if (clk && !dt) { - encoder_state = CCW_1; - } - break; - } - - case CW_1: { - if (!clk && !dt) { - encoder_state = CW_2; - } else if (clk && dt) { - encoder_state = IDLE; - } - break; - } - - case CW_2: { - if (clk && !dt) { - encoder_state = CW_3; - } else if (clk && dt) { - encoder_state = IDLE; - } - break; - } - - case CW_3: { - if (clk && dt) { - encoder_state = IDLE; - cw_callback(); - } - break; - } - - case CCW_1: { - if (!clk && !dt) { - encoder_state = CCW_2; - } else if (clk && dt) { - encoder_state = IDLE; - } - break; - } - - case CCW_2: { - if (!clk && dt) { - encoder_state = CCW_3; - } else if (clk && dt) { - encoder_state = IDLE; - } - break; - } - - case CCW_3: { - if (clk && dt) { - encoder_state = IDLE; - ccw_callback(); - } - break; - } - } - } - - if (gpio == PIN_ENC_SW) { - if ((to_ms_since_boot(get_absolute_time()) - last_sw_trigger_time) > debounce_time) { - last_sw_trigger_time = to_ms_since_boot(get_absolute_time()); - sw_callback(); - } - } -} \ No newline at end of file diff --git a/firmware-old/src/rotary_encoder.h b/firmware-old/src/rotary_encoder.h deleted file mode 100644 index 2593445..0000000 --- a/firmware-old/src/rotary_encoder.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ROTARY_ENCODER_H_ -#define ROTARY_ENCODER_H_ - -#include "config.h" -#include "hardware/gpio.h" - -// 00 10 [11] 01 -enum ENCODER_STATE { - IDLE, // 11 - - CW_1, // 01 - CW_2, // 00 - CW_3, // 10, - - CCW_1, // 10 - CCW_2, // 00 - CCW_3, // 01 -}; - -void cw_callback(void); -void ccw_callback(void); -void sw_callback(void); -typedef void (*cw_callback_t)(); -typedef void (*ccw_callback_t)(); -typedef void (*sw_callback_t)(); - -void init_rotary_encoder(gpio_irq_callback_t irq_callback); -void rotary_encoder_irq_callback(uint gpio, uint32_t events, cw_callback_t cw_callback, ccw_callback_t ccw_callback, sw_callback_t sw_callback); - -#endif \ No newline at end of file diff --git a/firmware-old/src/tusb_config.h b/firmware-old/src/tusb_config.h deleted file mode 100644 index 0d23349..0000000 --- a/firmware-old/src/tusb_config.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * 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. - * - */ - -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -//-------------------------------------------------------------------- -// COMMON CONFIGURATION -//-------------------------------------------------------------------- - -// defined by board.mk -#ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined -#endif - -// RHPort number used for device can be defined by board.mk, default to port 0 -#ifndef BOARD_DEVICE_RHPORT_NUM -#define BOARD_DEVICE_RHPORT_NUM 0 -#endif - -// RHPort max operational speed can defined by board.mk -// Default to Highspeed for MCU with internal HighSpeed PHY (can be port -// specific), otherwise FullSpeed -#ifndef BOARD_DEVICE_RHPORT_SPEED -#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 || \ - CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) -#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED -#else -#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED -#endif -#endif - -// Device mode with rhport and speed defined by board.mk -#if BOARD_DEVICE_RHPORT_NUM == 0 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#elif BOARD_DEVICE_RHPORT_NUM == 1 -#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#else -#error "Incorrect RHPort configuration" -#endif - -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE -#endif - -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 - -/* USB DMA on some MCUs can only access a specific SRAM region with restriction - * on alignment. Tinyusb use follows macros to declare transferring memory so - * that they can be put into those specific section. e.g - * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) - * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) - */ -#ifndef CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_SECTION -#endif - -#ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4))) -#endif - -//-------------------------------------------------------------------- -// DEVICE CONFIGURATION -//-------------------------------------------------------------------- - -#ifndef CFG_TUD_ENDPOINT0_SIZE -#define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - -//------------- CLASS -------------// -#define CFG_TUD_HID 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_EP_BUFSIZE 16 - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_CONFIG_H_ */ diff --git a/firmware-old/src/usb_descriptors.c b/firmware-old/src/usb_descriptors.c deleted file mode 100644 index 8ded13a..0000000 --- a/firmware-old/src/usb_descriptors.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * 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. - * - */ - -#include "usb_descriptors.h" -#include "tusb.h" - -/* A combination of interfaces must have a unique product id, since PC will save - * device driver after the first plug. Same VID/PID with different interface e.g - * MSC (first), then CDC (later) will possibly cause system error on PC. - * - * Auto ProductID layout's Bitmap: - * [MSB] HID | MSC | CDC [LSB] - */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) -#define USB_PID \ - (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4)) - -#define USB_VID 0xCafe -#define USB_BCD 0x0200 - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = {.bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = USB_BCD, - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = - CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = USB_VID, - .idProduct = USB_PID, - .bcdDevice = 0x0100, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01}; - -// Invoked when received GET DEVICE DESCRIPTOR -// Application return pointer to descriptor -uint8_t const *tud_descriptor_device_cb(void) { - return (uint8_t const *)&desc_device; -} - -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ - -uint8_t const desc_hid_report[] = { - TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD)), - TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL))}; -// TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID_GAMEPAD)) - -// Invoked when received GET HID REPORT DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) { - (void)instance; - return desc_hid_report; -} - -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ - -enum { ITF_NUM_HID, - ITF_NUM_TOTAL }; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN) - -#define EPNUM_HID 0x81 - -uint8_t const desc_configuration[] = { - // Config number, interface count, string index, total length, attribute, - // power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), - - // Interface number, string index, protocol, report descriptor len, EP In - // address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, - sizeof(desc_hid_report), EPNUM_HID, - CFG_TUD_HID_EP_BUFSIZE, 5)}; - -#if TUD_OPT_HIGH_SPEED -// Per USB specs: high speed capable device must report device_qualifier and -// other_speed_configuration - -// other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; - -// device qualifier is mostly similar to device descriptor since we don't change -// configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { - .bLength = sizeof(tusb_desc_device_qualifier_t), - .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, - .bcdUSB = USB_BCD, - - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .bNumConfigurations = 0x01, - .bReserved = 0x00}; - -// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long -// enough for transfer to complete. device_qualifier descriptor describes -// information about a high-speed capable device that would change if the device -// were operating at the other speed. If not highspeed capable stall this -// request. -uint8_t const *tud_descriptor_device_qualifier_cb(void) { - return (uint8_t const *)&desc_device_qualifier; -} - -// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long -// enough for transfer to complete Configuration descriptor in the other speed -// e.g if high speed then this is for full speed and vice versa -uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { - (void)index; // for multiple configurations - - // other speed config is basically configuration with type = OHER_SPEED_CONFIG - memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN); - desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; - - // this example use the same configuration for both high and full speed mode - return desc_other_speed_config; -} - -#endif // highspeed - -// Invoked when received GET CONFIGURATION DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { - (void)index; // for multiple configurations - - // This example use the same configuration for both high and full speed mode - return desc_configuration; -} - -//--------------------------------------------------------------------+ -// String Descriptors -//--------------------------------------------------------------------+ - -// array of pointer to string descriptors -char const *string_desc_arr[] = { - (const char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) - "Heiso", // 1: Manufacturer - "Macrolev", // 2: Product - "123456", // 3: Serials, should use chip ID -}; - -static uint16_t _desc_str[32]; - -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long -// enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - (void)langid; - - uint8_t chr_count; - - if (index == 0) { - memcpy(&_desc_str[1], string_desc_arr[0], 2); - chr_count = 1; - } else { - // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - - if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) - return NULL; - - const char *str = string_desc_arr[index]; - - // Cap at max char - chr_count = strlen(str); - if (chr_count > 31) - chr_count = 31; - - // Convert ASCII string into UTF-16 - for (uint8_t i = 0; i < chr_count; i++) { - _desc_str[1 + i] = str[i]; - } - } - - // first byte is length (including header), second byte is string type - _desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * chr_count + 2); - - return _desc_str; -} diff --git a/firmware-old/src/usb_descriptors.h b/firmware-old/src/usb_descriptors.h deleted file mode 100644 index ff03e8a..0000000 --- a/firmware-old/src/usb_descriptors.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * 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. - */ - -#ifndef USB_DESCRIPTORS_H_ -#define USB_DESCRIPTORS_H_ - -typedef enum { - REPORT_ID_KEYBOARD = 1, - REPORT_ID_CONSUMER_CONTROL, -} REPORT_ID; - -#endif /* USB_DESCRIPTORS_H_ */ diff --git a/firmware-old/src/utils.c b/firmware-old/src/utils.c deleted file mode 100644 index 1ad5e09..0000000 --- a/firmware-old/src/utils.c +++ /dev/null @@ -1,9 +0,0 @@ -void print_bytes(int bytes) { - for (int i = 12; i >= 0; i--) { - if (1 << i & bytes) { - printf("1"); - } else { - printf("0"); - } - } -} \ No newline at end of file diff --git a/firmware-old/src/utils.h b/firmware-old/src/utils.h deleted file mode 100644 index cb6c06f..0000000 --- a/firmware-old/src/utils.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef UTILS_H_ -#define UTILS_H_ - -void print_bytes(int bytes); - -#endif \ No newline at end of file diff --git a/firmware-old/src/void_switches.c b/firmware-old/src/void_switches.c deleted file mode 100644 index 1c3e329..0000000 --- a/firmware-old/src/void_switches.c +++ /dev/null @@ -1,288 +0,0 @@ -#include "void_switches.h" -#include "config.h" -#include "hardware/adc.h" -#include "hardware/gpio.h" -#include "pico/stdlib.h" -#include -#include -#include -#include - -#define DEBUG 1 - -#define MIN_TIME_BETWEEN_EVENTS_US 10000 // 10ms -#define CONSTANT_LOOP_DURATION_US 50 -#define CALIBRATION_CYCLES 1000 - -#define MIN_VALUE_APPROX 1800 -#define MAX_VALUE_APPROX 2100 -#define MIN_OFFSET 10 -#define MAX_OFFSET 40 - -static struct void_switch vswitches[ROWS][COLUMNS]; - -void void_switches_on_triggered(struct void_switch *vswitch); -void void_switches_on_reset(struct void_switch *vswitch); -void void_switches_on_change(struct void_switch *vswitch); - -void init_switch(uint8_t row, uint8_t column, uint16_t trigger_offset, uint16_t rapid_trigger_offset, uint8_t is_continuous_rapid_trigger_enabled) { - struct void_switch *vswitch = &vswitches[row][column]; - - vswitch->row = row; - vswitch->column = column; - - vswitch->is_enabled = 0; - - vswitch->calibration.is_calibrating = 1; - vswitch->calibration.cycles_count = 0; - vswitch->calibration.min_value = MIN_VALUE_APPROX; - vswitch->calibration.is_min_calibrated = 0; - vswitch->calibration.max_value = MAX_VALUE_APPROX; - vswitch->calibration.is_max_calibrated = 0; - - vswitch->actuation.status = RESET; - vswitch->actuation.changed_at = 0; - vswitch->actuation.trigger_offset = trigger_offset; - vswitch->actuation.rapid_trigger_offset = rapid_trigger_offset; - vswitch->actuation.is_continuous_rapid_trigger_enabled = is_continuous_rapid_trigger_enabled; - - vswitch->state.is_pressing = 0; -} - -void update_switch_state(struct void_switch *vswitch) { - struct state state; - - // Get a reading - state.value = adc_read(); - - // Get distance - if (state.value <= vswitch->calibration.min_value) { - state.distance = 0; - } else if (state.value >= vswitch->calibration.max_value) { - state.distance = vswitch->calibration.max_value - vswitch->calibration.min_value; - } else { - state.distance = state.value - vswitch->calibration.min_value; - } - - // Update velocity - state.velocity = state.distance - vswitch->state.distance; - - // // Update Acceleration - // state.acceleration = (state.velocity - vswitch->state.velocity) / 2; - - // // Update jerk - // state.jerk = (state.acceleration - vswitch->state.acceleration) / 3; - - // Map distance in percentages - state.distance = state.distance * 100 / (vswitch->calibration.max_value - vswitch->calibration.min_value); - - // Update movement - state.is_pressing = vswitch->state.velocity > 0 && state.velocity > 0; - - vswitch->state = state; -} - -void update_switch(struct void_switch *vswitch) { - if (vswitch->calibration.is_calibrating) { - update_switch_state(vswitch); - - // Calibrate min value - vswitch->calibration.min_value = (1 - 0.9) * vswitch->state.value + 0.9 * vswitch->calibration.min_value; - - vswitch->calibration.cycles_count++; - - if (vswitch->calibration.cycles_count >= CALIBRATION_CYCLES) { - vswitch->calibration.is_calibrating = 0; - vswitch->calibration.min_value = vswitch->calibration.min_value + MIN_OFFSET; - - // TODO: Find a better way to detect if a switch is out of order - if (vswitch->calibration.min_value > MIN_VALUE_APPROX * 0.85) { - vswitch->calibration.is_min_calibrated = 1; - } - } - } - - else if (!vswitch->calibration.is_max_calibrated) { - update_switch_state(vswitch); - - // Calibrate max value - // Add some brain, if we never reach max value in multiple pressing/releasing cycles, might change max value - if (vswitch->state.value - MAX_OFFSET > vswitch->calibration.max_value) { - vswitch->calibration.max_value = vswitch->state.value - MAX_OFFSET; - } - - // TODO: Find a better way to detect if a switch is out of order - if (vswitch->calibration.max_value > vswitch->calibration.min_value + 100) { - vswitch->calibration.is_max_calibrated = 1; - vswitch->is_enabled = 1; - } - } - - else if (vswitch->is_enabled) { - update_switch_state(vswitch); - - // Calibrate max value - // Add some brain, if we never reach max value in multiple pressing/releasing cycles, might change max value - if (vswitch->state.value - MAX_OFFSET > vswitch->calibration.max_value) { - vswitch->calibration.max_value = vswitch->state.value - MAX_OFFSET; - } - - // Send event if motion detected - if (vswitch->state.velocity != 0) { - void_switches_on_change(vswitch); - } - - /** - * https://www.youtube.com/watch?v=_Sl-T6iQr8U&t - * - * |-----| <- FULL RESET - - * | | | Continuous rapid trigger domain (deactivated when full_reset) - * | | | - * | - | <- trigger_offset - - * | | | Rapid trigger domain - * | | | - * |-----| - - * - */ - - bool is_ready_to_trigger = time_reached(vswitch->actuation.trigger_timeout); - bool is_reset = vswitch->actuation.status == RESET; - bool has_moved_more_than_min = abs(vswitch->state.distance - vswitch->actuation.changed_at) > 10; - bool is_after_trigger_offset = vswitch->state.distance > vswitch->actuation.trigger_offset; - - // Trigger - if (is_ready_to_trigger && is_reset && has_moved_more_than_min && is_after_trigger_offset) { - vswitch->actuation.status = TRIGGERED; - vswitch->actuation.trigger_timeout = make_timeout_time_us(MIN_TIME_BETWEEN_EVENTS_US); - vswitch->actuation.changed_at = vswitch->state.distance; - void_switches_on_triggered(vswitch); - } - - // Reset - else if (!is_reset && has_moved_more_than_min && !is_after_trigger_offset) { - vswitch->actuation.status = RESET; - vswitch->actuation.changed_at = vswitch->state.distance; - void_switches_on_reset(vswitch); - } - - // Full reset - if (vswitch->state.distance == 0) { - vswitch->actuation.changed_at = 0; - if (!is_reset) { - vswitch->actuation.status = RESET; - void_switches_on_reset(vswitch); - } - } - } -} - -/** - * @brief Init gpios and adc - * - * @param trigger_point Trigger point, when the switch value is or is greater than the trigger point, fire an event. - */ -void void_switches_init(uint16_t trigger_offset, uint16_t rapid_trigger_offset, uint8_t is_continuous_rapid_trigger_enabled) { - for (uint8_t row = 0; row < ROWS; row++) { - for (uint8_t column = 0; column < COLUMNS; column++) { - init_switch(row, column, trigger_offset, rapid_trigger_offset, is_continuous_rapid_trigger_enabled); - } - } - - // Init pins for columns and rows - for (uint8_t i = 0; i < COLUMNS; i++) { - adc_gpio_init(PIN_FIRST_COLUMN + i); - } - for (uint8_t i = 0; i < ROWS; i++) { - gpio_init(PIN_FIRST_ROW + i); - gpio_set_dir(PIN_FIRST_ROW + i, GPIO_OUT); - gpio_disable_pulls(PIN_FIRST_ROW + i); - } - - // Init adc - adc_init(); - - sleep_ms(100); -} - -/** - * @brief Main loop - * - */ -void void_switches_loop() { -#ifdef DEBUG - uint32_t start = time_us_32(); -#endif - - absolute_time_t end = make_timeout_time_us(CONSTANT_LOOP_DURATION_US); - - for (uint8_t row = 0; row < ROWS; row++) { - gpio_put(PIN_FIRST_ROW + row, 1); - - for (uint8_t column = 0; column < COLUMNS; column++) { - adc_select_input(column); - // Wait a bit before reading adc, being to fast could result in "some" spikes. - sleep_us(1); - - update_switch(&vswitches[row][column]); - } - gpio_put(PIN_FIRST_ROW + row, 0); - } - -#ifdef DEBUG - uint32_t loop_duration_before_wait = time_us_32() - start; -#endif - - sleep_until(end); - -#ifdef DEBUG - uint32_t loop_duration = time_us_32() - start; - struct void_switch *vswitch = &vswitches[0][0]; - printf("/*"); - // Misc values - printf("%d,", vswitch->calibration.is_calibrating); - printf("%d,", vswitch->calibration.cycles_count); - printf("%d,", vswitch->calibration.min_value); - printf("%d,", vswitch->calibration.max_value); - printf("%d,", loop_duration_before_wait); - printf("%d,", loop_duration); - printf("%d,", vswitch->actuation.trigger_offset); - printf("%d,", vswitch->actuation.rapid_trigger_offset); - printf("%d,", vswitch->actuation.is_continuous_rapid_trigger_enabled); - - // Min/max calibration check - printf("%d,", vswitch->state.value); - printf("%d,", vswitch->calibration.min_value); - printf("%d,", vswitch->calibration.max_value); - - // Motion check - printf("%d,", vswitch->state.distance); - printf("%d,", vswitch->state.velocity); - // printf("%d,", vswitch->state.is_pressing ? vswitch->state.motion.started_from : 0); - // printf("%d,", !vswitch->state.is_pressing ? vswitch->state.motion.started_from : 0); - printf("%d,", 0); - printf("%d,", 0); - - // Trigger/reset check - printf("%d,", vswitch->state.distance); - printf("%d,", vswitch->actuation.trigger_offset); - if (vswitch->actuation.status == RESET) { - printf("%d,", vswitch->actuation.rapid_trigger_offset > 0 ? vswitch->actuation.changed_at + vswitch->actuation.rapid_trigger_offset : 0); - } else if (vswitch->actuation.status == TRIGGERED) { - printf("%d,", vswitch->actuation.rapid_trigger_offset > 0 ? vswitch->actuation.changed_at - vswitch->actuation.rapid_trigger_offset : 0); - } - - printf("0*/\n"); -#endif -} - -// TODO: constant loop time - -// TODO: rapid trigger -// TODO: continuous rapid trigger - -// TODO: better cycle calculation, maybe DMA ? or sleep by sample ? let's try to have better spacing between analysis - -// TODO: Batch on_trigger -// TODO: browser configurator - -// TODO: trigger point by switch \ No newline at end of file diff --git a/firmware-old/src/void_switches.h b/firmware-old/src/void_switches.h deleted file mode 100644 index 6909fd4..0000000 --- a/firmware-old/src/void_switches.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef VOID_SWITCHES_H_ -#define VOID_SWITCHES_H_ - -#include "pico.h" -#include - -// #define DEBUG 1 - -struct calibration { - uint8_t is_calibrating; - uint16_t cycles_count; - uint16_t min_value; - uint8_t is_min_calibrated; - uint16_t max_value; - uint8_t is_max_calibrated; -}; - -struct state { - int16_t value; - int16_t distance; - int16_t velocity; - int16_t acceleration; - int16_t jerk; - uint8_t is_pressing; -}; - -enum actuation_status { - RESET, - TRIGGERED, -}; - -struct actuation { - enum actuation_status status; - uint16_t changed_at; - uint16_t trigger_offset; - uint16_t rapid_trigger_offset; - uint8_t is_continuous_rapid_trigger_enabled; - absolute_time_t trigger_timeout; -}; - -struct void_switch { - uint8_t is_enabled; - uint8_t row; - uint8_t column; - struct calibration calibration; - struct state state; - struct actuation actuation; -}; - -void void_switches_init(uint16_t trigger_point, uint16_t rapid_trigger_offset, uint8_t _continuous_rapid_trigger); - -void void_switches_loop(); - -#endif \ No newline at end of file diff --git a/firmware-old/tests/drv2605L.c b/firmware-old/tests/drv2605L.c deleted file mode 100644 index 16545d2..0000000 --- a/firmware-old/tests/drv2605L.c +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -// Sweep through all 7-bit I2C addresses, to see if any slaves are present on -// the I2C bus. Print out a table that looks like this: -// -// I2C Bus Scan -// 0 1 2 3 4 5 6 7 8 9 A B C D E F -// 0 -// 1 @ -// 2 -// 3 @ -// 4 -// 5 -// 6 -// 7 -// -// E.g. if slave addresses 0x12 and 0x34 were acknowledged. - -#include "../src/DRV2605L.h" -#include "pico/stdlib.h" -#include "tusb.h" -#include - -int main() { - // Enable UART so we can print status output - stdio_init_all(); - - printf("waiting for usb host"); - while (!tud_cdc_connected()) { - printf("."); - sleep_ms(500); - } - printf("\nusb host detected!\n"); - - drv2605l_init(); - - drv2605l_selectLibrary(1); - drv2605l_setMode(DRV2605_MODE_INTTRIG); - - uint8_t effect = 1; - while (1) { - printf("%d\n", effect); - drv2605l_setWaveform(0, 1); - drv2605l_setWaveform(1, 0); - drv2605l_go(); - - sleep_ms(500); - - effect++; - if (effect > 117) - effect = 1; - } - - return 0; -} diff --git a/firmware-old/tests/queue.c b/firmware-old/tests/queue.c deleted file mode 100644 index 695b7c2..0000000 --- a/firmware-old/tests/queue.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include - -static int read = 0; -static int write = 0; -#define REPORT_SIZE 6 -static int queue[REPORT_SIZE]; - -void queue_report(int value) { - queue[write] = value; - - write = (write + 1) % REPORT_SIZE; - - if (write == read) { - read = (read + 1) % REPORT_SIZE; - } - - printf("added %d, read %d, write %d\n", value, read, write); -} - -int has_reports() { - printf("has_report %d\n", read != write); - return read != write; -} - -int consume_report() { - int rtn = read; - - read = (read + 1) % REPORT_SIZE; - - printf("consumed index %d, value %d, read %d, write %d\n", rtn, queue[rtn], - read, write); - return rtn; -} - -int main(void) { - queue_report(10); - queue_report(20); - queue_report(30); - queue_report(40); - queue_report(50); - queue_report(60); - queue_report(70); - - while (has_reports()) { - int index = consume_report(); - } -} \ No newline at end of file diff --git a/firmware-old/tests/rotary.c b/firmware-old/tests/rotary.c deleted file mode 100644 index 964737a..0000000 --- a/firmware-old/tests/rotary.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../src/rotary_encoder.h" -#include "pico/stdlib.h" -#include - -void volume_up() { - printf("UP\n"); -} - -void volume_down() { - printf("DOWN\n"); -} - -void play_pause() { - printf("PLAY PAUSE\n"); -} - -void irq_callback(uint gpio, uint32_t events) { - rotary_encoder_irq_callback(gpio, events, &volume_up, &volume_down, &play_pause); -} - -int main(void) { - stdio_init_all(); - - init_rotary_encoder(&irq_callback); - - while (1) { - sleep_ms(1); - } - - return 0; -} \ No newline at end of file diff --git a/firmware-old/tests/usb.c b/firmware-old/tests/usb.c deleted file mode 100644 index cdbd03a..0000000 --- a/firmware-old/tests/usb.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "pico/stdlib.h" -#include - -int main() { - stdio_init_all(); - while (true) { - printf("Hello, world!\n"); - sleep_ms(1000); - } - return 0; -} \ No newline at end of file diff --git a/firmware-old/tests/void_switches.c b/firmware-old/tests/void_switches.c deleted file mode 100644 index 4f23421..0000000 --- a/firmware-old/tests/void_switches.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "../src/void_switches.h" -#include "../src/config.h" -#include "hardware/clocks.h" -#include "pico/stdlib.h" -#include - -int main(void) { - stdio_init_all(); - - while (!stdio_usb_connected()) { - sleep_ms(100); - } - - void_switches_init(25, 0, 0); - - while (1) { - void_switches_loop(true); - } - return 0; -} - -void void_switches_on_triggered(struct void_switch *vswitch) { - // printf("%d-%d TRIGGERED at %d\n", vswitch->row, vswitch->column, vswitch->actuation.changed_at); -} - -void void_switches_on_reset(struct void_switch *vswitch) { - // printf("%d-%d RESET at %d\n", vswitch->row, vswitch->column, vswitch->actuation.changed_at); -} - -#define range 10 -void void_switches_on_change(struct void_switch *vswitch) { - // if (vswitch->row == 0 && vswitch->column == 0) { - // printf("\n"); - // } - - // uint8_t new_value = (vswitch->state.distance * range) / 100; - - // printf("%d,%d [", vswitch->row, vswitch->column); - // for (int i = 0; i <= range; i++) { - // if (i <= new_value) { - // if (i >= range / 2) { - // printf("x"); - // } else { - // printf("o"); - // } - // } else { - // printf("-"); - // } - // } - // printf("] "); -} \ No newline at end of file