Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
209 changes: 198 additions & 11 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,9 +37,20 @@ 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;

static map<string, 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)
{
Expand Down Expand Up @@ -100,16 +120,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 +341,179 @@ 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)\n";
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 << "\n";

// 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.\n";
return -1;
}
int channel_num = _get_ads7830_pin_address(channel);
if (channel_num == -1) {
LOG(ERROR) << "Invalid ADC pin: " << channel << "\n";
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 string &name)
{
// Find the device in the local map of remotely opened devices
auto it = remote_adc_devices.find(name);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a heads-up in remote_close_adc_device, the pointer stored in remote_adc_devices isn’t being freed before erase, which means the allocated _remote_adc_data will leak. You might want to delete it->second; before erasing, or even better switch the map to unique_ptr so cleanup happens automatically.

if (it != remote_adc_devices.end()) {
remote_adc_device dev = it->second;
// Call the remote closing function
remote_close_adc_device(dev);
} 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 << "\n";
remote_adc_devices.erase(it);
} else {
LOG(WARNING) << "Attempted to close unknown ADC device: " << dev->name << "\n";
}
}
}
Loading