Just wanted to share this PIC24 implementation of a circular buffer, for collecting the last n readings from a set of sensors. (It iterates in temporal order, from oldest to latest entry, so that more-recent data will overplot earlier data.) This is my first Forth data structure, so I would welcome tips or comments from the experts!
\ circbuf.fs\ Generic circular buffer\ https://en.wikipedia.org/wiki/Circular_buffer\\ David C. Norris 2024-07-18-circbufmarker-circbufdecimalram\ "If one or more parameters are to be compiled, or if space for\ variable data is to be allocated, it is convenient to use a\ previously defined defining word to handle that."\ -- Conklin & Rather p.172:all0t( u -- )hereswapdupalloterase;\ Allocate w-word records in a length-n array prefixed by w, n, and index i.:records:( "name" +w +n -- )ramcreate2dup*rot,swap,-1,cellsall0t;:circbuf:( "name" +w +n -- )records:does>( -- w &i n )@+swap@+;:@-( a-addr -- a-addr-2 x )dup2-swap@;:(+cb)( &i -- &[i+1]%n )dup@-1+( &i &n i+1 )swap@modover!;:(r0-)( w &i' -- w &r0-2 )2dup@*cells+;\ thus 2+ @ reads first record:(+>)( w &i -- &r0-2 w )(+cb)(r0-)swap;:into( "bufname" x1..xw )'executedrop(+>)for2+tuck!nextdrop;:each( w &i << xw..x1 w )2dup(+>)tuckfor2+tuck@swaprotnextdrop;:cb.( w &i n -- )crforeachfor..""nextcrnext2drop;marker-tests37circbuf:cbuf:test1( -- )cbufswap@-1=swap7=andswap3=andabort"ERROR"."OK";test1123intocbuf456intocbufcbufcb.789intocbufcbufcb.-tests
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here's an updated version, pursuant to this advice from Mikael. It works very nicely in my application.
\ circbuf.fs\ Generic circular buffer\ https://en.wikipedia.org/wiki/Circular_buffer\\ David C. Norris 2024-08-05-circbufmarker-circbufdecimalram:all0t( u -- )hereswapdupalloterase;\ Allocate w-word records in length-n array: (w,n,&i) ~> flash, index i ~> ram.:(index,)( u i -- )ramhereflash,ram,cellsall0t;:records:( "name" +n +w -- )flashcreate2dup,,*-1(index,);:circbuf:( "name" +n +w -- )records:does>( -- w &&i n )@+swap@+;:@-( a-addr -- a-addr-2 x )dup2-swap@;( The missing counterpart to @+ ):(+>)( w &&i -- &xw-2 w )@-dup@1+rot@modover!2dup@*cells+swap;:each( w &&i << xw..x1 w )2dup(+>)tuckfor2+dup@rotrotnextdrop;:circbuf.( w &&i n -- )crforeachfor..""nextcrnext2drop;:>circbuf( x1..xw w &&i n -- )drop(+>)for2+tuck!nextdrop;marker-tests73circbuf:cbuf:>cbuf( x1 x2 x3 w &&i n -- )cbuf>circbuf;:.cbuf( -- )cbufcircbuf.;:test1( -- )cbufswap@@-1=swap7=andswap3=andabort"ERROR"."OK";test1123>cbuf456>cbufcbufcircbuf.789>cbufcbufcircbuf.:test2( x1 x2 x3 -- )cbuf>circbufcbufcircbuf.;222test2:test3( x1 x2 x3 -- )>cbuf.cbuf;333test3( The CIRCBUF: defining word can be curried ):htbuf:( "name" +n -- )4circbuf:;\ <-- ie, a CIRCBUF: with 4-word records5htbuf:humtemp:>humtemp( h1 t1 h2 t2 4 &&i n -- )humtemp>circbuf;:.humtemp( -- )humtempcircbuf.;7624757777907357>humtemp.humtemp-tests
Last edit: David C. Norris 2024-08-08
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Just wanted to share this PIC24 implementation of a circular buffer, for collecting the last n readings from a set of sensors. (It iterates in temporal order, from oldest to latest entry, so that more-recent data will overplot earlier data.) This is my first Forth data structure, so I would welcome tips or comments from the experts!
Here's an updated version, pursuant to this advice from Mikael. It works very nicely in my application.
Last edit: David C. Norris 2024-08-08