KISS TNC mode for the AX25 stack and example.

This commit is contained in:
Stephen Olesen 2015-07-13 18:55:07 -06:00
parent 45ec01bd31
commit a22b814d63
3 changed files with 159 additions and 0 deletions

88
KISS.cpp Normal file
View File

@ -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);
}

35
KISS.h Normal file
View File

@ -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_ */

36
examples/KISS/KISS.ino Normal file
View File

@ -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();
}