You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
5.1 KiB

/*
* Header here
*
*/
#if defined(GPIO)
#include <wiringPi.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
#include <cstring>
#include <cstdio>
#include "UDRCController.h"
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
// Pin definitions
// These use the BCM numbering system, *NOT* physical pin numbers or WiringPi
// "we need to be special" pin numbering.
static const unsigned int BASE_PIN = 6;
static const unsigned int PTT_PIN = 12;
static const unsigned int PKSQL_PIN = 5;
static const unsigned int SQL_PIN = 25;
static const unsigned int EXT1_PIN = 24;
static const unsigned int EXT2_PIN = 22;
static const unsigned int EXT3_PIN = 23;
static const unsigned int EXT4_PIN = 27;
static const unsigned int input_pins[] = {
SQL_PIN,
PKSQL_PIN,
};
static const unsigned int output_pins[] = {
BASE_PIN,
EXT1_PIN,
EXT2_PIN,
EXT3_PIN,
EXT4_PIN,
};
static const char vendor_string_path[] = "/proc/device-tree/hat/vendor";
static const char product_id_string_path[] = "/proc/device-tree/hat/product_id";
static const char nwdr_vendor_string[] = "NW Digital Radio";
#define UDRC_PRODUCT_ID 2
#define UDRC_II_PRODUCT_ID 3
static int getNWDRProductID() {
int proc_file = -1;
ssize_t read_size;
char buffer[255];
long product_id = 0;
if((proc_file = open(vendor_string_path, O_RDONLY|O_NONBLOCK)) == -1) {
::fprintf(stderr, "Open %s: %s\n", vendor_string_path, strerror(errno));
}
read_size = read(proc_file, buffer, sizeof(buffer));
if(read_size < 1) {
::fprintf(stderr, "Read %s: %s\n", vendor_string_path, strerror(errno));
close(proc_file);
return -1;
}
close(proc_file);
if(strncmp(nwdr_vendor_string, buffer, sizeof(nwdr_vendor_string))) {
::fprintf(stderr, "HAT is not a NW Digital Radio Product: %.255s\n", buffer);
return -1;
}
if((proc_file = open(product_id_string_path, O_RDONLY|O_NONBLOCK)) == -1) {
::fprintf(stderr, "Open %s: %s\n", product_id_string_path, strerror(errno));
}
read_size = read(proc_file, buffer, sizeof(buffer));
if(read_size < 1) {
::fprintf(stderr, "Read %s: %s\n", product_id_string_path, strerror(errno));
close(proc_file);
return -1;
}
close(proc_file);
product_id = strtol(buffer, nullptr, 16);
if(product_id == EINVAL || product_id == ERANGE) {
::fprintf(stderr, "Invalid value for product id: %.255s\n", buffer);
return -1;
}
return product_id;
}
// XXX This is ugly, we should have a better parent class
CUDRCController::CUDRCController(enum repeater_modes mode) :
CExternalController(nullptr, false),
m_mode(mode),
m_pttPin(PTT_PIN)
{
}
void CUDRCController::switchMode(enum repeater_modes mode) {
if(mode == HOTSPOT)
return;
switch(mode) {
case AUTO_FM: // Auto/FM
::digitalWrite(EXT1_PIN, HIGH);
::digitalWrite(EXT2_PIN, HIGH);
break;
case DIGITAL_DIGITAL: // Digital/Digital
::digitalWrite(EXT1_PIN, HIGH);
::digitalWrite(EXT2_PIN, LOW);
break;
case FM_FM: // FM/FM Fixed
::digitalWrite(EXT1_PIN, LOW);
::digitalWrite(EXT2_PIN, HIGH);
break;
case AUTO_AUTO: // Auto/Auto
::digitalWrite(EXT1_PIN, LOW);
::digitalWrite(EXT2_PIN, LOW);
break;
default:
break;
}
}
bool CUDRCController::open()
{
if(::wiringPiSetupGpio() != 0) {
::fprintf(stderr, "Unable to initialize the wiringPi library\n");
return false;
}
if(m_mode != HOTSPOT) {
::pinMode(m_pttPin, OUTPUT);
for(unsigned int i = 0; i < ARRAY_SIZE(input_pins); ++i) {
::pinMode(input_pins[i], INPUT);
::pullUpDnControl(input_pins[i], PUD_UP);
}
for(unsigned int i = 0; i < ARRAY_SIZE(output_pins); ++i) {
::pinMode(output_pins[i], OUTPUT);
::digitalWrite(output_pins[i], HIGH);
}
::digitalWrite(m_pttPin, HIGH);
::digitalWrite(BASE_PIN, LOW);
switchMode(m_mode);
::digitalWrite(BASE_PIN, HIGH);
} else {
// On a UDRC II in Hotspot mode, the PTT is on EXT3_PIN instead
switch(getNWDRProductID()) {
case UDRC_PRODUCT_ID:
m_pttPin = PTT_PIN;
break;
case UDRC_II_PRODUCT_ID:
m_pttPin = EXT3_PIN;
break;
case -1:
return false;
default:
::fprintf(stderr, "Unknown NW Digital Radio Product\n");
return false;
}
::pinMode(m_pttPin, OUTPUT);
::digitalWrite(m_pttPin, LOW);
}
return true;
}
bool CUDRCController::getDisable() const
{
if(m_mode == HOTSPOT)
return false;
return ::digitalRead(PKSQL_PIN) == LOW;
}
void CUDRCController::setRadioTransmit(bool value)
{
// If we're in hotspot mode, we're using the miniDIN connector that is
// reversed from the normal sense of PTT.
if(m_mode == HOTSPOT)
value = !value;
::digitalWrite(m_pttPin, value ? LOW : HIGH);
}
void CUDRCController::setActive(bool value)
{
if(m_mode == HOTSPOT)
return;
if(value == HIGH) {
::digitalWrite(BASE_PIN, LOW);
switchMode(FM_FM);
} else {
switchMode(m_mode);
::digitalWrite(BASE_PIN, HIGH);
}
}
// This needs to be overridden for now because the base class, ExternalController
// will try to dork around with threads that we're not using anymore.
void CUDRCController::close()
{
if(m_mode == HOTSPOT) {
::digitalWrite(m_pttPin, LOW);
} else {
::digitalWrite(m_pttPin, HIGH);
}
}
#endif

Powered by TurnKey Linux.