24 Commits
1.1.1 ... 1.1.3

Author SHA1 Message Date
Morgan Redfield
3d3f6a36b6 update dtmf, morse, and examples 2019-07-14 13:37:14 -07:00
Morgan Redfield
71acbbb975 update DTMF tx and rx 2019-06-01 18:09:15 -07:00
Morgan Redfield
6472b103b4 update Morse 2019-06-01 15:25:56 -07:00
Morgan Redfield
7e509ca0fc minor morse updates 2019-05-11 15:32:13 -07:00
Morgan Redfield
12fd074aed let HSTone be generated by HamShield itself 2019-04-28 11:41:29 -07:00
Morgan Redfield
1d0eb281e2 serial messenger bug fixes 2019-04-12 11:50:17 -07:00
Morgan Redfield
7941388980 adding in HandyTalkie_nrf52840 2019-04-06 14:00:45 -07:00
Morgan Redfield
f83b547de4 merge RPi branch in, add Feather nRF52840 Express example BLE sketch 2019-04-06 14:00:03 -07:00
Morgan Redfield
b147edfcfa minor bug fix 2019-03-24 15:17:45 -07:00
Morgan Redfield
3c3d83c057 unify pin naming scheme 2019-03-15 10:43:15 -07:00
Morgan Redfield
9d708e4046 update afsk_messenger example 2019-02-10 12:01:09 -08:00
Morgan Redfield
250dd330b7 noTone bugfixes 2019-02-04 17:41:35 -08:00
Morgan Redfield
289d1f73a8 removing duration from tone calls 2019-02-04 15:25:29 -08:00
morgan
00fd294bde working with RPi 2019-02-04 21:28:59 +00:00
morgan
1b1c9b3f80 fix noTone calls 2019-02-02 21:22:37 +00:00
morgan
467765d892 update tone calls 2019-02-02 21:16:33 +00:00
morgan
844bb6b8c6 finish abstraction for RPi 2019-02-02 21:13:21 +00:00
Morgan Redfield
f7c76eb1ad begin abstracting hardware functions 2019-01-29 21:10:18 -08:00
morgan
76a92a882f remove library control of button 2019-01-29 20:13:45 -08:00
morgan
7427b426b1 allow non-standard digital control pins 2019-01-29 20:09:42 -08:00
Morgan Redfield
6b05b7754d update vox and mic signal strength reading 2019-01-19 11:42:39 -08:00
morgan
6c891c9f32 update example comments 2018-12-09 09:43:41 -08:00
morgan
d65877ad29 update library properties 2018-11-17 11:43:59 -08:00
morgan
dc93752730 temporary fixes for KISS example 2018-11-07 16:45:46 -08:00
21 changed files with 1366 additions and 589 deletions

View File

