Solved: Peek/ Poke?

Any other dinosaurs out there? Remember "Peek" and "Poke"?

Maybe not BEST way to do it, but, bear with me, we'll come to that?

I'd like a way to set aside some bytes of memory, and then access them as directly as possible. I'm using the word "byte" precisely... and 8-bit value. I won't try to stuff, say, 300, into one of the elements of my memory space.

In the old days...

DIM Buffer (100);// set aside the memory

//Fill it with values
for x=0 to 99
poke Buffer(x)=x
end of for loop

//Check that it worked....
for x=0 to 99
print x
end of for loop

====
Ideas welcome!

The closer you can get to that, the more welcome the answer will be.

On the other hand, if something close to that is a Really Bad Idea, and ther are Better Ways, I will do my best to understand the new way. If that come with a "why it is better", it will be even more welcome.

====
I do realize that each byte taken for the buffer is one less byte for other things. I'll ask about the wheres and hows of using different places a byte might be stored in a separate post, once I've digested answers to this one.

Thanks!

In C++ we call it an array and you don't need keywords peek and poke you just access the elements directly. Google "C++ array" and you'll find tons of resources. You sound like you want to make an array of bytes.

So your program above might look like:

byte nameMe[100];

for(int i = 0; i < 100; i++){
nameMe[i] = i ;
}

for(int i=0; i<100; i++){
Serial.println(nameMe[i]);
}

tkbyd:
Ideas welcome!

Idea:

// DIM Buffer (100);// set aside the memory
byte Buffer[100];

void setup() {
  Serial.begin(9600); // Prepare Serial for output at 9600 Baud

  //Fill it with values
  // for x=0 to 99
  //  poke Buffer(x)=x
  //  end of for loop
  for (int x=0;x<100;x++)
  {
    Buffer[x]=x;
  }

  //Check that it worked....
  // for x=0 to 99
  // print x
  // end of for loop
  for (int x=0;x<100;x++)
  {
    Serial.println(Buffer[x]);
  }
}


void loop() {
  // put your main code here, to run repeatedly:
}

tkbyd:
The closer you can get to that, the more welcome the answer will be.

You can come closer to the original code when replacing the for-loop condition with:

 for (int x=0;x<=99;x++)

But generally C-programmers prefer to test the condition "<numberOfElements" instead of "<=numberOfElements-1". But of course, both is possible.

As I recall it, peek and poke were used to change values for given port addresses, not array elements. The dialects of Basic I once used all supported arrays, so using peek/poke on an array could be done, but really wasn't needed. With C, array subscripting is the norm, or use pointers.

On the Inmos transputer, poke was a link primitive which allowed you to boot a remote romless processor, by writing executable code into its memory.
Peek was another primitive which allowed you to verify the code, or read things like ID registers.

econjack:
As I recall it, peek and poke were used to change values for given port addresses, not array elements. The dialects of Basic I once used all supported arrays, so using peek/poke on an array could be done, but really wasn't needed. With C, array subscripting is the norm, or use pointers.

10 REM Peek() and Poke() read and write a given memory location, respectively.
20 REM On an 8 bit processor, they address a byte.
30 REM If a port is memory mapped, then you can use them to access it.

shouldn't it be something like:

//
//    FILE: peekpoke.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: peek & poke demo
//    DATE: 2015-11-20
//     URL:
//
// Released to the public domain
//


byte mypeek(byte * address)
{
  return * address;
}

void mypoke(byte * address, byte value)
{
  *address = value;
}

int ar[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

void setup()
{
  Serial.begin(115200);
  Serial.print("Start ");
  Serial.println(__FILE__);

  int x = mypeek((byte*)&ar[0]);
  Serial.println(mypeek((byte*)&ar[0]), DEC);
  mypoke((byte*)&ar[0], 123);
  Serial.println(mypeek((byte*)&ar[0]), DEC);
  mypoke((byte*)&ar[0], 42);
  Serial.println(mypeek((byte*)&ar[0]), DEC);
  mypoke((byte*)&ar[0], x);

  Serial.println("..done..");
}

void loop()
{
}

Everybody is also forgetting about the "VARPTR" statement (likely only in the Microsoft BASIC dialects - which were most of the commercial microcomputer BASIC dialect of the time) - it basically returned the starting address (aka - variable pointer, hence the statement name) for the beginning of memory for a given variable; something like (my BASIC is rusty - lol):

10 CLEAR 2000: REM RESERVE 2000 BYTES
20 DIM A(100)
30 X = VARPTR(A): REM GET POINTER TO START OF ARRAY
40 POKE X, 20: REM A(0) = 20
50 POKE X+1, 55: REM A(1) = 55
60 PRINT A(0)
70 PRINT PEEK(X): REM OUTPUT SAME AS PREV LINE
80 PRINT A(1)
90 PRINT PEEK(X+1)
100 END

:slight_smile:

BTW - Line 10 isn't absolutely necessary, but may be needed on larger BASIC programs, depending on where BASIC resided and how many variables/memory was needed - to avoid clobbering the beginning of your code in memory (because sometimes the code would be started after a particular area of memory meant for the variables, and if you used more variable space than was available - you'd either get an ?OM ERROR - out of memory - or your code would get clobbered; usually the former, though).

