Compare commits

..

No commits in common. "5954e875b18449ebf3f1b361b1c105671bfb5fc7" and "6c8119424b92399540ace96dbdb4666e7fe68081" have entirely different histories.

4 changed files with 62 additions and 79 deletions

83
ssp.c
View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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