Skip to content

Commit

Permalink
Added configurable amplifier sequencing
Browse files Browse the repository at this point in the history
(TX delay, TX hold off, AMP on/off)
  • Loading branch information
bubnikv committed Apr 2, 2018
1 parent f54bfc3 commit 56ee924
Show file tree
Hide file tree
Showing 11 changed files with 419 additions and 27 deletions.
Binary file modified basic.cydsn/TopDesign/TopDesign.cysch
Binary file not shown.
38 changes: 38 additions & 0 deletions basic.cydsn/VariableDelay32/API/api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "`$INSTANCE_NAME`_api.h"
#include <device.h>

void `$INSTANCE_NAME`_Start(void)
{
// Reset the counter.
CY_SET_REG8(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_A0_REG, 0);
CY_SET_REG8(`$INSTANCE_NAME`_Datapath_1_u2__16BIT_A0_REG, 0);
// Reset the delay to a single tick.
CY_SET_REG8(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_D1_REG, 1);
CY_SET_REG8(`$INSTANCE_NAME`_Datapath_1_u2__16BIT_D1_REG, 0);
CY_SET_REG8(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_D0_REG, 1);
CY_SET_REG8(`$INSTANCE_NAME`_Datapath_1_u2__16BIT_D0_REG, 0);
}

void `$INSTANCE_NAME`_SetDelay(int8 delay)
{
uint32 high = 1 << delay;
uint32 mask = high - 1;
// Reset the counter.
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_A0_REG, 0);
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u2__16BIT_A0_REG, 0);
#if 1
// Set the length of a shift register by a mask.
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_D1_REG, mask & 0x0ffff);
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u1__16BIT_D1_REG, mask >> 16);
// Set the highest bit of the shift register. This is the output of the shift register.
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_D0_REG, high & 0x0ffff);
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u1__16BIT_D0_REG, high >> 16);
#else
// Set the length of a shift register by a mask.
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u2__16BIT_D1_REG, mask & 0x0ffff);
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_D1_REG, mask >> 16);
// Set the highest bit of the shift register. This is the output of the shift register.
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u2__16BIT_D0_REG, high & 0x0ffff);
CY_SET_REG16(`$INSTANCE_NAME`_Datapath_1_u0__16BIT_D0_REG, high >> 16);
#endif
}
21 changes: 21 additions & 0 deletions basic.cydsn/VariableDelay32/API/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// ========================================
// Copyright 2013 David Turnbull AE9RB
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================

#include "cytypes.h"
#include "cyfitter.h"

void `$INSTANCE_NAME`_Start();
void `$INSTANCE_NAME`_SetDelay(int8 delay);
Binary file added basic.cydsn/VariableDelay32/VariableDelay32.cysym
Binary file not shown.
Binary file not shown.
237 changes: 236 additions & 1 deletion basic.cydsn/basic.cyprj

Large diffs are not rendered by default.

27 changes: 21 additions & 6 deletions basic.cydsn/basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,34 @@ extern uint8 TX_Phase;
// End the transmit of PC audio data.
#define TX_PHASE_TXPC_EXIT 11
// Transmitting an internal shaped IQ tone, keyed by the external key down signal.
#define TX_PHASE_IQTONE_RAMP_UP 20
#define TX_PHASE_IQTONE_STEADY 21
#define TX_PHASE_IQTONE_RAMP_DOWN 22
#define TX_PHASE_IQTONE_END 23
#define TX_PHASE_IQTONE_UNMUTE 24
#define TX_PHASE_IQTONE_EXIT 25
#define TX_PHASE_IQTONE_IDLE 20
#define TX_PHASE_IQTONE_RAMP_UP 21
#define TX_PHASE_IQTONE_STEADY 22
#define TX_PHASE_IQTONE_RAMP_DOWN 23
#define TX_PHASE_IQTONE_HANG 24
#define TX_PHASE_IQTONE_END 25
#define TX_PHASE_IQTONE_UNMUTE 26
#define TX_PHASE_IQTONE_EXIT 27

// Phase of the IQ tone generator (position at the amplitude envelope of the IQ hump).
extern uint8 TX_IQ_Phase;

// Is the TX frequency active? If false, Si570_RX_LO is active, otherwise Si570_TX_LO is active.
extern uint8 TX_Frequency;

struct AmpSequencingConfig
{
uint8 AMP_Enabled;
// Initial TX delay after AMP relay is switched in, in 0.5ms. Maximum time is 15ms.
uint8 TX_Delay;
// TX Hang time for the amplifier control, in 0.5ms. Maximum time 32 seconds.
uint16 TX_Hang;
};

extern struct AmpSequencingConfig AmpSequencingNew;
extern struct AmpSequencingConfig AmpSequencingCurrent;

void AmpSequencingReset();
void TX_Main(void);

// t1.c
Expand Down
3 changes: 0 additions & 3 deletions basic.cydsn/iambic/API/iambic.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,16 @@

