1
0
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:
James Snyder 2009-02-16 23:01:32 +00:00
parent 42ff856578
commit b3f6110150
9 changed files with 152 additions and 127 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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