diff --git a/Sharpi/Pot.cs b/Sharpi/Pot.cs new file mode 100644 index 0000000..87cf706 --- /dev/null +++ b/Sharpi/Pot.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Sharpi +{ + public partial class Pot + { + // pot (common interface) + + [DllImport("sharpi")] + [return: MarshalAs(UnmanagedType.LPStr)] + internal static extern string pot_get_description(IntPtr sensor); + + [DllImport("sharpi")] + internal static extern void pot_delete(IntPtr sensor); + + + // pot (special functions for each type) + + + // AMG8833 + [DllImport("sharpi")] + internal static extern IntPtr pot_ds3502_new(byte i2cAddress); + + [DllImport("sharpi")] + internal static extern IntPtr pot_ds3502_new_x(byte i2cAddress, [MarshalAs(UnmanagedType.LPStr)] string i2cDevice); + + + [DllImport("sharpi")] + internal static extern void pot_ds3502_power_on(IntPtr sensor); + + [DllImport("sharpi")] + internal static extern void pot_ds3502_power_off(IntPtr sensor); + + [DllImport("sharpi")] + internal static extern byte pot_ds3502_get_wiper(IntPtr pot); + + [DllImport("sharpi")] + internal static extern void pot_ds3502_set_wiper(IntPtr pot, byte value); + + [DllImport("sharpi")] + internal static extern void pot_ds3502_set_wiper_persistent(IntPtr pot, byte value); + } + + // sensor + + public abstract class PotBase : IDisposable + { + protected IntPtr _handle = IntPtr.Zero; + + public PotBase(IntPtr handle) + { + _handle = handle; + } + + public void Dispose() + { + if (_handle != IntPtr.Zero) + { + Pot.pot_delete(_handle); + _handle = IntPtr.Zero; + } + } + + public string Description + { + get + { + if (_handle != IntPtr.Zero) + { + return Pot.pot_get_description(_handle); + } + else + { + return ""; + } + } + } + } + + + public static partial class Pot + { + public class Ds3502 : PotBase + { + /// + /// Ds3502 digipot, standard i2caddress 0x28 + /// + public Ds3502(byte i2caddress) + : base(pot_ds3502_new(i2caddress)) + { + } + + public Ds3502(byte i2caddress, string i2cdevice) + : base(pot_ds3502_new_x(i2caddress, i2cdevice)) + { + } + + public void PowerOn() + { + pot_ds3502_power_on(_handle); + } + + public void PowerOff() + { + pot_ds3502_power_off(_handle); + } + + public byte GetWiper() + { + return pot_ds3502_get_wiper(_handle); + } + + /// + /// sets the wiper value + /// + /// 0..127 + public void SetWiper(byte value) + { + pot_ds3502_set_wiper(_handle, value); + } + + /// + /// sets the wiper value and stores it in the EEPROM (~50000 writes) + /// + /// 0..127 + public void SetWiperPersistent(byte value) + { + pot_ds3502_set_wiper_persistent(_handle, value); + } + } + + } + + +} diff --git a/Sharpi/Sharpi.csproj b/Sharpi/Sharpi.csproj index ff0bc99..83851a4 100644 --- a/Sharpi/Sharpi.csproj +++ b/Sharpi/Sharpi.csproj @@ -14,7 +14,7 @@ img\sharpi.png 1.0.3.1 1.0.3.1 - 1.0.3.4 + 1.0.3.5 Raspberry;Pi;iot; https://github.com/A-J-Bauer/sharpi diff --git a/Sharpi/cpp/sharpi/CMakeLists.txt b/Sharpi/cpp/sharpi/CMakeLists.txt index 5419288..1638084 100644 --- a/Sharpi/cpp/sharpi/CMakeLists.txt +++ b/Sharpi/cpp/sharpi/CMakeLists.txt @@ -37,6 +37,9 @@ add_library(sharpi SHARED SensorAmg8833.cpp SensorIr28khz.h SensorIr28khz.cpp + Pot.h + PotDs3502.h + PotDs3502.cpp ) target_include_directories(sharpi diff --git a/Sharpi/cpp/sharpi/Pot.h b/Sharpi/cpp/sharpi/Pot.h new file mode 100644 index 0000000..6476f81 --- /dev/null +++ b/Sharpi/cpp/sharpi/Pot.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +/// +/// The base class for pots, all pots participating in the C-Api have to derive from this +/// +class Pot +{ + +public: + Pot() {}; + virtual ~Pot() {}; + virtual std::string GetDescription() = 0; + virtual const char* GetDescriptionC() = 0; + virtual void PowerOn() = 0; + virtual void PowerOff() = 0; +}; + + diff --git a/Sharpi/cpp/sharpi/PotDs3502.cpp b/Sharpi/cpp/sharpi/PotDs3502.cpp new file mode 100644 index 0000000..d9c7183 --- /dev/null +++ b/Sharpi/cpp/sharpi/PotDs3502.cpp @@ -0,0 +1,136 @@ +#include "PotDs3502.h" + +string PotDs3502::description = +"----------------------------------------------\n" +" Maxim DS3502 \n" +" \n" +" The DS3502 is a 7-bit, nonvolatile (NV) \n" +" digital potentiometer (POT) featuring an \n" +" output voltage range of up to 15.5V. \n" +" Programming is accomplished by an I2C- \n" +" compatible interface, which can operate at \n" +" speeds of up to 400kHz.External voltages are \n" +" applied at the RL and RH inputs to define the\n" +" lowest and highest potentiometer outputs. \n" +" (10 uSOP package) \n" +" \n" +" I2c slave address adjustable via A0 and A1 \n" +" \n" +" A convenient breakout board is available \n" +" from Adafruit. \n" +" \n" +"config: \n" +" \n" +" edit /boot/config.txt \n" +" dtparam=i2c_arm=on,i2c_arm_baudrate=400000 \n" +" \n" +"wiring: \n" +" \n" +" rpi physical pins \n" +" \n" +" vin -- 1 2 \n" +" sda -- 3 4 \n" +" scl -- 5 6 \n" +" 7 8 \n" +" gnd -- 9 10 ---------- \n" +" (int) -- 11 12 sda -| + |- scl \n" +" 13 14 gnd -| |- v+ \n" +" 15 16 vcc -| ds3502 |- rl \n" +" 17 18 a1 -| |- rw \n" +" 19 20 a0 -| |- rh \n" +" 21 22 ---------- \n" +" 23 24 \n" +" 25 26 \n" +" 27 28 \n" +" 29 30 \n" +" 31 32 \n" +" 33 34 \n" +" 35 36 \n" +" 37 38 \n" +" 39 40 \n" +" \n" +"----------------------------------------------\n" +; + +const string PotDs3502::I2CDEVICE = "/dev/i2c-1"; + +PotDs3502::PotDs3502(uint8_t i2cAddress) + : PotDs3502::PotDs3502(i2cAddress, I2CDEVICE) +{ +} + +PotDs3502::PotDs3502(uint8_t i2cAddress, string i2cDevice) +{ + _i2cAddress = i2cAddress; + _i2cDevice = i2cDevice; +} + +PotDs3502::~PotDs3502() +{ +} + +string PotDs3502::GetDescription() +{ + return description; +}; + +const char* PotDs3502::GetDescriptionC() +{ + return description.c_str(); +} + +void PotDs3502::PowerOn() +{ + if (_devI2c == NULL) + { + _devI2c = new DevI2c(_i2cDevice, _i2cAddress); + if (!_devI2c->Open()) + { + delete _devI2c; + _devI2c = NULL; + } + + _devI2c->WriteRegU8(Regs::CR::addr, Regs::CR::Modes::Mode_1_WR_ONLY); + } +} + +void PotDs3502::PowerOff() +{ + if (_devI2c != NULL) + { + _devI2c->Close(); + delete _devI2c; + _devI2c = NULL; + } +} + + +uint8_t PotDs3502::GetWiper(void) +{ + if (_devI2c == NULL) { return 0; }; + + uint8_t value; + _devI2c->ReadRegU8(Regs::WR::addr, &value); + return value; +} + +void PotDs3502::SetWiper(uint8_t value) +{ + if (_devI2c == NULL) { return; }; + + if (value > 127) { return; } + + _devI2c->WriteRegU8(Regs::WR::addr, value); +} + +void PotDs3502::SetWiperPersistent(uint8_t value) +{ + if (_devI2c == NULL) { return; }; + + if (value > 127) { return; } + + _devI2c->WriteRegU8(Regs::CR::addr, Regs::CR::Modes::Mode_0_WR_IVR); + _devI2c->WriteRegU8(Regs::WR::addr, value); + usleep(20000); // max EEPROM write time 20ms + _devI2c->WriteRegU8(Regs::CR::addr, Regs::CR::Modes::Mode_1_WR_ONLY); +} \ No newline at end of file diff --git a/Sharpi/cpp/sharpi/PotDs3502.h b/Sharpi/cpp/sharpi/PotDs3502.h new file mode 100644 index 0000000..5c67b8d --- /dev/null +++ b/Sharpi/cpp/sharpi/PotDs3502.h @@ -0,0 +1,71 @@ +#pragma once + +#include "Pot.h" +#include "DevI2c.h" + +using namespace std; + +class PotDs3502 : Pot +{ +private: + static string description; + +private: + static const string I2CDEVICE; + + string _i2cDevice = I2CDEVICE; + DevI2c* _devI2c = NULL; + uint8_t _i2cAddress; + +public: + PotDs3502(uint8_t i2cAddress); + PotDs3502(uint8_t i2cAddress, string i2cDevice); + ~PotDs3502(); + + string GetDescription(); + const char* GetDescriptionC(); + + void PowerOn(); + void PowerOff(); + + uint8_t GetWiper(void); + void SetWiper(uint8_t value); + void SetWiperPersistent(uint8_t value); // 50000 - 200000 EEPROM writes + +public: + class Regs + { + public: + /// + /// Control Register + /// + class CR + { + public: + static const uint8_t addr = 0x02; + class Modes + { + public: + enum : uint8_t + { + /// + /// mode0: write to memory address 00h, write to both WR (Wiper Register) and IVR (Initial Value Register), read from WR + /// mode1: write to memory address 00h, write to WR, read from WR, for writing from SRAM to EEPROM an i2c stop must occur + /// + Mode_0_WR_IVR = 0x00, + Mode_1_WR_ONLY = 0x80 + }; + }; + }; + + /// + /// Wiper Register + /// + class WR + { + public: + static const uint8_t addr = 0x00; + + }; + }; +}; \ No newline at end of file diff --git a/Sharpi/cpp/sharpi/sharpi.cpp b/Sharpi/cpp/sharpi/sharpi.cpp index 2df8684..67c5100 100644 --- a/Sharpi/cpp/sharpi/sharpi.cpp +++ b/Sharpi/cpp/sharpi/sharpi.cpp @@ -698,4 +698,57 @@ SHARPI void sensor_ir28khz_power_on(csensor* handle) SHARPI void sensor_ir28khz_power_off(csensor* handle) { ((SensorIr28khz*)handle)->PowerOff(); +} + + +// pot common + +typedef struct cpot cpot; + +SHARPI const char* pot_get_description(cpot* handle) +{ + return ((Pot*)handle)->GetDescriptionC(); +} + +SHARPI void pot_delete(cpot* handle) +{ + delete ((Pot*)handle); +} + +// pot specific + + +SHARPI cpot* pot_ds3502_new(uint8_t i2cAddress) +{ + return (cpot*)new PotDs3502(i2cAddress); +} + +SHARPI cpot* pot_ds3502_new_x(uint8_t i2cAddress, string i2cDevice) +{ + return (cpot*)new PotDs3502(i2cAddress, i2cDevice); +} + +SHARPI void pot_ds3502_power_on(cpot* handle) +{ + ((PotDs3502*)handle)->PowerOn(); +} + +SHARPI void pot_ds3502_power_off(cpot* handle) +{ + ((PotDs3502*)handle)->PowerOff(); +} + +SHARPI uint8_t pot_ds3502_get_wiper(cpot* handle) +{ + return ((PotDs3502*)handle)->GetWiper(); +} + +SHARPI void pot_ds3502_set_wiper(cpot* handle, uint8_t value) +{ + ((PotDs3502*)handle)->SetWiper(value); +} + +SHARPI void pot_ds3502_set_wiper_persistent(cpot* handle, uint8_t value) +{ + ((PotDs3502*)handle)->SetWiperPersistent(value); } \ No newline at end of file diff --git a/Sharpi/cpp/sharpi/sharpi.h b/Sharpi/cpp/sharpi/sharpi.h index 0cb8029..4a249a3 100644 --- a/Sharpi/cpp/sharpi/sharpi.h +++ b/Sharpi/cpp/sharpi/sharpi.h @@ -17,6 +17,8 @@ #include "AdcMcp3008.h" #include "SensorAmg8833.h" #include "SensorIr28khz.h" +#include "Pot.h" +#include "PotDs3502.h" #include "include/core/SkImageEncoder.h" #include "include/core/SkColor.h" @@ -234,6 +236,25 @@ extern "C" { SHARPI void sensor_ir28khz_power_on(csensor* handle); SHARPI void sensor_ir28khz_power_off(csensor* handle); + // pot common + + typedef struct cpot cpot; + + SHARPI const char* pot_get_description(cpot* handle); + SHARPI void pot_delete(cpot* handle); + + // pot specific + + SHARPI cpot* pot_ds3502_new(uint8_t i2cAddress); + SHARPI cpot* pot_ds3502_new_x(uint8_t i2cAddress, string i2cDevice); + + SHARPI void pot_ds3502_power_on(cpot* handle); + SHARPI void pot_ds3502_power_off(cpot* handle); + + SHARPI uint8_t pot_ds3502_get_wiper(cpot* handle); + SHARPI void pot_ds3502_set_wiper(cpot* handle, uint8_t value); + SHARPI void pot_ds3502_set_wiper_persistent(cpot* handle, uint8_t value); + #ifdef __cplusplus } #endif diff --git a/Sharpi/native/libsharpi.so b/Sharpi/native/libsharpi.so index da07a13..2556453 100644 Binary files a/Sharpi/native/libsharpi.so and b/Sharpi/native/libsharpi.so differ