SoftRock-V9.0 Receiver Firmware USB AVR Si570 controler. @ Home     Access count

I like to play around with embedded software. I also build the SoftRock V9.0 with is using the ATTiny45 chip for controling the receiver and handeling the USB bus. The firmware in de AVR chip is build on the free USB AVR Code by Tom Baier (DG8SAQ) who used it in his own SI570 board.

Because of a bug in the firmware I was become interested in the firmware and start extending the functionality, the whole process can be found on this page.
This modified firmware is the now the official supplied firmware in the SoftRock kits of Tony Parks that are using a Si570 chip from Silicon Laboratories (SiLabs).

I you want to use the SoftRock V9.0 with WinRad from Alberto I2PHD you may like to use my ExtIO_Si570 DLL.
Reuse of the ATtiny45 chip can be done only with a AVR high voltage programmer or a tool like my fuse bit restore.

I like to thank Prof. Dr. Thomas C. Baier for the publication of the initial software.


Version 15.1: Bug fixed.

The same software in the SoftRock-V9.0 board gives a problem because the SoftRock-V9.0 is using different power for the AVR chip (5V USB) and the Si570 chip (3.3V RX). When the power supply's are switched ON on the same moment (one dubble power switch) there is no problem. Switching only the AVR (or switching the RX off) will hang the software and the USB connection will be broken.

I changed the software so that the software will not hang on that bug. I also cleaned the software by removing many not used (I hope :-) commands. Compiled it with the WinAVR gcc compiler (WinAVR-20071221) and the lates version of the AVR USB library (usbdrv-20081022).

 * Modifications by Fred Krom, PE0FKO at Nov 2008
 * - Fixed hang on no pull up of SCL line i2c to Si570 (or power down of Si590 in SR-V90)
 * - Initialize Si570 when seen on the i2c bus
 * - Compiler (WinAVR-20071221) optimized the i2c delay loop a way!
 * - AVR USB Version usbdrv-20081022
 * - Source cleanup and split in deferend files.
 * - Remove many debug USB command calls!
 * - Add command 0x31, write only the Si570 registers (change freq max 3500ppm)

Version 15.2: Si570 Algorithme.

In the new version V15.2 I changed the code for calculating the Si570 registers. The algorithm searched for the lowest DCO frequency and will calculate the full 38 bits of the RFREQ register. That is done in less code than the older versions and much faster.
The old code was very bad in calculating the register value, most programs do not use this function bacause the frequency was far from the specified one (< 5KHz). The programs will calculate the si570 registers and will send them to the chip. The USB interface will be chip dependent and the interface can not be used for controlling a DDS.
It is necessary to use command such as "set the freq to 7.040MHz" and not commands like "Set the Si570 registers to 0xAB, 0xCD...".

But for normal users the code change is not that important (maybe the precise frequency?). The speed improvements from 2ms to 0.37ms will not be mention by normal users, and that the chip uses less code...
But for future improvements you will need the speed and free code (maybe).
The next I working on is the fraction tuning, when the chip's frequency has to be changed a little bit there is no need to stop and start the chip again. A smooth tuning is then possible for small (+/-3500PPM) frequency changes.

 * - Change the Si570 register calculation and now use the full 38 bits of the chip!
 *   Is is acurate, fast and small code! It cost only 350us (old 2ms) to calculate the new registers.
 * - Add command 0x3d, Read the actual used xtal frequenty (4 bytes, 24 bits fraction, 8.24 bits)

Version 15.3: Automatic Smooth Tune.

In the new version V15.3 I added the "automatic smooth tune" (AST) functionality and the I/O function. The AST will work only on the "set freq by value" and not on the register setting. The AST is automatic and enabled by default. The range (+/- 3500PPM) can be changed and read from the device, setting it on zero will disable the function.
The I/O function works in one call with a value for the I/O direction (Input or Output) and a bit value for the Output bit and it will return all the bits in one word. This hardware only support bit0 and bit1.
There are support command for setting and reading the crystal frequency, startup frequency and the AST PPM value.

Version 15.4: Automatic Band Pass Filter selection

In this new version V15.4 I added the "Automatic Band Pass Filter selection" (ABPF) functionality for the Softrock V9 BPF. The device will accept 3 filter cross over values and will automatic select between the four filters. De functionality can be disabled by software. By changing the main.c function I released a lot of code space to implement this and maybe other functions.
This functionality (also the AST) will only work with the call "set frequency by value" and not the "set frequency by Si570 registers". Now there is still room for some more code, maybe we can change both functions to work with the register call?
For application software that want to see the difference between the old and new firmware, I changed the USB version number. That will give one small problem, this software will ask for the driver the very first time it is plugged into a PC. The same as the old firmware did the first time. The serial number will not be checked in most existing software (I hope) so no change had to be made there. You will need this PC driver software for installing the driver (also included in the .zip file). Put the software in a directory and when the device is plugged in and asked for his driver then specify that directory. After that, the directory can be removed.

Version 15.5: Smooth tune and band pass filter to the "Set freq by Si570 registers" command.

Many existing SDR receivers are using the "Set freq by Si570 registers" command and not the (easier to use) "Set freq by value" command. That is due to history.
My smooth tune and automatic band pass filter are working in the previous versions only on the ".. value" command. Now they are also working on the ".. Si570 register" command. The working behind it is that from the given Si570 registers the requested frequency is calculated (< 100 us) and that frequency is passed to the "Set freq by value" command. The calculations are done with all the precision (bits) of the Si570 chip.
I will recommend that new SDR software is going to use the "Set freq by value" command despite this functionality.

Version 15.6: Bug fix.

This version is a small Bug fix, after rebooting the PC with the USB connected there will be no USB connection. That is fixed, something with the watchdog timer. There was also a small problem, when reading the frequency from the USB controller it will return the smooth tune center frequency and not the oscillating frequency. No application programs is using that call, only my own Winrad dll for information only.

