application: implement DS2432 (the reading part)

This commit is contained in:
King Kévin 2017-08-07 23:20:45 +02:00
parent f37b8309bb
commit 73ac1db354
1 changed files with 322 additions and 40 deletions

View File

@ -12,7 +12,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** STM32F1 application example
/** STM32F1 Maxim DS2432 (1k-Bit Protected 1-Wire EEPROM with SHA-1 Engine) implementation
* @file application.c
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016-2017
@ -167,6 +167,138 @@ error:
return;
}
/** static table used for the table_driven implementation
* Generated by pycrc v0.9, https://pycrc.org
* using the configuration:
* Width = 16
* Poly = 0x8005
* Xor_In = 0x0000
* ReflectIn = True
* Xor_Out = 0xffff
* ReflectOut = True
* Algorithm = table-driven
*/
static const uint16_t crc_table[256] = {
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
/** update the crc value with new data.
* @param crc The current crc value.
* @param data Pointer to a buffer of @a data_len bytes.
* @param data_len Number of bytes in the @a data buffer.
* @return The updated crc value.
*/
static uint16_t crc16_update(uint16_t crc, const uint8_t *data, size_t data_len)
{
const unsigned char *d = (const unsigned char *)data;
unsigned int tbl_idx;
while (data_len--) {
tbl_idx = (crc ^ *d) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff;
d++;
}
return crc & 0xffff;
}
/** SHA-1 input data to calculate MAC for 'Read Authenticated Page' function command */
static uint32_t m[16] = {0};
/** intermediate calculation */
uint32_t wt[80] = {0};
/** DS2432 SHA-1 S function, rotating to the left
* @param[in] x value to rotate by @a n to the left
* @param[in] n rotate @a x by n to the left
* @return @a x rotated ny @a n to the left
*/
static uint32_t s_left(uint32_t x, uint8_t n) {
return (((x)<<(n)) | ((x)>>(32-(n))));
}
/** DS2432 SHA-1 F function
* @param[in] t time/round
* @param[in] b B value
* @param[in] c C value
* @param[in] d D value
* @return result of the F function
*/
static uint32_t f(uint8_t t, uint32_t b, uint32_t c, uint32_t d) {
if (t<20) {
return (b&c)|((~b)&d);
} else if (t<40) {
return b^c^d;
} else if (t<60) {
return (b&c)|(b&d)|(c&d);
} else if (t<80) {
return b^c^d;
} else { // this should not happen
return 0;
}
}
/** DS2432 SHA-1 K function
* @param[in] t time/round
* @return result of the K function
*/
static uint32_t k(uint8_t t) {
if (t<20) {
return 0x5A827999;
} else if (t<40) {
return 0x6ED9EBA1;
} else if (t<60) {
return 0x8F1BBCDC;
} else if (t<80) {
return 0xCA62C1D6;
} else { // this should not happen
return 0;
}
}
/** DS2432 SHA-1 W function
* @param[in] t time/round
* @note uses @a m or previously calculated @a wt values
* @return result of the W function
*/
static uint32_t w(uint8_t t) {
if (t<16) {
return m[t];
} else {
return s_left(wt[t-3]^wt[t-8]^wt[t-14]^wt[t-16], 1);
}
}
/** program entry point
* this is the firmware function started by the micro-controller
*/
@ -175,7 +307,6 @@ void main(void)
{
rcc_clock_setup_in_hse_8mhz_out_72mhz(); // use 8 MHz high speed external clock to generate 72 MHz internal clock
#if DEBUG
// enable functionalities for easier debug
DBGMCU_CR |= DBGMCU_CR_IWDG_STOP; // stop independent watchdog counter when code is halted
@ -192,7 +323,7 @@ void main(void)
board_setup(); // setup board
usart_setup(); // setup USART (for printing)
usb_cdcacm_setup(); // setup USB CDC ACM (for printing)
printf("welcome to the CuVoodoo STM32F1 1-Wire salve example application\n"); // print welcome message
printf("welcome to the CuVoodoo STM32F1 DS2432 implementation (1k-Bit Protected 1-Wire EEPROM with SHA-1 Engine)\n"); // print welcome message
#if !(DEBUG)
// show watchdog information
@ -217,43 +348,66 @@ void main(void)
time_tm = localtime(&time_rtc); // convert time
printf("date: %d-%02d-%02d %02d:%02d:%02d\n", 1900+time_tm->tm_year, time_tm->tm_mon+1, time_tm->tm_mday, time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec);
uint8_t ds2432_eeprom[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97}; /**< EEPROM content (including secret) */
uint8_t ds2432_scratchpad[8]; /**< scratchpad data */
uint8_t ds2432_address[2+1] = {0, 0, 0x5f}; /**< address registers: target address and E/S */
uint8_t ds2432_buffer[2+1+8+2]; /**< buffer to save command code target address, data status, scratchpad, and CRC */
const uint8_t ds2432_padding = 0xff; /**< padding byte used in Read Authenticated Page command */
uint16_t ds2432_crc = 0; // CRC-16 used in 1-Wire DS2432 communication
uint8_t ds2432_mac[20] = {0}; // buffer for the MAC
enum {
DS2432_STATE_IDLE,
DS2432_STATE_WRITE_SCRATCHPAD_DATA,
DS2432_STATE_WRITE_SCRATCHPAD_CRC,
DS2432_STATE_READ_SCRATCHPAD_ADDRESS,
DS2432_STATE_READ_SCRATCHPAD_DATA,
DS2432_STATE_READ_SCRATCHPAD_CRC,
DS2432_STATE_READ_AUTHENTICATED_PAGE_ADDRESS,
DS2432_STATE_READ_AUTHENTICATED_PAGE_DATA,
DS2432_STATE_READ_AUTHENTICATED_PAGE_PADDING,
DS2432_STATE_READ_AUTHENTICATED_PAGE_CRC,
DS2432_STATE_READ_AUTHENTICATED_PAGE_MAC,
DS2432_STATE_READ_AUTHENTICATED_PAGE_MACCRC,
DS2432_STATE_READ_MEMORY_ADDRESS,
DS2432_STATE_READ_MEMORY_DATA,
} ds2432_state = DS2432_STATE_IDLE; /**< current state */
printf("setup 1-Wire bus: ");
onewire_slave_setup(0xb3, 0x0047414feedb); // setup 1-Wire peripheral to act as slave
onewire_slave_setup(ds2432_eeprom[0x90], ((uint64_t)ds2432_eeprom[0x91]<<0)+((uint64_t)ds2432_eeprom[0x91]<<0)+((uint64_t)ds2432_eeprom[0x92]<<8)+((uint64_t)ds2432_eeprom[0x93]<<16)+((uint64_t)ds2432_eeprom[0x94]<<24)+((uint64_t)ds2432_eeprom[0x95]<<32)+((uint64_t)ds2432_eeprom[0x96]<<40)); // setup 1-Wire peripheral to act as slave
printf("OK\n");
uint8_t onewire_slave_data[2] = {0}; // data to be transferred
// main loop
printf("command input: ready\n");
bool action = false; // if an action has been performed don't go to sleep
button_flag = false; // reset button flag
char c = '\0'; // to store received character
char ch = '\0'; // to store received character
bool char_flag = false; // a new character has been received
while (true) { // infinite loop
iwdg_reset(); // kick the dog
while (usart_received) { // data received over UART
action = true; // action has been performed
led_toggle(); // toggle LED
c = usart_getchar(); // store receive character
ch = usart_getchar(); // store receive character
char_flag = true; // notify character has been received
}
while (usb_cdcacm_received) { // data received over USB
action = true; // action has been performed
led_toggle(); // toggle LED
c = usb_cdcacm_getchar(); // store receive character
ch = usb_cdcacm_getchar(); // store receive character
char_flag = true; // notify character has been received
}
while (char_flag) { // user data received
char_flag = false; // reset flag
action = true; // action has been performed
printf("%c",c); // echo receive character
if (c=='\r' || c=='\n') { // end of command received
printf("%c",ch); // echo receive character
if (ch=='\r' || ch=='\n') { // end of command received
if (command_i>0) { // there is a command to process
command[command_i] = 0; // end string
command_i = 0; // prepare for next command
process_command(command); // process user command
}
} else { // user command input
command[command_i] = c; // save command input
command[command_i] = ch; // save command input
if (command_i<LENGTH(command)-2) { // verify if there is place to save next character
command_i++; // save next character
}
@ -277,42 +431,170 @@ void main(void)
printf("time: %02d:%02d:%02d\n", time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec);
}
}
while (onewire_slave_function_code_received) {
while (onewire_slave_function_code_received) { // we received a function command code over the 1-Wire bus
onewire_slave_function_code_received = false; // reset flag
action = true; // action has been performed
printf("1-Wire function command received: 0x%02x\n", onewire_slave_function_code);
if (0x55==onewire_slave_function_code) { // master will write data
onewire_slave_function_read(onewire_slave_data, LENGTH(onewire_slave_data)*8);
} else if (0xf0==onewire_slave_function_code) { // master will read data
onewire_slave_function_write(onewire_slave_data, LENGTH(onewire_slave_data)*8);
} else if (0x23==onewire_slave_function_code) { // master will first write data, then read
onewire_slave_function_read(onewire_slave_data, LENGTH(onewire_slave_data)*8);
switch (onewire_slave_function_code) {
case 0x0f: // Write Scratchpad
onewire_slave_function_read(ds2432_buffer, 2+8); // read target address and scratchpad
ds2432_state = DS2432_STATE_WRITE_SCRATCHPAD_DATA; // update state
break;
case 0xaa: // Read Scratchpad
onewire_slave_function_write(ds2432_address, LENGTH(ds2432_address)); // send address registers
ds2432_state = DS2432_STATE_READ_SCRATCHPAD_ADDRESS; // update state
break;
case 0xa5: // Read Authenticated Page
onewire_slave_function_read(ds2432_buffer, 2); // read target address
ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_ADDRESS; // update state
break;
case 0xf0: // Read Memory
onewire_slave_function_read(ds2432_buffer, 2); // read target address
ds2432_state = DS2432_STATE_READ_MEMORY_ADDRESS; // update state
break;
default: // unknown function command code
ds2432_state = DS2432_STATE_IDLE; // return to idle state
break;
}
printf("1-Wire function command received: 0x%02x\n", onewire_slave_function_code);
}
while (onewire_slave_transfer_complete) {
while (onewire_slave_transfer_complete) { // the current data transfer completed
onewire_slave_transfer_complete = false; // reset flag
action = true; // action has been performed
printf("1-Wire transfer complete\n");
if (0x55==onewire_slave_function_code) { // master wrote data
printf("data read: ");
for (uint8_t i=0; i<LENGTH(onewire_slave_data); i++) {
printf("0x%02x ", onewire_slave_data[i]);
}
printf("\n");
} else if (0xf0==onewire_slave_function_code) { // master read data
printf("data written: ");
for (uint8_t i=0; i<LENGTH(onewire_slave_data); i++) {
printf("0x%02x ", onewire_slave_data[i]);
}
printf("\n");
} else if (0x23==onewire_slave_function_code) { // master write then read data
printf("data read/written: ");
for (uint8_t i=0; i<LENGTH(onewire_slave_data); i++) {
printf("0x%02x ", onewire_slave_data[i]);
}
printf("\n");
onewire_slave_function_write(onewire_slave_data, LENGTH(onewire_slave_data)*8);
switch (ds2432_state) {
case DS2432_STATE_WRITE_SCRATCHPAD_DATA:
ds2432_crc = crc16_update(0, (const uint8_t *)&onewire_slave_function_code, 1); // initialize CRC with function code
ds2432_crc = crc16_update(ds2432_crc, ds2432_buffer, (2+8)); // calculate CRC
ds2432_crc ^= 0xffff; // invert CRC
ds2432_buffer[2+1+8+0] = ds2432_crc>>0; // save CRC (LSB first)
ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last)
onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // write CRC
ds2432_state = DS2432_STATE_WRITE_SCRATCHPAD_CRC; // update state
ds2432_address[0] = ds2432_buffer[0]&0xf8; // save target address
ds2432_address[1] = ds2432_buffer[1]; // save target address
ds2432_address[2] = 0x5f; // reset state
for (uint8_t i=0; i<LENGTH(ds2432_scratchpad) && i<LENGTH(ds2432_buffer)-2; i++) {
ds2432_scratchpad[i] = ds2432_buffer[i+2]; // save scratchpad
}
break;
case DS2432_STATE_READ_SCRATCHPAD_ADDRESS:
onewire_slave_function_write(ds2432_scratchpad, LENGTH(ds2432_scratchpad)); // send scratchpad
ds2432_state = DS2432_STATE_READ_SCRATCHPAD_DATA; // update state
ds2432_crc = crc16_update(0, (const uint8_t *)&onewire_slave_function_code, 1); // initialize CRC with function code
ds2432_crc = crc16_update(ds2432_crc, ds2432_address, LENGTH(ds2432_address)); // calculate CRC
ds2432_crc = crc16_update(ds2432_crc, ds2432_scratchpad, LENGTH(ds2432_scratchpad)); // calculate CRC
ds2432_crc ^= 0xffff; // invert CRC
ds2432_buffer[2+1+8+0] = ds2432_crc>>0; // save CRC (LSB first)
ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last)
break;
case DS2432_STATE_READ_SCRATCHPAD_DATA: // scratchpad data transfer complete, send CRC
onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // send CRC
ds2432_state = DS2432_STATE_WRITE_SCRATCHPAD_CRC; // update state
break;
case DS2432_STATE_READ_AUTHENTICATED_PAGE_ADDRESS: // target address transfer completed, send data
if (0==ds2432_buffer[1] && ds2432_buffer[0]<0x80) { // target address matches to memory page
onewire_slave_function_write(&ds2432_eeprom[ds2432_buffer[0]], 0x20-(ds2432_buffer[0]&0x1f)); // send memory data until end of page
ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_DATA; // update state
} else { // target address is out of range
ds2432_state = DS2432_STATE_IDLE; // return to idle state
}
break;
case DS2432_STATE_READ_AUTHENTICATED_PAGE_DATA: // memory page data transfer completed, send padding byte
onewire_slave_function_write((uint8_t *)&ds2432_padding, 1); // send padding byte
ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_PADDING; // update state
ds2432_crc = crc16_update(0, (const uint8_t *)&onewire_slave_function_code, 1); // initialize CRC with function code
ds2432_crc = crc16_update(ds2432_crc, ds2432_buffer, 2); // update CRC with target address
ds2432_crc = crc16_update(ds2432_crc, &ds2432_eeprom[ds2432_buffer[0]], 0x20-(ds2432_buffer[0]&0x1f)); // update CRC with data
ds2432_crc = crc16_update(ds2432_crc, &ds2432_padding, 1); // update CRC with padding
ds2432_crc ^= 0xffff; // invert CRC
ds2432_buffer[2+1+8+0] = ds2432_crc>>0; // save CRC (LSB first)
ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last)
break;
case DS2432_STATE_READ_AUTHENTICATED_PAGE_PADDING: // padding byte transfer complete, send CRC
onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // send CRC
ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_CRC; // update state
// calculate MAC
{
ds2432_buffer[0] &= 0xe0; // set target address to start of page
// initialize SHA-1 input data (see table 4)
m[0] = (ds2432_eeprom[0x80+0]<<24)+(ds2432_eeprom[0x80+1]<<16)+(ds2432_eeprom[0x80+2]<<8)+(ds2432_eeprom[0x80+3]<<0); // copy secret
for (uint8_t i=0; i<8; i++) { // copy page
m[1+i] = (ds2432_eeprom[ds2432_buffer[0]+i*4+0]<<24)+(ds2432_eeprom[ds2432_buffer[0]+i*4+1]<<16)+(ds2432_eeprom[ds2432_buffer[0]+i*4+2]<<8)+(ds2432_eeprom[ds2432_buffer[0]+i*4+3]<<0);
}
m[9] = (0xff<<24)+(0xff<<16)+(0xff<<8)+(0xff<<0); // filling bytes
m[10] = ((0x40+(ds2432_buffer[0]>>5))<<24)+(ds2432_eeprom[0x90+0]<<16)+(ds2432_eeprom[0x90+1]<<8)+(ds2432_eeprom[0x90+2]<<0); // copy target and ROM code
m[11] = (ds2432_eeprom[0x90+3]<<24)+(ds2432_eeprom[0x90+4]<<16)+(ds2432_eeprom[0x90+5]<<8)+(ds2432_eeprom[0x90+6]<<0); // copy ROM code
m[12] = (ds2432_eeprom[0x80+4]<<24)+(ds2432_eeprom[0x80+5]<<16)+(ds2432_eeprom[0x80+6]<<8)+(ds2432_eeprom[0x80+7]<<0); // copy rest of secret
m[13] = (ds2432_scratchpad[4]<<24)+(ds2432_scratchpad[5]<<16)+(ds2432_scratchpad[6]<<8)+(0x80<<0); // copy challenge
m[14] = (0x00<<24)+(0x00<<16)+(0x00<<8)+(0x00<<0);
m[15] = (0x00<<24)+(0x00<<16)+(0x01<<8)+(0xb8<<0);
// initialize variables
uint32_t a = 0x67452301;
uint32_t b = 0xEFCDAB89;
uint32_t c = 0x98BADCFE;
uint32_t d = 0x10325476;
uint32_t e = 0xC3D2E1F0;
// loop through computation
for (uint8_t t=0; t<80; t++) {
wt[t] = w(t);
uint32_t tmp = s_left(a, 5)+f(t,b,c,d)+wt[t]+k(t)+e;
e = d;
d = c;
c = s_left(b, 30);
b = a;
a = tmp;
}
// copy result
ds2432_mac[0] = e>>0;
ds2432_mac[1] = e>>8;
ds2432_mac[2] = e>>16;
ds2432_mac[3] = e>>24;
ds2432_mac[4] = d>>0;
ds2432_mac[5] = d>>8;
ds2432_mac[6] = d>>16;
ds2432_mac[7] = d>>24;
ds2432_mac[8] = c>>0;
ds2432_mac[9] = c>>8;
ds2432_mac[10] = c>>16;
ds2432_mac[11] = c>>24;
ds2432_mac[12] = b>>0;
ds2432_mac[13] = b>>8;
ds2432_mac[14] = b>>16;
ds2432_mac[15] = b>>24;
ds2432_mac[16] = a>>0;
ds2432_mac[17] = a>>8;
ds2432_mac[18] = a>>16;
ds2432_mac[19] = a>>24;
}
break;
case DS2432_STATE_READ_AUTHENTICATED_PAGE_CRC: // CRC transfer completed, send MAC
onewire_slave_function_write(ds2432_mac, LENGTH(ds2432_mac)); // send CRC
ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_MAC; // update state
ds2432_crc = crc16_update(0, ds2432_mac, LENGTH(ds2432_mac)); // calculate CRC for MAC
ds2432_crc ^= 0xffff; // invert CRC
ds2432_buffer[2+1+8+0] = ds2432_crc>>0; // save CRC (LSB first)
ds2432_buffer[2+1+8+1] = ds2432_crc>>8; // save CRC (MSB last)
break;
case DS2432_STATE_READ_AUTHENTICATED_PAGE_MAC: // padding byte transfer complete, send CRC
onewire_slave_function_write(&ds2432_buffer[2+1+8+0], 2); // send CRC
ds2432_state = DS2432_STATE_READ_AUTHENTICATED_PAGE_MACCRC; // update state
break;
case DS2432_STATE_READ_MEMORY_ADDRESS:
if (0==ds2432_buffer[1] && ds2432_buffer[0]<0x97) { // target address is in EEPROM range
onewire_slave_function_write(&ds2432_eeprom[ds2432_buffer[0]], LENGTH(ds2432_eeprom)-ds2432_buffer[0]); // send memory data until end of page
ds2432_state = DS2432_STATE_READ_MEMORY_DATA; // update state
} else { // target address is out of range
ds2432_state = DS2432_STATE_IDLE; // return to idle state
}
break;
default: // unknown or end state
ds2432_state = DS2432_STATE_IDLE; // return to idle state
break;
}
printf("1-Wire transfer complete\n");
}
if (action) { // go to sleep if nothing had to be done, else recheck for activity
action = false;