SparkFun Forums 

Where electronics enthusiasts find answers.

Your source for all things Atmel.
By Liencouer
#112184
This may be a little old, but I figure I'll add to it anyways.
dumais wrote:Since the constant I am passing is part of the instruction (ldi r24,101 is one full instruction) it will never even go in ram, it will be loaded in the r24 register directly. Avoiding a memory transfer. The only "memory transfer" is the one the the instruction register needed to be loaded but that is insignificant because we would need it anyway if we were to do it any other way. When I do "std Y+2,r24" there is also a memory transfer from register to RAM that I would have to do any way.
AVR does not have a SRAM->SRAM instruction. Everything has to go through registers.

As stevech has pointed out, by using the LDI instructions you are trading off program space for execution time.
By dumais
#112241
I don't think I mentionned anything about sram to sram. :)

bufToSendToenc28j60[0]='t'; will load an immediate to register, then register to sram.

I don't think I am trading program space for execution time either. Because using LDI instead of fetching from pgrm space will: save program space by using less instruction (see post #12) and save execution time by having less instructions to execute.

So basically, if there is a way of doing this faster/smaller:
Code: Select all
ldi r24,lo8(116)
std Y+1,r24
ldi r24,lo8(101)
std Y+2,r24
Then, I sure would like to know. Otherwise, I would like to know how to generate the previous example using C and using the values in a "string" form instead of char by char like the example in post #12.
By Liencouer
#112259
Should have been memory, not SRAM. AVR has no memory->memory instruction.
dumais wrote:I don't think I am trading program space for execution time either.
Depending on the length of your string, at some point the LDI instructions will exceed the size of the program read byte macro + the program memory usage of the string itself.

The LDI instruction requires 2 bytes of progspace per character. The program read byte function requires N bytes of progspace, and each character requires 1 byte progspage. At some point those lines intersect. For small strings, the LDI instruction is smaller, but for larger strings the program read byte is smaller.

As for how to generate the LDI/STD instructions more cleanly in C, it seems like something a cleverly written macro can do. The following is very untested, but it might give you an idea how to start. It should iterate over the string and create var[n-1] = str[n-1]; var[n-1] = str[n-2]; ... var[0] = str[0];
Code: Select all
#define LOAD_STRING(var_name, str, len) { var_name##[##len-1##]=str[len-1];  if(len>0)LOAD_STRING(var_name, str, len-1); }
By dumais
#112262
Hmm, the example does not work but I see what you are getting at. I will play around with that. Thanks!

As for program space and the string lenght: yes you are right, sorry about that. This is exactly what I want though. I have 128K of flash and I am only using 16k right now, so I would like use the rest of it in order to gain more speed.

Thanks again. That should do it.
By Liencouer
#112460
Meh. For some reason I thought you could do recursive macros, but I must have been mistaken.

I was also looking at this: http://stackoverflow.com/questions/1286 ... a-sequence, but I cant quite get it to work with the string either.

If you like python, the following
Code: Select all
with open("tmp.txt", 'w') as f:

    s = "test_string";
    f.write("char str[");
    f.write(str(len(s)));
    f.write("];\r\n");
    
    for i in range(len(s)):
        f.write("str[");
        f.write(str(i));
        f.write("] = '");
        f.write(str(s[i]));
        f.write("';\r\n");

import os;
os.startfile("tmp.txt");
will generate
Code: Select all
char str[11];
str[0] = 't';
str[1] = 'e';
str[2] = 's';
str[3] = 't';
str[4] = '_';
str[5] = 's';
str[6] = 't';
str[7] = 'r';
str[8] = 'i';
str[9] = 'n';
str[10] = 'g';
which generates
Code: Select all
str[0] = 't';
  94:	84 e7       	ldi	r24, 0x74	; 116
  96:	89 83       	std	Y+1, r24	; 0x01

str[1] = 'e';
  98:	85 e6       	ldi	r24, 0x65	; 101
  9a:	8a 83       	std	Y+2, r24	; 0x02

[... et al ...]
The python should be clean enough for you to modify to fit your needs. I'm a little upset I cant figure out how to do it with the macros though... My problem is that I can't break up the passed string into its individual characters in the macro. Somehow you have to get from "string" to 's', 't', 'r', 'i', 'n', 'g'. I think it probably works if you pass each character as an individual parameter, but thats not a whole lot better than doing it all by hand.