Version 15.7: Minor updates.

This is the latest version of my Si570 Firmware upgrade.
It is tested on the SoftRock V9 (with and without the BPF) and SoftRock RXTX 6.3 hardware and it is compatible with most SDR Radio software that support the Si570 driver. For use with the SoftRock RXTX you will need to disable the ABPF settings!
I tested it with WinRad ExtIO_Si570.dll, WinRad ExtIO_si570_usb.dll, Rocky V3.6 and PowerSDR-IQ V1.12.3.
Because the basic command's are not changed from the original firmware, I expect the software can be a good replacement for the original firmware. It will give the automatic antenna tuning and smooth tune functionality and some bug fixes.
Only be aware that some software my depend on functionality that is supported in the original but not in this firmware! In the original software there are command's to handle all kind of I2C functions. For example the USB_Synth program used a calibration with the chip factory default startup frequency (Menu "Setup", button "calibrate to factory startup frequency") that will not work with the new firmware (do not use it). The same function (and working for this firmware) will be found in the new WinRad ExtIO_Si570_V0.7 dll version 0.7.


Version 15.8: Change in calculate frequency from Si570 registers.

I was not right, there is a new version release. I do like a power of two!
In a mail from Alex, he mention a nice future that he was expecting to work in my firmware. But is was not working, never crossed my mind until then.
I did try to make the difference between the two "set frequency" calls minimal. There was only a difference between them in the calibration. Using the "set freq by value" call the crystal frequency in the firmware must be calibrated, using the "set freq by Si570 registers" call the application crystal frequency must be calibrated.
I changed it that only the crystal frequency in the firmware had to be calibrated, and not the application program (SDR receiver) any more. But the application program must use the default crustal freq 114.285 MHz!
In the "set frequency by value" (command 0x32) the internal stored crystal frequency is used, when that crystal frequency is calibrated all the requested frequency's are correct. The command (0x30) "set frequency by Si570 registers" will calculate the frequency from the registers and then calls the "set frequency by value" command. In both calculations the internal crystal frequency is used and will be eliminated by the calculations!
The calculations are from registers to frequency to registers, and will give in the old version the same register settings as was input! That process was necessary because the smooth tune and ABPF setting where implemented in the "set frequency by value" command. But there is no calibration in that process any more, the application had to use the calibrated crystal frequency!
In the new version I calculate from the registers to frequency with the fixed value 114.285 MHz and then from the frequency to registers with the calibrated crystal frequency. That will deliver the calibrated frequency the application did calculate.
The application's are using as default the 114.285 MHz and that value had not to be changed any more!

It is a lot of text for a very small software update, only one variable changed to a fixed number!


Version 15.9: Disable I/O functions in case the ABPF is enabled.

