diff --git a/ALSASound.c b/ALSASound.c
index 3507e9f..5764e94 100644
--- a/ALSASound.c
+++ b/ALSASound.c
@@ -799,7 +799,8 @@ int OpenSoundCapture(char * CaptureDevice, int m_sampleRate, int Report)
 	
 	if ((err = snd_pcm_hw_params_set_channels(rechandle, hw_params, m_recchannels)) < 0)
 	{
-		Debugprintf("cannot set rec channel count to 2 (%s)", snd_strerror(err));
+		if (Report)
+			Debugprintf("cannot set rec channel count to 2 (%s)", snd_strerror(err));
 
 		m_recchannels = 1;
 
@@ -854,10 +855,10 @@ int OpenSoundCapture(char * CaptureDevice, int m_sampleRate, int Report)
 		snd_pcm_hw_params_set_rate(rechandle, hw_params, m_sampleRate, 0);
 		snd_pcm_hw_params_set_channels(rechandle, hw_params, m_recchannels);
 
-		err = snd_pcm_hw_params_set_buffer_size(rechandle, hw_params, 65536);
+	//	err = snd_pcm_hw_params_set_buffer_size(rechandle, hw_params, 65536);
 
-		if (err)
-			Debugprintf("cannot set buffer size (%s)", snd_strerror(err));
+	//	if (err)
+	//		Debugprintf("cannot set buffer size (%s)", snd_strerror(err));
 
 		err = snd_pcm_hw_params_set_period_size(rechandle, hw_params, (snd_pcm_uframes_t) { 1024 }, (int) { 0 });
 
@@ -1266,6 +1267,7 @@ int InitSound(BOOL Quiet)
 
 int min = 0, max = 0, lastlevelreport = 0, lastlevelGUI = 0;
 UCHAR CurrentLevel = 0;		// Peak from current samples
+UCHAR CurrentLevelR = 0;		// Peak from current samples
 
 void PollReceivedSamples()
 {
diff --git a/QtSoundModem.cpp b/QtSoundModem.cpp
index 976ca95..fe1a717 100644
--- a/QtSoundModem.cpp
+++ b/QtSoundModem.cpp
@@ -481,7 +481,7 @@ void DoPSKWindows()
 
 	for (i = 0; i < 4; i++)
 	{
-		if (pskStates[i])
+		if (soundChannel[i] && pskStates[i])
 		{
 			constellationLabel[i]->setGeometry(QRect(NextX, 19, 121, 121));
 			QualLabel[i]->setGeometry(QRect(1 + NextX, 1, 120, 15));
@@ -660,6 +660,11 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent)
 	ui.RXLevel->setPixmap(QPixmap::fromImage(*RXLevel));
 	RXLevelCopy = ui.RXLevel;
 
+	RXLevel2 = new QImage(150, 10, QImage::Format_RGB32);
+	RXLevel2->fill(white);
+	ui.RXLevel2->setPixmap(QPixmap::fromImage(*RXLevel2));
+	RXLevel2Copy = ui.RXLevel2;
+
 	DCDLabel[0] = new QLabel(this);
 	DCDLabel[0]->setObjectName(QString::fromUtf8("DCDLedA"));
 	DCDLabel[0]->setGeometry(QRect(280, 31, 12, 12));
@@ -2462,8 +2467,7 @@ void QtSoundModem::doRestartWF()
 	RXLevel2->fill(white);
 
 	ui.RXLevel->setVisible(1);
-	if (UsingBothChannels)
-		ui.RXLevel2->setVisible(1);
+	ui.RXLevel2->setVisible(1);
 
 	lockWaterfall = false;
 }
@@ -2553,7 +2557,7 @@ void QtSoundModem::RefreshSpectrum(unsigned char * Data)
 
 }
 
-void RefreshLevel(unsigned int Level)
+void RefreshLevel(unsigned int Level, unsigned int LevelR)
 {
 	// Redraw the RX Level Bar Graph
 
@@ -2577,9 +2581,29 @@ void RefreshLevel(unsigned int Level)
 		}
 	}
 	RXLevelCopy->setPixmap(QPixmap::fromImage(*RXLevel));
+
+	for (x = 0; x < 150; x++)
+	{
+		for (y = 0; y < 10; y++)
+		{
+			if (x < LevelR)
+			{
+				if (LevelR < 50)
+					RXLevel2->setPixel(x, y, yellow);
+				else if (LevelR > 135)
+					RXLevel2->setPixel(x, y, red);
+				else
+					RXLevel2->setPixel(x, y, green);
+			}
+			else
+				RXLevel2->setPixel(x, y, white);
+		}
+	}
+	RXLevel2Copy->setPixmap(QPixmap::fromImage(*RXLevel2));
 }
 
 extern "C" unsigned char CurrentLevel;
