/****************************************************************************
 ■ TransMitter
   2010(C) Mr.Honey
   H/W Rev.001  S/W Rev.001
****************************************************************************/
#include <pic.h>

// Configuration
__CONFIG (
	INTIO &			// internal osc/GP4 = IO//GP5 = IO
	UNPROTECT &		// data protect off
	BORDIS &		// brown out reset disabled
	MCLRDIS &		// master clear reset function disabled
	PWRTEN & 		// power up timer enabled
	WDTDIS			// watchdog timer disabled
);
__IDLOC(0101);		// Revision

//=================================================================

#define U8 unsigned char
#define U16 unsigned short

#define NS73M_CK	GPIO1
#define NS73M_DA	GPIO0
#define NS73M_LA	GPIO2
#define LED			GPIO5

#define InputSW()	((GPIO >> 3) & 0x03)
#define SetLED(f)	LED = (f)

#define NORMAL		0b11
#define MODE01		0b01
#define MODE10		0b10
#define MODE00		0b00

//=================================================================

static void InitSystem(void);
static void InitNS73M(void);
static void Run(void);

static void Mode01(void);
static void Mode10(void);
static void Mode00(void);
static U8 Pause(U8 mode);
static void Blink(U8 ms, U8 count);

static void Send(U8 addr, U8 data);
static void DelayMs(U8 n);

//=================================================================

// 設定記録領域
eeprom U8 s_nFreq = 0;	// Frequency preset number
eeprom U8 s_nAG = 0b00;	// Audio input level (初期値:100mV)
eeprom U8 s_nPL = 0b01;	// TX power level (初期値:0.5mW)
eeprom U8 s_nRsv[5];	// reserved

// 周波数設定値テーブル
typedef struct _fsets_t {
	U8 R3, R4, R8;
} fsets_t;

eeprom fsets_t s_Freqs[4] = {
	//{ 0xDE, 0x29, 0x1B },	// 87.5MHz
	//{ 0xEA, 0x29, 0x1B },	// 87.6MHz
	//{ 0xF7, 0x29, 0x1B },	// 87.7MHz
	//{ 0x03, 0x2A, 0x1B },	// 87.8MHz
	//{ 0x0F, 0x2A, 0x1B },	// 87.9MHz
	//{ 0x1B, 0x2A, 0x1B },	// 88.0MHz
	//{ 0x28, 0x2A, 0x1B },	// 88.1MHz
	//{ 0x34, 0x2A, 0x1B },	// 88.2MHz
	//{ 0x40, 0x2A, 0x1B },	// 88.3MHz
	{ 0x4C, 0x2A, 0x1B },	// 88.4MHz
	{ 0x58, 0x2A, 0x1B },	// 88.5MHz
	{ 0x65, 0x2A, 0x1B },	// 88.6MHz
	{ 0x71, 0x2A, 0x1B },	// 88.7MHz
	//{ 0x7D, 0x2A, 0x1B },	// 88.8MHz
	//{ 0x89, 0x2A, 0x1B },	// 88.9MHz
	//{ 0x95, 0x2A, 0x1B },	// 89.0MHz
	//{ 0xA2, 0x2A, 0x1B },	// 89.1MHz
	//{ 0xAE, 0x2A, 0x1B },	// 89.2MHz
	//{ 0xBA, 0x2A, 0x1B },	// 89.3MHz
	//{ 0xC6, 0x2A, 0x1B },	// 89.4MHz
	//{ 0xD2, 0x2A, 0x1B },	// 89.5MHz
	//{ 0xDF, 0x2A, 0x1B },	// 89.6MHz
	//{ 0xEB, 0x2A, 0x1B },	// 89.7MHz
	//{ 0xF7, 0x2A, 0x1B },	// 89.8MHz
	//{ 0x03, 0x2B, 0x1B },	// 89.9MHz
	//{ 0x0F, 0x2B, 0x1A },	// 90.0MHz
	//{ 0x1C, 0x2B, 0x1A },	// 90.1MHz
	//{ 0x28, 0x2B, 0x1A },	// 90.2MHz
	//{ 0x34, 0x2B, 0x1A },	// 90.3MHz
	//{ 0x40, 0x2B, 0x1A },	// 90.4MHz
	//{ 0x4C, 0x2B, 0x1A },	// 90.5MHz
	//{ 0x59, 0x2B, 0x1A },	// 90.6MHz
	//{ 0x65, 0x2B, 0x1A },	// 90.7MHz
	//{ 0x71, 0x2B, 0x1A },	// 90.8MHz
	//{ 0x7D, 0x2B, 0x1A },	// 90.9MHz
	//{ 0x8A, 0x2B, 0x1A },	// 91.0MHz
};

//=================================================================

// ●メインエントリ
void main(void)
{
	InitSystem();
	InitNS73M();

	Blink(255, 2);
	Run();
}

// ●システム初期化
static void InitSystem(void)
{
	// 初期化
	CMCON = 0b00000111;		// コンパレータ OFF

	GPPU = 0;				// プルアップ ON
	GPIO = 0b00000000;
	TRISIO = 0b00011000;	// 入力：GP4,GP3　出力:GP5,GP2,GP1,GP0
}

