I have a table in program memory and want to store a byte at a given location into register R16. (This is just example data for testing) MyTable: ; 256 bytes .db $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F .db $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F <snip> .db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF R17 contains a number between $00 and $FF which represents the offset from MyTable. Can someone please show me a nice way of doing this? -- -Mike
AVR Assembler - Data from a table in program memory (ATMega8)
Started by ●March 19, 2008
Reply by ●March 19, 20082008-03-19
On Mar 19, 7:25=A0am, "Mike Warren" <miwa-not-this-...@or-this- csas.net.au> wrote:> I have a table in program memory and want to store a byte at a given > location into register R16. > > (This is just example data for testing) > > MyTable: ; 256 bytes > .db $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F > .db $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F > =A0 =A0 <snip> > .db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF > > R17 contains a number between $00 and $FF which represents the offset > from MyTable. > > Can someone please show me a nice way of doing this?You need to use the LPM instruction, which uses the Z register pair (R31:R30). Something like (no guarantees on the syntax) ldi r31, (high) MyTable ldi r30, (low) MyTable ;load base of table into Z pair add r30,r17 adc r31,#0 ;address of desired value now in Z pair lpm r16,Z ;fetch desired value
Reply by ●March 19, 20082008-03-19
On Mar 19, 8:25=A0am, Mike Silva <snarflem...@yahoo.com> wrote:> On Mar 19, 7:25=A0am, "Mike Warren" <miwa-not-this-...@or-this- > > > > > > csas.net.au> wrote: > > I have a table in program memory and want to store a byte at a given > > location into register R16. > > > (This is just example data for testing) > > > MyTable: ; 256 bytes > > .db $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F > > .db $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F > > =A0 =A0 <snip> > > .db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF > > > R17 contains a number between $00 and $FF which represents the offset > > from MyTable. > > > Can someone please show me a nice way of doing this? > > You need to use the LPM instruction, which uses the Z register pair > (R31:R30). =A0Something like (no guarantees on the syntax) > > ldi =A0r31, (high) MyTable > ldi =A0r30, (low) MyTable =A0;load base of table into Z pair > add =A0r30,r17 > adc =A0r31,#0 =A0;address of desired value now in Z pair > lpm =A0r16,Z =A0 ;fetch desired value- Hide quoted text - > > - Show quoted text -OK, looks like "adc r31,#0" isn't allowed. I suppose the alternative is ldi r16,0 adc r31,r16 AVR assembly programmers, is there a better way here? BTW, I know avr-gcc sets up a zero register (r1 IIRC). If you set one up in your program it would be useful to use here for the adc instruction (and many other places, presumably).
Reply by ●March 19, 20082008-03-19
Mike Silva wrote:> You need to use the LPM instruction, which uses the Z register pair > (R31:R30). Something like (no guarantees on the syntax)Thanks for the reply Mike.> ldi r31, (high) MyTable > ldi r30, (low) MyTable ;load base of table into Z pair > add r30,r17Ok, I wasn't sure add(ing) to ZL (R30) would work on all 16 bits of the Z register.> adc r31,#0 ;address of desired value now in Z pairI don't understand this. What's supposed to happen here?> lpm r16,Z ;fetch desired value-- -Mike
Reply by ●March 19, 20082008-03-19
Mike Silva wrote:> OK, looks like "adc r31,#0" isn't allowed. I suppose the > alternative is > > ldi r16,0 > adc r31,r16I see now. These three together work on the 16 bits.> AVR assembly programmers, is there a better way here? > > BTW, I know avr-gcc sets up a zero register (r1 IIRC). If you set > one up in your program it would be useful to use here for the adc > instruction (and many other places, presumably).Sounds like a good idea. I'll keep that in mind. Thanks. -- -Mike
Reply by ●March 19, 20082008-03-19
On Mar 19, 9:03=A0am, "Mike Warren" <miwa-not-this-...@or-this- csas.net.au> wrote:> Mike Silva wrote: > > You need to use the LPM instruction, which uses the Z register pair > > (R31:R30). =A0Something like (no guarantees on the syntax) > > Thanks for the reply Mike. > > > ldi =A0r31, (high) MyTable > > ldi =A0r30, (low) MyTable =A0;load base of table into Z pair > > add =A0r30,r17 > > Ok, I wasn't sure add(ing) to ZL (R30) would work on all 16 bits of > the Z register.No, it doesn't. We're adding an 8 bit value to the low 8 bits of Z (r30), which may or may not result in a carry out. If there is a carry we need to add it to the high 8 bits of Z (r31).> > adc =A0r31,r1 =A0;address of desired value now in Z pair > > I don't understand this. What's supposed to happen here?First of all, I replaced "#0" with "r1", assuming that r1 contains 0. This instruction is then adding the carry bit from the "add r30,r17" to r31. Two examples, one without carry and one with: Z =3D MyTable =3D 0x380 (r31 =3D 0x3, r30 =3D 0x80) r17 =3D 0x40 add r30,r17 =3D 0xC0 (no carry) adc r31,r1 =3D 3+0+C(=3D0) =3D 3 (no carry added to r31) r31:r30 =3D 0x3C0 2nd example, same MyTable base address r17 =3D 0xA0 add r30,r17 =3D 0x20 (with carry) adc r31,r1 =3D 3+0+C(=3D1) =3D 4 (adding the carry to r31) r31:r30 =3D 0x420
Reply by ●March 19, 20082008-03-19
Mike Silva wrote:> Two examples, one without carry and one with: > > Z = MyTable = 0x380 (r31 = 0x3, r30 = 0x80) > r17 = 0x40 > add r30,r17 = 0xC0 (no carry) > adc r31,r1 = 3+0+C(=0) = 3 (no carry added to r31) > r31:r30 = 0x3C0 > > 2nd example, same MyTable base address > r17 = 0xA0 > add r30,r17 = 0x20 (with carry) > adc r31,r1 = 3+0+C(=1) = 4 (adding the carry to r31) > r31:r30 = 0x420All very clear now. Thank you. -- -Mike