/* * cc110x.c * * Created on: Jul 20, 2012 * Author: tkl */ #include #include #include "board.h" #include "stack.h" #include "queue.h" #include "thread.h" #include "schedule.h" #include "irq.h" #include "sys_tick.h" #include "cc110x.h" static volatile bool tx_condition; extern volatile struct thread_context *current_thread; static void it_cb(const struct cc110x *cc110x, enum cc110x_it_type it_type); int cc110x_open(const struct cc110x *cc110x) { if(NULL == cc110x) return (-1); tx_condition = false; cc110x->fp->init(cc110x); cc110x->fp->set_it_callback(cc110x->arch_dep_device, it_cb, cc110x); cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_PWD); cc110x_write_pa_table(cc110x); return (0); } int cc110x_close(const struct cc110x *cc110x) { cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_PWD); blocking_read_wakeup(cc110x); return 0; } void cc110x_set_radio_mode(const struct cc110x *cc110x, enum cc110x_radio_mode mode) { if(NULL == cc110x) { return; } *(cc110x->radio_mode) = mode; enum cc110x_strobe_cmd cmd = STROBE_SIDLE; switch(mode) { case CC110X_RADIO_MODE_NONE: return; case CC110X_RADIO_MODE_IDLE: cmd = STROBE_SIDLE; break; case CC110X_RADIO_MODE_RX: cmd = STROBE_SRX; break; case CC110X_RADIO_MODE_TX: cmd = STROBE_STX; break; case CC110X_RADIO_MODE_PWD: cmd = STROBE_SPWD; break; } cc110x->fp->strobe(cc110x->arch_dep_device, cmd); } enum cc110x_radio_mode cc110x_get_radio_mode(const struct cc110x *cc110x) { if(NULL == cc110x) return (CC110X_RADIO_MODE_NONE); return (*(cc110x->radio_mode)); } void cc110x_write_pa_table(const struct cc110x *cc110x) { if(NULL == cc110x) return; cc110x->fp->write_pa_table(cc110x->arch_dep_device); } void cc110x_strobe(const struct cc110x *cc110x, enum cc110x_strobe_cmd cmd) { if(NULL == cc110x) return; cc110x->fp->strobe(cc110x->arch_dep_device, cmd); } int cc110x_write(const struct cc110x *cc110x, const char *buffer, int size) { enum cc110x_radio_mode mode; int ret; if((NULL == cc110x) || (NULL == buffer)) return (-1); mode = cc110x_get_radio_mode(cc110x); cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE); cc110x_strobe(cc110x, STROBE_SFTX); ret = cc110x->fp->write(cc110x->arch_dep_device, buffer, size); tx_condition = true; cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_TX); while(tx_condition); cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE); cc110x_strobe(cc110x, STROBE_SFTX); cc110x_set_radio_mode(cc110x, mode); return (ret); } int cc110x_read(const struct cc110x *cc110x, char *buffer, int size) { int ret; unsigned int irq; if((NULL == cc110x) || (NULL == buffer)) return (-1); if(0 == cc110x_get_rx_count(cc110x)) { irq = disable_irq(); current_thread->status = THREAD_STATUS_BLOCKING; current_thread->wakeup_blocking_source = (void*) cc110x; restore_irq(irq); schedule(); } enum cc110x_radio_mode mode = cc110x_get_radio_mode(cc110x); cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE); ret = cc110x_get_rx_count(cc110x); ret = cc110x->fp->read(cc110x->arch_dep_device, buffer, ret); cc110x_strobe(cc110x, STROBE_SFRX); cc110x_set_radio_mode(cc110x, mode); return (ret); } int cc110x_get_rx_count(const struct cc110x *cc110x) { if(NULL == cc110x) return (-1); return (cc110x->fp->get_rx_count(cc110x->arch_dep_device)); } static void it_cb(const struct cc110x *cc110x, enum cc110x_it_type it_type) { if(NULL == cc110x) return; switch(it_type) { case IT_TYPE_NONE: break; case IT_TYPE_RX_COMPLETE: blocking_read_wakeup(cc110x); break; case IT_TYPE_TX_COMPLETE: tx_condition = false; break; } }