Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions coresdk/src/backend/backend_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,19 @@ namespace splashkit_lib
GPIO_CMD_SET_PWM_DUTYCYCLE,
GPIO_CMD_SET_PWM_RANGE,
GPIO_CMD_SET_PWM_FREQ,
GPIO_CMD_CLEAR_BANK_1 = 12

GPIO_CMD_CLEAR_BANK_1 = 12,

// I2C Command Codes
GPIO_I2C_CMD_OPEN,
GPIO_I2C_CMD_CLOSE,
GPIO_I2C_CMD_SLAVE_READ,
GPIO_I2C_CMD_SLAVE_WRITE,
GPIO_I2C_CMD_READ_DEVICE,
GPIO_I2C_CMD_WRITE_DEVICE,
GPIO_I2C_CMD_READ_BYTE_DATA,
GPIO_I2C_CMD_WRITE_BYTE_DATA,
GPIO_I2C_CMD_READ_WORD_DATA,
GPIO_I2C_CMD_WRITE_WORD_DATA
};

}
Expand Down
74 changes: 74 additions & 0 deletions coresdk/src/backend/gpio_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,80 @@ namespace splashkit_lib
sk_gpio_send_cmd(pi, set_dutycycle_cmd);
}

int sk_remote_i2c_open(connection pi, int bus, int address, int flags)
{
sk_pigpio_cmd_t i2c_open_cmd;
i2c_open_cmd.cmd_code = GPIO_I2C_CMD_OPEN;
i2c_open_cmd.param1 = bus;
i2c_open_cmd.param2 = address;
i2c_open_cmd.param3 = flags;

return sk_gpio_send_cmd(pi, i2c_open_cmd);
}

int sk_remote_i2c_close(connection pi, int handle) {
sk_pigpio_cmd_t set_cmd;
set_cmd.cmd_code = GPIO_I2C_CMD_CLOSE;
set_cmd.param1 = handle;

return sk_gpio_send_cmd(pi, set_cmd);
}

int sk_remote_i2c_read_byte(connection pi, int handle) {
sk_pigpio_cmd_t set_cmd;
set_cmd.cmd_code = GPIO_I2C_CMD_SLAVE_READ;
set_cmd.param1 = handle;

return sk_gpio_send_cmd(pi, set_cmd);
}

int sk_remote_i2c_write_byte(connection pi, int handle, int data) {
sk_pigpio_cmd_t set_cmd;
set_cmd.cmd_code = GPIO_I2C_CMD_SLAVE_WRITE;
set_cmd.param1 = handle;
set_cmd.param2 = data;

return sk_gpio_send_cmd(pi, set_cmd);
}

int sk_remote_i2c_read_byte_data(connection pi, int handle, int reg) {
sk_pigpio_cmd_t set_cmd;
set_cmd.cmd_code = GPIO_I2C_CMD_READ_BYTE_DATA;
set_cmd.param1 = handle;
set_cmd.param2 = reg;

return sk_gpio_send_cmd(pi, set_cmd);
}

void sk_remote_i2c_write_byte_data(connection pi, int handle, int reg, int data) {
sk_pigpio_cmd_t set_cmd;
set_cmd.cmd_code = GPIO_I2C_CMD_WRITE_BYTE_DATA;
set_cmd.param1 = handle;
set_cmd.param2 = reg;
set_cmd.param3 = data;

sk_gpio_send_cmd(pi, set_cmd);
}

int sk_remote_i2c_read_word_data(connection pi, int handle, int reg) {
sk_pigpio_cmd_t set_cmd;
set_cmd.cmd_code = GPIO_I2C_CMD_READ_WORD_DATA;
set_cmd.param1 = handle;
set_cmd.param2 = reg;

return sk_gpio_send_cmd(pi, set_cmd);
}

void sk_remote_i2c_write_word_data(connection pi, int handle, int reg, int data) {
sk_pigpio_cmd_t set_cmd;
set_cmd.cmd_code = GPIO_I2C_CMD_WRITE_WORD_DATA;
set_cmd.param1 = handle;
set_cmd.param2 = reg;
set_cmd.param3 = data;

sk_gpio_send_cmd(pi, set_cmd);
}