+extern "C" unsigned char CurrentLevelR;
 
 void QtSoundModem::RefreshWaterfall(int snd_ch, unsigned char * Data)
 {
@@ -2899,7 +2923,7 @@ void doWaterfallThread(void * param)
 	float ImagOut[8192];
 
 
-	RefreshLevel(CurrentLevel);	// Signal Level
+	RefreshLevel(CurrentLevel, CurrentLevelR);	// Signal Level
 
 	hFFTSize = FFTSize / 2;
 
@@ -2910,12 +2934,9 @@ void doWaterfallThread(void * param)
 	// So can use 1024 or 4096. 1024 gives 512 bins of 11.71875 and a 512 pixel 
 	// display (is this enough?)
 
-
-
 	Start = (WaterfallMin / BinSize);		// First and last bins to process
 	End = (WaterfallMax / BinSize);
 
-
 	if (0)	//RSID_WF
 	{
 		// Use the Magnitudes in float aFFTAmpl[RSID_FFT_SIZE];
diff --git a/QtSoundModem.vcxproj.user b/QtSoundModem.vcxproj.user
index 8b8926c..059beae 100644
--- a/QtSoundModem.vcxproj.user
+++ b/QtSoundModem.vcxproj.user
@@ -20,15 +20,15 @@
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
   <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <QtLastBackgroundBuild>2023-10-15T11:35:54.9027336Z</QtLastBackgroundBuild>
+    <QtLastBackgroundBuild>2023-11-24T17:50:14.6138870Z</QtLastBackgroundBuild>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="QtSettings">
-    <QtLastBackgroundBuild>2023-10-15T11:35:55.0741785Z</QtLastBackgroundBuild>
+    <QtLastBackgroundBuild>2023-11-24T17:50:14.7454647Z</QtLastBackgroundBuild>
   </PropertyGroup>
   <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <QtLastBackgroundBuild>2023-10-15T11:35:55.2661628Z</QtLastBackgroundBuild>
+    <QtLastBackgroundBuild>2023-11-24T17:50:14.8872599Z</QtLastBackgroundBuild>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="QtSettings">
-    <QtLastBackgroundBuild>2023-10-15T11:35:55.4659021Z</QtLastBackgroundBuild>
+    <QtLastBackgroundBuild>2023-11-24T17:50:15.0594798Z</QtLastBackgroundBuild>
   </PropertyGroup>
 </Project>
\ No newline at end of file
diff --git a/UZ7HOStuff.h b/UZ7HOStuff.h
index 4a68356..b27e76f 100644
--- a/UZ7HOStuff.h
+++ b/UZ7HOStuff.h
@@ -4,8 +4,8 @@
 //	 My port of UZ7HO's Soundmodem
 //
 
-#define VersionString "0.0.0.71"
-#define VersionBytes {0, 0, 0, 71}
+#define VersionString "0.0.0.72 Beta 1"
+#define VersionBytes {0, 0, 0, 72}
 
 // Added FX25. 4x100 FEC and V27 not Working and disabled
 
@@ -106,13 +106,13 @@
 
 // 0.48 Send FRMR for unrecognised frame types
 
-// 0.49 Add Andy's FEC Tag correlation coode
+// 0.49 Add Andy's FEC Tag correlation code
 
 // 0.50 Fix Waterfall display when only using right channel
 //		Allow 1200 baud fsk at other center freqs
 //		Add Port numbers to Window title and Try Icon tooltip
 //		Fix calculation of filters for multiple decoders
-//		Add RX Offset setting (for satellite operation
+//		Add RX Offset setting (for satellite operation)
 
 // 0.51	Fix Multithreading with more that 2 modems
 
@@ -178,7 +178,7 @@
 //		Improve reliability of waterfall update
 //		Report and set fx.25 and il2p flags to/from BPQ
 
-
+// .72	Fix IL2P for RUH modems
 
 
 #include <string.h>
@@ -330,8 +330,6 @@ typedef struct TFX25_t
 	Byte size_cnt;
 } TFX25;
 
-
-
 typedef struct TDetector_t
 {
 	struct TFX25_t fx25[4];
diff --git a/Waveout.c b/Waveout.c
index 0b37658..6b5c987 100644
--- a/Waveout.c
+++ b/Waveout.c
@@ -509,9 +509,10 @@ for (i = 0; i < 100; i++)
 	return TRUE;
 }
 
-static int min = 0, max = 0, lastlevelGUI = 0, lastlevelreport = 0;
+static int minL = 0, maxL = 0, minR = 0; maxR = 0, lastlevelGUI = 0, lastlevelreport = 0;
 
 UCHAR CurrentLevel = 0;		// Peak from current samples
+UCHAR CurrentLevelR = 0;	// Peak from current samples
 
 void PollReceivedSamples()
 {
@@ -521,7 +522,7 @@ void PollReceivedSamples()
 	// For level display we want a fairly rapid level average but only want to report 
 	// to log every 10 secs or so
 
-	// with Windows we get mono data
+	// We get stereo data
 
 	if (stdinMode)
 	{
@@ -534,16 +535,26 @@ void PollReceivedSamples()
 		short * ptr = &inbuffer[inIndex][0];
 		int i;
 
+		// Find min and max left abd right samples 
+
 		for (i = 0; i < ReceiveSize; i++)
 		{
-			if (*(ptr) < min)
-				min = *ptr;
-			else if (*(ptr) > max)
-				max = *ptr;
+			if (*(ptr) < minL)
+				minL = *ptr;
+			else if (*(ptr) > maxL)
+				maxL = *ptr;
+	
+			ptr++;
+
+			if (*(ptr) < minR)
+				minR = *ptr;
+			else if (*(ptr) > maxR)
+				maxR = *ptr;
 			ptr++;
 		}
 
-		CurrentLevel = ((max - min) * 75) /32768;	// Scale to 150 max
+		CurrentLevel = ((maxL - minL) * 75) / 32768;	// Scale to 150 max
+		CurrentLevelR = ((maxR - minR) * 75) / 32768;	// Scale to 150 max
 
 		if ((Now - lastlevelGUI) > 2000)	// 2 Secs
 		{
@@ -557,11 +568,13 @@ void PollReceivedSamples()
 				char HostCmd[64];
 				lastlevelreport = Now;
 
-				sprintf(HostCmd, "INPUTPEAKS %d %d", min, max);
-				Debugprintf("Input peaks = %d, %d", min, max);
-
+				sprintf(HostCmd, "INPUTPEAKS %d %d", minL, maxL);
+				if (UsingBothChannels)
+					Debugprintf("Input peaks L= %d, %d, R= %d, %d", minL, maxL, minR, maxR);
+				else
+					Debugprintf("Input peaks = %d, %d", minL, maxL);
 			}
-			min = max = 0;
+			minL = maxL = minR = maxR = 0;
 		}
 
 //		debugprintf(LOGDEBUG, "Process %d %d", inIndex, inheader[inIndex].dwBytesRecorded/2);
@@ -977,14 +990,14 @@ void StdinPollReceivedSamples()
 
 	for (i = 0; i < ReceiveSize; i++)
 	{
-		if (*(ptr) < min)
-			min = *ptr;
-		else if (*(ptr) > max)
-			max = *ptr;
+		if (*(ptr) < minL)
+			minL = *ptr;
+		else if (*(ptr) > maxL)
+			maxL = *ptr;
 		ptr++;
 	}
 
-	CurrentLevel = ((max - min) * 75) / 32768;	// Scale to 150 max
+	CurrentLevel = ((maxL - minL) * 75) / 32768;	// Scale to 150 max
 
 	if ((Now - lastlevelGUI) > 2000)	// 2 Secs
 	{
@@ -996,11 +1009,11 @@ void StdinPollReceivedSamples()
 			char HostCmd[64];
 			lastlevelreport = Now;
 
-			sprintf(HostCmd, "INPUTPEAKS %d %d", min, max);
-			Debugprintf("Input peaks = %d, %d", min, max);
+			sprintf(HostCmd, "INPUTPEAKS %d %d", minL, maxL);
+			Debugprintf("Input peaks = %d, %d", minL, maxL);
 
 		}
-		min = max = 0;
+		minL = maxL = 0;
 	}
 
 	//		debugprintf(LOGDEBUG, "Process %d %d", inIndex, inheader[inIndex].dwBytesRecorded/2);
diff --git a/ax25.c b/ax25.c
index e55e286..4ae9083 100644
--- a/ax25.c
+++ b/ax25.c
@@ -869,6 +869,9 @@ int get_addr(char * Calls, UCHAR * AXCalls)
 
 	ptr = strtok_s(NULL, " ,", &Context);
 
+	if (ptr == NULL)
+		return FALSE;
+
 	if (ConvToAX25(ptr, axptr) == 0)
 		return FALSE;
 
diff --git a/dw9600.c b/dw9600.c
index 407feb1..8e6db00 100644
--- a/dw9600.c
+++ b/dw9600.c
@@ -27,6 +27,7 @@ extern int fx25_mode[4];
 extern int il2p_mode[4];
 extern int il2p_crc[4];
 extern short rx_baudrate[5];
+extern short tx_bitrate[5];
 
 #define FX25_MODE_NONE  0
 #define FX25_MODE_RX  1
@@ -453,9 +454,11 @@ a good modem here and providing a result when it is received.
 void hdlc_rec_bit(int chan, int subchan, int slice, int raw, int is_scrambled, int not_used_remove)
 {
 
-	int dbit;			/* Data bit after undoing NRZI. */
+	int dbit;		/* Data bit after undoing NRZI. */
 					/* Should be only 0 or 1. */
+
 	struct hdlc_state_s *H;
+	int descram;
 
 	/*
 	 * Different state information for each channel / subchannel / slice.
@@ -469,27 +472,31 @@ void hdlc_rec_bit(int chan, int subchan, int slice, int raw, int is_scrambled, i
 	 *   A '1' bit is represented by no change.
 	 */
 
-	if (is_scrambled) {
-		int descram;
-
+	if (is_scrambled)
+	{
 		descram = descramble(raw, &(H->lfsr));
-
-		dbit = (descram == H->prev_descram);
+		dbit = (descram == H->prev_descram);			// This does nrzi
 		H->prev_descram = descram;
 		H->prev_raw = raw;
 	}
 	else {
 
 		dbit = (raw == H->prev_raw);
-
-		H->prev_raw = raw;
+		H->prev_raw = raw;						// This does nrzi
 	}
 
+	// dbit should be after nrzi, descram after descramble but before nrzi
+
 	// After BER insertion, NRZI, and any descrambling, feed into FX.25 decoder as well.
 
 //	fx25_rec_bit (chan, subchan, slice, dbit);
 
-	il2p_rec_bit (chan, subchan, slice, raw);	// Note: skip NRZI.
+	if (il2p_mode[chan])
+	{
+		il2p_rec_bit(chan, subchan, slice, raw);	// not scrambled, not nrzi	
+		if (il2p_mode[chan] == IL2P_MODE_ONLY)		// Dont try HDLC decode
+			return;
+	}
 
 	/*
 	 * Octets are sent LSB first.
@@ -618,7 +625,7 @@ void hdlc_rec_bit(int chan, int subchan, int slice, int raw, int is_scrambled, i
 		 *
 		 * This indicates loss of signal.
 		 * But we will let it slip thru because it might diminish
-		 * our single bit fixup effort.   Instead give up on frame
+		 * our float bit fixup effort.   Instead give up on frame
 		 * only when we see eight 1 bits in a row.
 		 *
 		 *	11111111
@@ -961,7 +968,7 @@ typedef struct retry_conf_s {
 
 static const char * retry_text[] = {
 		"NONE",
-		"SINGLE",
+		"float",
 		"DOUBLE",
 		"TRIPLE",
 		"TWO_SEP",
@@ -990,7 +997,7 @@ static int sanity_check(unsigned char *buf, int blen, retry_t bits_flipped, enum
  *					Level of effort to recover from
  *					a bad FCS on the frame.
  *					0 = no effort
- *					1 = try inverting a single bit
+ *					1 = try inverting a float bit
  *					2... = more techniques...
  *
  *	    			enum sanity_e sanity_test;
@@ -1114,7 +1121,7 @@ void hdlc_rec2_block(rrbb_t block)
  * Global In:	configuration fix_bits - Maximum level of fix up to attempt.
  *
  *				RETRY_NONE (0)	- Don't try any.
- *				RETRY_INVERT_SINGLE (1)  - Try inverting single bits.
+ *				RETRY_INVERT_float (1)  - Try inverting float bits.
  *				etc.
  *
  *		configuration passall - Let it thru with bad CRC after exhausting
@@ -1158,7 +1165,7 @@ static int try_to_fix_quick_now(rrbb_t block, int chan, int subchan, int slice,
 	 */
 	if (fix_bits < RETRY_INVERT_SINGLE) {
 
-		/* Stop before single bit fix up. */
+		/* Stop before float bit fix up. */
 
 		return 0;	/* failure. */
 	}
@@ -1174,7 +1181,7 @@ static int try_to_fix_quick_now(rrbb_t block, int chan, int subchan, int slice,
 		if (ok) {
 #if DEBUG
 			text_color_set(DW_COLOR_ERROR);
-			dw_printf("*** Success by flipping SINGLE bit %d of %d ***\n", i, len);
+			dw_printf("*** Success by flipping float bit %d of %d ***\n", i, len);
 #endif
 			return 1;
 		}
@@ -1227,7 +1234,7 @@ static int try_to_fix_quick_now(rrbb_t block, int chan, int subchan, int slice,
 
 
 	/*
-	 * Two  non-adjacent ("separated") single bits.
+	 * Two  non-adjacent ("separated") float bits.
 	 * It chews up a lot of CPU time.  Usual test takes 4 times longer to run.
 	 *
 	 * Processing time is order N squared so time goes up rapidly with larger frames.
@@ -1363,7 +1370,7 @@ inline static char is_sep_bit_modified(int bit_idx, retry_conf_t retry_conf) {
  *	   			retry:
  *					Level of effort to recover from a bad FCS on the frame.
  *				                RETRY_NONE = 0
- *				                RETRY_INVERT_SINGLE = 1
+ *				                RETRY_INVERT_float = 1
  *				                RETRY_INVERT_DOUBLE = 2
  *		                                RETRY_INVERT_TRIPLE = 3
  *		                                RETRY_INVERT_TWO_SEP = 4
@@ -3282,73 +3289,40 @@ static const int gray2phase_v27[8] = { 1, 0, 2, 3, 6, 7, 5, 4 };
 
 // We are only using this for RUH modes
 
-void tone_gen_put_bit(int chan, int dat)
+void tone_gen_put_bit(int chan, int dat, int scramble)
 {
-	int modem_type = MODEM_SCRAMBLE;
 	int a = 0;
 
 	// scramble
 
-	int x;
+	if (scramble)
+	{
+		int x;
 
-	x = (dat ^ (lfsr[chan] >> 16) ^ (lfsr[chan] >> 11)) & 1;
-	lfsr[chan] = (lfsr[chan] << 1) | (x & 1);
-	dat = x;
+		x = (dat ^ (lfsr[chan] >> 16) ^ (lfsr[chan] >> 11)) & 1;
+		lfsr[chan] = (lfsr[chan] << 1) | (x & 1);
+		dat = x;
+	}
 
 	do {		/* until enough audio samples for this symbol. */
 
 		int sam;
 
-		switch (modem_type)
+		if (dat != prev_dat[chan])
 		{
-
-		case MODEM_AFSK:
-
-			// v1.7 reversed.
-			// Previously a data '1' selected the second (usually higher) tone.
-			// It never really mattered before because we were using NRZI.
-			// With the addition of IL2P, we need to be more careful.
-			// A data '1' should be the mark tone.
-
-			tone_phase[chan] += dat ? f1_change_per_sample[chan] : f2_change_per_sample[chan];
-			sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
-			gen_tone_put_sample(chan, a, sam);
-			break;
-
-		case MODEM_QPSK:
-		case MODEM_8PSK:
-
 			tone_phase[chan] += f1_change_per_sample[chan];
-			sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
-			gen_tone_put_sample(chan, a, sam);
-			break;
-
-		case MODEM_BASEBAND:
-		case MODEM_SCRAMBLE:
-		case MODEM_AIS:
-
-			if (dat != prev_dat[chan])
-			{
-				tone_phase[chan] += f1_change_per_sample[chan];
-			}
-			else
-			{
-				if (tone_phase[chan] & 0x80000000)
-					tone_phase[chan] = 0xc0000000;	// 270 degrees.
-				else
-					tone_phase[chan] = 0x40000000;	// 90 degrees.
-			}
-
-			sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
-			gen_tone_put_sample(chan, a, sam);
-			break;
-
-		default:
-			text_color_set(DW_COLOR_ERROR);
-			dw_printf("INTERNAL ERROR: %s %d achan[%d].modem_type = %d\n",
-				__FILE__, __LINE__, chan, save_audio_config_p->achan[chan].modem_type);
-			exit(0);
 		}
+		else
+		{
+			if (tone_phase[chan] & 0x80000000)
+				tone_phase[chan] = 0xc0000000;	// 270 degrees.
+			else
+				tone_phase[chan] = 0x40000000;	// 90 degrees.
+		}
+
+		sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
+		gen_tone_put_sample(chan, a, sam);
+
 
 		/* Enough for the bit time? */
 
@@ -3399,18 +3373,13 @@ void gen_tone_put_sample(int chan, int a, int sam)
 //    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
 
-static void send_byte_msb_first(int chan, int x, int polarity);
 
 static void send_control_nrzi(int, int);
 static void send_data_nrzi(int, int);
 static void send_bit_nrzi(int, int);
 
-
-
 static int number_of_bits_sent[MAX_CHANS];	// Count number of bits sent by "hdlc_send_frame" or "hdlc_send_flags"
 
-
-
 /*-------------------------------------------------------------
  *
  * Name:	layer2_send_frame
@@ -3521,23 +3490,6 @@ static int ax25_only_hdlc_send_frame(int chan, unsigned char *fbuf, int flen, in
 }
 
 
-
-// The next one is only for IL2P.  No NRZI.
-// MSB first, opposite of AX.25.
-
-static void send_byte_msb_first(int chan, int x, int polarity)
-{
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		int dbit = (x & 0x80) != 0;
-		tone_gen_put_bit(chan, (dbit ^ polarity) & 1);
-		x <<= 1;
-		number_of_bits_sent[chan]++;
-	}
-}
-
-
 // The following are only for HDLC.
 // All bits are sent NRZI.
 // Data (non flags) use bit stuffing.
@@ -3594,7 +3546,7 @@ static void send_bit_nrzi(int chan, int b)
 		output[chan] = !output[chan];
 	}
 
-	tone_gen_put_bit(chan, output[chan]);
+	tone_gen_put_bit(chan, output[chan], MODEM_SCRAMBLE);
 
 	number_of_bits_sent[chan]++;
 }
@@ -4034,7 +3986,7 @@ void dw9600ProcessSample(int snd_ch, short Sample)
 void init_RUH48(int snd_ch)
 {
 	modem_mode[snd_ch] = MODE_RUH;
-	rx_baudrate[snd_ch] = 4800;
+	tx_bitrate[snd_ch] = rx_baudrate[snd_ch] = 4800;
 
 	if (was_init[snd_ch] == 0)
 	{
@@ -4054,7 +4006,7 @@ void init_RUH48(int snd_ch)
 void init_RUH96(int snd_ch)
 {
 	modem_mode[snd_ch] = MODE_RUH;
-	rx_baudrate[snd_ch] = 9600;
+	tx_bitrate[snd_ch] =  rx_baudrate[snd_ch] = 9600;
 
 	if (was_init[snd_ch] == 0)
 	{
@@ -4077,16 +4029,163 @@ void text_color_set(dw_color_t c)
 	return;
 }
 
+typedef struct  TMChannel_t
+{
+
+	float prev_LPF1I_buf[4096];
+	float LPF1Q_buf[4096];
+	float prev_dLPFI_buf[4096];
+	float prev_dLPFQ_buf[4096];
+	float prev_AFCI_buf[4096];
+	float prev_AFCQ_buf[4096];
+	float AngleCorr;
+	float MUX_osc;
+	float AFC_IZ1;
+	float AFC_IZ2;
+	float AFC_QZ1;
+	float AFC_QZ2;
+	float AFC_bit_buf1I[1024];
+	float AFC_bit_buf1Q[1024];
+	float AFC_bit_buf2[1024];
+	float AFC_IIZ1;
+	float AFC_QQZ1;
+
+} TMChannel;
+
+
+typedef struct TFX25_t
+{
+	string  data;
+	uint8_t  status;
+	uint8_t  bit_cnt;
+	uint8_t  uint8_t_rx;
+	unsigned long long tag;
+	uint8_t  size;
+	uint8_t  rs_size;
+	uint8_t size_cnt;
+} TFX25;
+
+typedef struct TDetector_t
+{
+	struct TFX25_t fx25[4];
+	TStringList	mem_ARQ_F_buf[5];
+	TStringList mem_ARQ_buf[5];
+	float pll_loop[5];
+	float last_sample[5];
+	uint8_t ones[5];
+	uint8_t zeros[5];
+	float bit_buf[5][1024];
+	float bit_buf1[5][1024];
+	uint8_t sample_cnt[5];
+	uint8_t last_bit[5];
+	float PSK_IZ1[5];
+	float PSK_QZ1[5];
+	float PkAmpI[5];
+	float PkAmpQ[5];
+	float PkAmp[5];
+	float PkAmpMax[5];
+	int newpkpos[5];
+	float AverageAmp[5];
+	float AngleCorr[5];
+	float MinAmp[5];
+	float MaxAmp[5];
+	float MUX3_osc[5];
+	float MUX3_1_osc[5];
+	float MUX3_2_osc[5];
+	float Preemphasis6[5];
+	float Preemphasis12[5];
+	float PSK_AGC[5];
+	float AGC[5];
+	float AGC1[5];
+	float AGC2[5];
+	float AGC3[5];
+	float AGC_max[5];
+	float AGC_min[5];
+	float AFC_IZ1[5];
+	float AFC_IZ2[5];
+	float AFC_QZ1[5];
+	float AFC_QZ2[5];
+
+	uint8_t last_rx_bit[5];
+	uint8_t bit_stream[5];
+	uint8_t uint8_t_rx[5];
+	uint8_t bit_stuff_cnt[5];
+	uint8_t bit_cnt[5];
+	float bit_osc[5];
+	uint8_t frame_status[5];
+	string rx_data[5];
+	string FEC_rx_data[5];
+	//
+	uint8_t FEC_pol[5];
+	unsigned short FEC_err[5];
+	unsigned long long FEC_header1[5][2];
+	unsigned short FEC_blk_int[5];
+	unsigned short FEC_len_int[5];
+	unsigned short FEC_len[5];
+
+	unsigned short FEC_len_cnt[5];
+
+	uint8_t rx_intv_tbl[5][4];
+	uint8_t rx_intv_sym[5];
+	uint8_t rx_viterbi[5];
+	uint8_t viterbi_cnt[5];
+	//	  SurvivorStates [1..4,0..511] of TSurvivor;
+		  //
+	TMChannel MChannel[5][4];
+
+	float AFC_dF_avg[5];
+	float AFC_dF[5];
+	float AFC_bit_osc[5];
+	float AFC_bit_buf[5][1024];
+	unsigned short AFC_cnt[5];
+
+	string raw_bits1[5];
+	string raw_bits[5];
+	uint8_t last_nrzi_bit[5];
+
+	float BPF_core[5][2048];
+	float LPF_core[5][2048];
+
+	float src_INTR_buf[5][8192];
+	float src_INTRI_buf[5][8192];
+	float src_INTRQ_buf[5][8192];
+	float src_LPF1I_buf[5][8192];
+	float src_LPF1Q_buf[5][8192];
+
+	float src_BPF_buf[5][2048];
+	float src_Loop_buf[5][8192];
+	float prev_BPF_buf[5][4096];
+
+	float prev_LPF1I_buf[5][4096];
+	float prev_LPF1Q_buf[5][4096];
+	float prev_INTR_buf[5][16384];
+	float prev_INTRI_buf[5][16384];
+	float prev_INTRQ_buf[5][16384];
+
+	uint8_t emph_decoded;
+	uint8_t rx_decoded;
+	uint8_t errors;
+
+} TDetector;
+
 
 extern TStringList detect_list[5];
 extern TStringList detect_list_c[5];
 
+#define nr_emph 2
+extern struct TDetector_t  DET[nr_emph + 1][16];
+
+#define decodedNormal 4 //'-'
+#define decodedFEC    3 //'F'
+#define decodedMEM	  2 //'#'
+#define decodedSingle 1 //'$'
+
 
 int multi_modem_process_rec_frame(int chan, int subchan, int slice, unsigned char *fbuf, int flen, int alevel, int retries, int is_fx25)
 {
 	// Convert to QtSM internal format
 
-//	struct TDetector_t * pDET = &DET[emph][subchan];
+	struct TDetector_t * pDET = &DET[0][subchan];
 	string *  data = newString();
 	char Mode[16] = "RUH";
 	int i, found;
@@ -4100,7 +4199,7 @@ int multi_modem_process_rec_frame(int chan, int subchan, int slice, unsigned cha
 
 		freeString(data);
 		Debugprintf("Discarding copy rcvr %d emph %d", subchan, 0);
-		return;
+		return 0;
 	}
 
 	string * xx = newString();
@@ -4109,6 +4208,10 @@ int multi_modem_process_rec_frame(int chan, int subchan, int slice, unsigned cha
 	Add(&detect_list_c[chan], xx);
 	Add(&detect_list[chan], data);
 
+	pDET->rx_decoded = decodedNormal;
+	pDET->emph_decoded = decodedNormal;
+	pDET->errors = 0;
+
 	//	if (retries)
 	//		sprintf(Mode, "IP2P-%d", retries);
 
@@ -4137,13 +4240,52 @@ void RUHEncode(unsigned char * Data, int Len, int chan)
 
 	int bitcount;
 	int txdcount;
-	int j;
+	int i, j;
 	unsigned short CRC;
 
 	number_of_bits_sent[chan] = 0;
 
 	SampleNo = 0;
 
+	if (il2p_mode[chan] >= IL2P_MODE_TXRX)
+	{
+		// il2p generates TXDELAY as part of the frame, so just build frame
+
+		string * result;
+		packet_t pp = ax25_new();
+		int polarity = 0;
+
+		// Call il2p_send_frame to build the bit stream
+
+		pp->frame_len = Len;
+		memcpy(pp->frame_data, Data, Len + 2);	// Copy the crc in case we are going to send it
+
+		result = il2p_send_frame(chan, pp, 1, 0);
+
+		for (j = 0; j < result->Length; j++)
+		{
+			int x = result->Data[j];
+
+			for (i = 0; i < 8; i++) 
+			{
+				int dbit = (x & 0x80) != 0;
+				tone_gen_put_bit(chan, (dbit ^ polarity) & 1, 0);		// No Scramble
+				x <<= 1;
+				number_of_bits_sent[chan]++;
+			}
+		}
+
+		freeString(result);
+		ax25_delete(pp);
+
+		// sample No should now contain number of (stereo) samples
+
+		ARDOPTXLen[chan] = SampleNo;
+		ARDOPTXPtr[chan] = 0;
+
+		return;
+	}
+
 	// First do TX delay
 
 	// Set up txd worth of flags
diff --git a/dw9600.h b/dw9600.h
index e80d2ac..ea34bae 100644
--- a/dw9600.h
+++ b/dw9600.h
@@ -376,7 +376,7 @@ typedef struct alevel_s {
 
 #ifndef AXTEST
 // TODO: remove this?
-#define AX25MEMDEBUG 1
+#define AX25MEMDEBUG 0
 #endif
 
 
@@ -1982,7 +1982,7 @@ int gen_tone_init(struct audio_s *pp, int amp, int gen_packets);
 
 //int gen_tone_close (void);
 
-void tone_gen_put_bit(int chan, int dat);
+void tone_gen_put_bit(int chan, int dat, int scramble);
 
 void gen_tone_put_sample(int chan, int a, int sam); 
 
diff --git a/il2p.c b/il2p.c
index 6a284f2..895feaa 100644
--- a/il2p.c
+++ b/il2p.c
@@ -127,7 +127,7 @@ typedef struct alevel_s {
 
 
 alevel_t demod_get_audio_level(int chan, int subchan);
-void tone_gen_put_bit(int chan, int dat);
+void tone_gen_put_bit(int chan, int dat, int scramble);
 
 int ax25memdebug = 1;
 
@@ -1031,9 +1031,6 @@ packet_t ax25_i_frame(char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_add
 } /* end ax25_i_frame */
 
 
-
-
-
 extern TStringList detect_list[5];
 extern TStringList detect_list_c[5];
 
@@ -1075,9 +1072,9 @@ void multi_modem_process_rec_packet(int snd_ch, int subchan, int slice, packet_t
 		if (CRCCALC != CRCMSG)
 		{
 			Debugprintf("CRC Error Decoder %d  Received %x Sent %x", subchan, CRCCALC, CRCMSG);
-	//		freeString(data);
-	//		ax25_delete(pp);
-	//		return;
+			freeString(data);
+			ax25_delete(pp);
+			return;
 		}
 	}
 
@@ -3959,7 +3956,7 @@ struct il2p_context_s *il2p_context[4][16][3];
  *
  * Name:        il2p_rec_bit
  *
- * Purpose:     Extract FX.25 packets from a stream of bits.
+ * Purpose:     Extract il2p packets from a stream of bits.
  *
  * Inputs:      chan    - Channel number.
  *
@@ -3984,15 +3981,18 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit)
 
 	if (dbit)
 		dbit = 1;
+	else
+		dbit = 0;
 
 	struct il2p_context_s *F = il2p_context[chan][subchan][slice];
+
 	if (F == NULL) {
 		//assert(chan >= 0 && chan < MAX_CHANS);
 		//assert(subchan >= 0 && subchan < MAX_SUBCHANS);
 		//assert(slice >= 0 && slice < MAX_SLICERS);
 		F = il2p_context[chan][subchan][slice] = (struct il2p_context_s *)malloc(sizeof(struct il2p_context_s));
 		//assert(F != NULL);
-memset(F, 0, sizeof(struct il2p_context_s));
+		memset(F, 0, sizeof(struct il2p_context_s));
 	}
 
 	// Accumulate most recent 24 bits received.  Most recent is LSB.
@@ -4018,7 +4018,7 @@ memset(F, 0, sizeof(struct il2p_context_s));
 
 			centreFreq[chan] = GuessCentreFreq(chan);
 		}
-		else if (__builtin_popcount((~F->acc & 0x00ffffff) ^ IL2P_SYNC_WORD) <= 1) {
+		else if (__builtin_popcount((~(F->acc) & 0x00ffffff) ^ IL2P_SYNC_WORD) <= 1) {
 			// FIXME - this pops up occasionally with random noise.  Find better way to convey information.
 			// This also happens for each slicer - to noisy.
 			//Debugprintf ("IL2P header has reverse polarity\n");
diff --git a/release/moc_predefs.h b/release/moc_predefs.h
index 54e9037..4c9c0c7 100644
--- a/release/moc_predefs.h
+++ b/release/moc_predefs.h
@@ -1,11 +1,11 @@
-#define _MSC_EXTENSIONS 
-#define _INTEGRAL_MAX_BITS 64
-#define _MSC_VER 1916
-#define _MSC_FULL_VER 191627043
-#define _MSC_BUILD 0
-#define _WIN32 
-#define _M_IX86 600
-#define _M_IX86_FP 2
-#define _CPPRTTI 
-#define _MT 
-#define _DLL 
+#define _MSC_EXTENSIONS 
+#define _INTEGRAL_MAX_BITS 64
+#define _MSC_VER 1916
+#define _MSC_FULL_VER 191627043
+#define _MSC_BUILD 0
+#define _WIN32 
+#define _M_IX86 600
+#define _M_IX86_FP 2
+#define _CPPRTTI 
+#define _MT 
+#define _DLL