Hi-Fi audio preamplifier using Burr-Brown PGA2310
Posted: Wed Jul 13, 2011 9:39 am
I decided to build this project, firstly to help a member of forum and secondly because it was a good opportunity for me to explore new devices such as rotary encoders and the widely used in audio industry Stereo Volume Control PGA2310 of Burr-Brown. The whole project will be a manually – remotely controlled high fidelity audio preamplifier. The nice PIC16F887 is the heart of control circuit. It can offers 36 pins as I/O thanks to its internal precise oscillator and MCLR modules. Flow Code proved again a precious tool for the development of program offering everything ready thanks to its wonderful graphical interface! Never had to use C or assembly code - from which I know few things.
Let’s take a look on PGA2310 digital section (Figure 1). A lot of control and data ports are available making it very flexible. In the current project I make use of just 3 ports: a) SCLK (clock to synchronize PGA2310 with the host controller during data transmission), b) SDI (serial data input) and c) MUTE (active Low). The required serial data format is very simple: 16bit long, 8bits for each channel, b0 - b7 = L0 - L7 and b8 – b15 = R0 – R7 where L0 – L7 represents the Gain of Left channel and R0 – R7 the Gain of Right channel. There is no special demand for the serial clock (Figure 2); it can has a frequency from… 0 up to 6.25MHz and 80nsec minimum width for both Low and High semi periods; given this Hi and Low states of clock is not necessary to be equal. Serial data are transferred into PGA2310 registers during the rising edge of clock. Thanks to this simplicity there is no need of using any of the timer outputs of PIC; we simply have to set an output – that represents the synchronization clock - in Hi and Low state and to MASK sequentially one by one the 16 bits of two registers that hold a word of Gain data. Gain of each channel is set by an 8-bit code in straight binary format. The formula that gives the gain setting is: Gain (dB) = 31.5 – [ 0.5 X ( 255 – N) ] where N is the decimal equivalent of the existing 8-bit code. When N = 0 the internal logic circuit of PGA2310 recognizes a MUTE condition and connects its input multiplexer to analog GND. When N = 1 – 255 Gain takes a value within a range from -95.5dB up to +31.5dB. Inside the program only integer numbers are calculated while numbers with fractional part are rejected. Thus we have a numerical sequence of: -95, -94, -93… +30, +31dB. This simplifies the Gain calculation and printing on LCD display.
Looking at Flow Code control panel, we can see a 2 X 16 LCD display connected at port C.0 – C.5, two momentary switches PWRON/STBY and MUTE connected at port B.4and B.5 respectively. Flow Code does not offer rotary encoder unit, so it is simulated – I have seen enough members on the forum that use the same trick – with one momentary and one toggle switch. The toggle defines the direction (CW or CCW) and the momentary reproduces steps like an encoder. There are two square Led of which the green represents the relay that activates the analog power supply (in audio devices is mandatory the use of separate power supply for the analog section unless the noise of MCU oscillator could be pass into the audio signal path) and the red that simply indicates the MUTE state of PGA2310 (active LOW) so when Led is off means that MUTE is activated. There are another 3 round Led: The red is lit when device is in Stand-By mode. In digitally controlled audio devices stand-by means that the analog power supply is deactivated, while the digital supply remains active to keep the microcontroller running continuously. The green Led shows the serial clock Hi and Low state, and the blue one shows the serial data transmitted i.e. is lit when a transmitted bit is “1”. In the current project I have adopted the use of common type relays (non Latching) so the use of EEPROM is redundant. Let’s look at the Flow Code:
After the MAIN macro beginning we have to initialize the switches. Because we use the same momentary switch to enable and disable the analog power supply, the program should recognize if the switch is pressed for first or second time. To this, a variable named “Power_Sw” is used; when the PWRON/STBY switch is pressed and “Power_Sw = 0” the program starts the activation process (Power ON); if “Power_Sw = 1” the program starts the deactivation process (Stand By). The same applies to the MUTE switch for which a variable named “Mute_Sw” is used. Thus, in the beginning of program we have to reset the flags (= “0”) of these two variables. Then, we have to initialize the variable “counter” in which is stored the existing number of steps executed from Encoder. By default, when PGA2310 is powered a reset of its internal logic is executed, is placed in MUTE state and in its internal Gain registers is written “00h”, so we have to give an initial value “0x00” in variable “counter”. This initial process is necessary because the SRAM registers that used to store these variables take unpredictable values during micro powering. Returning to the program Flow, we can see that in the next command the Port B (change state or IOC according to Microchip) interrupt is enabled and when occurs it calls the Macro “Scan_Switch”. It should be noted that P16F887 offers this interrupt possibility on all 8 pins of Port B while its predecessor P16F877 only from RB.4 to RB.7. Then the program Flow enters into a conditional Loop. Because the given condition is “While 1” and is checked at the start of the Loop, it means that is always TRUE resulting in a continuously executed Loop which can be “broken” only by an interrupt request like this of Port B - change state. So, if any of the 3 switches is pressed it causes interrupt and calls the ISR which is the Macro “Scan_Switch”.
In the beginning of macro “Scan_Switch”, we have to define the Port register and the variable that is related with the next operations of program. This definition is given into Input icon “Port B” in which is also defined the variable “SWITCH” that used to store the code of switch pressed. Next from this, there are 3 sequential Decision icons for the recognition of switch that is pressed. When the switch code matches with the test number of a Decision, program Flow is turned to its “yes” branch. If the switch pressed is the POWERON/STBY and after a small delay (10ms for debounce) the program tests if it is pressed for first or second time. This executed inside a Decision in which is checked if the flag of variable “Power_Switch” is set ( = 1 ) or reset ( = 0 ). Accordingly the program Flow is turned either to the “Yes” or “No” branch for the execution of Disable (Stand By) or Enable (Power On) process of preamplifier. In a similar way is executed the MUTE process, when is recognized that the MUTE switch is pressed. To prevent any activity of the MUTE switch and Encoder, during preamplifier Stand-By mode, in the beginning of the “yes” branch of each Decision is first checked if the flag of variable “Power_Switch” is set (=1). When the switch STEP is pressed and recognized by the corresponding Decision we can see that first the Port interrupt is – temporarily - disabled. In this way the steps of Encoder can be counted one by one using the variable “counter”, and a possible confusion of step number calculation can be avoided if the Encoder is “crazy” turned by the user. In the next step the program calls the Macro “COUNT”.
After the beginning of Macro “COUNT”, first is defined the Input of toggle switch which is the RA.0 (to the present) and the variable “switch_A0” in which is stored the state of switch (Hi or Lo). In the following Decision is checked the state of switch: if it is Low (= “0”) the program Flow is turned to the NO branch to increment the “counter”. If it is Hi (= “1”) is turned to the YES branch to decrement the counter. In both branches, first a check is made whether the Counter has reached its maximum or minimum value. The maximum value of counter which corresponds to a Gain integer is 254 (+31dB), while the minimum is 2 (-95dB). In any of the two cases, the counter stops to increment or decrement. That is necessary because prevents a counting loop, which may result in a steep (and dangerous to loudspeakers) transition from minimum to maximum Gain (volume) and vice versa. If not the case, then counter continues to increment or decrement according to the position of toggle switch. This is executed by the Calculation “counter = counter + 2” or “counter = counter – 2” respectively. As we have seen only even "N" numbers can result in integer Gain value, so increment or decrement of counter by “2” rejects numbers with fractional part. It should be noted that the program Flow, up here, is temporary and serves just for simulation. An actual “gray scale” rotary encoder usually executes 24 steps per revolution and under the given program structure, only the half number (12) would be calculated. Let’s stay tuned with this to the present. The rest part of Macro will be – less or more – the same in the final project. In the next step of program Flow, is checked if the “counter” holds a number greater than 192. The number N = 192 corresponds exactly to “0dB”. A value of counter bigger than 192 results in positive dBs, while a value of counter less than 192 results in negative dBs. I have simplified the formula of Gain calculation which for positive dBs results in the equation: Gain (+dB) = ( N – 192 ) / 2. For negative dBs results in the equation: Gain (-dB) = ( 192 – N ) / 2. Where N is the number of steps executed by Encoder and is contained into the variable “counter”. In any case, the program Flow is turned to the corresponding branch of Decision “If counter > 192?” and in the following steps the above calculation is executed while the result is stored into the variable “Gain_dB”.
All indications are printed on LCD display at constant x, y coordinates except the Gain value which can have a length of 1 (“0”), or 2 (e.g. “+3”) or 3 (e.g. “-36”) characters. Some precaution of LCD display is needed before the update of Gain value. Take for example the current program: The Gain is printed at the upper right corner of display. The string “dB” is constant and is always printed on squares 14-15 of first line { x = 14, y = 0 }. The value of Gain is printed on squares 11, 12 and 13. To be tidy its appearance on the display, if the number to be printed is “0” coordinates should be { x=13, y=0 }. If the number is unary with sign then coordinates should be { x=12, y=0 } and if it is decade with sign coordinates should be { x=11, y=0 }. Also, before the renewal of Gain value, first the old value must be cleared - unless display will show hieroglyphics instead numbers. To clear the 3 characters that represent the Gain value we have to print 3 spaces on their place. That is executed after the calculation of variable “Gain_dB” with two LCD macro commands: In the first the cursor is placed at { x = 11, y = 0 } and then, 3 spaces are printed { LCD Display Print String “ “ }. In the following Decision is checked “If Gain_dB=0?” and if it is so, a jump to connection point “A” or “B” is executed by the program, and the “0” is printed at square 13 exactly before string “dB”. If “Gain_dB” is not “0” the program Flow continues to the NO branch where the variable is checked by the Decision “If Gain_dB > 9?” if holds a decade number and if it is so, program Flow is turned to YES branch to print a signed decade number at { x = 11, y = 0 }. If “Gain_dB” is equal or less than “9” the program Flow is turned to NO branch to print a signed unary number at { x = 12, y = 0 }. That’s all.
I have to mention two members of forum “medelec35” and “Dutchie_World_Wide” who helped me – when I was newbie in Flow Code – to learn this nice program sequence that offers a professional appearance of continuously updated numerical indications on display, without flickering. Thanks again guys.
Before the end of macro “COUNT” the flag of a variable “Counter_update” is set (=1). Then the program Flow returns to the MAIN Loop where the flag of “Counter_update” is continuously checked by a Decision “If Counter_update is TRUE?”. Because the flag of “Counter_update” has been Set (=1), which means that is TRUE, the program Flow is turned to its YES branch and calls the macro “SERIAL_OUT”.
Inside the macro “SERIAL_OUT” the 8-bit code that holds the variable “counter” and which is the binary equivalent of the Gain setting, is transmitted in serial format thru Port RD.4 of micro which is directly connected to SDI of PGA2310. That is obtained by Masking one by one the 8 bits of “counter” in sequence, starting from the LSB. The result of each Mask operation is stored into variable “Serial”. Take a look on the Flow Chart of “SERIAL_OUT”: After the beginning, in the first Calculation “Serial = counter AND 0x01” the LSB of variable “counter” is checked and the result is stored into variable “Serial”. In the following Output icon the clock output RD.3 that is connected directly to SCLK of PGA2310 is set to Hi state. Then the PGA2310 input register is ready to receive the first transmitted bit. Next from this, the content of variable “Serial” is extracted to the serial output RD.4 for transmission. The following Delay of 10μsec keeps the clock output in Hi state for a while, so that reception of LSB from PGA2310 to be sure. In the next step, the clock Output is cleared (“Output 0D.3) and remains in Low state for 10μsec. After this, the second bit of “counter” is tested (“Serial = counter AND 0x02”) and the previously described steps are repeated until the extraction of the last bit of “counter” which is the MSB. Before the end of macro “SERIAL_OUT” the flag of variable “Counter_update” is cleared (=0) and the program Flow returns in the Main macro, at the Yes branch of Decision “If Counter_update?” and the Port interrupt is enabled again. Then, the Main Loop is reactivated and runs continuously waiting for the next interrupt request. At this point, a whole cycle of program, starting from an interrupt request, has been completed.
It should be noted that the given max clock frequency of PGA2310 is 6.25MHz resulting in a minimum period of 0.16μsec. In the current program, the two Delays of 10μsec placed after the Hi and Low states of serial clock combined with the time needed from MCU to complete the transmission of each one bit results in a sum of 22μsec as much or F = 45.4545KHz which is sufficiently fast for the current project and within the clock range of PGA2310. Another one issue is that in the PGA2310 datasheet is not expressly referred which bit is received first. From the timing figures, I can suppose that the reception sequence is bit0 first - bit16 last. Having this in my mind I did the development of macro “SERIAL_OUT” in which the LSB of “counter” is first transmitted. This can be confirmed only by testing the program on the actual project; unfortunately I haven’t in my hands a PGA2310, I hope that I will have money left over next month (that is the true Greek economic crisis) to buy a PGA2310, a rotary encoder and two LM4562 or four LME49710 to build a complete preamplifier.
By observing the blue Led, you can see the serial transmitted byte. Do the following: Select from “Project Options” menu a simulation speed of 20 and place on Variable window the variables: counter, GAIN_dB, Serial and Clock. Run the simulator. Press first the PWRON/STBY switch to enable the project. After the initial process the program returns in the Main Loop, while on the display is printed -95dB. While running the program, double click on the variable “counter” inside the Variables window. In the box that opens, you can change the “counter” value; print e.g. 180 and click OK. That is equal to -6dB of Gain. Press the STEP switch – for a while to take effect the interrupt because the speed of program is slow – and the “counter” will increment to 182. If you press again the STEP switch, the expected number of “counter” will be 184. Before this, make your calculation: N = 184 Gain (dB) = 192 – 184 / 2 = -4dB that will printed on display. With the help of windows calculator, make the following conversion: Print on calculator the decimal 184 and then select Binary; the result will be “10111000”. That means that the blue LED should be lit when the program Flow pass over the Calculation icons “Serial = counter AND 0x08” “Serial = counter AND 0x10”, “Serial = counter AND 0x20”, and “Serial = counter AND 0x80”. Press the STEP switch, and keep your eyes - big care needed – on the Flow Code red frame running over program icons. When it passes into the macro “COUNT”, press the PAUSE button of simulator. Now, by pressing the “Step Into” button (or F8 function key on your keyboard) once at a time, you will navigate step by step thru the Flow Code simulator in the current program sequence. Press again and again the “Step Into” and some time the program will enter in the macro “SERIAL_OUT”. Then, you have to observe if the blue Led lit on the correct Calculation icons described above. At the same time, you can observe and the green Led that simulates the clock output. Try it and with other values of “counter”, is wonderful to watch live a serial code transmission.
Of course, the macro “SERIAL_OUT” should be repeated and for the other channel. I will do this in the next part of article combined with Balance operation, Input select and remote control function. In this first part, we have built the main frame of project.
Thanks for your time
Fotios
Please see in the last post for the updated software v1.2
Let’s take a look on PGA2310 digital section (Figure 1). A lot of control and data ports are available making it very flexible. In the current project I make use of just 3 ports: a) SCLK (clock to synchronize PGA2310 with the host controller during data transmission), b) SDI (serial data input) and c) MUTE (active Low). The required serial data format is very simple: 16bit long, 8bits for each channel, b0 - b7 = L0 - L7 and b8 – b15 = R0 – R7 where L0 – L7 represents the Gain of Left channel and R0 – R7 the Gain of Right channel. There is no special demand for the serial clock (Figure 2); it can has a frequency from… 0 up to 6.25MHz and 80nsec minimum width for both Low and High semi periods; given this Hi and Low states of clock is not necessary to be equal. Serial data are transferred into PGA2310 registers during the rising edge of clock. Thanks to this simplicity there is no need of using any of the timer outputs of PIC; we simply have to set an output – that represents the synchronization clock - in Hi and Low state and to MASK sequentially one by one the 16 bits of two registers that hold a word of Gain data. Gain of each channel is set by an 8-bit code in straight binary format. The formula that gives the gain setting is: Gain (dB) = 31.5 – [ 0.5 X ( 255 – N) ] where N is the decimal equivalent of the existing 8-bit code. When N = 0 the internal logic circuit of PGA2310 recognizes a MUTE condition and connects its input multiplexer to analog GND. When N = 1 – 255 Gain takes a value within a range from -95.5dB up to +31.5dB. Inside the program only integer numbers are calculated while numbers with fractional part are rejected. Thus we have a numerical sequence of: -95, -94, -93… +30, +31dB. This simplifies the Gain calculation and printing on LCD display.
Looking at Flow Code control panel, we can see a 2 X 16 LCD display connected at port C.0 – C.5, two momentary switches PWRON/STBY and MUTE connected at port B.4and B.5 respectively. Flow Code does not offer rotary encoder unit, so it is simulated – I have seen enough members on the forum that use the same trick – with one momentary and one toggle switch. The toggle defines the direction (CW or CCW) and the momentary reproduces steps like an encoder. There are two square Led of which the green represents the relay that activates the analog power supply (in audio devices is mandatory the use of separate power supply for the analog section unless the noise of MCU oscillator could be pass into the audio signal path) and the red that simply indicates the MUTE state of PGA2310 (active LOW) so when Led is off means that MUTE is activated. There are another 3 round Led: The red is lit when device is in Stand-By mode. In digitally controlled audio devices stand-by means that the analog power supply is deactivated, while the digital supply remains active to keep the microcontroller running continuously. The green Led shows the serial clock Hi and Low state, and the blue one shows the serial data transmitted i.e. is lit when a transmitted bit is “1”. In the current project I have adopted the use of common type relays (non Latching) so the use of EEPROM is redundant. Let’s look at the Flow Code:
After the MAIN macro beginning we have to initialize the switches. Because we use the same momentary switch to enable and disable the analog power supply, the program should recognize if the switch is pressed for first or second time. To this, a variable named “Power_Sw” is used; when the PWRON/STBY switch is pressed and “Power_Sw = 0” the program starts the activation process (Power ON); if “Power_Sw = 1” the program starts the deactivation process (Stand By). The same applies to the MUTE switch for which a variable named “Mute_Sw” is used. Thus, in the beginning of program we have to reset the flags (= “0”) of these two variables. Then, we have to initialize the variable “counter” in which is stored the existing number of steps executed from Encoder. By default, when PGA2310 is powered a reset of its internal logic is executed, is placed in MUTE state and in its internal Gain registers is written “00h”, so we have to give an initial value “0x00” in variable “counter”. This initial process is necessary because the SRAM registers that used to store these variables take unpredictable values during micro powering. Returning to the program Flow, we can see that in the next command the Port B (change state or IOC according to Microchip) interrupt is enabled and when occurs it calls the Macro “Scan_Switch”. It should be noted that P16F887 offers this interrupt possibility on all 8 pins of Port B while its predecessor P16F877 only from RB.4 to RB.7. Then the program Flow enters into a conditional Loop. Because the given condition is “While 1” and is checked at the start of the Loop, it means that is always TRUE resulting in a continuously executed Loop which can be “broken” only by an interrupt request like this of Port B - change state. So, if any of the 3 switches is pressed it causes interrupt and calls the ISR which is the Macro “Scan_Switch”.
In the beginning of macro “Scan_Switch”, we have to define the Port register and the variable that is related with the next operations of program. This definition is given into Input icon “Port B” in which is also defined the variable “SWITCH” that used to store the code of switch pressed. Next from this, there are 3 sequential Decision icons for the recognition of switch that is pressed. When the switch code matches with the test number of a Decision, program Flow is turned to its “yes” branch. If the switch pressed is the POWERON/STBY and after a small delay (10ms for debounce) the program tests if it is pressed for first or second time. This executed inside a Decision in which is checked if the flag of variable “Power_Switch” is set ( = 1 ) or reset ( = 0 ). Accordingly the program Flow is turned either to the “Yes” or “No” branch for the execution of Disable (Stand By) or Enable (Power On) process of preamplifier. In a similar way is executed the MUTE process, when is recognized that the MUTE switch is pressed. To prevent any activity of the MUTE switch and Encoder, during preamplifier Stand-By mode, in the beginning of the “yes” branch of each Decision is first checked if the flag of variable “Power_Switch” is set (=1). When the switch STEP is pressed and recognized by the corresponding Decision we can see that first the Port interrupt is – temporarily - disabled. In this way the steps of Encoder can be counted one by one using the variable “counter”, and a possible confusion of step number calculation can be avoided if the Encoder is “crazy” turned by the user. In the next step the program calls the Macro “COUNT”.
After the beginning of Macro “COUNT”, first is defined the Input of toggle switch which is the RA.0 (to the present) and the variable “switch_A0” in which is stored the state of switch (Hi or Lo). In the following Decision is checked the state of switch: if it is Low (= “0”) the program Flow is turned to the NO branch to increment the “counter”. If it is Hi (= “1”) is turned to the YES branch to decrement the counter. In both branches, first a check is made whether the Counter has reached its maximum or minimum value. The maximum value of counter which corresponds to a Gain integer is 254 (+31dB), while the minimum is 2 (-95dB). In any of the two cases, the counter stops to increment or decrement. That is necessary because prevents a counting loop, which may result in a steep (and dangerous to loudspeakers) transition from minimum to maximum Gain (volume) and vice versa. If not the case, then counter continues to increment or decrement according to the position of toggle switch. This is executed by the Calculation “counter = counter + 2” or “counter = counter – 2” respectively. As we have seen only even "N" numbers can result in integer Gain value, so increment or decrement of counter by “2” rejects numbers with fractional part. It should be noted that the program Flow, up here, is temporary and serves just for simulation. An actual “gray scale” rotary encoder usually executes 24 steps per revolution and under the given program structure, only the half number (12) would be calculated. Let’s stay tuned with this to the present. The rest part of Macro will be – less or more – the same in the final project. In the next step of program Flow, is checked if the “counter” holds a number greater than 192. The number N = 192 corresponds exactly to “0dB”. A value of counter bigger than 192 results in positive dBs, while a value of counter less than 192 results in negative dBs. I have simplified the formula of Gain calculation which for positive dBs results in the equation: Gain (+dB) = ( N – 192 ) / 2. For negative dBs results in the equation: Gain (-dB) = ( 192 – N ) / 2. Where N is the number of steps executed by Encoder and is contained into the variable “counter”. In any case, the program Flow is turned to the corresponding branch of Decision “If counter > 192?” and in the following steps the above calculation is executed while the result is stored into the variable “Gain_dB”.
All indications are printed on LCD display at constant x, y coordinates except the Gain value which can have a length of 1 (“0”), or 2 (e.g. “+3”) or 3 (e.g. “-36”) characters. Some precaution of LCD display is needed before the update of Gain value. Take for example the current program: The Gain is printed at the upper right corner of display. The string “dB” is constant and is always printed on squares 14-15 of first line { x = 14, y = 0 }. The value of Gain is printed on squares 11, 12 and 13. To be tidy its appearance on the display, if the number to be printed is “0” coordinates should be { x=13, y=0 }. If the number is unary with sign then coordinates should be { x=12, y=0 } and if it is decade with sign coordinates should be { x=11, y=0 }. Also, before the renewal of Gain value, first the old value must be cleared - unless display will show hieroglyphics instead numbers. To clear the 3 characters that represent the Gain value we have to print 3 spaces on their place. That is executed after the calculation of variable “Gain_dB” with two LCD macro commands: In the first the cursor is placed at { x = 11, y = 0 } and then, 3 spaces are printed { LCD Display Print String “ “ }. In the following Decision is checked “If Gain_dB=0?” and if it is so, a jump to connection point “A” or “B” is executed by the program, and the “0” is printed at square 13 exactly before string “dB”. If “Gain_dB” is not “0” the program Flow continues to the NO branch where the variable is checked by the Decision “If Gain_dB > 9?” if holds a decade number and if it is so, program Flow is turned to YES branch to print a signed decade number at { x = 11, y = 0 }. If “Gain_dB” is equal or less than “9” the program Flow is turned to NO branch to print a signed unary number at { x = 12, y = 0 }. That’s all.
I have to mention two members of forum “medelec35” and “Dutchie_World_Wide” who helped me – when I was newbie in Flow Code – to learn this nice program sequence that offers a professional appearance of continuously updated numerical indications on display, without flickering. Thanks again guys.
Before the end of macro “COUNT” the flag of a variable “Counter_update” is set (=1). Then the program Flow returns to the MAIN Loop where the flag of “Counter_update” is continuously checked by a Decision “If Counter_update is TRUE?”. Because the flag of “Counter_update” has been Set (=1), which means that is TRUE, the program Flow is turned to its YES branch and calls the macro “SERIAL_OUT”.
Inside the macro “SERIAL_OUT” the 8-bit code that holds the variable “counter” and which is the binary equivalent of the Gain setting, is transmitted in serial format thru Port RD.4 of micro which is directly connected to SDI of PGA2310. That is obtained by Masking one by one the 8 bits of “counter” in sequence, starting from the LSB. The result of each Mask operation is stored into variable “Serial”. Take a look on the Flow Chart of “SERIAL_OUT”: After the beginning, in the first Calculation “Serial = counter AND 0x01” the LSB of variable “counter” is checked and the result is stored into variable “Serial”. In the following Output icon the clock output RD.3 that is connected directly to SCLK of PGA2310 is set to Hi state. Then the PGA2310 input register is ready to receive the first transmitted bit. Next from this, the content of variable “Serial” is extracted to the serial output RD.4 for transmission. The following Delay of 10μsec keeps the clock output in Hi state for a while, so that reception of LSB from PGA2310 to be sure. In the next step, the clock Output is cleared (“Output 0D.3) and remains in Low state for 10μsec. After this, the second bit of “counter” is tested (“Serial = counter AND 0x02”) and the previously described steps are repeated until the extraction of the last bit of “counter” which is the MSB. Before the end of macro “SERIAL_OUT” the flag of variable “Counter_update” is cleared (=0) and the program Flow returns in the Main macro, at the Yes branch of Decision “If Counter_update?” and the Port interrupt is enabled again. Then, the Main Loop is reactivated and runs continuously waiting for the next interrupt request. At this point, a whole cycle of program, starting from an interrupt request, has been completed.
It should be noted that the given max clock frequency of PGA2310 is 6.25MHz resulting in a minimum period of 0.16μsec. In the current program, the two Delays of 10μsec placed after the Hi and Low states of serial clock combined with the time needed from MCU to complete the transmission of each one bit results in a sum of 22μsec as much or F = 45.4545KHz which is sufficiently fast for the current project and within the clock range of PGA2310. Another one issue is that in the PGA2310 datasheet is not expressly referred which bit is received first. From the timing figures, I can suppose that the reception sequence is bit0 first - bit16 last. Having this in my mind I did the development of macro “SERIAL_OUT” in which the LSB of “counter” is first transmitted. This can be confirmed only by testing the program on the actual project; unfortunately I haven’t in my hands a PGA2310, I hope that I will have money left over next month (that is the true Greek economic crisis) to buy a PGA2310, a rotary encoder and two LM4562 or four LME49710 to build a complete preamplifier.
By observing the blue Led, you can see the serial transmitted byte. Do the following: Select from “Project Options” menu a simulation speed of 20 and place on Variable window the variables: counter, GAIN_dB, Serial and Clock. Run the simulator. Press first the PWRON/STBY switch to enable the project. After the initial process the program returns in the Main Loop, while on the display is printed -95dB. While running the program, double click on the variable “counter” inside the Variables window. In the box that opens, you can change the “counter” value; print e.g. 180 and click OK. That is equal to -6dB of Gain. Press the STEP switch – for a while to take effect the interrupt because the speed of program is slow – and the “counter” will increment to 182. If you press again the STEP switch, the expected number of “counter” will be 184. Before this, make your calculation: N = 184 Gain (dB) = 192 – 184 / 2 = -4dB that will printed on display. With the help of windows calculator, make the following conversion: Print on calculator the decimal 184 and then select Binary; the result will be “10111000”. That means that the blue LED should be lit when the program Flow pass over the Calculation icons “Serial = counter AND 0x08” “Serial = counter AND 0x10”, “Serial = counter AND 0x20”, and “Serial = counter AND 0x80”. Press the STEP switch, and keep your eyes - big care needed – on the Flow Code red frame running over program icons. When it passes into the macro “COUNT”, press the PAUSE button of simulator. Now, by pressing the “Step Into” button (or F8 function key on your keyboard) once at a time, you will navigate step by step thru the Flow Code simulator in the current program sequence. Press again and again the “Step Into” and some time the program will enter in the macro “SERIAL_OUT”. Then, you have to observe if the blue Led lit on the correct Calculation icons described above. At the same time, you can observe and the green Led that simulates the clock output. Try it and with other values of “counter”, is wonderful to watch live a serial code transmission.
Of course, the macro “SERIAL_OUT” should be repeated and for the other channel. I will do this in the next part of article combined with Balance operation, Input select and remote control function. In this first part, we have built the main frame of project.
Thanks for your time
Fotios
Please see in the last post for the updated software v1.2