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