19 Commits
dev ... v1.0.3

Author SHA1 Message Date
Morgan Redfield
307d33add0 update version to 1.0.3 2017-01-15 12:12:20 -08:00
nick6x
219d89ff60 Merge branch 'master' of https://github.com/EnhancedRadioDevices/HamShield 2017-01-15 12:06:12 -08:00
nick6x
6954402ac6 Clarify example descriptions 2017-01-15 12:05:43 -08:00
morgan
ec0400c1c6 adding narrow/wide band control 2017-01-15 11:31:22 -08:00
morgan
1d02387649 add yaac instructions to example 2016-12-27 12:46:27 -08:00
morgan
4593f1d44c fix KISS example 2016-12-27 12:08:28 -08:00
morgan
292a774a79 make morse dot duration user settable 2016-12-19 11:53:36 -08:00
morgan
5874e6b8e5 make morse tone freq user settable 2016-12-19 11:40:44 -08:00
morgan
4ff3f7d9d0 working afsk packets 2016-09-24 17:33:00 -07:00
morgan
b9f75e0c11 update AFSK messenger example 2016-09-24 15:32:24 -07:00
Morgan Redfield
f462bc0342 Merge pull request #24 from Temtel/master
Fixed Frequency Display at startup in AX25Receive.ino
2016-09-20 10:10:40 -07:00
Temtel
33962a585d Fixed Frequency Display at startup
Added   Serial.println(radio.getFrequency()); to setup.  May have been
removed accidentaly
2016-09-18 15:12:42 -07:00
Morgan Redfield
d54c5404a8 clarify new library setup 2016-08-27 09:36:01 -07:00
nick6x
6b775130d1 Remove unfinished examples 2016-08-26 15:02:40 -07:00
nick6x
e65893402a Fix typos 2016-08-26 14:40:47 -07:00
nick6x
9096d2ffa2 Update to separated libraries 2016-08-26 11:22:41 -07:00
nick6x
3e76e6e72f Merge branch 'master' of https://github.com/EnhancedRadioDevices/HamShield 2016-08-26 11:15:27 -07:00
Nigel Vander Houwen
164888fd49 Fixed DDS.cpp to reference ADC channel 2 instead of old channel 0. 2016-08-23 20:39:21 -07:00
nick6x
25813b7968 Clairify Parrot example description. 2016-08-18 20:47:35 -07:00
16 changed files with 339 additions and 744 deletions

View File

@@ -1,15 +1,21 @@
# HamShield
WARNING: The dev branch is not guaranteed to work. Please use caution if you choose to use that branch.
All of the AFSK, DDS, etc. files have been moved to the in Progress directory. These files collectively use twice as much memory as the essential HamShield functions. The current plan is to make sure these are only included if they're going to be used. We'll also be adapting them to make them more friendly to non-Uno Arduinos. Stay tuned for those changes.
The master branch is intended for use with HamShield hardware -09 and above.
HamShield Arduino Library and Example Sketches
WARNING: The dev branch is not guaranteed to work. Please use caution if you choose to use that branch.
# HamShield Arduino Library and Example Sketches
This repository is meant to be checked out into your Arduino application's libraries folder. After reloading the application, the library and example sketches should be available for use.
For overview, help, tricks, tips, and more, check out the wiki:
https://github.com/EnhancedRadioDevices/HamShield/wiki
# KISS and AFSK
We've moved the KISS and AFSK code to a separate library to help keep memory usage in simple sketches down. To use the AFSK examples, please also install these libraries:
- https://github.com/EnhancedRadioDevices/DDS
- https://github.com/EnhancedRadioDevices/HamShield_KISS

View File

