From 1ae29677ed6390913b1cef72737469196c5158fd Mon Sep 17 00:00:00 2001 From: endail <52652357+endail@users.noreply.github.com> Date: Sun, 24 Nov 2024 20:32:19 +1100 Subject: [PATCH] add spi support - untested --- .vscode/c_cpp_properties.json | 24 +++--- .vscode/extensions.json | 9 ++ .vscode/launch.json | 73 +++++++++++++--- .vscode/settings.json | 72 +++++++--------- .vscode/tasks.json | 56 ++++++++++-- CMakeLists.txt | 21 ++++- include/common.h | 6 ++ include/hx711_spi_master.h | 153 ++++++++++++++++++++++++++++++++ include/hx711_spi_slave.h | 77 +++++++++++++++++ src/common.c | 31 +++++++ src/hx711_spi_master.c | 158 ++++++++++++++++++++++++++++++++++ src/hx711_spi_slave.c | 110 +++++++++++++++++++++++ tests/CMakeLists.txt | 14 +++ tests/spi_test.c | 83 ++++++++++++++++++ 14 files changed, 814 insertions(+), 73 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 include/hx711_spi_master.h create mode 100644 include/hx711_spi_slave.h create mode 100644 src/hx711_spi_master.c create mode 100644 src/hx711_spi_slave.c create mode 100644 tests/spi_test.c diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 4b97248..a9157ca 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,21 +3,19 @@ { "name": "Pico", "includePath": [ - "${workspaceFolder}/include/**", - "${env:PICO_TOOLCHAIN_PATH}/lib/gcc/arm-none-eabi/**", - "${env:PICO_SDK_PATH}/**" + "${workspaceFolder}/**", + "${userHome}/.pico-sdk/sdk/2.0.0/**" ], - "defines": [ - "_DEBUG", - "UNICODE", - "_UNICODE" + "forcedInclude": [ + "${workspaceFolder}/build/generated/pico_base/pico/config_autogen.h", + "${userHome}/.pico-sdk/sdk/2.0.0/src/common/pico_base_headers/include/pico.h" ], - "windowsSdkVersion": "10.0.22000.0", - "compilerPath": "${env:PICO_TOOLCHAIN_PATH}/bin/arm-none-eabi-gcc.exe", - "cppStandard": "c++11", - "intelliSenseMode": "gcc-arm", - "cStandard": "c11", - "configurationProvider": "ms-vscode.cmake-tools" + "defines": [], + "compilerPath": "${userHome}/.pico-sdk/toolchain/13_3_Rel1/bin/arm-none-eabi-gcc", + "compileCommands": "${workspaceFolder}/build/compile_commands.json", + "cStandard": "c17", + "cppStandard": "c++14", + "intelliSenseMode": "linux-gcc-arm" } ], "version": 4 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..2354cf2 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "marus25.cortex-debug", + "ms-vscode.cpptools", + "ms-vscode.cpptools-extension-pack", + "ms-vscode.vscode-serial-monitor", + "raspberry-pi.raspberry-pi-pico", + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json index 65ab975..4e9b386 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,24 +2,69 @@ "version": "0.2.0", "configurations": [ { - "name": "Debug file->elf", - "cwd": "${workspaceFolder}", - "executable": "${workspaceFolder}${pathSeparator}build${pathSeparator}${relativeFileDirname}${pathSeparator}${fileBasenameNoExtension}.elf", + "name": "Pico Debug (Cortex-Debug)", + "cwd": "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "executable": "${command:raspberry-pi-pico.launchTargetPath}", "request": "launch", "type": "cortex-debug", "servertype": "openocd", - "device": "Pico2040", - "showDevDebugOutput": "both", - // "runToEntryPoint": "main", - "preLaunchTask": "CMake Build", + "serverpath": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "gdbPath": "${command:raspberry-pi-pico.getGDBPath}", + "device": "${command:raspberry-pi-pico.getChipUppercase}", "configFiles": [ - "interface${pathSeparator}picoprobe.cfg", - "target${pathSeparator}rp2040.cfg" + "interface/cmsis-dap.cfg", + "target/${command:raspberry-pi-pico.getTarget}.cfg" ], - "searchDir": [ - "${env:OPENOCD_PATH}${pathSeparator}tcl" + "svdFile": "${userHome}/.pico-sdk/sdk/2.0.0/src/${command:raspberry-pi-pico.getChip}/hardware_regs/${command:raspberry-pi-pico.getChipUppercase}.svd", + "runToEntryPoint": "main", + // Fix for no_flash binaries, where monitor reset halt doesn't do what is expected + // Also works fine for flash binaries + "overrideLaunchCommands": [ + "monitor reset init", + "load \"${command:raspberry-pi-pico.launchTargetPath}\"" ], - "svdFile": "${env:PICO_SDK_PATH}${pathSeparator}src${pathSeparator}rp2040${pathSeparator}hardware_regs${pathSeparator}rp2040.svd" - } + "openOCDLaunchCommands": [ + "adapter speed 5000" + ] + }, + { + "name": "Pico Debug (Cortex-Debug with external OpenOCD)", + "cwd": "${workspaceRoot}", + "executable": "${command:raspberry-pi-pico.launchTargetPath}", + "request": "launch", + "type": "cortex-debug", + "servertype": "external", + "gdbTarget": "localhost:3333", + "gdbPath": "${command:raspberry-pi-pico.getGDBPath}", + "device": "${command:raspberry-pi-pico.getChipUppercase}", + "svdFile": "${userHome}/.pico-sdk/sdk/2.0.0/src/${command:raspberry-pi-pico.getChip}/hardware_regs/${command:raspberry-pi-pico.getChipUppercase}.svd", + "runToEntryPoint": "main", + // Fix for no_flash binaries, where monitor reset halt doesn't do what is expected + // Also works fine for flash binaries + "overrideLaunchCommands": [ + "monitor reset init", + "load \"${command:raspberry-pi-pico.launchTargetPath}\"" + ] + }, + { + "name": "Pico Debug (C++ Debugger)", + "type": "cppdbg", + "request": "launch", + "cwd": "${workspaceRoot}", + "program": "${command:raspberry-pi-pico.launchTargetPath}", + "MIMode": "gdb", + "miDebuggerPath": "${command:raspberry-pi-pico.getGDBPath}", + "miDebuggerServerAddress": "localhost:3333", + "debugServerPath": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "debugServerArgs": "-f interface/cmsis-dap.cfg -f target/${command:raspberry-pi-pico.getTarget}.cfg -c \"adapter speed 5000\"", + "serverStarted": "Listening on port .* for gdb connections", + "filterStderr": true, + "hardwareBreakpoints": { + "require": true, + "limit": 4 + }, + "preLaunchTask": "Flash", + "svdPath": "${userHome}/.pico-sdk/sdk/2.0.0/src/${command:raspberry-pi-pico.getChip}/hardware_regs/${command:raspberry-pi-pico.getChipUppercase}.svd" + }, ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index a2736bc..4a4d57c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,47 +1,39 @@ { - "cmake.statusbar.advanced": { - "debug": { - "visibility": "hidden" + "cmake.options.statusBarVisibility": "hidden", + "cmake.options.advanced": { + "build": { + "statusBarVisibility": "hidden" }, "launch": { - "visibility": "hidden" + "statusBarVisibility": "hidden" }, - "launchTarget": { - "visibility": "hidden" + "debug": { + "statusBarVisibility": "hidden" } }, - "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", - "cmake.buildBeforeRun": true, - "cmake.configureOnOpen": true, - "files.associations": { - "stdio.h": "c", - "hx711.h": "c", - "cstdlib": "c", - "stdint.h": "c", - "cstdint": "c", - "time.h": "c", - "_timespec.h": "c", - "_types.h": "c", - "gpio.h": "c", - "hx711_multi.h": "c", - "array": "c", - "deque": "c", - "string": "c", - "unordered_map": "c", - "vector": "c", - "string_view": "c", - "initializer_list": "c", - "util.h": "c", - "random": "c", - "limits": "c", - "cstddef": "c", - "mutex.h": "c", - "platform.h": "c" + "cmake.configureOnEdit": false, + "cmake.automaticReconfigure": false, + "cmake.configureOnOpen": false, + "cmake.generator": "Ninja", + "cmake.cmakePath": "${userHome}/.pico-sdk/cmake/v3.28.6/bin/cmake", + "C_Cpp.debugShortcut": false, + "terminal.integrated.env.windows": { + "PICO_SDK_PATH": "${env:USERPROFILE}/.pico-sdk/sdk/2.0.0", + "PICO_TOOLCHAIN_PATH": "${env:USERPROFILE}/.pico-sdk/toolchain/13_3_Rel1", + "Path": "${env:USERPROFILE}/.pico-sdk/toolchain/13_3_Rel1/bin;${env:USERPROFILE}/.pico-sdk/picotool/2.0.0/picotool;${env:USERPROFILE}/.pico-sdk/cmake/v3.28.6/bin;${env:USERPROFILE}/.pico-sdk/ninja/v1.12.1;${env:PATH}" + }, + "terminal.integrated.env.osx": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.0.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/13_3_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/13_3_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.0.0/picotool:${env:HOME}/.pico-sdk/cmake/v3.28.6/bin:${env:HOME}/.pico-sdk/ninja/v1.12.1:${env:PATH}" + }, + "terminal.integrated.env.linux": { + "PICO_SDK_PATH": "${env:HOME}/.pico-sdk/sdk/2.0.0", + "PICO_TOOLCHAIN_PATH": "${env:HOME}/.pico-sdk/toolchain/13_3_Rel1", + "PATH": "${env:HOME}/.pico-sdk/toolchain/13_3_Rel1/bin:${env:HOME}/.pico-sdk/picotool/2.0.0/picotool:${env:HOME}/.pico-sdk/cmake/v3.28.6/bin:${env:HOME}/.pico-sdk/ninja/v1.12.1:${env:PATH}" }, - "C_Cpp.intelliSenseEngineFallback": "enabled", - "C_Cpp.default.intelliSenseMode": "gcc-arm", - "C_Cpp.default.browse.limitSymbolsToIncludedHeaders": false, - "C_Cpp.default.cppStandard": "", - "C_Cpp.default.cStandard": "c11", - "C_Cpp.default.mergeConfigurations": true -} \ No newline at end of file + "raspberry-pi-pico.cmakeAutoConfigure": true, + "raspberry-pi-pico.useCmakeTools": false, + "raspberry-pi-pico.cmakePath": "${HOME}/.pico-sdk/cmake/v3.28.6/bin/cmake", + "raspberry-pi-pico.ninjaPath": "${HOME}/.pico-sdk/ninja/v1.12.1/ninja" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 0c24940..0af9a31 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,11 +2,57 @@ "version": "2.0.0", "tasks": [ { - "label": "CMake Build", - "command": "${command:cmake.tasksBuildCommand}", - "type": "shell", + "label": "Compile Project", + "type": "process", + "isBuildCommand": true, + "command": "${userHome}/.pico-sdk/ninja/v1.12.1/ninja", + "args": ["-C", "${workspaceFolder}/build"], "group": "build", - "problemMatcher": [] + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": "$gcc", + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/ninja/v1.12.1/ninja.exe" + } + }, + { + "label": "Run Project", + "type": "process", + "command": "${env:HOME}/.pico-sdk/picotool/2.0.0/picotool/picotool", + "args": [ + "load", + "${command:raspberry-pi-pico.launchTargetPath}", + "-fx" + ], + "presentation": { + "reveal": "always", + "panel": "dedicated" + }, + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/picotool/2.0.0/picotool/picotool.exe" + } + }, + { + "label": "Flash", + "type": "process", + "command": "${userHome}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + "args": [ + "-s", + "${userHome}/.pico-sdk/openocd/0.12.0+dev/scripts", + "-f", + "interface/cmsis-dap.cfg", + "-f", + "target/${command:raspberry-pi-pico.getTarget}.cfg", + "-c", + "adapter speed 5000; program \"${command:raspberry-pi-pico.launchTargetPath}\" verify reset exit" + ], + "problemMatcher": [], + "windows": { + "command": "${env:USERPROFILE}/.pico-sdk/openocd/0.12.0+dev/openocd.exe", + } } ] -} \ No newline at end of file +} diff --git a/CMakeLists.txt b/CMakeLists.txt index aee7068..de2ba9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2023 Daniel Robertson +# Copyright (c) 2024 Daniel Robertson # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -20,6 +20,22 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +# == DO NOT EDIT THE FOLLOWING LINES for the Raspberry Pi Pico VS Code Extension to work == +if(WIN32) + set(USERHOME $ENV{USERPROFILE}) +else() + set(USERHOME $ENV{HOME}) +endif() +set(sdkVersion 2.0.0) +set(toolchainVersion 13_3_Rel1) +set(picotoolVersion 2.0.0) +set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake) +if (EXISTS ${picoVscode}) + include(${picoVscode}) +endif() +# ==================================================================================== +set(PICO_BOARD pico CACHE STRING "Board type") + cmake_minimum_required(VERSION 3.12) # this must go above project()! @@ -73,6 +89,7 @@ target_link_libraries(hx711-pico-c INTERFACE hardware_gpio hardware_irq hardware_pio + hardware_spi hardware_timer pico_platform pico_sync @@ -82,6 +99,8 @@ target_link_libraries(hx711-pico-c INTERFACE target_sources(hx711-pico-c INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/hx711.c ${CMAKE_CURRENT_LIST_DIR}/src/hx711_multi.c + ${CMAKE_CURRENT_LIST_DIR}/src/hx711_spi_master.c + ${CMAKE_CURRENT_LIST_DIR}/src/hx711_spi_slave.c ${CMAKE_CURRENT_LIST_DIR}/src/common.c ${CMAKE_CURRENT_LIST_DIR}/src/util.c ) diff --git a/include/common.h b/include/common.h index ba385f5..f7138fa 100644 --- a/include/common.h +++ b/include/common.h @@ -25,6 +25,8 @@ #include "hx711.h" #include "hx711_multi.h" +#include "hx711_spi_master.h" +#include "hx711_spi_slave.h" #ifdef __cplusplus extern "C" { @@ -32,9 +34,13 @@ extern "C" { extern const hx711_config_t HX711__DEFAULT_CONFIG; extern const hx711_multi_config_t HX711__MULTI_DEFAULT_CONFIG; +extern const hx711_spi_master_config_t HX711__SPI_MASTER_DEFAULT_CONFIG; +extern const hx711_spi_slave_config_t HX711__SPI_SLAVE_DEFAULT_CONFIG; void hx711_get_default_config(hx711_config_t* const cfg); void hx711_multi_get_default_config(hx711_multi_config_t* const cfg); +void hx711_spi_master_get_default_config(hx711_spi_master_config_t* const cfg); +void hx711_spi_slave_get_default_config(hx711_spi_slave_config_t* const cfg); #ifdef __cplusplus } diff --git a/include/hx711_spi_master.h b/include/hx711_spi_master.h new file mode 100644 index 0000000..1327b7b --- /dev/null +++ b/include/hx711_spi_master.h @@ -0,0 +1,153 @@ +// MIT License +// +// Copyright (c) 2024 Daniel Robertson +// +// 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 HX711_SPI_MASTER_H_20E2043E_D984_444F_A079_562B3C56AC12 +#define HX711_SPI_MASTER_H_20E2043E_D984_444F_A079_562B3C56AC12 + +#include +#include "hardware/spi.h" +#include "hx711.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HX711_SPI_BAUD_RATE 1000000 + +typedef enum { + hx711_spi_command_none = 0, + hx711_spi_command_power_up = 1, + hx711_spi_command_power_down = 2, + hx711_spi_command_set_gain = 3, + hx711_spi_command_get_value = 4 +} hx711_spi_command_t; + +typedef struct { + + uint _rx_pin; + uint _sck_pin; + uint _tx_pin; + uint _csn_pin; + + spi_inst_t* _spi; + uint _baud_rate; + +} hx711_spi_master_t; + +typedef struct { + + uint rx_pin; + uint sck_pin; + uint tx_pin; + uint csn_pin; + + spi_inst_t* spi; + uint baud_rate; + +} hx711_spi_master_config_t; + +void hx711_spi_master_init( + hx711_spi_master_t* const hx_spi, + const hx711_spi_master_config_t * const hx_spi_config); + +/** + * @brief Stop SPI communication. + * + * @param hx_spi + */ +void hx711_spi_master_close( + hx711_spi_master_t* const hx_spi); + +/** + * @brief Sets the HX711 gain. + * + * @param hx_spi + * @param gain + */ +void hx711_spi_master_set_gain( + hx711_spi_master_t* const hx_spi, + const hx711_gain_t gain); + +/** + * @brief Obtains a value from the HX711. Blocks until a value + * is available. + * + * @param hx_spi + * @return int32_t + */ +int32_t hx711_spi_master_get_value( + hx711_spi_master_t* const hx_spi); + +/** + * @brief Power up the HX711 with an initial gain. + * + * @param hx_spi + * @param gain + */ +void hx711_spi_master_power_up( + hx711_spi_master_t* const hx_spi, + const hx711_gain_t gain); + +/** + * @brief Power down the HX711. + * + * @param hx_spi + */ +void hx711_spi_master_power_down( + hx711_spi_master_t* const hx_spi); + +/** + * @brief Checks whether the given gain value is valid for + * transmissions across SPI. + * + * @param spi_gain + * @return true + * @return false + */ +bool hx711_spi_is_spi_gain_valid( + const uint8_t spi_gain); + +/** + * @brief Converts a hx711_gain_t to a value suitable for + * transmission across SPI. + * + * @param gain + * @return uint8_t + */ +uint8_t hx711_spi_gain_to_spi_gain( + const hx711_gain_t gain); + +/** + * @brief Converts a gain value obtained via SPI to a + * hx711_gain_t. + * + * @param spi_gain + * @return hx711_gain_t + */ +hx711_gain_t hx711_spi_spi_gain_to_gain( + const uint8_t spi_gain); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/hx711_spi_slave.h b/include/hx711_spi_slave.h new file mode 100644 index 0000000..9b43f5f --- /dev/null +++ b/include/hx711_spi_slave.h @@ -0,0 +1,77 @@ +// MIT License +// +// Copyright (c) 2024 Daniel Robertson +// +// 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 HX711_SPI_SLAVE_H_A013478A_24EE_4581_AF94_BC52198CFF1D +#define HX711_SPI_SLAVE_H_A013478A_24EE_4581_AF94_BC52198CFF1D + +#include +#include "hardware/spi.h" +#include "hx711.h" +#include "hx711_spi_master.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HX711_SPI_BAUD_RATE 1000000 + +typedef struct { + + uint _rx_pin; + uint _sck_pin; + uint _tx_pin; + uint _csn_pin; + + spi_inst_t* _spi; + uint _baud_rate; + + hx711_t* _hx; + +} hx711_spi_slave_t; + +typedef struct { + + uint rx_pin; + uint sck_pin; + uint tx_pin; + uint csn_pin; + + spi_inst_t* spi; + uint baud_rate; + + hx711_t* hx; + +} hx711_spi_slave_config_t; + +void hx711_spi_slave_init( + hx711_spi_slave_t* const hx_spi, + const hx711_spi_slave_config_t * const hx_spi_config); + +void hx711_spi_slave_close(hx711_spi_slave_t* const hx_spi); + +void hx711_spi_slave_listen(hx711_spi_slave_t* const hx_spi); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common.c b/src/common.c index 91dad36..213bb12 100644 --- a/src/common.c +++ b/src/common.c @@ -29,6 +29,8 @@ #include "../include/hx711_multi.h" #include "../include/hx711_multi_awaiter.pio.h" #include "../include/hx711_multi_reader.pio.h" +#include "../include/hx711_spi_master.h" +#include "../include/hx711_spi_slave.h" const hx711_config_t HX711__DEFAULT_CONFIG = { .clock_pin = 0, @@ -53,6 +55,25 @@ const hx711_multi_config_t HX711__MULTI_DEFAULT_CONFIG = { .reader_prog_init = hx711_multi_reader_program_init }; +const hx711_spi_master_config_t HX711__SPI_MASTER_DEFAULT_CONFIG = { + .rx_pin = 0, + .sck_pin = 2, + .tx_pin = 3, + .csn_pin = 1, + .spi = spi_default, + .baud_rate = HX711_SPI_BAUD_RATE +}; + +const hx711_spi_slave_config_t HX711__SPI_SLAVE_DEFAULT_CONFIG = { + .rx_pin = 0, + .sck_pin = 2, + .tx_pin = 3, + .csn_pin = 1, + .spi = spi_default, + .baud_rate = HX711_SPI_BAUD_RATE, + .hx = NULL +}; + void hx711_get_default_config(hx711_config_t* const cfg) { assert(cfg != NULL); *cfg = HX711__DEFAULT_CONFIG; @@ -62,3 +83,13 @@ void hx711_multi_get_default_config(hx711_multi_config_t* const cfg) { assert(cfg != NULL); *cfg = HX711__MULTI_DEFAULT_CONFIG; } + +void hx711_spi_master_get_default_config(hx711_spi_master_config_t* const cfg) { + assert(cfg != NULL); + *cfg = HX711__SPI_MASTER_DEFAULT_CONFIG; +} + +void hx711_spi_slave_get_default_config(hx711_spi_slave_config_t* const cfg) { + assert(cfg != NULL); + *cfg = HX711__SPI_SLAVE_DEFAULT_CONFIG; +} diff --git a/src/hx711_spi_master.c b/src/hx711_spi_master.c new file mode 100644 index 0000000..14bd552 --- /dev/null +++ b/src/hx711_spi_master.c @@ -0,0 +1,158 @@ +// MIT License +// +// Copyright (c) 2023 Daniel Robertson +// +// 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 +#include +#include +#include "hardware/gpio.h" +#include "hardware/spi.h" +#include "../include/hx711.h" +#include "../include/hx711_spi_master.h" +#include "../include/util.h" + +void hx711_spi_master_init( + hx711_spi_master_t* const hx_spi, + const hx711_spi_master_config_t * const hx_spi_config) { + + assert(hx_spi != NULL); + assert(hx_spi_config != NULL); + + check_gpio_param(hx_spi_config->rx_pin); + check_gpio_param(hx_spi_config->sck_pin); + check_gpio_param(hx_spi_config->tx_pin); + check_gpio_param(hx_spi_config->csn_pin); + + assert(hx_spi_config->spi != NULL); + assert(hx_spi_config->baud_rate > 0); + + hx_spi->_rx_pin = hx_spi_config->rx_pin; + hx_spi->_sck_pin = hx_spi_config->sck_pin; + hx_spi->_tx_pin = hx_spi_config->tx_pin; + hx_spi->_csn_pin = hx_spi_config->csn_pin; + + hx_spi->_spi = hx_spi_config->spi; + hx_spi->_baud_rate = hx_spi_config->baud_rate; + + gpio_set_function(hx_spi->_rx_pin, GPIO_FUNC_SPI); + gpio_set_function(hx_spi->_sck_pin, GPIO_FUNC_SPI); + gpio_set_function(hx_spi->_tx_pin, GPIO_FUNC_SPI); + gpio_set_function(hx_spi->_csn_pin, GPIO_FUNC_SPI); + + spi_init(hx_spi->_spi, hx_spi->_baud_rate); + spi_set_slave(hx_spi->_spi, false); + +} + +void hx711_spi_master_close( + hx711_spi_master_t* const hx_spi) { + assert(hx_spi != NULL); + assert(hx_spi->_spi != NULL); + spi_deinit(hx_spi->_spi); +} + +void hx711_spi_master_set_gain( + hx711_spi_master_t* const hx_spi, + const hx711_gain_t gain) { + + assert(hx_spi != NULL); + assert(hx_spi->_spi != NULL); + assert(hx711_is_gain_valid(gain)); + + const uint8_t data = + (hx711_spi_gain_to_spi_gain(gain) << 3) | + (uint8_t)hx711_spi_command_set_gain; + + spi_write_blocking( + hx_spi->_spi, + &data, + sizeof(data)); + +} + +int32_t hx711_spi_master_get_value( + hx711_spi_master_t* const hx_spi) { + + assert(hx_spi != NULL); + assert(hx_spi->_spi != NULL); + + int32_t val; + + spi_read_blocking( + hx_spi->_spi, + hx711_spi_command_none, + (uint8_t*)&val, + sizeof(val)); + + return val; + +} + +void hx711_spi_master_power_up( + hx711_spi_master_t* const hx_spi, + const hx711_gain_t gain) { + + assert(hx_spi != NULL); + assert(hx_spi->_spi != NULL); + assert(hx711_is_gain_valid(gain)); + + const uint8_t data = + (hx711_spi_gain_to_spi_gain(gain) << 3) | + (uint8_t)hx711_spi_command_set_gain; + + spi_write_read_blocking( + hx_spi->_spi, + &data, + NULL, + sizeof(data)); + +} + +void hx711_spi_master_power_down( + hx711_spi_master_t* const hx_spi) { + + assert(hx_spi != NULL); + assert(hx_spi->_spi != NULL); + + const uint8_t cmd = (uint8_t)hx711_spi_command_power_down; + + spi_write_blocking( + hx_spi->_spi, + &cmd, + sizeof(cmd)); + +} + +bool hx711_spi_is_spi_gain_valid(const uint8_t spi_gain) { + return spi_gain <= count_of(HX711_CLOCK_PULSES) - 1; +} + +uint8_t hx711_spi_gain_to_spi_gain(const hx711_gain_t gain) { + assert(hx711_is_gain_valid(gain)); + return (uint8_t)gain - HX711_READ_BITS; +} + +hx711_gain_t hx711_spi_spi_gain_to_gain(const uint8_t spi_gain) { + assert(hx711_spi_is_spi_gain_valid(spi_gain)); + const hx711_gain_t gain = (hx711_gain_t)HX711_CLOCK_PULSES[spi_gain]; + assert(hx711_is_gain_valid(gain)); + return gain; +} diff --git a/src/hx711_spi_slave.c b/src/hx711_spi_slave.c new file mode 100644 index 0000000..9473acc --- /dev/null +++ b/src/hx711_spi_slave.c @@ -0,0 +1,110 @@ +// MIT License +// +// Copyright (c) 2023 Daniel Robertson +// +// 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 +#include +#include +#include "hardware/gpio.h" +#include "hardware/spi.h" +#include "../include/hx711.h" +#include "../include/hx711_spi_slave.h" +#include "../include/util.h" + +void hx711_spi_slave_init( + hx711_spi_slave_t* const hx_spi, + const hx711_spi_slave_config_t * const hx_spi_config) { + + assert(hx_spi != NULL); + assert(hx_spi_config != NULL); + + check_gpio_param(hx_spi_config->rx_pin); + check_gpio_param(hx_spi_config->sck_pin); + check_gpio_param(hx_spi_config->tx_pin); + check_gpio_param(hx_spi_config->csn_pin); + + assert(hx_spi_config->spi != NULL); + assert(hx_spi_config->baud_rate > 0); + + hx_spi->_rx_pin = hx_spi_config->rx_pin; + hx_spi->_sck_pin = hx_spi_config->sck_pin; + hx_spi->_tx_pin = hx_spi_config->tx_pin; + hx_spi->_csn_pin = hx_spi_config->csn_pin; + + hx_spi->_spi = hx_spi_config->spi; + hx_spi->_baud_rate = hx_spi_config->baud_rate; + + gpio_set_function(hx_spi->_rx_pin, GPIO_FUNC_SPI); + gpio_set_function(hx_spi->_sck_pin, GPIO_FUNC_SPI); + gpio_set_function(hx_spi->_tx_pin, GPIO_FUNC_SPI); + gpio_set_function(hx_spi->_csn_pin, GPIO_FUNC_SPI); + + spi_init(hx_spi->_spi, hx_spi->_baud_rate); + spi_set_slave(hx_spi->_spi, false); + +} + +void hx711_spi_slave_close(hx711_spi_slave_t* const hx_spi) { + assert(hx_spi != NULL); + assert(hx_spi->_spi != NULL); + spi_deinit(hx_spi->_spi); +} + +void hx711_spi_slave_listen(hx711_spi_slave_t* const hx_spi) { + + hx711_spi_command_t cmd; + uint8_t data; + hx711_gain_t gain; + int32_t out; + + while(true) { + + spi_read_blocking( + hx_spi->_spi, + hx711_spi_command_none, + &data, + sizeof(data)); + + cmd = (hx711_spi_command_t)(data & 0b00000111); + data = data >> 5; + + switch(cmd) { + default: + case hx711_spi_command_get_value: + out = hx711_get_value(hx_spi->_hx); + spi_write_blocking(hx_spi->_spi, (uint8_t*)&out, sizeof(out)); + break; + case hx711_spi_command_set_gain: + gain = hx711_spi_spi_gain_to_gain(data); + hx711_set_gain(hx_spi->_hx, gain); + break; + case hx711_spi_command_power_up: + gain = hx711_spi_spi_gain_to_gain(data); + hx711_power_up(hx_spi->_hx, gain); + break; + case hx711_spi_command_power_down: + hx711_power_down(hx_spi->_hx); + break; + } + + } + +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e02e63e..88d2a04 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,12 +40,26 @@ add_executable(main ${CMAKE_CURRENT_LIST_DIR}/main.c ) +add_executable(spi_test + ${CMAKE_CURRENT_LIST_DIR}/spi_test.c + ) + target_link_libraries(main hx711-pico-c pico_stdlib pico_stdio ) +target_link_libraries(spi_test + hx711-pico-c + pico_stdlib + pico_stdio + ) + pico_enable_stdio_usb(main 1) pico_enable_stdio_uart(main 1) pico_add_extra_outputs(main) + +pico_enable_stdio_usb(spi_test 1) +pico_enable_stdio_uart(spi_test 1) +pico_add_extra_outputs(spi_test) \ No newline at end of file diff --git a/tests/spi_test.c b/tests/spi_test.c new file mode 100644 index 0000000..db1675a --- /dev/null +++ b/tests/spi_test.c @@ -0,0 +1,83 @@ +// MIT License +// +// Copyright (c) 2024 Daniel Robertson +// +// 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 +#include +#include "pico/stdio.h" +#include "tusb.h" +#include "../include/common.h" + +int main(void) { + + stdio_init_all(); + + while (!tud_cdc_connected()) { + sleep_ms(1); + } + +//slave +#if 1 + hx711_config_t hxcfg; + hx711_get_default_config(&hxcfg); + + hxcfg.clock_pin = 14; + hxcfg.data_pin = 15; + + hx711_t hx; + + hx711_init(&hx, &hxcfg); + + hx711_spi_slave_config_t spicfg; + hx711_spi_slave_get_default_config(&spicfg); + + spicfg.hx = &hx; + + hx711_spi_slave_t hxspi; + + hx711_spi_slave_init(&hxspi, &spicfg); + hx711_spi_slave_listen(&hxspi); + hx711_spi_slave_close(&hxspi); + + hx711_close(&hx); + + printf("Closed communication with single HX711 chip\n"); +#endif + +//master +#if 0 + hx711_spi_master_config_t spicfg; + hx711_spi_master_get_default_config(&spicfg); + + hx711_spi_master_t hxspi; + + hx711_spi_master_init(&hxspi, &spicfg); + hx711_spi_master_power_up(&hxspi, hx711_gain_128); + hx711_wait_settle(hx711_rate_80); + printf("Value from SPI: %li\n", hx711_spi_master_get_value(&hxspi)); + hx711_spi_master_close(&hxspi); +#endif + + while(1); + + return EXIT_SUCCESS; + +}