If using the automatic band pass filters (ABPF) together with Rocky (maybe other SDR radio's to) there was a little problem discovered by Bob. Starting Rocky with a frequency that need a odd BPF (filter 1 and 3) the wrong filter was selected (filter 0 or 2). It was only at the start of Rocky, if a other LO was selected it chose the correct filter. The reason for that was that the correct filter was selected but Rocky did disable the first I/O bit, that I/O line is used in SoftRock RXTX 6.3 (and lower) for the TX enable line! Rocky did not know it is a RX only (SoftRock V9).
The problem can be changed in Rocky, I expect, but maybe the firmware must disable the I/O functions if the ABPF is using the I/O lines! That will solve all the problems of selecting the wrong BPF in the SoftRock V9.


Version 15.10: Add LO calculations.

The LO frequency send to the firmware can be changed by the firmware with a offset and a multiply factor, both numbers are fix point numbers with a [11.21] bits resolution.
The used calculation is "FSI570 = ( FLO - Offset ) * Multiply", the Offset is a signed number. The used default value's in the firmware are Offset=0.0 and Multiply=1.0, that will not change the LO frequency.
This feature can be used by frond end mixers with a fixed frequency, all kind of sub-sampling or other fraction multiply like the SoftRock VHF converter is using.
The LO frequency change will work on both set-frequency commands 0x30 and 0x32. To manage the offset and multiply factor two command's are added, one (0x31) to write the two numbers and one (0x39) to read the numbers.

For the use of this firmware in the "USB I2C Interface board" of Tony, the support for the second CW Key input (iambic keying) is added to the command 0x50 and 0x51. Also both command's will return a key open in case of the ABPF is enabled in the firmware. That will prevent the band filter selection bits being seen as CW key input.


Version 15.11: Bug fix with negative frequency offset value.

Using a negative offset value in the LO calculation will not add / subtract anything, in the previous firmware version.
The bug is fixed, and the code still fit in a ATtiny45 chip (2 bytes free) also the ATtiny85 version is available.
A other small change is made to the band crossover point values. The previous version did store the si570 running frequency, the new version will store the set frequency. In the default case of offset=0 and multiply=1 there is no change. And also the command 0x3A will return the set frequency and not the Si570 running frequency.
The change is completely handled by the configuration tool ExtIO_Si570 version 0.9, use that or newer versions for this firmware version.


Version 15.12: Added the Intelligent Band Pass Filter.

This firmware version handles the separate band selection and filter crossover values differently. The previous versions used the filter crossover table to select the band / filter in an incrementing frequency sequence. The filter used for the ABPF was the same number as the band from the crossover table, therefore the actual filters used need to be in a increasing frequency sequence!
There was also, starting from version 15.10, an offset / multiply factor that recalculated the requested LO frequency.

Version 15.12 still uses the filter crossover table to select the frequency band. For every band (0..3) the filter number used can specified, also every band has it's own frequency offset / multiply factor! So the real filters do not necessarily have be in increasing frequency order (v9.0 RX option 2 BPF), also sub harmonic sampling can be specified differently for each band if required.
There is a change to the USB Serial-Number. This can be now set so that every device can have it's own unique serial number. This allows more than one device to be connected to the PC at the same time and used by different application software (if the application software is able to use that field to select a device).

A small change is made to the command 0x41 to set the I2C address, it will now also return the old I2C address and the address zero will not been set.

The sourcecode is made available on Google Code and as normal on this web-side.

One minor disadvantage of the extended functionality provided is that the code will no longer fit in the ATtiny45 chip, the bigger ATtiny85 device has to be used.


Supported Firmware functionality.

The firmware support the following functionality on both set frequency commands 0x30 and 0x32.

Function
Description
Smooth tune
Tuning without clicking on every frequency change. The smooth tune is only possible if the frequency change is no more that 3500ppm (that value can be changed, 0 is disabling the functionality)
Automatic Band Pass Filter
Selecting automatic one of the four band pass filter for every LO frequency. The functionality can be enabled / disabled and will use the two I/O lines on the SoftRock V9. If enabled other I/O settings are disabled.
V15.12: The used hardware filter for a band can be user specified.
One site calibration
Only the firmware had te be calibrated and not the SDR PC Software. The calibration can be done with WinRad and my control ExtIO_Si570 DLL. Keep (if it can be changed) the crystal frequency in the PC SDR application on the default (114.285 MHz) value.
Local ocilator calculation
The LO frequency can be changed by a offset and multiply factor. The real Si570 frequency will be calculated for every frequency change by formula "FSI570 = ( FLO - Offset ) * Multiply". The offset and multiply is a fixed point number stored in eeprom and can be changed by the software.
V15.12: There is a offset / multiply factor for every band.


Supported SDR Receivers.

The firmware has been tested with some the most popular (for what I know) free SDR receivers to check the functionality from the above table.

SDR Software
Version
DLL
Description
WinRad
1.32, 1.42
Yes
Winrad by Alberto, I2PHD.
WinRadHD
v0.0.7
Yes
DG0JBJ, Based on WinRad
Rocky
3.6
No
Rocky by Alex Shovkoplyas, VE3NEA.
PowerSDR-IQ
1.12.20
No
PowerSDR-IQ by Christos Nikolaou, SV1EIA.
PowerSDR-SR40
1.9.0
No
PowerSDR-SR40 by Guido ten Dolle, PE1NNZ.
PowerSDR
1.18.0
Yes
PowerSDR by FlexRadio Systems.
The supported DLL is a changed version from pe1nnz to support this firmware.
CfgSR
1.2
Yes
SoftRock configuration program.


Firmware set-up tips & tricks.

To setup the firmware the configuration tool ExtIO_Si570 can be used.
To learn all about the possible configuration, please read the "PE0FKO SoftRock AVR Firmware User Guide Issue 1_1" created by Bob, G8VOI.
There is also a very nice documents ("v9.0 VHF converters and firmware set-up") describing a lot about the special firmware setup's made by Bob, G8VOI that can be found at this link.


Download Firmware source and .hex files.

V15.1 at 02/12/2008: First release of PE0FKO.
V15.2 at 19/12/2008: Change the Si570 code.
V15.3 at 02/01/2009: Add Automatich smooth tune.
V15.4 at 06/01/2009: Add Automatic Band Pass Filter Selection.
V15.5 at 14/01/2009: Add the Smooth tune and band pass filter to the "Set freq by Si570 registers" command.
V15.6 at 17/01/2009: Bug fix, PC reboot connection. Return frequency was smooth tune center frequency.
V15.7 at 25/01/2009: Minor updates.
V15.8 at 11/02/2009: Change in calculate frequency from Si570 registers.
V15.9 at 19/02/2009: Disable I/O functions in case the ABPF is enabled.
V15.10 at 12/03/2009: LO frequency subtract and multiply.
V15.11 at 27/07/2009: Bug fix with negative frequency subtract value.
V15.12 at 28/09/2009: Added the Inteligent Band Pass Filter.

Firmware version V15.12 from PE0FKO

Download the source AVR-FirmwareV15.12.zip file.
Download the ATtiny85 hex AVR-FirmwareV15.12-ATtiny85.hex file.

Firmware version V15.11 from PE0FKO

Download the source AVR-FirmwareV15.11.zip file.
Download the ATtiny45 hex AVR-FirmwareV15.11-ATtiny45.hex file.
Download the ATtiny85 hex AVR-FirmwareV15.11-ATtiny85.hex file 1).

1) For the people that want to use the ATtiny85 chip with this firmware I included a hex file for that cpu also. It is the same firmware only compiled for the ATtiny85 chip (and used only 4K of the chip flash rom).


Installing the PC driver software.

For installing the device you will need the USB PC driver software. First extract the .zip file to a temporary directory (on the Desktop), plug in the device and it will show "Found new hardware DG8SAQ-I2C". Direct the wizard to the place where the software was stored and the software will be installed.


Upgrading Firmware.

Upgrading the firmware will be done, in most cases, by changing the old ATtiny45 / Attiny85 by a new one with the correct code and fuse bits loaded. Cecil, K5NWA can supply the programmed chips via his website www.dspradio.org, order a ATTINY85-20 chip with "Program an AVR chip on this order.".

The original chip can be upgraded but it will cost some hardware and AVR micro controller programming skills.
To reprogram the original ATtiny45 / Attiny85 chip from Tony you will need to release the RSTDISBL fuse bit, that can be done with a fuse bit restore tool, or by using a AVR high voltage programmer. After restoring the RSTDISBL fuse bit a normal AVR ISP programmer can be used.

With a *new* Attiny45 / Attiny85 chip, the fuse bit restore is not necessary, until you program the RSTDISBL fuse bit to use the PB5 as a extra I/O line.

For people that are willing to learn something about the programming of the Atmel AVR chip's, there is a lot of information on the web.
Also Bob, G8VOI created a very nice document ("A Beginners Guide to Programming the Atmel ATtiny") about the steps to be taken to (re)program the ATTiny45 or ATTiny85 chip with this firmware. The document and other documents from Bob can be found at this webpage.

