static uint8_t myID[8];
void read_EE(uint8_t word, uint8_t *buf, uint8_t offset) {
noInterrupts();
FTFL_FCCOB0 = 0x41; // Selects the READONCE command
FTFL_FCCOB1 = word; // read the given word of read once area
// launch command and wait until complete
FTFL_FSTAT = FTFL_FSTAT_CCIF;
while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF))
;
*(buf+offset+0) = FTFL_FCCOB4;
*(buf+offset+1) = FTFL_FCCOB5;
*(buf+offset+2) = FTFL_FCCOB6;
*(buf+offset+3) = FTFL_FCCOB7;
interrupts();
}
void read_myID() {
read_EE(0xe,myID,0); // should be 04 E9 E5 xx, this being PJRC's registered OUI
read_EE(0xf,myID,4); // xx xx xx xx
}
void print_myID() {
Serial.printf(" ID byte = %d decimal, from ", myID[7]);
for (int i=0; i < sizeof(myID); i++)
Serial.printf("%02X:", myID[i]);
}
Note: the "read_mac()" contributed function yields 6 of of the 8 bytes.
Technically, one should have approval by PJRC to use addresses in their block starting with 04 E9 E5 - perhaps a blanket statement by PJRC that it be used only for certain purposes beyond the 64 bit product serial number.
void setup() {
}
void loop() {
print_myID();
delay(1000);
}
void loop() {
// put your main code here, to run repeatedly:
read_myID();
print_myID();
delay(1000);
}
unsigned long serialNum = 0;
void print_myID() {
int ii;
Serial.printf(" ID byte = %d decimal, from ", myID[7]);
for (ii = 0; ii < sizeof(myID); ii++) {
if ( ii )
Serial.printf(" :");
Serial.printf("%02X", myID[ii]);
if ( ii > 3)
serialNum = (serialNum << 8) + myID[ii];
}
Serial.printf(" Serial# %lu0\n", serialNum);
}
#if !defined(CORE_TEENSY)
Serial.println ("Danger Will Robinson, non-Teensy found");
#elif !defined(__arm__)
Serial.println ("Running on a non-arm Teensy like the 2.0/2.1++");
#elif defined(__MKL26Z64__)
Serial.println ("Running on a Teensy LC");
#elif defined(__MK20DX256__)
Serial.println ("Running on a Teensy 3.1");
#elif defined(__MK20DX128__)
Serial.println ("Running on a Teensy 3.0");
#else
Serial.println ("Running on an unknown Teensy processor");
#endif
uint8_t mac[6];
void read(uint8_t word, uint8_t *mac, uint8_t offset) {
FTFL_FCCOB0 = 0x41; // Selects the READONCE command
FTFL_FCCOB1 = word; // read the given word of read once area
// launch command and wait until complete
FTFL_FSTAT = FTFL_FSTAT_CCIF;
while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF));
*(mac + offset) = FTFL_FCCOB5; // collect only the top three bytes,
*(mac + offset + 1) = FTFL_FCCOB6; // in the right orientation (big endian).
*(mac + offset + 2) = FTFL_FCCOB7; // Skip FTFL_FCCOB4 as it's always 0.
}
void read_mac() {
read(0xe, mac, 0);
read(0xf, mac, 3);
}
void print_mac() {
size_t count = 0;
for (uint8_t i = 0; i < 6; ++i) {
if (i != 0) count += Serial.print(":");
count += Serial.print((*(mac + i) & 0xF0) >> 4, 16);
count += Serial.print(*(mac + i) & 0x0F, 16);
}
}
void setup() {
Serial.begin(115200);
while (!Serial);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH); // just to show that the board is active
delay (1000);
Serial.print("Reading MAC address from hardware: ");
read_mac();
print_mac();
}
void loop() {
}
processor specific macros:
- Teensy 3.0: __MK20DX128__
- Teensy 3.1: __MK20DX256__
- Teensy LC: __MKL26Z64__
You would use it in conditional compilation:
Thanks for that compilation @MM - I've never come across it as such. Compile time makes sense since it won't cross compile&load anyhow.