Smart-Home am Beispiel der Präsenzerkennung im Raum Projektarbeit Lennart Heimbs, Johannes Krug, Sebastian Dohle und Kevin Holzschuh bei Prof. Oliver Hofmann SS2019
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ATSHA204.cpp 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. #include "Arduino.h"
  2. #include "ATSHA204.h"
  3. /* Local data and function prototypes */
  4. static uint8_t device_pin;
  5. #ifdef ARDUINO_ARCH_AVR
  6. static volatile uint8_t *device_port_DDR, *device_port_OUT, *device_port_IN;
  7. #endif
  8. static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc);
  9. static uint8_t sha204c_check_crc(uint8_t *response);
  10. static void swi_set_signal_pin(uint8_t is_high);
  11. static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer);
  12. static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer);
  13. static uint8_t swi_send_byte(uint8_t value);
  14. static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response);
  15. static uint8_t sha204c_resync(uint8_t size, uint8_t *response);
  16. static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
  17. uint8_t execution_delay, uint8_t execution_timeout);
  18. /* SWI bit bang functions */
  19. static void swi_set_signal_pin(uint8_t is_high)
  20. {
  21. SHA204_SET_OUTPUT();
  22. if (is_high) {
  23. SHA204_POUT_HIGH();
  24. } else {
  25. SHA204_POUT_LOW();
  26. }
  27. }
  28. static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer)
  29. {
  30. uint8_t i, bit_mask;
  31. // Disable interrupts while sending.
  32. noInterrupts(); //swi_disable_interrupts();
  33. // Set signal pin as output.
  34. SHA204_POUT_HIGH();
  35. SHA204_SET_OUTPUT();
  36. // Wait turn around time.
  37. delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY;
  38. for (i = 0; i < count; i++) {
  39. for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
  40. if (bit_mask & buffer[i]) {
  41. SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
  42. delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
  43. SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin;
  44. delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7;
  45. } else {
  46. // Send a zero bit.
  47. SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
  48. delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
  49. SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin;
  50. delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
  51. SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
  52. delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
  53. SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin;
  54. delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5;
  55. }
  56. }
  57. }
  58. interrupts(); //swi_enable_interrupts();
  59. return SWI_FUNCTION_RETCODE_SUCCESS;
  60. }
  61. static uint8_t swi_send_byte(uint8_t value)
  62. {
  63. return swi_send_bytes(1, &value);
  64. }
  65. static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
  66. {
  67. uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS;
  68. uint8_t i;
  69. uint8_t bit_mask;
  70. uint8_t pulse_count;
  71. uint8_t timeout_count;
  72. // Disable interrupts while receiving.
  73. noInterrupts(); //swi_disable_interrupts();
  74. // Configure signal pin as input.
  75. SHA204_SET_INPUT();
  76. // Receive bits and store in buffer.
  77. for (i = 0; i < count; i++) {
  78. for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
  79. pulse_count = 0;
  80. // Make sure that the variable below is big enough.
  81. // Change it to uint16_t if 255 is too small, but be aware that
  82. // the loop resolution decreases on an 8-bit controller in that case.
  83. timeout_count = START_PULSE_TIME_OUT;
  84. // Detect start bit.
  85. while (--timeout_count > 0) {
  86. // Wait for falling edge.
  87. if (SHA204_PIN_READ() == 0) {
  88. break;
  89. }
  90. }
  91. if (timeout_count == 0) {
  92. status = SWI_FUNCTION_RETCODE_TIMEOUT;
  93. break;
  94. }
  95. do {
  96. // Wait for rising edge.
  97. if (SHA204_PIN_READ() != 0) {
  98. // For an Atmel microcontroller this might be faster than "pulse_count++".
  99. pulse_count = 1;
  100. break;
  101. }
  102. } while (--timeout_count > 0);
  103. if (pulse_count == 0) {
  104. status = SWI_FUNCTION_RETCODE_TIMEOUT;
  105. break;
  106. }
  107. // Trying to measure the time of start bit and calculating the timeout
  108. // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU.
  109. // So let's just wait the maximum time for the falling edge of a zero bit
  110. // to arrive after we have detected the rising edge of the start bit.
  111. timeout_count = ZERO_PULSE_TIME_OUT;
  112. // Detect possible edge indicating zero bit.
  113. do {
  114. if (SHA204_PIN_READ() == 0) {
  115. // For an Atmel microcontroller this might be faster than "pulse_count++".
  116. pulse_count = 2;
  117. break;
  118. }
  119. } while (--timeout_count > 0);
  120. // Wait for rising edge of zero pulse before returning. Otherwise we might interpret
  121. // its rising edge as the next start pulse.
  122. if (pulse_count == 2) {
  123. do {
  124. if (SHA204_PIN_READ() != 0) {
  125. break;
  126. }
  127. } while (timeout_count-- > 0);
  128. }
  129. // Update byte at current buffer index.
  130. else {
  131. buffer[i] |= bit_mask; // received "one" bit
  132. }
  133. }
  134. if (status != SWI_FUNCTION_RETCODE_SUCCESS) {
  135. break;
  136. }
  137. }
  138. interrupts(); //swi_enable_interrupts();
  139. if (status == SWI_FUNCTION_RETCODE_TIMEOUT) {
  140. if (i > 0) {
  141. // Indicate that we timed out after having received at least one byte.
  142. status = SWI_FUNCTION_RETCODE_RX_FAIL;
  143. }
  144. }
  145. return status;
  146. }
  147. /* Physical functions */
  148. static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
  149. {
  150. uint8_t i;
  151. uint8_t ret_code;
  152. for (i = 0; i < size; i++) {
  153. response[i] = 0;
  154. }
  155. (void) swi_send_byte(SHA204_SWI_FLAG_TX);
  156. ret_code = swi_receive_bytes(size, response);
  157. if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
  158. uint8_t count_byte;
  159. count_byte = response[SHA204_BUFFER_POS_COUNT];
  160. if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
  161. return SHA204_INVALID_SIZE;
  162. }
  163. return SHA204_SUCCESS;
  164. }
  165. // Translate error so that the Communication layer
  166. // can distinguish between a real error or the
  167. // device being busy executing a command.
  168. if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) {
  169. return SHA204_RX_NO_RESPONSE;
  170. } else {
  171. return SHA204_RX_FAIL;
  172. }
  173. }
  174. /* Communication functions */
  175. static uint8_t sha204c_resync(uint8_t size, uint8_t *response)
  176. {
  177. // Try to re-synchronize without sending a Wake token
  178. // (step 1 of the re-synchronization process).
  179. delay(SHA204_SYNC_TIMEOUT);
  180. uint8_t ret_code = sha204p_receive_response(size, response);
  181. if (ret_code == SHA204_SUCCESS) {
  182. return ret_code;
  183. }
  184. // We lost communication. Send a Wake pulse and try
  185. // to receive a response (steps 2 and 3 of the
  186. // re-synchronization process).
  187. atsha204_sleep();
  188. ret_code = atsha204_wakeup(response);
  189. // Translate a return value of success into one
  190. // that indicates that the device had to be woken up
  191. // and might have lost its TempKey.
  192. return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code);
  193. }
  194. static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
  195. uint8_t execution_delay, uint8_t execution_timeout)
  196. {
  197. uint8_t ret_code = SHA204_FUNC_FAIL;
  198. uint8_t ret_code_resync;
  199. uint8_t n_retries_send;
  200. uint8_t n_retries_receive;
  201. uint8_t i;
  202. uint8_t status_byte;
  203. uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT];
  204. uint8_t count_minus_crc = count - SHA204_CRC_SIZE;
  205. uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT;
  206. volatile uint16_t timeout_countdown;
  207. // Append CRC.
  208. sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc);
  209. // Retry loop for sending a command and receiving a response.
  210. n_retries_send = SHA204_RETRY_COUNT + 1;
  211. while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) {
  212. // Send command.
  213. ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD);
  214. if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) {
  215. ret_code = SHA204_COMM_FAIL;
  216. } else {
  217. ret_code = swi_send_bytes(count, tx_buffer);
  218. }
  219. if (ret_code != SHA204_SUCCESS) {
  220. if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
  221. return ret_code; // The device seems to be dead in the water.
  222. } else {
  223. continue;
  224. }
  225. }
  226. // Wait minimum command execution time and then start polling for a response.
  227. delay(execution_delay);
  228. // Retry loop for receiving a response.
  229. n_retries_receive = SHA204_RETRY_COUNT + 1;
  230. while (n_retries_receive-- > 0) {
  231. // Reset response buffer.
  232. for (i = 0; i < rx_size; i++) {
  233. rx_buffer[i] = 0;
  234. }
  235. // Poll for response.
  236. timeout_countdown = execution_timeout_us;
  237. do {
  238. ret_code = sha204p_receive_response(rx_size, rx_buffer);
  239. timeout_countdown -= SHA204_RESPONSE_TIMEOUT;
  240. } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
  241. if (ret_code == SHA204_RX_NO_RESPONSE) {
  242. // We did not receive a response. Re-synchronize and send command again.
  243. if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
  244. // The device seems to be dead in the water.
  245. return ret_code;
  246. } else {
  247. break;
  248. }
  249. }
  250. // Check whether we received a valid response.
  251. if (ret_code == SHA204_INVALID_SIZE) {
  252. // We see 0xFF for the count when communication got out of sync.
  253. ret_code_resync = sha204c_resync(rx_size, rx_buffer);
  254. if (ret_code_resync == SHA204_SUCCESS) {
  255. // We did not have to wake up the device. Try receiving response again.
  256. continue;
  257. }
  258. if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) {
  259. // We could re-synchronize, but only after waking up the device.
  260. // Re-send command.
  261. break;
  262. } else {
  263. // We failed to re-synchronize.
  264. return ret_code;
  265. }
  266. }
  267. // We received a response of valid size.
  268. // Check the consistency of the response.
  269. ret_code = sha204c_check_crc(rx_buffer);
  270. if (ret_code == SHA204_SUCCESS) {
  271. // Received valid response.
  272. if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) {
  273. // Received non-status response. We are done.
  274. return ret_code;
  275. }
  276. // Received status response.
  277. status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS];
  278. // Translate the three possible device status error codes
  279. // into library return codes.
  280. if (status_byte == SHA204_STATUS_BYTE_PARSE) {
  281. return SHA204_PARSE_ERROR;
  282. }
  283. if (status_byte == SHA204_STATUS_BYTE_EXEC) {
  284. return SHA204_CMD_FAIL;
  285. }
  286. if (status_byte == SHA204_STATUS_BYTE_COMM) {
  287. // In case of the device status byte indicating a communication
  288. // error this function exits the retry loop for receiving a response
  289. // and enters the overall retry loop
  290. // (send command / receive response).
  291. ret_code = SHA204_STATUS_CRC;
  292. break;
  293. }
  294. // Received status response from CheckMAC, DeriveKey, GenDig,
  295. // Lock, Nonce, Pause, UpdateExtra, or Write command.
  296. return ret_code;
  297. }
  298. else {
  299. // Received response with incorrect CRC.
  300. ret_code_resync = sha204c_resync(rx_size, rx_buffer);
  301. if (ret_code_resync == SHA204_SUCCESS) {
  302. // We did not have to wake up the device. Try receiving response again.
  303. continue;
  304. }
  305. if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) {
  306. // We could re-synchronize, but only after waking up the device.
  307. // Re-send command.
  308. break;
  309. } else {
  310. // We failed to re-synchronize.
  311. return ret_code;
  312. }
  313. } // block end of check response consistency
  314. } // block end of receive retry loop
  315. } // block end of send and receive retry loop
  316. return ret_code;
  317. }
  318. /* CRC Calculator and Checker */
  319. static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc)
  320. {
  321. uint8_t counter;
  322. uint16_t crc_register = 0;
  323. uint16_t polynom = 0x8005;
  324. uint8_t shift_register;
  325. uint8_t data_bit, crc_bit;
  326. for (counter = 0; counter < length; counter++) {
  327. for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
  328. data_bit = (data[counter] & shift_register) ? 1 : 0;
  329. crc_bit = crc_register >> 15;
  330. // Shift CRC to the left by 1.
  331. crc_register <<= 1;
  332. if ((data_bit ^ crc_bit) != 0) {
  333. crc_register ^= polynom;
  334. }
  335. }
  336. }
  337. crc[0] = (uint8_t) (crc_register & 0x00FF);
  338. crc[1] = (uint8_t) (crc_register >> 8);
  339. }
  340. static uint8_t sha204c_check_crc(uint8_t *response)
  341. {
  342. uint8_t crc[SHA204_CRC_SIZE];
  343. uint8_t count = response[SHA204_BUFFER_POS_COUNT];
  344. count -= SHA204_CRC_SIZE;
  345. sha204c_calculate_crc(count, response, crc);
  346. return (crc[0] == response[count] && crc[1] == response[count + 1])
  347. ? SHA204_SUCCESS : SHA204_BAD_CRC;
  348. }
  349. /* Public functions */
  350. void atsha204_init(uint8_t pin)
  351. {
  352. #if defined(ARDUINO_ARCH_AVR)
  353. device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin
  354. uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers
  355. // Point to data direction register port of pin
  356. device_port_DDR = portModeRegister(port);
  357. // Point to output register of pin
  358. device_port_OUT = portOutputRegister(port);
  359. // Point to input register of pin
  360. device_port_IN = portInputRegister(port);
  361. #else
  362. device_pin = pin;
  363. #endif
  364. }
  365. void atsha204_idle(void)
  366. {
  367. swi_send_byte(SHA204_SWI_FLAG_IDLE);
  368. }
  369. void atsha204_sleep(void)
  370. {
  371. swi_send_byte(SHA204_SWI_FLAG_SLEEP);
  372. }
  373. uint8_t atsha204_wakeup(uint8_t *response)
  374. {
  375. swi_set_signal_pin(0);
  376. delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH);
  377. swi_set_signal_pin(1);
  378. delay(SHA204_WAKEUP_DELAY);
  379. uint8_t ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
  380. if (ret_code != SHA204_SUCCESS) {
  381. return ret_code;
  382. }
  383. // Verify status response.
  384. if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) {
  385. ret_code = SHA204_INVALID_SIZE;
  386. } else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) {
  387. ret_code = SHA204_COMM_FAIL;
  388. } else {
  389. if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
  390. || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) {
  391. ret_code = SHA204_BAD_CRC;
  392. }
  393. }
  394. if (ret_code != SHA204_SUCCESS) {
  395. delay(SHA204_COMMAND_EXEC_MAX);
  396. }
  397. return ret_code;
  398. }
  399. uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
  400. uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size,
  401. uint8_t *rx_buffer)
  402. {
  403. uint8_t poll_delay, poll_timeout, response_size;
  404. uint8_t *p_buffer;
  405. uint8_t len;
  406. (void)tx_size;
  407. // Supply delays and response size.
  408. switch (op_code) {
  409. case SHA204_GENDIG:
  410. poll_delay = GENDIG_DELAY;
  411. poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY;
  412. response_size = GENDIG_RSP_SIZE;
  413. break;
  414. case SHA204_HMAC:
  415. poll_delay = HMAC_DELAY;
  416. poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY;
  417. response_size = HMAC_RSP_SIZE;
  418. break;
  419. case SHA204_NONCE:
  420. poll_delay = NONCE_DELAY;
  421. poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY;
  422. response_size = param1 == NONCE_MODE_PASSTHROUGH
  423. ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG;
  424. break;
  425. case SHA204_RANDOM:
  426. poll_delay = RANDOM_DELAY;
  427. poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY;
  428. response_size = RANDOM_RSP_SIZE;
  429. break;
  430. case SHA204_SHA:
  431. poll_delay = SHA_DELAY;
  432. poll_timeout = SHA_EXEC_MAX - SHA_DELAY;
  433. response_size = param1 == SHA_INIT
  434. ? SHA_RSP_SIZE_SHORT : SHA_RSP_SIZE_LONG;
  435. break;
  436. case SHA204_WRITE:
  437. poll_delay = WRITE_DELAY;
  438. poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY;
  439. response_size = WRITE_RSP_SIZE;
  440. break;
  441. default:
  442. poll_delay = 0;
  443. poll_timeout = SHA204_COMMAND_EXEC_MAX;
  444. response_size = rx_size;
  445. }
  446. // Assemble command.
  447. len = datalen1 + SHA204_CMD_SIZE_MIN;
  448. p_buffer = tx_buffer;
  449. *p_buffer++ = len;
  450. *p_buffer++ = op_code;
  451. *p_buffer++ = param1;
  452. *p_buffer++ = param2 & 0xFF;
  453. *p_buffer++ = param2 >> 8;
  454. if (datalen1 > 0) {
  455. memcpy(p_buffer, data1, datalen1);
  456. p_buffer += datalen1;
  457. }
  458. sha204c_calculate_crc(len - SHA204_CRC_SIZE, tx_buffer, p_buffer);
  459. // Send command and receive response.
  460. return sha204c_send_and_receive(&tx_buffer[0], response_size,
  461. &rx_buffer[0], poll_delay, poll_timeout);
  462. }
  463. uint8_t atsha204_getSerialNumber(uint8_t * response)
  464. {
  465. uint8_t readCommand[READ_COUNT];
  466. uint8_t readResponse[READ_4_RSP_SIZE];
  467. /* read from bytes 0->3 of config zone */
  468. uint8_t returnCode = atsha204_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03);
  469. if (!returnCode) {
  470. for (int i=0; i<4; i++) {// store bytes 0-3 into respones array
  471. response[i] = readResponse[SHA204_BUFFER_POS_DATA+i];
  472. }
  473. /* read from bytes 8->11 of config zone */
  474. returnCode = atsha204_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47);
  475. for (int i=4; i<8; i++) {// store bytes 4-7 of SN into response array
  476. response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)];
  477. }
  478. if (!returnCode) {
  479. /* Finally if last two reads were successful, read byte 8 of the SN */
  480. returnCode = atsha204_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8);
  481. response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE
  482. }
  483. }
  484. return returnCode;
  485. }
  486. uint8_t atsha204_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address)
  487. {
  488. uint8_t rx_size;
  489. address >>= 2;
  490. tx_buffer[SHA204_COUNT_IDX] = READ_COUNT;
  491. tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ;
  492. tx_buffer[READ_ZONE_IDX] = zone;
  493. tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK);
  494. tx_buffer[READ_ADDR_IDX + 1] = 0;
  495. rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE;
  496. return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY,
  497. READ_EXEC_MAX - READ_DELAY);
  498. }