mirror of
https://github.com/xtacocorex/CHIP_IO
synced 2025-07-20 04:43:21 +00:00
PWM support fixed, the test fails when trying to change the frequency, but I don't think that's an issue. Have not run this against something that needs PWM to operate, but the .dtb I have loaded has /sys/class/pwm/pwmchip0 and it can be configured with this code
This commit is contained in:
2
setup.py
2
setup.py
@ -20,7 +20,7 @@ classifiers = ['Development Status :: 3 - Alpha',
|
|||||||
'Topic :: System :: Hardware']
|
'Topic :: System :: Hardware']
|
||||||
|
|
||||||
setup(name = 'CHIP_IO',
|
setup(name = 'CHIP_IO',
|
||||||
version = '0.0.5',
|
version = '0.0.6',
|
||||||
author = 'Robert Wolterman',
|
author = 'Robert Wolterman',
|
||||||
author_email = 'robert.wolterman@gmail.com',
|
author_email = 'robert.wolterman@gmail.com',
|
||||||
description = 'A module to control CHIP IO channels',
|
description = 'A module to control CHIP IO channels',
|
||||||
|
@ -52,6 +52,8 @@ struct pwm_exp
|
|||||||
int period_fd;
|
int period_fd;
|
||||||
int duty_fd;
|
int duty_fd;
|
||||||
int polarity_fd;
|
int polarity_fd;
|
||||||
|
int enable_fd;
|
||||||
|
int enable;
|
||||||
unsigned long duty;
|
unsigned long duty;
|
||||||
unsigned long period_ns;
|
unsigned long period_ns;
|
||||||
struct pwm_exp *next;
|
struct pwm_exp *next;
|
||||||
@ -126,7 +128,7 @@ int pwm_set_frequency(const char *key, float freq) {
|
|||||||
|
|
||||||
int pwm_set_polarity(const char *key, int polarity) {
|
int pwm_set_polarity(const char *key, int polarity) {
|
||||||
int len;
|
int len;
|
||||||
char buffer[7]; /* allow room for trailing NUL byte */
|
char buffer[9]; /* allow room for trailing NUL byte */
|
||||||
struct pwm_exp *pwm;
|
struct pwm_exp *pwm;
|
||||||
|
|
||||||
pwm = lookup_exported_pwm(key);
|
pwm = lookup_exported_pwm(key);
|
||||||
@ -135,7 +137,17 @@ int pwm_set_polarity(const char *key, int polarity) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = snprintf(buffer, sizeof(buffer), "%d", polarity);
|
if (polarity < 0 || polarity > 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polarity == 0) {
|
||||||
|
len = snprintf(buffer, sizeof(buffer), "%s", "normal");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = snprintf(buffer, sizeof(buffer), "%s", "inverted");
|
||||||
|
}
|
||||||
write(pwm->polarity_fd, buffer, len);
|
write(pwm->polarity_fd, buffer, len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -163,13 +175,37 @@ int pwm_set_duty_cycle(const char *key, float duty) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pwm_set_enable(const char *key, int enable)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char buffer[20];
|
||||||
|
struct pwm_exp *pwm;
|
||||||
|
|
||||||
|
if (enable != 0 || enable != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pwm = lookup_exported_pwm(key);
|
||||||
|
|
||||||
|
if (pwm == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm->enable = enable;
|
||||||
|
|
||||||
|
len = snprintf(buffer, sizeof(buffer), "%d", pwm->enable);
|
||||||
|
write(pwm->enable_fd, buffer, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int pwm_start(const char *key, float duty, float freq, int polarity)
|
int pwm_start(const char *key, float duty, float freq, int polarity)
|
||||||
{
|
{
|
||||||
char pwm_base_path[45];
|
char pwm_base_path[45];
|
||||||
char period_path[50];
|
char period_path[50];
|
||||||
char duty_path[50];
|
char duty_path[50];
|
||||||
|
char enable_path[50];
|
||||||
char polarity_path[55];
|
char polarity_path[55];
|
||||||
int period_fd, duty_fd, polarity_fd;
|
int period_fd, duty_fd, polarity_fd, enable_fd;
|
||||||
struct pwm_exp *new_pwm, *pwm;
|
struct pwm_exp *new_pwm, *pwm;
|
||||||
|
|
||||||
if(!pwm_initialized) {
|
if(!pwm_initialized) {
|
||||||
@ -180,23 +216,31 @@ int pwm_start(const char *key, float duty, float freq, int polarity)
|
|||||||
snprintf(pwm_base_path, sizeof(pwm_base_path), "/sys/class/pwm/pwmchip0/%d", "pwm0");
|
snprintf(pwm_base_path, sizeof(pwm_base_path), "/sys/class/pwm/pwmchip0/%d", "pwm0");
|
||||||
|
|
||||||
//create the path for the period and duty
|
//create the path for the period and duty
|
||||||
|
snprintf(enable_path, sizeof(enable_path), "%s/enable", pwm_base_path);
|
||||||
snprintf(period_path, sizeof(period_path), "%s/period", pwm_base_path);
|
snprintf(period_path, sizeof(period_path), "%s/period", pwm_base_path);
|
||||||
snprintf(duty_path, sizeof(duty_path), "%s/duty", pwm_base_path);
|
snprintf(duty_path, sizeof(duty_path), "%s/duty_cycle", pwm_base_path);
|
||||||
snprintf(polarity_path, sizeof(polarity_path), "%s/polarity", pwm_base_path);
|
snprintf(polarity_path, sizeof(polarity_path), "%s/polarity", pwm_base_path);
|
||||||
|
|
||||||
//add period and duty fd to pwm list
|
//add period and duty fd to pwm list
|
||||||
if ((period_fd = open(period_path, O_RDWR)) < 0)
|
if ((enable_fd = open(enable_path, O_RDWR)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if ((period_fd = open(period_path, O_RDWR)) < 0) {
|
||||||
|
close(enable_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((duty_fd = open(duty_path, O_RDWR)) < 0) {
|
if ((duty_fd = open(duty_path, O_RDWR)) < 0) {
|
||||||
//error, close already opened period_fd.
|
//error, close already opened period_fd.
|
||||||
|
close(enable_fd);
|
||||||
close(period_fd);
|
close(period_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((polarity_fd = open(polarity_path, O_RDWR)) < 0) {
|
if ((polarity_fd = open(polarity_path, O_RDWR)) < 0) {
|
||||||
//error, close already opened period_fd and duty_fd.
|
//error, close already opened period_fd and duty_fd.
|
||||||
|
close(enable_fd);
|
||||||
close(period_fd);
|
close(period_fd);
|
||||||
close(duty_fd);
|
close(duty_fd);
|
||||||
return -1;
|
return -1;
|
||||||
@ -213,6 +257,7 @@ int pwm_start(const char *key, float duty, float freq, int polarity)
|
|||||||
new_pwm->period_fd = period_fd;
|
new_pwm->period_fd = period_fd;
|
||||||
new_pwm->duty_fd = duty_fd;
|
new_pwm->duty_fd = duty_fd;
|
||||||
new_pwm->polarity_fd = polarity_fd;
|
new_pwm->polarity_fd = polarity_fd;
|
||||||
|
new_pwm->enable_fd = enable_fd;
|
||||||
new_pwm->next = NULL;
|
new_pwm->next = NULL;
|
||||||
|
|
||||||
if (exported_pwms == NULL)
|
if (exported_pwms == NULL)
|
||||||
@ -229,6 +274,7 @@ int pwm_start(const char *key, float duty, float freq, int polarity)
|
|||||||
|
|
||||||
pwm_set_frequency(key, freq);
|
pwm_set_frequency(key, freq);
|
||||||
pwm_set_polarity(key, polarity);
|
pwm_set_polarity(key, polarity);
|
||||||
|
pwm_set_enable(key, 1);
|
||||||
pwm_set_duty_cycle(key, duty);
|
pwm_set_duty_cycle(key, duty);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -245,6 +291,12 @@ int pwm_disable(const char *key)
|
|||||||
// we need to export 0 here to enable pwm0
|
// we need to export 0 here to enable pwm0
|
||||||
int gpio = 0;
|
int gpio = 0;
|
||||||
|
|
||||||
|
// Disable the PWM
|
||||||
|
pwm_set_frequency(key, 0);
|
||||||
|
pwm_set_polarity(key, 0);
|
||||||
|
pwm_set_enable(key, 0);
|
||||||
|
pwm_set_duty_cycle(key, 0);
|
||||||
|
|
||||||
if ((fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY)) < 0)
|
if ((fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY)) < 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
@ -260,6 +312,7 @@ int pwm_disable(const char *key)
|
|||||||
if (strcmp(pwm->key, key) == 0)
|
if (strcmp(pwm->key, key) == 0)
|
||||||
{
|
{
|
||||||
//close the fd
|
//close the fd
|
||||||
|
close(pwm->enable_fd);
|
||||||
close(pwm->period_fd);
|
close(pwm->period_fd);
|
||||||
close(pwm->duty_fd);
|
close(pwm->duty_fd);
|
||||||
close(pwm->polarity_fd);
|
close(pwm->polarity_fd);
|
||||||
|
@ -33,4 +33,5 @@ int pwm_start(const char *key, float duty, float freq, int polarity);
|
|||||||
int pwm_disable(const char *key);
|
int pwm_disable(const char *key);
|
||||||
int pwm_set_frequency(const char *key, float freq);
|
int pwm_set_frequency(const char *key, float freq);
|
||||||
int pwm_set_duty_cycle(const char *key, float duty);
|
int pwm_set_duty_cycle(const char *key, float duty);
|
||||||
|
int pwm_set_enable(const char *key, int enable);
|
||||||
void pwm_cleanup(void);
|
void pwm_cleanup(void);
|
||||||
|
@ -121,19 +121,19 @@ pins_t table[] = {
|
|||||||
{ "TWI2-SDA", "U14_25", 50, -1, -1},
|
{ "TWI2-SDA", "U14_25", 50, -1, -1},
|
||||||
{ "TWI2-SCK", "U14_26", 49, -1, -1},
|
{ "TWI2-SCK", "U14_26", 49, -1, -1},
|
||||||
{ "CSIPCK", "U14_27", 128, -1, -1},
|
{ "CSIPCK", "U14_27", 128, -1, -1},
|
||||||
{ "CSICK", "U14_28", 129, 4, -1},
|
{ "CSICK", "U14_28", 129, -1, -1},
|
||||||
{ "CSIHSYNC", "U14_29", 130, 1, -1},
|
{ "CSIHSYNC", "U14_29", 130, 1, -1},
|
||||||
{ "CSIVSYNC", "U14_30", 131, -1, -1},
|
{ "CSIVSYNC", "U14_30", 131, -1, -1},
|
||||||
{ "CSID0", "U14_31", 132, 1, -1},
|
{ "CSID0", "U14_31", 132, 1, -1},
|
||||||
{ "CSID1", "U14_32", 133, -1, -1},
|
{ "CSID1", "U14_32", 133, -1, -1},
|
||||||
{ "CSID2", "U14_33", 134, -1, 4},
|
{ "CSID2", "U14_33", 134, -1, -1},
|
||||||
{ "CSID3", "U14_34", 135, -1, -1},
|
{ "CSID3", "U14_34", 135, -1, -1},
|
||||||
{ "CSID4", "U14_35", 136, -1, 6},
|
{ "CSID4", "U14_35", 136, -1, -1},
|
||||||
{ "CSID5", "U14_36", 137, -1, 5},
|
{ "CSID5", "U14_36", 137, -1, -1},
|
||||||
{ "CSID6", "U14_37", 138, -1, 2},
|
{ "CSID6", "U14_37", 138, -1, -1},
|
||||||
{ "CSID7", "U14_38", 139, -1, 3},
|
{ "CSID7", "U14_38", 139, -1, -1},
|
||||||
{ "GND", "U14_39", 0, -1, 0},
|
{ "GND", "U14_39", 0, -1, -1},
|
||||||
{ "GND", "U14_40", 0, -1, 1},
|
{ "GND", "U14_40", 0, -1, -1},
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,6 +76,6 @@ void define_constants(PyObject *module)
|
|||||||
both_edge = Py_BuildValue("i", BOTH_EDGE);
|
both_edge = Py_BuildValue("i", BOTH_EDGE);
|
||||||
PyModule_AddObject(module, "BOTH", both_edge);
|
PyModule_AddObject(module, "BOTH", both_edge);
|
||||||
|
|
||||||
version = Py_BuildValue("s", "0.0.4");
|
version = Py_BuildValue("s", "0.0.6");
|
||||||
PyModule_AddObject(module, "VERSION", version);
|
PyModule_AddObject(module, "VERSION", version);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class TestPwmSetup:
|
|||||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||||
|
|
||||||
assert os.path.exists(pwm_test)
|
assert os.path.exists(pwm_test)
|
||||||
duty = open(pwm_test + '/duty').read()
|
duty = open(pwm_test + '/duty_cycle').read()
|
||||||
period = open(pwm_test + '/period').read()
|
period = open(pwm_test + '/period').read()
|
||||||
assert int(duty) == 0
|
assert int(duty) == 0
|
||||||
assert int(period) == 500000
|
assert int(period) == 500000
|
||||||
@ -25,12 +25,12 @@ class TestPwmSetup:
|
|||||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||||
|
|
||||||
assert os.path.exists(pwm_test)
|
assert os.path.exists(pwm_test)
|
||||||
duty = open(pwm_test + '/duty').read()
|
duty = open(pwm_test + '/duty_cycle').read()
|
||||||
period = open(pwm_test + '/period').read()
|
period = open(pwm_test + '/period').read()
|
||||||
polarity = open(pwm_test + '/polarity').read()
|
polarity = open(pwm_test + '/polarity').read()
|
||||||
assert int(duty) == 0
|
assert int(duty) == 0
|
||||||
assert int(period) == 500000
|
assert int(period) == 500000
|
||||||
assert int(polarity) == 1
|
assert string(polarity) == "inverted"
|
||||||
PWM.cleanup()
|
PWM.cleanup()
|
||||||
|
|
||||||
def test_start_pwm_with_polarity_default(self):
|
def test_start_pwm_with_polarity_default(self):
|
||||||
@ -39,12 +39,12 @@ class TestPwmSetup:
|
|||||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||||
|
|
||||||
assert os.path.exists(pwm_test)
|
assert os.path.exists(pwm_test)
|
||||||
duty = open(pwm_test + '/duty').read()
|
duty = open(pwm_test + '/duty_cycle').read()
|
||||||
period = open(pwm_test + '/period').read()
|
period = open(pwm_test + '/period').read()
|
||||||
polarity = open(pwm_test + '/polarity').read()
|
polarity = open(pwm_test + '/polarity').read()
|
||||||
assert int(duty) == 0
|
assert int(duty) == 0
|
||||||
assert int(period) == 500000
|
assert int(period) == 500000
|
||||||
assert int(polarity) == 0
|
assert string(polarity) == "normal"
|
||||||
PWM.cleanup()
|
PWM.cleanup()
|
||||||
|
|
||||||
def test_start_pwm_with_polarity_zero(self):
|
def test_start_pwm_with_polarity_zero(self):
|
||||||
@ -53,12 +53,12 @@ class TestPwmSetup:
|
|||||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||||
|
|
||||||
assert os.path.exists(pwm_test)
|
assert os.path.exists(pwm_test)
|
||||||
duty = open(pwm_test + '/duty').read()
|
duty = open(pwm_test + '/duty_cycle').read()
|
||||||
period = open(pwm_test + '/period').read()
|
period = open(pwm_test + '/period').read()
|
||||||
polarity = open(pwm_test + '/polarity').read()
|
polarity = open(pwm_test + '/polarity').read()
|
||||||
assert int(duty) == 0
|
assert int(duty) == 0
|
||||||
assert int(period) == 500000
|
assert int(period) == 500000
|
||||||
assert int(polarity) == 0
|
assert string(polarity) == "normal"
|
||||||
PWM.cleanup()
|
PWM.cleanup()
|
||||||
|
|
||||||
def test_pwm_start_invalid_pwm_key(self):
|
def test_pwm_start_invalid_pwm_key(self):
|
||||||
@ -113,13 +113,13 @@ class TestPwmSetup:
|
|||||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||||
|
|
||||||
assert os.path.exists(pwm_test)
|
assert os.path.exists(pwm_test)
|
||||||
duty = open(pwm_test + '/duty').read()
|
duty = open(pwm_test + '/duty_cycle').read()
|
||||||
period = open(pwm_test + '/period').read()
|
period = open(pwm_test + '/period').read()
|
||||||
assert int(duty) == 0
|
assert int(duty) == 0
|
||||||
assert int(period) == 500000
|
assert int(period) == 500000
|
||||||
|
|
||||||
PWM.set_duty_cycle("PWM0", 100)
|
PWM.set_duty_cycle("PWM0", 100)
|
||||||
duty = open(pwm_test + '/duty').read()
|
duty = open(pwm_test + '/duty_cycle').read()
|
||||||
period = open(pwm_test + '/period').read()
|
period = open(pwm_test + '/period').read()
|
||||||
assert int(duty) == 500000
|
assert int(duty) == 500000
|
||||||
assert int(period) == 500000
|
assert int(period) == 500000
|
||||||
|
Reference in New Issue
Block a user