// EFR Broadcast Packet Sender
// ARDUINO MEGA 2560
// 0.5 AD9850 DDS対応
// 0.6 telegramNumber入れた
#define CLK 6
#define FQ 7
#define DATA 8
#define RST 9
const long oFreq = 21390000;
#include <LiquidCrystal.h>
LiquidCrystal lcd(34,35,36,37,38,39,40);
#include <TimerOne.h>
#define MARK 392 //500000/1275(Hz)
#define SPACE 346 //500000/1445(Hz)
#include <FlexiTimer2.h>
//packet
byte startMk = 0x68; //start marker
byte LField; //length
byte CField; //control, function
byte AField = 0xFF; //a1, address
byte CIField = 0xFF; //a2, control information
char message[] = "JI3BNB TEST"; //max 16 bytes
byte msgLen;
byte checkSum;
byte stopMk = 0x16; //stop marker
//controls
int sSq;
boolean snd;
int ti;
byte telegramNumber; //0-15
//data
char ascii;
//dds
void shortPulse (char PIN)
{
digitalWrite(PIN, 1);
digitalWrite(PIN, 0);
}
void setFreq(double freq)
{
//--calculate
int32_t d_Phase = freq * pow(2, 32) / 125000000;
//--send first 32bit
for (int i=0; i<32; i++, d_Phase>>=1)
{
if(d_Phase & 1 == 1)
{
digitalWrite(DATA, HIGH); //--data
}
else
{
digitalWrite(DATA, LOW); //--data
}
shortPulse(CLK);
}
//--send rest 8bit
digitalWrite(DATA, LOW); //--data
for (int i=0; i<8; i++)
{
shortPulse(CLK);
}
//--finish
shortPulse(FQ);
}
void setup()
{
//DDS
pinMode(CLK, OUTPUT);
pinMode(FQ, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(RST, OUTPUT);
//--dds reset
shortPulse(RST);
shortPulse(CLK);
//--change mode
shortPulse(FQ);
//pins
pinMode(12, OUTPUT); //AFSK AUDIO
pinMode(13, OUTPUT); //TTL
//LCD
lcd.begin(16, 2);
//timers
Timer1.initialize();
FlexiTimer2::set(1, timer2_interrupt); //1:200Bd 4:50Bd
FlexiTimer2::start();
//calculate message length
int n;
while(message[n] != '\0')
{
n++;
}
msgLen = n;
LField = msgLen + 3;
}
//AFSK TONE GENERATOR
void timer1_interrupt(void)
{
static boolean toggle;
toggle = toggle ^ 1;
digitalWrite(12, toggle);
}
void setOutput(bool state)
{
if(state == true)
{
Timer1.setPeriod(MARK);
digitalWrite(13, 1);
setFreq(oFreq);
}
else
{
Timer1.setPeriod(SPACE);
digitalWrite(13, 0);
setFreq(oFreq + 340);
}
}
//8E1 ascii GENERATOR
void timer2_interrupt(void)
{
byte paritySum;
static bool bit1;
static bool bit2;
static bool bit3;
static bool bit4;
static bool bit5;
static bool bit6;
static bool bit7;
static bool bit8;
static bool parity;
if(snd == 1)
{
switch(ti)
{
case 0:
setOutput(false);
bit1 = ascii & B00000001; paritySum += bit1;
bit2 = ascii & B00000010; paritySum += bit2;
bit3 = ascii & B00000100; paritySum += bit3;
bit4 = ascii & B00001000; paritySum += bit4;
bit5 = ascii & B00010000; paritySum += bit5;
bit6 = ascii & B00100000; paritySum += bit6;
bit7 = ascii & B01000000; paritySum += bit7;
bit8 = ascii & B10000000; paritySum += bit8;
if(paritySum % 2 == 0)
{
parity = false;
}
else
{
parity = true;
}
break;
case 5:
setOutput(bit1);
break;
case 10:
setOutput(bit2);
break;
case 15:
setOutput(bit3);
break;
case 20:
setOutput(bit4);
break;
case 25:
setOutput(bit5);
break;
case 30:
setOutput(bit6);
break;
case 35:
setOutput(bit7);
break;
case 40:
setOutput(bit8);
break;
case 45:
setOutput(parity);
break;
case 50:
setOutput(true);
break;
case 55:
snd = 0;
break;
}
ti++;
}
}
void loop()
{
static int addr;
if(sSq == 0) //--- pretone ---
{
checkSum = 0;
lcd.clear();
Timer1.attachInterrupt(timer1_interrupt, MARK); setFreq(oFreq);
delay(400);
addr = 0; sSq = 1;
}
if(sSq == 1) //--- packet ---
{
if(snd == 0)
{
if(addr == 0)
{
ascii = startMk;
}
else if(addr == 1)
{
ascii = LField;
}
else if(addr == 2)
{
ascii = LField;
}
else if(addr == 3)
{
ascii = startMk;
}
else if(addr == 4)
{
CField = telegramNumber;
CField = CField << 4;
bitWrite(CField, 3, 0);
bitWrite(CField, 2, 1);
bitWrite(CField, 1, 1);
bitWrite(CField, 0, 1);
ascii = CField;
checkSum += CField;
}
else if(addr == 5)
{
ascii = AField;
checkSum += AField;
}
else if(addr == 6)
{
ascii = CIField;
checkSum += CIField;
}
else if(addr >= 6 + 1 && addr <= 6 + msgLen)
{
ascii = message[addr - 7];
checkSum += ascii;
lcd.print(ascii);
}
else if(addr == 6 + msgLen + 1)
{
ascii = checkSum;
}
else if(addr == 6 + msgLen + 2)
{
ascii = stopMk;
}
else if(addr > 6 + msgLen + 2)
{
telegramNumber++;
if(telegramNumber ==16)
{
telegramNumber = 0;
}
sSq = 2;
goto intv;
}
ti = 0; snd = 1;
addr++;
}
}
intv: //-- interval --
if(sSq == 2)
{
Timer1.detachInterrupt(); setFreq(5);
delay(3000);
sSq = 0;
}
delay(5);
}