From 96a8c3b35f2f198db4690f2609fbdb0c9f9180a2 Mon Sep 17 00:00:00 2001 From: jaseg Date: Mon, 28 Jan 2013 00:00:58 +0100 Subject: [PATCH] It is working now. To be fixed: * There is some dirty stuff going on inside the AVR ISR. * For ease of debugging the config is stored and sent in plain text, the LZMA stuff needs to be uncommented. * Quite probably one or two more ugly hacks, the whole thing should be reviewed. --- .gitignore | 1 + avr/uart.c | 34 ++++++++---- avr/uart.h | 16 +----- avr/ws2801-patterns.c.tp | 114 ++++++++++++++++++++++++----------------- common/comm_handle.h | 18 +++++-- common/main.c | 7 +-- common/uart.h | 1 + generator.py | 10 ++-- pylibcerebrum/pylibcerebrum.py | 24 +++++---- 9 files changed, 131 insertions(+), 94 deletions(-) diff --git a/.gitignore b/.gitignore index 09ede66..ee60c76 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ builds lib .zsh */__pycache__ +makefile diff --git a/avr/uart.c b/avr/uart.c index 19c2f70..0a27e03 100644 --- a/avr/uart.c +++ b/avr/uart.c @@ -204,14 +204,15 @@ static volatile unsigned char UART_TxTail; ISR(UART0_RECEIVE_INTERRUPT) { unsigned char data; - unsigned char usr; - unsigned char lastRxError; + //unsigned char usr; + //unsigned char lastRxError; /* read UART status register and UART data register */ - usr = UART0_STATUS; + //usr = UART0_STATUS; data = UART0_DATA; + /* #if defined( AT90_UART ) lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); #elif defined( ATMEGA_USART ) @@ -221,7 +222,9 @@ ISR(UART0_RECEIVE_INTERRUPT) #elif defined ( ATMEGA_UART ) lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); #endif + */ + //uart_putc(data); comm_handle(data); } @@ -258,8 +261,6 @@ void uart_init(unsigned int baudrate) { UART_TxHead = 0; UART_TxTail = 0; - UART_RxHead = 0; - UART_RxTail = 0; #if defined( AT90_UART ) /* set baud rate */ @@ -335,20 +336,31 @@ void uart_putc(unsigned char data) { unsigned char tmphead; + tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK; - tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK; - - while ( tmphead == UART_TxTail ){ - ;/* wait for free space in buffer */ - } + while ( tmphead == UART_TxTail );/* wait for free space in buffer */ UART_TxBuf[tmphead] = data; UART_TxHead = tmphead; /* enable UDRE interrupt */ UART0_CONTROL |= _BV(UART0_UDRIE); +} + +void uart_putc_nonblocking(unsigned char data){ + unsigned char tmphead; + + tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK; + + if(tmphead == UART_TxTail) //if there is no free space in buffer + return; + + UART_TxBuf[tmphead] = data; + UART_TxHead = tmphead; -}/* uart_putc */ + //enable UDRE interrupt + UART0_CONTROL |= _BV(UART0_UDRIE); +} /************************************************************************* diff --git a/avr/uart.h b/avr/uart.h index 11bf1ef..106541c 100644 --- a/avr/uart.h +++ b/avr/uart.h @@ -145,6 +145,7 @@ extern unsigned int uart_getc(void); */ extern void uart_putc(unsigned char data); +extern void uart_putc_nonblocking(unsigned char data); /** * @brief Put string to ringbuffer for transmitting via UART @@ -177,21 +178,6 @@ extern void uart_puts_p(const char *s ); */ #define uart_puts_P(__s) uart_puts_p(PSTR(__s)) - - -/** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */ -extern void uart1_init(unsigned int baudrate); -/** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */ -extern unsigned int uart1_getc(void); -/** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */ -extern void uart1_putc(unsigned char data); -/** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */ -extern void uart1_puts(const char *s ); -/** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */ -extern void uart1_puts_p(const char *s ); -/** @brief Macro to automatically put a string constant into program memory */ -#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s)) - /**@}*/ diff --git a/avr/ws2801-patterns.c.tp b/avr/ws2801-patterns.c.tp index a3721c9..3829906 100644 --- a/avr/ws2801-patterns.c.tp +++ b/avr/ws2801-patterns.c.tp @@ -14,7 +14,7 @@ ${modulevar("buffer", "uint8_t", "{}B".format(member["length"]*3), array=member["length"]*3)}; // B G R -#define NR_OF_PATTERNS 7 +#define NR_OF_PATTERNS 11 const uint8_t patterns[NR_OF_PATTERNS*${member["length"]*3}] PROGMEM = { @@ -89,7 +89,7 @@ const uint8_t patterns[NR_OF_PATTERNS*${member["length"]*3}] PROGMEM = { // rote lange wuerstchen % for i in range(member["length"]): % if i % 128 < 64: - 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0x00, % else: 0x00, 0x00, 0x00, % endif @@ -98,68 +98,94 @@ const uint8_t patterns[NR_OF_PATTERNS*${member["length"]*3}] PROGMEM = { // TEMPLATE CODE ////////////////////////////////////// +// rote lange wuerstchen % for i in range(member["length"]): -<% foo=int(i*6/member["length"]) %> -<% r=i-foo*member["length"]/6 %> -% if foo == 0: - 0xFF, - ${r*6/member["length"]}*255, - 0x00, -% endif -% if foo == 1: - ${1-r*6/member["length"]}*255, - 0xFF, - 0x00, +% if i % 128 < 64: + 0x00, 0x00, 0xFF, +% else: + 0x00, 0x00, 0x00, % endif -% if foo == 2: - 0x00, - 0xFF, - ${r*6/member["length"]}*255, +% endfor + + +// TEMPLATE CODE ////////////////////////////////////// + +// kleiner weisser pupsi + +% for i in range(member["length"]): +% if i % 256 < 16: + 0xFF, 0xFF, 0xFF, +% else: + 0x00, 0x00, 0x00, % endif -% if foo == 3: - 0x00, - ${1-r*6/member["length"]}*255, - 0xFF, +% endfor + + +// TEMPLATE CODE ////////////////////////////////////// + +// kleiner blauer pupsi + +% for i in range(member["length"]): +% if i % 256 < 16: + 0xFF, 0x00, 0x00, +% else: + 0x00, 0x00, 0x00, % endif -% if foo == 4: - ${r*6/member["length"]}*255, - 0x00, - 0xFF, +% endfor + +// TEMPLATE CODE ////////////////////////////////////// + +// kleiner gruener pupsi + +% for i in range(member["length"]): +% if i % 256 < 16: + 0x00, 0xFF, 0x00, +% else: + 0x00, 0x00, 0x00, % endif -% if foo == 5: - 0xFF, - 0x00, - ${1-r*6/member["length"]}*255, +% endfor + + +// TEMPLATE CODE ////////////////////////////////////// + +// kleiner roter pupsi + +% for i in range(member["length"]): +% if i % 256 < 16: + 0x00, 0x00, 0xFF, +% else: + 0x00, 0x00, 0x00, % endif % endfor + // TEMPLATE CODE ////////////////////////////////////// +// notbeleuchtung + % for i in range(member["length"]): -% if i < 16: - 0xFF, 0xFF, 0xFF, +% if i % 32 < 4: + 0x00, 0x24, 0x24, % else: 0x00, 0x00, 0x00, % endif % endfor -}; +}; -//${modulevar("pattern", None, "B")} -void callback_set_${modulevar("pattern")} (uint16_t payload_offset, uint16_t argsize, uint8_t* args){ - if (args[0] < NR_OF_PATTERNS) { +//${modulevar("pattern", None, "B", accid=register_callback("callback_get_"+modulevar("pattern")))} +//${register_callback("callback_set_"+modulevar("pattern"))} +void callback_set_${modulevar("pattern")} (const comm_callback_descriptor* cb, void* argbuf_end){ + uint8_t pattern=((uint8_t*)cb->argbuf)[0]; + if (pattern < NR_OF_PATTERNS) { //memcpy(${modulevar("buffer")}, patterns[args[0]], ${member["length"]*3}); - memcpy_PF(${modulevar("buffer")}, patterns+(${member["length"]*3}*args[0]), ${member["length"]*3}); + memcpy_PF(${modulevar("buffer")}, patterns+(${member["length"]*3}*pattern), ${member["length"]*3}); } uart_putc(0x00); uart_putc(0x00); - uart_putc(0x00); - uart_putc(0x00); } -void callback_get_${modulevar("pattern")} (uint16_t payload_offset, uint16_t argsize, uint8_t* args){ - uart_putc(0x00); - uart_putc(0x00); +void callback_get_${modulevar("pattern")} (const comm_callback_descriptor* cb, void* argbuf_end){ uart_putc(0x00); uart_putc(0x00); } @@ -169,7 +195,6 @@ ${modulevar("speed", "int8_t", "b")} = 2; void ${loop_function()}(void){ //for(uint8_t* i=${modulevar("buffer")}; i<${modulevar("buffer")}+${member["length"]*3}; i++){ - /* for(uint16_t i=0; i<${member["length"]}; i++){ uint16_t j=${modulevar("offset")}+i; if(j>=${member["length"]}) @@ -184,10 +209,5 @@ void ${loop_function()}(void){ if(${modulevar("offset")}<0) ${modulevar("offset")}+=${member["length"]}; _delay_us(1000); - */ } -void ${init_function()}(void){ - uint8_t foo[] = {1}; - callback_set_${modulevar("pattern")} (0,1,foo); -} diff --git a/common/comm_handle.h b/common/comm_handle.h index 644133a..fab6f50 100644 --- a/common/comm_handle.h +++ b/common/comm_handle.h @@ -1,13 +1,14 @@ #ifndef COMM_HANDLE_H #define COMM_HANDLE_H -#include - +#include "comm.h" #ifdef __TEST__ #include +#include //FIXME detect endianness #define comm_debug_print(...) //fprintf(stderr, __VA_ARGS__) #define comm_debug_print2(...) //fprintf(stderr, __VA_ARGS__) #else//__TEST__ +#define htobe16(...) (__VA_ARGS__) #define comm_debug_print(...) #define comm_debug_print2(...) #endif//__TEST__ @@ -28,6 +29,10 @@ static inline void comm_handle(uint8_t c){ args_t* args = (args_t*)global_argbuf; #define ARGS_END (((uint8_t*)(args))+sizeof(args_t)) //comm_debug_print("[DEBUG] received %c\n", c); + /*uart_putc_nonblocking('A'); + uart_putc_nonblocking(c); + uart_putc_nonblocking(state.escaped); + uart_putc_nonblocking(state.receiving);*/ if(state.escaped){ state.escaped = 0; if(c == '#'){ @@ -62,7 +67,7 @@ static inline void comm_handle(uint8_t c){ argbuf = comm_callbacks[htobe16(args->funcid)].argbuf; current_callback = comm_callbacks + htobe16(args->funcid); uint16_t len = current_callback->argbuf_len; - if(htobe16(args->arglen) < len){ + if(htobe16(args->arglen) <= len){ len = htobe16(args->arglen); } argbuf_end = argbuf+len; @@ -71,11 +76,16 @@ static inline void comm_handle(uint8_t c){ } } comm_debug_print2("[DEBUG] calling callback\n"); + state.receiving = 0; if(current_callback->callback != 0){ + sei(); (*current_callback->callback)(current_callback, argbuf_end); + }else{ + //Send a minimal response. + uart_putc_nonblocking(0); + uart_putc_nonblocking(0); } comm_debug_print("[DEBUG] going to idle state\n"); - state.receiving = 0; } #undef ARGS_END } diff --git a/common/main.c b/common/main.c index 875c708..fbc75b2 100644 --- a/common/main.c +++ b/common/main.c @@ -9,6 +9,7 @@ #ifdef __AVR__ #include #include +#include #endif #include @@ -20,7 +21,6 @@ #endif void init(void); -void loop(void); int main(void){ init(); @@ -31,7 +31,7 @@ int main(void){ comm_handle(v); } #else - for(;;) auto_loop(); + for(;;) loop_auto(); #endif } @@ -51,7 +51,8 @@ void init(){ P1SEL |= 0x03; P1SEL2 |= 0x03; #elif defined(__AVR__)//__MSPGCC__ - uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(9600, F_CPU)); + wdt_disable(); + uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(115200, F_CPU)); #endif//AVR init_auto(); diff --git a/common/uart.h b/common/uart.h index a970e33..2dd0e26 100644 --- a/common/uart.h +++ b/common/uart.h @@ -6,6 +6,7 @@ void uart_init(); uint16_t uart_getc(void); void uart_putc(uint8_t data); +void uart_putc_nonblocking(uint8_t data); #endif // UART_H diff --git a/generator.py b/generator.py index 9fc68de..6ad6813 100644 --- a/generator.py +++ b/generator.py @@ -157,7 +157,7 @@ def generate(desc, device, build_path, builddate, target = 'all'): functions = {} #FIXME possibly swap the positions of ctype and fmt - def modulevar(name, ctype=None, fmt=None, array=False, access="rw", set_action=""): + def modulevar(name, ctype=None, fmt=None, array=False, access="rw", accid=None): """Get the c name of a module variable and possibly register the variable with the code generator. If only name is given, the autogenerated c name of the module variable will be returned. @@ -180,9 +180,10 @@ def generate(desc, device, build_path, builddate, target = 'all'): if array != False: aval = array - accid = register_callback("generic_getter_callback", ("" if array else "&")+varname, "sizeof("+varname+")") - if "w" in access: - register_callback(None, ("" if array else "&")+varname, "sizeof("+varname+")") + if accid is None: + accid = register_callback("generic_getter_callback", ("" if array else "&")+varname, "sizeof("+varname+")") + if "w" in access: + register_callback(None, ("" if array else "&")+varname, "sizeof("+varname+")") properties[name] = { "size": struct.calcsize(fmt), @@ -231,6 +232,7 @@ def generate(desc, device, build_path, builddate, target = 'all'): loop_function=loop_function, modulevar=modulevar, module_callback=module_callback, + register_callback=register_callback, member=member, device=device) diff --git a/pylibcerebrum/pylibcerebrum.py b/pylibcerebrum/pylibcerebrum.py index a8fdf18..2dec06b 100644 --- a/pylibcerebrum/pylibcerebrum.py +++ b/pylibcerebrum/pylibcerebrum.py @@ -38,19 +38,23 @@ class Ganglion: self._config = None if ser is None: assert(config is None) - self._ser = serial.Serial(port=device, baudrate=baudrate, timeout=1) + s = serial.Serial(port=device, baudrate=baudrate, timeout=1) #Trust me, without the following two lines it *wont* *work*. Fuck serial ports. - self._ser.setXonXoff(True) - self._ser.setXonXoff(False) - self._opened_ser = self._ser + s.setXonXoff(True) + s.setXonXoff(False) + s.setDTR(True) + s.setDTR(False) + self._opened_ser = self._ser = s i=0 while True: try: self._config = self._read_config() + time.sleep(0.1) break except TimeoutException as e: print('Timeout', e) - pass + except ValueError as e: + print('That device threw some nasty ValueError\'ing JSON!', e) i += 1 if i > 20: raise serial.serialutil.SerialException('Could not connect, giving up after 20 tries') @@ -125,16 +129,16 @@ class Ganglion: def _callfunc(self, fid, argsfmt, args, retfmt): """Call a function on the device by id, directly passing argument/return format parameters.""" - cmd = b'\\#' + struct.pack(">HH", fid, struct.calcsize(argsfmt)) + struct.pack(argsfmt, *args) + cmd = b'\\#' + struct.pack("H", self._my_ser_read(2)) - #print('clen ', clen) + print('clen ', clen) #payload data cbytes = self._my_ser_read(clen) - #print('cbytes ', cbytes) + print('cbytes ', cbytes) if clen != struct.calcsize(retfmt): #print('cbytes', cbytes) #CAUTION! This error is thrown not because the user supplied a wrong value but because the device answered in an unexpected manner. -- 2.11.4.GIT