void sk_remote_clear_bank_1(connection pi)
{
sk_pigpio_cmd_t clear_bank_cmd;
Expand Down
12 changes: 12 additions & 0 deletions coresdk/src/backend/gpio_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define SPLASHKIT_GPIO_H

#include "backend_types.h"
#include "types.h"
#include <stdint.h> // Include the appropriate header file for stdint.h

// Relevant error codes from pigpio library
Expand Down Expand Up @@ -229,6 +230,17 @@ namespace splashkit_lib
void sk_remote_set_pwm_range(connection pi, int pin, int range);
void sk_remote_set_pwm_frequency(connection pi, int pin, int frequency);
void sk_remote_set_pwm_dutycycle(connection pi, int pin, int dutycycle);

// Remote I2C
int sk_remote_i2c_open(connection pi, int bus, int address, int flags);
int sk_remote_i2c_close(connection pi, int handle);
int sk_remote_i2c_read_byte(connection pi, int handle);
int sk_remote_i2c_write_byte(connection pi, int handle, int data);
int sk_remote_i2c_read_byte_data(connection pi, int handle, int reg);
void sk_remote_i2c_write_byte_data(connection pi, int handle, int reg, int data);
int sk_remote_i2c_read_word_data(connection pi, int handle, int reg);
void sk_remote_i2c_write_word_data(connection pi, int handle, int reg, int data);

void sk_remote_clear_bank_1(connection pi);
bool sk_remote_gpio_cleanup(connection pi);

Expand Down
239 changes: 205 additions & 34 deletions coresdk/src/coresdk/raspi_adc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
using std::map;
using std::string;

using connection = int;
using adc_type = int;
using adc_pin = int;
constexpr adc_type ADS7830 = 0;
constexpr adc_pin ADC_PIN_0 = 0;
constexpr adc_pin ADC_PIN_7 = 7;
constexpr int ADC_PTR = 123;
constexpr int NONE_PTR = 0;

namespace splashkit_lib
{
// Internal structure for the ADC device.
Expand All @@ -28,35 +37,34 @@ namespace splashkit_lib
string name; // Device name
};

struct _remote_adc_data
{
pointer_identifier id; // Should be ADC_PTR
int i2c_handle; // I2C handle (obtained from i2c_open)
int bus; // I2C bus number
int address; // I2C address for the ADC device
adc_type type; // ADC type (e.g., ADS7830, PCF8591, etc.)
string name; // Device name
connection pi;
};

// Static map to manage loaded ADC devices (keyed by name)
static map<string, adc_device> _adc_devices;

std::map<std::string, std::unique_ptr<remote_adc_device>> remote_adc_devices;
// a function to return address based on pin number of ads7830
int _get_ads7830_pin_address(adc_pin pin)
{
switch (pin)
{
case ADC_PIN_0:
return 0x84; // CH0
case ADC_PIN_1:
return 0xC4; // CH1
case ADC_PIN_2:
return 0x94; // CH2
case ADC_PIN_3:
return 0xD4; // CH3
case ADC_PIN_4:
return 0xA4; // CH4
case ADC_PIN_5:
return 0xE4; // CH5
case ADC_PIN_6:
return 0xB4; // CH6
case ADC_PIN_7:
return 0xF4; // CH7
default:
return -1; // Invalid pin
int _get_ads7830_pin_address(adc_pin pin) {
switch (pin) {
case ADC_PIN_0: return 0x84; // Channel 0
case ADC_PIN_1: return 0xC4; // Channel 1
case ADC_PIN_2: return 0x94; // Channel 2
case ADC_PIN_3: return 0xD4; // Channel 3
case ADC_PIN_4: return 0xA4; // Channel 4
case ADC_PIN_5: return 0xE4; // Channel 5
case ADC_PIN_6: return 0xB4; // Channel 6
case ADC_PIN_7: return 0xF4; // Channel 7
default: return -1; // Or handle as an error
}
}
// const int CMD_CH0 = 0x84;

bool has_adc_device(const string &name)
{
Expand Down Expand Up @@ -100,16 +108,8 @@ namespace splashkit_lib
// Try to write a test byte to the device to check if it's responding.
// This is a simple way to check if the device is connected.
// For ADS7830, we can use a command like 0x84 (CH0) to test.
int test = sk_i2c_write_byte(result->i2c_handle, 0x84);
if (test < 0)
{
// ask the user to check the device connection
LOG(WARNING) << "Error communicating with ADC device, check your ADC connection" << name
<< " on bus " << bus << " at address " << address;
sk_i2c_close(result->i2c_handle);
delete result;
return nullptr;
}
sk_i2c_write_byte(result->i2c_handle, 0x84);


_adc_devices[name] = result;
return result;
Expand Down Expand Up @@ -329,4 +329,175 @@ namespace splashkit_lib
LOG(ERROR) << "ADC not supported on this platform";
#endif
}

bool remote_has_adc_device(const std::string& name) {
return remote_adc_devices.count(name) > 0;
}

// Start of remote functions
remote_adc_device remote_adc_device_named(const std::string& name) {
if (remote_has_adc_device(name)) {
return remote_adc_devices[name];
}
return nullptr;
}

remote_adc_device remote_load_adc_device(connection pi, const string &name, int bus, int address, adc_type type)
{
if (remote_has_adc_device(name)) {
return remote_adc_device_named(name);
}

// Use std::make_unique for safe memory allocation and ownership transfer
remote_adc_device result = new _remote_adc_data();
static int next_adc_id = 0;
result->id = static_cast<splashkit_lib::pointer_identifier>(next_adc_id++);
result->pi = pi;
result->bus = bus;
result->address = address;
result->name = name;
result->type = type;

result->i2c_handle = sk_remote_i2c_open(result->pi, result->bus, result->address, 0);

if (result->i2c_handle < 0) {
LOG(WARNING) << "Error opening remote ADC device " << name;
delete result;
return nullptr;
}

int test_result = sk_remote_i2c_write_byte(result->pi, result->i2c_handle, 0x84);
if (test_result < 0) {
LOG(WARNING) << "Failed to communicate with ADC device " << name << " (write test byte failed)";
sk_remote_i2c_close(result->pi, result->i2c_handle);
delete result;
return nullptr;
}

LOG(INFO) << "ADC device " << name << " loaded on bus " << bus << " at address " << address;

// Transfer ownership to the map
remote_adc_devices[name] = result;
return remote_adc_devices[name];
}

remote_adc_device remote_open_adc(connection pi, string name, adc_type type)
{
if (type != ADS7830)
{
LOG(ERROR) << "Unsupported ADC type for " << name;
return nullptr;
}
const int default_bus = 1;
const int default_address = 0x48; // Default I2C address for ADS7830
return remote_load_adc_device(pi, name, default_bus, default_address, type);
}

remote_adc_device remote_open_adc(connection pi, string name, int bus, int address, adc_type type)
{
if (remote_has_adc_device(name))
{
LOG(WARNING) << "ADC device " << name << " already loaded.";
return remote_adc_device_named(name);
}
return remote_load_adc_device(pi, name, bus, address, type);
}

int remote_read_adc_channel(remote_adc_device dev, int channel)
{
if (dev == nullptr)
{
LOG(WARNING) << "Invalid ADC device.";
return -1;
}

int command = 0;
switch (dev->type)
{
case ADS7830:
command = channel;
break;
default:
LOG(WARNING) << "Unsupported ADC type for device " << dev->name;
return -1;
}

if (sk_remote_i2c_write_byte(dev->pi, dev->i2c_handle, command) < 0)
{
LOG(WARNING) << "Failed to write ADC channel command for channel " << std::to_string(channel) << " on device " << dev->name;
return -1;
}

delay(10);

int value = sk_remote_i2c_read_byte(dev->pi, dev->i2c_handle);
if (value < 0)
{
LOG(WARNING) << "Error reading ADC channel " << std::to_string(channel) << " from device " << dev->name;
}
return value;
}

int remote_read_adc(remote_adc_device adc, adc_pin channel)
{
if (adc == nullptr)
{
LOG(ERROR) << "ADC device not initialized.";
return -1;
}

if (channel < ADC_PIN_0 || channel > ADC_PIN_7)
{
LOG(WARNING) << "Invalid ADC channel: " << std::to_string(channel) << " for device " << adc->name << " (ADS7830 supports 0-7)";
return -1;
}

int channel_num = _get_ads7830_pin_address(channel);
if (channel_num == -1)
{
LOG(ERROR) << "Invalid ADC pin: " << std::to_string(channel);
return -1;
}
return remote_read_adc_channel(adc, channel_num);
}

int remote_read_adc(const std::string& name, adc_pin channel) {
_remote_adc_data* dev = remote_adc_device_named(name);
if (dev == nullptr) {
LOG(ERROR) << "ADC device " << name << " not found.";
return -1;
}
int channel_num = _get_ads7830_pin_address(channel);
if (channel_num == -1) {
LOG(ERROR) << "Invalid ADC pin: " << channel <<;
return -1;
}
return remote_read_adc_channel(remote_adc_devices.at(name), channel_num);
}

void remote_close_adc(remote_adc_device adc)
{
remote_close_adc_device(adc);
}

void remote_close_adc(const std::string &name) {
auto it = remote_adc_devices.find(name);
if (it != remote_adc_devices.end()) {
remote_adc_devices.erase(it);
} else {
LOG(WARNING) << "Attempted to close unknown ADC device: " << name;
}
}

void remote_close_adc_device(remote_adc_device dev)
{
auto it = remote_adc_devices.find(dev->name);
if (it != remote_adc_devices.end()) {
sk_remote_i2c_close(it->second->pi, it->second->i2c_handle);
LOG(INFO) << "Closed ADC device: " << dev->name;
remote_adc_devices.erase(it);
} else {
LOG(WARNING) << "Attempted to close unknown ADC device: " << dev->name;
}
}
}
Loading