Compare commits
No commits in common. "5954e875b18449ebf3f1b361b1c105671bfb5fc7" and "6c8119424b92399540ace96dbdb4666e7fe68081" have entirely different histories.
5954e875b1
...
6c8119424b
4 changed files with 62 additions and 79 deletions
83
ssp.c
83
ssp.c
|
|
@ -12,12 +12,11 @@
|
|||
|
||||
static volatile struct ssp_job job;
|
||||
struct ssp_match ssp_match;
|
||||
const struct ssp_batch *ssp_batch;
|
||||
static const struct ssp_batch *ssp_batch;
|
||||
static int ssp_batch_repeats;
|
||||
unsigned int ssp_bits;
|
||||
volatile unsigned int ssp_lastword;
|
||||
unsigned int ssp_ssel_mask = SSP_SSEL_MASK0 | SSP_SSEL_MASK1;
|
||||
static const struct timer_wait *ssp_batch_wait;
|
||||
|
||||
unsigned short *ssp_buffer;
|
||||
volatile unsigned int ssp_frame_count;
|
||||
|
|
@ -83,44 +82,49 @@ static void ssp_isr(void)
|
|||
}
|
||||
j->read_count = rc;
|
||||
|
||||
sr |= SSPSR; // race between SSPSR_BSY, SSPSR_RNE?
|
||||
if (!j->cmd_count && !j->idle_count) {
|
||||
if (!rc && !(sr & (SSPSR_BSY|SSPSR_RNE))) {
|
||||
SSPIMSC = 0;
|
||||
if (ssp_batch)
|
||||
ssp_run_batch();
|
||||
}
|
||||
else
|
||||
SSPIMSC = SSP_INT_RX;
|
||||
goto out;
|
||||
if (!nread && !rc && !(sr&SSPSR_BSY) && !j->cmd_count && !j->idle_count) {
|
||||
// there is nothing left to do
|
||||
SSPIMSC = 0;
|
||||
VICVectAddr = 0;
|
||||
return;
|
||||
}
|
||||
else if (!(sr & (SSPSR_BSY|SSPSR_RNE)))
|
||||
nread = 8;
|
||||
|
||||
// Send at most as many new frames as where received.
|
||||
// This prevents Rx FIFO overflow.
|
||||
// Except, when the Tx is not busy at all, then we can fill it up.
|
||||
|
||||
// There may be a race, when the SSPSR_BSY goes low before the SSPSR_RNE
|
||||
// goes high for the last frame sent. Does it?
|
||||
// Reread SSPSR and check!
|
||||
|
||||
if (!(sr&SSPSR_BSY)) {
|
||||
sr = SSPSR;
|
||||
if (!(sr & (SSPSR_BSY|SSPSR_RNE)))
|
||||
nread = 8;
|
||||
}
|
||||
if (rc && nread > rc)
|
||||
nread = rc;
|
||||
unsigned int ic = j->idle_count;
|
||||
while (nread && (sr&SSPSR_TNF)) {
|
||||
if (j->cmd_count) {
|
||||
j->cmd_count--;
|
||||
SSPDR = *j->command++;
|
||||
}
|
||||
else if (ic) {
|
||||
ic--;
|
||||
SSPDR = ssp_match.idle;
|
||||
}
|
||||
else {
|
||||
SSPIMSC = SSP_INT_RX;
|
||||
goto outic;
|
||||
if (!(rc || ic)) {
|
||||
// nothing to send, disable TX irq
|
||||
SSPIMSC = SSP_INT_RX;
|
||||
break;
|
||||
}
|
||||
if (ic)
|
||||
ic--;
|
||||
SSPDR = ssp_match.idle;
|
||||
}
|
||||
nread--;
|
||||
sr = SSPSR;
|
||||
}
|
||||
outic:
|
||||
j->idle_count = ic;
|
||||
out:
|
||||
|
||||
VICVectAddr = 0;
|
||||
}
|
||||
|
||||
|
|
@ -221,11 +225,7 @@ int ssp_busy(void)
|
|||
return c;
|
||||
// Hardware is busy
|
||||
if (SSPSR&(SSPSR_RNE|SSPSR_BSY))
|
||||
return -1;
|
||||
if (SSPIMSC & (SSP_INT_RX | SSP_INT_TX))
|
||||
return -2;
|
||||
if (!ssp_run_batch())
|
||||
return -3;
|
||||
return 1;
|
||||
done:
|
||||
ssp_reset();
|
||||
return 0;
|
||||
|
|
@ -259,42 +259,34 @@ struct ssp_config ssp_conf_bate[] = {
|
|||
},
|
||||
};
|
||||
|
||||
// called first by `ssp_submit_batch()`
|
||||
// called next by `ssp_isr()` when a job is done
|
||||
// called by `timer_wait.callback()` when the delay, event happend
|
||||
int ssp_wait_miso(const struct ssp_wait *wait)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssp_run_batch()
|
||||
int ssp_run_batch(void)
|
||||
{
|
||||
const struct ssp_batch *batch = ssp_batch;
|
||||
if (!batch || !batch->job)
|
||||
return -1;
|
||||
|
||||
const struct timer_wait *wait = batch->wait;
|
||||
if (wait) {
|
||||
if (ssp_batch_wait != wait) {
|
||||
// we need to wait for something
|
||||
ssp_batch_wait = wait;
|
||||
timer_wait_init(wait, (void*)batch);
|
||||
return 0;
|
||||
}
|
||||
// we did the waiting … continue with the batch
|
||||
ssp_batch_wait = 0;
|
||||
if (batch->wait) {
|
||||
int c = ssp_wait_miso(batch->wait);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
|
||||
if (ssp_batch_repeats++ >= batch->count) {
|
||||
// we did all repeats … advance to the next job
|
||||
ssp_batch_repeats = 0;
|
||||
ssp_batch++;
|
||||
}
|
||||
|
||||
const struct ssp_config *ssel = batch->ssel;
|
||||
if (ssel) {
|
||||
if (ssel)
|
||||
if (ssel->mode)
|
||||
ssp_init(ssel);
|
||||
else if (ssel->ssel)
|
||||
ssp_config.ssel = ssel->ssel;
|
||||
ssp_deassert_ssel();
|
||||
}
|
||||
const struct ssp_match *match = batch->match;
|
||||
if (match)
|
||||
ssp_match = *match;
|
||||
|
|
@ -310,6 +302,5 @@ int ssp_submit_batch(const struct ssp_batch *batch, int timeout)
|
|||
return c;
|
||||
ssp_batch_repeats = 0;
|
||||
ssp_batch = batch;
|
||||
ssp_batch_wait = 0;
|
||||
return ssp_run_batch();
|
||||
}
|
||||
|
|
|
|||
16
ssp.h
16
ssp.h
|
|
@ -3,7 +3,6 @@
|
|||
#define _ssp_h_
|
||||
|
||||
#include "gpio.h"
|
||||
#include "timer.h"
|
||||
|
||||
void ssp_reset(void);
|
||||
|
||||
|
|
@ -76,14 +75,13 @@ extern struct ssp_match {
|
|||
unsigned int size;
|
||||
} ssp_match;
|
||||
|
||||
extern const
|
||||
struct ssp_batch {
|
||||
int count;
|
||||
const struct ssp_job *job;
|
||||
const struct ssp_match *match;
|
||||
const struct ssp_config *ssel;
|
||||
const struct timer_wait *wait;
|
||||
} *ssp_batch;
|
||||
struct ssp_job *job;
|
||||
struct ssp_match *match;
|
||||
struct ssp_config *ssel;
|
||||
struct ssp_wait *wait;
|
||||
};
|
||||
|
||||
// search for a pattern before recording frames
|
||||
static inline
|
||||
|
|
@ -104,8 +102,4 @@ void ssp_set_read(unsigned int count, unsigned int size)
|
|||
ssp_match.size = size;
|
||||
}
|
||||
|
||||
int ssp_submit_job(const struct ssp_job *jj);
|
||||
int ssp_submit_batch(const struct ssp_batch *batch, int timeout);
|
||||
int ssp_run_batch();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
32
timer.c
32
timer.c
|
|
@ -14,7 +14,7 @@ void tick_timer(volatile struct timer_tick *tick, unsigned int ir)
|
|||
if (n != 0xffff)
|
||||
tick->n = n+1;
|
||||
if (tick->callback)
|
||||
tick->callback(tick);
|
||||
tick->callback(ir, n);
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt ("IRQ")))
|
||||
|
|
@ -79,28 +79,28 @@ static void timer_wait_abort(void) {
|
|||
waiting = 0;
|
||||
}
|
||||
|
||||
static void wait_callback(const volatile struct timer_tick *tick)
|
||||
static void wait_callback(unsigned int ir, unsigned int n)
|
||||
{
|
||||
const struct timer_wait *w = waiting;
|
||||
if (!w)
|
||||
return;
|
||||
if (timer_wait_pin_status(w))
|
||||
goto hit;
|
||||
if (w->mclk && tick->ir & 0x100 && tick->n >= w->mclk)
|
||||
if (w->mclk && n >= w->mclk)
|
||||
goto hit;
|
||||
if (w->pclk && tick->ir & 0x200 && tick->ir & 1)
|
||||
if (w->pclk && ir & 1)
|
||||
goto hit;
|
||||
return;
|
||||
hit:
|
||||
timer_wait_abort();
|
||||
if (w->callback)
|
||||
w->callback(tick);
|
||||
w->callback();
|
||||
}
|
||||
|
||||
int timer_wait_init(const struct timer_wait *wait, void *data)
|
||||
int timer_wait_init(const struct timer_wait *wait)
|
||||
{
|
||||
timer_wait_abort();
|
||||
if (!wait || timer_wait_pin_status(wait))
|
||||
if (!wait)
|
||||
return 0;
|
||||
timer0_tick = (struct timer_tick){.callback=0};
|
||||
timer1_tick = (struct timer_tick){.callback=0};
|
||||
|
|
@ -148,14 +148,11 @@ int timer_wait_init(const struct timer_wait *wait, void *data)
|
|||
}
|
||||
|
||||
waiting = wait;
|
||||
if (wait->ccr0 || wait->mclk) {
|
||||
timer0_tick.data = data;
|
||||
timer0_tick.callback = wait_callback;
|
||||
}
|
||||
if (wait->ccr1 || wait->pclk) {
|
||||
timer1_tick.data = data;
|
||||
timer1_tick.callback = wait_callback;
|
||||
}
|
||||
if (wait->ccr0 || wait->mclk)
|
||||
timer0_tick.callback = &wait_callback;
|
||||
if (wait->ccr1 || wait->pclk)
|
||||
timer1_tick.callback = &wait_callback;
|
||||
wait_callback(0,0);
|
||||
enable_irq(iflg);
|
||||
return !!waiting;
|
||||
}
|
||||
|
|
@ -164,3 +161,8 @@ int timer_wait_status(const struct timer_wait *wait)
|
|||
{
|
||||
return waiting && (!wait || wait==waiting);
|
||||
}
|
||||
|
||||
int timer_wait_mclk_status(const struct timer_wait *w)
|
||||
{
|
||||
return timer0_tick.n;
|
||||
}
|
||||
|
|
|
|||
10
timer.h
10
timer.h
|
|
@ -6,14 +6,10 @@
|
|||
void timer0_init();
|
||||
void timer1_init();
|
||||
|
||||
struct timer_tick;
|
||||
typedef void (*timer_callback_t)(const volatile struct timer_tick *tick);
|
||||
|
||||
extern volatile struct timer_tick {
|
||||
unsigned int ir;
|
||||
unsigned int n;
|
||||
timer_callback_t callback;
|
||||
void *data;
|
||||
void (*callback)(unsigned, unsigned);
|
||||
} timer0_tick, timer1_tick;
|
||||
|
||||
struct timer_wait {
|
||||
|
|
@ -23,10 +19,10 @@ struct timer_wait {
|
|||
unsigned short ccr1;
|
||||
unsigned int pinmask;
|
||||
unsigned int pinvalue;
|
||||
timer_callback_t callback;
|
||||
void (*callback)(void);
|
||||
};
|
||||
|
||||
int timer_wait_init(const struct timer_wait *wait, void *data);
|
||||
int timer_wait_init(const struct timer_wait *wait);
|
||||
int timer_wait_status(const struct timer_wait *wait);
|
||||
|
||||
static inline
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue