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