AN16833 Signal Mixing with PSoC Switched Capacitor Blocks.pdf

THIS SPEC IS OBSOLETE
Spec No: 001-16833
Spec Title: SIGNAL MIXING WITH PSOC(R) SWITCHED CAPACITOR
BLOCKS - AN16833
Sunset Owner: Kannan Sadasivam (QVS)
Replaced by: None
AN16833
Signal Mixing with PSoC® Switched Capacitor Blocks
Author: Sampath Selvaraj
Associated Project: Yes
Associated Part Family: CY8C27443 (Project), CY8C27x43, CY8C29x66
Software Version: PSoC ® Designer™ 4.4
Related Application Notes: AN2041, AN2223
If you have a question, or need help with this application note, contact the author at
[email protected].
Routing analog signals inside a PSoC® device can be tricky because the desired connections are often not directly
available. This application note describes some useful methods to allow configurations that seem impossible, such as
the developed example of an eight channel (four channel stereo) audio mixer with adjustment potentiometers.
Contents
Introduction
Introduction ....................................................................... 1
All Blocks are not created equal ................................... 2
A Switched Capacitor PGA ............................................... 2
Creating an Eight Channel Mixer .................................. 4
Reading Potentiometers without an ADC ..................... 4
Noise ................................................................................. 5
Possibilities and Improvements .................................... 5
Summary ......................................................................... 22
Worldwide Sales and Design Support ............................. 24
A PSoC analog user module’s input choices are
determined by its location. Certain locations have access
to Port 0 input multiplexers; others have direct access to
the Port 2 inputs. Some only have access to certain
adjacent blocks and their column’s analog output bus.
Placement of an analog user module requires the correct
type of target analog blocks: Continuous Time or Switched
Capacitor. Therefore, not all analog user modules have
access to a desired signal without another analog module
to route it. In some cases – such as routing a Port 0 signal
through a PGA to feed it to an ADC – this is a
straightforward process.
However, after all four possible PGAs are used and
additional simultaneous analog input signals are required,
it is confusing to route these signals in, especially to where
they are needed.
Some inputs that are typically read with an analog-todigital converter, such as adjustment potentiometers, can
be set up to be read by a timer user module. This frees up
valuable analog resources. Some tricks are shown to
convert a voltage into a charge time using a single digital
pin for discharge and input (one pin per potentiometer).
Here is a method to multiplex as many potentiometers as
desired sequentially with a single-timer user module.
By configuring generic switched capacitor user modules to
act as PGA buffers, an eight channel mixer with both
stereo and mono outputs can be completely implemented
within a single PSoC device with no external routing.
This mixer includes 15 adjustment potentiometers. There
are potentiometers to adjust levels of each of the eight
inputs and master adjustments for the left, right, and mono
channels. Four more potentiometer inputs control the preamp levels of the PGAs in line with some inputs. This
www.cypress.com
Document No. 001-16833 Rev. *C
1
®
Signal Mixing with PSoC Switched Capacitor Blocks
allows the large range adjustment needed for
microphones (or other small signal sources) on half of the
inputs (specifically, inputs C and D on each side). The
current design allows for a sixteenth adjustment
potentiometer, but it does not yet have a use.
Figure 1. Analog Block Arrangement
A serial TX user module is also included and is configured
to output a formatted single-line output of all 15 gains. It
outputs every couple sets of readings while adjustments
are made, at a rate of 57,600 bps. This status display may
be viewed with any standard serial terminal.
All Blocks are not created equal
Continuous Time (CT) analog blocks are easy to use:
simple analog modules such as PGAs and Comparators
go here. All four CT blocks have access to at least four
Port 0 input pins (the two center blocks have extra
multiplexers allowing connection to any of the eight Port 0
input pins), and the analog column clock has very little
effect (if any) on operation.
All four CT blocks are the same and have similar
designations; “ACBxy,” where x is the analog row (always
0) and y is the analog column number (0 to 3). These four
blocks are along the top row of the analog section, shown
in Figure 1.
Switched Capacitor (SC) analog blocks can give the PSoC
many capabilities. These blocks can perform such a
variety of real time functions that they were given a
completely customizable user module, instead of separate
modules for each function. This “Generic SCBlock” user
module is found as the only entry under the “Generic”
category.
SC blocks come in two varieties – Type C and Type D.
Originally, in the CY8C25xxx/26xxx PSoC families, these
were Type A and Type B. This is detailed in AN2041,
“Understanding Analog Switched Capacitor Blocks.” Most,
if not all of it, still applies to the newer CY8C27x43 and
CY8C29x66 devices.
The old Type A blocks have evolved into the new Type C
blocks and the old Type B blocks have evolved into the
new type D blocks.
A Switched Capacitor PGA
A Generic SC user module is configured to act as a PGA
and amplify audio signals. The SC PGA does not have as
large a range of gains as the standard CT PGA, but it is
perfect for low and unity gain applications. The standard
CT PGA user module provides gains from 0.062x to 48x,
whereas the SC PGA created here has a range of 0.062x
to only 1.938x (with an FCap value of 16; this range gets
smaller and finer when FCap is set to 32). See Table 1
and Table 2 for details.
However, an SC PGA has the unique capability to mix two
inputs and control their gains independently. An SC PGA
can also invert its non-inverting input. The ratio between
FCap and either ACap or BCap controls the gain applied
to either the A or B inputs.
Empirically, an analog column clock of 4 MHz is optimum
for an audio SC PGA. Faster clocks result in distortion, as
the SC blocks do not perform quite as well near their
upper limits.
The parameters necessary to create an SC PGA intended
for use with AC signals (or audio) from a Generic SC user
module are shown for the two types of SC blocks in Figure
2 and Figure 3.
Figure 2. SC Type C as a 2 Channel Audio PGA, 1.00x
Gain
Type C SC blocks are designated “ASCxy,” where x is the
analog row (1 or 2) and y is the analog column (0 to 3).
Type D SC blocks are designated “ASDxy,” where x is the
analog row (1 or 2) and y is the analog column (0 to 3).
Type D blocks include an additional option to allow BCap
to function as a regular capacitor instead of a switched
capacitor – set this BSW to “On” for normal operation.
Type C and D SC blocks are arranged in a checkerboard
pattern, beginning with ASC10 as shown in Figure 1.
www.cypress.com
Document No. 001-16833 Rev. *C
2
®
Signal Mixing with PSoC Switched Capacitor Blocks
Figure 3. SC Type D as a 2 Channel Audio PGA, 1.00x
Gain
www.cypress.com
Table 1. SC PGA Gain Settings, FCap = 16
ACap or BCap
Gain
0
0
1
0.0625
2
0.125
3
0.1875
4
0.25
5
0.3125
6
0.375
7
0.4375
8
0.5
9
0.5625
10
0.625
11
0.6875
12
0.75
13
0.8125
14
0.875
15
0.9375
16
1
17
1.0625
18
1.125
19
1.1875
20
1.25
21
1.3125
22
1.375
23
1.4375
24
1.5
25
1.5625
26
1.625
27
1.6875
28
1.75
29
1.8125
30
1.875
31
1.9375
Document No. 001-16833 Rev. *C
3
®
Signal Mixing with PSoC Switched Capacitor Blocks
Table 2. SC PGA Gain Settings, FCap = 32
Port 2) are mixed into three outputs — Left, Right, and
Mono. The basic mixer schematic and internal routing is
shown in Figure 5.
ACap or BCap
Gain
0
0
1
0.03125
2
0.06250
3
0.09375
4
0.12500
5
0.15625
6
0.18750
7
0.21875
8
0.25000
9
0.28125
10
0.31250
11
0.34375
If you can preset all your gain settings, then you are done.
However, most applications require some real time control
over these gains.
12
0.37500
Reading Potentiometers without an ADC
13
0.40625
14
0.43750
15
0.46875
Potentiometers are arranged into four banks of four inputs,
requiring eight PSoC pins and one timer. Fifteen of the 16
possible potentiometer inputs from this configuration are
used in the mixer design, as shown in Figure 6.
16
0.50000
17
0.53125
18
0.56250
19
0.59375
20
0.62500
21
0.65625
22
0.68750
23
0.71875
24
0.75000
25
0.78125
26
0.81250
27
0.84375
28
0.87500
29
0.90625
30
0.93750
31
0.96875
The Left output consists of a mix of input channels La, Lb,
Lc, and Ld. The Right output consists of a mix of input
channels Ra, Rb, Rc, and Rd. Mono output is a mix of all
eight inputs.
Lc, Ld, Rc, and Rd are routed through CT PGAs before
entering the mix and can have a pre-amp gain applied to
them. This makes these channels ideal for use as
microphone inputs.
The mixer portion of this project operates without logic.
The only code required is to initialize the CT PGA
modules; the SC PGA modules do not need start
commands when their power level is set in the Device
Editor to Low, Medium, or High.
The four inputs to the PSoC are on P1[0], P1[1], P1[2],
and P1[3]. The four bank control outputs are on P1[4],
P1[5], P1[6], and P2[6].
The logic to read all 15 potentiometers sequentially is
shown in the flowchart in Figure 7.
First, the potentiometer controlling the gain of La is
serviced. P1[4] is raised to activate the first bank of inputs
and the timer is set to capture the signal on P1[0]. Then,
all four input pins are disconnected from their global input
buses and changed to drive Open Drain Low outputs.
These outputs are driven low for a brief period to
discharge the capacitors. They are then released, set back
to High Z digital input drives, and reconnected to their
global input busses. Then the timer is started.
A High Z digital input, whether connected to the global
input bus or not, acts as an analog comparator referenced
to ground with a threshold of approximately 0.500, or ½ of
VCC. This allows a timer to measure a potentiometer’s
position based on how long it takes its capacitor to charge
up to this threshold level.
Creating an Eight Channel Mixer
Using CT and SC PGA user modules, all eight
simultaneously routable analog input signals (four CT
inputs from Port 0 and four end-column SC inputs from
www.cypress.com
Now that the capacitor is discharged and the timer is
started immediately afterwards (when the timer obtains a
Capture event), its count is a direct ADC-style reading of
the potentiometer. This is accessed after the interrupt
through the timer’s Compare register.
However, in some cases, the input threshold is reached
before the command to start the timer is supplied. This is
Document No. 001-16833 Rev. *C
4
®
Signal Mixing with PSoC Switched Capacitor Blocks
not good, as timer user modules do not operate very well
with a steady high capture signal. This situation incorrectly
results in a minimum reading (zero). Special “Fast Charge”
logic is implemented to catch this situation and handle it
separately.
The timer is set up to produce a value from 0 to 127 for
seven bits of resolution. These seven bits are shifted down
to five bits, directly translating into ACap or BCap values
for SC PGA gains.
In the case of the CT PGA gain adjustments, these five
bits allow access to 32 of the available 33 gains. Because
the top gain is so much more significant than the bottom
gain, adding one to the CT PGA gain sets the top at 48x
(and sets the bottom at 0.12x, excluding 0.06x).
This is done for simplicity and speed, as access to the
bottom CT PGA gain is seldom required in this particular
application. A separate algorithm (shifting the timer
reading down to six bits to interpret the CT PGA gain)
could be written if access to all 33 gains is required.
After the potentiometer for La is read (and the gain for La
adjusted if there is a change), all bank select outputs are
released. A short delay then creates a brief dead band.
This process is then repeated for the other seven input
controls, three master controls, and four CT PGA pre-amp
controls – each time activating the proper bank and
reading the appropriate input to access the desired
potentiometer.
Every three sets of readings, the applied gains of each of
the 15 adjustments are sent out the serial TX port for
display on a standard terminal. This allows the user to see
exactly what gains are applied, and where. Example
output is shown in Figure 4.
Configuration of the PSoC eight channel mixer is shown in
Figure 8, Figure 9, Figure 10, and Figure 11 on page 14,
15, 16, and 19 respectively.
Figure 4. Example Serial Mixer Gain Display Output
Noise
The PSoC does not create isolated environments for all its
modules and blocks. It also does not completely isolate
the analog section from the digital section. As a result,
many digital functions inject a small amount of audible
noise into analog audio streams.
When the TX user module was initially set up to output on
P2[7], starting the module (no transmissions) added
audible noise into the otherwise quiet inputs on
P2[0]–P2[3]. For this reason, the TX uses P1[7] as its
output.
The scanning of the potentiometers also injects some
unpleasant audible noise into the mix. This noise is much
louder when any of the input signals are floating. If all
eight inputs are connected, this noise is less noticeable.
The enable button or switch on P2[7] is implemented for
this reason. The scanning of the potentiometers is only
performed when P2[7] is high; it ceases when P2[7] is low.
A button might be labeled “Hold to adjust or Push to
update.” A switch might be labeled “Down to lock out
changes and Up to adjust.”
There is another situation caused by leakage in this
application. The bank select outputs were originally driven
as Open Drain High, which should theoretically mix
without diodes in the potentiometer scanning circuitry. The
www.cypress.com
bank selects were driven high to select a particular bank,
and released to float otherwise. Unfortunately, when
floating, the bank outputs sharing Port 1 with the inputs
were affected by the various charging capacitors. This
resulted in multiple gains being adjusted unintentionally.
For this reason, the bank selects are now strong outputs.
They are driven high to select a bank, and low otherwise.
To ensure that low drives do not affect the potentiometer
readings, blocking diodes (D1, D2, D3, and D4) are now
required on these lines.
Notes

A simple resistor divider provides the VCC/2 AGND,
used to bias the AC-coupled inputs.

The two 100 μF bypass caps (C14, C15) are arranged
in series with the supply to facilitate a quick initial
charge-up.

The ACap and BCap settings in the Device Editor
have no effect because they are set in the software.
Possibilities and Improvements
The current design requires two programming jumpers to
be removed to burn the PSoC in-circuit. This is because
P1[0] and P1[1], which are the pins used for programming,
have capacitance attached to them. If these capacitors are
not removed when attempting in-circuit programming, it
Document No. 001-16833 Rev. *C
5
®
Signal Mixing with PSoC Switched Capacitor Blocks
fails. By exchanging these inputs with bank control signals
and making the necessary changes to the software, incircuit programming no longer requires jumpers.
Even with all the analog functionality present in this eight
channel mixer, there is still a single SC block left open.
Another analog feature can also be added to this project.
A serial RX user module could be added to allow remote
control of the gains. This may be useful in studio situations
where multiple users in multiple locations might want to
adjust the gains of a single mixer.
As shown in AN2412, “Reverb and Echo with a PSoCStyle FIFO,” a DelSig ADC user module may be used to
sample a stream of audio. The single-order DelSig only
requires a single SC block (and a digital block), and has its
choice of input signals.
A slightly altered version of the eight channel mixer can
act as a studio headphone amp, where the artist can
select his or her own personal mix of seven line feeds
along with an intercom channel back to the control room.
PGA_Rd is configured as an intercom with its own output
(P0[2]) and can easily be disconnected from SC_Rcd, if
necessary.
With the PSoC adding a bit of reverb and a PRS8 user
module representing this altered stream, there may be use
for the 16th potentiometer input – adjusting the amount of
reverb or echo. This creates another studio application. A
singer can control his or her own “scratch mix wetness,”
as personal unrecorded reverb adjustments are referred to
in the musicians’ world.
Figure 5. Audio Mixer Schematic
www.cypress.com
Document No. 001-16833 Rev. *C
6
®
Signal Mixing with PSoC Switched Capacitor Blocks
Figure 6. Potentiometer/Knob Interface Schematic
www.cypress.com
Document No. 001-16833 Rev. *C
7
®
Signal Mixing with PSoC Switched Capacitor Blocks
Figure 7. Eight Channel Mixer Flowchart
Note: Preparation
to read a
potentiometer in
this case means:
1) Driving all bank
selects low
2) Waiting a short
delay to create a
deadband
3) Driving the
appropriate bank
select high
4) Connecting the
timer module's
capture input to the
appropriate global
input bus
Start
Initialize variables,
modules, interrupt.
Output serial titles.
Is enable
button
pressed?
Yes
Timer interrupt
Stop self (timer
module).
Set flag indicating
current
potentiomter has
been measured.
Return
Prepare to read
potentiometer "La"
Prepare to read
potentiometer "Ra"
Prepare to read
potentiometer "L"
Prepare to read
pot "MLc"
Time
Pot
Time
Pot
Time
Pot
Time
Pot
Prepare to read
potentiometer "Lb"
Prepare to read
potentiometer "Rb"
Prepare to read
potentiometer "R"
Prepare to read
pot "MLd"
Time
Pot
Time
Pot
Time
Pot
Time
Pot
Prepare to read
potentiometer "Lc"
Prepare to read
potentiometer "Rc"
Prepare to read
potentiometer "LR"
Prepare to read
pot "MRc"
Time
Pot
Time
Pot
Time
Pot
Time
Pot
Prepare to read
potentiometer "Ld"
Prepare to read
potentiometer "Rd"
Time
Pot
Have 3 sets
of readings been
taken?
Time
Pot
Set all 4 input lines
to Open Drain Low
and discharge the
capacitors.
Reconnect all 4
input lines to their
Global Input
busses; set all to
High Z input drive
www.cypress.com
Has
pot charge
exceeded threshold
already?
Yes
Set incoming gain
to maximum value
Yes
Time
Pot
Transmit serial,
reset # readings
Increase #
readings
Time
Pot
Prepare to read
pot "MRd"
No
No
Start timer module.
Wait for timer
interrupt.
Is
current gain =
incoming
gain?
Read timer
module's Compare
register, shift out
the lower two bits,
and write to the
incoming gain
Document No. 001-16833 Rev. *C
No
Update current
gain with incoming
gain; set flag
indicating a gain
change was made
Yes
Return
8
®
Signal Mixing with PSoC Switched Capacitor Blocks
Code 1. Eight Channel Mixer Source Code
//----------main.c:
//---------------------------------------------------------------------------#define CyclesToDischargeKnob 50
//0-4million: number of cycles to wait whilst
discharging each knob
#define CyclesOfDeadbandBetweenReadings 100
//0-4million: number of cycles to wait in
between readings to enable settling
#define SerialOutputEnabled 1
//Comment out this line to disable the serial output
function
#define ReadingSetsBetweenSerialBursts 3
//0-255
//---------------------------------------------------------------------------#include <m8c.h>
// part specific constants and macros
#include "PSoCAPI.h"
// PSoC API definitions for all User Modules
#include <stdlib.h>
//--------------------------------------------------------------------#define Bit(bitNumber) ( 1 << (bitNumber) )
unsigned long int Counter = 0;
void Wait(unsigned long int);
void Wait(unsigned long int ToWait){ for (Counter = 0; Counter < ToWait; Counter++);
}
//------------------------------------------------------------#define OutputSerialTitles TX_CPutString(
" La | Lb | Lc | Ld | Ra | Rb | Rc | Rd | L |
R | LR | MLc | MLd | MRc | MRd ")
//
"1.00|1.00|1.00|1.00|1.00|1.00|1.00|1.00|1.00|1.00|1.00|48.00|48.00|48.00|48.00"
#define OutputSerialSeparator TX_PutChar('|')
//----------------------------------------------------------------------------------------char ZTS[9];
//void CharToZTS(unsigned char);
//void CharToZTS(unsigned char ToConvert)
//{
// if (ToConvert >= 100) itoa(&ZTS[0], ToConvert, 10);
// else if (ToConvert >= 10){ZTS[0]='0'; itoa(&ZTS[1], ToConvert, 10);}
// else{ZTS[0]='0'; ZTS[1]='0'; itoa(&ZTS[2], ToConvert, 10);}
// ZTS[3] = 0;
//for ZTS
//}
unsigned char Index=0;
unsigned char Target=0;
void IntToFloatZTS(unsigned int, unsigned char);
void IntToFloatZTS(unsigned int ToConvert, unsigned char NumDecimalPlaces)
{
if (ToConvert >= 10000) itoa(&ZTS[0], ToConvert, 10);
else if (ToConvert >= 1000){ZTS[0]='0';
itoa(&ZTS[1], ToConvert, 10);}
else if (ToConvert >= 100){ZTS[0]='0'; ZTS[1]='0'; itoa(&ZTS[2], ToConvert, 10);}
else if (ToConvert >= 10){ZTS[0]='0'; ZTS[1]='0'; ZTS[2]='0'; itoa(&ZTS[3], ToConvert,
10);}
else{ZTS[0]='0'; ZTS[1]='0'; ZTS[2]='0'; ZTS[3]='0'; itoa(&ZTS[4], ToConvert, 10);}
ZTS[5] = 0;
//for ZTS
if (NumDecimalPlaces)
{
Target=5-NumDecimalPlaces;
//init target to where decimal point should be
Index=6;
while (Index>Target)
{
ZTS[Index]=ZTS[Index-1];
Index--;
}
www.cypress.com
//shift char right
Document No. 001-16833 Rev. *C
9
®
Signal Mixing with PSoC Switched Capacitor Blocks
ZTS[Index]='.';
//insert decimal point
}
}
void TransmitSerial(void);
//----------------------------------------------------------------------------------------//-----CT PGA
#define NumGains 33
const BYTE CtPgaGains[NumGains]={PGA_Lc_G0_06,PGA_Lc_G0_12,PGA_Lc_G0_18,PGA_Lc_G0_25, //0-3
PGA_Lc_G0_31,PGA_Lc_G0_37,PGA_Lc_G0_43,PGA_Lc_G0_50,PGA_Lc_G0_56,PGA_Lc_G0_62,
//4-9
PGA_Lc_G0_68,PGA_Lc_G0_75,PGA_Lc_G0_81,PGA_Lc_G0_87,PGA_Lc_G0_93,PGA_Lc_G1_00,
//10-15
PGA_Lc_G1_06,PGA_Lc_G1_14,PGA_Lc_G1_23,PGA_Lc_G1_33,PGA_Lc_G1_46,PGA_Lc_G1_60,
//16-21
PGA_Lc_G1_78,PGA_Lc_G2_00,PGA_Lc_G2_27,PGA_Lc_G2_67,PGA_Lc_G3_20,PGA_Lc_G4_00,
//22-27
PGA_Lc_G5_33,PGA_Lc_G8_00,PGA_Lc_G16_0,PGA_Lc_G24_0,PGA_Lc_G48_0};
//28-32
const
unsigned
int
CtPgaGainValues[NumGains]={6,12,18,25,31,37,43,50,56,62,68,75,81,87,93,100,106,114,123,
\
133,146,160,178,200,227,267,320,400,533,800,1600,2400,4800};
//index 15 = 1.00x
#define CtPgaGainOffset 1 //shift incoming gain value this far up (add this) to ensure
access
//to 24x and 48x gains (skips 0.06x and 0.12x though)
#define DefaultCtPgaGain 15
//-----SC PGA
#define NumScPgaGains 32
//The below constant contains the SC PGA gain values in fixed-point decimal (to avoid float
values) - //move decimal point two digits left for real value and display
//Below constant only needed for displaying gain values on an LCD (for example)
//For reference, the below values represent gains 0.00x - 1.94x, varying ACap and BCap
equally while //holding FCap constant at 16
const
unsigned
int
ScPgaGainValuesFCap16[NumScPgaGains]={0,6,13,19,25,31,38,44,50,56,62,69,75,81,88,94,100,106,1
13,119,125,131,138,144,150,156,162,169,175,181,188,194};
#define DefaultScPgaGain 0
#define MaxScPgaGain NumScPgaGains-1
#define MinScPgaGain 0
/*
CR0 [43210] = ACap
i.e. SC_Lab_cr0
CR1 [43210] = BCap
i.e. SC_Lab_cr1
*/
unsigned char TempCr;
unsigned char TempCr1;
#define ResetAorBCap 0b11100000
unsigned char IncomingGain;
//Bank0
unsigned char GainLab_A=DefaultScPgaGain;
unsigned char GainLab_B=DefaultScPgaGain;
unsigned char GainLcd_C=DefaultScPgaGain;
unsigned char GainLcd_D=DefaultScPgaGain;
#define UpdateLab_AGain TempCr=(SC_Lab_cr0
#define UpdateLab_BGain TempCr=(SC_Lab_cr1
#define UpdateLcd_CGain TempCr=(SC_Lcd_cr0
#define UpdateLcd_DGain TempCr=(SC_Lcd_cr1
//Bank1
unsigned char GainRab_A=DefaultScPgaGain;
unsigned char GainRab_B=DefaultScPgaGain;
www.cypress.com
&
&
&
&
ResetAorBCap)
ResetAorBCap)
ResetAorBCap)
ResetAorBCap)
Document No. 001-16833 Rev. *C
|
|
|
|
GainLab_A;
GainLab_B;
GainLcd_C;
GainLcd_D;
SC_Lab_cr0=TempCr
SC_Lab_cr1=TempCr
SC_Lcd_cr0=TempCr
SC_Lcd_cr1=TempCr
10
®
Signal Mixing with PSoC Switched Capacitor Blocks
unsigned char GainRcd_C=DefaultScPgaGain;
unsigned char GainRcd_D=DefaultScPgaGain;
#define UpdateRab_AGain TempCr=(SC_Rab_cr0 & ResetAorBCap) | GainRab_A; SC_Rab_cr0=TempCr
#define UpdateRab_BGain TempCr=(SC_Rab_cr1 & ResetAorBCap) | GainRab_B; SC_Rab_cr1=TempCr
#define UpdateRcd_CGain TempCr=(SC_Rcd_cr0 & ResetAorBCap) | GainRcd_C; SC_Rcd_cr0=TempCr
#define UpdateRcd_DGain TempCr=(SC_Rcd_cr1 & ResetAorBCap) | GainRcd_D; SC_Rcd_cr1=TempCr
//Bank2
unsigned char GainL=DefaultScPgaGain;
unsigned char GainR=DefaultScPgaGain;
unsigned char GainLR=DefaultScPgaGain;
#define UpdateLGain TempCr=(SC_Labcd_cr0 & ResetAorBCap) | GainL; TempCr1=(SC_Labcd_cr1 &
ResetAorBCap) | GainL; SC_Labcd_cr0=TempCr; SC_Labcd_cr1=TempCr1
#define UpdateRGain TempCr=(SC_Rabcd_cr0 & ResetAorBCap) | GainR; TempCr1=(SC_Rabcd_cr1 &
ResetAorBCap) | GainR; SC_Rabcd_cr0=TempCr; SC_Rabcd_cr1=TempCr1
#define UpdateLRGain TempCr=(SC_LR_cr0 & ResetAorBCap) | GainLR; TempCr1=(SC_LR_cr1 &
ResetAorBCap) | GainLR; SC_LR_cr0=TempCr; SC_LR_cr1=TempCr1
//Mic gains are CT PGA gains, Bank3
unsigned char GainMicLc=DefaultCtPgaGain;
unsigned char GainMicLd=DefaultCtPgaGain;
unsigned char GainMicRc=DefaultCtPgaGain;
unsigned char GainMicRd=DefaultCtPgaGain;
#define UpdateMicLcGain PGA_Lc_SetGain(CtPgaGains[GainMicLc+CtPgaGainOffset])
#define UpdateMicLdGain PGA_Ld_SetGain(CtPgaGains[GainMicLd+CtPgaGainOffset])
#define UpdateMicRcGain PGA_Rc_SetGain(CtPgaGains[GainMicRc+CtPgaGainOffset])
#define UpdateMicRdGain PGA_Rd_SetGain(CtPgaGains[GainMicRd+CtPgaGainOffset])
unsigned char KnobReading=0;
//-----------------------------------------------------------------------------------------#define
ScaleReadingOfKnob
KnobReading>>=2;
if(KnobReading>MaxScPgaGain){
KnobReading=MaxScPgaGain; }
#define KNOB_FASTCHARGE 3
#define KNOB_SERVICED 2
#define KNOB_TIMED 1
#define KNOB_TIMING 0
unsigned char KnobStatus=0;
//Target charge rate of ~188Hz -- ok, adjusted to 178Hz to match 7 bits of resolution to
shift directly down to 5 for ACap/BCap control
#define IsKnobTimed (KnobStatus==KNOB_TIMED)
#define IsKnobServiced (KnobStatus==KNOB_SERVICED)
#define IsKnobFastCharge (KnobStatus==KNOB_FASTCHARGE)
#define SetKnobAsServiced KnobStatus=KNOB_SERVICED
#define SetKnobAsTimed KnobStatus=KNOB_TIMED
#define SetKnobAsFastCharge KnobStatus=KNOB_FASTCHARGE
#define ResetKnobStatus KnobStatus=KNOB_TIMING
#define ResetKnobTmr TMR_Knob_WritePeriod(TMR_Knob_PERIOD); TMR_Knob_WriteCompareValue(0)
#define ReadKnobTmr KnobReading=TMR_Knob_COMPARE_REG; \
ScaleReadingOfKnob; IncomingGain=KnobReading
#define ServiceKnob if(IsKnobTimed) \
{ \
ReadKnobTmr; \
ResetKnobTmr; \
SetKnobAsServiced; \
} \
else if(IsKnobFastCharge) \
{ \
IncomingGain=MaxScPgaGain; \
ResetKnobTmr; \
SetKnobAsServiced; \
}
#define CheckChargeStatusRowIn0 (Bit(0))
www.cypress.com
Document No. 001-16833 Rev. *C
11
®
Signal Mixing with PSoC Switched Capacitor Blocks
#define CheckChargeStatusRowIn1 (Bit(1))
#define CheckChargeStatusRowIn2 (Bit(2))
#define CheckChargeStatusRowIn3 (Bit(3))
unsigned char CurrentInputMask=CheckChargeStatusRowIn1;
#define CheckCurrentChargeStatus (PRT1DR&CurrentInputMask)
#define
AllInputsMask
(CheckChargeStatusRowIn0
|
CheckChargeStatusRowIn1
|
CheckChargeStatusRowIn2 | CheckChargeStatusRowIn3)
#define
AllInputsToOpenDrainLow
PRT1DM2|=AllInputsMask;
PRT1DM1|=AllInputsMask;
PRT1DM0|=AllInputsMask
#define
AllInputsToHiZ
PRT1DM2&=~AllInputsMask;
PRT1DM1|=AllInputsMask;
PRT1DM0&=~AllInputsMask
#define AllInputsToStdCpu PRT1GS&=~AllInputsMask
#define AllInputsToGlobalIO PRT1GS|=AllInputsMask
#define DischargeKnobInput PRT1DR&=~AllInputsMask
#define ReleaseKnobInput PRT1DR|=AllInputsMask
#define DrainAndStartKnob AllInputsToStdCpu; AllInputsToOpenDrainLow; DischargeKnobInput;
Wait(CyclesToDischargeKnob); \
ResetKnobStatus; ReleaseKnobInput; AllInputsToHiZ; \
if(CheckCurrentChargeStatus) { SetKnobAsFastCharge; } \
else { TMR_Knob_Start(); ResetKnobStatus; } \
AllInputsToGlobalIO
#define CheckKnobEnableButton (PRT2DR&Bit(7))
//------------------------------------------------------------------------------//P1_4, P1_5, P1_6 = KnobBank0, 1, 2
//P2_6=KnobBank3
#define
AllBanksOff
PRT1DR&=~(Bit(4)
|
Bit(5)
|
Bit(6));
PRT2DR&=~(Bit(6));
Wait(CyclesOfDeadbandBetweenReadings)
#define KnobToBank0 AllBanksOff; PRT1DR|=Bit(4)
#define KnobToBank1 AllBanksOff; PRT1DR|=Bit(5)
#define KnobToBank2 AllBanksOff; PRT1DR|=Bit(6)
#define KnobToBank3 AllBanksOff; PRT2DR|=Bit(6)
#define
#define
#define
#define
KnobInputToRow0In
KnobInputToRow1In
KnobInputToRow2In
KnobInputToRow3In
TMR_Knob_INPUT_REG=0xc1;
TMR_Knob_INPUT_REG=0xd1;
TMR_Knob_INPUT_REG=0xe1;
TMR_Knob_INPUT_REG=0xf1;
CurrentInputMask=CheckChargeStatusRowIn0
CurrentInputMask=CheckChargeStatusRowIn1
CurrentInputMask=CheckChargeStatusRowIn2
CurrentInputMask=CheckChargeStatusRowIn3
//Left A,B,C,D input adjustments on Bank0
#define PrepareToReadKnobLab_A KnobToBank0;
#define PrepareToReadKnobLab_B KnobToBank0;
#define PrepareToReadKnobLcd_C KnobToBank0;
#define PrepareToReadKnobLcd_D KnobToBank0;
KnobInputToRow0In
KnobInputToRow1In
KnobInputToRow2In
KnobInputToRow3In
//Right
#define
#define
#define
#define
KnobInputToRow0In
KnobInputToRow1In
KnobInputToRow2In
KnobInputToRow3In
A,B,C,D input adjustments on Bank1
PrepareToReadKnobRab_A KnobToBank1;
PrepareToReadKnobRab_B KnobToBank1;
PrepareToReadKnobRcd_C KnobToBank1;
PrepareToReadKnobRcd_D KnobToBank1;
//Master L, R, LR input adjustments on Bank2
#define PrepareToReadKnobL KnobToBank2; KnobInputToRow0In
#define PrepareToReadKnobR KnobToBank2; KnobInputToRow1In
#define PrepareToReadKnobLR KnobToBank2; KnobInputToRow2In
//Mic Preamp input adjustments
#define PrepareToReadKnobMicLc
#define PrepareToReadKnobMicLd
#define PrepareToReadKnobMicRc
#define PrepareToReadKnobMicRd
www.cypress.com
on Bank3
KnobToBank3;
KnobToBank3;
KnobToBank3;
KnobToBank3;
KnobInputToRow0In
KnobInputToRow1In
KnobInputToRow2In
KnobInputToRow3In
Document No. 001-16833 Rev. *C
12
®
Signal Mixing with PSoC Switched Capacitor Blocks
BOOL GainChangeThisCycle=0;
#define
CycleThroughAndReadTheInputs
PrepareToReadKnobLab_A;
DrainAndStartKnob;
while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainLab_A){
GainLab_A=IncomingGain;
UpdateLab_AGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobLab_B; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainLab_B){
GainLab_B=IncomingGain;
UpdateLab_BGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobLcd_C; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainLcd_C){
GainLcd_C=IncomingGain;
UpdateLcd_CGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobLcd_D; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainLcd_D){
GainLcd_D=IncomingGain;
UpdateLcd_DGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobRab_A; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainRab_A){
GainRab_A=IncomingGain;
UpdateRab_AGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobRab_B; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainRab_B){
GainRab_B=IncomingGain;
UpdateRab_BGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobRcd_C; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainRcd_C){
GainRcd_C=IncomingGain;
UpdateRcd_CGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobRcd_D; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainRcd_D){
GainRcd_D=IncomingGain;
UpdateRcd_DGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobL; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainL){ GainL=IncomingGain; UpdateLGain; GainChangeThisCycle=1; } \
PrepareToReadKnobR; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainR){ GainR=IncomingGain; UpdateRGain; GainChangeThisCycle=1; } \
PrepareToReadKnobLR; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainLR){ GainLR=IncomingGain; UpdateLRGain; GainChangeThisCycle=1; } \
PrepareToReadKnobMicLc; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainMicLc){
GainMicLc=IncomingGain;
UpdateMicLcGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobMicLd; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainMicLd){
GainMicLd=IncomingGain;
UpdateMicLdGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobMicRc; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainMicRc){
GainMicRc=IncomingGain;
UpdateMicRcGain;
GainChangeThisCycle=1; } \
PrepareToReadKnobMicRd; DrainAndStartKnob; while(!IsKnobServiced){ ServiceKnob; } \
if(IncomingGain!=GainMicRd){
GainMicRd=IncomingGain;
UpdateMicRdGain;
GainChangeThisCycle=1; } \
AllBanksOff
//-unsigned char SerialOutputCounter=0;
//-----------------------------------------------------------------------------------------void main()
{
UpdateLab_AGain;
UpdateLab_BGain;
UpdateLcd_CGain;
UpdateLcd_DGain;
UpdateRab_AGain;
UpdateRab_BGain;
UpdateRcd_CGain;
www.cypress.com
Document No. 001-16833 Rev. *C
13
®
Signal Mixing with PSoC Switched Capacitor Blocks
UpdateRcd_DGain;
UpdateLGain;
UpdateRGain;
UpdateLRGain;
UpdateMicLcGain;
UpdateMicLdGain;
UpdateMicRcGain;
UpdateMicRdGain;
PGA_Lc_Start(PGA_Lc_HIGHPOWER);
PGA_Ld_Start(PGA_Ld_HIGHPOWER);
PGA_Rc_Start(PGA_Rc_HIGHPOWER);
PGA_Rd_Start(PGA_Rd_HIGHPOWER);
Clk_Tx_Start();
TX_Start(TX_PARITY_NONE);
TMR_Knob_EnableInt();
M8C_EnableGInt;
TX_PutCRLF();
TX_PutCRLF();
OutputSerialTitles;
TX_PutCRLF();
while(1)
{
if(CheckKnobEnableButton)
{
CycleThroughAndReadTheInputs;
if(++SerialOutputCounter>ReadingSetsBetweenSerialBursts)
{
if(GainChangeThisCycle){ TransmitSerial(); GainChangeThisCycle=0; }
SerialOutputCounter=0;
}
}
}
}
void TransmitSerial(void)
{
#ifdef SerialOutputEnabled
IntToFloatZTS(ScPgaGainValuesFCap16[GainLab_A],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainLab_B],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainLcd_C],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainLcd_D],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainRab_A],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainRab_B],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainRcd_C],2);
TX_PutString(&ZTS[2]);
www.cypress.com
Document No. 001-16833 Rev. *C
14
®
Signal Mixing with PSoC Switched Capacitor Blocks
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainRcd_D],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainL],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainR],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(ScPgaGainValuesFCap16[GainLR],2);
TX_PutString(&ZTS[2]);
OutputSerialSeparator;
IntToFloatZTS(CtPgaGainValues[GainMicLc+CtPgaGainOffset],2);
TX_PutString(&ZTS[1]);
OutputSerialSeparator;
IntToFloatZTS(CtPgaGainValues[GainMicLd+CtPgaGainOffset],2);
TX_PutString(&ZTS[1]);
OutputSerialSeparator;
IntToFloatZTS(CtPgaGainValues[GainMicRc+CtPgaGainOffset],2);
TX_PutString(&ZTS[1]);
OutputSerialSeparator;
IntToFloatZTS(CtPgaGainValues[GainMicRd+CtPgaGainOffset],2);
TX_PutString(&ZTS[1]);
TX_PutChar(13);
#endif
}
//----------TMR_KnobINT.asm:
_TMR_Knob_ISR:
;@PSoC_UserCode_BODY@ (Do not change this line.)
;--------------------------------------------------; Insert your custom code below this banner
;--------------------------------------------------;
NOTE: interrupt service routines must preserve
;
the values of the A and X CPU registers.
push A
TMR_Knob_Stop_M
mov [_KnobStatus], 1
pop A
www.cypress.com
Document No. 001-16833 Rev. *C
15
®
Signal Mixing with PSoC Switched Capacitor Blocks
Figure 8. Eight Channel Mixer PSoC Pinout Configuration
www.cypress.com
Document No. 001-16833 Rev. *C
16
®
Signal Mixing with PSoC Switched Capacitor Blocks
Figure 9. Eight Channel Mixer PSoC User Module Placement GUI
www.cypress.com
Document No. 001-16833 Rev. *C
17
®
Signal Mixing with PSoC Switched Capacitor Blocks
Figure 10. Eight Channel Mixer User Module Parameter Configuration
www.cypress.com
Document No. 001-16833 Rev. *C
18
®
Signal Mixing with PSoC Switched Capacitor Blocks
www.cypress.com
Document No. 001-16833 Rev. *C
19
®
Signal Mixing with PSoC Switched Capacitor Blocks
www.cypress.com
Document No. 001-16833 Rev. *C
20
®
Signal Mixing with PSoC Switched Capacitor Blocks
www.cypress.com
Document No. 001-16833 Rev. *C
21
®
Signal Mixing with PSoC Switched Capacitor Blocks
Figure 11. Eight Channel Mixer Global Resource Configuration
Summary
PSoC 1 has routing schemes that seems to have
limitations. But we have seen here, how the switched
capacitor blocks and the continuous time blocks can be
made to simulate the other and thereby achieve the
routing we require.
www.cypress.com
About the Author
Name:
Sampath Selvaraj
Title:
Applications Engr Sr Staff
Contact:
[email protected]
Document No. 001-16833 Rev. *C
22
®
Signal Mixing with PSoC Switched Capacitor Blocks
Document History
Document Title: Signal Mixing with PSoC® Switched Capacitor Blocks - AN16833
Document Number: 001-16833
Revision
ECN
Orig. of
Change
Submission
Date
Description of Change
**
2540267
Chris
Paiano
07/23/08
New Application Note
*A
2754641
JVY
08/21/09
Changed the document title from “Advanced Internal Analog Routing without
Output Buffers” to “Signal Mixing with PSoC Switched Capacitor Blocks”.
*B
3739098
SAMP
09/10/2012
Added Summary.
Updated in new template.
*C
4822035
ASRI
07/03/2015
Obsolete document.
Completing Sunset Review.
www.cypress.com
Document No. 001-16833 Rev. *C
23
®
Signal Mixing with PSoC Switched Capacitor Blocks
Worldwide Sales and Design Support
Cypress maintains a worldwide network of offices, solution centers, manufacturer’s representatives, and distributors. To find
the office closest to you, visit us at Cypress Locations.
PSoC® Solutions
Products
Automotive
cypress.com/go/automotive
psoc.cypress.com/solutions
Clocks & Buffers
cypress.com/go/clocks
PSoC 1 | PSoC 3 | PSoC 5
Interface
cypress.com/go/interface
Lighting & Power Control
cypress.com/go/powerpsoc
cypress.com/go/plc
Memory
cypress.com/go/memory
Optical Navigation Sensors
cypress.com/go/ons
PSoC
cypress.com/go/psoc
Touch Sensing
cypress.com/go/touch
USB Controllers
cypress.com/go/usb
Wireless/RF
cypress.com/go/wireless
Cypress Developer Community
Community | Forums | Blogs | Video | Training
Technical Support
cypress.com/go/support
PSoC® is a registered trademark of Cypress Semiconductor Corp. "Programmable System-on-Chip," PSoC Designer is a trademark of Cypress
Semiconductor Corp. All other trademarks or registered trademarks referenced herein are the property of their respective owners.
Cypress Semiconductor
198 Champion Court
San Jose, CA 95134-1709
Phone
Fax
Website
: 408-943-2600
: 408-943-4730
: www.cypress.com
© Cypress Semiconductor Corporation, 2008-2015. The information contained herein is subject to change without notice. Cypress Semiconductor
Corporation assumes no responsibility for the use of any circuitry other than circuitry embodied in a Cypress product. Nor does it convey or imply any
license under patent or other rights. Cypress products are not warranted nor intended to be used for medical, life support, life saving, critical control or
safety applications, unless pursuant to an express written agreement with Cypress. Furthermore, Cypress does not authorize its products for use as
critical components in life-support systems where a malfunction or failure may reasonably be expected to result in significant injury to the user. The
inclusion of Cypress products in life-support systems application implies that the manufacturer assumes all risk of such use and in doing so indemnifies
Cypress against all charges.
This Source Code (software and/or firmware) is owned by Cypress Semiconductor Corporation (Cypress) and is protected by and subject to worldwide
patent protection (United States and foreign), United States copyright laws and international treaty provisions. Cypress hereby grants to licensee a
personal, non-exclusive, non-transferable license to copy, use, modify, create derivative works of, and compile the Cypress Source Code and derivative
works for the sole purpose of creating custom software and or firmware in support of licensee product to be used only in conjunction with a Cypress
integrated circuit as specified in the applicable agreement. Any reproduction, modification, translation, compilation, or representation of this Source
Code except as specified above is prohibited without the express written permission of Cypress.
Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS MATERIAL, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress reserves the
right to make changes without further notice to the materials described herein. Cypress does not assume any liability arising out of the application or
use of any product or circuit described herein. Cypress does not authorize its products for use as critical components in life-support systems where a
malfunction or failure may reasonably be expected to result in significant injury to the user. The inclusion of Cypress’ product in a life-support systems
application implies that the manufacturer assumes all risk of such use and in doing so indemnifies Cypress against all charges.
Use may be limited by and subject to the applicable Cypress software license agreement.
www.cypress.com
Document No. 001-16833 Rev. *C
24