9S08 indexed adressing - this example considered sloppy? - Page 1
Forum section: electronics / general

author: Circlotron
author_rank: Super Contributor
timestamp: February 11, 2021, 03:29:34 am
content: I want to go through a table of 32 bytes and move them all down one address. It would be very convenient and simple to use DBNZX at the bottom of the loop to to tell X where to point. The thing is, the loop will then exit on zero and so X won't get to point to zero offset address. Is it considered bad practice to specify the top of the table as 1 less than actual and use offsets 1-32 instead of 0-31? The "top" of the table would never be used by this function. Example code below.Code:*************************************;Uses offset 1-32, not 0-31;$6F can be used by something else*************************************SAMPLEEQU$40TABLEEQU$6F;real table starts at $70PUSH_DOWNLDX#31;second from end of tableXLOOPLDATABLE,X;STATABLE+1,X;DBNZXXLOOP;MOVSAMPLE,TABLE+1;put latest sample to top of table*************************************

author: ozcar
author_rank: Frequent Contributor
timestamp: February 11, 2021, 04:46:47 pm
content: I don't have any problem with that, but then I'm not into exotic theories about good or bad practice.I see that is similar to what you are doing in the other code you posted recently. For 32 entries, I can see it would be tedious to do it the way you did there. However, do you really have to push the whole lot down? If all you are going to do is add them all up, as in your other code, why not a circular buffer?I never programmed a 9S08, but it looks very similar to HC08 which I last used nearly twenty years ago. I don't have any fond memories of HC08 though, I kept wishing for something more like the 6809, with its two index registers, two stack pointers, and two accumulators with their 16-bit concatenation.

author: Circlotron
author_rank: Super Contributor
timestamp: February 11, 2021, 09:43:47 pm
content: Okay, that sounds interesting. Could you point me to some good info on circular buffers? No pun intended.

author: ozcar
author_rank: Frequent Contributor
timestamp: February 12, 2021, 12:34:52 am
content: Quote from: Circlotron on February 11, 2021, 09:43:47 pmYour Google-fu is probably as good as mine.Basically, just use the index register to address the position in the buffer when storing data into the table (like you do in your XLOOP there). Probably does not matter too much which way you go, but say start with index zero, and then increment it after storing your data, with a check for index register at the end of the table to reset it back to zero.

author: Circlotron
author_rank: Super Contributor
timestamp: February 12, 2021, 01:54:38 pm
content: Okay, so I got a 256 byte circular buffer up and going. What a drama! On the MC9S08PA16 micro I am using, 2K of RAM starts at $40. I was using 256 bytes from $50 to $14F as the buffer. I had an analog voltage from a pot going in and an 8-bit R2R network for an analog output. Once powered up, whenever I moved the pot the output would not change until above a certain input, above which the whole thing would crash. Spent half the day fiddling with it. Finally I found that if I moved the entire buffer above the 8-bit memory address area it worked just fine! It didn't like indexed addressing with some in 8-bit area and some in 16-bit area. I wasn't using any instructions that only work with 8-bit addresses like MOV. Is this a known issue or have I discovered something new?

author: Nominal Animal
author_rank: Super Contributor
timestamp: February 12, 2021, 05:43:33 pm
content: Quote from: Circlotron on February 11, 2021, 09:43:47 pmOn an 8-bit microcontroller, you already noticed you do not really want to cross a 256-byte boundary when traversing the buffer.If you have a 256-byte buffer, starting at a 256-byte boundary (low 8 bits of the start address zero), you can use the following code to save a 16-bit value VALHI:VALLO to the buffer. BUFPTR is a 16-bit variable, initialized to start of buffer.Code:LDHX BUFPTR ; 5 cyclesLDA VALHI ; 4 cyclesSTA ,X ; 2 cyclesINCX ; 1 cycleLDA VALLO ; 4 cyclesSTA ,X ; 2 cyclesINCX ; 1 cycleSTX BUFPTR+1 ; 4 cyclesI'm not terribly sure about the cycle counts (I haven't used HCS08), but 23 cycles should be in the ball park.Let's say the buffer is smaller, and the low byte of the first address after the buffer is BUF_ENDLO (can be 0x00 if buffer ends at 256-byte boundary), then:Code:LDHX BUFPTR ; 5 cyclesLDA VALHI ; 4 cyclesSTA ,X ; 2 cyclesINCX ; 1 cycleLDA VALLO ; 4 cyclesSTA ,X ; 2 cyclesINCX ; 1 cycleCPX #BUF_ENDLO ; 2 cyclesBNE done ; 3 cyclesLDHX #BUFFER ; 5 cyclesdone:STX BUFPTR+1 ; 4 cyclesfor somewhere around 33 cycles.You can shave several cycles off that by putting BUFPTR, VALHI, and VALLO within the first 256 bytes of RAM. It's a good idea to put buffer higher in memory.In pseudocode, the idea of a circular buffer is trivial. You have an array, and an index variable or pointer that points to the oldest entry in the cyclic buffer.Code:Let cbuffer = Array[ 0 .. N-1 ]Let cbindex = 0Function Append(value):cbuffer = valuecbindex = cbindex + 1If (cbindex >= N): Thencbindex = 0End IfEnd Functionor in C,Code:struct sometype_cbuffer {sometype *buf; /* Pointer to start of buffer */sometype *ptr; /* Pointer to oldest element */sometype *end; /* Pointer to just past the end of the buffer */};void sometype_cbuffer_append(sometype_cbuffer *const cb, sometype const val){*((cb->ptr)++) = val;if (cb->ptr >= cb->end)cb->ptr = cb->buf;}

