begin abstracting hardware functions

This commit is contained in:
Morgan Redfield 2019-01-29 21:10:18 -08:00
parent 76a92a882f
commit f7c76eb1ad
4 changed files with 121 additions and 75 deletions

View File

@ -3,13 +3,20 @@
// 11/22/2013 by Morgan Redfield <redfieldm@gmail.com> // 11/22/2013 by Morgan Redfield <redfieldm@gmail.com>
// 04/26/2015 various changes Casey Halverson <spaceneedle@gmail.com> // 04/26/2015 various changes Casey Halverson <spaceneedle@gmail.com>
#include "Arduino.h"
#include "HamShield.h" #include "HamShield.h"
#include "stdint.h"
#include "math.h"
#if defined(__AVR__)
#include <avr/pgmspace.h> #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 */ /* don't change this regulatory value, use dangerMode() and safeMode() instead */
bool restrictions = true; bool restrictions = true;
/* channel lookup tables */ /* channel lookup tables */
@ -31,7 +38,6 @@ unsigned int morse_dot_millis = 100;
// It will occupy 108 bytes of memory (or program memory if defined) // It will occupy 108 bytes of memory (or program memory if defined)
#define MORSE_TABLE_LENGTH 54 #define MORSE_TABLE_LENGTH 54
#define MORSE_TABLE_PROGMEM
#ifndef MORSE_TABLE_PROGMEM #ifndef MORSE_TABLE_PROGMEM
const struct asciiMorse { const struct asciiMorse {
char ascii; char ascii;
@ -119,8 +125,9 @@ const unsigned char AFSK_space[] PROGMEM = { 140, 228, 250, 166, 53, 0, 53, 166,
* @see A1846S_ADDRESS_AD0_LOW * @see A1846S_ADDRESS_AD0_LOW
* @see A1846S_ADDRESS_AD0_HIGH * @see A1846S_ADDRESS_AD0_HIGH
*/ */
HamShield::HamShield(uint8_t cs_pin = nSEN, uint8_t clk_pin = CLK, uint8_t dat_pin = DAT) { HamShield::HamShield(uint8_t cs_pin = nSEN, uint8_t clk_pin = CLK, uint8_t dat_pin = DAT, uint8_t pwm_pin = HAMSHIELD_PWM_PIN) {
devAddr = cs_pin; devAddr = cs_pin;
hs_pwm_pin = pwm_pin;
HSsetPins(cs_pin, clk_pin, dat_pin); HSsetPins(cs_pin, clk_pin, dat_pin);
} }
@ -193,13 +200,13 @@ void HamShield::initialize(bool narrowBand) {
// calibration // calibration
tx_data = 0x00A4; tx_data = 0x00A4;
HSwriteWord(devAddr, 0x30, tx_data); HSwriteWord(devAddr, 0x30, tx_data);
delay(100); HSdelay(100);
tx_data = 0x00A6; tx_data = 0x00A6;
HSwriteWord(devAddr, 0x30, tx_data); HSwriteWord(devAddr, 0x30, tx_data);
delay(100); HSdelay(100);
tx_data = 0x0006; tx_data = 0x0006;
HSwriteWord(devAddr, 0x30, tx_data); HSwriteWord(devAddr, 0x30, tx_data);
delay(100); HSdelay(100);
// set band width // set band width
@ -209,7 +216,7 @@ void HamShield::initialize(bool narrowBand) {
setupWideBand(); setupWideBand();
} }
delay(100); HSdelay(100);
/* /*
// setup default values // setup default values
@ -397,15 +404,9 @@ bool HamShield::testConnection() {
* to 7FH, and then write value to the address subtracted by * to 7FH, and then write value to the address subtracted by
* 80H. Finally write 0x0000 to 7FH * 80H. Finally write 0x0000 to 7FH
* Example: writing 85H register address is 0x001F . * Example: writing 85H register address is 0x001F .
* Move 7FH 0x0001{ * Move 7FH 0x0001{}
* Move 05H 0x001F{} 05H=85H-80H
} * Move 7FH 0x0000{}
* Move 05H 0x001F{
} 05H=85H-80H
* Move 7FH 0x0000{
}
*/ */
uint16_t HamShield::readCtlReg() { uint16_t HamShield::readCtlReg() {
@ -416,7 +417,7 @@ uint16_t HamShield::readCtlReg() {
void HamShield::softReset() { void HamShield::softReset() {
uint16_t tx_data = 0x1; uint16_t tx_data = 0x1;
HSwriteWord(devAddr, A1846S_CTL_REG, tx_data); 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; tx_data = 0x4;
HSwriteWord(devAddr, A1846S_CTL_REG, tx_data); HSwriteWord(devAddr, A1846S_CTL_REG, tx_data);
} }
@ -540,7 +541,7 @@ void HamShield::setTX(bool on_noff){
//setGpioHi(4); // V1 //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); HSwriteBitW(devAddr, A1846S_CTL_REG, A1846S_TX_MODE_BIT, on_noff);
@ -562,7 +563,7 @@ void HamShield::setRX(bool on_noff){
setGpioLow(4); // V1 setGpioLow(4); // V1
setGpioLow(5); // V2 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); HSwriteBitW(devAddr, A1846S_CTL_REG, A1846S_RX_MODE_BIT, on_noff);
@ -1066,10 +1067,10 @@ void HamShield::lookForTone(uint16_t t_hz) {
float tone_hz = (float) t_hz; float tone_hz = (float) t_hz;
float Fs = 6400000/1024; float Fs = 6400000/1024;
float k = floor(tone_hz/Fs*127 + 0.5); 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); 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 // set tone
HSwriteWord(devAddr, 0x68, t); HSwriteWord(devAddr, 0x68, t);
@ -1370,8 +1371,12 @@ bool HamShield::frequency_float(float freq_khz) {
/* FRS Lookup Table */ /* FRS Lookup Table */
bool HamShield::setFRSChannel(uint8_t channel) { bool HamShield::setFRSChannel(uint8_t channel) {
if(channel < 15) { if(channel < 15) {
#if defined(__AVR__)
setFrequency(pgm_read_dword_near(FRS + channel)); setFrequency(pgm_read_dword_near(FRS + channel));
#else
setFrequency(FRS[channel]);
#endif
return true; return true;
} }
return false; return false;
@ -1382,11 +1387,19 @@ bool HamShield::setFRSChannel(uint8_t channel) {
bool HamShield::setGMRSChannel(uint8_t channel) { bool HamShield::setGMRSChannel(uint8_t channel) {
if((channel > 8) & (channel < 16)) { if((channel > 8) & (channel < 16)) {
channel = channel - 7; // we start with 0, to try to avoid channel 8 being nothing 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; return true;
} }
if(channel < 9) { 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 true;
} }
return false; return false;
@ -1396,7 +1409,11 @@ bool HamShield::setGMRSChannel(uint8_t channel) {
bool HamShield::setMURSChannel(uint8_t channel) { bool HamShield::setMURSChannel(uint8_t channel) {
if(channel < 6) { 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; return true;
} }
} }
@ -1405,7 +1422,11 @@ bool HamShield::setMURSChannel(uint8_t channel) {
bool HamShield::setWXChannel(uint8_t channel) { bool HamShield::setWXChannel(uint8_t channel) {
if(channel < 8) { 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(); setModeReceive();
// turn off squelch? // turn off squelch?
// channel bandwidth? // channel bandwidth?
@ -1421,7 +1442,7 @@ uint8_t HamShield::scanWXChannel() {
int16_t toprssi = 0; int16_t toprssi = 0;
for(int x = 0; x < 8; x++) { for(int x = 0; x < 8; x++) {
setWXChannel(x); setWXChannel(x);
delay(100); HSdelay(100);
int16_t rssi = readRSSI(); int16_t rssi = readRSSI();
if(rssi > toprssi) { toprssi = rssi; channel = x; } if(rssi > toprssi) { toprssi = rssi; channel = x; }
} }
@ -1527,13 +1548,13 @@ Does not take in account the millis() overflow
bool HamShield::waitForChannel(long timeout = 0, long breakwindow = 0, int setRSSI = HAMSHIELD_EMPTY_CHANNEL_RSSI) { 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 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 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() 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 rssi = readRSSI(); // Read signal strength
if(rssi < setRSSI) { // If the channel is empty, lets see if anyone breaks in. if(rssi < setRSSI) { // If the channel is empty, lets see if anyone breaks in.
timer = millis() + breakwindow; timer = HSmillis() + breakwindow;
while(timer > millis()) { while(timer > HSmillis()) {
rssi = readRSSI(); rssi = readRSSI();
if(rssi > setRSSI) { return false; } // Someone broke into the channel, abort. if(rssi > setRSSI) { return false; } // Someone broke into the channel, abort.
} return true; // It passed the test...channel is open. } return true; // It passed the test...channel is open.
@ -1577,13 +1598,13 @@ void HamShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) {
// We delay by 4 here, if we previously sent a symbol. Otherwise 7. // We delay by 4 here, if we previously sent a symbol. Otherwise 7.
// This could probably just be always 7 and go relatively unnoticed. // This could probably just be always 7 and go relatively unnoticed.
if(prev == 0 || prev == ' '){ if(prev == 0 || prev == ' '){
//tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis * 7); //tone(hs_pwm_pin, 6000, morse_dot_millis * 7);
noTone(HAMSHIELD_PWM_PIN); HSnoTone(hs_pwm_pin);
delay(morse_dot_millis*7); HSdelay(morse_dot_millis*7);
} else { } else {
//tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis * 4); //tone(hs_pwm_pin, 6000, morse_dot_millis * 4);
noTone(HAMSHIELD_PWM_PIN); HSnoTone(hs_pwm_pin);
delay(morse_dot_millis*4); HSdelay(morse_dot_millis*4);
} }
continue; continue;
} }
@ -1592,22 +1613,22 @@ void HamShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) {
if(bits) { // If it is a valid character... if(bits) { // If it is a valid character...
do { do {
if(bits & 1) { if(bits & 1) {
tone(HAMSHIELD_PWM_PIN, morse_freq, morse_dot_millis * 3); HStone(hs_pwm_pin, morse_freq, morse_dot_millis * 3);
delay(morse_dot_millis*3); HSdelay(morse_dot_millis*3);
} else { } else {
tone(HAMSHIELD_PWM_PIN, morse_freq, morse_dot_millis); HStone(hs_pwm_pin, morse_freq, morse_dot_millis);
delay(morse_dot_millis); HSdelay(morse_dot_millis);
} }
//tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis); //tone(hs_pwm_pin, 6000, morse_dot_millis);
noTone(HAMSHIELD_PWM_PIN); HSnoTone(hs_pwm_pin);
delay(morse_dot_millis); HSdelay(morse_dot_millis);
bits >>= 1; // Shift into the next symbol bits >>= 1; // Shift into the next symbol
} while(bits != 1); // Wait for 1 termination to be all we have left } while(bits != 1); // Wait for 1 termination to be all we have left
} }
// End of character // End of character
//tone(HAMSHIELD_PWM_PIN, 6000, morse_dot_millis * 3); //tone(hs_pwm_pin, 6000, morse_dot_millis * 3);
noTone(HAMSHIELD_PWM_PIN); HSnoTone(hs_pwm_pin);
delay(morse_dot_millis * 3); HSdelay(morse_dot_millis * 3);
} }
return; return;
} }
@ -1674,7 +1695,7 @@ void HamShield::SSTVVISCode(int code) {
toneWait(1900,300); toneWait(1900,300);
toneWait(1200,30); toneWait(1200,30);
for(int x = 0; x < 7; x++) { 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); } if(parityCalc(code)) { toneWait(1300,30); } else { toneWait(1100,30); }
toneWait(1200,30); toneWait(1200,30);
@ -1737,19 +1758,19 @@ void HamShield::SSTVTestPattern(int code) {
/* wait for tone to complete */ /* wait for tone to complete */
void HamShield::toneWait(uint16_t freq, long timer) { void HamShield::toneWait(uint16_t freq, long timer) {
tone(HAMSHIELD_PWM_PIN,freq,timer); HStone(hs_pwm_pin,freq,timer);
delay(timer); HSdelay(timer);
} }
/* wait microseconds for tone to complete */ /* wait microseconds for tone to complete */
void HamShield::toneWaitU(uint16_t freq, long timer) { void HamShield::toneWaitU(uint16_t freq, long timer) {
if(freq < 16383) { if(freq < 16383) {
tone(HAMSHIELD_PWM_PIN,freq); HStone(hs_pwm_pin,freq);
delayMicroseconds(timer); noTone(HAMSHIELD_PWM_PIN); return; HSdelayMicroseconds(timer); HSnoTone(hs_pwm_pin); return;
} }
tone(HAMSHIELD_PWM_PIN,freq); HStone(hs_pwm_pin,freq);
delay(timer / 1000); noTone(HAMSHIELD_PWM_PIN); return; HSdelay(timer / 1000); HSnoTone(hs_pwm_pin); return;
} }

View File

@ -9,22 +9,12 @@
#define _HAMSHIELD_H_ #define _HAMSHIELD_H_
#include "HamShield_comms.h" #include "HamShield_comms.h"
//#include "SimpleFIFO.h"
//#include "AFSK.h"
//#include "DDS.h"
#include <avr/pgmspace.h>
// HamShield constants // HamShield constants
#define HAMSHIELD_MORSE_BUFFER_SIZE 80 // Char buffer size for morse code text #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" #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 // Device Registers
#define A1846S_CTL_REG 0x30 // control register #define A1846S_CTL_REG 0x30 // control register
#define A1846S_CLK_MODE_REG 0x04 // clk_mode #define A1846S_CLK_MODE_REG 0x04 // clk_mode
@ -230,10 +220,7 @@
class HamShield { class HamShield {
public: public:
// public singleton for ISRs to reference HamShield(uint8_t cs_pin = nSEN, uint8_t clk_pin = CLK, uint8_t dat_pin = DAT, uint8_t pwm_pin = HAMSHIELD_PWM_PIN);
static HamShield *sHamShield; // HamShield singleton, used for ISRs mostly
HamShield(uint8_t cs_pin = nSEN, uint8_t clk_pin = CLK, uint8_t dat_pin = DAT);
void initialize(); // defaults to 12.5kHz void initialize(); // defaults to 12.5kHz
void initialize(bool narrowBand); // select 12.5kHz if true or 25kHz if false void initialize(bool narrowBand); // select 12.5kHz if true or 25kHz if false
@ -509,6 +496,7 @@ class HamShield {
private: private:
uint8_t devAddr; uint8_t devAddr;
uint8_t hs_pwm_pin;
uint16_t radio_i2c_buf[4]; uint16_t radio_i2c_buf[4];
bool tx_active; bool tx_active;
bool rx_active; bool rx_active;

View File

@ -5,6 +5,8 @@
#include "HamShield_comms.h" #include "HamShield_comms.h"
#include "Arduino.h"
//#include "I2Cdev.h"
uint8_t ncs_pin = nSEN; uint8_t ncs_pin = nSEN;
uint8_t clk_pin = CLK; uint8_t clk_pin = CLK;
@ -131,4 +133,25 @@ bool HSwriteWord(uint8_t devAddr, uint8_t regAddr, uint16_t data)
digitalWrite(devAddr, 1); //PORTC |= (1<<1); //CS digitalWrite(devAddr, 1); //PORTC |= (1<<1); //CS
return true; return true;
}
// Hardware abstraction
unsigned long HSmillis(){
return millis();
}
void HSdelay(unsigned long ms) {
delay(ms);
}
void HSdelayMicroseconds(unsigned int us) {
delayMicroseconds(us);
}
void HStone(uint8_t pin, unsigned int frequency) {
tone(pin, frequency);
}
void HStone(uint8_t pin, unsigned int frequency, unsigned long duration) {
tone(pin, frequency, duration);
}
void HSnoTone(uint8_t pin) {
noTone(pin);
} }

View File

@ -4,12 +4,14 @@
#ifndef _HAMSHIELD_COMMS_H_ #ifndef _HAMSHIELD_COMMS_H_
#define _HAMSHIELD_COMMS_H_ #define _HAMSHIELD_COMMS_H_
#include "Arduino.h" #include "stdint.h"
//#include "I2Cdev.h"
#include "Arduino.h"
#define nSEN A1 //15 //
#define CLK A5 //19 //
#define DAT A4 //18 //
#define HAMSHIELD_PWM_PIN 3 // Pin assignment for PWM output
#define nSEN A1
#define CLK A5
#define DAT A4
void HSsetPins(uint8_t ncs, uint8_t clk, uint8_t dat); void HSsetPins(uint8_t ncs, uint8_t clk, uint8_t dat);
@ -21,4 +23,16 @@ 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 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); bool HSwriteWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
// hardware abstraction layer
unsigned long HSmillis();
void HSdelay(unsigned long ms);
void HSdelayMicroseconds(unsigned int us);
void HStone(uint8_t pin, unsigned int frequency);
void HStone(uint8_t pin, unsigned int frequency, unsigned long duration);
void HSnoTone(uint8_t pin);
#endif /* _HAMSHIELD_COMMS_H_ */ #endif /* _HAMSHIELD_COMMS_H_ */