diff --git a/reefnet_sensusultra.c b/reefnet_sensusultra.c index 8e70f06..e12b446 100644 --- a/reefnet_sensusultra.c +++ b/reefnet_sensusultra.c @@ -153,6 +153,18 @@ reefnet_sensusultra_checksum (const unsigned char *data, unsigned int size) } +static int +reefnet_sensusultra_isempty (const unsigned char *data, unsigned int size) +{ + for (unsigned int i = 0; i < size; ++i) { + if (data[i] != 0xFF) + return 0; + } + + return 1; +} + + static int reefnet_sensusultra_send_uchar (sensusultra *device, unsigned char value) { @@ -517,6 +529,100 @@ reefnet_sensusultra_sense (sensusultra *device, unsigned char *data, unsigned in } +int +reefnet_sensusultra_read_dives (sensusultra *device, dive_callback_t callback, void *userdata) +{ + if (device == NULL) + return REEFNET_ERROR; + + unsigned char *data = malloc (REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE * sizeof (unsigned char)); + if (data == NULL) { + WARNING ("Memory allocation error."); + return REEFNET_ERROR_MEMORY; + } + + const unsigned char header[4] = {0x00, 0x00, 0x00, 0x00}; + const unsigned char footer[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + + // Initialize the state for the parsing code. + unsigned int previous = REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE; + unsigned int current = (REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE >= 4 ? + REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE - 4 : 0); + + // Send the instruction code to the device. + int rc = reefnet_sensusultra_send_ushort (device, 0xB421); + if (rc != REEFNET_SUCCESS) { + free (data); + return rc; + } + + unsigned int nbytes = 0; + unsigned int npages = 0; + while (nbytes < REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE) { + // Receive the packet. + unsigned int index = REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE - + nbytes - REEFNET_SENSUSULTRA_PACKET_SIZE; + rc = reefnet_sensusultra_page (device, data + index, REEFNET_SENSUSULTRA_PACKET_SIZE, npages); + if (rc != REEFNET_SUCCESS) { + free (data); + return rc; + } + + // Abort the transfer if the page contains no useful data. + if (reefnet_sensusultra_isempty (data + index, REEFNET_SENSUSULTRA_PACKET_SIZE)) + break; + + // Search the page data for a start marker. + while (current > index) { + current--; + if (memcmp (data + current, header, sizeof (header)) == 0) { + // Once a start marker is found, start searching + // for the corresponding stop marker. The search is + // now limited to the start of the previous dive. + int found = 0; + unsigned int offset = current + 16; // Skip non-sample data. + while (offset + 4 <= previous) { + if (memcmp (data + offset, footer, sizeof (footer)) == 0) { + found = 1; + break; + } else { + offset++; + } + } + + // Report an error if no stop marker was found. + if (!found) { + WARNING ("No stop marker present."); + free (data); + return REEFNET_ERROR; + } + + if (callback) + callback (data + current, offset + 4 - current, userdata); + + // Prepare for the next dive. + previous = current; + current = (current >= 4 ? current - 4 : 0); + } + } + + // Accept the packet. + rc = reefnet_sensusultra_send_uchar (device, ACCEPT); + if (rc != REEFNET_SUCCESS) { + free (data); + return rc; + } + + nbytes += REEFNET_SENSUSULTRA_PACKET_SIZE; + npages++; + } + + free (data); + + return REEFNET_SUCCESS; +} + + int reefnet_sensusultra_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata) { @@ -536,9 +642,6 @@ reefnet_sensusultra_extract_dives (const unsigned char data[], unsigned int size unsigned int offset = current + 16; // Skip non-sample data. while (offset + 4 <= previous) { if (memcmp (data + offset, footer, sizeof (footer)) == 0) { - if (callback) - callback (data + current, offset + 4 - current, userdata); - found = 1; break; } else { @@ -547,8 +650,13 @@ reefnet_sensusultra_extract_dives (const unsigned char data[], unsigned int size } // Report an error if no stop marker was found. - if (!found) + if (!found) { + WARNING ("No stop marker present."); return REEFNET_ERROR; + } + + if (callback) + callback (data + current, offset + 4 - current, userdata); // Prepare for the next dive. previous = current; diff --git a/reefnet_sensusultra.h b/reefnet_sensusultra.h index 1784238..882a8a6 100644 --- a/reefnet_sensusultra.h +++ b/reefnet_sensusultra.h @@ -34,6 +34,8 @@ int reefnet_sensusultra_write_averaging (sensusultra *device, unsigned int value int reefnet_sensusultra_sense (sensusultra *device, unsigned char *data, unsigned int size); +int reefnet_sensusultra_read_dives (sensusultra *device, dive_callback_t callback, void *userdata); + int reefnet_sensusultra_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); #ifdef __cplusplus diff --git a/reefnet_sensusultra_test.c b/reefnet_sensusultra_test.c index 1d9bf27..5591836 100644 --- a/reefnet_sensusultra_test.c +++ b/reefnet_sensusultra_test.c @@ -10,6 +10,50 @@ } +int test_dump_memory_dives (const char* name, const char* filename) +{ + sensusultra *device = NULL; + unsigned char handshake[REEFNET_SENSUSULTRA_HANDSHAKE_SIZE] = {0}; + + message ("reefnet_sensusultra_open\n"); + int rc = reefnet_sensusultra_open (&device, name); + if (rc != REEFNET_SUCCESS) { + WARNING ("Error opening serial port."); + return rc; + } + + message ("reefnet_sensusultra_handshake\n"); + rc = reefnet_sensusultra_handshake (device, handshake, sizeof (handshake)); + if (rc != REEFNET_SUCCESS) { + WARNING ("Cannot read handshake."); + reefnet_sensusultra_close (device); + return rc; + } + + time_t now = time (NULL); + unsigned char datetime[21] = {0}; + strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now)); + message ("time=%lu (%s)\n", (unsigned long)now, datetime); + + message ("reefnet_sensusultra_read_dives\n"); + rc = reefnet_sensusultra_read_dives (device, NULL, NULL); + if (rc != REEFNET_SUCCESS) { + WARNING ("Cannot read dives."); + reefnet_sensusultra_close (device); + return rc; + } + + message ("reefnet_sensusultra_close\n"); + rc = reefnet_sensusultra_close (device); + if (rc != REEFNET_SUCCESS) { + WARNING ("Cannot close device."); + return rc; + } + + return REEFNET_SUCCESS; +} + + int test_dump_memory_data (const char* name, const char* filename) { sensusultra *device = NULL; @@ -153,11 +197,13 @@ int main(int argc, char *argv[]) int a = test_dump_memory_data (name, "SENSUSULTRA_DATA.DMP"); int b = test_dump_memory_user (name, "SENSUSULTRA_USER.DMP"); + int c = test_dump_memory_dives (name, "SENSUSULTRA_DIVES.DMP"); message ("SUMMARY\n"); message ("-------\n"); message ("test_dump_memory_data: %s\n", errmsg (a)); message ("test_dump_memory_user: %s\n", errmsg (b)); + message ("test_dump_memory_dives: %s\n", errmsg (c)); message_set_logfile (NULL);