A C program (rptrctrl.c) to do a 'minimalist' repeater controller using a Raspberry PI and simple interfacing circuitry on the GPIO Port.
To clone this repo, type:
git clone https://github.com/kodetroll/rptr-ctrl-pi.git
Alternatively, either click on the 'Download' button to download a zipfile (master.zip) of the repository contents, or use this url:
https://github.com/kodetroll/rptr-ctrl-pi/archive/master.zip
This code was converted from an Arduino sketch I wrote sometime ago and is only intended as a starting point test bed for testing the implementation method. Standard Arduino sketch functions (digitalWrite, digitalRead, pinMode, etc.) were replaced with functions abstracting calls to Mike McCauley's library for Broadcom BCM2835 GPIO. This functionality is pretty close to a 1:1 map. Good enough for a start, anyway. (Yes, I realize there is a wiringPI lib for the Raspberry PI).
This implementation of a repeater controller does not afford a separate input for a tone decoder's output, hence the term, 'minimalist'. To provide tone access control, the receiver must have tone decoding built in and the COR output from the receiver must 'AND' with this.
Currently ID audio is intended to be generated by pulsing a GPIO pin which should control an off board audio tone generator. Onboard tone generation via PWM is a work in progress and WAV based VOICE ID may be in the next version!
The COR input, COR Indication, PTT output, and CWID keyer pins on the Rasberry PI GPIO port are specified by global defines in the source code. These should be changed to match your hardware configuration or implementation.
The default pin mappings are that the PTT output pin (PTT_PIN) is GPIO17, the COR input pin (CIR_PIN) is on GPIO18, the COR Indicator (COR_LED) (illuminates an LED when COR is active) is on GPIO22 and the CW ID Pin (ID_PIN) (gates or controls an offboard tone generator for the ID audio) is on GPIO21.
For testing, the COR input is simulated by a switch to ground on the COR input pin. An internal pull up resistor on this pin is enabled in the pinMode() function. The PTT is simulated by an LED and resistor to ground, which illuminates when PTT is active. The COR indicator LED as well as the CW ID pin can also be an LED to ground to accomplish that function.
Default values for the ID timer (600 Seconds - 10 minutes) and the squelch tail timer (1 second) are specified by defines. The runtime values of these parameters are stored in variables and could be changed programatically, if desired (e.g. via the serial port). Of course, you'd have to write that code.
The ID Time out timer is implemented using the C time library and is based on the elapsed time counter (unsigned long int seconds) so timeout timer precision is restricted to integer values of one second. The squelch tail timer is implemented the same way, so it has the same restrictions.
See INSTALL for instructions on building the application.
See LICENSE for licensing info
'sudo ./rptctrl'
- NOTE: This application must be run as root to have permissions to modify the GPIO pins.
There are three debug defines, DEBUG, DEBUG_BEEP, and DEBUG_TONE. These should be set to zero. These are left over from my conversion from the Arduino sketch.
The default starting timer values are defined as:
- DEFAULT_ID_TIMER - The time between CWIDs, defaults to 600 Seconds
- DEFAULT_SQ_TIMER - The squelch tail ON time, defaults to 1 Second
Other misc timer values (specified in mS):
- ID_PTT_DELAY - Time between PTT ON and start of CBEEP, defaults to 200 mS
- ID_PTT_HANG - Amount of PTT time after CBEEP, defaults to 500 mS
- CW_MIN_DELAY - Minimum inter-element delay, defaults to 30 mS
- COR_DEBOUNCE_DELAY - Amount of time COR must be present before being counted as valid, defaults to 50 mS
COR and PTT logic sense can be specified as POSITIVE or NEGATIVE; there are INI file settings to define these without recompiling. The defaults are COR_NEG_LOGIC (H to L transition, L active), and PTT_POS_LOGIC (L to H transition, H active). If the defaults are changed in the sources, the application must be recompiled. However, the value read from the config file will override the defaults.
[CONTROL]
CORSense=Negative
PTTSense=Positive
PTTPin=17
CORPin=18
CORLEDPin=22
CWIDPin=21
PWMPin=18
IDPTTDelay=200
IDPTTHang=500
CWMinDelay=30
CORDebounceDelay=50
The GPIO pins that control COR/PTT/COR INDICATION & CWID are definable as well. The defaults are defined as follows:
// This is where we define what DIO PINs map to what functions
int PTT_PIN = 17; // DIO Pin number for the PTT out - 17
int COR_PIN = 18; // DIO Pin number for the COR in - 18
int COR_LED = 22; // DIO Pin number for the undebounced COR indicator LED - 22
int ID_PIN = 21; // DIO Pin for the ID Audio output tone
int PWM_PIN = 18; // PWM Pin for the ID Audio output tone
Change these values to map these functions to alternate GPIO pins. These are variables, so they can be overridden by chages to the config file. However, if the defaults are changed, the application must be recompiled.
This program utilizes a state machine to control the various stages of the repeater action. These are enumerated as CtrlStates and are (briefly):
| State Name | State Description |
|---|---|
| CS_START | Starting state |
| CS_IDLE | IDLE state, waiting for COR activity |
| CS_DEBOUNCE_COR_ON | COR active sensed, waiting debounce time. |
| CS_PTT_ON | Setting PTT to active state |
| CS_PTT | PTT in active hold state |
| CS_DEBOUNCE_COR_OFF | COR dropped, going to Squelch Tail |
| CS_SQT_ON | Squelch tail activated |
| CS_SQT_BEEP | Courtesy Beep generating |
| CS_SQT | Squelch tail hold |
| CS_SQT_OFF | Setting Squelch tail to inactive |
| CS_PTT_OFF | Setting PTT to inactive |
| CS_ID | Play ID |
As the program runs, various events (changing inputs, timers, etc) cause the program to advance from state to state. At each state, actions are taken (outputs changed, etc) abd the next state decided. The program is limited to only those states programmed.
The program layout somewhat resembles an arduino sketch. There is a 'setup' function that resembles the similarly named arduino function, which is run once at program start, and a 'loop' function that runs continiously.
During execution of the loop section, the COR state is read and a switch statement fires a CASE (once for each state) based on the current state. As each state CASE is completed, the next state is defined. In this way the program steps from state to state. Some states are transition states, in which they are executed once and proceed immediately to the next state with the next call of loop(). Other states are entered and the program will loiter there through multiple calls of loop() until some condition is met or reached and the state changes. Transition states may output messages to STDOUT indicating current machine status.
To permanently program the CW ID callsign, simply change the value of DEFAULT_CALLSIGN as defined in the source header.
Note: All conversion to 'Elements' is taken care of automagically.
With the version that supports an external configuratio file, you can edit the supplied example file 'rptrctrl.cfg', replacing the contents of the file to suityour installation. For example:
[CWID]
Callsign=N0S
[TONES]
CWIDFreq=1200
CBEEPtype=DeDoop
CBEEPFreq1=1000
CBEEPFreq2=800
CBEEPTimeDuration=2
CWIDClockTime=50
To set the CW ID Speed, find and change the value of CWIDClockTime. This will set the value of CW_TIMEBASE at runtime. If this value is missing from, it will default to a value of '50' mS which is about 20 WPM, give or take.
The type of courtesy beep is set by the value of CBEEPtype, which sets the value of BEEP_type at runtime. You can specify 5 different types of courtesy beep (CBEEP) by changing the value of the CBEEPType config value. The possible values are: are:
| Type | Description |
|---|---|
| CBEEP_NONE | No CBEEP |
| CBEEP_SINGLE | Single tone |
| CBEEP_DEDOOP | Two tone, hi to low frequency |
| CBEEP_DODEEP | Two tone, low to hi frequency |
| CBEEP_DEDEEP | Two tone, same frequency |
The default is CBEEP_SINGLE. The software must be recompiled for any changes to the default to take effect.
The duration of the courtesy tone beep is set by CBEEPTimeDuration which sets the value of BeepDuration at runtime. This value defaults to '2' (in CWID clock increments) or 100 mS.
The two differenet CBEEP tone frequencies are set by changing the values of CBEEPFreq1 and CBEEPFreq2. These in turn set the runtime values of BEEP_tone1 and BEEP_tone2. These default to 1000 and 800 hz, respectivly.
The CWID Tone value is set with CWIDFreq which sets the runtime value of ID_tone, and defaults to 1200 hz.
These tones are generated by the PWM module of the bcm2835 lib and are written out to the pin specified by the value of PWM_PIN. This signal can be mixed or injected into the repeater audio path. In addition, an external tone generator can be keyed by using the ID_PIN GPIO output.
Currently, changing these values no longer requires a recompile to make any changes active. Merely setting them in the config file is all that is required.