Skip to content

Commit 8994acf

Browse files
Merge pull request #99 from nasa-jpl/feat-el2809-driver
Feat el2809 driver
2 parents 88163c1 + 24ffcf9 commit 8994acf

File tree

9 files changed

+312
-0
lines changed

9 files changed

+312
-0
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_library(jsd-lib STATIC
99
jsd_el3602.c
1010
jsd_el3208.c
1111
jsd_el2124.c
12+
jsd_el2809.c
1213
jsd_egd.c
1314
jsd_el3356.c
1415
jsd_jed0101.c

src/jsd.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "jsd/jsd_egd.h"
1111
#include "jsd/jsd_el1008.h"
1212
#include "jsd/jsd_el2124.h"
13+
#include "jsd/jsd_el2809.h"
1314
#include "jsd/jsd_el3104.h"
1415
#include "jsd/jsd_el3162.h"
1516
#include "jsd/jsd_el3202.h"
@@ -448,6 +449,10 @@ bool jsd_init_single_device(jsd_t* self, uint16_t slave_id) {
448449
return jsd_el2124_init(self, slave_id);
449450
break;
450451
}
452+
case JSD_EL2809_PRODUCT_CODE: {
453+
return jsd_el2809_init(self, slave_id);
454+
break;
455+
}
451456
case JSD_EL3356_PRODUCT_CODE: {
452457
return jsd_el3356_init(self, slave_id);
453458
break;

src/jsd_el2809.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include "jsd/jsd_el2809.h"
2+
3+
#include <assert.h>
4+
5+
#include "jsd/jsd_sdo.h"
6+
7+
/****************************************************
8+
* Public functions
9+
****************************************************/
10+
11+
/**
12+
* @brief RxPDO struct used to set device command data in SOEM IOmap
13+
*/
14+
typedef struct __attribute__((__packed__)) {
15+
uint16_t flags;
16+
} jsd_el2809_rxpdo_t;
17+
18+
const jsd_el2809_state_t* jsd_el2809_get_state(jsd_t* self, uint16_t slave_id) {
19+
assert(self);
20+
assert(self->ecx_context.slavelist[slave_id].eep_id ==
21+
JSD_EL2809_PRODUCT_CODE);
22+
23+
return &self->slave_states[slave_id].el2809;
24+
}
25+
26+
void jsd_el2809_process(jsd_t* self, uint16_t slave_id) {
27+
assert(self);
28+
assert(self->ecx_context.slavelist[slave_id].eep_id ==
29+
JSD_EL2809_PRODUCT_CODE);
30+
31+
jsd_el2809_rxpdo_t* rxpdo =
32+
(jsd_el2809_rxpdo_t*)self->ecx_context.slavelist[slave_id].outputs;
33+
34+
int ch;
35+
for (ch = 0; ch < JSD_EL2809_NUM_CHANNELS; ch++) {
36+
uint8_t output = self->slave_states[slave_id].el2809.output[ch];
37+
38+
if (output > 0) {
39+
rxpdo->flags |= 0x01 << ch;
40+
} else {
41+
rxpdo->flags &= ~(0x01 << ch);
42+
}
43+
}
44+
}
45+
46+
void jsd_el2809_write_single_channel(jsd_t* self, uint16_t slave_id,
47+
uint8_t channel, uint8_t output) {
48+
assert(self);
49+
assert(self->ecx_context.slavelist[slave_id].eep_id ==
50+
JSD_EL2809_PRODUCT_CODE);
51+
52+
self->slave_states[slave_id].el2809.output[channel] = output;
53+
}
54+
55+
void jsd_el2809_write_all_channels(jsd_t* self, uint16_t slave_id,
56+
uint8_t output[JSD_EL2809_NUM_CHANNELS]) {
57+
int ch;
58+
for (ch = 0; ch < JSD_EL2809_NUM_CHANNELS; ch++) {
59+
jsd_el2809_write_single_channel(self, slave_id, ch, output[ch]);
60+
}
61+
}
62+
63+
/****************************************************
64+
* Private functions
65+
****************************************************/
66+
67+
bool jsd_el2809_init(jsd_t* self, uint16_t slave_id) {
68+
assert(self);
69+
assert(self->ecx_context.slavelist[slave_id].eep_id ==
70+
JSD_EL2809_PRODUCT_CODE);
71+
assert(self->ecx_context.slavelist[slave_id].eep_man ==
72+
JSD_BECKHOFF_VENDOR_ID);
73+
74+
jsd_slave_config_t* config = &self->slave_configs[slave_id];
75+
76+
// no PO2SO callback for 2809 devices, so set the success flag now
77+
config->PO2SO_success = true;
78+
79+
return true;
80+
}

src/jsd_el2809.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef JSD_EL2809_H
2+
#define JSD_EL2809_H
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
#include "jsd/jsd_el2809_pub.h"
9+
10+
/** @brief Initializes el2809
11+
*
12+
* @param self pointer JSD context
13+
* @param slave_id index of device on EtherCAT bus
14+
* @return true on success, false on failure
15+
*/
16+
bool jsd_el2809_init(jsd_t* self, uint16_t slave_id);
17+
18+
#ifdef __cplusplus
19+
}
20+
#endif
21+
22+
#endif

src/jsd_el2809_pub.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef JSD_EL2809_PUB_H
2+
#define JSD_EL2809_PUB_H
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
#include "jsd/jsd_el2809_types.h"
9+
#include "jsd/jsd_pub.h"
10+
11+
/**
12+
* @brief Read the EL2809 State
13+
*
14+
* Note: this device does not actually provide PDO feedback on state,
15+
* This function reads back the cmd sent to the EL2809 device
16+
*
17+
* @param self pointer to JSD context
18+
* @param slave_id id of EL2809 device
19+
* @return Pointer to EL2809 device state
20+
*/
21+
const jsd_el2809_state_t* jsd_el2809_get_state(jsd_t* self, uint16_t slave_id);
22+
23+
/**
24+
* @brief process loop required for proper device function
25+
*
26+
* @param self pointer to JSD context
27+
* @param slave_id id of EL2809 device
28+
*/
29+
void jsd_el2809_process(jsd_t* self, uint16_t slave_id);
30+
31+
/**
32+
* @brief Sets a specified channel level
33+
*
34+
* @param self pointer to JSD context
35+
* @param slave_id id of EL2809 device
36+
* @param channel specified device channel to command
37+
* @param output command level (0 or 1)
38+
*/
39+
void jsd_el2809_write_single_channel(jsd_t* self, uint16_t slave_id,
40+
uint8_t channel, uint8_t output);
41+
42+
/**
43+
* @brief Sets all channel levels
44+
*
45+
* @param self pointer to JSD context
46+
* @param slave_id id of EL2809 device
47+
* @param output command level (0 or 1)
48+
*/
49+
void jsd_el2809_write_all_channels(jsd_t* self, uint16_t slave_id,
50+
uint8_t output[JSD_EL2809_NUM_CHANNELS]);
51+
52+
#ifdef __cplusplus
53+
}
54+
#endif
55+
56+
#endif

