/*
 *
 *
 *    decoder.cc
 *
 *    Experimental NOAA NWS / EAS data decoder.
 *
 *    Copyright (C) 2018 by Matt Roberts.
 *    License: GNU GPL3 (www.gnu.org)
 *
 *
 */


#include "decoder.h"
#include "localtypes.h"

using namespace std;

//
//  Decoder::process_sample(bool)
//
void Decoder::process_sample(bool output) {
	// if the state has changed...
	if (output != last_out) {
		// ...update the clock recovery algorithm
		last_out = output;
		period = bc.run(sinceLast);
		next = period;
		sinceLast = 1;
	} else {
		// otherwise just keep counting
		++sinceLast;
	}

	// use clock recovery to pick the next bit
	if (next) {
		// count down towards the next predicted edge
		--next;

		// if we're mid-bit, get the next bit
		if (next == get) {
			#ifdef RAW_OUTPUT
			cout << output;
			#else

			// shift in the current bit value
			shift_reg = (shift_reg >> 1) | (output ? (1 << 31) : 0);
			// and increment the SR counter
			++shift_ct;

			// if the larger shift register shows four bytes of header...
			if (shift_reg == header) {
				// clear the SR
				shift_ct = 0;

				// move to newline in the output
				if (!lastCR)
					cout << endl;
				lastCR = true;

				// unmute
				mute = false;
			} else if (shift_ct == 8) {
				// if there was otherwise a complete byte in the SR, get it
				shift_ct = 0;
				unsigned char ch = static_cast<unsigned char>((shift_reg & 0xFF000000) >> 24);

				// test whether the byte is printable
				bool print = isprint(ch);
				
				// if so...
				if (print) {
					// ... if we are unmuted, print the byte
					if (!mute) {
						cout << ch;
						lastCR = false;
					}
				} else {
					// otherwise (not printable), if we were unmuted, print a newline
					//    (assume the line is done)
					if (lastPrint && !mute) {
						cout << endl;
						lastCR = true;
					}

					// mute the output
					mute = true;
				}

				// save the 'last byte was printable' flag
				lastPrint = print;
			}
			#endif
			//cout.flush();
		}

		// if we have reached the expected edge time, start the counter over again
		//    with the current (hopefully phase-locked) period...
		if (next == 0) {
			next = period;
			get = period / 2;
		}
	}

	#ifdef DEMOD_DEBUG
	// compute the input binary state
	bool input = (freq > F0 ? true : false);

	cerr << setw(6) << i << setw(6) << (i * 1000 / MODEM_FS);
	cerr << fixed << setw(COLUMN_WIDTH) << static_cast<int64_t>(sample);
	cerr << fixed << setw(COLUMN_WIDTH) << static_cast<int64_t>(demod.output());
	cerr << fixed << setw(COLUMN_WIDTH) << static_cast<int64_t>(demod.output_high());
	cerr << fixed << setw(COLUMN_WIDTH) << static_cast<int64_t>(demod.output_low());
	cerr << fixed << setw(COLUMN_WIDTH) << static_cast<int64_t>(demod.level_high());
	cerr << fixed << setw(COLUMN_WIDTH) << static_cast<int64_t>(demod.level_low());
	cerr << fixed << setw(COLUMN_WIDTH) << static_cast<double>(demod.angle());
	cerr << fixed << setw(COLUMN_WIDTH) << (int)(demod.deviation());
	cerr << fixed << setw(COLUMN_WIDTH) << (int)(demod.offset());
	cerr << setw(COLUMN_WIDTH) << input;
	cerr << setw(COLUMN_WIDTH) << output;
	cerr << endl;
	#elif defined (CLOCK_DEBUG)
	cerr << "Output: " << output << "; Period: " << period << "; Next: " << next << "; Get = " << get;
	if (next == get) {
		cerr << "; BIT";
	}
	cerr << endl;
	#endif
}