void `$INSTANCE_NAME`_SetSpeed(uint8 val)
{
// CY_SET_REG8(`$INSTANCE_NAME`_cntr8_D0_PTR,val);
CY_SET_REG8(`$INSTANCE_NAME`_cntr8_u0__D0_REG,val);
}

uint8 `$INSTANCE_NAME`_GetSpeed()
{
// return CY_GET_REG8(`$INSTANCE_NAME`_cntr8_D0_PTR);
return CY_GET_REG8(`$INSTANCE_NAME`_cntr8_u0__D0_REG);
}

void `$INSTANCE_NAME`_SetMode(uint8 val)
{
// CY_SET_REG8(`$INSTANCE_NAME`_cntr8_D0_PTR,val);
CY_SET_REG8(`$INSTANCE_NAME`_IAMBIC_CONTROL__CONTROL_REG,val);
}

Expand Down
4 changes: 3 additions & 1 deletion basic.cydsn/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ void main_init() {
TONE_CLK_SetDividerRegister(625, 1);
// 1200Hz sidetone
TONE_CLK_SetDividerRegister(625/2, 1);

AmpSequencingReset();
}

// A compliant USB device is required to monitor
Expand Down Expand Up @@ -74,6 +76,7 @@ void main()
for(;;) {
// USB Audio is very high priority
Audio_Main();
// Sync the internal RC oscillator onto the isochronous USB 1kHz framing.
Sync_Main();
// Everything else runs twice per millisecond
// Keep T1 first for timing accuracy
Expand Down Expand Up @@ -107,7 +110,6 @@ void main()
beat = i;
}
}

}
}

Expand Down
111 changes: 95 additions & 16 deletions basic.cydsn/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,51 @@
#define TX_LED_BLINK_ON_MS 40
#define TX_LED_BLINK_OFF_MS 50

// Bitmap of TX_xxx flags indicating TX state.
uint8 TX_State = 0;
// Phase of the IQ tone generator (position at the amplitude envelope of the IQ hump).
uint8 TX_Phase = TX_PHASE_RECEIVING;
// Is the TX frequency active? If false, Si570_RX_LO is active, otherwise Si570_TX_LO is active.
uint8 TX_Frequency = 0;

uint16 TX_HangCounter = 0;

struct AmpSequencingConfig AmpSequencingNew;
struct AmpSequencingConfig AmpSequencingCurrent;

void AmpSequencingReset()
{
AmpSequencingNew.AMP_Enabled = 0;
AmpSequencingNew.TX_Delay = 0;
AmpSequencingNew.TX_Hang = 0;
AmpSequencingCurrent.TX_Delay = 1;
}

uint32 KeyerDelayAcc = 0;
uint32 KeyerDelayMask = 0;
uint32 KeyerDelayOut = 0;

#define KEYER_PTT (KeyerDelayAcc)
#define KEYER_DOWN ((KeyerDelayAcc & KeyerDelayOut) != 0)