src/jsd_el2809_types.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef JSD_EL2809_TYPES_H
2+
#define JSD_EL2809_TYPES_H
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
#include "jsd/jsd_common_device_types.h"
9+
10+
#define JSD_EL2809_PRODUCT_CODE (uint32_t)0x0af93052
11+
12+
#define JSD_EL2809_NUM_CHANNELS 16
13+
14+
/**
15+
* @brief EL2809 State Data
16+
*/
17+
typedef struct {
18+
uint8_t output[JSD_EL2809_NUM_CHANNELS]; ///< digital output level (0 or 1)
19+
} jsd_el2809_state_t;
20+
21+
/**
22+
* @brief EL2809 device configuration
23+
*/
24+
typedef struct {
25+
} jsd_el2809_config_t;
26+
27+
#ifdef __cplusplus
28+
}
29+
#endif
30+
31+
#endif

src/jsd_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extern "C" {
1212
#include "jsd/jsd_ati_fts_types.h"
1313
#include "jsd/jsd_egd_types.h"
1414
#include "jsd/jsd_el2124_types.h"
15+
#include "jsd/jsd_el2809_types.h"
1516
#include "jsd/jsd_el1008_types.h"
1617
#include "jsd/jsd_el3104_types.h"
1718
#include "jsd/jsd_el3162_types.h"
@@ -37,6 +38,7 @@ typedef struct {
3738
jsd_el3602_config_t el3602;
3839
jsd_el3208_config_t el3208;
3940
jsd_el2124_config_t el2124;
41+
jsd_el2809_config_t el2809;
4042
jsd_egd_config_t egd;
4143
jsd_el3356_config_t el3356;
4244
jsd_jed0101_config_t jed0101;
@@ -60,6 +62,7 @@ typedef struct {
6062
jsd_el3602_state_t el3602;
6163
jsd_el3208_state_t el3208;
6264
jsd_el2124_state_t el2124;
65+
jsd_el2809_state_t el2809;
6366
jsd_egd_private_state_t egd;
6467
jsd_el3356_state_t el3356;
6568
jsd_jed0101_state_t jed0101;

test/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ if(BUILD_JSD_TESTS)
4646
jsd_test_utils.c)
4747
target_link_libraries(jsd_el2124_test ${jsd_test_libs})
4848

49+
add_executable(jsd_el2809_test
50+
device/jsd_el2809_test.c
51+
jsd_test_utils.c)
52+
target_link_libraries(jsd_el2809_test ${jsd_test_libs})
53+
4954
add_executable(jsd_el3602_test
5055
device/jsd_el3602_test.c
5156
jsd_test_utils.c)

test/device/jsd_el2809_test.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include <assert.h>
2+
#include <string.h>
3+
4+
#include "jsd/jsd_el2809_pub.h"
5+
#include "jsd_test_utils.h"
6+
7+
extern bool quit;
8+
extern FILE* file;
9+
uint8_t slave_id;
10+
uint8_t cmd_output[JSD_EL2809_NUM_CHANNELS] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
11+
12+
void telemetry_header() {
13+
int i;
14+
if (!file) {
15+
return;
16+
}
17+
for (i = 0; i < JSD_EL2809_NUM_CHANNELS; ++i) {
18+
fprintf(file, "EL2809_output_ch%d, ", i);
19+
}
20+
fprintf(file, "\n");
21+
}
22+
23+
void telemetry_data(void* self) {
24+
assert(self);
25+
if (!file) {
26+
return;
27+
}
28+
29+
single_device_server_t* sds = (single_device_server_t*)self;
30+
const jsd_el2809_state_t* state = jsd_el2809_get_state(sds->jsd, slave_id);
31+
32+
int i;
33+
for (i = 0; i < JSD_EL2809_NUM_CHANNELS; ++i) {
34+
fprintf(file, "%u,", state->output[i]);
35+
}
36+
fprintf(file, "\n");
37+
fflush(file);
38+
}
39+
40+
void print_info(void* self) {
41+
assert(self);
42+
single_device_server_t* sds = (single_device_server_t*)self;
43+
44+
const jsd_el2809_state_t* state = jsd_el2809_get_state(sds->jsd, slave_id);
45+
46+
MSG("Ch0: %u, Ch1: %u, Ch2: %u, Ch3: %u, Ch4: %u, Ch5: %u, Ch6: %u, Ch7: %u, Ch8: %u, "
47+
"Ch9: %u, Ch10: %u, Ch11: %u, Ch12: %u, Ch13: %u, Ch14: %u, Ch15: %u, ",
48+
state->output[0], state->output[1], state->output[2], state->output[3],
49+
state->output[4], state->output[5], state->output[6], state->output[7],
50+
state->output[8], state->output[9], state->output[10], state->output[11],
51+
state->output[12], state->output[13], state->output[14], state->output[15]);
52+
}
53+
54+
void extract_data(void* self) {
55+
assert(self);
56+
single_device_server_t* sds = (single_device_server_t*)self;
57+
58+
jsd_el2809_process(sds->jsd, slave_id);
59+
}
60+
61+
void command(void* self) {
62+
assert(self);
63+
single_device_server_t* sds = (single_device_server_t*)self;
64+
65+
cmd_output[0] ^= 0x01;
66+
cmd_output[1] ^= 0x01;
67+
cmd_output[2] ^= 0x01;
68+
cmd_output[3] ^= 0x01;
69+
70+
jsd_el2809_write_all_channels(sds->jsd, slave_id, cmd_output);
71+
}
72+
73+
int main(int argc, char const* argv[]) {
74+
if (argc != 4) {
75+
ERROR("Expecting exactly 3 arguments");
76+
MSG("Usage: jsd_el2809_test <ifname> <el2809_slave_index> <loop_freq_hz>");
77+
MSG("Example: $ jsd_el2809 eth0 5 500");
78+
return 0;
79+
}
80+
81+
char* ifname = strdup(argv[1]);
82+
slave_id = atoi(argv[2]);
83+
uint16_t loop_freq_hz = atoi(argv[3]);
84+
MSG("Configuring device %s, using slave %d", ifname, slave_id);
85+
MSG("Using frequency of %u hz", loop_freq_hz);
86+
87+
single_device_server_t sds;
88+
89+
sds_set_telemetry_header_callback(&sds, telemetry_header);
90+
sds_set_telemetry_data_callback(&sds, telemetry_data);
91+
sds_set_print_info_callback(&sds, print_info);
92+
sds_set_extract_data_callback(&sds, extract_data);
93+
sds_set_command_callback(&sds, command);
94+
95+
sds_setup(&sds, loop_freq_hz);
96+
97+
// set device configuration here
98+
jsd_slave_config_t my_config = {0};
99+
100+
snprintf(my_config.name, JSD_NAME_LEN, "bigfoot");
101+
my_config.configuration_active = true;
102+
my_config.product_code = JSD_EL2809_PRODUCT_CODE;
103+
104+
jsd_set_slave_config(sds.jsd, slave_id, my_config);
105+
106+
sds_run(&sds, ifname, "/tmp/jsd_el2809.csv");
107+
108+
return 0;
109+
}

0 commit comments

Comments
 (0)