PonyProg.

Bob G8VOI did some excellent field work for the programming of the firmware in a new ATtiny45 / Attiny85 chip with PonyProg, and created a easy to use PonyProg script file. Please read this document "Beginners Guide to Programming the Atmel ATtiny45 and ATtiny85" by Bob, G8VOI. Hopefully that should make it very easy for a beginner to program their own chip.


************************************************************************
**
** Project......: Firmware USB AVR Si570 controler.
**
** Platform.....: ATtiny45
**
** Licence......: This software is freely available for non-commercial 
**                use - i.e. for research and experimentation only!
**                Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
**                Based on ObDev's AVR USB driver by Christian Starkjohann
**
** Programmer...: F.W. Krom, PE0FKO.
**                Thanks to Tom Baier DG8SAQ for the initial program.
**                Thanks to Alex Lee for the command 0x17 description.
** 
** Description..: Control the Si570 Freq. PLL chip over the USB port.
**
** History......: V15.1 02/12/2008: First release of PE0FKO.
**                V15.2 19/12/2008: Change the Si570 code.
**                V15.3 02/01/2009: Add Automatich smooth tune.
**                V15.4 06/01/2009: Add Automatic Band Pass Filter Selection.
**                V15.5 14/01/2009: Add the Smooth tune and band pass filter 
**                                  to the "Set freq by Si570 registers" command.
**                V15.6 17/01/2009: Bug fix, no connection on boot from PC.
**                                  Used a FreqSmooth so the returned freq is
**                                  the real freq and not the smooth center freq.
**                V15.7 22/01/2009: Source change. Upgrade ObDev to 20081022.
**                                  FreqSmoothTune variable removed from eeprom.
**                                  Test errors in i2c code changed. 
**                                  Add cmd 0x00, return firmware version number.
**                                  Add cmd 0x20, Write Si570 register
**                                  Add cmd 0x0F, Reset by Watchdog
**                V15.8 10/02/2009: CalcFreqFromRegSi570() will use the fixed
**                                  xtal freq of 114.285 MHz. Change static 
**                                  variables to make some more free rom space.
**                V15.9 17/02/2009: Disable I/O functions in case the ABPF is enabled.
**               V15.10 18/03/2009: LO frequency subtract and multiply.
**                                  Add cmd 0x31, Write the frequency subtract multiply to the eeprom
**                                  Add cmd 0x39, Return the frequency subtract multiply
**                                  Check if the DCO freq is lower than the Si570 max.
**                                  Include some .c files, it is smaller in size.
**                                  Move some static variables to register, smaller code size.
**                                  Add support for the CW Key_2 in command 0x50 & 0x51.
**                                  CW Key always return open if ABPF is enabled (command 0x50 & 0x51)
**               V15.11 27/07/2009: BUG in the CalcFreqMulAdd() with a negative subtract value.
**                                  Change the SetFreq() so that the filter table is set and 
**                                  after it the subtract multiply is done! (changed in order)
**                                  Changed the SetFreq() so that cmd 0x3a will return the requested
**                                  freq and not the Si570 freq. 
**               V15.12 28/08/2009: Added the IBPF settings. Every band, selected with the Filter
**                                  cross-over table, holds its own offset/multiply and filter number.
**                                  The command 0x41 will return the old I2C address, it only accept
**                                  I2C addresses if Index is zero.
**                                  Change of the USB Serial number is possible for the last char of 
**                                  that string "PE0FKO-0". The "0" can be changed with command 0x43.
**
**************************************************************************

Compiler: WinAVR-20071221
Chip: ATtiny45 (4Kb prom)
V14			3866 bytes (94.4% Full)
V15.1		3856 bytes (94.1% Full)
V15.2		3482 bytes (85.0% Full)
V15.3		3892 bytes (95.0% Full)
V15.4		3918 bytes (95.7% Full)
V15.5		4044 bytes (98.7% Full)
V15.6		4072 bytes (99.4% Full)
V15.7		4090 bytes (99.9% Full)
V15.8		3984 bytes (97.3% Full)
V15.9		3984 bytes (97.3% Full)
V15.10		4018 bytes (98.1% Full)
V15.11		4094 bytes (100.% Full)
Compiler: WinAVR-20090313
Chip: ATtiny85 (8Kb prom)
V15.12		5112 bytes (62.4% Full)


Fuse bit information:
Fuse high byte:
0xdd = 1 1 0 1   1 1 0 1     RSTDISBL disabled (SPI programming can be done)
0x5d = 0 1 0 1   1 1 0 1     RSTDISBL enabled (PB5 can be used as I/O pin)
       ^ ^ ^ ^   ^ \-+-/ 
       | | | |   |   +------ BODLEVEL 2..0 (brownout trigger level -> 2.7V)
       | | | |   +---------- EESAVE (preserve EEPROM on Chip Erase -> not preserved)
       | | | +-------------- WDTON (watchdog timer always on -> disable)
       | | +---------------- SPIEN (enable serial programming -> enabled)
       | +------------------ DWEN (debug wire enable)
       +-------------------- RSTDISBL (disable external reset -> disabled)