void TX_Main(void) {
static uint8 blink;
uint8 i;
uint8 status = Status_Read();
KeyerDelayAcc = ((KeyerDelayAcc & KeyerDelayMask) << 1) | ((status & STATUS_KEYER) != 0);

switch (TX_Phase) {
case TX_PHASE_RECEIVING:
AmpSequencingCurrent.AMP_Enabled = AmpSequencingNew.AMP_Enabled;
if (AmpSequencingCurrent.TX_Delay != AmpSequencingNew.TX_Delay) {
AmpSequencingCurrent.TX_Delay = AmpSequencingNew.TX_Delay;
KeyerDelayAcc = 0;
KeyerDelayOut = ((uint32)1) << AmpSequencingCurrent.TX_Delay;
KeyerDelayMask = KeyerDelayOut - 1;
}
AmpSequencingCurrent.TX_Hang = AmpSequencingNew.TX_Hang;
// Remember the current state of tkey key down input.
if (Status_Read() & STATUS_KEYER)
if (status & STATUS_KEYER)
TX_State |= TX_KEY_REQUESTED;
else
TX_State &= ~TX_KEY_REQUESTED;
Expand All @@ -51,9 +84,11 @@ void TX_Main(void) {
TX_Phase = TX_PHASE_AMP_ENABLE;
break;
case TX_PHASE_AMP_ENABLE:
// Enable an externa amplifier.
Control_Write(Control_Read() & ~CONTROL_AMP);
TX_Phase = (TX_State & TX_PC_ACTIVE) ? TX_PHASE_TXPC : TX_PHASE_IQTONE_RAMP_UP;
// Enable an external amplifier.
if (AmpSequencingCurrent.AMP_Enabled)
Control_Write(Control_Read() & ~CONTROL_AMP);
TX_Phase = (TX_State & TX_PC_ACTIVE) ? TX_PHASE_TXPC :
(KEYER_DOWN) ? TX_PHASE_IQTONE_RAMP_UP : TX_PHASE_IQTONE_IDLE;
blink = 1;
break;
case TX_PHASE_TXPC:
Expand Down Expand Up @@ -82,7 +117,7 @@ void TX_Main(void) {
break;
case TX_PHASE_IQTONE_STEADY:
// Transmitting an internal shaped IQ tone, keyed by the external key down signal.
if ((Status_Read() & STATUS_KEYER) == 0) {
if (! KEYER_DOWN) {
// Key is released.
TX_State &= ~TX_KEY_REQUESTED;
TX_Phase = TX_PHASE_IQTONE_RAMP_DOWN;
Expand All @@ -94,22 +129,66 @@ void TX_Main(void) {
// Transition from TX_PHASE_IQTONE_RAMP_DOWN to TX_PHASE_IQTONE_END is controlled by the IQ tone generator.
break;
case TX_PHASE_IQTONE_END:
// Transmitting an internal shaped IQ tone, keyed by the external key down signal.
Control_Write((Control_Read() & ~(CONTROL_TX | CONTROL_LED)) | CONTROL_AMP);
TX_Phase = TX_PHASE_IQTONE_UNMUTE;
TX_IQ_Phase = 0;
case TX_PHASE_IQTONE_IDLE:
{
// Wait for the amplifier relay to switch to TX.
if (KEYER_DOWN) {
// The AMP relay sequencing and the signal has been delayed by the FPGA modules
// ImabicKeyer and KeyDelay to avoid hot switching of the AMP relay.
// Now it is safe to start the trasmitting.
TX_Phase = TX_PHASE_IQTONE_RAMP_UP;
} else if (! KEYER_PTT) {
if (AmpSequencingNew.TX_Hang == 0) {
Control_Write((Control_Read() & ~(CONTROL_TX | CONTROL_LED)) | CONTROL_AMP);
TX_Phase = TX_PHASE_IQTONE_UNMUTE;
} else {
TX_Phase = TX_PHASE_IQTONE_HANG;
TX_HangCounter = AmpSequencingNew.TX_Hang;
}
}
break;
}
case TX_PHASE_IQTONE_HANG:
// Wait for the keyamplifier relay to switch to TX.
if (KEYER_DOWN)
// The AMP relay sequencing and the signal has been delayed by the FPGA modules
// ImabicKeyer and KeyDelay to avoid hot switching of the AMP relay.
// Now it is safe to start the trasmitting.
TX_Phase = TX_PHASE_IQTONE_RAMP_UP;
else if (KEYER_PTT)
// Key was pressed, but the key may be delayed.
TX_Phase = (AmpSequencingCurrent.TX_Delay == 0) ? TX_PHASE_IQTONE_RAMP_UP : TX_PHASE_IQTONE_IDLE;
else if (-- TX_HangCounter == 0) {
// The FPGA module PttOffCounter indicates an end of TX.
Control_Write((Control_Read() & ~(CONTROL_TX | CONTROL_LED)) | CONTROL_AMP);
TX_Phase = TX_PHASE_IQTONE_UNMUTE;
TX_IQ_Phase = 0;
}
break;
case TX_PHASE_IQTONE_UNMUTE:
Control_Write(Control_Read() | CONTROL_RX);
TX_Phase = TX_PHASE_IQTONE_EXIT;
TX_IQ_Phase = 0;
// Switch back to receive LO frequency.
TX_Frequency = 0;
if (KEYER_PTT) {
TX_Phase = TX_PHASE_TX_ENABLE;
} else {
Control_Write(Control_Read() | CONTROL_RX);
TX_Phase = TX_PHASE_IQTONE_EXIT;
TX_IQ_Phase = 0;
// Switch back to receive LO frequency.
TX_Frequency = 0;
}
break;
case TX_PHASE_IQTONE_EXIT:
TX_Phase = TX_PHASE_RECEIVING;
TX_State &= ~TX_KEY_ACTIVE;
RX_MuteCounter = 10;
if (KEYER_PTT) {
TX_Phase = TX_PHASE_TX_ENABLE;
// Let the Si570 thread switch the LO to Si570_TX_LO.
TX_Frequency = Si570_TX_LO != 0;
// Mute the receiver.
Control_Write(Control_Read() & ~CONTROL_RX);
} else {
TX_Phase = TX_PHASE_RECEIVING;
TX_State &= ~TX_KEY_ACTIVE;
RX_MuteCounter = 10;
}
break;
}

Expand Down
5 changes: 5 additions & 0 deletions basic.cydsn/usbvend.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ uint8 USBFS_HandleVendorRqst(void)
USBFS_currentTD.count = 1;
requestHandled = USBFS_InitControlWrite();
break;
case 0x67: // CMD_SET_AMP_SEQUENCING
USBFS_currentTD.pData = (void *)&AmpSequencingNew;
USBFS_currentTD.count = 4;
requestHandled = USBFS_InitControlWrite();
break;
case 0x69: // CMD_SET_CW_IQ_WAVEFORM
// Receive 9ms of IQ int16 words,
// representing 4ms of raise, 1ms of steady and 4ms of fall.
Expand Down

0 comments on commit 56ee924

Please sign in to comment.