mirror of
https://github.com/elua/elua.git
synced 2025-01-08 20:56:17 +08:00
ADC bugfixes, and change to sample and burst being non-blocking. Samples are
acquired with getsamples.
This commit is contained in:
parent
42ff856578
commit
b3f6110150
10
inc/buf.h
10
inc/buf.h
@ -48,9 +48,17 @@ enum
|
||||
BUF_SIZE_32768
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BUF_DSIZE_U8 = 0,
|
||||
BUF_DSIZE_U16,
|
||||
BUF_DSIZE_U32
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Buffer API
|
||||
int buf_set(unsigned resid, unsigned resnum, u8 logsize, size_t dsize);
|
||||
int buf_set(unsigned resid, unsigned resnum, u8 logsize, u8 logdsize);
|
||||
int buf_is_enabled( unsigned resid, unsigned resnum );
|
||||
unsigned buf_get_size( unsigned resid, unsigned resnum );
|
||||
unsigned buf_get_count( unsigned resid, unsigned resnum );
|
||||
|
@ -28,7 +28,8 @@ u16 adc_get_processed_sample( unsigned id );
|
||||
void adc_init_state( unsigned id );
|
||||
int adc_update_smoothing( unsigned id, u8 loglen );
|
||||
void adc_flush_smoothing( unsigned id );
|
||||
u8 adc_samples_requested( unsigned id );
|
||||
u8 adc_samples_ready( unsigned id );
|
||||
u16 adc_samples_requested( unsigned id );
|
||||
u16 adc_samples_available( unsigned id );
|
||||
void adc_wait_pending( unsigned id );
|
||||
|
||||
#endif
|
@ -1,40 +1,52 @@
|
||||
require("LM3S")
|
||||
|
||||
disp.init(1000000)
|
||||
disp.clear()
|
||||
adcchannels = {0, 1, 2, 3}
|
||||
adcsmoothing = {4, 16, 32, 64}
|
||||
|
||||
adc.setsmoothing(0,4)
|
||||
adc.setsmoothing(1,16)
|
||||
adc.setsmoothing(2,32)
|
||||
adc.setsmoothing(3,64)
|
||||
for i, v in ipairs(adcchannels) do
|
||||
adc.setmode(v,0)
|
||||
adc.setsmoothing(v,adcsmoothing[i])
|
||||
end
|
||||
|
||||
disp.stringdraw( "ADC Scope", 10, 10, 11 )
|
||||
term.clrscr()
|
||||
|
||||
adcvals = {}
|
||||
ctr = 0
|
||||
term.gotoxy(1,1)
|
||||
term.putstr("ADC Status:")
|
||||
term.gotoxy(1,3)
|
||||
term.putstr(" CH SLEN RES")
|
||||
term.gotoxy(1,#adcchannels+6)
|
||||
term.putstr("Press ESC to exit.")
|
||||
|
||||
while ( true ) do
|
||||
local adcvals = {}
|
||||
local ctr = 0
|
||||
|
||||
while true do
|
||||
local key, stime, etime, dtime
|
||||
local sample = adc.sample
|
||||
local getsamples = adc.getsamples
|
||||
ctr = ctr + 1
|
||||
|
||||
stime = tmr.start(0)
|
||||
adcvals[0] = adc.sample(0)
|
||||
adcvals[1] = adc.sample(1)
|
||||
adcvals[2] = adc.sample(2)
|
||||
adcvals[3] = adc.sample(3)
|
||||
for i, v in ipairs(adcchannels) do
|
||||
sample(v)
|
||||
adcvals[i] = getsamples(v,1)
|
||||
end
|
||||
etime = tmr.read(0)
|
||||
dtime = tmr.diff(0,etime,stime)
|
||||
|
||||
if ( ctr == 100 ) then
|
||||
ctr = 0
|
||||
outstring = string.format("ADC0 (4): %04d",adcvals[0])
|
||||
disp.stringdraw( outstring, 10, 10, 11 )
|
||||
outstring = string.format("ADC1 (16): %04d",adcvals[1])
|
||||
disp.stringdraw( outstring, 10, 20, 11 )
|
||||
outstring = string.format("ADC2 (32): %04d",adcvals[2])
|
||||
disp.stringdraw( outstring, 10, 30, 11 )
|
||||
outstring = string.format("ADC3 (64): %04d",adcvals[3])
|
||||
disp.stringdraw( outstring, 10, 40, 11 )
|
||||
outstring = string.format("Tcyc: %06d (us)",dtime)
|
||||
disp.stringdraw( outstring, 10, 50, 11 )
|
||||
term.gotoxy(1,4)
|
||||
for i, v in ipairs(adcchannels) do
|
||||
term.putstr(string.format("ADC%d (%03d): %04d\n",v,adcsmoothing[i],adcvals[i]))
|
||||
term.gotoxy(1,i+4)
|
||||
end
|
||||
term.putstr(string.format("Tcyc: %06d (us)\n",dtime))
|
||||
|
||||
key = term.getch( term.NOWAIT )
|
||||
if key == term.KC_ESC then break end
|
||||
end
|
||||
end
|
||||
if key == term.KC_ESC then break end
|
||||
end
|
||||
|
||||
term.clrscr()
|
||||
term.gotoxy( 1 , 1 )
|
14
src/buf.c
14
src/buf.c
@ -52,20 +52,15 @@ static const buf_desc* buf_desc_array[ BUF_ID_TOTAL ] =
|
||||
// resid - resource ID (BUF_ID_UART ...)
|
||||
// resnum - resource number (0, 1, 2...)
|
||||
// bufsize - new size of the buffer (one of the BUF_SIZE_xxx constants from
|
||||
// dsize - number of bytes held by each element (must be a power of 2)
|
||||
// buf.h, or BUF_SIZE_NONE to disable buffering
|
||||
// logdsize - log2(bytes) size of elements (from BUF_DSIZE_xxx constants)
|
||||
// Returns 1 on success, 0 on failure
|
||||
int buf_set( unsigned resid, unsigned resnum, u8 logsize, size_t dsize )
|
||||
int buf_set( unsigned resid, unsigned resnum, u8 logsize, u8 logdsize )
|
||||
{
|
||||
BUF_GETPTR( resid, resnum );
|
||||
u8 prevlogsize = pbuf->logsize;
|
||||
|
||||
// Make sure dsize is a power of 2
|
||||
if ( dsize & ( dsize - 1 ) )
|
||||
return PLATFORM_ERR;
|
||||
|
||||
pbuf->logdsize = intlog2( dsize );
|
||||
pbuf->logsize = logsize + ( pbuf->logdsize );
|
||||
pbuf->logdsize = logdsize;
|
||||
pbuf->logsize = logsize + logdsize;
|
||||
|
||||
if( ( pbuf->buf = ( t_buf_data* )realloc( pbuf->buf, BUF_BYTESIZE( pbuf ) ) ) == NULL )
|
||||
{
|
||||
@ -90,7 +85,6 @@ void buf_flush( unsigned resid, unsigned resnum )
|
||||
// resid - resource ID (BUF_ID_UART ...)
|
||||
// resnum - resource number (0, 1, 2...)
|
||||
// data - pointer for where data will come from
|
||||
// dsize - length of data to get
|
||||
// Returns PLATFORM_OK on success, PLATFORM_ERR on failure
|
||||
// [TODO] maybe add a buffer overflow flag
|
||||
int buf_write( unsigned resid, unsigned resnum, t_buf_data *data )
|
||||
|
@ -38,7 +38,7 @@ void adc_init_state( unsigned id )
|
||||
s->smoothsum = 0;
|
||||
|
||||
// Buffer initialization
|
||||
buf_set( BUF_ID_ADC, id, ADC_BUF_SIZE, sizeof( u16 ) );
|
||||
buf_set( BUF_ID_ADC, id, ADC_BUF_SIZE, BUF_DSIZE_U16 );
|
||||
}
|
||||
|
||||
int adc_update_smoothing( unsigned id, u8 loglen )
|
||||
@ -135,15 +135,26 @@ void adc_flush_smoothing( unsigned id )
|
||||
}
|
||||
}
|
||||
|
||||
u8 adc_samples_requested( unsigned id )
|
||||
u16 adc_samples_requested( unsigned id )
|
||||
{
|
||||
elua_adc_state *s = adc_get_ch_state( id );
|
||||
return s->reqsamples;
|
||||
}
|
||||
|
||||
u8 adc_samples_ready( unsigned id )
|
||||
u16 adc_samples_available( unsigned id )
|
||||
{
|
||||
return ( u8 ) buf_get_count( BUF_ID_ADC, id );
|
||||
return ( u16 ) buf_get_count( BUF_ID_ADC, id );
|
||||
}
|
||||
|
||||
void adc_wait_pending( unsigned id )
|
||||
{
|
||||
elua_adc_state *s = adc_get_ch_state( id );
|
||||
|
||||
if ( s->nonblocking == 0 && s->op_pending == 1 )
|
||||
{
|
||||
while ( s->op_pending == 1 ) { ; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -15,15 +15,15 @@
|
||||
static int adc_sample( lua_State* L )
|
||||
{
|
||||
unsigned id;
|
||||
int res;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
platform_adc_sample( id );
|
||||
if ( adc_samples_ready( id ) >= 1 )
|
||||
{
|
||||
lua_pushinteger( L, adc_get_processed_sample( id ) );
|
||||
return 1;
|
||||
}
|
||||
res = platform_adc_sample( id );
|
||||
|
||||
if ( res != PLATFORM_OK )
|
||||
return luaL_error( L, "burst failed" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -40,21 +40,14 @@ static int adc_maxval( lua_State* L )
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: isdone( id )
|
||||
static int adc_data_ready( lua_State* L )
|
||||
// Lua: samplesready( id )
|
||||
static int adc_samples_ready( lua_State* L )
|
||||
{
|
||||
unsigned id;
|
||||
u8 asamp, rsamp;
|
||||
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
asamp = adc_samples_ready( id );
|
||||
rsamp = adc_samples_requested( id );
|
||||
if ( rsamp > 0 && asamp >= rsamp )
|
||||
lua_pushinteger( L, 1 );
|
||||
else
|
||||
lua_pushinteger( L, 0 );
|
||||
|
||||
lua_pushinteger( L, adc_samples_available( id ) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -122,7 +115,7 @@ static int adc_flush( lua_State* L )
|
||||
// Lua: burst( id, count, timer_id, frequency )
|
||||
static int adc_burst( lua_State* L )
|
||||
{
|
||||
unsigned id, timer_id, i, count;
|
||||
unsigned id, timer_id, count;
|
||||
u32 frequency;
|
||||
int res;
|
||||
|
||||
@ -132,52 +125,59 @@ static int adc_burst( lua_State* L )
|
||||
timer_id = luaL_checkinteger( L, 3 );
|
||||
MOD_CHECK_ID( timer, timer_id );
|
||||
frequency = luaL_checkinteger( L, 4 );
|
||||
|
||||
if ( ( count == 0 ) || count & ( count - 1 ) )
|
||||
return luaL_error( L, "count must be power of 2 and > 0" );
|
||||
|
||||
res = platform_adc_burst( id, intlog2( count ), timer_id, frequency );
|
||||
if ( res != PLATFORM_OK )
|
||||
return luaL_error( L, "burst failed" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( count == 0 )
|
||||
return 0;
|
||||
|
||||
// Lua: getsamples( id, count )
|
||||
static int adc_get_samples( lua_State* L )
|
||||
{
|
||||
unsigned id, i, count;
|
||||
int total = lua_gettop( L );
|
||||
u16 nsamps;
|
||||
|
||||
if ( count & ( count - 1 ) )
|
||||
return luaL_error( L, "count must be power of 2" );
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
nsamps = adc_samples_available( id );
|
||||
|
||||
// If we already have enough data, return it and start next burst
|
||||
if( adc_samples_ready( id ) >= count )
|
||||
if ( total == 2 )
|
||||
count = luaL_checkinteger( L, 2 );
|
||||
else
|
||||
count = nsamps;
|
||||
|
||||
if ( count == 0 ) { count = nsamps; } // count = 0 means grab all samples
|
||||
|
||||
adc_wait_pending( id );
|
||||
|
||||
if ( nsamps > 0 && nsamps >= count )
|
||||
{
|
||||
// Push data back to Lua
|
||||
lua_createtable( L, count, 0 );
|
||||
for( i = 0; i < count; i ++ )
|
||||
if ( nsamps == 1 || count == 1 )
|
||||
{
|
||||
lua_pushinteger( L, adc_get_processed_sample( id ) );
|
||||
lua_rawseti( L, -2, i+1 );
|
||||
}
|
||||
|
||||
res = platform_adc_burst( id, intlog2( count ), timer_id, frequency );
|
||||
if ( res != PLATFORM_OK )
|
||||
return luaL_error( L, "burst failed" );
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
else // If no data is available, kick off burst, return data if we have some afterwards
|
||||
{
|
||||
res = platform_adc_burst( id, intlog2( count ), timer_id, frequency );
|
||||
if ( res != PLATFORM_OK )
|
||||
return luaL_error( L, "burst failed" );
|
||||
|
||||
if( adc_samples_ready( id ) >= count )
|
||||
else
|
||||
{
|
||||
// Push data back to Lua
|
||||
lua_createtable( L, count, 0 );
|
||||
for( i = 0; i < count; i ++ )
|
||||
{
|
||||
lua_pushinteger( L, adc_get_processed_sample( id ) );
|
||||
lua_rawseti( L, -2, i+1 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Module function map
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
@ -185,12 +185,13 @@ const LUA_REG_TYPE adc_map[] =
|
||||
{
|
||||
{ LSTRKEY( "sample" ), LFUNCVAL( adc_sample ) },
|
||||
{ LSTRKEY( "maxval" ), LFUNCVAL( adc_maxval ) },
|
||||
{ LSTRKEY( "dataready" ), LFUNCVAL( adc_data_ready ) },
|
||||
{ LSTRKEY( "samplesready" ), LFUNCVAL( adc_samples_ready ) },
|
||||
{ LSTRKEY( "setmode" ), LFUNCVAL( adc_set_mode ) },
|
||||
{ LSTRKEY( "setsmoothing" ), LFUNCVAL( adc_set_smoothing ) },
|
||||
{ LSTRKEY( "getsmoothing" ), LFUNCVAL( adc_get_smoothing ) },
|
||||
{ LSTRKEY( "burst" ), LFUNCVAL( adc_burst ) },
|
||||
{ LSTRKEY( "flush" ), LFUNCVAL( adc_flush ) },
|
||||
{ LSTRKEY( "getsamples" ), LFUNCVAL( adc_get_samples ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
|
@ -83,7 +83,7 @@ int platform_init()
|
||||
USART_SetReceiverEnabled( pusart, 1 );
|
||||
#if defined( BUF_ENABLE_UART ) && defined( CON_BUF_SIZE )
|
||||
// Enable buffering on the console UART
|
||||
buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, sizeof ( char ) );
|
||||
buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, BUF_DSIZE_U8 );
|
||||
// Set interrupt handler and interrupt flag on UART
|
||||
unsigned uart_id = CON_UART_ID == 0 ? AT91C_ID_US0 : AT91C_ID_US1;
|
||||
AIC_DisableIT( uart_id );
|
||||
|
@ -118,7 +118,7 @@ int platform_init()
|
||||
platform_uart_setup( CON_UART_ID, CON_UART_SPEED, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 );
|
||||
#if defined( BUF_ENABLE_UART ) && defined( CON_BUF_SIZE )
|
||||
// Enable buffering on the console UART
|
||||
buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, sizeof ( char ) );
|
||||
buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, BUF_DSIZE_U8 );
|
||||
// Set interrupt handler and interrupt flag on UART
|
||||
INTC_register_interrupt( &uart_rx_handler, CON_UART_IRQ, AVR32_INTC_INT0 );
|
||||
volatile avr32_usart_t *pusart = ( volatile avr32_usart_t* )uart_base_addr[ CON_UART_ID ];
|
||||
|
@ -277,7 +277,7 @@ static void uarts_init()
|
||||
|
||||
#if defined( BUF_ENABLE_UART ) && defined( CON_BUF_SIZE )
|
||||
// Enable buffering on the console UART
|
||||
buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, sizeof ( t_buf_data ) );
|
||||
buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, BUF_DSIZE_U8 );
|
||||
// Set interrupt handler and interrupt flag on UART
|
||||
|
||||
IntEnable(INT_UART0);
|
||||
@ -533,9 +533,7 @@ void ADCIntHandler( void )
|
||||
{
|
||||
unsigned long rawSample;
|
||||
unsigned id;
|
||||
|
||||
platform_cpu_disable_interrupts();
|
||||
|
||||
|
||||
// Check each sequence for a pending sample
|
||||
for( id = 0; id < NUM_ADC; id ++ )
|
||||
{
|
||||
@ -559,10 +557,13 @@ void ADCIntHandler( void )
|
||||
platform_adc_stop( id );
|
||||
}
|
||||
else if ( s->burst == 0 )
|
||||
{
|
||||
// Need to manually fire off sample request in single sample mode
|
||||
ADCProcessorTrigger( ADC_BASE, id );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
platform_cpu_enable_interrupts();
|
||||
}
|
||||
|
||||
static void adcs_init()
|
||||
@ -599,19 +600,22 @@ int platform_adc_sample( unsigned id )
|
||||
elua_adc_state *s = adc_get_ch_state( id );
|
||||
int res;
|
||||
|
||||
res = buf_set( BUF_ID_ADC, id, ADC_BUF_SIZE , sizeof( u16 ) );
|
||||
if ( res != PLATFORM_OK )
|
||||
return res;
|
||||
|
||||
// Need more general buf resizing... for now flush each time
|
||||
buf_flush( BUF_ID_ADC, id );
|
||||
|
||||
s->burst = 0;
|
||||
s->op_pending = 1;
|
||||
s->reqsamples = 1;
|
||||
|
||||
// Make sure sequencer is disabled before making changes
|
||||
ADCSequenceDisable( ADC_BASE, id );
|
||||
|
||||
// If switching from burst, resize & flush buffer
|
||||
if ( s->burst == 1 )
|
||||
{
|
||||
buf_flush( BUF_ID_ADC, id );
|
||||
res = buf_set( BUF_ID_ADC, id, ADC_BUF_SIZE , BUF_DSIZE_U16 );
|
||||
if ( res != PLATFORM_OK )
|
||||
return res;
|
||||
s->burst = 0;
|
||||
s->reqsamples = 0;
|
||||
}
|
||||
|
||||
s->op_pending = 1;
|
||||
s->reqsamples += 1;
|
||||
|
||||
// Conversion will run back-to-back until required samples are acquired
|
||||
ADCSequenceConfigure( ADC_BASE, id, ADC_TRIGGER_PROCESSOR, id ) ;
|
||||
@ -620,11 +624,6 @@ int platform_adc_sample( unsigned id )
|
||||
ADCSequenceEnable( ADC_BASE, id );
|
||||
ADCProcessorTrigger( ADC_BASE, id );
|
||||
|
||||
// If in blocking mode and sample is pending, wait for ready flag
|
||||
if ( s->nonblocking == 0 && s->op_pending == 1 )
|
||||
{
|
||||
while ( s->op_pending == 1 ) { ; }
|
||||
}
|
||||
return PLATFORM_OK;
|
||||
}
|
||||
|
||||
@ -633,21 +632,25 @@ int platform_adc_burst( unsigned id, u8 logcount, unsigned timer_id, u32 frequen
|
||||
elua_adc_state *s = adc_get_ch_state( id );
|
||||
int res;
|
||||
|
||||
res = buf_set( BUF_ID_ADC, id, logcount , sizeof( u16 ) );
|
||||
if ( res != PLATFORM_OK )
|
||||
return res;
|
||||
// Make sure sequencer is disabled before making changes
|
||||
ADCSequenceDisable( ADC_BASE, id );
|
||||
|
||||
// If switching from non-burst, resize & flush buffer
|
||||
if (s->burst == 0 || ( (u16) 1 << logcount ) != buf_get_count( BUF_ID_ADC, id ) )
|
||||
{
|
||||
res = buf_set( BUF_ID_ADC, id, logcount, BUF_DSIZE_U16 );
|
||||
if ( res != PLATFORM_OK )
|
||||
return res;
|
||||
// Need more general buf resizing... for now flush each time
|
||||
buf_flush( BUF_ID_ADC, id );
|
||||
s->burst = 1;
|
||||
s->reqsamples = 0;
|
||||
}
|
||||
|
||||
// Need more general buf resizing... for now flush each time
|
||||
buf_flush( BUF_ID_ADC, id );
|
||||
|
||||
s->burst = 1;
|
||||
s->timer_id = timer_id;
|
||||
s->op_pending = 1;
|
||||
s->reqsamples = (u16) 1 << logcount;
|
||||
|
||||
// Make sure sequencer is disabled before making changes
|
||||
ADCSequenceDisable( ADC_BASE, id );
|
||||
|
||||
// Set sequence id to be triggered repeatedly, with priority id
|
||||
ADCSequenceConfigure( ADC_BASE, id, ADC_TRIGGER_TIMER, id );
|
||||
|
||||
@ -660,11 +663,6 @@ int platform_adc_burst( unsigned id, u8 logcount, unsigned timer_id, u32 frequen
|
||||
TimerControlTrigger(timer_base[timer_id], TIMER_A, true);
|
||||
TimerEnable(timer_base[timer_id], TIMER_A);
|
||||
|
||||
// If in blocking mode and sampling task is pending, wait until buffer fills
|
||||
if ( s->nonblocking == 0 && s->op_pending == 1 )
|
||||
{
|
||||
while ( s->op_pending == 1 ) { ; }
|
||||
}
|
||||
return PLATFORM_OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user