Fuse low byte:
0xe1 = 1 1 1 0   0 0 0 1
       ^ ^ \+/   \--+--/
       | |  |       +------- CKSEL 3..0 (clock selection -> HF PLL)
       | |  +--------------- SUT 1..0 (BOD enabled, fast rising power)
       | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
       +-------------------- CKDIV8 (divide clock by 8 -> don't divide) 


Modifications by Fred Krom, PE0FKO at Nov 2008
- Hang on no pull up of SCL line i2c to Si570 (or power down of Si590 in SR-V90)
- Compiler (WinAVR-20071221) optimized the i2c delay loop a way!
- Calculating the Si570 registers from a given frequency, returns a HIGH HS_DIV value
- Source cleanup and split in deferent files.
- Remove many debug USB command calls!
- Version usbdrv-20081022
- Add command 0x31, write only the Si570 registers (change freq max 3500ppm)
- Change the Si570 register calculation and now use the full 38 bits of the chip!
  Is is accurate, fast and small code! It cost only 350us (old 2ms) to calculate the new registers.
- Add command 0x3d, Read the actual used xtal frequency (4 bytes, 24 bits fraction, 8.24 bits)
- Add the "automatic smooth tune" functionality.
- Add the I/O function command 0x15
- Add the commands 0x34, 0x35, 0x3A, 0x3B, 0x3C, 0x3D
- Add the I/O function command 0x16
- Add read / write Filter cross over points 0x17
- Many code optimalization to make the small code.
- Calculation of the freq from the Si570 registers and call 0x32, command 0x30


Implemented functions:
----------------------

V15.10
+----+---+---+---+-----------------------------------------------------
|Cmd |SQA|FKO| IO| Function
+0x--+---+---+---+-----------------------------------------------------
| 00 | * |   | I | Echo value variable
| 00 |   | * | I | Get Firmware version number
| 01 | * | * | I | [DO NOT USE] set port directions
| 02 | * | * | I | [DO NOT USE] read ports
| 03 | * | * | I | [DO NOT USE] read port states 
| 04 | * | * | I | [DO NOT USE] set ports
| 05 | * |   | I | [DO NOT USE] send I2C start sequence
| 06 | * |   | I | [DO NOT USE] send I2C stop sequence
| 07 | * |   | I | [DO NOT USE] send byte to I2C
| 08 | * |   | I | [DO NOT USE] send word to I2C
| 09 | * |   | I | [DO NOT USE] send dword to I2C
| 0A | * |   | I | [DO NOT USE] send word to I2C with start and stop sequence
| 0B | * |   | I | [DO NOT USE] receive word from I2C with start and stop sequence
| 0C | * |   | I | [DO NOT USE] modify I2C clock
| 0D |   |   | I | [DO NOT USE] read OSCCAL to "value"
| 0E |   |   | I | [DO NOT USE] Write "value" to OSCCAL
| 0F | * | * | I | [DO NOT USE] Reset by Watchdog
| 10 | * |   | I | [DO NOT USE] EEPROM write byte value=address, index=data
| 11 | * |   | I | [DO NOT USE] EEPROM read byte "value"=address
| 13 |   |   | I | [DO NOT USE] return usb device address
| 15 |   | * | I | Set IO port with mask and data bytes, and perform cmd 0x16
| 16 |   | * | I | Return the I/O pin value
| 17 |   | * | I | Read the Filter cross over points and set one point
| 18 |   | * | I | Set the RX Band Pass Filter Address for one band: 0..3
| 19 |   | * | I | Read the RX Band Pass Filter Address for one band: 0..3
| 1A |   |   | I | Set the TX Low Pass Filter Address for one band: 0..7 (MOBO)
| 1B |   |   | I | Read the TX Low Pass Filter Address for one band: 0..7 (MOBO)
| 20 | * | * | I | Write byte to Si570 register
| 21 | * |   | I | [DO NOT USE] SI570: read byte to register index (Use command 0x3F)
| 22 | * |   | I | [DO NOT USE] SI570: freeze NCO (Use command 0x20)
| 23 | * |   | I | [DO NOT USE] SI570: unfreeze NCO (Use command 0x20)
| 30 | * | * | O | Set frequency by register and load Si570
| 31 |   | * | O | Write the frequency subtract multiply to the eeprom
| 32 | * | * | O | Set frequency by value and load Si570
| 33 | * | * | O | write new crystal frequency to EEPROM and use it.
| 34 |   | * | O | Write new startup frequency to eeprom
| 35 |   | * | O | Write new smooth tune to eeprom and use it.
| 39 |   | * | I | Return the frequency subtract multiply
| 3A |   | * | I | Return running frequency
| 3B |   | * | I | Return smooth tune ppm value
| 3C |   | * | I | Return the startup frequency
| 3D |   | * | I | Return the XTal frequency
| 3E |   |   | I | [DEBUG] read out calculated frequency control registers
| 3F | * | * | I | Read out frequency control registers
| 40 | * | * | I | Return I2C transmission error status
| 41 | * |   | I | [DO NOT USE] set/reset init freq status
| 41 |   | * | I | Set the new i2c address.
| 42 |   | * | I | CPU Temperaure
| 43 |   | * | I | Change USB SerialNumber ID
| 50 | * | * | I | Set USR_P1 and get cw-key status
| 51 | * | * | I | Read SDA and CW key level simultaneously


Commands:
---------
All the command are working with the "usb_control_msg" command from the LibUSB open source project.
I'm using "libusb-win32-device-bin-0.1.12.1" from http://sourceforge.net/projects/libusb-win32/

To use the library include the header file ./include/usb.h in your project and add the 
library ./lib/*/libusb.lib for your linker.

Open the device with usb_open(...) with the VID & PID to get a device handle.

  int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
                      int value, int index, char *bytes, int size,
                      int timeout);

    requesttype:    Data In or OUT command (table IO value)
        I = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN
        O = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT

    request: The command number.
    value:   Word parameter 0
    index:   Word parameter 1
    bytes:   Array data send to the device (OUT) or from the device (IN)
    size:    length in bytes of the "bytes" array.


In case of a unknow command the firmware will return a 1 (one) if there is a bytes array specified it 
returns the byte 255.


In the next examples I will use two subroutines that will call the usb_control_msg function, it make's 
the examples more readable:

int usbCtrlMsgIN(int request, int value, int index, char *bytes, int size)
{
  return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
                         request, value, index, bytes, size, 500);
}

int usbCtrlMsgOUT(int request, int value, int index, char *bytes, int size)
{
  return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
                         request, value, index, bytes, size, 500);
}




Command 0x00:
-------------
This call will return the version number of the firmware. The high byte is the version major and the
low byte the version minor number.

It is a bid tricky for the previous versions because they used a "word echo command" on command 0x00.
If the call will be done with the "value" parameter is set to 0x0E00 it will return version 14.0 for the
original DG8SAQ software. (Also my previous software will return the version 14.0, the owner had to
upgrade or not use it). There is also a other way to check the type of software, use the USB Version 
string for that.

Code sample:
    uint16_t version;
    r = usbCtrlMsgIN(0x00, 0x0E00, 0, &version, sizeof(version));
	// if the return value is 2, the variable version will give the major and minor
	// version number in the high and low byte.

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x00
    value:           0x0E00
    index:           0
    bytes:           Version word variable
    size:            2


Command 0x01:
-------------
Set port directions.
Do not use, use I/O function 0x15


Command 0x02:
-------------
Read ports.
Do not use, use I/O function 0x15


Command 0x03:
-------------
Read port states.
Do not use.


Command 0x04:
-------------
Set ports.
In case of the enabled ABPF no change of I/O will be done.
Do not use, use I/O function 0x15


Command 0x0F:
-------------
Restart the board (done by Watchdog timer).

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x0F
    value:           0
    index:           0
    bytes:           NULL
    size:            0


Command 0x15:
-------------
Set the I/O bits of the device. The SoftRock V9 only had two I/O lines, bit0 and bit1.
It also returned the I/O value (like command 0x16).

There are two values for every I/O bit, the data direction and data bits.
+-----+------+----------------------
| DDR | DATA | PIN Function
+-----+------+----------------------
|  0  |   0  | input
|  0  |   1  | input internal pullup
|  1  |   0  | output 0
|  1  |   1  | output 1
+-----+------+----------------------

In case of the enabled ABPF no change of I/O will be done.

Code sample:
    uint16_t INP;
    r = usbCtrlMsgIN(0x15, 0x02, 0x02, &INP, sizeof(INP));
    // Set P2 to output and one!
    // Use P1 as input, no internal pull up R enabled.
    // Read the input in array INP[], only bit0 and bit1 used by this hardware.

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x15
    value:           Data Direction Register
    index:           Data register
    bytes:           PIN status (returned)
    size:            2


Command 0x16:
-------------
Get the I/O values in the returned word, the SoftRock V9 only had two I/O lines, bit0 and bit1.

Code sample:
    uint16_t INP;
    r = usbCtrlMsgIN(0x16, 0, 0, &INP, sizeof(INP));
    // Read the input word INP, only bit0 and bit1 used by SoftRock V9 hardware.

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x16
    value:           0
    index:           0
    bytes:           PIN status (returned)
    size:            2


Command 0x17:
-------------
Read the Filter cross over points and set one point.

This command can control 2 banks of filters.  Typically the first bank is the Rx and Tx BPF
used in the QSD and QSE stages.  The second bank is the Tx LPF between the PA and the antenna
output.  The # of crossover points of the two banks of filters can be different.  For example,
the first bank is usually 4 bands (160m, 80/40m, 30/17/20m, 15/12/10m) as in Softrock v6.3 and
v9.0.  The second bank is usually 6 bands but can go up to 7, 8, 12 or even 16!

The index is used to specify the particular filter crossover point.  The index of the 1st bank
starts from 0, and ends at the last crossover point.  For example, if there are 4 bands, then
there will be 3 crossover points: 0, 1, and 2.  Index 3 is used as a boolean flag, specifying
whether this filter bank is enabled or disabled (for automatic band pass filter ABPF function).

The index of the 2nd filter bank starts from 256, and ends at the last crossover point.  For
example, if there are 6 LPF's, then there will be 5 crossover points, with index 256, 257, 258,
259, and 260.  index 261 is used as a boolean flag, specifying whether this filter bank is
enabled or disabled (for automatic switching).  If "disabled", it usually means the filter is
set for "all pass" or bypassed.

The first call to this command should be used to find out how many crossover points there are.
Call with an index of 255 for the 1st filter bank, and an index of 256+255 for the 2nd filter
bank.

  filter_number_of_bytes = usbCtrlMsgIN(0x17, 0, 255, FilterCrossOver, sizeof(FilterCrossOver));

If there are 4 filters (3 crossover points), then the filter_number_of_bytes returned will be 8.
(Each crossover point is 2 bytes.  Thus there will be 6 bytes.  Following that another 2 bytes will
be for the boolean flag, making a total of 8).

If ther are 6 filters (5 crossover points), there filter_number_of_bytes returned will be 12.

Subsequent calls to this command can then be used to:

1.  set one of the filter crossover points by specifying the index
2.  enable/disable the filter bank by specifying the last index (for the boolean flag)
3.  read the cross over points only - all of them of one bank at once, by specifying 255 (1st bank)
    or 256+255 (2nd bank).

(Note that in actions 1 and 2 above, the cross over points are also read out after the completion
of the action.)

The data format of the crossover points is a 11.5 bits in MHz, that gives a resolution of 1/32 MHz.
The last data entry is a boolean flag to enable or disable the filter bank.

Code sample:
   uint16_t FilterCrossOver[16];        // allocate enough space for up to 16 filters
   unsigned int filter_number_of_bytes;

  // first find out how may cross over points there are for the 1st bank, use 255 for index
  filter_number_of_bytes = usbCtrlMsgIN(0x17, 0, 255, FilterCrossOver, sizeof(FilterCrossOver));

  // Specify filter cross over point for a softrock that divide the LO by 4!
  // And read the points back from the device in the last call.
  if (filter_number_of_bytes == 8)  // 3 crossover points and one flag, so set them up
  {
	FilterCrossOver[0] = 4.1 * 4.0 * (1<<5);
	FilterCrossOver[1] = 8.0 * 4.0 * (1<<5);
	FilterCrossOver[2] = 16. * 4.0 * (1<<5);
	FilterCrossOver[3] = true;        // Enable

	usbCtrlMsgIN(0x17, FilterCrossOver[0], 0, NULL, 0);
	usbCtrlMsgIN(0x17, FilterCrossOver[1], 1, NULL, 0);
	usbCtrlMsgIN(0x17, FilterCrossOver[2], 2, NULL, 0);
	usbCtrlMsgIN(0x17, FilterCrossOver[3], 3, FilterCrossOver, sizeof(FilterCrossOver));
  }


Parameters: Setting one of the points
   requesttype:    USB_ENDPOINT_IN
   request:         0x17
   value:           FilterCrossOver[i]   i being the index of the particular cross over point
   index:           index of the 'value' filter point.
   bytes:           Array of up to 16 16bits integers for the filter points.
   size:            filter_number_of_bytes

Parameters: Enable / disable the filter
   requesttype:    USB_ENDPOINT_IN
   request:         0x17
   value:           0 (disable) or 1 (enable)
   index:           index of 1 plus the last crossover point
   bytes:           Array of up to 16 16bits integers for the filter points.
   size:            filter_number_of_bytes


Command 0x18:
-------------
Set the RX Band Pass Filter Address for one band: 0..3

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x18
    value:           Filter for the band
    index:           Band number (0..3)
    bytes:           pointer 4 byte array, Band2Filter table
    size:            4


Command 0x19:
-------------
Read the RX Band Pass Filter Address for one band: 0..3

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x19
    value:           0
    index:           0
    bytes:           pointer 4 byte array, Band2Filter table
    size:            4


Command 0x1A:
-------------
Set the TX Low Pass Filter Address for one band: 0..7 (MOBO)
Not implemented


Command 0x1B:
-------------
Read the TX Low Pass Filter Address for one band: 0..7 (MOBO)
Not implemented


Command 0x20:
-------------
Write one byte to a Si570 register. Return value is the i2c error boolean in the buffer array.

Code sample:
	// Si570 RECALL function
	uint8_t i2cError;
    r = usbCtrlMsgIN(0x20, 0x55 | (135<<8), 0x01, &i2cError, 1);
	if (r == 1 && i2cError == 0)
		// OK

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x20
    value:           I2C Address low byte (only for the DG8SAQ firmware)
                     Si570 register high byte
    index:           Register value low byte
    bytes:           NULL
    size:            0


Command 0x30:
-------------
Set the oscillator frequency by Si570 register. The real frequency will be 
calculated by the firmware and the called command 0x32

Default:    None

Parameters:
    requesttype:    USB_ENDPOINT_OUT
    request:         0x30
    value:           I2C Address (only for the DG8SAQ firmware), 0
    index:           7 (only for the DG8SAQ firmware), 0
    bytes:           pointer 48 bits register
    size:            6


Command 0x31:
-------------
Write the frequency subtract, multiply value's to the eeprom and use it.

The real frequency is the input frequnecy minus the subtract value times the multiply value.
Si570_F = (Finput - subtract) * multiply


Default:    None

Parameters:
    requesttype:    USB_ENDPOINT_OUT
    request:         0x31
    value:           0
    index:           0
    bytes:           pointer 2 * 32 bits interger
    size:            8

Code sample:
	double sub, mul;
    uint32_t iSM[2];

	sub = 135.0;
	mul = 4.0;

	iSM[0] = (uint32_t)( sub * (1UL << 21) );
	iSM[1] = (uint32_t)( mul * (1UL << 21) );

    r = usbCtrlMsgOUT(0x31, 0, 0, (char *)iSM, sizeof(iSM));
    if (r != sizeof(iSM)) Error



Command 0x32:
-------------
Set the oscillator frequency by value. The frequency is formatted in MHz
as 11.21 bits value. 
The "automatic band pass filter selection", "smooth tune", "one side calibration" and
the "frequency subtract multiply" are all done in this function. (if anabled in the firmware)

Default:    None

Parameters:
    requesttype:    USB_ENDPOINT_OUT
    request:         0x32
    value:           0
    index:           0
    bytes:           pointer 32 bits integer
    size:            4

Code sample:
    uint32_t iFreq;
    double   dFreq;

    dFreq = 30.123456; // MHz
    iFreq = (uint32_t)( dFreq * (1UL << 21) )
    r = usbCtrlMsgOUT(0x32, 0, 0, (char *)&iFreq, sizeof(iFreq));
    if (r < 0) Error


Command 0x33:
-------------
Write new crystal frequency to EEPROM and use it. It can be changed to calibrate the device.
The frequency is formatted in MHz as a 8.24 bits value.

Default:    114.285 MHz

Parameters:
    requesttype:    USB_ENDPOINT_OUT
    request:         0x33
    value:           0
    index:           0
    bytes:           pointer 32 bits integer
    size:            4

Code sample:
    uint32_t iXtalFreq;
    double   dXtalFreq;

    dXtalFreq = 114.281;
    iXtalFreq = (uint32_t)( dXtalFreq * (1UL<<24) )
    r = usbCtrlMsgOUT(0x33, 0, 0, (char *)&iXtalFreq, sizeof(iXtalFreq));
    if (r < 0) Error


Command 0x34:
-------------
Write new startup frequency to eeprom. When the device is started it will output
this frequency until a program set an other frequency.
The frequency is formatted in MHz as a 11.21 bits value.

Default:    4 * 7.050 MHz

Parameters:
    requesttype:    USB_ENDPOINT_OUT
    request:         0x34
    value:           0
    index:           0
    bytes:           pointer 32 bits integer
    size:            4

Code sample:
    uint32_t iXtalFreq;
    double   dXtalFreq;

    dFreq = 4.0 * 3.550; // MHz
    iFreq = (uint32_t)( dFreq * (1UL<<24) )
    r = usbCtrlMsgOUT(0x34, 0, 0, (char *)&iFreq, sizeof(iFreq));
    if (r < 0) Error


Command 0x35:
-------------
Write new smooth tune to eeprom and use it.

Default:    3500 PPM

Parameters:
    requesttype:    USB_ENDPOINT_OUT
    request:         0x35
    value:           0
    index:           0
    bytes:           pointer 16 bits integer
    size:            2

Code sample:
    uint16_t Smooth;
    Smooth = 3400;
    r = usbCtrlMsgOUT(0x35, 0, 0, (char *)&Smooth, sizeof(Smooth));
    if (r < 0) Error


Command 0x39:
-------------
Return the frequency subtract multiply values.
V15.12: The index is tha band for with the values are working.

Default:    subtract = 0.0, multiply = 1.0

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x39
    value:           0
    index:           0	or	Index into band
    bytes:           pointer 2 * 32 bits integer
    size:            8

Code sample:
    uint32_t iSM[2];
	double sub, mul;
	uint8_t iBand;

	iBand = 0;
    r = usbCtrlMsgIN(0x39, 0, iBand, (char *)iSM, sizeof(iSM));
    if (r != sizeof(iSM)) Error

	sub = (double)(int32_t)iSM[0] / (1UL << 21); // Signed value
	mul = (double)         iSM[1] / (1UL << 21);


Command 0x3A:
-------------
Return actual frequency of the device.
The frequency is formatted in MHz as a 11.21 bits value.

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x3A
    value:           0
    index:           0
    bytes:           pointer 32 bits integer
    size:            4

Code sample:
    uint32_t iFreq;
    double   dFreq;
    r = usbCtrlMsgIN(0x3A, 0, 0, (char *)&iFreq, sizeof(iFreq));
    if (r == 4)
        dFreq = (double)iFreq / (1UL<<21);


Command 0x3B:
-------------
Return the "Smooth tune" PPM (pulse per MHz) of the device.
The value is default 3500 (from data sheet) and can be changed. I do not know what 
happened with the chip if it is out of range (>3500).
If the value is set to zero it will disable the "Automatic Smooth tune" function.

Default:    3500 PPM

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x3B
    value:           0
    index:           0
    bytes:           pointer 16 bits integer
    size:            2

Code sample:
    uint16_t Smooth;
    r = usbCtrlMsgIN(0x3B, 0, 0, (char *)&Smooth, sizeof(Smooth));
    if (r == 2) ...


Command 0x3C:
-------------
Return device startup frequency.
The frequency is formatted in MHz as a 11.21 bits value.

Default:    4 * 7.050 MHz

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x3C
    value:           0
    index:           0
    bytes:           pointer 32 bits integer
    size:            4

Code sample:
    uint32_t iFreq;
    double   dFreq;
    r = usbCtrlMsgIN(0x3C, 0, 0, (char *)&iFreq, sizeof(iFreq));
    if (r == 4)
        dFreq = (double)iFreq / (1UL<<21);


Command 0x3D:
-------------
Return device crystal frequency.
The frequency is formatted in MHz as a 8.24 bits value.

Default:    114.285 MHz

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x3D
    value:           0
    index:           0
    bytes:           pointer 32 bits integer
    size:            4

Code sample:
    uint32_t iFreqXtal;
    double   dFreqXtal;
    r = usbCtrlMsgIN(0x3D, 0, 0, (char *)&iFreqXtal, sizeof(iFreqXtal));
    if (r == 4)
        dFreqXtal = (double)iFreqXtal / (1UL<<24);


Command 0x3F:
-------------
Return the Si570 frequency control registers (reg 7 .. 12). If there are I2C errors
the return length is 0.

Default:    None

Parameters:
    requesttype:     USB_ENDPOINT_IN
    request:         0x3F
    value:           0
    index:           0
    bytes:           pointer 6 byte register array
    size:            6


Command 0x41:
-------------
Set a new I2C address for the Si570 chip and return the old I2C address.
If the value is not zero the I2C address will be writen to eeprom and the old value is always returned, 
The function can also be used to reset the device to "factory default" by writing the
value 255. After a restart the device will initialize to all the default values.

Default:    0x55 (85 decimal)

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x41
    value:           I2C address or 255 [byte]
    index:           0
    bytes:           pointer 1 byte I2C address
    size:            1


Command 0x42:
-------------
Get CPU Temperaure from the attiny[48]5

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x42
    value:           0
    index:           0
    bytes:           pointer 2 bytes ADC temperatur value
    size:            2


Command 0x43:
-------------
Set and return the USB SerialNumber ID. The USB SerialNumber "PE0FKO-0" can be changed only for the
last char "0". If the value is not zero the ID char will be writen to eeprom and the old value is always returned, 

Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x43
    value:           New ID char (>0) [byte]
    index:           0
    bytes:           pointer 1 byte ID address
    size:            1


Command 0x50:
-------------
Set PTT (PB4) I/O line and read CW key level from the PB5 (CW Key_1) and PB1 (CW Key_2).
In case of the enabled ABPF no change of PTT I/O line will be done and no read of the CW key's are
done. The command will return (in case of enabled ABPF) for both CW key's a open status (bits are 1).
The returnd bit value is bit 5 (0x20) for CW key_1 and bit 1 (0x02) for CW key_2, the other bits are zero.


Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x50
    value:           Output bool to user output PTT
    index:           0
    bytes:           pointer to 1 byte variable CW Key's
    size:            1


Command 0x51:
-------------
Read CW key level from the PB5 (CW Key_1) and PB1 (CW Key_2).
In case of the enabled ABPF no read of the CW key's are done. The command will return for both CW key's 
a open status (bits are 1).
The returnd bit value is bit 5 (0x20) for CW key_1 and bit 1 (0x02) for CW key_2, the other bits are zero.


Parameters:
    requesttype:    USB_ENDPOINT_IN
    request:         0x51
    value:           0
    index:           0
    bytes:           pointer to 1 byte variable CW Key's
    size:            1


EOF

 

Disclaimer: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

F.W. Krom

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

eXTReMe Tracker