Many thanks... lots of useful material here... including even the "simple" answer I most wanted. But some useful "extensions" for me, too!

I always seem to get into trouble when I used Arduino arrays... I'm glad that what I THOUGHT would work SHOULD work. Must Try Harder not to make whatever mistakes I am making when I try to do arrays!

tkbyd:
Many thanks... lots of useful material here... including even the "simple" answer I most wanted. But some useful "extensions" for me, too!

I always seem to get into trouble when I used Arduino arrays... I'm glad that what I THOUGHT would work SHOULD work. Must Try Harder not to make whatever mistakes I am making when I try to do arrays!

Remember that the first element in an array is element #0 and the last element is element #(size of array -1).

I just searched the Forum for "PEEK POKE" and found this thread. :slight_smile:

Yes, I am an old fossil, and I LOVE my BASIC!!! In fact, I am trying to make a radio project I built, able to store and recall presets for AM and FM stations... and C++ is very confusing to me, ESPECIALLY the way it handles the EEPROM!

Oh, how I WISH I could just do something like this with the EEPROM in the Arduino! (Line #'s omitted)

EEPROM=49152

INPUT "Enter Preset channel number to save this station:",PRESET

REM to save a preset-

POKE (EEPROM+PRESET), CURENTFREQUENCY

REM to recall a preset-

CURRENTFREQUENCY=PEEK(EEPROM+PRESET)

Something like that. :slight_smile:

You can absolutely write directly to locations in EEPROM. The syntax looks nothing like that. It's actually even simpler.

Use the EEPROM functions to read and write values.
EEPROM.write(address, value)
EEPROM.read(address)

You can also read values for variables stored in PROGRAM memory, but there is no simple way to write to it.

BASIC will always have a place in my heart, ever since I found it while playing with a teletype terminal at my high school in 1969. I used it to teach myself how to translate ideas into a linear sequence with logical branching. In other words, programming. I stuck with basic (with a brief detour into it's 'adultish homunculus' FORTRAN) until the mid 80s when I found FORTH.

Shouldn't a real PEEK and POKE work with flash memory on the Arduino as well? Often these were used to dynamically change the program. It seem kind of magical at the time. Our computers back then used Von Neumann architecture (aka Princeton architecture) then so all the memory (variables plus program instructions) was available in the same address space.

Arduinos (and many other modern processors) use Harvard architecture. Program instructions and RAM (variables, stacks, and other dynamic memory) are addressed in a separate space. This adds complexity to the arguments needed for PEEK and POKE functions. (And as Willie---, DeltaG and jremmington have been discussing, so does EEPROM. But I would be glad to leave that as a different animal. But I think PEEK and POKE should cover both RAM and Flash memory in an Arduino programming environment.

Used to do this all the time in C when computers had CGA video cards. Everybody did. The incantation was:

#define screen (((unsigned *)[80])0xB8000000)

which defined memory location B800:0000 to be a 2-d array of unsigned. To make line 5, column 3 into a uppercase 'A' that was bright white on blue, you'd:

[nobbc]screen[5][3] = 'A' | 0x1F00; [/nobbc]

There was only one caveat: the video cards weren't dual-ported, so writing to them would make snow appear on the screen. To fix this, you'd watch the vertical retrace hardware port and wait for it to go high, and do your screen updates then.

Ah! Memories!

ChrisTenone:
(with a brief detour into it's 'adultish homunculus' FORTRAN) until the mid 80s when I found FORTH.

:slight_smile:

I think people should all start in BASIC. I don't know why, but it feels like you have to understand the concepts and constructs better and it is easier to understand them. When people first see C++ I think it all too often looks like just a group of esoteric statements that magically the computer recognizes and takes some action for. I think people lose the fact that it is still executed line by line in order. With BASIC you couldn't miss that.

I think blink without delay is a perfect example. Very few people seem to see that and say, oh record the time and compare to some other time. Too many people just see, if I write these four lines together it will make a timer. The action somehow gets separated from the lines of code that perform it.

UnoWatt:
Talking of, don't forget that Arduino EEPROM has a limit of 100000 writes per location, so if you do EEPROM writes in loop() without being careful you'll wear it out before you take a sip of coffee.

Only write to the EEPROM when something changes that has a global and lasting effect.

For example, a clock program could write to the EEprom every time it reset the clock. If the program checked every millisecond, and recorded the result it would take less than two minutes to use up the 'guaranteed' life of an Arduino EEPROM.

On the other hand, a worse case scenario, using a 3231 real time clock chip means the EEPROM should be written once every 6 days. Then the EEPROM will fail sometime in the year 2525. . . . "If man is still alive, if woman can survive, they may find ..." their Arduino device will fail. Yeah, anti climatic, huh.

Delta_G:
... The action somehow gets separated from the lines of code that perform it.

I think this is the key to nearly all learning difficulties. This is why 'learning by doing' is so much more effective than 'book learning'. Actions and results are viscerally associated.

I started with BASIC because it was free and easy. Kinda my whole college story in a single metaphor. None-the-less, I can program (and since it's not my job I also enjoy programming) and I have three offspring. And a couple grand-offspring. Yeah humanity. Yeah education.

But I mean ... is there a smiley?