/* parse_sp2.cpp Program to parse sp2 files produced by Yokogawa NR800 Near Infrared Analyzer. The command line options are: The file 'filename' is expected to be a sp2 file. This program is refered to at http://www.iwriteiam.nl/NR800_SP2.html Copyright (C) 2009 Frans Faase This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. GNU General Public License: http://www.iwriteiam.nl/GNU.txt */ #include typedef unsigned char byte; float ui2float(unsigned int i) { union { unsigned int i; float f; } v; v.i = i; return v.f; } float getFloat(byte *buffer, int i) { unsigned int v = (buffer[i] << 24) | (buffer[i+1] << 16) | (buffer[i+2] << 8) | buffer[i+3]; return ui2float(v); } double getDouble(byte *buffer, int i) { return *(double*)(buffer + i); } unsigned int getWord(byte *buffer, int i) { return (buffer[i] << 8) | buffer[i+1]; } unsigned int getLong(byte *buffer, int i) { return (buffer[i] << 24) | (buffer[i+1] << 16) | (buffer[i+2] << 8) | buffer[i+3]; } void dump(byte* buffer, int from, int till) { for (int i = from; i < till; i++) { printf("[%d] dump ", i); for (int j = 7; j >= 0; j--) printf("%d", 1 & (buffer[i] >> j)); printf(" %02x %3d ", buffer[i], buffer[i]); printf("%6d ", getWord(buffer, i)); printf("%ld ", getLong(buffer, i)); if (' ' < buffer[i] && buffer[i] < 127) printf("%c ", buffer[i]); else printf(" "); printf("%e ", getFloat(buffer, i)); printf("%le\n", getDouble(buffer, i)); } } void zeros(byte* buffer, int from, int till) { printf("[%d-%d] %d zeros", from, till-1, till-from); for (int i = from; i < till; i++) { if (buffer[i] != 0) printf(" buffer[%d]=%d", i, buffer[i]); } printf("\n"); } int main(int argc, char* argv) { if (argc < 2) { printf("%s \n", argv[0]); return 0; } FILE *f = fopen(argv[1], "rb"); if (f == 0) { printf("Cannot open file '%s'\n", argv[1]); return 0; } byte buffer[40000]; size_t len = fread(buffer, 1, 40000, f); printf("len = %d\n", len); printf("[0-3] %ld\n", getLong(buffer, 0)); printf("[4-9] Date %04d/%02d/%02d\n", getWord(buffer, 4), getWord(buffer, 6), getWord(buffer, 8)); printf("[10-15] Time %02d:%02d:%02d\n", getWord(buffer, 10), getWord(buffer, 12), getWord(buffer, 14)); printf("[16-27] "); for (int i = 16; i < 28; i++) printf("%c", buffer[i]); printf("\n"); zeros(buffer, 28, 80); printf("[80-83] ? %ld\n", getLong(buffer, 80)); printf("[84-87] Average Number %d\n", getLong(buffer, 84)); printf("[88-89] ? %d\n", getWord(buffer, 88)); printf("[90-91] ? %d\n", getWord(buffer, 90)); printf("[92-95] AD Gain S %d\n", getLong(buffer, 92)); printf("[96-99] AD Gain R %d\n", getLong(buffer, 96)); printf("[100-103] IV Gain S %d\n", getLong(buffer, 100)); printf("[104-107] IV Gain R %d\n", getLong(buffer, 104)); printf("[108-111] Coefficient for Wave Number Correction %f\n", getFloat(buffer, 108)); printf("[112-115] ? %ld\n", getLong(buffer, 112)); printf("[116-119] ? %ld\n", getLong(buffer, 116)); printf("[120-123] Stream number? %ld\n", getLong(buffer, 120)); printf("[124-127] Stream number? %ld\n", getLong(buffer, 124)); zeros(buffer, 128, 140); printf("[140-143] ? %ld\n", getLong(buffer, 140)); printf("[144-149] Date %04d/%02d/%02d\n", getWord(buffer, 144), getWord(buffer, 146), getWord(buffer, 148)); printf("[150-155] Time %02d:%02d:%02d\n", getWord(buffer, 150), getWord(buffer, 152), getWord(buffer, 154)); printf("[156-163] Sample Name: "); for (int i = 156; i < 164; i++) printf("%c", buffer[i]); printf("\n"); dump(buffer, 164, 188); zeros(buffer, 188, 240); printf("[240-243] long = %d\n", getLong(buffer, 240)); // 244-291 for (int i = 0; i < 12; i++) printf("[%d-%d] %d: %e\n", 244+i*4, 247+i*4, i+1, getFloat(buffer, 244+i*4)); // 292-315 for (int i = 0; i < 12; i++) printf("[%d-%d] %d: %d\n", 292+i*2, 293+i*2, i+1, getWord(buffer, 316+i*2)); // 316-339 for (int i = 0; i < 12; i++) printf("[%d-%d] %d: %d\n", 316+i*2, 317+i*2, i+1, getWord(buffer, 316+i*2)); printf("[340-343] long = %d\n", getLong(buffer, 340)); // 344-391 for (int i = 0; i < 12; i++) printf("[%d-%d] %d: %e\n", 344+i*4, 347+i*4, i+1, getFloat(buffer, 344+i*4)); // 392-415 for (int i = 0; i < 12; i++) printf("[%d-%d] %d: %d\n", 392+i*2, 399+i*2, i+1, getWord(buffer, 392+i*2)); // 416-439 for (int i = 0; i < 12; i++) printf("[%d-%d] %d: %d\n", 416+i*2, 417+i*2, i+1, getWord(buffer, 416+i*2)); printf("[440-443] long = %d\n", getLong(buffer, 440)); // 444-539 for (int i = 0; i < 12; i++) { printf("[%d-%d] %d: ", 444+i*8, 451+i*8, i+1); for (byte *s = &buffer[444+i*8]; *s != '\0'; s++) printf("%c", *s); printf("\n"); } zeros(buffer, 539, 579); printf("[580-583] text: '"); for (int i = 580; i < 584; i++) printf("%c", buffer[i]); printf("'\n"); printf("[584-587] ? %ld\n", getLong(buffer, 584)); printf("[588-591] ? %ld\n", getLong(buffer, 588)); int nrPoints = getLong(buffer, 592); printf("[592-595] nr points in data %ld\n", nrPoints); zeros(buffer, 596, 604); printf("[604-607] text: '"); for (int i = 604; i < 608; i++) printf("%c", buffer[i]); printf("'\n"); double start_wave = 11138.866; double end_wave = 3980.370; double wave_step = (end_wave - start_wave) / (nrPoints - 1); double wave = start_wave; int j = 0; int i = 608; for (; j < nrPoints && i < len; j++, i += 4, wave += wave_step) { printf("[%d] %.3f %e\n", i, wave, getFloat(buffer, i)); } }