@@ -13,7 +13,6 @@
*/
#define DDS_REFCLK_DEFAULT 9600
#include <HamShield.h>
#include <DDS.h>
@@ -51,84 +50,99 @@ void setup() {
radio.initialize();
radio.frequency(145570);
radio.setRfPower(0);
radio.setVolume1(0xFF);
radio.setVolume2(0xFF);
radio.setSQHiThresh(-100);
radio.setSQLoThresh(-100);
radio.setSQOn();
dds.start();
afsk.start(&dds);
delay(100);
radio.setModeReceive();
Serial.println("HELLO");
}
String temp[1] = "";
void loop() {
if(Serial.available()) {
char temp = (char)Serial.read();
if(temp == '`') {
prepMessage(); msgptr = 0; Serial.print("!!"); }
//Serial.println(messagebuff);
prepMessage();
msgptr = 0;
Serial.print("!!");
}
else {
messagebuff += temp;
msgptr++;
}
}
if(msgptr > 254) { messagebuff = ""; Serial.print("X!"); }
if(afsk.decoder.read() || 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(afsk.rxPacketCount()) {
AFSK::Packet *packet = afsk.getRXPacket();
Serial.print(F("Packet: "));
if(packet) {
packet->printPacket(&Serial);
AFSK::PacketBuffer::freePacket(packet);
}
}
}
}
void prepMessage() {
radio.setModeTransmit();
delay(500);
origin_call = messagebuff.substring(0,messagebuff.indexOf(',')); // get originating callsign
destination_call = messagebuff.substring(messagebuff.indexOf(',')+1,
messagebuff.indexOf(',',messagebuff.indexOf(',')+1)); // get the destination call
textmessage = messagebuff.substring(messagebuff.indexOf(":"));
delay(1000);
origin_call = messagebuff.substring(0,messagebuff.indexOf(',')); // get originating callsign
destination_call = messagebuff.substring(messagebuff.indexOf(',')+1,messagebuff.indexOf(',',messagebuff.indexOf(',')+1)); // get the destination call
textmessage = messagebuff.substring(messagebuff.indexOf(":")+1);
AFSK::Packet *packet = AFSK::PacketBuffer::makePacket(22 + 32);
// Serial.print("From: "); Serial.print(origin_call); Serial.print(" To: "); Serial.println(destination_call); Serial.println("Text: "); Serial.println(textmessage);
packet->start();
packet->appendCallsign(origin_call.c_str(),0);
packet->appendCallsign(destination_call.c_str(),15,true);
packet->appendFCS(0x03);
packet->appendFCS(0xf0);
packet->print(textmessage);
packet->finish();
AFSK::Packet *packet = AFSK::PacketBuffer::makePacket(22 + 32);
textmessage = "";
packet->start();
packet->appendCallsign(origin_call.c_str(),0);
packet->appendCallsign(destination_call.c_str(),15,true);
packet->appendFCS(0x03);
packet->appendFCS(0xf0);
packet->print(textmessage);
packet->finish();
bool ret = afsk.putTXPacket(packet);
bool ret = afsk.putTXPacket(packet);
if(afsk.txReady()) {
Serial.println(F("txReady"));
//radio.setModeTransmit();
//delay(100);
if(afsk.txStart()) {
Serial.println(F("txStart"));
} else {
radio.setModeReceive();
}
if(afsk.txReady()) {
Serial.println(F("txReady"));
radio.setModeTransmit();
//delay(100);
if(afsk.txStart()) {
Serial.println(F("txStart"));
} else {
radio.setModeReceive();
}
// Wait 2 seconds before we send our beacon again.
Serial.println("tick");
// Wait up to 2.5 seconds to finish sending, and stop transmitter.
// TODO: This is hackery.
for(int i = 0; i < 500; i++) {
if(afsk.encoder.isDone())
break;
delay(50);
}
Serial.println("Done sending");
delay(3000);
radio.setModeReceive();
}
// Wait 2 seconds before we send our beacon again.
Serial.println("tick");
// Wait up to 2.5 seconds to finish sending, and stop transmitter.
// TODO: This is hackery.
for(int i = 0; i < 500; i++) {
if(afsk.encoder.isDone())
break;
delay(50);
}
Serial.println("Done sending");
radio.setModeReceive();
}
// TODO: d2 is now our switch, so don't write to that
ISR(TIMER2_OVF_vect) {
TIFR2 = _BV(TOV2);
static uint8_t tcnt = 0;
if(++tcnt == 8) {
//digitalWrite(2, HIGH);
dds.clockTick();
//digitalWrite(2, LOW);
dds.clockTick();
tcnt = 0;
}
}
@@ -136,15 +150,9 @@ ISR(TIMER2_OVF_vect) {
ISR(ADC_vect) {
static uint8_t tcnt = 0;
TIFR1 = _BV(ICF1); // Clear the timer flag
//PORTD |= _BV(2); // Diagnostic pin (D2)
dds.clockTick();
if(++tcnt == 1) {
if(afsk.encoder.isSending()) {
afsk.timer();
}
afsk.timer();
tcnt = 0;
}
//PORTD &= ~(_BV(2)); // Pin D2 off again
}

View File

@@ -47,6 +47,7 @@ void setup() {
radio.frequency(145010);
radio.setSQOff();
Serial.println(F("Frequency"));
Serial.println(radio.getFrequency());
delay(100);
Serial.print(F("Squelch(H/L): "));
Serial.print(radio.getSQHiThresh());

View File

@@ -6,8 +6,10 @@
* into the HamShield RF jack. Connect the Arduino to wall
* power and then to your computer via USB. After uploading
* this program to your Arduino, open the Serial Monitor.
* Type 'h' into the bar at the top of the Serial Monitor
* and click the "Send" button for more instructions.
* Make sure drop-down menu at the bottom of Serial Monitor
* is set to "Newline". Type 'h' into the bar at the top of
* the Serial Monitor and click the "Send" button for more
* instructions.
*/
#define DDS_REFCLK_DEFAULT 38400

View File

@@ -1,6 +1,6 @@
/* Hamshield
* Example: DDS
* This is a simple example to show hot to transmit arbitrary
* This is a simple example to show how to transmit arbitrary
* tones. In this case, the sketh alternates between 1200Hz
* and 2200Hz at 1s intervals.
* Connect the HamShield to your Arduino. Screw the antenna

View File

@@ -53,6 +53,9 @@ void setup() {
radio.initialize();
radio.setRfPower(0);
radio.setMorseFreq(400);
radio.setMorseDotMillis(200);
// Configure the HamShield to transmit and recieve on 446.000MHz
radio.frequency(438000);

View File

@@ -1,283 +0,0 @@
// BlueHAM Proto01 Connection Guide
/**********************
**
** BlueHAM Proto01 <--> Arduino
** ADC_SCL A5
** ADC_DIO A4
** GND GND
** PWM_RF_CTL D9
**
** Setting Connections
** MODE -> GND
** SENB -> GND
** PDN -> 3.3V
** AVDD -> 5V (note this should be a beefy supply, could draw up to 4As)
**
**
**
** Pinout information for RadioPeripheral01 Prototype board
** GPIO0 -
** GPIO1 -
** GPIO2 - VHF_SEL
** GPIO3 - UHF_SEL
** GPIO4 - RX_EN
** GPIO5 - TX_EN
** GPIO6 -
** GPIO7 -
**************************/
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
#include "HAMShield.h"
#include <Goertzel.h>
//typedef enum {
#define MAIN_S 0
#define RX_S 1
#define TX_S 2
#define FREQ_S 3
#define UHF_S 4
#define VHF_S 5
#define PWR_S 6
#define GPIO_S 7
//} menu_view;
int state;
/* goertzel routines */
int sensorPin = A0;
int led = 13;
const float TARGET_FREQUENCY = 2200;
const int N = 100;
const float THRESHOLD = 4000;
const float SAMPLING_FREQUENCY = 8900;
Goertzel goertzel = Goertzel(TARGET_FREQUENCY, N, SAMPLING_FREQUENCY);
// create object for RDA
HAMShield radio;
#define LED_PIN 13
bool blinkState = false;
void setup() {
// initialize serial communication
Serial.begin(115200);
Serial.println("beginning radio setup");
// join I2C bus (I2Cdev library doesn't do this automatically)
Wire.begin();
// verify connection
Serial.println("Testing device connections...");
Serial.println(radio.testConnection() ? "RDA radio connection successful" : "RDA radio connection failed");
// initialize device
Serial.println("Initializing I2C devices...");
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
Serial.println("setting default Radio configuration");
// set frequency
Serial.println("changing frequency");
radio.setFrequency(446000); // in kHz
radio.setModeReceive();
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
state = MAIN_S;
print_menu();
}
void loop() {
goertzel.sample(sensorPin);
float magnitude = goertzel.detect();
if(magnitude>THRESHOLD) digitalWrite(led, HIGH); //if found, enable led
else digitalWrite(led, LOW);
while (Serial.available()) {
if (state == FREQ_S) {
char freq_khz[6];
int i = 0;
while(i < 6) {
if (Serial.available()) {
freq_khz[i] = Serial.read();
i++;
}
}
// interpret frequency
uint32_t freq = 0;
i = 0;
while (i < 6) {
uint32_t temp = freq_khz[i] - '0';
for (int k = 5-i; k > 0; k--) {
temp = temp * 10;
}
freq += temp;
i++;
}
Serial.print("setting frequency to: ");
Serial.println(freq);
radio.setFrequency(freq);
state = MAIN_S;
} else if (state == PWR_S) {
uint8_t pwr_raw[3];
int i = 0;
while(i < 3) {
if (Serial.available()) {
pwr_raw[i] = Serial.read();
i++;
}
}
// interpret power
uint8_t pwr = 0;
i = 0;
while (i < 3) {
uint8_t temp = pwr_raw[i] - '0';
for (int k = 2-i; k > 0; k--) {
temp = temp * 10;
}
pwr += temp;
i++;
}
Serial.print("Setting power to: ");
Serial.println(pwr);
radio.setRfPower(pwr);
state = MAIN_S;
} else if (state == GPIO_S) {
uint8_t gpio_raw[2];
int i = 0;
while(i < 2) {
if (Serial.available()) {
gpio_raw[i] = Serial.read();
i++;
}
}
uint16_t gpio_pin = gpio_raw[0] - 48; // '0';
uint16_t gpio_mode = gpio_raw[1] - 48;
radio.setGpioMode(gpio_pin, gpio_mode);
state = MAIN_S;
} else {
char action = Serial.read();
if (action == 'r') { // get current state
state = RX_S;
} else if (action == 't') {
state = TX_S;
} else if (action == 'f') {
state = FREQ_S;
} else if (action == 'u') {
state = UHF_S;
} else if (action == 'v') {
state = VHF_S;
} else if (action == '1') {
turn_on(state);
state = MAIN_S;
} else if (action == '0') {
turn_off(state);
state = MAIN_S;
} else if (action == 'p') {
state = PWR_S;
} else if (action == 'g') {
state = GPIO_S;
} else if (action == 's') {
int16_t rssi = radio.readRSSI();
Serial.print("rssi: ");
Serial.println(rssi);
} else if (action == 'i') {
int16_t vssi = radio.readVSSI();
Serial.print("vssi: ");
Serial.println(vssi);
}
Serial.println(action);
}
Serial.flush();
print_menu();
}
}
void turn_off(int dev) {
switch (dev) {
case RX_S:
radio.setRX(0);
break;
case TX_S:
radio.setTX(0);
break;
case UHF_S:
radio.setGpioMode(3, 3); // set GPIO3 high (uhf is active low)
break;
case VHF_S:
radio.setGpioMode(2, 3); // set GPIO2 high (vhf is active low)
break;
default:
break;
}
}
void turn_on(int dev) {
switch (dev) {
case RX_S:
radio.setRX(1);
break;
case TX_S:
radio.setTX(1);
break;
case UHF_S:
radio.setGpioMode(3, 2); // set GPIO3 low (uhf is active low)
break;
case VHF_S:
radio.setGpioMode(2, 2); // set GPIO2 low (uhf is active low)
break;
default:
break;
}
}
void print_menu() {
Serial.println("MENU");
switch (state) {
case MAIN_S:
Serial.println("select step: [r]x, [t]x, [f]req, [u]hf, [v]hf, [p]wr, [g]pio control, r[s]si, vss[i] ...");
break;
case RX_S:
Serial.println("enter 1 to turn on rx, 0 to turn off rx");
break;
case TX_S:
Serial.println("enter 1 to turn on tx, 0 to turn off tx");
break;
case FREQ_S:
Serial.println("enter frequency in kHz (ffffff)");
break;
case UHF_S:
Serial.println("enter 1 to turn on uhf, 0 to turn off uhf");
break;
case VHF_S:
Serial.println("enter 1 to turn on vhf, 0 to turn off vhf");
break;
case PWR_S:
Serial.println("enter power (raw) (ppp)");
break;
case GPIO_S:
Serial.println("enter GPIO pin and control (no spaces, eg pin 1 mode 3 is 13");
Serial.println("modes 0 - HiZ, 1 - FCN, 2 - Low, 3 - Hi");
break;
default:
state = MAIN_S;
break;
}
}

View File

@@ -1,60 +0,0 @@
/* Hamshield
* Example: HAMBot
* Simple DTMF controlled HAM Radio Robot. You will need
* seperate DTMF equipment as well as robot for this
* example.
* Connect the HamShield to your Arduino. Screw the antenna
* into the HamShield RF jack. Connect the Arduino to wall
* power and then to your computer via USB. After uploading
* this program to your Arduino, you can send commands from
* your DTMF equipment using the following list:
* '4' => turn robot left
* '6' => turn robot right
* '2' => move robot forward
* '5' => tell robot to send morse code identity
*/
#include <ArduinoRobot.h> // include the robot library
#include <HamShield.h>
#include <SPI.h>
#define PWM_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
HamShield radio;
void setup() {
// NOTE: if not using PWM out, it should be held low to avoid tx noise
pinMode(PWM_PIN, OUTPUT);
digitalWrite(PWM_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
// set up the reset control pin
pinMode(RESET_PIN, OUTPUT);
digitalWrite(RESET_PIN, HIGH);
Robot.begin();
radio.initialize();
radio.frequency(145510);
}
void loop() {
if(radio.waitForDTMF()) { // wait for a received DTMF tone
uint8_t command = radio.getLastDTMFDigit(); // get the last DTMF tone sent
if(command == '4') { Robot.turn(-90); } // turn robot left
if(command == '6') { Robot.turn(90); } // turn robot right
if(command == '2') { Robot.motorsWrite(-255,-255); delay(500); Robot.motorsWrite(255, 255); } // move robot forward
if(command == '5') { // tell robot to send morse code identity
if(radio.waitForChannel()) { // wait for the user to release the transmit button
radio.setModeTransmit(); // turn on transmit mode
radio.morseOut("1ZZ9ZZ I AM HAMRADIO ROBOT"); // send morse code
radio.setModeReceive(); // go back to receive mode on radio
}
}
}
}

View File

@@ -1,95 +0,0 @@
/*
Indentifier
Arduino audio overlay example
*/
#include <HamShield.h>
#define DOT 100
#define PWM_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
HamShield radio;
const char *bascii = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?'!/()&:;=+-_\"$@",
*bitu[] = { ".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",".-.-.-","--..--","..--..",".----.","-.-.--","-..-.","-.--.","-.--.-",".-...","---...","-.-.-.","-...-",".-.-.","-....-","..--.-",".-..-.","...-..-",".--.-."
};
const char *callsign = {"1ZZ9ZZ/B"} ;
char morsebuffer[8];
void setup() {
// NOTE: if not using PWM out, it should be held low to avoid tx noise
pinMode(PWM_PIN, OUTPUT);
digitalWrite(PWM_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
// set up the reset control pin
pinMode(RESET_PIN, OUTPUT);
digitalWrite(RESET_PIN, HIGH);
Serial.begin(9600);
Serial.println("starting up..");
Serial.print("Radio status: ");
int result = radio.testConnection();
Serial.println(result,DEC);
radio.initialize();
radio.frequency(446000);
radio.setVolume1(0xF);
radio.setVolume2(0xF);
radio.setModeReceive();
radio.setTxSourceMic();
radio.setSQLoThresh(80);
radio.setSQOn();
Serial.println("Done with radio beacon setup. Press and hold a key to transmit.");
}
int state = 0;
long timer = 0;
int morseletter = 0;
int morsesymbol = 0;
long keyer = 0;
char symbol;
void loop() {
if(Serial.available() > 0) {
if(state == 0) {
state = 10;
radio.setModeTransmit();
timer = millis();
keyer = millis();
}
if(state == 10) {
timer = millis();
}
}
if(millis() > (timer + 500)) { radio.setModeReceive(); morseletter = 0; morsesymbol = 0; state = 0; }
if(state == 10) {
if(millis() > (keyer + (DOT * 3))) {
keyer = millis();
symbol = lookup(callsign[morseletter],morsesymbol);
if(symbol == '-') { tone(9,1000,DOT*3); }
if(symbol == '.') { tone(9,1000,DOT); }
if(symbol == 0) { morsesymbol = 0; morseletter++; }
if(callsign[morseletter] == 0) { morsesymbol = 0; morseletter = 0; }
}
}
}
char lookup(char letter, int morsesymbol) {
for(int x = 0; x < 54; x++) {
if(letter == bascii[x]) {
return bitu[x][morsesymbol];
}
}
}

View File

@@ -1,131 +0,0 @@
/* Hamshield
* Example: Parrot
* Record sound and then plays it back a few times. Very low
* sound quality @ 2KHz 0.75 seconds. A bit robotic and weird.
* You will need a HandyTalkie (HT) to test the output of this
* example.
* Connect the HamShield to your Arduino. Screw the antenna
* into the HamShield RF jack. Plug a pair of headphones into
* the HamShield. Connect the Arduino to wall power and then to
* your computer via USB. To test the output, tune you HT to
* 446MHz. The HamShield should make a recording ofthe next
* broadcast on that frequncy. The recording should then be
* repeated ten times by the HamShield.
*/
#include <HamShield.h>
#define PWM_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
#define RATE 500
#define SIZE 1500
HamShield radio;
char sound[SIZE];
unsigned int sample1;
int x = -1;
int16_t rssi;
byte mode = 8;
void setup() {
// NOTE: if not using PWM out, it should be held low to avoid tx noise
pinMode(PWM_PIN, OUTPUT);
digitalWrite(PWM_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
// set up the reset control pin
pinMode(RESET_PIN, OUTPUT);
digitalWrite(RESET_PIN, HIGH);
// int result = radio.testConnection();
radio.initialize();
radio.frequency(446000);
setPwmFrequency(9, 1);
}
void loop() {
rssi = radio.readRSSI();
if(rssi > -100) {
if(x == -1) {
for(x = 0; x < SIZE; x++) {
if(mode == 4) {
sample1 = analogRead(2);
sound[x] = sample1 >> 4;
delayMicroseconds(RATE); x++;
sample1 = analogRead(2);
sound[x] = (sample1 & 0xF0) | sound[x];
delayMicroseconds(RATE);
} else {
sound[x] = analogRead(2);
delayMicroseconds(RATE); x++;
sound[x] = analogRead(2);
delayMicroseconds(RATE);
}
}
}
}
if(rssi < -100) {
if(x == 1500) {
radio.setModeTransmit();
delay(500);
tone(9,1000,500); delay(750);
for(int r = 0; r < 10; r++) {
for(x = 0; x < SIZE; x++) {
if(mode == 4) {
analogWrite(9,sound[x] << 4);
delayMicroseconds(RATE); x++;
analogWrite(9,sound[x] & 0xF);
delayMicroseconds(RATE); } else {
analogWrite(9,sound[x]);
delayMicroseconds(RATE); x++;
analogWrite(9,sound[x]);
delayMicroseconds(RATE);
}
} }
tone(9,1000,500); delay(750);
radio.setModeReceive();
x = -1;
}
}
}
void setPwmFrequency(int pin, int divisor) {
byte mode;
if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 64: mode = 0x03; break;
case 256: mode = 0x04; break;
case 1024: mode = 0x05; break;
default: return;
}
if(pin == 5 || pin == 6) {
TCCR0B = TCCR0B & 0b11111000 | mode;
} else {
TCCR1B = TCCR1B & 0b11111000 | mode;
}
} else if(pin == 3 || pin == 11) {
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 32: mode = 0x03; break;
case 64: mode = 0x04; break;
case 128: mode = 0x05; break;
case 256: mode = 0x06; break;
case 1024: mode = 0x7; break;
default: return;
}
TCCR2B = TCCR2B & 0b11111000 | mode;
}
}

View File

@@ -4,9 +4,10 @@
* will check to see if the channel is clear before it will
* transmit.
* Connect the HamShield to your Arduino. Screw the antenna
* into the HamShield RF jack. Connect the Arduino to wall power and then
* to your computer via USB. To test, set a HandyTalkie
* to 438MHz. You should hear a one-minute tone every 10-13 minutes.
* into the HamShield RF jack. Connect the Arduino to wall
* power and then to your computer via USB. To test, set a
* HandyTalkie to 438MHz. You should hear a one-minute tone
* followed by a callsign every 10-13 minutes.
*/
#include <HamShield.h>

View File

@@ -7,18 +7,29 @@
* into the HamShield RF jack. Connect the Arduino to wall
* power and then to your computer via USB. Issue commands
* via the KISS equipment.
*
* To use the KISS example with YAAC:
* 1. open the configure YAAC wizard
* 2. follow the prompts and enter in your details until you get to the "Add and Configure Interfaces" window
* 3. Choose "Add Serial KISS TNC Port"
* 4. Choose the COM port for your Arduino
* 5. set baud rate to 9600 (default)
* 6. set it to KISS-only: with no command to enter KISS mode (just leave the box empty)
* 7. Use APRS protocol (default)
* 8. hit the next button and follow directions to finish configuration
*/
#include <HamShield.h>
#include <KISS.h>
#include <DDS.h>
#include <packet.h>
#include <avr/wdt.h>
HamShield radio;
DDS dds;
KISS kiss(&Serial, &radio, &dds);
AFSK afsk;
KISS kiss(&Serial, &radio, &dds, &afsk);
//TODO: move these into library
#define PWM_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -33,28 +44,44 @@ void setup() {
// set up the reset control pin
pinMode(RESET_PIN, OUTPUT);
digitalWrite(RESET_PIN, LOW);
digitalWrite(RESET_PIN, HIGH);
Serial.begin(9600);
while (digitalRead(SWITCH_PIN));
// let the AU ot of reset
digitalWrite(RESET_PIN, HIGH);
radio.initialize();
radio.setSQOff();
//radio.setSQOff();
radio.setVolume1(0xFF);
radio.setVolume2(0xFF);
radio.setSQHiThresh(-100);
radio.setSQLoThresh(-100);
radio.setSQOn();
radio.frequency(144390);
//I2Cdev::writeWord(A1846S_DEV_ADDR_SENLOW, 0x44, 0x05FF);
dds.start();
afsk.start(&dds);
delay(100);
radio.setModeReceive();
}
void loop() {
kiss.loop();
}
ISR(ADC_vect) {
kiss.isr();
ISR(TIMER2_OVF_vect) {
TIFR2 = _BV(TOV2);
static uint8_t tcnt = 0;
if(++tcnt == 8) {
dds.clockTick();
tcnt = 0;
}
}
ISR(ADC_vect) {
static uint8_t tcnt = 0;
TIFR1 = _BV(ICF1); // Clear the timer flag
dds.clockTick();
if(++tcnt == 1) {
afsk.timer();
tcnt = 0;
}
}

View File

@@ -21,29 +21,15 @@ Mode ASCII Description
-------------- ----------- -------------------------------------------------------------------------------------------------------------------------------------------- -----------------
Transmit space Space must be received at least every 500 mS Yes
Receive not space If space is not received and/or 500 mS timeout of space occurs, unit will go into receive mode Yes
CTCSS In A<tone>; <tone> must be a numerical ascii value with decimal point indicating CTCSS receive tone required to unsquelch No
CTCSS Out B<tone>; <tone> must be a numerical ascii value with decimal point indicating CTCSS transmit tone No
CTCSS Enable C<state>; Turns on CTCSS mode (analog tone) with 1, off with 0. No
CDCSS Enable D<state>; Turns on CDCSS mode (digital tone) with 1, off with 0. No
Bandwidth E<mode>; for 12.5KHz mode is 0, for 25KHz, mode is 1 No
Frequency F<freq>; Set the receive frequency in KHz, if offset is disabled, this is the transmit frequency No
CDCSS In G<code>; <code> must be a valid CDCSS code No
CDCSS Out H<code>; <code> must be a valid CDCSS code No
Print tones I Prints out all configured tones and codes, coma delimited in format: CTCSS In, CTCSS Out, CDCSS In, CDCSS Out No
Morse Out M<text>; A small buffer for morse code (32 chars)
Power level P<level>; Set the power amp level, 0 = lowest, 15 = highest No
Enable Offset R<state>; 1 turns on repeater offset mode, 0 turns off repeater offset mode No
Squelch S<level>; Set the squelch level No
TX Offset T<freq>; The absolute frequency of the repeater offset to transmit on in KHz No
Volume V<level>; Set the volume level of the receiver No
Reset X Reset all settings to default No
Sleep Z Sleep radio No
Filters @<state>; Set bit to enable, clear bit to disable: 0 = pre/de-emphasis, 1 = high pass filter, 2 = low pass filter (default: ascii 7, all enabled) No
Vox mode $<state>; 0 = vox off, >= 1 audio sensitivity. lower value more sensitive No
Mic Channel *<state>; Set the voice channel. 0 = signal from mic or arduino, 1 = internal tone generator No
RSSI ? Respond with the current receive level in - dBm (no sign provided on numerical response) No
Tone Gen % (notes) To send a tone, use the following format: Single tone: %1,<freq>,<length>; Dual tone: %2,<freq>,<freq>,<length>; DTMF: %3,<key>,<length>; No
Voice Level ^ Respond with the current voice level (VSSI)
RSSI ?; Respond with the current receive level in - dBm (no sign provided on numerical response) No
Voice Level ^; Respond with the current voice level (VSSI)
Responses:

View File

@@ -1,5 +1,5 @@
name=HamShield
version=1.0.2
version=1.0.3
author=Morgan Redfield <morgan@enhancedradio.com>, Casey Halverson <casey@enhancedradio.com>
maintainer=Morgan Redfield <morgan@enhancedradio.com>
sentence=A library for use with HamShield by Enhanced Radio Devices.

View File

@@ -24,6 +24,10 @@ const uint32_t MURS[] PROGMEM = {0,151820,151880,151940,154570,154600};
const uint32_t WX[] PROGMEM = {0,162550,162400,162475,162425,162450,162500,162525};
unsigned int morse_freq = 600;
unsigned int morse_dot_millis = 100;
/* morse code lookup table */
// This is the Morse table in reverse binary format.
// It will occupy 108 bytes of memory (or program memory if defined)
@@ -147,10 +151,19 @@ HamShield::HamShield(uint8_t cs_pin) {
digitalWrite(DAT, HIGH);
}
/** Power on and prepare for general usage.
*
*/
void HamShield::initialize() {
initialize(true);
}
/** Power on and prepare for general usage.
*
*/
void HamShield::initialize(bool narrowBand) {
// Note: these initial settings are for UHF 12.5kHz channel
// see the A1846S register table and initial settings for more info
@@ -179,7 +192,99 @@ void HamShield::initialize() {
tx_data = 0x0AF2; //
HSwriteWord(devAddr, 0x33, tx_data); // agc number
// AGC table
tx_data = 0x067F; //0x0601; //0x470F;
HSwriteWord(devAddr, 0x41, tx_data); // voice gain tx [6:0]
tx_data = 0x02FF; // using 0x04FF to avoid tx voice delay
HSwriteWord(devAddr, 0x44, tx_data); // tx gain [11:8]
tx_data = 0x7F2F;
HSwriteWord(devAddr, 0x47, tx_data);
tx_data = 0x2C62;
HSwriteWord(devAddr, 0x4F, tx_data);
tx_data = 0x0094;
HSwriteWord(devAddr, 0x53, tx_data); // compressor update time (bits 6:0, 5.12ms per unit)
tx_data = 0x2A18;
HSwriteWord(devAddr, 0x54, tx_data);
tx_data = 0x0081;
HSwriteWord(devAddr, 0x55, tx_data);
tx_data = 0x0B22;
HSwriteWord(devAddr, 0x56, tx_data); // sq detect time
tx_data = 0x1C00;
HSwriteWord(devAddr, 0x57, tx_data);
tx_data = 0x800D;
HSwriteWord(devAddr, 0x58, tx_data);
tx_data = 0x0EDD;
HSwriteWord(devAddr, 0x5A, tx_data); // sq and noise detect times
tx_data = 0x3FFF;
HSwriteWord(devAddr, 0x63, tx_data); // pre-emphasis bypass
// calibration
tx_data = 0x00A4;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
tx_data = 0x00A6;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
tx_data = 0x0006;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
// set band width
if (narrowBand) {
setupNarrowBand();
} else {
setupWideBand();
}
delay(100);
/*
// setup default values
frequency(446000);
//setVolume1(0xF);
//setVolume2(0xF);
setModeReceive();
setTxSourceMic();
setRfPower(0);
setSQLoThresh(80);
setSQOn();
*/
}
/** Set up the AU1846 in Narrow Band mode (12.5kHz).
*/
void HamShield::setupNarrowBand() {
uint16_t tx_data;
// setup for 12.5kHz channel width
tx_data = 0x3D37;
HSwriteWord(devAddr, 0x11, tx_data);
tx_data = 0x0100;
HSwriteWord(devAddr, 0x12, tx_data);
tx_data = 0x1100;
HSwriteWord(devAddr, 0x15, tx_data);
tx_data = 0x4495;
HSwriteWord(devAddr, 0x32, tx_data); // agc target power [11:6]
tx_data = 0x2B8E;
HSwriteWord(devAddr, 0x34, tx_data);
tx_data = 0x40C3;
HSwriteWord(devAddr, 0x3A, tx_data); // modu_det_sel sq setting
tx_data = 0x0407;
HSwriteWord(devAddr, 0x3C, tx_data); // pk_det_th sq setting [8:7]
tx_data = 0x28D0;
HSwriteWord(devAddr, 0x3F, tx_data); // rssi3_th sq setting
tx_data = 0x203E;
HSwriteWord(devAddr, 0x48, tx_data);
tx_data = 0x1BB7;
HSwriteWord(devAddr, 0x60, tx_data);
tx_data = 0x0A10; // use 0x1425 if there's an LNA
HSwriteWord(devAddr, 0x62, tx_data);
tx_data = 0x2494;
HSwriteWord(devAddr, 0x65, tx_data);
tx_data = 0xEB2E;
HSwriteWord(devAddr, 0x66, tx_data);
// AGC table
tx_data = 0x0001;
HSwriteWord(devAddr, 0x7F, tx_data);
tx_data = 0x000C;
@@ -220,84 +325,80 @@ void HamShield::initialize() {
HSwriteWord(devAddr, 0x7F, tx_data);
// end AGC table
tx_data = 0x067F; //0x0601; //0x470F;
HSwriteWord(devAddr, 0x41, tx_data); // voice gain tx [6:0]
tx_data = 0x02FF; // using 0x04FF to avoid tx voice delay
HSwriteWord(devAddr, 0x44, tx_data); // tx gain [11:8]
tx_data = 0x7F2F;
HSwriteWord(devAddr, 0x47, tx_data);
tx_data = 0x2C62;
HSwriteWord(devAddr, 0x4F, tx_data);
tx_data = 0x0094;
HSwriteWord(devAddr, 0x53, tx_data); // compressor update time (bits 6:0, 5.12ms per unit)
tx_data = 0x2A18;
HSwriteWord(devAddr, 0x54, tx_data);
tx_data = 0x0081;
HSwriteWord(devAddr, 0x55, tx_data);
tx_data = 0x0B22;
HSwriteWord(devAddr, 0x56, tx_data); // sq detect time
tx_data = 0x1C00;
HSwriteWord(devAddr, 0x57, tx_data);
tx_data = 0x800D;
HSwriteWord(devAddr, 0x58, tx_data);
tx_data = 0x0EDD;
HSwriteWord(devAddr, 0x5A, tx_data); // sq and noise detect times
tx_data = 0x3FFF;
HSwriteWord(devAddr, 0x63, tx_data); // pre-emphasis bypass
}
// calibration
tx_data = 0x00A4;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
tx_data = 0x00A6;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
tx_data = 0x0006;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
// setup for 12.5kHz channel width
/** Set up the AU1846 in Wide Band mode (25kHz).
*/
void HamShield::setupWideBand() {
uint16_t tx_data;
// setup for 25kHz channel width
tx_data = 0x3D37;
HSwriteWord(devAddr, 0x11, tx_data);
tx_data = 0x0100;
HSwriteWord(devAddr, 0x12, tx_data);
tx_data = 0x1100;
tx_data = 0x1F00;
HSwriteWord(devAddr, 0x15, tx_data);
tx_data = 0x4495;
tx_data = 0x7564;
HSwriteWord(devAddr, 0x32, tx_data); // agc target power [11:6]
tx_data = 0x2B8E;
HSwriteWord(devAddr, 0x34, tx_data);
tx_data = 0x40C3;
tx_data = 0x44C3;
HSwriteWord(devAddr, 0x3A, tx_data); // modu_det_sel sq setting
tx_data = 0x0407;
tx_data = 0x1930;
HSwriteWord(devAddr, 0x3C, tx_data); // pk_det_th sq setting [8:7]
tx_data = 0x28D0;
tx_data = 0x29D2;
HSwriteWord(devAddr, 0x3F, tx_data); // rssi3_th sq setting
tx_data = 0x203E;
tx_data = 0x21C0;
HSwriteWord(devAddr, 0x48, tx_data);
tx_data = 0x1BB7;
tx_data = 0x101E;
HSwriteWord(devAddr, 0x60, tx_data);
tx_data = 0x0A10; // use 0x1425 if there's an LNA
tx_data = 0x3767; // use 0x1425 if there's an LNA
HSwriteWord(devAddr, 0x62, tx_data);
tx_data = 0x2494;
tx_data = 0x248A;
HSwriteWord(devAddr, 0x65, tx_data);
tx_data = 0xEB2E;
tx_data = 0xFFAE;
HSwriteWord(devAddr, 0x66, tx_data);
delay(100);
/*
// setup default values
frequency(446000);
//setVolume1(0xF);
//setVolume2(0xF);
setModeReceive();
setTxSourceMic();
setRfPower(0);
setSQLoThresh(80);
setSQOn();
*/
// AGC table
tx_data = 0x0001;
HSwriteWord(devAddr, 0x7F, tx_data);
tx_data = 0x000C;
HSwriteWord(devAddr, 0x05, tx_data);
tx_data = 0x0024;
HSwriteWord(devAddr, 0x06, tx_data);
tx_data = 0x0214;
HSwriteWord(devAddr, 0x07, tx_data);
tx_data = 0x0224;
HSwriteWord(devAddr, 0x08, tx_data);
tx_data = 0x0314;
HSwriteWord(devAddr, 0x09, tx_data);
tx_data = 0x0324;
HSwriteWord(devAddr, 0x0A, tx_data);
tx_data = 0x0344;
HSwriteWord(devAddr, 0x0B, tx_data);
tx_data = 0x0384;
HSwriteWord(devAddr, 0x0C, tx_data);
tx_data = 0x1384;
HSwriteWord(devAddr, 0x0D, tx_data);
tx_data = 0x1B84;
HSwriteWord(devAddr, 0x0E, tx_data);
tx_data = 0x3F84;
HSwriteWord(devAddr, 0x0F, tx_data);
tx_data = 0xE0EB;
HSwriteWord(devAddr, 0x12, tx_data);
tx_data = 0xF2FE;
HSwriteWord(devAddr, 0x13, tx_data);
tx_data = 0x0A16;
HSwriteWord(devAddr, 0x14, tx_data);
tx_data = 0x2424;
HSwriteWord(devAddr, 0x15, tx_data);
tx_data = 0x2424;
HSwriteWord(devAddr, 0x16, tx_data);
tx_data = 0x2424;
HSwriteWord(devAddr, 0x17, tx_data);
tx_data = 0x0000;
HSwriteWord(devAddr, 0x7F, tx_data);
// end AGC table
}
/** Verify the I2C connection.
@@ -1283,6 +1384,29 @@ bool HamShield::waitForChannel(long timeout = 0, long breakwindow = 0, int setRS
return false;
}
// Get current morse code tone frequency (in Hz)
unsigned int HamShield::getMorseFreq() {
return morse_freq;
}
// Set current morse code tone frequency (in Hz)
void HamShield::setMorseFreq(unsigned int morse_freq_hz) {
morse_freq = morse_freq_hz;
}
// Get current duration of a morse dot (shorter is more WPM)
unsigned int HamShield::getMorseDotMillis() {
return morse_dot_millis;
}
// Set current duration of a morse dot (shorter is more WPM)
void HamShield::setMorseDotMillis(unsigned int morse_dot_dur_millis) {
morse_dot_millis = morse_dot_dur_millis;
}
/* Morse code out, blocking */
@@ -1295,11 +1419,11 @@ void HamShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) {
// We delay by 4 here, if we previously sent a symbol. Otherwise 7.
// This could probably just be always 7 and go relatively unnoticed.
if(prev == 0 || prev == ' '){
tone(HAMSHIELD_PWM_PIN, 6000, HAMSHIELD_MORSE_DOT * 7);
delay(HAMSHIELD_MORSE_DOT*7);
tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis * 7);
delay(morse_dot_millis*7);
} else {
tone(HAMSHIELD_PWM_PIN, 6000, HAMSHIELD_MORSE_DOT * 4);
delay(HAMSHIELD_MORSE_DOT*4);
tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis * 4);
delay(morse_dot_millis*4);
}
continue;
}
@@ -1308,20 +1432,20 @@ void HamShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) {
if(bits) { // If it is a valid character...
do {
if(bits & 1) {
tone(HAMSHIELD_PWM_PIN, 600, HAMSHIELD_MORSE_DOT * 3);
delay(HAMSHIELD_MORSE_DOT*3);
tone(HAMSHIELD_PWM_PIN, morse_freq, morse_dot_millis * 3);
delay(morse_dot_millis*3);
} else {
tone(HAMSHIELD_PWM_PIN, 600, HAMSHIELD_MORSE_DOT);
delay(HAMSHIELD_MORSE_DOT);
tone(HAMSHIELD_PWM_PIN, morse_freq, morse_dot_millis);
delay(morse_dot_millis);
}
tone(HAMSHIELD_PWM_PIN, 6000, HAMSHIELD_MORSE_DOT);
delay(HAMSHIELD_MORSE_DOT);
tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis);
delay(morse_dot_millis);
bits >>= 1; // Shift into the next symbol
} while(bits != 1); // Wait for 1 termination to be all we have left
}
// End of character
tone(HAMSHIELD_PWM_PIN, 6000, HAMSHIELD_MORSE_DOT * 3);
delay(HAMSHIELD_MORSE_DOT * 3);
tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis * 3);
delay(morse_dot_millis * 3);
}
return;
}

View File

@@ -16,7 +16,6 @@
// HamShield constants
#define HAMSHIELD_MORSE_DOT 100 // Morse code dot length (smaller is faster WPM)
#define HAMSHIELD_MORSE_BUFFER_SIZE 80 // Char buffer size for morse code text
#define HAMSHIELD_AUX_BUTTON 2 // Pin assignment for AUX button
#define HAMSHIELD_PWM_PIN 3 // Pin assignment for PWM output
@@ -256,7 +255,10 @@ class HamShield {
HamShield();
HamShield(uint8_t cs_pin);
void initialize();
void initialize(); // defaults to 12.5kHz
void initialize(bool narrowBand); // select 12.5kHz if true or 25kHz if false
void setupWideBand();
void setupNarrowBand();
bool testConnection();
// read control reg
@@ -481,6 +483,10 @@ class HamShield {
void buttonMode(uint8_t mode);
static void isr_ptt();
static void isr_reset();
unsigned int getMorseFreq();
void setMorseFreq(unsigned int morse_freq_hz);
unsigned int getMorseDotMillis();
void setMorseDotMillis(unsigned int morse_dot_dur_millis);
void morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]);
uint8_t morseLookup(char letter);
bool waitForChannel(long timeout, long breakwindow, int setRSSI);