Skip to content

Commit

Permalink
Initial implementation gperf based reg parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
matwey committed Aug 4, 2019
1 parent a820ef8 commit 98ee691
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 25 deletions.
17 changes: 15 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ pkg_check_modules(CHECK REQUIRED check)
pkg_check_modules(LIBFTDI REQUIRED libftdi1)
pkg_check_modules(LIBZIP REQUIRED libzip>=1.0)

set(CMAKE_C_FLAGS "-std=c99 ${LIBFTDI_C_FLAGS} ${LIBZIP_C_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 ${LIBFTDI_C_FLAGS} ${LIBZIP_C_FLAGS}")

include_directories ("${PROJECT_SOURCE_DIR}/include")
include_directories ("${CMAKE_CURRENT_BINARY_DIR}")
include_directories ("${LIBFTDI_INCLUDE_DIRS}")
if(LIBZIP_INCLUDE_DIRS)
include_directories ("${LIBZIP_INCLUDE_DIRS}")
Expand All @@ -25,8 +26,20 @@ add_custom_command(OUTPUT ov3.fwpkg.o
COMMAND objcopy --rename-section .data=.rodata,contents,readonly ${CMAKE_CURRENT_BINARY_DIR}/ov3.fwpkg.o ${CMAKE_CURRENT_BINARY_DIR}/ov3.fwpkg.o
MAIN_DEPENDENCY ov3.fwpkg)

find_program(GPERF NAMES gperf)
if(NOT GPERF)
message(FATAL_ERROR "Could not find gperf tool")
endif()

add_custom_command(OUTPUT reg_gperf.h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GPERF} -t -L C src/reg.gperf > ${CMAKE_CURRENT_BINARY_DIR}/reg_gperf.h
MAIN_DEPENDENCY src/reg.gperf)

file(GLOB_RECURSE SOURCES src/*.c)
add_library(openvizsla SHARED ${SOURCES} ov3.fwpkg.o)
add_library(openvizsla SHARED ${SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/ov3.fwpkg.o
${CMAKE_CURRENT_BINARY_DIR}/reg_gperf.h)
target_link_libraries(openvizsla ${LIBFTDI_LIBRARIES} ${LIBZIP_LIBRARIES})
set_target_properties(openvizsla PROPERTIES VERSION 0.0.0 SOVERSION 0)

Expand Down
16 changes: 12 additions & 4 deletions include/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@

#include <stdint.h>

enum reg_name {
CSTREAM_CFG,
CSTREAM_CONS_LO,
CSTREAM_CONS_HI,

LEDS_OUT,

REG_MAX
};

struct reg {
const char* error_str;
uint16_t leds_out;
uint16_t addr[REG_MAX];
};

int reg_init(struct reg* reg);
int reg_from_map(struct reg* reg, char* map);
int reg_validate(struct reg* reg);
int reg_init(struct reg* reg, char* map);

#endif // _REG_H
43 changes: 33 additions & 10 deletions src/reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include <string.h>
#include <assert.h>

/* reg_gperf.h is generated by gperf */
#include <reg_gperf.h>

static char* x_strchr(const char *s, int c) {
char* n = NULL;

Expand All @@ -18,16 +21,22 @@ static char* x_strchr(const char *s, int c) {
}

static int reg_from_pair(struct reg* reg, char* key, unsigned long int value) {

assert(value > 0);
assert(value <= 0xFFFF);
assert(value < 0xFFFF);

/* in_word_set() is generated by gperf */
struct reg_decode* rd = in_word_set(key, strlen(key));
if (!rd) {
return -1;
}

reg->leds_out = value;
reg->addr[rd->reg_name] = value;

return 0;
}

static int reg_from_line(struct reg* reg, char* line) {
const char sep[] = " ";
char* key = line;
char* value = NULL;

Expand All @@ -38,16 +47,28 @@ static int reg_from_line(struct reg* reg, char* line) {
return -1;
*(value++) = '\0';

return reg_from_pair(reg, key, strtoul(value, NULL, 16));
key = strtok(key, sep);
assert(key);

reg_from_pair(reg, key, strtoul(value, NULL, 16));

return 0;
}

int reg_init(struct reg* reg) {
memset(reg, 0, sizeof(struct reg));
static int reg_validate(struct reg* reg) {
size_t i = 0;

for (i = 0; i < REG_MAX; ++i) {
if (reg->addr[REG_MAX] == 0xffff) {
reg->error_str = "Missed register address";
return -1;
}
}

return 0;
}

int reg_from_map(struct reg* reg, char* map) {
static int reg_init_from_map(struct reg* reg, char* map) {
char* c = map;
char* n = NULL;

Expand All @@ -61,10 +82,12 @@ int reg_from_map(struct reg* reg, char* map) {
c = n;
} while (n);

return 0;
return reg_validate(reg);
}

int reg_validate(struct reg* reg) {
int reg_init(struct reg* reg, char* map) {
memset(reg, 0xff, sizeof(struct reg));
reg->error_str = NULL;

return 0;
return reg_init_from_map(reg, map);
}
7 changes: 7 additions & 0 deletions src/reg.gperf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
struct reg_decode { char* name; enum reg_name reg_name; };
%%
CSTREAM_CFG, CSTREAM_CFG
CSTREAM_CONS_LO, CSTREAM_CONS_LO
CSTREAM_CONS_HI, CSTREAM_CONS_HI
LEDS_OUT, LEDS_OUT
%%
11 changes: 2 additions & 9 deletions test/reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@

#include <reg.h>

START_TEST (test_reg_init1) {
struct reg reg;
ck_assert_int_eq(reg_init(&reg), 0);
}
END_TEST
START_TEST (test_reg_from_map1) {
char x[] = "LEDS_OUT = 0x42";
struct reg reg;
ck_assert_int_eq(reg_init(&reg), 0);
ck_assert_int_eq(reg_from_map(&reg, x), 0);
ck_assert_int_eq(reg.leds_out, 0x42);
ck_assert_int_eq(reg_init(&reg, x), 0);
ck_assert_int_eq(reg.addr[LEDS_OUT], 0x42);
}
END_TEST

Expand All @@ -25,7 +19,6 @@ Suite* range_suite(void) {

tc_core = tcase_create("Core");

tcase_add_test(tc_core, test_reg_init1);
tcase_add_test(tc_core, test_reg_from_map1);
suite_add_tcase(s, tc_core);

Expand Down

0 comments on commit 98ee691

Please sign in to comment.