author: ozcar
author_rank: Frequent Contributor
timestamp: February 12, 2021, 08:26:28 pm
content: Quote from: Nominal Animal on February 12, 2021, 05:43:33 pmOn these processors, there is a 16-bit index register. One thing to watch out for though is that for compatibility with earlier processors, the index register is split into two parts, H (for High-order) and X (the low order part), and some instruction only affect the low order X portion. So, yes there is an INCX instruction, but that does not affect the H part of the index register, so a buffer crossing a 256-byte boundary will cause trouble if you use INCX.On the other hand, if you use the auto-increment indexed addressing mode, then the entire H:X register is incremented, and in that case there should not be a problem crossing a 256-byte boundary. Unlike on my favourite 6809, I think the auto-increment mode is quite restrictive (might require the index register pointing directly to the target with no offset??).At least that is how I remember the similar HC08.

author: Circlotron
author_rank: Super Contributor
timestamp: February 12, 2021, 11:49:09 pm
content: I assume you mean crossing any 256 byte boundary, not just reaching past the first 256 bytes where different addressing mode can be used so there is something inherently different about them. I’ve never used auto increment mode. Is that what STA ,X for example is? I’ll have to look into that. I was using X rather than HX because seeing my buffer is 256 bytes then X rolls over to zero without any need to check for a final value, clear and branch. With HX as index, clearly it should be okay to cross 256 byte boundaries because of how much can now be addressed, but does it have to start at a 256 byte boundary or can it start anywhere there is enough room?

author: ozcar
author_rank: Frequent Contributor
timestamp: February 13, 2021, 12:39:45 am
content: Quote from: Circlotron on February 12, 2021, 11:49:09 pmThat just means no offset from the index register (ie like zero offset). The auto increment is indicated by using "X+" notation, but the snag is that few instructions allow that, and STA is not one of them, but IIRC MOV does allow that.

author: Nominal Animal
author_rank: Super Contributor
timestamp: February 13, 2021, 12:48:45 am
content: I'm usingNXP MC9S08PL16RM reference manual (pdf); I've never programmed this particular beast at all.Let's see. Maybe this is better? Is this compatible with your hardware? Are these comments sufficient to describe the purpose of each instruction?Code:LDHX BUFPTR ; 5 Load pointer to oldest entry in bufferMOV ,X+,VAL_HI ; 5 Copy byte at VAL_HI to H:X, increment H:X; VAL_HI < 256.MOV ,X+,VAL_LO ; 5 Copy byte at VAL_LO to H:X, increment H:X; VAL_LO < 256.CPHX #BUFEND ; 3 Pointer past end of buffer? (BUFEND = BUFFER + SIZE)BLO store ; 3 Skip to store if still within bufferLDHX #BUFFER ; 3 Reset pointer to beginning of bufferstore:STHX BUFPTR ; 5 Store pointer to now oldest entry in bufferThe above works just fine even if the buffer crosses a page boundary. So should this summation:Code:CLRA ; 1 Saves five cycles over CLR, since each CLR takes 5STA VAL_UN ; 3 Clear sumSTA VAL_LO ; 3STA VAL_HI ; 3LDHX #BUFFER ; 3 Pointer to beginning of bufferloop:LDA VAL_UN ; 3 Least significant byte of 24-bit VAL_HI:VAL_LO:VAL_UN valueADD ,X ; 3 Add the byte at H:XSTA VAL_UN ; 3AIX #1 ; 2 Increment H:X, does not affect carryLDA VAL_LO ; 3ADC ,X ; 3 Add carry and the byte at H:XSTA VAL_LO ; 3AIX #1 ; 2 Increment H:X, does not affect carryLDA VAL_HI ; 3ADC #0 ; 3 Add carry onlySTA VAL_HI ; 3CPHX #BUFEND ; 3 At end of buffer?BLO loop ; 3I really should install an MC9S08 assembler, so I could at least compile-test my suggestions.. Do you know if there is a Linux toolchain, maybe an emulator for this?

author: Circlotron
author_rank: Super Contributor
timestamp: February 18, 2021, 02:36:48 am
content: Quote from: Nominal Animal on February 13, 2021, 12:48:45 amThis one will edit and assemble for S08PA16 that I am using even though it is meant for HC08. Install the JK3 version. Works okay with Wine 4. Free too.http://www.pemicro.com/products/product_viewDetails.cfm?product_id=147&productTab=1

author: Nominal Animal
author_rank: Super Contributor
timestamp: February 18, 2021, 02:58:28 am
content: Have you tested whethersdas(assembler) anducsim(simulator/emulator) fromsdccwork comparably to your MCU? It'd be much easier for me than playing with Wine (which I don't even have installed right now)... I know, I whine!

author: Circlotron
author_rank: Super Contributor
timestamp: February 18, 2021, 03:16:29 am
content: Haven't tried that one. I'll have a look see.

author: Circlotron
author_rank: Super Contributor
timestamp: February 18, 2021, 01:02:16 pm
content: Nah, couldn't get it to do anything. Everything i tried would only bring up the options list. No fun at all. I'll stick with what I've got.