Program memory interactions - Abathargh/avr_io GitHub Wiki
The avr_io/progmem module provides utilities to interact with program memory in AVR chips. This module provides primitives useful to store data in program memory, retrieve it and manipulate it.
Storing data in program memory
The progmem macro allows the user to store many kinds of data into program memory. Note that a let statement is required. The type of the data is inferred from the first element when using arrays.
let
testFloat {.progmem.} = 11.23'f32 # floats
testInt1 {.progmem.} = 12'u8 # 8-bit integers
testInt2 {.progmem.} = 13'u16 # 16-bit integers
testInt3 {.progmem.} = 14'u32 # 32-bit integers
testStr {.progmem.} = "test progmem string\n" # strings
testArr {.progmem.} = [116'u8, 101, 115, 116, # arrays
32, 97, 114, 114, 97,
121, 10]
Objects can also be stored in program memory:
type
foo = object
f1: int16
f2: float32
bar = object
b1: bool
b2: cstring # in objects, we must use cstring
foobar = object
fb1: bool
fb2: foo
barfoo = object
bf1: int
bf2: bar
arr_elem = object
i: int
f: float
let
testObj1 {.progmem.} = foo(f1: 42'i16, f2: 45.67)
testObj2 {.progmem.} = bar(b1: true, b2: "test string in object\n")
testObj3 {.progmem.} = foobar(fb1: false, fb2: foo(f1: 21, f2: 77.0))
testObj4 {.progmem.} = barfoo(bf1: 69, bf2: bar(b1: false, b2: "inner\n"))
testArrObj {.progmem.} = [arr_elem(i: 1, f: 0.1), arr_elem(i: 2, f: 0.2)]
You can also reserve a block of program memory of size size, containing objects of type type, using the progmem_array(type, size) macro. This is particularly useful when wanting to embed metadata within your binaries.
progmem_array(testNonInitArr, uint8, 10)
Note: usage of {.progmem.} are type-checked, and only plain, non-managed value types are accepted by the library.
Accessing data stored in program memory
Data stored in program memory can be accessed in different ways depending on the type of data.
To get the contents of a progmem variable, you just dereference said variable through the [] operator:
# sendData sends data through uart as its ASCII representation
sendData(testFloat[])
sendData(testInt1[])
sendData((testInt3[])
The same applies for progmem objects:
sendData(testObj1[].f1)
sendData(testObj1[].f2)
sendData(testObj2[].b1)
sendData(testObj2[].b2)
Progmem array utilities
Progmem arrays can be accessed in a variety of ways. You can dereference them and get a copy of the whole array:
sendData(testArr[])
sendData(testNonInitArr[])
This works for progmem strings too: dereferencing one will yield an object of array[S, cchar] type:
sendData(testStr[])
Progmem arrays can also be indexed, by using an offset as when indexing normal arrays:
sendData(testArr[0])
sendData(testArr[1])
sendData(testArr[2])
sendData(testArr[3])
Finally, they can also be iterated, which makes them easier and safer to use:
for num in progmemIter(testArr):
sendData(num)