// ●NS73M 初期化
static void InitNS73M(void)
{
	/* 8.7 Controller basic operation routines */

	// few mS waiting
	DelayMs(10);

	// Software Reset
	Send(0xE, 0b00000101);

	// Initial Set
	Send(0x1, 0b10110100); // PLT->ON, SUBC->ON
	Send(0x2, 0b00000100 | s_nPL); // PL->{0.5mW|1.0mW|2.0mW}, ULD->ON

	Send(0x5, 0b00000000);
	Send(0x7, 0b00000000);
	Send(0x9, 0b00000000);
	Send(0xA, 0b00000000);
	Send(0xB, 0b00000000);

	// Set Reg3,4,8
	Send(0x3, s_Freqs[s_nFreq].R3);
	Send(0x4, s_Freqs[s_nFreq].R4);
	Send(0x8, s_Freqs[s_nFreq].R8);

	// Set Reg0 (PE->ON, PDX->ON, MUTE->OFF, EM->ON, EMS->50us, AG->{100mV|140mV|200mV})
	Send(0x0, 0b00000001 | (s_nAG << 6));

	// Software Reset
	Send(0xE, 0b00000101);

	// Set Reg6
	Send(0x6, 0b00011010); // CIA->1.25uA, CIB->320uA
}

// ●実行ループ
static void Run(void)
{
	U16 nPika = 0;

	for(;;)
	{
		U8 n2, n1 = InputSW();
		if (n1 != NORMAL)
		{
			U8 i = 20;
			nPika = 0;
			SetLED(1);

			// DIPSW選択が確定するまで待つ
			do {
				DelayMs(100);
				n2 = InputSW();
				if (n2 == NORMAL)
					break;
				if (n1 != n2)
				{
					n1 = n2;
					i = 20;
				}
			}
			while (--i > 0);

			// 各モード設定モードへ分岐
			switch(n2)
			{
			case MODE01: Mode01();
				continue;
			case MODE10: Mode10();
				continue;
			case MODE00: Mode00();
				continue;
			}
		}
		SetLED(0);

		// 存在点滅
		if (++nPika == 150)
		{
			nPika = 0;
			Blink(75, 1);
			continue;
		}
		DelayMs(100);
	}
}

// ●[D3:OFF D4:ON]周波数切替モード
static void Mode01(void)
{
	// Pattern-1: Preset number 1
	// Pattern-2: Preset number 2
	// Pattern-3: Preset number 3
	// Pattern-4: Preset number 4

	// 現在値表示
	Blink(150, s_nFreq + 1);
	while (Pause(MODE01))
	{
		// パターン表示点滅
		U8 nTemp = s_nFreq;
		s_nFreq = ++nTemp % 4;
		Blink(150, s_nFreq + 1);

		// R6[CIA->80uA, CIB->320uA]
		Send(0x6, 0b00011110);

		// R3,R4,R8
		Send(0x3, s_Freqs[s_nFreq].R3);
		Send(0x4, s_Freqs[s_nFreq].R4);
		Send(0x8, s_Freqs[s_nFreq].R8);

		// R6[CIA->1.25uA, CIB->320uA]
		Send(0x6, 0b00011010);
	}
}

// ●[D3:ON D4:OFF]入力レベル切替モード
static void Mode10(void)
{
	// Pattern-1: 100mV(00)
	// Pattern-2: 140mV(01)
	// Pattern-3: 200mV(10)

	// 現在値表示
	Blink(150, s_nAG + 1);
	while (Pause(MODE10))
	{
		// パターン表示点滅
		U8 nTemp = s_nAG;
		s_nAG = ++nTemp % 3;
		Blink(150, s_nAG + 1);

		// R0[PE->ON, PDX->ON, MUTE->OFF, EM->ON, EMS->50us, AG->{100mV|140mV|200mV}]
		Send(0x0, 0b00000001 | (s_nAG << 6));
	}
}

// ●[D3:ON D4:ON] 出力レベル切替モード
static void Mode00(void)
{
	// Pattern-1: 0.5mW(01)
	// Pattern-2: 1.0mW(10)
	// Pattern-3: 2.0mW(11)

	// 現在値表示
	Blink(150, s_nPL);
	while (Pause(MODE00))
	{
		// パターン表示点滅
		U8 nTemp = s_nPL;
		s_nPL = (nTemp % 3) + 1;
		Blink(150, s_nPL);

		// R2[PL->{0.5mW|1.0mW|2.0mW}, ULD->ON]
		Send(0x2, 0b00000100 | s_nPL);
	}
}

// ●暫く待機する
static U8 Pause(U8 mode)
{
	U8 i = 50; // 5秒
	do {
		DelayMs(100);
		if (InputSW() != mode)
			return 0;
	}
	while (--i > 0);
	return 1;
}

// ●LED点滅
static void Blink(U8 ms, U8 count)
{
	do {
		LED = !LED;
		DelayMs(ms);
		LED = !LED;
		DelayMs(ms);
	}
	while (--count > 0);
}

// ●送信(3-wire bus)
static void Send(U8 addr, U8 data)
{
	U8 mask;

	// Address (A0-A3 LSB First)
	mask = 1;
	do {
		NS73M_DA = (addr & mask)? 1 : 0;
		NS73M_CK = 1;
		NS73M_CK = 0;
	}
	while ((mask <<= 1) < 0b10000); // 4Bits

	// Data (D0-D7 LSB First)
	mask = 1;
	do {
		NS73M_DA = (data & mask)? 1 : 0;
		NS73M_CK = 1;
		NS73M_CK = 0;
	}
	while (mask <<= 1); // 8Bits

	// Latch
	NS73M_DA = 0;
	NS73M_LA = 1;
	NS73M_LA = 0;
}

// ●遅延(ms)
static void DelayMs(U8 n)
{
	#define	XTAL_FREQ	4MHZ
	#define	MHZ			*1000L

	#define	DelayUs(x)	{ U8 _dcnt; \
		_dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
		while(--_dcnt != 0) continue; }

	do {
		U8 i = 4;
		do { DelayUs(246); }
		while (--i);
	}
	while (--n);
}