@@ -12,7 +12,7 @@
* To send a message: connect to the Arduino over a Serial link.
* Send the following over the serial link:
* `from,to,:message
* example: * `KG7OGM,KG7OGM,:Hi there
* example: * KG7OGM,KG7OGM,:Hi there`
*/
@@ -22,7 +22,7 @@
#include <packet.h>
#include <avr/wdt.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -37,8 +37,8 @@ int msgptr = 0;
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -52,14 +52,14 @@ void setup() {
Serial.begin(9600);
radio.initialize();
radio.frequency(145570);
radio.frequency(144390); // default aprs frequency in North America
radio.setRfPower(0);
radio.setVolume1(0xFF);
radio.setVolume2(0xFF);
radio.setSQHiThresh(-100);
radio.setSQLoThresh(-100);
radio.setSQOn();
//radio.bypassPreDeEmph();
//radio.setSQOn();
radio.bypassPreDeEmph();
dds.start();
afsk.start(&dds);
delay(100);
@@ -74,6 +74,7 @@ void loop() {
//Serial.println(messagebuff);
prepMessage();
msgptr = 0;
messagebuff = "";
Serial.print("!!");
}
else {

View File

@@ -5,7 +5,7 @@
#include <HamShield.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -17,8 +17,8 @@ uint8_t pl_rx_buffer[32];
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -36,7 +36,7 @@ void setup() {
Serial.println("Setting radio to its defaults..");
radio.initialize();
radio.setRfPower(0);
radio.frequency(146520);
radio.frequency(432100); // 70cm calling frequency
radio.setModeReceive();
}

View File

@@ -29,7 +29,7 @@ HamShield radio;
#define LED_PIN 13
#define RSSI_REPORT_RATE_MS 5000
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -43,8 +43,8 @@ unsigned long rssi_timeout;
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -75,13 +75,11 @@ void setup() {
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
Serial.println("setting default Radio configuration");
radio.dangerMode();
// set frequency
Serial.println("changing frequency");
radio.setSQOff();
freq = 446000;
freq = 432100; // 70cm calling frequency
radio.frequency(freq);
// set to receive
@@ -92,6 +90,11 @@ void setup() {
Serial.println(radio.readCtlReg());
Serial.println(radio.readRSSI());
// set up squelch
radio.setSQLoThresh(-80);
radio.setSQHiThresh(-70);
radio.setSQOn();
radio.setRfPower(0);
// CTCSS Setup code

View File

@@ -14,7 +14,7 @@
#include <HamShield.h>
#include <DDS.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -26,8 +26,8 @@ DDS dds;
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);

View File

@@ -1,12 +1,12 @@
/* Hamshield
* Example: DTMF
* This is a simple example to demonstrate how to ues DTMF.
* This is a simple example to demonstrate how to use DTMF.
*
* 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, open
* the Serial Monitor. Press the button on the HamShield to
* the Serial Monitor. Press the switch on the HamShield to
* begin setup. After setup is complete, type in a DTMF value
* (0-9, A, B, C, D, *, #) and hit enter. The corresponding
* DTMF tones will be transmitted. The sketch will also print
@@ -20,7 +20,7 @@ HamShield radio;
#define LED_PIN 13
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -28,8 +28,8 @@ uint32_t freq;
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -45,7 +45,7 @@ void setup() {
while (digitalRead(SWITCH_PIN));
// let the AU ot of reset
// now we let the AU ot of reset
digitalWrite(RESET_PIN, HIGH);
delay(5); // wait for device to come up
@@ -56,7 +56,7 @@ void setup() {
Serial.println(radio.testConnection() ? "HamShield connection successful" : "HamShield connection failed");
// initialize device
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
radio.initialize();
Serial.println("setting default Radio configuration");
@@ -71,11 +71,11 @@ void setup() {
radio.setSQOn();
//radio.setSQOff();
Serial.println("changing frequency");
freq = 420000;
Serial.println("setting frequency to: ");
freq = 432100; // 70cm calling frequency
radio.frequency(freq);
Serial.print("new frequency: ");
Serial.println(radio.getFrequency());
Serial.print(radio.getFrequency());
Serial.println("kHz");
// set RX volume to minimum to reduce false positives on DTMF rx
radio.setVolume1(6);
@@ -104,40 +104,25 @@ void setup() {
Serial.println("ready");
}
char rx_dtmf_buf[255];
int rx_dtmf_idx = 0;
void loop() {
// look for tone
if (radio.getDTMFSample() != 0) {
uint16_t code = radio.getDTMFCode();
rx_dtmf_buf[rx_dtmf_idx++] = code2char(code);
// reset after this tone
int j = 0;
while (j < 4) {
if (radio.getDTMFSample() == 0) {
j++;
}
delay(10);
}
} else if (rx_dtmf_idx > 0) {
rx_dtmf_buf[rx_dtmf_idx] = '\0'; // NULL terminate the string
Serial.println(rx_dtmf_buf);
rx_dtmf_idx = 0;
char m = radio.DTMFRxLoop();
if (m != 0) {
Serial.print(m);
}
// Is it time to send tone?
if (Serial.available()) {
uint8_t code = char2code(Serial.read());
// get first code
uint8_t code = radio.DTMFchar2code(Serial.read());
// start transmitting
radio.setDTMFCode(code); // set first
radio.setTxSourceTones();
radio.setModeTransmit();
delay(300); // wait for TX to come to full power
bool dtmf_to_tx = true;
while (dtmf_to_tx) {
// wait until ready
@@ -145,56 +130,23 @@ void loop() {
// wait until we're ready for a new code
delay(10);
}
if (Serial.available()) {
code = radio.DTMFchar2code(Serial.read());
if (code == 255) code = 0xE; // throw a * in there so we don't break things with an invalid code
radio.setDTMFCode(code); // set first
} else {
dtmf_to_tx = false;
break;
}
while (radio.getDTMFTxActive() != 0) {
// wait until this code is done
delay(10);
}
if (Serial.available()) {
code = char2code(Serial.read());
if (code == 255) code = 0xE; // throw a * in there so we don't break things with an invalid code
radio.setDTMFCode(code); // set first
} else {
dtmf_to_tx = false;
}
}
// done with tone
radio.setModeReceive();
radio.setTxSourceMic();
}
}
uint8_t char2code(char c) {
uint8_t code;
if (c == '#') {
code = 0xF;
} else if (c=='*') {
code = 0xE;
} else if (c >= 'A' && c <= 'D') {
code = c - 'A' + 0xA;
} else if (c >= '0' && c <= '9') {
code = c - '0';
} else {
// invalid code, skip it
code = 255;
}
return code;
}
char code2char(uint16_t code) {
char c;
if (code < 10) {
c = '0' + code;
} else if (code < 0xE) {
c = 'A' + code - 10;
} else if (code == 0xE) {
c = '*';
} else if (code == 0xF) {
c = '#';
} else {
c = '?'; // invalid code
}
return c;
}

View File

@@ -16,7 +16,7 @@
#define DDS_REFCLK_DEFAULT 9600
#include <HamShield.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -25,8 +25,8 @@ HamShield radio;
// Run our start up things here
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -57,8 +57,8 @@ void setup() {
radio.setMorseFreq(600);
radio.setMorseDotMillis(100);
// Configure the HamShield to operate on 438.000MHz
radio.frequency(438000);
// Configure the HamShield
radio.frequency(432300); // 70cm beacon frequency
Serial.println("Radio Configured.");
}

View File

@@ -15,7 +15,7 @@
#include <HamShield.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -29,8 +29,8 @@ 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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -61,8 +61,8 @@ void setup() {
radio.setMorseFreq(600);
radio.setMorseDotMillis(100);
// Configure the HamShield to operate on 438.000Mhz
radio.frequency(438000);
// Configure the HamShield frequency
radio.frequency(432400);
Serial.println("Radio configured.");
}
@@ -79,7 +79,7 @@ void loop() {
radio.setModeTransmit();
// Generate a 600Hz tone for TRANSMITLENGTH time
tone(PWM_PIN, 600, TRANSMITLENGTH);
tone(MIC_PIN, 600, TRANSMITLENGTH);
delay(TRANSMITLENGTH);
// Identify the transmitter

View File

@@ -20,11 +20,13 @@
// create object for radio
HamShield radio;
// To use non-standard pins, use the following initialization
//HamShield radio(ncs_pin, clk_pin, dat_pin);
#define LED_PIN 13
#define RSSI_REPORT_RATE_MS 5000
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -37,8 +39,8 @@ unsigned long rssi_timeout;
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -50,9 +52,10 @@ void setup() {
// initialize serial communication
Serial.begin(9600);
Serial.println("press the switch to begin...");
Serial.println("press the switch or send any character to begin...");
while (digitalRead(SWITCH_PIN));
while (digitalRead(SWITCH_PIN) && !Serial.available());
Serial.read(); // flush
// let the AU ot of reset
digitalWrite(RESET_PIN, HIGH);
@@ -69,13 +72,12 @@ void setup() {
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
Serial.println("setting default Radio configuration");
radio.dangerMode();
// set frequency
Serial.println("changing frequency");
radio.setSQOff();
freq = 446000;
freq = 432100; // 70cm calling frequency
radio.frequency(freq);
// set to receive

View File

@@ -0,0 +1,282 @@
/* Hamshield
* Example: HandyTalkie_nRF52840
* This is a simple example to demonstrate the HamShield working
* with an Adafruit Feather nRF52840 Express
*
* HamShield to Feather Connections:
* SPKR - Feather A0
* MIC - Feather D11
* CLK - Feather D5
* nCS - Feather D6
* DAT - Feather D9
* GND - Feather GND
* VCC - Feather 3.3V
*
* Connect the HamShield to your Feather as above.
* Screw the antenna into the HamShield RF jack. Plug a pair
* of headphones into the HamShield.
*
* Connect the Feather nRF52840 Express to your computer via
* a USB Micro B cable. After uploading this program to
* your Feather, open the Serial Monitor. You should see some
* text displayed that documents the setup process.
*
* Once the Feather is set up and talking to the HamShield,
* you can control it over USB-Serial or BLE-Serial(UART).
*
* Try using Adafruit's Bluefruit app to connect to the Feather.
* Once you're connected, you can control the HamShield using
* the same commands you'd use over USB-Serial. The response to
* all commands will be echoed to both USB-Serial and BLE-Serial(UART).
*
* Serial UART commands:
* t - change from Tx to Rx (or vice versa)
* F123400 - set frequency to 123400 kHz
*/
#include <bluefruit.h>
// BLE Service
BLEDis bledis; // device information
BLEUart bleuart; // uart over ble
BLEBas blebas; // battery
#include <HamShield.h>
// create object for radio
HamShield radio(9,5,6);
// To use non-standard pins, use the following initialization
//HamShield radio(ncs_pin, clk_pin, dat_pin);
#define LED_PIN 3
#define RSSI_REPORT_RATE_MS 5000
#define MIC_PIN A1
bool blinkState = false;
bool currently_tx;
uint32_t freq;
unsigned long rssi_timeout;
void setup() {
// NOTE: if not using PWM out, it should be held low to avoid tx noise
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// initialize serial communication
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Setting up BLE");
// Setup the BLE LED to be enabled on CONNECT
// Note: This is actually the default behaviour, but provided
// here in case you want to control this LED manually via PIN 19
Bluefruit.autoConnLed(true);
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(4);
Bluefruit.setName("MyBlueHam");
//Bluefruit.setName(getMcuUniqueID()); // useful testing with multiple central connections
Bluefruit.setConnectCallback(connect_callback);
Bluefruit.setDisconnectCallback(disconnect_callback);
// Configure and Start Device Information Service
bledis.setManufacturer("Enhanced Radio Devices");
bledis.setModel("BlueHam");
bledis.begin();
// Configure and Start BLE Uart Service
bleuart.begin();
// Start BLE Battery Service
blebas.begin();
blebas.write(100);
// Set up and start advertising
startAdv();
delay(100);
Serial.println("beginning Ham radio setup");
// verify connection
Serial.println("Testing device connections...");
if (radio.testConnection()) {
Serial.println("HamShield connection successful");
} else {
Serial.print("HamShield connection failed");
while(1) delay(100);
}
// 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.setSQOff();
freq = 432100; // 70cm calling frequency
radio.frequency(freq);
// set to receive
radio.setModeReceive();
currently_tx = false;
Serial.print("config register is: ");
Serial.println(radio.readCtlReg());
Serial.println(radio.readRSSI());
/*
// set to transmit
radio.setModeTransmit();
// maybe set PA bias voltage
Serial.println("configured for transmit");
radio.setTxSourceMic();
*/
radio.setRfPower(0);
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
rssi_timeout = 0;
}
void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(bleuart);
// Secondary Scan Response packet (optional)
// Since there is no room for 'Name' in Advertising packet
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
#define TEXT_BUF_LEN 64
char text_buf[TEXT_BUF_LEN];
void loop() {
char c = 0;
bool ble_serial = false;
if (Serial.available()) {
Serial.readBytes(&c, 1);
} else if (bleuart.available()) {
c = (char) bleuart.read();
ble_serial = true;
}
if (c != 0) {
if (c == 't')
{
if (!currently_tx)
{
currently_tx = true;
// set to transmit
radio.setModeTransmit();
Serial.println("Tx");
int str_len = snprintf(text_buf, TEXT_BUF_LEN, "Tx\n");
bleuart.write(text_buf, str_len);
//radio.setTxSourceMic();
//radio.setRfPower(1);
} else {
radio.setModeReceive();
currently_tx = false;
Serial.println("Rx");
int str_len = snprintf(text_buf, TEXT_BUF_LEN, "Rx\n");
bleuart.write(text_buf, str_len);
}
} else if (c == 'F') {
if (ble_serial == false) {
Serial.setTimeout(40);
freq = Serial.parseInt();
Serial.flush();
} else {
int idx = 0;
while (bleuart.available() &&
bleuart.peek() >= '0' &&
bleuart.peek() <= '9' &&
idx < TEXT_BUF_LEN) {
text_buf[idx] = bleuart.read();
idx++;
}
text_buf[idx] = 0; // null terminate
freq = atoi(text_buf);
}
radio.frequency(freq);
Serial.print("set frequency: ");
Serial.println(freq);
int str_len = snprintf(text_buf, TEXT_BUF_LEN, "set frequency: %d\n", freq);
bleuart.write(text_buf, str_len);
}
}
if (!currently_tx && (millis() - rssi_timeout) > RSSI_REPORT_RATE_MS)
{
int rssi = radio.readRSSI();
Serial.println(rssi);
int str_len = snprintf(text_buf, TEXT_BUF_LEN, "rssi: %d\n", rssi);
bleuart.write(text_buf, str_len);
rssi_timeout = millis();
}
}
// callback invoked when central connects
void connect_callback(uint16_t conn_handle)
{
char central_name[32] = { 0 };
Bluefruit.Gap.getPeerName(conn_handle, central_name, sizeof(central_name));
Serial.print("Connected to ");
Serial.println(central_name);
}
/**
* Callback invoked when a connection is dropped
* @param conn_handle connection where this event happens
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
* https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void) conn_handle;
(void) reason;
Serial.println();
Serial.println("Disconnected");
}

View File

@@ -7,6 +7,11 @@
* into the HamShield RF jack. Connect the Arduino to wall
* power and then to your computer via USB. Issue commands
* via the KISS equipment.
*
* You can also just use the serial terminal to send and receive
* APRS packets, but keep in mind that several fields in the packet
* are bit-shifted from standard ASCII (so if you're receiving,
* you won't get human readable callsigns or paths).
*
* To use the KISS example with YAAC:
* 1. open the configure YAAC wizard
@@ -30,14 +35,14 @@ DDS dds;
AFSK afsk;
KISS kiss(&Serial, &radio, &dds, &afsk);
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -55,9 +60,9 @@ void setup() {
radio.setVolume2(0xFF);
radio.setSQHiThresh(-100);
radio.setSQLoThresh(-100);
radio.setSQOn();
//radio.setSQOn();
radio.frequency(144390);
//radio.bypassPreDeEmph();
radio.bypassPreDeEmph();
dds.start();
afsk.start(&dds);

View File

@@ -10,46 +10,40 @@
* monitor the status of the beacon. To test, set a HandyTalkie
* to 438MHz. You should hear the message " CALLSIGN HAMSHIELD"
* in morse code.
*
*
* Note: only upper case letters, numbers, and a few symbols
* are supported.
* Supported symbols: &/+(=:?";@`-._),!$
*
* If you're having trouble accurately decoding, you may want to
* tweak the min/max . and - times. You can also uncomment
* the Serial.print debug statements that can tell you when tones
* are being detected, how long they're detected for, and whether
* the tones are decoded as a . or -.
*
*/
#define DDS_REFCLK_DEFAULT 9600
#include <HamShield.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
#define MORSE_FREQ 600
#define MORSE_DOT 100 // ms
#define MORSE_DOT 150 // ms
// Note that all timing is defined in terms of MORSE_DOT relative durations
// You may want to tweak those timings below
#define SYMBOL_END_TIME 5 //millis
#define CHAR_END_TIME (MORSE_DOT*2.3)
#define MESSAGE_END_TIME (MORSE_DOT*15)
#define MIN_DOT_TIME (MORSE_DOT*0.7)
#define MAX_DOT_TIME (MORSE_DOT*1.3)
#define MIN_DASH_TIME (MORSE_DOT*2.7)
#define MAX_DASH_TIME (MORSE_DOT*3.3)
HamShield radio;
uint32_t last_tone_check; // track how often we check for morse tones
uint32_t tone_in_progress; // track how long the current tone lasts
uint32_t space_in_progress; // track how long since the last tone
uint8_t rx_morse_char;
uint8_t rx_morse_bit;
char rx_msg[128];
uint8_t rx_idx;
// Run our start up things here
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -80,63 +74,19 @@ void setup() {
radio.setMorseDotMillis(MORSE_DOT);
radio.lookForTone(MORSE_FREQ);
// Configure the HamShield to operate on 438.000MHz
radio.frequency((uint32_t) 438000);
radio.setupMorseRx();
// Configure the HamShield frequency
radio.frequency(432100); // 70cm calling frequency
radio.setModeReceive();
Serial.println("Radio Configured.");
last_tone_check = millis();
space_in_progress = 0; // haven't checked yet
tone_in_progress = 0; // not currently listening to a tone
rx_morse_char = 0; // haven't found any tones yet
rx_idx = 0;
rx_morse_bit = 1;
}
void loop() {
// are we receiving anything
if (radio.toneDetected()) {
space_in_progress = 0;
if (tone_in_progress == 0) {
// start a new tone
tone_in_progress = millis();
}
} else {
// keep track of how long the silence is
if (space_in_progress == 0) space_in_progress = millis();
// we wait for a bit of silence before ending the last
// symbol in order to smooth out the detector
if ((millis() - space_in_progress) > SYMBOL_END_TIME)
{
if (tone_in_progress != 0) {
// end the last tone
uint16_t tone_time = millis() - tone_in_progress;
tone_in_progress = 0;
handleTone(tone_time);
}
}
// we might be done with a character if the space is long enough
if ((millis() - space_in_progress) > CHAR_END_TIME) {
char m = parseMorse();
if (m != 0) {
rx_msg[rx_idx++] = m;
}
}
// we might be done with a message if the space is long enough
if ((millis() - space_in_progress) > MESSAGE_END_TIME) {
if (rx_idx > 0) {
// we got a message, print it now
rx_msg[rx_idx] = '\0'; // null terminate
Serial.println(rx_msg);
rx_idx = 0; // reset message buffer
}
rx_morse_char = 0;
rx_morse_bit = 1;
}
char rx_char = radio.morseRxLoop();
if (rx_char != 0) {
Serial.print(rx_char);
}
// should we send anything
@@ -145,9 +95,11 @@ void loop() {
// We'll wait up to 30 seconds for a clear channel, requiring that the channel is clear for 2 seconds before we transmit
if (radio.waitForChannel(30000,2000,-5)) {
// If we get here, the channel is clear.
Serial.println("sending");
// Start transmitting by putting the radio into transmit mode.
radio.setModeTransmit();
Serial.println("tx");
unsigned int MORSE_BUF_SIZE = 128;
char morse_buf[MORSE_BUF_SIZE];
unsigned int morse_idx;
@@ -161,8 +113,9 @@ void loop() {
radio.morseOut(morse_buf);
// We're done sending the message, set the radio back into recieve mode.
radio.setModeReceive();
Serial.println("sent");
radio.setModeReceive();
radio.lookForTone(MORSE_FREQ);
} else {
// If we get here, the channel is busy. Let's also print out the RSSI.
Serial.print("The channel was busy. RSSI: ");
@@ -171,33 +124,4 @@ void loop() {
}
}
void handleTone(uint16_t tone_time) {
//Serial.println(tone_time);
if (tone_time > MIN_DOT_TIME && tone_time < MAX_DOT_TIME) {
// add a dot
//Serial.print(".");
//nothing to do for this bit position, since . = 0
} else if (tone_time > MIN_DASH_TIME && tone_time < MAX_DASH_TIME) {
// add a dash
//Serial.print("-");
rx_morse_char += rx_morse_bit;
}
// prep for the next bit
rx_morse_bit = rx_morse_bit << 1;
}
char parseMorse() {
// if morse_char is a valid morse character, return the character
// if morse_char is an invalid (incomplete) morse character, return 0
//if (rx_morse_bit != 1) Serial.println(rx_morse_char, BIN);
rx_morse_char += rx_morse_bit; // add the terminator bit
// if we got a char, then print it
char c = radio.morseReverseLookup(rx_morse_char);
rx_morse_char = 0;
rx_morse_bit = 1;
return c;
}

View File

@@ -10,7 +10,7 @@
* 446MHz to receive the image output.
*/
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -28,8 +28,8 @@ int16_t rssi;
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);

View File

@@ -16,7 +16,7 @@
#include <HamShield.h>
#include <DDS.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -32,8 +32,8 @@ ddsAccumulator_t freqTable[3];
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -54,7 +54,7 @@ void setup() {
// Tell the HamShield to start up
radio.initialize();
radio.setRfPower(0);
radio.frequency(145500);
radio.frequency(446000);
// put your setup code here, to run once:
//dds.setReferenceClock(34965/4);
dds.start();

View File

@@ -15,22 +15,32 @@
* R1;
* [Just a space]
// see also: https://github.com/EnhancedRadioDevices/HamShield/wiki/HamShield-Serial-Mode
Commands:
Mode ASCII Description Implemented
-------------- ----------- -------------------------------------------------------------------------------------------------------------------------------------------- -----------------
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
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
Mode ASCII Description
-------------- ----------- --------------------------------------------------------------------------------------------------------------------------------------------
Transmit space Space must be received at least every 500 mS
Receive not space If space is not received and/or 500 mS timeout of space occurs, unit will go into receive mode
Frequency F<freq>; Set the receive frequency in KHz, if offset is disabled, this is the transmit frequency
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
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)
Morse In N; Sets mode to Morse In, listening for Morse
Power level P<level>; Set the power amp level, 0 = lowest, 15 = highest
Enable Offset R<state>; 1 turns on repeater offset mode, 0 turns off repeater offset mode
Squelch S<level>; Set the squelch level
TX Offset T<freq>; The absolute frequency of the repeater offset to transmit on in KHz
RSSI ? Respond with the current receive level in - dBm (no sign provided on numerical response)
Voice Level ^ Respond with the current voice level (VSSI), only valid when transmitting
DTMF Out D<vals>; A small buffer for DTMF out (only 0-9,A,B,C,D,*,# accepted)
DTMF In B; Sets mode to DTMF In, listening for DTMF
PL Tone Tx A<val>; Sets PL tone for TX, value is tone frequency in Hz (float), set to 0 to disable
PL Tone Rx C<val>; Sets PL tone for RX, value is tone frequency in Hz (float), set to 0 to disable
Volume 1 V1<val>; Set volume 1 (value between 0 and 15)
Volume 2 V2<val>; Set volume 2 (value between 0 and 15)
KISS TNC K; Move to KISS TNC mode (send ^; to move back to normal mode). NOT IMPELEMENTED YET
Normal Mode _ Move to Normal mode from any other mode (except TX)
Responses:
@@ -42,23 +52,44 @@ Error X<code>; Indicates an error code. The numerical value is the type
Value :<value>; In response to a query
Status #<value>; Unsolicited status message
Debug Msg @<text>; 32 character debug message
Rx Msg R<text>; up to 32 characters of received message, only if device is in DTMF or Morse Rx modes
*/
// Note that the following are not yet implemented
// TODO: change get_value so it's intuitive
// TODO: Squelch open and squelch shut independently controllable
// TODO: pre/de emph filter
// TODO: walkie-talkie
// TODO: KISS TNC
#include "HamShield.h"
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
int state;
enum {TX, NORMAL, DTMF, MORSE, KISS};
int state = NORMAL;
bool rx_ctcss = false;
bool muted = false;
int txcount = 0;
long timer = 0;
long freq = 144390;
long tx = 0;
long timer = 0; // Transmit timer to track timeout (send space to reset)
long freq = 432100; // 70cm calling frequency, receive frequency and default transmit frequency
long tx_freq = 0; // transmit frequency if repeater is on
int pwr = 0; // tx power
char cmdbuff[32] = "";
int temp = 0;
int repeater = 0;
bool repeater = false; // true if transmit and receive operate on different frequencies
char pl_rx_buffer[32]; // pl tone rx buffer
char pl_tx_buffer[32]; // pl tone tx buffer
float ctcssin = 0;
float ctcssout = 0;
int cdcssin = 0;
@@ -67,12 +98,10 @@ int cdcssout = 0;
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);
// NOTE: if not using PWM out (MIC pin), it should be held low to avoid tx noise
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -80,7 +109,6 @@ void setup() {
// set up the reset control pin
pinMode(RESET_PIN, OUTPUT);
digitalWrite(RESET_PIN, HIGH);
delay(5); // wait for device to come up
Serial.begin(9600);
Serial.println(";;;;;;;;;;;;;;;;;;;;;;;;;;");
@@ -90,137 +118,444 @@ void setup() {
Serial.print(result,DEC);
Serial.println(";");
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
Serial.println("*START;");
radio.frequency(freq);
radio.setVolume1(0xF);
radio.setVolume2(0xF);
radio.setModeReceive();
radio.setTxSourceMic();
radio.setRfPower(0);
radio.setSQLoThresh(80);
radio.setRfPower(pwr);
radio.setSQLoThresh(-80);
radio.setSQHiThresh(-70);
radio.setSQOn();
Serial.println("*START;");
}
void loop() {
if(Serial.available()) {
int text = Serial.read();
int text = Serial.read(); // get the first char to see what the upcoming command is
switch (state) {
case 10:
if(text == 32) { timer = millis();}
switch (state) {
// we handle commands differently based on what state we're in
case TX:
// we're currently transmitting
// if we got a space, reset our transmit timeout
if(text == ' ') { timer = millis();}
break;
case 0:
switch(text) {
case NORMAL:
switch(text) {
case ' ': // space - transmit
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
muted = false; // can't mute (for PL tones) during tx
radio.setUnmute();
radio.setModeTransmit();
state = TX;
Serial.println("#TX,ON;");
timer = millis();
break;
case 32: // space - transmit
if(repeater == 1) { radio.frequency(tx); }
radio.setModeTransmit();
state = 10;
Serial.println("#TX,ON;");
timer = millis();
break;
case 63: // ? - RSSI
Serial.print(":");
Serial.print(radio.readRSSI(),DEC);
Serial.println(";");
break;
case 65: // A - CTCSS In
getValue();
ctcssin = atof(cmdbuff);
radio.setCtcss(ctcssin);
break;
case 66: // B - CTCSS Out
break;
case 67: // C - CTCSS Enable
break;
case '?': // ? - RSSI
Serial.print(":");
Serial.print(radio.readRSSI(),DEC);
Serial.println(";");
break;
case 68: // D - CDCSS Enable
break;
case '^': // ^ - VSSI (voice) level
Serial.print(":");
Serial.print(radio.readVSSI(),DEC);
Serial.println(";");
break;
case 70: // F - frequency
getValue();
freq = atol(cmdbuff);
if(radio.frequency(freq) == true) { Serial.print("@"); Serial.print(freq,DEC); Serial.println(";!;"); } else { Serial.println("X1;"); }
break;
case 'F': // F - frequency
getValue();
freq = atol(cmdbuff);
if(radio.frequency(freq) == true) {
Serial.print("@");
Serial.print(freq,DEC);
Serial.println(";!;");
} else {
Serial.println("X1;");
}
break;
case 'P': // P - power level
getValue();
temp = atol(cmdbuff);
radio.setRfPower(temp);
Serial.println("!;");
break;
case 'S': // S - squelch
getValue();
temp = atol(cmdbuff);
if (temp < -2 && temp > -130) {
radio.setSQLoThresh(temp);
radio.setSQHiThresh(temp+2);
radio.setSQOn();
Serial.print(temp);
Serial.println("!;");
} else {
Serial.println("X!;");
}
break;
case 'R': // R - repeater offset mode
getValue();
temp = atol(cmdbuff);
if(temp == 0) { repeater = 0; }
if(temp == 1) { repeater = 1; }
Serial.println("!;");
break;
case 'T': // T - transmit offset
getValue();
tx_freq = atol(cmdbuff);
Serial.println("!;");
break;
case 'M': // M - Morse
getValue();
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
muted = false; // can't mute (for PL tones) during tx
radio.setUnmute();
radio.setModeTransmit();
delay(300);
radio.morseOut(cmdbuff);
if(repeater == true) { radio.frequency(freq); }
radio.setModeReceive();
Serial.println("!;");
break;
case 'N': // N - set to Morse in Mode
morse_rx_setup();
state = MORSE;
Serial.println("!;");
break;
case 'D': // D - DTMF Out
dtmfSetup();
getValue();
dtmf_out(cmdbuff);
Serial.println("!;");
break;
case 'M':
getValue();
radio.setModeTransmit();
delay(300);
radio.morseOut(cmdbuff);
state = 10;
break;
case 80: // P - power level
getValue();
temp = atol(cmdbuff);
radio.setRfPower(temp);
break;
case 82: // R - repeater offset mode
getValue();
temp = atol(cmdbuff);
if(temp == 0) { repeater = 0; }
if(temp == 1) { repeater = 1; }
break;
case 83: // S - squelch
getValue();
temp = atol(cmdbuff);
radio.setSQLoThresh(temp);
break;
case 84: // T - transmit offset
getValue();
tx = atol(cmdbuff);
break;
case 94: // ^ - VSSI (voice) level
Serial.print(":");
Serial.print(radio.readVSSI(),DEC);
Serial.println(";");
case 'B': // B - set to DTMF in Mode
dtmfSetup();
radio.enableDTMFReceive();
state = DTMF;
Serial.println("!;");
break;
case 'A': // A - TX PL Tone configuration command
pl_tone_tx();
Serial.println("!;");
break;
case 'C': // C - RX PL Tone configuration command
pl_tone_rx();
Serial.println("!;");
break;
case 'V': // V - set volume
getValue();
temp = cmdbuff[0];
if (temp == 0x31) {
temp = atol(cmdbuff + 1);
radio.setVolume1(temp);
Serial.println("!;");
} else if (temp == 0x32) {
temp = atol(cmdbuff + 1);
radio.setVolume2(temp);
Serial.println("!;");
} else {
// not a valid volume command
while (Serial.available()) { Serial.read(); }
Serial.println("X!;");
}
break;
case 'K': // K - switch to KISS TNC mode
//state = KISS;
//TODO: set up KISS
Serial.println("X1;");
break;
default:
// unknown command, flush the input buffer and wait for next one
Serial.println("X1;");
while (Serial.available()) { Serial.read(); }
break;
}
break;
break;
case KISS:
if (Serial.peek() == '_') {
state = NORMAL;
if (rx_ctcss) {
radio.enableCtcss();
muted = true; // can't mute (for PL tones) during tx
radio.setMute();
}
}
// TODO: handle KISS TNC
break;
case MORSE:
if (text == '_') { state = NORMAL; }
if (text == 'M') { // tx message
getValue();
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
muted = false; // can't mute (for PL tones) during tx
radio.setUnmute();
radio.setModeTransmit();
delay(300);
radio.morseOut(cmdbuff);
if(repeater == true) { radio.frequency(freq); }
radio.setModeReceive();
} else {
// not a valid cmd
while (Serial.available()) { Serial.read(); }
}
break;
case DTMF:
if (text == '_') { state = NORMAL; }
if (text == 'D') { // tx message
getValue();
dtmf_out(cmdbuff);
} else {
// not a valid cmd
while (Serial.available()) { Serial.read(); }
}
break;
default:
// we're in an invalid state, reset to safe settings
while (Serial.available()) { Serial.read(); }
radio.frequency(freq);
radio.setModeReceive();
state = NORMAL;
break;
}
}
if(state == 10) {
if(millis() > (timer + 500)) { Serial.println("#TX,OFF;");radio.setModeReceive(); if(repeater == 1) { radio.frequency(freq); } state = 0; txcount = 0; }
// now handle any state related functions
switch (state) {
case TX:
if(millis() > (timer + 500)) {
Serial.println("#TX,OFF;");
radio.setModeReceive();
if(repeater == true) { radio.frequency(freq); }
if (rx_ctcss) {
radio.setMute();
muted = true;
}
txcount = 0;
state = NORMAL;
}
break;
case NORMAL:
// deal with rx ctccs if necessary
if (rx_ctcss) {
if (radio.getCtcssToneDetected()) {
if (muted) {
muted = false;
radio.setUnmute();
}
} else {
if (!muted) {
muted = true;
radio.setMute();
}
}
}
break;
case DTMF:
dtmf_rx(); // wait for DTMF reception
break;
case MORSE:
morse_rx(); // wait for Morse reception
break;
}
// get rid of any trailing whitespace in the serial buffer
if (Serial.available()) {
char cpeek = Serial.peek();
while (cpeek == ' ' || cpeek == '\r' || cpeek == '\n')
{
Serial.read();
cpeek = Serial.peek();
}
}
}
void getValue() {
int p = 0;
char temp;
for(;;) {
if(Serial.available()) {
temp = Serial.read();
if(temp == 59) { cmdbuff[p] = 0; Serial.print("@");
for(int x = 0; x < 32; x++) { Serial.print(cmdbuff[x]);}
Serial.println();
return;
}
cmdbuff[p] = temp;
p++;
if(p == 32) {
Serial.print("@");
for(int x = 0; x < 32; x++) {
Serial.println(cmdbuff[x]);
}
cmdbuff[0] = 0;
Serial.println("X0;"); return; } // some sort of alignment issue? lets not feed junk into whatever takes this string in
}
if(Serial.available()) {
temp = Serial.read();
if(temp == 59) {
cmdbuff[p] = 0;
return;
}
cmdbuff[p] = temp;
p++;
if(p == 32) {
cmdbuff[0] = 0;
return;
}
}
}
}
void dtmfSetup() {
radio.setVolume1(6);
radio.setVolume2(0);
radio.setDTMFDetectTime(24); // time to detect a DTMF code, units are 2.5ms
radio.setDTMFIdleTime(50); // time between transmitted DTMF codes, units are 2.5ms
radio.setDTMFTxTime(60); // duration of transmitted DTMF codes, units are 2.5ms
}
void dtmf_out(char * out_buf) {
if (out_buf[0] == ';' || out_buf[0] == 0) return; // empty message
uint8_t i = 0;
uint8_t code = radio.DTMFchar2code(out_buf[i]);
// start transmitting
radio.setDTMFCode(code); // set first
radio.setTxSourceTones();
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
muted = false; // can't mute during transmit
radio.setUnmute();
radio.setModeTransmit();
delay(300); // wait for TX to come to full power
bool dtmf_to_tx = true;
while (dtmf_to_tx) {
// wait until ready
while (radio.getDTMFTxActive() != 1) {
// wait until we're ready for a new code
delay(10);
}
if (i < 32 && out_buf[i] != ';' && out_buf[i] != 0) {
code = radio.DTMFchar2code(out_buf[i]);
if (code == 255) code = 0xE; // throw a * in there so we don't break things with an invalid code
radio.setDTMFCode(code); // set first
} else {
dtmf_to_tx = false;
break;
}
i++;
while (radio.getDTMFTxActive() != 0) {
// wait until this code is done
delay(10);
}
}
// done with tone
radio.setModeReceive();
if (repeater == true) {radio.frequency(freq);}
radio.setTxSourceMic();
}
void dtmf_rx() {
char m = radio.DTMFRxLoop();
if (m != 0) {
// Note: not doing buffering of messages,
// we just send a single morse character
// whenever we get it
Serial.print('R');
Serial.print(m);
Serial.println(';');
}
}
// TODO: morse config info
void morse_rx_setup() {
// Set the morse code characteristics
radio.setMorseFreq(MORSE_FREQ);
radio.setMorseDotMillis(MORSE_DOT);
radio.lookForTone(MORSE_FREQ);
radio.setupMorseRx();
}
void morse_rx() {
char m = radio.morseRxLoop();
if (m != 0) {
// Note: not doing buffering of messages,
// we just send a single morse character
// whenever we get it
Serial.print('R');
Serial.print(m);
Serial.println(';');
}
}
void pl_tone_tx() {
memset(pl_tx_buffer,0,32);
uint8_t ptr = 0;
while(1) {
if(Serial.available()) {
uint8_t buf = Serial.read();
if(buf == 'X') { return; }
if(buf == ';') { pl_tx_buffer[ptr] = 0; program_pl_tx(); return; }
if(ptr == 31) { return; }
pl_tx_buffer[ptr] = buf; ptr++;
}
}
}
void program_pl_tx() {
float pl_tx = atof(pl_tx_buffer);
radio.setCtcss(pl_tx);
if (pl_tx == 0) {
radio.disableCtcssTx();
} else {
radio.enableCtcssTx();
}
}
void pl_tone_rx() {
memset(pl_rx_buffer,0,32);
uint8_t ptr = 0;
while(1) {
if(Serial.available()) {
uint8_t buf = Serial.read();
if(buf == 'X') { return; }
if(buf == ';') { pl_rx_buffer[ptr] = 0; program_pl_rx(); return; }
if(ptr == 31) { return; }
pl_rx_buffer[ptr] = buf; ptr++;
}
}
}
void program_pl_rx() {
float pl_rx = atof(pl_rx_buffer);
radio.setCtcss(pl_rx);
if (pl_rx == 0) {
rx_ctcss = false;
radio.setUnmute();
muted = false;
radio.disableCtcssRx();
} else {
rx_ctcss = true;
radio.setMute();
muted = true;
radio.enableCtcssRx();
}
}

View File

@@ -25,7 +25,7 @@ char CALLSIGN[] = "1ZZ9ZZ/B";
#include <HamShield.h>
#include <PCM.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -90,8 +90,8 @@ const unsigned char dbm[] PROGMEM = {
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);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, LOW);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -106,7 +106,7 @@ void setup() {
int result = radio.testConnection();
Serial.println(result);
radio.initialize();
radio.frequency(446000);
radio.frequency(432400);
radio.setVolume1(0xF);
radio.setVolume2(0xF);
radio.setModeReceive();

View File

@@ -12,7 +12,7 @@
#include <HamShield.h>
#define PWM_PIN 3
#define MIC_PIN 3
#define RESET_PIN A3
#define SWITCH_PIN 2
@@ -230,8 +230,8 @@ const uint8_t spYELLOW[] PROGMEM = {0x69,0xBD,0x56,0x15,0xAC,0x67,0xE5,0x
void setup() {
// NOTE: if not using PWM out, it should be held low to avoid tx noise
pinMode(PWM_PIN, OUTPUT);
digitalWrite(PWM_PIN, HIGH);
pinMode(MIC_PIN, OUTPUT);
digitalWrite(MIC_PIN, HIGH);
// prep the switch
pinMode(SWITCH_PIN, INPUT_PULLUP);
@@ -249,7 +249,7 @@ void setup() {
Serial.println("Setting radio to its defaults..");
radio.initialize();
radio.setRfPower(0);
radio.frequency(144025);
radio.frequency(145010);
radio.setModeTransmit();
voice.say(spKILO); // to change these to the words you would like to say, or a ham radio call sign - uncomment above encoded words

View File

@@ -1,5 +1,5 @@
name=HamShield
version=1.1.1
version=1.1.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

@@ -3,16 +3,22 @@
// 11/22/2013 by Morgan Redfield <redfieldm@gmail.com>
// 04/26/2015 various changes Casey Halverson <spaceneedle@gmail.com>
#include "Arduino.h"
#include "HamShield.h"
#include <avr/wdt.h>
#include "stdint.h"
#include "math.h"
#if defined(__AVR__)
#include <avr/pgmspace.h>
// #include <PCM.h>
#define MORSE_TABLE_PROGMEM
#else
// get rid of progmem for now and just put these tables in flash/program space
#define PROGMEM
#endif
/* don't change this regulatory value, use dangerMode() and safeMode() instead */
bool restrictions = true;
HamShield *HamShield::sHamShield = NULL;
uint16_t old_dtmf_reg;
/* channel lookup tables */
@@ -33,7 +39,6 @@ unsigned int morse_dot_millis = 100;
// It will occupy 108 bytes of memory (or program memory if defined)
#define MORSE_TABLE_LENGTH 54
#define MORSE_TABLE_PROGMEM
#ifndef MORSE_TABLE_PROGMEM
const struct asciiMorse {
char ascii;
@@ -115,45 +120,20 @@ const unsigned char AFSK_mark[] PROGMEM = { 154, 249, 91, 11, 205, 216, 25, 68,
const unsigned char AFSK_space[] PROGMEM = { 140, 228, 250, 166, 53, 0, 53, 166, 249, 230, 128, 24, 7, 88, 203, 255, 203, 88, 7, 24, 128, 230, 249, 167, 53, 0, 53, 167, 249, 230, 128, 24, 6, 88, 202, 255, 202, 88, 6, 24, 127, 231, 249, 167, 52, 0, 52, 167, 248, 231, 127, 25, 6, 89, 202, 255, 202, 89, 6, 25, 127, 231, 248, 167, 53, 0, 54, 165, 251, 227, 133, 14};
/* Aux button variables */
volatile int ptt = false;
volatile long bouncer = 0;
/** Default constructor, uses default I2C address.
* @see A1846S_DEFAULT_ADDRESS
*/
HamShield::HamShield() {
devAddr = A1; // devAddr is the chip select pin used by the HamShield
sHamShield = this;
pinMode(devAddr, OUTPUT);
digitalWrite(devAddr, HIGH);
pinMode(CLK, OUTPUT);
digitalWrite(CLK, HIGH);
pinMode(DAT, OUTPUT);
digitalWrite(DAT, HIGH);
}
/** Specific address constructor.
* @param chip select pin for HamShield
* @see A1846S_DEFAULT_ADDRESS
* @see A1846S_ADDRESS_AD0_LOW
* @see A1846S_ADDRESS_AD0_HIGH
*/
HamShield::HamShield(uint8_t cs_pin) {
devAddr = cs_pin;
HamShield::HamShield(uint8_t ncs_pin, uint8_t clk_pin, uint8_t dat_pin, uint8_t mic_pin) {
devAddr = ncs_pin;
hs_mic_pin = mic_pin;
pinMode(devAddr, OUTPUT);
digitalWrite(devAddr, HIGH);
pinMode(CLK, OUTPUT);
digitalWrite(CLK, HIGH);
pinMode(DAT, OUTPUT);
digitalWrite(DAT, HIGH);
HSsetPins(ncs_pin, clk_pin, dat_pin);
}
/** Power on and prepare for general usage.
*
*/
@@ -213,7 +193,7 @@ void HamShield::initialize(bool narrowBand) {
HSwriteWord(devAddr, 0x57, tx_data);
tx_data = 0x800D;
HSwriteWord(devAddr, 0x58, tx_data);
tx_data = 0x0EDD;
tx_data = 0x0EDB;
HSwriteWord(devAddr, 0x5A, tx_data); // sq and noise detect times
tx_data = 0x3FFF;
HSwriteWord(devAddr, 0x63, tx_data); // pre-emphasis bypass
@@ -221,13 +201,13 @@ void HamShield::initialize(bool narrowBand) {
// calibration
tx_data = 0x00A4;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
HSdelay(100);
tx_data = 0x00A6;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
HSdelay(100);
tx_data = 0x0006;
HSwriteWord(devAddr, 0x30, tx_data);
delay(100);
HSdelay(100);
// set band width
@@ -237,7 +217,7 @@ void HamShield::initialize(bool narrowBand) {
setupWideBand();
}
delay(100);
HSdelay(100);
/*
// setup default values
@@ -247,12 +227,15 @@ void HamShield::initialize(bool narrowBand) {
setModeReceive();
setTxSourceMic();
setRfPower(0);
setSQLoThresh(80);
setSQLoThresh(-80);
setSQOn();
*/
setDTMFIdleTime(50);
setDTMFTxTime(60);
setDTMFDetectTime(24);
HSreadWord(devAddr, A1846S_DTMF_ENABLE_REG, radio_i2c_buf);
old_dtmf_reg = radio_i2c_buf[0];
}
@@ -273,11 +256,11 @@ void HamShield::setupNarrowBand() {
HSwriteWord(devAddr, 0x34, tx_data);
tx_data = 0x40C3;
HSwriteWord(devAddr, 0x3A, tx_data); // modu_det_sel sq setting
tx_data = 0x0407;
tx_data = 0x0F1E;
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;
tx_data = 0x20BE;
HSwriteWord(devAddr, 0x48, tx_data);
tx_data = 0x1BB7;
HSwriteWord(devAddr, 0x60, tx_data);
@@ -425,15 +408,9 @@ bool HamShield::testConnection() {
* to 7FH, and then write value to the address subtracted by
* 80H. Finally write 0x0000 to 7FH
* Example: writing 85H register address is 0x001F .
* Move 7FH 0x0001{
}
* Move 05H 0x001F{
} 05H=85H-80H
* Move 7FH 0x0000{
}
* Move 7FH 0x0001{}
* Move 05H 0x001F{} 05H=85H-80H
* Move 7FH 0x0000{}
*/
uint16_t HamShield::readCtlReg() {
@@ -444,7 +421,7 @@ uint16_t HamShield::readCtlReg() {
void HamShield::softReset() {
uint16_t tx_data = 0x1;
HSwriteWord(devAddr, A1846S_CTL_REG, tx_data);
delay(100); // Note: see A1846S setup info for timing guidelines
HSdelay(100); // Note: see A1846S setup info for timing guidelines
tx_data = 0x4;
HSwriteWord(devAddr, A1846S_CTL_REG, tx_data);
}
@@ -568,7 +545,7 @@ void HamShield::setTX(bool on_noff){
//setGpioHi(4); // V1
delay(50); // delay required by AU1846
HSdelay(50); // delay required by AU1846
}
HSwriteBitW(devAddr, A1846S_CTL_REG, A1846S_TX_MODE_BIT, on_noff);
@@ -590,7 +567,7 @@ void HamShield::setRX(bool on_noff){
setGpioLow(4); // V1
setGpioLow(5); // V2
delay(50); // delay required by AU1846
HSdelay(50); // delay required by AU1846
}
HSwriteBitW(devAddr, A1846S_CTL_REG, A1846S_RX_MODE_BIT, on_noff);
@@ -796,20 +773,37 @@ void HamShield::setCtcssFreqToStandard(){
setCtcssFreq(13440);
}
void HamShield::enableCtcss() {
// enable TX
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 3);
// enable RX
setCtcssGpioSel(1);
void HamShield::enableCtcssTx() {
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 3);
}
void HamShield::enableCtcssRx() {
setCtcssGpioSel(1);
HSwriteBitW(devAddr, A1846S_TX_VOICE_REG, A1846S_CTCSS_DET_BIT, 0);
HSwriteBitW(devAddr, A1846S_FILTER_REG, A1846S_CTCSS_FILTER_BYPASS, 0);
setDetCtcss();
}
void HamShield::disableCtcss() {
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 0);
void HamShield::enableCtcss() {
// enable TX
enableCtcssTx();
// enable RX
enableCtcssRx();
}
void HamShield::disableCtcssTx() {
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 0);
}
void HamShield::disableCtcssRx() {
setCtcssGpioSel(0);
disableCtcssCdcss();
}
void HamShield::disableCtcss() {
disableCtcssTx();
disableCtcssRx();
}
// match threshold
void HamShield::setCtcssDetThreshIn(uint8_t thresh) {
@@ -893,24 +887,30 @@ bool HamShield::getSQState(){
void HamShield::setSQHiThresh(int16_t sq_hi_threshold){
// Sq detect high th, rssi_cmp will be 1 when rssi>th_h_sq, unit 1dB
uint16_t sq = 137 + sq_hi_threshold;
HSwriteWord(devAddr, A1846S_SQ_OPEN_THRESH_REG, sq);
HSwriteBitsW(devAddr, A1846S_SQ_OPEN_THRESH_REG, A1846S_SQ_OPEN_THRESH_BIT, A1846S_SQ_OPEN_THRESH_LENGTH, sq);
}
int16_t HamShield::getSQHiThresh(){
HSreadWord(devAddr, A1846S_SQ_OPEN_THRESH_REG, radio_i2c_buf);
HSreadBitsW(devAddr, A1846S_SQ_OPEN_THRESH_REG, A1846S_SQ_OPEN_THRESH_BIT, A1846S_SQ_OPEN_THRESH_LENGTH, radio_i2c_buf);
return radio_i2c_buf[0] - 137;
}
void HamShield::setSQLoThresh(int16_t sq_lo_threshold){
// Sq detect low th, rssi_cmp will be 0 when rssi<th_l_sq && time delay meet, unit 1 dB
uint16_t sq = 137 + sq_lo_threshold;
HSwriteWord(devAddr, A1846S_SQ_SHUT_THRESH_REG, sq);
HSwriteBitsW(devAddr, A1846S_SQ_SHUT_THRESH_REG, A1846S_SQ_SHUT_THRESH_BIT, A1846S_SQ_SHUT_THRESH_LENGTH, sq);
}
int16_t HamShield::getSQLoThresh(){
HSreadWord(devAddr, A1846S_SQ_SHUT_THRESH_REG, radio_i2c_buf);
HSreadBitsW(devAddr, A1846S_SQ_SHUT_THRESH_REG, A1846S_SQ_SHUT_THRESH_BIT, A1846S_SQ_SHUT_THRESH_LENGTH, radio_i2c_buf);
return radio_i2c_buf[0] - 137;
}
bool HamShield::getSquelching() {
HSreadBitW(devAddr, A1846S_FLAG_REG, A1846S_SQ_FLAG_BIT, radio_i2c_buf);
return (radio_i2c_buf[0] != 0);
}
// SQ out select
void HamShield::setSQOutSel(){
HSwriteBitW(devAddr, A1846S_SQ_OUT_SEL_REG, A1846S_SQ_OUT_SEL_BIT, 1);
@@ -938,20 +938,19 @@ bool HamShield::getVoxOn(){
// Vox Threshold
void HamShield::setVoxOpenThresh(uint16_t vox_open_thresh){
// When vssi > th_h_vox, then vox will be 1(unit mV )
HSwriteWord(devAddr, A1846S_TH_H_VOX_REG, vox_open_thresh);
HSwriteBitsW(devAddr, A1846S_TH_H_VOX_REG, A1846S_TH_H_VOX_BIT, A1846S_TH_H_VOX_LEN, vox_open_thresh);
}
uint16_t HamShield::getVoxOpenThresh(){
HSreadWord(devAddr, A1846S_TH_H_VOX_REG, radio_i2c_buf);
HSreadBitsW(devAddr, A1846S_TH_H_VOX_REG, A1846S_TH_H_VOX_BIT, A1846S_TH_H_VOX_LEN, radio_i2c_buf);
return radio_i2c_buf[0];
}
void HamShield::setVoxShutThresh(uint16_t vox_shut_thresh){
// When vssi < th_l_vox && time delay meet, then vox will be 0 (unit mV )
HSwriteWord(devAddr, A1846S_TH_L_VOX_REG, vox_shut_thresh);
HSwriteBitsW(devAddr, A1846S_TH_L_VOX_REG, A1846S_TH_L_VOX_BIT, A1846S_TH_L_VOX_LEN, vox_shut_thresh);
}
uint16_t HamShield::getVoxShutThresh(){
HSreadWord(devAddr, A1846S_TH_L_VOX_REG, radio_i2c_buf);
HSreadBitsW(devAddr, A1846S_TH_L_VOX_REG, A1846S_TH_L_VOX_BIT, A1846S_TH_L_VOX_LEN, radio_i2c_buf);
return radio_i2c_buf[0];
}
@@ -1022,6 +1021,67 @@ uint16_t HamShield::getDTMFIdleTime() {
return radio_i2c_buf[0];
}
char HamShield::DTMFRxLoop() {
char m = 0;
if (getDTMFSample() != 0) {
uint16_t code = getDTMFCode();
m = DTMFcode2char(code);
// reset after this tone
int j = 0;
while (j < 4) {
if (getDTMFSample() == 0) {
j++;
} else {
j = 1;
}
delay(10);
}
// reset read
//enableDTMFReceive();
}
return m;
}
char HamShield::DTMFcode2char(uint16_t code) {
char c;
if (code < 10) {
c = '0' + code;
} else if (code < 0xE) {
c = 'A' + code - 10;
} else if (code == 0xE) {
c = '*';
} else if (code == 0xF) {
c = '#';
} else {
c = '?'; // invalid code
}
return c;
}
uint8_t HamShield::DTMFchar2code(char c) {
uint8_t code;
if (c == '#') {
code = 0xF;
} else if (c=='*') {
code = 0xE;
} else if (c >= 'A' && c <= 'D') {
code = c - 'A' + 0xA;
} else if (c >= '0' && c <= '9') {
code = c - '0';
} else {
// invalid code, skip it
code = 255;
}
return code;
}
void HamShield::setDTMFTxTime(uint16_t tx_time) {
if (tx_time > 63) {tx_time = 63;} // maxed out
// tx time is duration of DTMF Tone
@@ -1090,34 +1150,83 @@ void HamShield::setDTMFCode(uint16_t code){
}
// Tone Transmission
void HamShield::HStone(uint8_t pin, unsigned int frequency) {
// store old dtmf reg for noTone
// HSreadWord(devAddr, A1846S_DTMF_ENABLE_REG, radio_i2c_buf);
// old_dtmf_reg = radio_i2c_buf[0];
// set frequency
HSwriteWord(devAddr, A1846S_TONE1_FREQ, frequency*10);
// set 0x79 dtmf control
HSwriteBitsW(devAddr, 0x79, 15, 2, 0x3); // transmit single tone (not dtmf)
// HSwriteBitsW(devAddr, A1846S_DTMF_ENABLE_REG, A1846S_DTMF_ENABLE_BIT, 2, 0x2); // transmit single tone (not dtmf)
// bypass pre/de-emphasis
HSwriteBitsW(devAddr, A1846S_FILTER_REG, A1846S_EMPH_FILTER_EN, 1, 1);
// set source for tx
setTxSourceTone1(); // writes to 3A
//tone(pin, frequency);
}
void HamShield::HSnoTone(uint8_t pin) {
setTxSourceMic();
//HSwriteWord(devAddr, A1846S_DTMF_ENABLE_REG, old_dtmf_reg); // disable tone and dtmf
// noTone(pin);
}
// Tone detection
void HamShield::lookForTone(uint16_t t_hz) {
float tone_hz = (float) t_hz;
// set 0x79 dtmf control
HSwriteBitsW(devAddr, 0x79, 15, 2, 0x3); // transmit single tone (not dtmf)
// bypass pre/de-emphasis
HSwriteBitsW(devAddr, A1846S_FILTER_REG, A1846S_EMPH_FILTER_EN, 1, 1);
float tone_hz = (float) t_hz;
float Fs = 6400000/1024;
float k = floor(tone_hz/Fs*127 + 0.5);
uint16_t t = (uint16_t) (round(2.0*cos(2.0*PI*k/127)*1024));
uint16_t t = (uint16_t) (round(2.0*cos(2.0*M_PI*k/127)*1024));
float k2 = floor(2*tone_hz/Fs*127+0.5);
uint16_t h = (uint16_t) (round(2.0*cos(2.0*PI*k2/127)*1024));
uint16_t h = (uint16_t) (round(2.0*cos(2.0*M_PI*k2/127)*1024));
// set tone
HSwriteWord(devAddr, 0x68, t);
HSwriteWord(devAddr, 0x67, t); // looking for tone 1
// set second harmonic
HSwriteWord(devAddr, 0x70, h);
HSwriteWord(devAddr, 0x6F, h); // looking for tone
// turn on tone detect
HSwriteBitW(devAddr, A1846S_DTMF_ENABLE_REG, A1846S_TONE_DETECT, 1);
HSwriteBitW(devAddr, A1846S_DTMF_ENABLE_REG, A1846S_DTMF_ENABLE_BIT, 1);
}
bool redetect = false;
uint8_t last_tone_detected = 0;
uint8_t HamShield::toneDetected() {
HSreadBitsW(devAddr, A1846S_DTMF_CODE_REG, A1846S_DTMF_SAMPLE_BIT, 1, radio_i2c_buf);
if (radio_i2c_buf[0] != 0) {
if (!redetect) {
redetect = true;
HSreadBitsW(devAddr, A1846S_DTMF_CODE_REG, A1846S_DTMF_CODE_BIT, A1846S_DTMF_CODE_LEN, radio_i2c_buf);
if (radio_i2c_buf[0] == 1) {
return 1;
}
}
last_tone_detected = radio_i2c_buf[0];
//Serial.print("t: ");
//Serial.println(last_tone_detected);
}
if (last_tone_detected == 0) {
return 1;
}
} else if (redetect) {
// re-enable detect
redetect = false;
HSwriteBitW(devAddr, A1846S_DTMF_ENABLE_REG, A1846S_TONE_DETECT, 1);
HSwriteBitW(devAddr, A1846S_DTMF_ENABLE_REG, A1846S_DTMF_ENABLE_BIT, 1);
}
return 0;
}
@@ -1295,9 +1404,14 @@ int16_t HamShield::readRSSI(){
return rssi;
}
uint16_t HamShield::readVSSI(){
HSreadWord(devAddr, A1846S_VSSI_REG, radio_i2c_buf);
HSreadBitsW(devAddr, A1846S_VSSI_REG, A1846S_VSSI_BIT, A1846S_VSSI_LENGTH, radio_i2c_buf);
return radio_i2c_buf[0] & 0x7FF; // only need lowest 10 bits
return radio_i2c_buf[0];
}
uint16_t HamShield::readMSSI(){
HSreadBitsW(devAddr, A1846S_VSSI_REG, A1846S_MSSI_BIT, A1846S_MSSI_LENGTH, radio_i2c_buf);
return radio_i2c_buf[0];
}
@@ -1394,8 +1508,12 @@ bool HamShield::frequency_float(float freq_khz) {
/* FRS Lookup Table */
bool HamShield::setFRSChannel(uint8_t channel) {
if(channel < 15) {
if(channel < 15) {
#if defined(__AVR__)
setFrequency(pgm_read_dword_near(FRS + channel));
#else
setFrequency(FRS[channel]);
#endif
return true;
}
return false;
@@ -1406,11 +1524,19 @@ bool HamShield::setFRSChannel(uint8_t channel) {
bool HamShield::setGMRSChannel(uint8_t channel) {
if((channel > 8) & (channel < 16)) {
channel = channel - 7; // we start with 0, to try to avoid channel 8 being nothing
setFrequency(pgm_read_dword_near(FRS + channel));
#if defined(__AVR__)
setFrequency(pgm_read_dword_near(FRS + channel));
#else
setFrequency(FRS[channel]);
#endif
return true;
}
if(channel < 9) {
setFrequency(pgm_read_dword_near(GMRS + channel));
#if defined(__AVR__)
setFrequency(pgm_read_dword_near(GMRS + channel));
#else
setFrequency(GMRS[channel]);
#endif
return true;
}
return false;
@@ -1420,7 +1546,11 @@ bool HamShield::setGMRSChannel(uint8_t channel) {
bool HamShield::setMURSChannel(uint8_t channel) {
if(channel < 6) {
setFrequency(pgm_read_dword_near(MURS + channel));
#if defined(__AVR__)
setFrequency(pgm_read_dword_near(MURS + channel));
#else
setFrequency(MURS[channel]);
#endif
return true;
}
}
@@ -1429,7 +1559,11 @@ bool HamShield::setMURSChannel(uint8_t channel) {
bool HamShield::setWXChannel(uint8_t channel) {
if(channel < 8) {
setFrequency(pgm_read_dword_near(WX + channel));
#if defined(__AVR__)
setFrequency(pgm_read_dword_near(WX + channel));
#else
setFrequency(WX[channel]);
#endif
setModeReceive();
// turn off squelch?
// channel bandwidth?
@@ -1445,7 +1579,7 @@ uint8_t HamShield::scanWXChannel() {
int16_t toprssi = 0;
for(int x = 0; x < 8; x++) {
setWXChannel(x);
delay(100);
HSdelay(100);
int16_t rssi = readRSSI();
if(rssi > toprssi) { toprssi = rssi; channel = x; }
}
@@ -1537,39 +1671,6 @@ uint32_t HamShield::findWhitespaceChannels(uint32_t buffer[],uint8_t buffsize, u
}
/* Setup the auxiliary button input mode and register the ISR */
void HamShield::buttonMode(uint8_t mode) {
pinMode(HAMSHIELD_AUX_BUTTON,INPUT); // set the pin mode to input
digitalWrite(HAMSHIELD_AUX_BUTTON,HIGH); // turn on internal pull up
if(mode == PTT_MODE) { attachInterrupt(HAMSHIELD_AUX_BUTTON, HamShield::isr_ptt, CHANGE); }
if(mode == RESET_MODE) { attachInterrupt(HAMSHIELD_AUX_BUTTON, HamShield::isr_reset, CHANGE); }
}
/* Interrupt routines */
/* handle aux button to reset condition */
void HamShield::isr_reset() {
wdt_enable(WDTO_15MS);
while(1) { }
}
/* Transmit on press, receive on release. We need debouncing !! */
void HamShield::isr_ptt() {
if((bouncer + 200) > millis()) {
if(ptt == false) {
ptt = true;
sHamShield->setModeTransmit();
bouncer = millis();
}
if(ptt == true) {
ptt = false;
sHamShield->setModeReceive();
bouncer = millis();
} }
}
/*
Radio etiquette function: Wait for empty channel.
@@ -1584,13 +1685,13 @@ Does not take in account the millis() overflow
bool HamShield::waitForChannel(long timeout = 0, long breakwindow = 0, int setRSSI = HAMSHIELD_EMPTY_CHANNEL_RSSI) {
int16_t rssi = 0; // Set RSSI to max received signal
for(int x = 0; x < 20; x++) { rssi = readRSSI(); } // "warm up" to get past RSSI hysteresis
long timer = millis() + timeout; // Setup the timeout value
long timer = HSmillis() + timeout; // Setup the timeout value
if(timeout == 0) { timer = 4294967295; } // If we want to wait forever, set it to the max millis()
while(timer > millis()) { // while our timer is not timed out.
while(timer > HSmillis()) { // while our timer is not timed out.
rssi = readRSSI(); // Read signal strength
if(rssi < setRSSI) { // If the channel is empty, lets see if anyone breaks in.
timer = millis() + breakwindow;
while(timer > millis()) {
timer = HSmillis() + breakwindow;
while(timer > HSmillis()) {
rssi = readRSSI();
if(rssi > setRSSI) { return false; } // Someone broke into the channel, abort.
} return true; // It passed the test...channel is open.
@@ -1599,6 +1700,10 @@ bool HamShield::waitForChannel(long timeout = 0, long breakwindow = 0, int setRS
return false;
}
void HamShield::setupMorseRx() {
// TODO: morse timing config (e.g. dot time, dash time, etc)
}
// Get current morse code tone frequency (in Hz)
unsigned int HamShield::getMorseFreq() {
@@ -1629,18 +1734,21 @@ void HamShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) {
int i;
char prev = 0;
for(i = 0; buffer[i] != '\0' && i < HAMSHIELD_MORSE_BUFFER_SIZE; prev = buffer[i], i++) {
// On a space, delay 7 dots
if(buffer[i] == ' ') {
// 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, morse_dot_millis * 7);
noTone(HAMSHIELD_PWM_PIN);
delay(morse_dot_millis*7);
//tone(hs_mic_pin, 6000, morse_dot_millis * 7);
HSnoTone(hs_mic_pin);
HSdelay(morse_dot_millis*7);
//Serial.print(" ");
} else {
//tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis * 4);
noTone(HAMSHIELD_PWM_PIN);
delay(morse_dot_millis*4);
//tone(hs_mic_pin, 6000, morse_dot_millis * 4);
HSnoTone(hs_mic_pin);
HSdelay(morse_dot_millis*4);
//Serial.print(" ");
}
continue;
}
@@ -1649,26 +1757,128 @@ 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, morse_freq, morse_dot_millis * 3);
delay(morse_dot_millis*3);
HStone(hs_mic_pin, morse_freq);//, morse_dot_millis * 3);
HSdelay(morse_dot_millis*3);
HSnoTone(hs_mic_pin);
//Serial.print('-');
} else {
tone(HAMSHIELD_PWM_PIN, morse_freq, morse_dot_millis);
delay(morse_dot_millis);
HStone(hs_mic_pin, morse_freq);//, morse_dot_millis);
HSdelay(morse_dot_millis);
HSnoTone(hs_mic_pin);
//Serial.print('.');
}
//tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis);
noTone(HAMSHIELD_PWM_PIN);
delay(morse_dot_millis);
//tone(hs_mic_pin, 6000, morse_dot_millis);
HSnoTone(hs_mic_pin);
HSdelay(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, morse_dot_millis * 3);
noTone(HAMSHIELD_PWM_PIN);
delay(morse_dot_millis * 3);
//tone(hs_mic_pin, 6000, morse_dot_millis * 3);
HSnoTone(hs_mic_pin);
HSdelay(morse_dot_millis * 3);
}
return;
}
// returns '\0' if no valid morse char found yet
char HamShield::morseRxLoop() {
static uint32_t last_tone_check = 0; // track how often we check for morse tones
static uint32_t tone_in_progress; // track how long the current tone lasts
static uint32_t space_in_progress; // track how long since the last tone
static uint8_t rx_morse_char;
static uint8_t rx_morse_bit;
static bool bits_to_process;
if (last_tone_check == 0) {
last_tone_check = millis();
space_in_progress = 0; // haven't checked yet
tone_in_progress = 0; // not currently listening to a tone
rx_morse_char = 0; // haven't found any tones yet
rx_morse_bit = 1;
bits_to_process = false;
}
char m = 0;
// are we receiving anything
if (toneDetected()) {
space_in_progress = 0;
if (tone_in_progress == 0) {
// start a new tone
tone_in_progress = millis();
//Serial.print('t');
}
} else {
// keep track of how long the silence is
if (space_in_progress == 0) space_in_progress = millis();
// we wait for a bit of silence before ending the last
// symbol in order to smooth out the detector
if ((millis() - space_in_progress) > SYMBOL_END_TIME)
{
if (tone_in_progress != 0) {
// end the last tone
uint16_t tone_time = millis() - tone_in_progress;
tone_in_progress = 0;
//Serial.println(tone_time);
bits_to_process = handleMorseTone(tone_time, bits_to_process, &rx_morse_char, &rx_morse_bit);
}
}
// we might be done with a character if the space is long enough
if (((millis() - space_in_progress) > CHAR_END_TIME) && bits_to_process) {
m = parseMorse(rx_morse_char, rx_morse_bit);
bits_to_process = false;
rx_morse_char = 0;
rx_morse_bit = 1;
}
// we might be done with a message if the space is long enough
if ((millis() - space_in_progress) > MESSAGE_END_TIME) {
rx_morse_char = 0;
rx_morse_bit = 1;
}
}
return m;
}
bool HamShield::handleMorseTone(uint16_t tone_time, bool bits_to_process,
uint8_t * rx_morse_char, uint8_t * rx_morse_bit) {
//Serial.println(tone_time);
if (tone_time > MIN_DOT_TIME && tone_time < MAX_DOT_TIME) {
// add a dot
//Serial.print(".");
bits_to_process = true;
//nothing to do for this bit position, since . = 0
} else if (tone_time > MIN_DASH_TIME && tone_time < MAX_DASH_TIME) {
// add a dash
//Serial.print("-");
bits_to_process = true;
*rx_morse_char += *rx_morse_bit;
}
// prep for the next bit
*rx_morse_bit = *rx_morse_bit << 1;
return bits_to_process;
}
char HamShield::parseMorse(uint8_t rx_morse_char, uint8_t rx_morse_bit) {
// if morse_char is a valid morse character, return the character
// if morse_char is an invalid (incomplete) morse character, return 0
//if (rx_morse_bit != 1) Serial.println(rx_morse_char, BIN);
rx_morse_char += rx_morse_bit; // add the terminator bit
// if we got a char, then print it
char c = morseReverseLookup(rx_morse_char);
return c;
}
/* Morse code lookup table */
uint8_t HamShield::morseLookup(char letter) {
@@ -1731,7 +1941,7 @@ void HamShield::SSTVVISCode(int code) {
toneWait(1900,300);
toneWait(1200,30);
for(int x = 0; x < 7; x++) {
if(bitRead(code,x)) { toneWait(1100,30); } else { toneWait(1300,30); }
if(code&(1<<x)) { toneWait(1100,30); } else { toneWait(1300,30); }
}
if(parityCalc(code)) { toneWait(1300,30); } else { toneWait(1100,30); }
toneWait(1200,30);
@@ -1794,19 +2004,20 @@ void HamShield::SSTVTestPattern(int code) {
/* wait for tone to complete */
void HamShield::toneWait(uint16_t freq, long timer) {
tone(HAMSHIELD_PWM_PIN,freq,timer);
delay(timer);
HStone(hs_mic_pin,freq);//,timer);
HSdelay(timer);
HSnoTone(hs_mic_pin);
}
/* wait microseconds for tone to complete */
void HamShield::toneWaitU(uint16_t freq, long timer) {
if(freq < 16383) {
tone(HAMSHIELD_PWM_PIN,freq);
delayMicroseconds(timer); noTone(HAMSHIELD_PWM_PIN); return;
HStone(hs_mic_pin,freq);
HSdelayMicroseconds(timer); HSnoTone(hs_mic_pin); return;
}
tone(HAMSHIELD_PWM_PIN,freq);
delay(timer / 1000); noTone(HAMSHIELD_PWM_PIN); return;
HStone(hs_mic_pin,freq);
HSdelay(timer / 1000); HSnoTone(hs_mic_pin); return;
}
@@ -1822,21 +2033,3 @@ bool HamShield::parityCalc(int code) {
return parity;
}
/*
void HamShield::AFSKOut(char buffer[80]) {
for(int x = 0; x < 65536; x++) {
startPlayback(AFSK_mark, sizeof(AFSK_mark)); delay(8);
startPlayback(AFSK_space, sizeof(AFSK_space)); delay(8); }
}
*/
// This is the ADC timer handler. When enabled, we'll see what we're supposed
// to be reading/handling, and trigger those on the main object.
/*ISR(ADC_vect) {
TIFR1 = _BV(ICF1); // Clear the timer flag
if(HamShield::sHamShield->afsk.enabled()) {
HamShield::sHamShield->afsk.timer();
}
}*/

View File

@@ -9,22 +9,12 @@
#define _HAMSHIELD_H_
#include "HamShield_comms.h"
//#include "SimpleFIFO.h"
//#include "AFSK.h"
//#include "DDS.h"
#include <avr/pgmspace.h>
// HamShield constants
#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
#define HAMSHIELD_EMPTY_CHANNEL_RSSI -110 // Default threshold where channel is considered "clear"
// button modes
#define PTT_MODE 1
#define RESET_MODE 2
// Device Registers
#define A1846S_CTL_REG 0x30 // control register
#define A1846S_CLK_MODE_REG 0x04 // clk_mode
@@ -38,11 +28,11 @@
//#define A1846S_ADCLK_FREQ_REG 0x2C // adclk_freq<15:0>
#define A1846S_INT_MODE_REG 0x2D // interrupt enables
#define A1846S_TX_VOICE_REG 0x3A // tx voice control reg
#define A1846S_TH_H_VOX_REG 0x41 // register holds vox high (open) threshold bits
#define A1846S_TH_L_VOX_REG 0x42 // register holds vox low (shut) threshold bits
#define A1846S_TH_H_VOX_REG 0x64 // register holds vox high (open) threshold bits
#define A1846S_TH_L_VOX_REG 0x64 // register holds vox low (shut) threshold bits
#define A1846S_FM_DEV_REG 0x43 // register holds fm deviation settings
#define A1846S_RX_VOLUME_REG 0x44 // register holds RX volume settings
#define A1846S_SQ_OPEN_THRESH_REG 0x48 // see sq
#define A1846S_SQ_OPEN_THRESH_REG 0x49 // see sq
#define A1846S_SQ_SHUT_THRESH_REG 0x49 // see sq
#define A1846S_CTCSS_FREQ_REG 0x4A // ctcss_freq<15:0>
#define A1846S_CDCSS_CODE_HI_REG 0x4B // cdcss_code<23:16>
@@ -115,7 +105,7 @@
#define A1846S_TXON_RF_INT_BIT 7 // txon_rf_uint16_t enable
#define A1846S_CTCSS_PHASE_INT_BIT 5 // ctcss phase shift detect uint16_t enable
#define A1846S_IDLE_TIMEOUT_INT_BIT 4 // idle state time out uint16_t enable
#define A1846S_RXON_RF_TIMeOUT_INT_BIT 3 // rxon_rf timerout uint16_t enable
#define A1846S_RXON_RF_TIMEOUT_INT_BIT 3 // rxon_rf timerout uint16_t enable
#define A1846S_SQ_INT_BIT 2 // sq uint16_t enable
#define A1846S_TXON_RF_TIMEOUT_INT_BIT 1 // txon_rf time out uint16_t enable
#define A1846S_VOX_INT_BIT 0 // vox uint16_t enable
@@ -126,8 +116,12 @@
#define A1846S_CTCSS_DET_BIT 5
// Bitfields for A1846S_TH_H_VOX_REG
#define A1846S_TH_H_VOX_BIT 14 // th_h_vox<14:0>
#define A1846S_TH_H_VOX_LENGTH 15
#define A1846S_TH_H_VOX_BIT 13 // th_h_vox<13:7>
#define A1846S_TH_H_VOX_LEN 7
// Bitfields for A1846S_TH_L_VOX_REG
#define A1846S_TH_L_VOX_BIT 6 // th_l_vox<6:0>
#define A1846S_TH_L_VOX_LEN 7
// Bitfields for A1846S_FM_DEV_REG
#define A1846S_FM_DEV_VOICE_BIT 12 // CTCSS/CDCSS and voice deviation <6:0>
@@ -151,12 +145,12 @@
#define A1846S_SHIFT_SEL_LEN 2
// Bitfields for A1846S_SQ_THRESH_REG
#define A1846S_SQ_OPEN_THRESH_BIT 9 // sq open threshold <9:0>
#define A1846S_SQ_OPEN_THRESH_LENGTH 10
#define A1846S_SQ_OPEN_THRESH_BIT 13 // sq open threshold <6:0>
#define A1846S_SQ_OPEN_THRESH_LENGTH 7
// Bitfields for A1846S_SQ_SHUT_THRESH_REG
#define A1846S_SQ_SHUT_THRESH_BIT 9 // sq shut threshold <9:0>
#define A1846S_SQ_SHUT_THRESH_LENGTH 10
#define A1846S_SQ_SHUT_THRESH_BIT 6 // sq shut threshold <6:0>
#define A1846S_SQ_SHUT_THRESH_LENGTH 7
// Bitfields for A1846S_SQ_OUT_SEL_REG
#define A1846S_SQ_OUT_SEL_BIT 7 // sq_out_sel
@@ -174,16 +168,18 @@
#define A1846S_CTCSS2_FLAG_BIT 8 // 1 when txon is enabled
#define A1846S_INVERT_DET_FLAG_BIT 7 // ctcss phase shift detect
#define A1846S_CSS_CMP_FLAG_BIT 2 // ctcss/cdcss compared
#define A1846S_SQ_FLAG_BIT 1 // sq final signal out from dsp
#define A1846S_VOX_FLAG_BIT 0 // vox out from dsp
#define A1846S_SQ_FLAG_BIT 0 // sq final signal out from dsp
#define A1846S_VOX_FLAG_BIT 1 // vox out from dsp
// Bitfields for A1846S_RSSI_REG
#define A1846S_RSSI_BIT 15 // RSSI readings <7:0>
#define A1846S_RSSI_LENGTH 8
// Bitfields for A1846S_VSSI_REG
#define A1846S_VSSI_BIT 14 // voice signal strength indicator <14:0> (unit mV)
#define A1846S_VSSI_LENGTH 15
#define A1846S_VSSI_BIT 15 // voice signal strength indicator <7:0> (unit 0.5dB)
#define A1846S_VSSI_LENGTH 8
#define A1846S_MSSI_BIT 7 // mic signal strength <7:0> (unit 0.5 dB)
#define A1846S_MSSI_LENGTH 8
// Bitfields for A1846S_DTMF_ENABLE_REG
#define A1846S_DTMF_ENABLE_BIT 15
@@ -221,14 +217,24 @@
#define HAMSHIELD_PSK31_FREQ 1000
// Morse Configuration
#define MORSE_FREQ 600
#define MORSE_DOT 150 // ms
#define SYMBOL_END_TIME 5 //millis
#define CHAR_END_TIME (MORSE_DOT*2.7)
#define MESSAGE_END_TIME (MORSE_DOT*8)
#define MIN_DOT_TIME (MORSE_DOT-30)
#define MAX_DOT_TIME (MORSE_DOT+55)
#define MIN_DASH_TIME (MORSE_DOT*3-30)
#define MAX_DASH_TIME (MORSE_DOT*3+55)
class HamShield {
public:
// public singleton for ISRs to reference
static HamShield *sHamShield; // HamShield singleton, used for ISRs mostly
HamShield();
HamShield(uint8_t cs_pin);
HamShield(uint8_t ncs_pin = nCS, uint8_t clk_pin = CLK, uint8_t dat_pin = DAT, uint8_t mic_pin = MIC);
void initialize(); // defaults to 12.5kHz
void initialize(bool narrowBand); // select 12.5kHz if true or 25kHz if false
@@ -248,14 +254,16 @@ class HamShield {
bool frequency_float(float freq_khz);
uint32_t getFrequency();
float getFrequency_float();
/* ToDo
// channel mode
// 11 - 25kHz channel
// 00 - 12.5kHz channel
// 10,01 - reserved
void setChanMode(uint16_t mode);
uint16_t getChanMode();
*/
void setModeTransmit(); // turn off rx, turn on tx
void setModeReceive(); // turn on rx, turn off tx
void setModeOff(); // turn off rx, turn off tx, set pwr_dwn bit
@@ -273,6 +281,7 @@ class HamShield {
void setTxSourceNone();
uint16_t getTxSource();
/*
// PA bias voltage is unused (maybe remove this)
// set PA_bias voltage
// 000000: 1.01V
@@ -285,6 +294,7 @@ class HamShield {
// 1111111:3.13V
void setPABiasVoltage(uint16_t voltage);
uint16_t getPABiasVoltage();
*/
// Subaudio settings
@@ -303,7 +313,11 @@ class HamShield {
uint16_t getCtcssFreqMilliHz();
float getCtcssFreqHz();
void setCtcssFreqToStandard(); // freq must be 134.4Hz for standard cdcss mode
void enableCtcssTx();
void enableCtcssRx();
void enableCtcss();
void disableCtcssTx();
void disableCtcssRx();
void disableCtcss();
void setCtcssDetThreshIn(uint8_t thresh);
uint8_t getCtcssDetThreshIn();
@@ -348,6 +362,7 @@ class HamShield {
int16_t getSQHiThresh();
void setSQLoThresh(int16_t sq_lo_threshold); // Sq detect low th, rssi_cmp will be 0 when rssi<th_l_sq && time delay meet, unit 1dB
int16_t getSQLoThresh();
bool getSquelching();
// SQ out select
void setSQOutSel();
@@ -393,6 +408,9 @@ class HamShield {
uint16_t getDTMFDetectTime();
void setDTMFIdleTime(uint16_t idle_time); // idle time is time between DTMF Tone
uint16_t getDTMFIdleTime();
char DTMFRxLoop();
char DTMFcode2char(uint16_t code);
uint8_t DTMFchar2code(char c);
void setDTMFTxTime(uint16_t tx_time); // tx time is duration of DTMF Tone
uint16_t getDTMFTxTime();
uint16_t disableDTMF();
@@ -402,6 +420,8 @@ class HamShield {
void setDTMFCode(uint16_t code);
// Tone
void HStone(uint8_t pin, unsigned int frequency);
void HSnoTone(uint8_t pin);
void lookForTone(uint16_t tone_hz);
uint8_t toneDetected();
@@ -466,6 +486,7 @@ class HamShield {
// Read Only Status Registers
int16_t readRSSI();
uint16_t readVSSI();
uint16_t readMSSI();
// set output power of radio
void setRfPower(uint8_t pwr);
@@ -482,14 +503,16 @@ class HamShield {
uint32_t findWhitespace(uint32_t start,uint32_t stop, uint8_t dwell, uint16_t step, uint16_t threshold);
uint32_t scanChannels(uint32_t buffer[],uint8_t buffsize, uint8_t speed, uint16_t threshold);
uint32_t findWhitespaceChannels(uint32_t buffer[],uint8_t buffsize, uint8_t dwell, uint16_t threshold);
void buttonMode(uint8_t mode);
static void isr_ptt();
static void isr_reset();
void setupMorseRx();
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]);
char morseRxLoop();
bool handleMorseTone(uint16_t tone_time, bool bits_to_process, uint8_t * rx_morse_char, uint8_t * rx_morse_bit);
char parseMorse(uint8_t rx_morse_char, uint8_t rx_morse_bit);
uint8_t morseLookup(char letter);
uint8_t morseReverseLookup(uint8_t itu);
bool waitForChannel(long timeout, long breakwindow, int setRSSI);
@@ -503,6 +526,7 @@ class HamShield {
private:
uint8_t devAddr;
uint8_t hs_mic_pin;
uint16_t radio_i2c_buf[4];
bool tx_active;
bool rx_active;

View File

@@ -4,6 +4,28 @@
#include "HamShield_comms.h"
uint8_t ncs_pin = nCS;
uint8_t clk_pin = CLK;
uint8_t dat_pin = DAT;
void HSsetPins(uint8_t ncs, uint8_t clk, uint8_t dat) {
ncs_pin = ncs;
clk_pin = clk;
dat_pin = dat;
#if !defined(ARDUINO)
wiringPiSetup();
#endif
pinMode(ncs_pin, OUTPUT);
digitalWrite(ncs_pin, HIGH);
pinMode(clk_pin, OUTPUT);
digitalWrite(clk_pin, HIGH);
pinMode(dat_pin, OUTPUT);
digitalWrite(dat_pin, HIGH);
}
int8_t HSreadBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data)
{
uint16_t b;
@@ -33,22 +55,22 @@ int8_t HSreadWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data)
uint16_t temp_dat;
// bitbang for great justice!
*data = 0;
pinMode(DAT, OUTPUT);
pinMode(dat_pin, OUTPUT);
regAddr = regAddr | (1 << 7);
digitalWrite(devAddr, 0); //PORTC &= ~(1<<1); //devAddr used as chip select
for (int i = 0; i < 8; i++) {
temp = ((regAddr & (0x80 >> i)) != 0);
digitalWrite(CLK, 0); //PORTC &= ~(1<<5); //
digitalWrite(DAT, temp);
digitalWrite(CLK, 1); //PORTC |= (1<<5); //
digitalWrite(clk_pin, 0); //PORTC &= ~(1<<5); //
digitalWrite(dat_pin, temp);
digitalWrite(clk_pin, 1); //PORTC |= (1<<5); //
}
// change direction of DAT
pinMode(DAT, INPUT); // DDRC &= ~(1<<4); //
// change direction of dat_pin
pinMode(dat_pin, INPUT); // DDRC &= ~(1<<4); //
for (int i = 15; i >= 0; i--) {
digitalWrite(CLK, 0); //PORTC &= ~(1<<5); //
digitalWrite(CLK, 1); //PORTC |= (1<<5); //
temp_dat = digitalRead(DAT); //((PINC & (1<<4)) != 0);
digitalWrite(clk_pin, 0); //PORTC &= ~(1<<5); //
digitalWrite(clk_pin, 1); //PORTC |= (1<<5); //
temp_dat = digitalRead(dat_pin); //((PINC & (1<<4)) != 0);
temp_dat = temp_dat << i;
*data |= temp_dat;
}
@@ -91,24 +113,35 @@ bool HSwriteWord(uint8_t devAddr, uint8_t regAddr, uint16_t data)
//digitalWrite(13, HIGH);
// bitbang for great justice!
pinMode(DAT, OUTPUT);
pinMode(dat_pin, OUTPUT);
regAddr = regAddr & ~(1 << 7);
digitalWrite(devAddr, 0); // PORTC &= ~(1<<1); //CS
for (int i = 0; i < 8; i++) {
temp_reg = ((regAddr & (0x80 >> i)) != 0);
digitalWrite(CLK, 0); //PORTC &= ~(1<<5); //
digitalWrite(DAT, regAddr & (0x80 >> i));
digitalWrite(CLK, 1); // PORTC |= (1<<5); //
digitalWrite(clk_pin, 0); //PORTC &= ~(1<<5); //
digitalWrite(dat_pin, regAddr & (0x80 >> i));
digitalWrite(clk_pin, 1); // PORTC |= (1<<5); //
}
for (int i = 0; i < 16; i++) {
temp_dat = ((data & (0x8000 >> i)) != 0);
digitalWrite(CLK, 0); //PORTC &= ~(1<<5); //
digitalWrite(DAT, temp_dat);
digitalWrite(CLK, 1); // PORTC |= (1<<5); //
digitalWrite(clk_pin, 0); //PORTC &= ~(1<<5); //
digitalWrite(dat_pin, temp_dat);
digitalWrite(clk_pin, 1); // PORTC |= (1<<5); //
}
digitalWrite(devAddr, 1); //PORTC |= (1<<1); //CS
return true;
}
}
// Hardware abstraction
unsigned long HSmillis(){
return millis();
}
void HSdelay(unsigned long ms) {
delay(ms);
}
void HSdelayMicroseconds(unsigned int us) {
delayMicroseconds(us);
}

View File

@@ -4,12 +4,27 @@
#ifndef _HAMSHIELD_COMMS_H_
#define _HAMSHIELD_COMMS_H_
#include "Arduino.h"
//#include "I2Cdev.h"
#define nSEN A1
#define CLK A5
#define DAT A4
#if defined(ARDUINO)
#include "Arduino.h"
#define nCS A1 //15 //
#define CLK A5 //19 //
#define DAT A4 //18 //
#define MIC 3
#else // assume Raspberry Pi
#include "stdint.h"
#include <wiringPi.h>
#include <softTone.h>
#define nCS 0 //BCM17, HW pin 11
#define CLK 3 //BCM22, HW pin 15
#define DAT 2 //BCM27, HW pin 13
#define MIC 1 //BCM18, HW pin 12
#endif
void HSsetPins(uint8_t ncs, uint8_t clk, uint8_t dat);
int8_t HSreadBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data);
int8_t HSreadBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data);
@@ -19,4 +34,12 @@ bool HSwriteBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data
bool HSwriteBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data);
bool HSwriteWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
#endif /* _HAMSHIELD_COMMS_H_ */
// hardware abstraction layer
unsigned long HSmillis();
void HSdelay(unsigned long ms);
void HSdelayMicroseconds(unsigned int us);
#endif /* _HAMSHIELD_COMMS_H_ */