KISS TNC mode for the AX25 stack and example.
This commit is contained in:
parent
45ec01bd31
commit
a22b814d63
|
@ -0,0 +1,88 @@
|
||||||
|
#include <HamShield.h>
|
||||||
|
#include "AFSK.h"
|
||||||
|
#include "KISS.h"
|
||||||
|
|
||||||
|
//AFSK::Packet kissPacket;
|
||||||
|
bool inFrame = false;
|
||||||
|
uint8_t kissBuffer[PACKET_MAX_LEN];
|
||||||
|
uint16_t kissLen = 0;
|
||||||
|
|
||||||
|
// Inside the KISS loop, we basically wait for data to come in from the
|
||||||
|
// KISS equipment, and look if we have anything to relay along
|
||||||
|
void KISS::loop() {
|
||||||
|
static bool currentlySending = false;
|
||||||
|
if(radio->afsk.decoder.read() || radio->afsk.rxPacketCount()) {
|
||||||
|
// A true return means something was put onto the packet FIFO
|
||||||
|
// If we actually have data packets in the buffer, process them all now
|
||||||
|
while(radio->afsk.rxPacketCount()) {
|
||||||
|
AFSK::Packet *packet = radio->afsk.getRXPacket();
|
||||||
|
if(packet) {
|
||||||
|
writePacket(packet);
|
||||||
|
AFSK::PacketBuffer::freePacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check if we have incoming data to turn into a packet
|
||||||
|
if(io->available()) {
|
||||||
|
uint8_t c = (uint8_t)io->read();
|
||||||
|
if(c == KISS_FEND) {
|
||||||
|
if(inFrame && kissLen > 0) {
|
||||||
|
int i;
|
||||||
|
AFSK::Packet *packet = AFSK::PacketBuffer::makePacket(PACKET_MAX_LEN);
|
||||||
|
packet->start();
|
||||||
|
for(i = 0; i < kissLen; i++) {
|
||||||
|
packet->append(kissBuffer[i]);
|
||||||
|
}
|
||||||
|
packet->finish();
|
||||||
|
radio->afsk.encoder.putPacket(packet);
|
||||||
|
}
|
||||||
|
kissLen = 0;
|
||||||
|
inFrame = false;
|
||||||
|
}
|
||||||
|
// We're inside the boundaries of a FEND
|
||||||
|
if(inFrame) {
|
||||||
|
// Unescape the incoming data
|
||||||
|
if(c == KISS_FESC) {
|
||||||
|
c = io->read();
|
||||||
|
if(c == KISS_TFESC) {
|
||||||
|
c = KISS_FESC;
|
||||||
|
} else {
|
||||||
|
c = KISS_FEND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kissBuffer[kissLen++] = c;
|
||||||
|
}
|
||||||
|
if(kissLen == 0 && c != KISS_FEND) {
|
||||||
|
if((c & 0xf) == 0) // First byte<3:0> should be a 0, otherwise we're having options
|
||||||
|
inFrame = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(radio->afsk.txReady()) {
|
||||||
|
radio->setModeTransmit();
|
||||||
|
currentlySending = true;
|
||||||
|
if(!radio->afsk.txStart()) { // Unable to start for some reason
|
||||||
|
radio->setModeReceive();
|
||||||
|
currentlySending = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(currentlySending && radio->afsk.encoder.isDone()) {
|
||||||
|
radio->setModeReceive();
|
||||||
|
currentlySending = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KISS::writePacket(AFSK::Packet *p) {
|
||||||
|
int i;
|
||||||
|
io->write(KISS_FEND);
|
||||||
|
io->write((uint8_t)0); // Host to TNC port identifier
|
||||||
|
for(i = 0; i < p->len-2; i++) {
|
||||||
|
char c = p->getByte(i);
|
||||||
|
if(c == KISS_FEND || c == KISS_FESC) {
|
||||||
|
io->write(KISS_FESC);
|
||||||
|
io->write((c==KISS_FEND?KISS_TFEND:KISS_TFESC));
|
||||||
|
} else {
|
||||||
|
io->write(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
io->write(KISS_FEND);
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef _KISS_H_
|
||||||
|
#define _KISS_H_
|
||||||
|
|
||||||
|
#include <HamShield.h>
|
||||||
|
#include "AFSK.h"
|
||||||
|
|
||||||
|
#define KISS_FEND 0xC0
|
||||||
|
#define KISS_FESC 0xDB
|
||||||
|
#define KISS_TFEND 0xDC
|
||||||
|
#define KISS_TFESC 0xDD
|
||||||
|
|
||||||
|
class KISS {
|
||||||
|
public:
|
||||||
|
KISS(Stream *_io, HamShield *h, DDS *d) : io(_io), radio(h), dds(d) {}
|
||||||
|
bool read();
|
||||||
|
void writePacket(AFSK::Packet *);
|
||||||
|
void loop();
|
||||||
|
inline void isr() {
|
||||||
|
static uint8_t tcnt = 0;
|
||||||
|
TIFR1 = _BV(ICF1); // Clear the timer flag
|
||||||
|
dds->clockTick();
|
||||||
|
if(++tcnt == (DDS_REFCLK_DEFAULT/9600)) {
|
||||||
|
PORTD |= _BV(2); // Diagnostic pin (D2)
|
||||||
|
radio->afsk.timer();
|
||||||
|
tcnt = 0;
|
||||||
|
}
|
||||||
|
PORTD &= ~(_BV(2));
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Stream *io;
|
||||||
|
HamShield *radio;
|
||||||
|
DDS *dds;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _KISS_H_ */
|
|
@ -0,0 +1,36 @@
|
||||||
|
#define DDS_REFCLK_DEFAULT 19200
|
||||||
|
|
||||||
|
#include <HamShield.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <KISS.h>
|
||||||
|
|
||||||
|
HamShield radio;
|
||||||
|
DDS dds;
|
||||||
|
KISS kiss(&Serial, &radio, &dds);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(2, OUTPUT);
|
||||||
|
pinMode(3, OUTPUT);
|
||||||
|
pinMode(11, INPUT);
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
Wire.begin();
|
||||||
|
radio.initialize();
|
||||||
|
radio.setVHF();
|
||||||
|
radio.setSQOff();
|
||||||
|
radio.setFrequency(145010);
|
||||||
|
I2Cdev::writeWord(A1846S_DEV_ADDR_SENLOW, 0x30, 0x06);
|
||||||
|
I2Cdev::writeWord(A1846S_DEV_ADDR_SENLOW, 0x30, 0x26);
|
||||||
|
I2Cdev::writeWord(A1846S_DEV_ADDR_SENLOW, 0x44, 0b0000011111111111);
|
||||||
|
|
||||||
|
dds.start();
|
||||||
|
radio.afsk.start(&dds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
kiss.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(ADC_vect) {
|
||||||
|
kiss.isr();
|
||||||
|
}
|
Loading…
Reference in New Issue