State-Driven Control using a Microchip PIC
App Note AN305B (695 kB, 1 pdf file): State Driven Control using a Microchip PIC
Introduction
When using low-end microcontrollers to configure Okika Technologies’s FPAA devices, it may not be possible to use the algorithmic code generated by DynAMx Design Lab Software (DDLS). This is because the performance may be too slow due to insufficient memory and computing capability. In this case, it is necessary for the user to write his own state-driven code.
The purpose of this document is to describe how to create the code for a simple example of an embedded system consisting of a PIC microcontroller controlling an Okika Technologies’ AN231E04 FPAA. The code described in this document is intended to be very efficient in terms of both memory and speed and is, therefore, suitable for even the simplest of microcontrollers.
The points covered in this document include:
- Creating the primary configuration data
- Writing the code to execute a primary configuration on power up
- Creating the reconfiguration data
- Writing the state-driven reconfiguration code
Writing the Primary Configuration Code
Create the Primary Circuit
|
The first thing to be done is to create the primary circuit, as shown in figure 1. |
![]() |
Create the Primary Configuration Data
Go to the “Dynamic Config.” menu in DDLS and select “State-driven Method.” Under the “States” tab click on “Complete Chips,” Select FPAA1 (or whatever the relevant chip is called) and click “OK.” Select the “Transitions” tab and check the box next to FPAA1 to indicate that this is a primary state. Select “Generation” tab, click on the radio button labeled “Generate C Formatted Configuration Text Files.” Also, click on “All transitions in one file.” Make sure that the destination directory is pointing to the required directory. Now click on the “Generate” button. A warning will come up saying that primary configurations will be generated but transitions will not. Click on “OK.”
A text file will be generated that contains the primary configuration data.
Write the Primary Configuration Code
The code generated above should be copied and pasted into the C-code in the form of an array as shown below. Note that when using more complex microprocessors or a PC, one would not normally copy and paste the array from text files in this way but generate state-driven C-code files and include these DDLS generated files in the project, then reference the arrays and functions in these C-code files. The problem with low-end micros is that some of the functions in the state- driven code may not be compilable for such simple devices. This is why we are writing our own code below:
#define Primary_Config_Size 149
const an_Byte Primary_Data[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, 0xB7, 0x20,
0x01, 0x00, 0x01, 0xC1, 0xC4, 0x00, 0x0E, 0x20,
0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x40, 0x00,
0x00, 0x51, 0xFF, 0x8F, 0xF1, 0x2A, 0xC2, 0x01,
0x01, 0x40, 0x2A, 0xDE, 0x01, 0x02, 0x02, 0xFF,
0x2A, 0xC6, 0x02, 0x01, 0xC0, 0x2A, 0xD6, 0x02,
0x01, 0x08, 0x2A, 0xC4, 0x03, 0x04, 0xFF, 0xFF,
0xFF, 0xFF, 0x2A, 0xD8, 0x03, 0x09, 0x01, 0x13,
0x01, 0x81, 0x01, 0x1C, 0x01, 0x81, 0x0F, 0x2A,
0xD7, 0x04, 0x09, 0x30, 0x00, 0x10, 0x00, 0x05,
0x00, 0xC0, 0x00, 0x10, 0x2A, 0xC0, 0x09, 0x08,
0xEF, 0xEE, 0x02, 0x3C, 0xEA, 0xEA, 0x3B, 0x02,
0x2A, 0xCD, 0x09, 0x14, 0x84, 0x00, 0x00, 0x00,
0x20, 0x00, 0x20, 0x01, 0x12, 0x01, 0x82, 0x00,
0x30, 0x00, 0x10, 0x01, 0x12, 0x01, 0x81, 0x0F,
0x2A, 0x89, 0x0A, 0x17, 0x03, 0x01, 0x00, 0x00,
0x20, 0x00, 0x20, 0x01, 0x31, 0x01, 0x82, 0x00,
0x05, 0x00, 0x30, 0x00, 0x10, 0x00, 0x05, 0x05,
0x15, 0x01, 0x81, 0x2A, 0x00
};
Note the #define at the top that defines the size of the array. This size is six greater than the size given at the top of the text file. This is because six dummy bytes have been added to the data, five at the start and one at the end. Note also that “an_Byte” has been defined earlier in the software as an 8-bit integer using the “typedef” command (see code that accompanies this app note).
Now we have to write the code to send this data to the FPAA. The function below sends a single byte to the FPAA using a simple “bit- banging” technique. Note that the compiler used in this case was CCS. This compiler uses the keyword “int8” to denote an 8-bit integer. Other compilers might use “char” or “unsigned char.”
void Data_Write(int8 data)
{
int8 bit = 8;
while (bit--)
{
if (data & 0x80)
SI_Hig h;
SCLK_Hig h; SCLK_Low
;
SI_Low; data <<= 1;
}
}
Some of the commands in this function have to be defined by the code writer, e.g., SCLK_High. The code that is included with this app note was written for the AN231K04 development board. Refer to this code to see how SCLK_High, SI_High, etc. were defined. These definitions are specific to the hardware so may need to be changed for another board.
The code below does the actual primary configuration.
void Load_Primary_Circuit(void)
{
int8 i;
for (i = 0; i <
Primary_Config_Size; i++) Data_Write(Primary_Data[i]);
}
Writing the Reconfiguration Code
Create the Reconfiguration Data
Go to the “Dynamic Config.” menu in DDLS and select “State-driven Method…”. Under the “States” tab select the primary state FPAA1 and click on “Remove” to delete it, then click on “Parameter Ranges”. Enter a name in the box at the top for the parameter that is to be varied (doesn’t matter what the name is but one must be entered. Now enter 5 into the minimum oscillator frequency box and enter 25 into the maximum box (we will vary the oscillator frequency from 5kHz to 25kHz). Now enter 4 into the number of steps (which means 5 states) and leave type as “Linear steps”. Now press “OK”. Under the “Transitions” tab the various states will be seen. Now select the “Generation” tab and click on “Generate” as before (same settings as before). Again, a text file will be generated but this time it will contain 5 sets of reconfiguration data corresponding to the 5 oscillator frequencies 5, 10, 15, 20, 25kHz. This data is shown below:
/******************************************************************************\
* *
* Transition Configurations *
* *
\******************************************************************************/
/* *\
| f: Fo[5] (15 bytes) |
\* */
0xD5, 0x01, 0xC1, 0x80, 0x09, 0x08, 0xEF, 0xEE,
0x02, 0x3C, 0xEA, 0xEA, 0x3B, 0x02, 0x2A, 0x00
/* *\
| f: Fo[10] (15 bytes) |
\* */
0xD5, 0x01, 0xC1, 0x80, 0x09, 0x08, 0xEE, 0xEE,
0x04, 0x78, 0xAF, 0xAF, 0x58, 0x03, 0x2A, 0x00
/* *\
| f: Fo[15] (15 bytes) |
\* */
0xD5, 0x01, 0xC1, 0x80, 0x09, 0x08, 0xEF, 0xEE,
0x06, 0xB4, 0xC3, 0xC2, 0x93, 0x05, 0x2A, 0x00
/* *\
| f: Fo[20] (15 bytes) |
\* */
0xD5, 0x01, 0xC1, 0x80, 0x09, 0x08, 0xD1, 0xD1,
0x07, 0xD2, 0xEA, 0xEA, 0xEB, 0x08, 0x2A, 0x00
0xD5, 0x01, 0xC1, 0x80, 0x09, 0x08, 0x78, 0x78,
0x05, 0x96, 0xBC, 0xBB, 0xEB, 0x08, 0x2A, 0x00
Write the Reconfiguration Code
There is a lot of repetition in the data generated above, so rather than making 5 arrays of full reconfiguration data we can reduce it to the following functions:
#define UpdateGainSize 11 void Osc_Freq_Reconfig(int8 freq)
{
an_Byte Reconfig_Data[] = {0x80, 0x09, 0x08, 0xEF, 0xEE, 0x02, 0x3C, 0xEA, 0xEA, 0x3B, 0x02};
const an_Byte cap_C1[] = {0xEF, 0xEE, 0xEF, 0xD1, 0x78}; const an_Byte cap_C2[] = {0xEE, 0xEE, 0xEE, 0xD1, 0x78}; const an_Byte cap_C3[] = {0x02, 0x04, 0x06, 0x07, 0x05}; const an_Byte cap_C4[] = {0x3C, 0x78, 0xB4, 0xD2, 0x96}; const an_Byte cap_C5[] = {0xEA, 0xAF, 0xC3, 0xEA, 0xBC}; const an_Byte cap_C6[] = {0xEA, 0xAF, 0xC2, 0xEA, 0xBB}; const an_Byte cap_C7[] =
{0x3B, 0x58, 0x93, 0xEB, 0xEB}; const an_Byte cap_C8[] = {0x02, 0x03, 0x05, 0x08, 0x08};
Reconfig_Data[3] = cap_C1[freq]; Reconfig_Data[4] = cap_C2[freq]; Reconfig_Data[5] = cap_C3[freq]; Reconfig_Data[6] = cap_C4[freq]; Reconfig_Data[7] = cap_C5[freq]; Reconfig_Data[8] = cap_C6[freq]; Reconfig_Data[9] = cap_C7[freq]; Reconfig_Data[10] = cap_C8[freq];
Reconfig(Reconfig_Data, UpdateGainSize);
}
void Reconfig(int8 *array, int8 size)
{
int8 i;
Data_Write(0xD5);Data_Write(0x01);Data_Write(0x05); for (i = 0 ; i < size ; i++) Data_Write(array[i]);Data_Write(0x2A);Data_Write(0x00);
}
Note that instead of writing five different arrays (containing a lot of the same bytes), the code above uses a single array and changes bytes within that array to make the different reconfigurations. This makes the code more efficient, especially when using large numbers of arrays.
The complete code is available with this document. If this code is compiled and loaded into an AN231K04 development board, it should load the primary circuit into the AN231E04 and then reconfigure the oscillator frequency at 1-second intervals.

