engine_control/source/firmware/kernel/driver/cc110x.c

147 lines
3.6 KiB
C
Raw Normal View History

2016-07-23 05:59:54 +00:00
/*
* cc110x.c
*
* Created on: Jul 20, 2012
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#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;
if((NULL == cc110x) || (NULL == buffer))
return (-1);
if(0 == cc110x_get_rx_count(cc110x)) {
2016-07-23 09:27:35 +00:00
unsigned int irq = disable_irq();
2016-07-23 05:59:54 +00:00
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;
}
}