I would like to use 652 unsigned long values on an Arduino Uno, but it doesn't look like there's enough memory. I thought about the splitting unsigned long values to 3 unsigned chars to store in PROGMEM which I can letter recall and join as unsigned long as needed.
I'm not super experienced with byte manipulations and I got myself stuck when trying to merge the data. When I try with one variable at a time, I get the expected output. The part I'm confused about is why do I get different values when using a variable as an array index for each value ? How can I fix this ?
Here's my test code so far:
#include <avr/pgmspace.h>
#include "flashData.h"
void setup() {
Serial.begin(115200);
unsigned long fromPROGMEM = (onsets1[0] << 16) | (onsets2[0] << 8) | onsets3[0];
Serial.println(fromPROGMEM);
unsigned long fromValues = (0x00 << 16) | (0x01 << 8) | 0xF3;
Serial.println(fromValues);
byte b1 = 0x00;
byte b2 = 0x01;
byte b3 = 0xF3;
unsigned long fromBytes = (b1 << 16) | (b2 << 8) | b3;
Serial.println(fromBytes);
delay(2000);
unsigned char c1,c2,c3;
unsigned long value;
Serial.println("data using same index:");
for(int i = 0 ; i < 10; i++){
c1 = onsets1[3];
c2 = onsets2[3];
c3 = onsets3[3];
value = (c1 << 16) | (c2 << 8) | c3;
Serial.print("index: ");
Serial.print(i);
Serial.print("\tvalue:");
Serial.println (value);
delay(10);
}
Serial.println("data using counter:");
for(int i = 0 ; i < 10; i++){
c1 = onsets1[i];
c2 = onsets2[i];
c3 = onsets3[i];
value = (c1 << 16) | (c2 << 8) | c3;
Serial.print("index: ");
Serial.print(i);
Serial.print("\tvalue:");
Serial.println (value);
delay(10);
}
}
void loop() {
}
and flashData.h:
#ifndef _flashData_h_
#define _flashData_h_
static PROGMEM const unsigned char onsets1[652] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03};
static PROGMEM const unsigned char onsets2[652] = {0x01,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x25,0x26,0x28,0x29,0x2A,0x2B,0x2C,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x38,0x39,0x3A,0x3B,0x3C,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x48,0x49,0x4A,0x4C,0x4D,0x4E,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x59,0x5A,0x5B,0x5C,0x5E,0x5F,0x61,0x63,0x64,0x65,0x67,0x6A,0x6B,0x6C,0x6D,0x6E,0x70,0x71,0x73,0x75,0x76,0x77,0x79,0x7C,0x7E,0x7F,0x80,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xC0,0xC2,0xC4,0xC6,0xC9,0xCB,0xCD,0xCF,0xD2,0xD4,0xD6,0xD8,0xDA,0xDB,0xDD,0xDF,0xE0,0xE2,0xE4,0xE6,0xE7,0xE8,0xE9,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF4,0xF6,0xF7,0xF8,0xF9,0xFA,0xFD,0xFE,0xFF,0x00,0x01,0x02,0x03,0x06,0x07,0x08,0x0A,0x0D,0x0F,0x10,0x11,0x12,0x13,0x14,0x16,0x18,0x19,0x1A,0x1C,0x1D,0x1F,0x21,0x22,0x23,0x25,0x28,0x2A,0x2B,0x2C,0x2E,0x30,0x31,0x33,0x34,0x35,0x38,0x3C,0x3D,0x3E,0x41,0x42,0x44,0x45,0x46,0x47,0x48,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x53,0x54,0x56,0x57,0x58,0x59,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x63,0x65,0x66,0x67,0x69,0x6A,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x75,0x77,0x78,0x79,0x7A,0x7B,0x7D,0x7E,0x7F,0x80,0x82,0x84,0x87,0x89,0x8B,0x8E,0x90,0x92,0x94,0x97,0x99,0x9B,0x9D,0xA0,0xA2,0xA4,0xA5,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB9,0xBA,0xBB,0xBD,0xBF,0xC0,0xC2,0xC4,0xC6,0xC7,0xC8,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,0xE2,0xE4,0xE6,0xE8,0xEA,0xEB,0xED,0xEF,0xF1,0xF2,0xF3,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFF,0x01,0x03,0x04,0x05,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0F,0x10,0x11,0x12,0x13,0x15,0x16,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x20,0x21,0x23,0x24,0x25,0x27,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x30,0x32,0x33,0x35,0x36,0x37,0x3A,0x3B,0x3C,0x3E,0x40,0x43,0x44,0x45,0x47,0x48,0x49,0x4A,0x4C,0x4D,0x4E,0x50,0x55,0x56,0x57,0x59,0x5A,0x5B,0x5E,0x5F,0x60,0x61,0x62,0x63,0x65,0x66,0x67,0x68,0x69,0x6B,0x6C,0x6F,0x70,0x71,0x72,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,0x7D,0x7F,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x99,0x9B,0x9D,0x9F,0xA2,0xA4,0xA6,0xA8,0xAB,0xAD,0xAF,0xB1,0xB4,0xB6,0xB7,0xB8,0xBB,0xBD,0xBE,0xBF,0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCC,0xCD,0xCE,0xCF,0xD1,0xD3,0xD6,0xD8,0xDA,0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,0xE4,0xE5,0xE7,0xE8,0xE9,0xEA,0xEC,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFE,0x01,0x03,0x04,0x05,0x07,0x09,0x0A,0x0B,0x0C,0x0E,0x10,0x12,0x13,0x14,0x15,0x17,0x18,0x1A,0x1C,0x1E,0x1F,0x20,0x21,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x34,0x35,0x37,0x39,0x3C,0x3E,0x40,0x42,0x43,0x45,0x47,0x49,0x4A,0x4B,0x4C,0x4E,0x50,0x52,0x53,0x54,0x56,0x57,0x58,0x59,0x5B,0x5C,0x5D,0x5F,0x60,0x61,0x62,0x64,0x66,0x68,0x69,0x6B,0x6C,0x6D,0x6E,0x70,0x71,0x72,0x74,0x75,0x76,0x78,0x79,0x7B,0x7C,0x7D,0x7F,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x8A,0x8B,0x8C,0x8D,0x8F,0x90,0x91,0x93,0x94,0x95,0x96,0x97,0x98,0x9B,0x9D,0x9F,0xA1};
static PROGMEM const unsigned char onsets3[652] = {0xF3,0x31,0x59,0x76,0x98,0xBA,0xDD,0xFF,0x43,0x66,0x88,0xAA,0xC7,0xEF,0x0B,0x2D,0x50,0x72,0x8E,0xB1,0xD3,0xF5,0x17,0x3A,0x5C,0x7E,0xA0,0xC8,0xE5,0x0D,0x29,0x6E,0x90,0xAC,0xD5,0xF7,0x13,0x35,0x58,0x7A,0x9C,0xB9,0xE1,0xFD,0x42,0x6A,0x86,0xA8,0xC5,0x0F,0x31,0x54,0x7C,0x92,0xB5,0xCB,0xF9,0x1B,0x43,0x60,0xA4,0xC1,0xE3,0x28,0x4A,0x72,0x8E,0xB1,0xD3,0xF5,0x17,0x34,0x5C,0x78,0xBD,0xDF,0x01,0x46,0x62,0x84,0xCF,0x0D,0x30,0x52,0x7A,0x91,0xD5,0xF7,0x1A,0x5E,0x86,0xA3,0xE7,0x26,0x5F,0x92,0xAF,0xF3,0x1B,0x32,0x5A,0x7C,0x9F,0xBB,0xE3,0x00,0x28,0x4A,0x66,0x89,0xAB,0xC7,0x0C,0x34,0x4A,0x72,0x95,0xB7,0xD9,0xFB,0x1E,0x3A,0x62,0x7F,0x9B,0xC3,0xE0,0x2A,0x52,0x69,0x91,0xB3,0xD5,0xF7,0x1F,0x36,0x58,0x80,0x9D,0xB9,0xE1,0xF8,0x42,0x65,0x81,0xA9,0xCB,0xE8,0x10,0x54,0x93,0xD2,0x16,0x60,0x9F,0xE4,0x28,0x6D,0xAB,0xF0,0x12,0x34,0x79,0xB2,0xDA,0x02,0x46,0x85,0xAD,0xCF,0xF2,0x0E,0x30,0x4D,0x75,0x97,0xB9,0xD0,0xFE,0x1A,0x65,0x87,0xA3,0xC5,0xE2,0x2C,0x4E,0x6B,0x8D,0xAF,0xD7,0xEE,0x38,0x5B,0x77,0xC1,0x00,0x45,0x67,0x89,0xAB,0xCE,0xF0,0x01,0x57,0x7F,0x95,0xDA,0xFC,0x1E,0x5D,0x7F,0x9C,0xE0,0x25,0x6F,0x91,0xAE,0xF2,0x14,0x3C,0x7B,0x98,0xBA,0x04,0x82,0xAF,0xCC,0x16,0x33,0x77,0x94,0xBC,0xD2,0xFA,0x1D,0x3F,0x61,0x7D,0xA6,0xC8,0xE4,0x29,0x51,0x8F,0xAC,0xCE,0xF0,0x13,0x35,0x57,0x79,0x9C,0xBE,0xE0,0x02,0x47,0x69,0x8B,0xCA,0xF2,0x31,0x53,0x75,0x98,0xBA,0xD6,0xF9,0x15,0x5F,0x82,0xA4,0xC6,0xE8,0x05,0x33,0x60,0x7D,0xBC,0xFA,0x3F,0x83,0xC2,0x0C,0x51,0x95,0xD4,0x18,0x5D,0xA1,0xE0,0x25,0x69,0xA8,0xD0,0xE7,0x0F,0x31,0x53,0x75,0x98,0xB4,0xDC,0xF9,0x1B,0x3D,0x5F,0x7C,0xA4,0xC0,0x05,0x21,0x49,0x88,0xD2,0xF4,0x11,0x55,0x94,0xBC,0xDE,0x1D,0x4B,0x62,0x8F,0xAC,0xF0,0x2F,0x57,0x74,0x96,0xB2,0xD5,0xF7,0x1F,0x3B,0x63,0x86,0xAE,0xC4,0xEC,0x09,0x47,0x8C,0xD0,0xF3,0x15,0x54,0x98,0xC0,0xE2,0x05,0x21,0x66,0x88,0xA4,0xD2,0xEF,0x39,0x72,0xBC,0xD9,0xFB,0x23,0x3F,0x62,0x84,0xA0,0xC3,0xF0,0x07,0x2F,0x4C,0x74,0x90,0xCF,0xF7,0x13,0x3B,0x58,0x74,0x9C,0xB9,0xDB,0x03,0x1F,0x6A,0x86,0xA3,0xED,0x0F,0x31,0x4E,0x76,0x92,0xB5,0xF9,0x27,0x38,0x7C,0xA4,0xC1,0x05,0x28,0x4A,0x8E,0xCD,0x11,0x3A,0x50,0x9B,0xBD,0xDF,0x93,0x24,0x40,0x68,0xA7,0x2A,0x58,0x74,0xB9,0xDB,0xF7,0x3C,0x5E,0x80,0xA3,0xC5,0xE7,0x09,0x2C,0x48,0x70,0x8D,0xD1,0xF9,0x38,0x54,0x77,0x9F,0xBB,0xDD,0x00,0x22,0x60,0x83,0x9F,0xE9,0x11,0x2E,0x50,0x72,0x95,0xB7,0xDF,0xFB,0x18,0x40,0x5C,0x7F,0xA1,0xB8,0x08,0x2A,0x46,0x6E,0x8B,0xAD,0xD5,0xFD,0x14,0x58,0x97,0xDC,0x20,0x59,0xA9,0xEE,0x32,0x71,0xB5,0xF4,0x38,0x77,0x99,0xC1,0x06,0x4A,0x6D,0x8F,0xAB,0xCE,0xF0,0x0C,0x34,0x57,0x79,0x95,0xBD,0xDA,0x02,0x1E,0x46,0x5D,0xA7,0xE6,0x25,0x6F,0xAE,0xF2,0x14,0x37,0x5F,0x7B,0xC0,0xE8,0xFE,0x21,0x43,0x6B,0x8D,0xC6,0x10,0x33,0x55,0x77,0x99,0xBC,0xD8,0x00,0x1D,0x45,0x5B,0x83,0xA0,0xE4,0x29,0x67,0x8F,0xAC,0xF0,0x18,0x35,0x63,0x79,0xB8,0xFD,0xC1,0x4D,0x6F,0x86,0xCA,0xF2,0x09,0x4D,0x92,0xBA,0xD6,0xF9,0x15,0x37,0x59,0x82,0xA4,0xBA,0xE8,0x05,0x27,0x49,0x6B,0x8E,0xAA,0xCC,0xEF,0x17,0x33,0x78,0xB6,0x01,0x3F,0x7E,0xC3,0xEB,0x07,0x4C,0x90,0xB2,0xD5,0xFD,0x19,0x5E,0xA2,0xBE,0xE1,0x03,0x25,0x47,0x64,0xAE,0xD6,0xED,0x15,0x31,0x59,0x76,0xB5,0xF9,0x1B,0x3E,0x7C,0xA4,0xC7,0xE9,0x0B,0x33,0x50,0x8E,0xB6,0xD9,0x01,0x11,0x56,0x7E,0x95,0xDF,0x9F,0x13,0x29,0x46,0x68,0x8A,0xAC,0xC9,0xEB,0x0D,0x2A,0x52,0x6E,0xAD,0xCF,0xF7,0x25,0x30,0x64,0x7B,0xA3,0xBF,0x09,0x42,0x8D,0xCB};
#endif
And here's what I see from Serial:
499
499
499
data using same index:
index: 0 value:1654
index: 1 value:1654
index: 2 value:1654
index: 3 value:1654
index: 4 value:1654
index: 5 value:1654
index: 6 value:1654
index: 7 value:1654
index: 8 value:1654
index: 9 value:1654
data using counter:
index: 0 value:4294945024
index: 1 value:4294962688
index: 2 value:12806
index: 3 value:28928
index: 4 value:4294948096
index: 5 value:4294964224
index: 6 value:14337
index: 7 value:30464
index: 8 value:4294940928
index: 9 value:4294951174
I see what I expect for first 3 values and also for data using same index, but no when using a variable as an index for the PROGMEM arrays.
What is going on and how can I fix this ?
Update Mikael's answer is the solution, but I will post a working snippet here for reference:
#include <avr/pgmspace.h>
#include "flashData.h"
void setup() {
Serial.begin(115200);
delay(2000);
unsigned char c1,c2,c3;
unsigned long value;
Serial.println("data using counter:");
for(int i = 0 ; i < 652; i++){
c1 = (unsigned char) pgm_read_byte(&onsets1[i]);
c2 = (unsigned char) pgm_read_byte(&onsets2[i]);
c3 = (unsigned char) pgm_read_byte(&onsets3[i]);
value = (((unsigned long) c1) << 16) | ((unsigned long)c2 << 8) | (unsigned long)c3;
Serial.print("index: ");
Serial.print(i);
Serial.print("\tvalue:");
Serial.println (value);
delay(10);
}
}
void loop() {
}
The key is not only explicitly casting the data read, but also correctly reading the the PROGMEM data.
unsigned long
needs 4unsigned char
s.(0 << 24) | (c1 << 16) | (c2 << 8) | c3
but the result looks the same.onsets1
. The values it holds are simple to generate at runtime. I'd also look at encoding the values inonsets2
differently, probably as a length and an increment. So the first pair would be 1 and 3, because there's one value (1), followed by an increment of 3 to produce 4. The next pair would be 7 and 3, because there are 7 sequential values (4, 5, 6, 7, 8, 9, A) and the next value is 3 more than the end of that sequence. Etc.