ECE-4180 Final Project
Introduction
The AFE4404 is an optical analog front-end developed by Texas Instruments for recording photoplethysmography data. Photoplethysmography is used for blood volume pulse sensing in multiple application areas such as heart-rate monitoring (in fitness monitoring devices like the Fitbit and Apple Watch) and blood oxygen saturation estimation (pulse oximeters).
Some of the features of the AFE4404 are listed below:
- High dynamic range (100 dB)
- Programmable LED current up to 100 mA
- 3 LEDs
- Programmable gain
- I2C interface
- Ambient subtraction at ADC output
The part can be purchased from Digikey. However, the IC comes in a DSBGA package, which makes it inconvenient for breadboard prototyping. Therefore, I placed an order for the board through Proto Advantage in order for them to place the device on a PCB.
The device can be hooked up to the MBED as shown in the figure below.
INP and INM should be connected to the cathode and anode of the photodiode, respectively, while the anode and cathode of the LED should be connected to Tx_SUP and TX_i (where i is 1, 2, or 3), respectively as shown in the schematic above (although I only used channel 2 for my project). Note that the current design requires three power supplies in order to independently turn on the power supplies in the manner specified in the datasheet. Future versions will explore the possibility of implementing a design with single power supply.
The AFE4404 uses an I2C interface for communication. Pull-up resistors are required because internal pull-ups are not provided by the front-end device. The I2C address for the device is the 7-bit representation of 0x58. To read from any register, the register address must be sent, and the REG_READ bit in register 0x00 of the AFE must be set to 1 (for all registers other than the ADC output registers). A repeated start condition (after the register address is sent) is required for reading data from the AFE4404's registers. To write to registers, the REG_READ bit must be set to 0 after sending the registers address. Note that 24-bit data are sent or received during each communication.
Project Demo
The demo code below shows how to instantiate a new AFE_4404 object . First, it creates a thread for initializing and monitoring the HTTP request handler for communicating with the mbed via RPC. The RPC protocol is used to update the AFE's register settings from the GUI (freeing up the virtual COM port for sending PPG data).
Aside
Note that mbed's C# library for making RPC calls to the mbed didn't work, so I had to implement a simple protocol for making RPC calls with HTTP. Because of this limitation, I only setup the GUI to program the current, feedback capacitance, and feedback gain for led2. Future versions will make programming of the AFE's registers via the GUI more robust. Furthermore, I used the ethernet on the mbed for the HTTP requests and setup a network bridge connection between it and my PC. Instructions for connecting mbed's ethernet are provided in the image below and those for setting up a network bridge for Windows 10 can be found in the link below.
http://www.windowscentral.com/how-set-and-manage-network-bridge-connection-windows-10
The main code initializes the AFE with its powerUpSequence method, which initializes the ports, the power supplies, and the AFE4404's registers with values very similar to the typical settings provided in the datasheet, and the clock output. Finally, the getData interrupt service routine (ISR) is associated with the rising edge of the AFE4404's data ready (drdy) pin, and interrupts from that pin are enabled.
The getData ISR disables interrupts on the drdy pin and then reads data from LED2. A two's complement sign extension is performed in order to convert the 24-bit ADC output codes to 32-bit integers. The ISR then sets the dataAvailable variable to true to alert the main code that data is ready for it to send to the PC over the serial port.
It is important to note that while the AFE_4404 constructor requires an argument specifying the MBED's clock output pin to the AFE4404, the current version of the code is hard-coded to output the clock on pin21. This is because the maximum frequency that can be output via the pwn pins (with the mbed APIs) is less than the 4MHz clock required by the AFE. Therefore, I had to set the clock output with the mbed's registers. Future versions of the library will address this issue.
Video
The video below shows the AFE4404 sending LED2 output codes via the serial port.
Import libraryAFE4404
Code for Interfacing with Texas Instruments' AFE4404 IC for photoplethysmography applications
Import programece4180_project
Implementation of AFE4404 in mbed and C#
AFE4404 header
#ifndef AFE_4404_H #define AFE_4404_H #include "mbed.h" #define LOWER_BYTE_MASK 0x000000FF #define SIGN_EXT 0xFF000000 #define SIGN_MASK 0x00800000 #define BITS_PER_BYTE 8 #define NUM_REGISTERS 38 class AFE_4404 { public: AFE_4404(PinName rxSupplyEn, PinName txSupplyEn, PinName resetz, PinName powerEn, PinName drdy, PinName clk, PinName sda, PinName scl); void initPorts(void); void initPowerSupply(void); void initRegisters(void); void initClock(void); void powerUpSequence(void); void inline enableWriteMode(void) { _writeBuffer[0] = 0x00; // AFE register address 0x00 // write 0 to REG_READ bit in register 0x00 to enable readout // of write registers _writeBuffer[1] = 0x00; _writeBuffer[2] = 0x00; _writeBuffer[3] = 0x00; _i2c.write(_address, _writeBuffer, 4); } void inline enableReadMode(void) { _writeBuffer[0] = 0x00; // AFE register address 0x00 // write 1 to REG_READ bit in register 0x00 to enable writes to // write registers _writeBuffer[1] = 0x00; _writeBuffer[2] = 0x00; _writeBuffer[3] = 0x01; _i2c.write(_address, _writeBuffer, 4); } void inline disableIRQ(void) { _drdy.disable_irq(); } void inline enableIRQ(void) { _drdy.enable_irq(); } void getData(void); void writeData(uint8_t reg, uint32_t data); uint32_t readData(uint8_t reg, bool adc); private: DigitalOut _rxSupplyEn; DigitalOut _txSupplyEn; DigitalOut _resetz; DigitalOut _powerEn; InterruptIn _drdy; PwmOut _clk; I2C _i2c; int _address; char _writeBuffer[5]; char _readBuffer[5]; // temporary variable to prevent multiple allocations uint32_t _tempData; }; #endif
AFE4404 Implementatopn (.cpp file)
#include "mbed.h" #include "AFE_4404.h" char LED = 0x2A; // LED2 on AFE4404 int32_t data; volatile bool dataAvailable = false; AFE_4404::AFE_4404(PinName rxSupplyEn, PinName txSupplyEn, PinName resetz, PinName powerEn, PinName drdy, PinName clk, PinName sda, PinName scl): _rxSupplyEn(rxSupplyEn), _txSupplyEn(txSupplyEn), _resetz(resetz), _powerEn(powerEn), _drdy(drdy), _clk(clk), _i2c(sda, scl) { // inputs: // rxSupplyEn, txSuppyEn, and powerEn: digital outputs (active low) used to // turn on the power supplies in the manner described in the datasheet // resetz: used to reset the AFE after power up (active low) // drdy: interrupt from AFE when data is ready // clk: pwm output at ~ 4.1MHz // sda, scl: I2C data and clock, respectively; // shift by 1 for 8-bit representation of 7-bit address _address = (0x58 << 1); } void AFE_4404::initPorts(void) { // turn off power supplies _rxSupplyEn = 0; _txSupplyEn = 0; _powerEn = 0; // resetz is active low, so leave on before power supply init _resetz = 1; // set the clock output to zero before power-up sequence // this convoluted method was required because of the way the the PWM // output is set up (faster that possible with the MBED APIs) _clk.period(10); _clk.write(0); disableIRQ(); } void AFE_4404::initPowerSupply(void) { wait_ms(100); _powerEn = 1; wait_ms(100); _rxSupplyEn = 1; wait_ms(10); _txSupplyEn = 1; wait_ms(20); _resetz = 0; wait_us(35); _resetz = 1; initClock(); wait_ms(2); } uint32_t AFE_4404::readData(uint8_t reg, bool adc = true) { if (!adc) { enableReadMode(); } _writeBuffer[0] = reg; // initialize write buffer with AFE register address // initialize read buffers to 0. probably unnecessary _readBuffer[0] = 0x00; _readBuffer[1] = 0x00; _readBuffer[2] = 0x00; // write the register to AFE and use repeated start mode as specified in // the datasheet _i2c.write(_address, _writeBuffer, 1, true); // read 3 bytes of data from register MSB first _i2c.read(_address, _readBuffer, 3); _tempData = 0; _tempData = (_readBuffer[0] << (BITS_PER_BYTE * 2)) | \ (_readBuffer[1] << BITS_PER_BYTE) | _readBuffer[2]; if (adc && (SIGN_MASK & _tempData)) { _tempData |= SIGN_EXT; } return _tempData; } void AFE_4404::writeData(uint8_t reg, uint32_t data) { enableWriteMode(); _writeBuffer[0] = reg; // store the lower 3 bytes of data in _writeBuffer (MSB first) for (int i = 2, j = 1; i >= 0; i--, j++) { _writeBuffer[j] = (data >> (BITS_PER_BYTE * i)) & LOWER_BYTE_MASK; } // write 4 bytes // 1 for the register address and 3 for the lower 3 bytes of data _i2c.write(_address, _writeBuffer, 4); } struct Register { uint8_t addr; uint32_t val; }; void AFE_4404::initRegisters(void) { unsigned char i; struct Register reg[NUM_REGISTERS]; reg[0].addr = 0x01; reg[0].val = 0x000050; reg[1].addr = 0x02; reg[1].val = 0x00018F; reg[2].addr = 0x03; reg[2].val = 0x000320; reg[3].addr = 0x04; reg[3].val = 0x0004AF; reg[4].addr = 0x05; reg[4].val = 0x0001E0; reg[5].addr = 0x06; reg[5].val = 0x00031F; reg[6].addr = 0x07; reg[6].val = 0x000370; reg[7].addr = 0x08; reg[7].val = 0x0004AF; reg[8].addr = 0x09; reg[8].val = 0x000000; reg[9].addr = 0x0A; reg[9].val = 0x00018F; reg[10].addr = 0x0B; reg[10].val = 0x0004FF; reg[11].addr = 0x0C; reg[11].val = 0x00063E; reg[12].addr = 0x0D; reg[12].val = 0x000198; reg[13].addr = 0x0E; reg[13].val = 0x0005BB; reg[14].addr = 0x0F; reg[14].val = 0x0005C4; reg[15].addr = 0x10; reg[15].val = 0x0009E7; reg[16].addr = 0x11; reg[16].val = 0x0009F0; reg[17].addr = 0x12; reg[17].val = 0x000E13; reg[18].addr = 0x13; reg[18].val = 0x000E1C; reg[19].addr = 0x14; reg[19].val = 0x00123F; reg[20].addr = 0x15; reg[20].val = 0x000191; reg[21].addr = 0x16; reg[21].val = 0x000197; reg[22].addr = 0x17; reg[22].val = 0x0005BD; reg[23].addr = 0x18; reg[23].val = 0x0005C3; reg[24].addr = 0x19; reg[24].val = 0x0009E9; reg[25].addr = 0x1A; reg[25].val = 0x0009EF; reg[26].addr = 0x1B; reg[26].val = 0x000E15; reg[27].addr = 0x1C; reg[27].val = 0x000E1B; reg[28].addr = 0x1D; reg[28].val = 0x009C3F; reg[29].addr = 0x1E; reg[29].val = 0x000103; reg[30].addr = 0x20; reg[30].val = 0x008003; reg[31].addr = 0x21; reg[31].val = 0x000003; reg[32].addr = 0x22; reg[32].val = 0x000400; reg[33].addr = 0x23; reg[33].val = 0x000000; reg[34].addr = 0x32; reg[34].val = 0x00155F; reg[35].addr = 0x33; reg[35].val = 0x00991F; reg[36].addr = 0x36; reg[36].val = 0x000190; reg[37].addr = 0x37; reg[37].val = 0x00031F; for (i = 0; i < NUM_REGISTERS; i++) writeData(reg[i].addr, reg[i].val); } void AFE_4404::initClock(void) { LPC_PWM1->TCR = (1 << 1); // Reset counter, disable PWM LPC_SC->PCLKSEL0 &= ~(0x3 << 12); LPC_SC->PCLKSEL0 |= (1 << 12); // Set peripheral clock divider to /1, i.e. system clock LPC_PWM1->MR0 = 22; // Match Register 0 is shared period counter for all PWM1 LPC_PWM1->MR6 = 11; // Pin 21 is PWM output 6, so Match Register 6 LPC_PWM1->LER |= 1; // Start updating at next period start LPC_PWM1->TCR = (1 << 0) || (1 << 3); // Enable counter and PWM } void AFE_4404::powerUpSequence(void) { initPorts(); initPowerSupply(); initRegisters(); initClock(); _drdy.rise(this, &AFE_4404::getData); enableIRQ(); } void AFE_4404::getData(void) { disableIRQ(); data = static_cast<int32_t> (readData(LED, true)); dataAvailable = true; enableIRQ(); }
Demo Code
main demo code
#include "mbed.h" #include "EthernetInterface.h" #include "HTTPServer.h" #include "mbed_rpc.h" #include "RPCFunction.h" #include "AFE_4404.h" EthernetInterface eth; HTTPServer svr; int baudRate = 115200; Serial pc(USBTX, USBRX); extern int32_t data; extern bool dataAvailable; // p22: rxSupplyEn, p8: txSupplyEn, p6: resetz, p7: powerEn, // p5: drdy, p21: clk, p9: sda, p10: scl AFE_4404 afe(p22, p8, p6, p7, p5, p21, p9, p10); Thread rpcThread; //automatically lock rpcBusy when it's been used volatile bool rpcBusy = true; void afeRpc(Arguments *input, Reply *output); RPCFunction afeRpcFunction(&afeRpc, "afe"); void afeRpc(Arguments *input, Reply *output){ int32_t registerAddress; int32_t registerData; int32_t suspend; // prevents main from writing to data if it's 1 // prevent main loop from writing data to serial rpcBusy = true; Thread::wait(100); registerAddress = input->getArg<int32_t>(); registerData = input->getArg<int32_t>(); suspend = input->getArg<int32_t>(); // write data to afe register afe.writeData( static_cast<uint8_t>(registerAddress), static_cast<uint32_t>(registerData)); output->putData(registerAddress); output->putData(registerData); // suspend serial writes in main loop. functionality isn't currently // being used, so rpcBusy is always false in current C# GUI version rpcBusy = (suspend == 1) ? true : false; } void rpcThreadRoutine() { printf("Setting up...\n"); eth.init(); // wait for a while because the initialization doesn't work without the delay // maybe the initialization is done asynchronously?? wait(10.0); int ethErr = eth.connect(); if(ethErr < 0) printf("Error %d in setup.\n", ethErr); svr.addHandler<HTTPRpcRequestHandler>("/rpc"); //attach server to port 80 svr.start(80, ð); // gives enough time to pause terminal application to obtain IP address Thread::wait(2000); printf("Listening...\n"); rpcBusy = false; //Listen indefinitely while(true) { svr.poll(); Thread::wait(1000); } } int main() { pc.baud(baudRate); rpcThread.start(rpcThreadRoutine); // spin until RPC is setup while(rpcBusy) {} afe.powerUpSequence(); while(true){ if(dataAvailable && !rpcBusy) { pc.printf("%d ", data); dataAvailable = false; } } }
C# GUI Code All Implemented by Me
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using System.IO.Ports; using System.Net; using System.Diagnostics; namespace AFE4404 { public partial class Form1 : Form { // parts of the data may be incomplete numbers, i.e., there's no delimiter after it // use partialNumber to store the incomplete number and concatenate with next incomplete // (but delimited) number read from serial port private string partialNumber = ""; // stores the number of available data (after accounting for incomplete numbers) private int validLength; // is split to obtain data private string dataString; // stores valid data obtained from dataString private string[] dataArray; private SerialPort serial; // serial data is read with interrupt driven I/O, so waitSerialData is used to // signal the background thread to read the data (background thread blocks until data // is available private AutoResetEvent waitSerialData; // background thread that reads and plots data on GUI private Thread serialThread; private int end = 0; // actual data is 22 bits (with 2's complement sign extension) representing // range [-1, 1] private double codeScale = Math.Pow(2, 21); // array that's used to store data to plot private double[] chartData = new double[400]; // adds raw data to list so that it can be exported as .csv private List<string> chartDataList = new List<string>(); // preallocate comma used for storing chartDataList in .csv byte comma = (byte)','; // min and max of data to plot private double min; private double max; // add's padding to the min and max (only currently works for strictly positive // data. will make modifications to account for negative (and 0) data later private double axisScaling = 0.02; // update axis after number of chart updates (keeps the plot axis from being jerky) private int axisUpdateDelay = 0; private string comPort = "COM4"; private int baudRate = 115200; private string mbedHostName = "http://128.61.33.139"; private string mbedRpcFunction = "afe"; // do not modify. I was supposed to use it for a different unimplemented functionality string url; // full url for rpc get request will be formed durin runtime int suspendMbedMain = 0; public Form1() { InitializeComponent(); baudRateComboBox.Text = baudRate.ToString(); comPortComboBox.Text = comPort.ToString(); chart1.ChartAreas[0].AxisY.LabelStyle.Format = "{0:0.000}"; led2CurrentNumericUpDown.DecimalPlaces = 1; // display led currents to 1 decimal place } private void Start_Click(object sender, EventArgs e) { if (serialThread != null && serialThread.IsAlive) { // end serial data connection if it already exists // change color/enable controls serialThread.Abort(); Start.Text = "Start"; Start.BackColor = Color.YellowGreen; Save.Enabled = true; Save.BackColor = Color.DarkGray; comPortComboBox.Enabled = true; comPortComboBox.BackColor = Color.DarkGray; baudRateComboBox.Enabled = true; baudRateComboBox.BackColor = Color.DarkGray; } else { // create a new thread for processing serial data in the background serialThread = new Thread(() => serialThreadRoutine()); serialThread.Start(); // disable controls and also update text and colors of controls Start.Text = "Stop"; Start.BackColor = Color.Red; Save.Enabled = false; // cannot save data in list if chart is updating Save.BackColor = Color.LightGray; comPortComboBox.Enabled = false; comPortComboBox.BackColor = Color.LightGray; baudRateComboBox.Enabled = false; baudRateComboBox.BackColor = Color.LightGray; } } public void serialThreadRoutine() { // create new event to alert thread that data is available waitSerialData = new AutoResetEvent(false); try { setupSerialPort(); serial.Open(); serial.DiscardInBuffer(); partialNumber = ""; while (true) { // wait for condition signal and process serial data once it receives // a signal that serial data is available waitSerialData.WaitOne(); Invoke((MethodInvoker)delegate { process(); }); } } finally { serial.Close(); } } public void setupSerialPort() { serial = new SerialPort(comPort); serial.BaudRate = baudRate; serial.Parity = Parity.None; serial.StopBits = StopBits.One; serial.DataBits = 8; serial.Handshake = Handshake.None; serial.DataReceived += dataReceivedHandler; } public void dataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { // all interrupt service routine for serial does is alert background thread that // serial data is available waitSerialData.Set(); } public void process() { if (serial.IsOpen) { dataString = serial.ReadExisting(); // concatenate partially formed number from previous serial data to new data // received from serial port dataString = (partialNumber == "") ? dataString : partialNumber + dataString; // break up serial data into array. space is used as delimiter dataArray = dataString.Split((char[])null, StringSplitOptions.RemoveEmptyEntries); // this condition may lead to occasional incorrect samples. I still need to debug to verify if (dataArray.Length > 0) { // store last number if it wasn't delimited partialNumber = (dataString.Last() == ' ') ? "" : dataArray.Last(); // don't plot/store the last number if it wasn't delimited validLength = (partialNumber == "") ? dataArray.Length : dataArray.Length - 1; // the following code segment is inefficient and will be improved later to remove // the redundant array copy. this can be done by directly writing to chartDataList // and updating the chart directly with chartDataList // ************************************************************************************ end = chartData.Length - validLength; Array.Copy(chartData, validLength, chartData, 0, end); for (int i = 0; i < validLength; i++) { chartData[end++] = Int32.Parse(dataArray[i]) / codeScale; chartDataList.Add(dataArray[i]); } chart1.Series["Series1"].Points.Clear(); min = 10e7; max = 0; for (int i = 0; i < chartData.Length; i++) { chart1.Series["Series1"].Points.AddY(chartData[i]); min = (chartData[i] < min) ? chartData[i] : min; max = (chartData[i] > max) ? chartData[i] : max; } // ************************************************************************************ // update axis range only after N number of chart updates if (axisUpdateDelay > 0) { axisUpdateDelay--; } else { // change the axis range (include padding) chart1.ChartAreas[0].AxisY.Minimum = min - axisScaling * min; chart1.ChartAreas[0].AxisY.Maximum = max + axisScaling * max; // reset number of char updates before axis rescaling axisUpdateDelay = 100; } } } } private void Save_Click(object sender, EventArgs e) { // save to .csv file // code found online Stream myStream = null; SaveFileDialog saveFileDialog1 = new SaveFileDialog(); // set initial save directory to two directories above the current one saveFileDialog1.InitialDirectory = Path.GetFullPath(".." + ".."); saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"; saveFileDialog1.FilterIndex = 2; saveFileDialog1.RestoreDirectory = true; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { try { if ((myStream = saveFileDialog1.OpenFile()) != null) { using (myStream) { foreach (string value in chartDataList) { byte[] data = new UTF8Encoding(true).GetBytes(value); myStream.Write(data, 0, data.Length); myStream.Write(new byte[] { comma }, 0, 1); } } } } catch (Exception ex) { MessageBox.Show("Error: Could not write file to disk:\nOriginal error: " + ex.Message); } } } private void refreshComButton_Click(object sender, EventArgs e) { foreach (string str in SerialPort.GetPortNames()) { if ( !comPortComboBox.Items.Contains(str) ) comPortComboBox.Items.Add(str); } } private void comPortComboBox_SelectedIndexChanged(object sender, EventArgs e) { Object selectedItem = comPortComboBox.SelectedItem; comPort = selectedItem.ToString(); } private void baudRateComboBox_SelectedIndexChanged(object sender, EventArgs e) { Object selectedItem = baudRateComboBox.SelectedItem; baudRate = int.Parse(selectedItem.ToString()); } private void updateRegistersButton_Click(object sender, EventArgs e) { // be sure to select current, gain, and capacitance if you're updating the registers // because the current implementation sets default values for all of them. // I don't have time to make it more configurable right now, but I'll do so later // AFE register for modifying led2 current int led2RegAddress = 0x22; // AFE register for modifying gain and feedback capacitance of led2 channel int gainRegAddress = 0x21; double led2Value = Convert.ToDouble(led2CurrentNumericUpDown.Value); // add epsilon to led2 value because of floating point issues int led2Index = (int) ((led2Value + 0.01) / 0.8); int ledRegValue = 0; // 3 bit led2 current control start at bit 6 ledRegValue |= (led2Index << 6); int gainsRegValue = 0; if (tiaCapComboBox != null) gainsRegValue |= (tiaCapComboBox.SelectedIndex << 3); if (tiaGainComboBox.SelectedItem != null) gainsRegValue |= tiaGainComboBox.SelectedIndex; // make RPC call to change led2 current url = getURL(led2RegAddress, ledRegValue); Invoke((MethodInvoker)delegate { makeHttpRPCRequest(url); }); // make RPC call to modify led2 gain and capacitance url = getURL(gainRegAddress, gainsRegValue); Invoke((MethodInvoker)delegate { makeHttpRPCRequest(url); }); } private string getURL(int regAddress, int regValue) { return string.Format( mbedHostName + "/rpc/" + mbedRpcFunction + "/run%20{0}%20{1}%20{2}", regAddress, regValue, suspendMbedMain); } private void makeHttpRPCRequest(string url) { // code found online for making HTTP get requests string html = string.Empty; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.AutomaticDecompression = DecompressionMethods.GZip; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { html = reader.ReadToEnd(); } } } }
C# Code Mostly Auto-generated by VisualStudio Enterprise 2015 (with a few modifications by me)
namespace AFE4404 { partial class Form1 { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea3 = new System.Windows.Forms.DataVisualization.Charting.ChartArea(); System.Windows.Forms.DataVisualization.Charting.Legend legend3 = new System.Windows.Forms.DataVisualization.Charting.Legend(); System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.Start = new System.Windows.Forms.Button(); this.chart1 = new System.Windows.Forms.DataVisualization.Charting.Chart(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.label2 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); this.baudRateComboBox = new System.Windows.Forms.ComboBox(); this.Save = new System.Windows.Forms.Button(); this.comPortComboBox = new System.Windows.Forms.ComboBox(); this.tabPage3 = new System.Windows.Forms.TabPage(); this.led2CurrentLabel = new System.Windows.Forms.Label(); this.led2CurrentNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.updateRegistersButton = new System.Windows.Forms.Button(); this.tiaGainComboBox = new System.Windows.Forms.ComboBox(); this.tiaGainLabel = new System.Windows.Forms.Label(); this.tiaCapComboBox = new System.Windows.Forms.ComboBox(); this.tiaCapLabel = new System.Windows.Forms.Label(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.chart1)).BeginInit(); this.tabPage2.SuspendLayout(); this.tabPage3.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.led2CurrentNumericUpDown)).BeginInit(); this.SuspendLayout(); // // tabControl1 // this.tabControl1.Appearance = System.Windows.Forms.TabAppearance.Buttons; this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Controls.Add(this.tabPage3); this.tabControl1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.tabControl1.Location = new System.Drawing.Point(2, 37); this.tabControl1.Margin = new System.Windows.Forms.Padding(2); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(736, 600); this.tabControl1.TabIndex = 0; // // tabPage1 // this.tabPage1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.tabPage1.Controls.Add(this.Start); this.tabPage1.Controls.Add(this.chart1); this.tabPage1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.tabPage1.ForeColor = System.Drawing.Color.Blue; this.tabPage1.Location = new System.Drawing.Point(4, 32); this.tabPage1.Margin = new System.Windows.Forms.Padding(2); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(2); this.tabPage1.Size = new System.Drawing.Size(728, 564); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "Chart"; this.tabPage1.UseVisualStyleBackColor = true; // // Start // this.Start.BackColor = System.Drawing.Color.YellowGreen; this.Start.ForeColor = System.Drawing.Color.Black; this.Start.Location = new System.Drawing.Point(638, 241); this.Start.Margin = new System.Windows.Forms.Padding(2); this.Start.Name = "Start"; this.Start.Size = new System.Drawing.Size(85, 58); this.Start.TabIndex = 1; this.Start.Text = "Start"; this.Start.UseVisualStyleBackColor = false; this.Start.Click += new System.EventHandler(this.Start_Click); // // chart1 // chartArea3.Name = "ChartArea1"; this.chart1.ChartAreas.Add(chartArea3); legend3.Enabled = false; legend3.Name = "Legend1"; this.chart1.Legends.Add(legend3); this.chart1.Location = new System.Drawing.Point(4, 9); this.chart1.Margin = new System.Windows.Forms.Padding(2); this.chart1.Name = "chart1"; series3.ChartArea = "ChartArea1"; series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Spline; series3.Legend = "Legend1"; series3.Name = "Series1"; this.chart1.Series.Add(series3); this.chart1.Size = new System.Drawing.Size(635, 559); this.chart1.TabIndex = 0; this.chart1.Text = "chart1"; // // tabPage2 // this.tabPage2.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.tabPage2.Controls.Add(this.label2); this.tabPage2.Controls.Add(this.label1); this.tabPage2.Controls.Add(this.baudRateComboBox); this.tabPage2.Controls.Add(this.Save); this.tabPage2.Controls.Add(this.comPortComboBox); this.tabPage2.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.tabPage2.ForeColor = System.Drawing.SystemColors.Desktop; this.tabPage2.Location = new System.Drawing.Point(4, 32); this.tabPage2.Margin = new System.Windows.Forms.Padding(2); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(2); this.tabPage2.Size = new System.Drawing.Size(728, 564); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Settings"; this.tabPage2.UseVisualStyleBackColor = true; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(2, 133); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(86, 20); this.label2.TabIndex = 4; this.label2.Text = "Baud Rate"; // // label1 // this.label1.AutoSize = true; this.label1.ForeColor = System.Drawing.Color.Black; this.label1.Location = new System.Drawing.Point(5, 18); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(153, 20); this.label1.TabIndex = 3; this.label1.Text = "Available COM Ports"; // // baudRateComboBox // this.baudRateComboBox.FormattingEnabled = true; this.baudRateComboBox.Items.AddRange(new object[] { 9600, 115200}); this.baudRateComboBox.Location = new System.Drawing.Point(4, 159); this.baudRateComboBox.Margin = new System.Windows.Forms.Padding(2); this.baudRateComboBox.Name = "baudRateComboBox"; this.baudRateComboBox.Size = new System.Drawing.Size(134, 28); this.baudRateComboBox.TabIndex = 2; this.baudRateComboBox.SelectedIndexChanged += new System.EventHandler(this.baudRateComboBox_SelectedIndexChanged); // // Save // this.Save.Location = new System.Drawing.Point(4, 267); this.Save.Margin = new System.Windows.Forms.Padding(2); this.Save.Name = "Save"; this.Save.Size = new System.Drawing.Size(134, 27); this.Save.TabIndex = 1; this.Save.Text = "Save Data"; this.Save.UseVisualStyleBackColor = true; this.Save.Click += new System.EventHandler(this.Save_Click); // // comPortComboBox // this.comPortComboBox.FormattingEnabled = true; this.comPortComboBox.Location = new System.Drawing.Point(6, 46); this.comPortComboBox.Margin = new System.Windows.Forms.Padding(2); this.comPortComboBox.Name = "comPortComboBox"; this.comPortComboBox.Size = new System.Drawing.Size(136, 28); this.comPortComboBox.Sorted = true; this.comPortComboBox.TabIndex = 0; this.comPortComboBox.DropDown += new System.EventHandler(this.refreshComButton_Click); this.comPortComboBox.SelectedIndexChanged += new System.EventHandler(this.comPortComboBox_SelectedIndexChanged); // // tabPage3 // this.tabPage3.Controls.Add(this.tiaCapLabel); this.tabPage3.Controls.Add(this.tiaCapComboBox); this.tabPage3.Controls.Add(this.tiaGainLabel); this.tabPage3.Controls.Add(this.tiaGainComboBox); this.tabPage3.Controls.Add(this.led2CurrentLabel); this.tabPage3.Controls.Add(this.led2CurrentNumericUpDown); this.tabPage3.Controls.Add(this.updateRegistersButton); this.tabPage3.Location = new System.Drawing.Point(4, 32); this.tabPage3.Name = "tabPage3"; this.tabPage3.Padding = new System.Windows.Forms.Padding(3); this.tabPage3.Size = new System.Drawing.Size(728, 564); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "AFE Registers"; this.tabPage3.UseVisualStyleBackColor = true; // // led2CurrentLabel // this.led2CurrentLabel.AutoSize = true; this.led2CurrentLabel.Location = new System.Drawing.Point(4, 54); this.led2CurrentLabel.Name = "led2CurrentLabel"; this.led2CurrentLabel.Size = new System.Drawing.Size(145, 20); this.led2CurrentLabel.TabIndex = 3; this.led2CurrentLabel.Text = "LED2 Current (mA)"; // // led2CurrentNumericUpDown // this.led2CurrentNumericUpDown.Increment = new decimal(new int[] { 8, 0, 0, 65536}); this.led2CurrentNumericUpDown.Location = new System.Drawing.Point(15, 79); this.led2CurrentNumericUpDown.Maximum = new decimal(new int[] { 50, 0, 0, 0}); this.led2CurrentNumericUpDown.Name = "led2CurrentNumericUpDown"; this.led2CurrentNumericUpDown.Size = new System.Drawing.Size(120, 26); this.led2CurrentNumericUpDown.TabIndex = 2; // // updateRegistersButton // this.updateRegistersButton.Location = new System.Drawing.Point(284, 144); this.updateRegistersButton.Name = "updateRegistersButton"; this.updateRegistersButton.Size = new System.Drawing.Size(151, 30); this.updateRegistersButton.TabIndex = 1; this.updateRegistersButton.Text = "Update Registers"; this.updateRegistersButton.UseVisualStyleBackColor = true; this.updateRegistersButton.Click += new System.EventHandler(this.updateRegistersButton_Click); // // tiaGainComboBox // this.tiaGainComboBox.FormattingEnabled = true; this.tiaGainComboBox.Items.AddRange(new object[] { "500 K", "250 K", "100 K", "50 K", "25 K", "10 K", "1 M", "2 M"}); this.tiaGainComboBox.Location = new System.Drawing.Point(298, 79); this.tiaGainComboBox.Name = "tiaGainComboBox"; this.tiaGainComboBox.Size = new System.Drawing.Size(121, 28); this.tiaGainComboBox.TabIndex = 4; // // tiaGainLabel // this.tiaGainLabel.AutoSize = true; this.tiaGainLabel.Location = new System.Drawing.Point(321, 56); this.tiaGainLabel.Name = "tiaGainLabel"; this.tiaGainLabel.Size = new System.Drawing.Size(72, 20); this.tiaGainLabel.TabIndex = 5; this.tiaGainLabel.Text = "TIA Gain"; // // tiaCapComboBox // this.tiaCapComboBox.FormattingEnabled = true; this.tiaCapComboBox.Items.AddRange(new object[] { "5 pF", "2.5 pF", "10 pF", "7.5 pF", "20 pF", "17.5 pF", "25 pF", "22.5 pF"}); this.tiaCapComboBox.Location = new System.Drawing.Point(588, 79); this.tiaCapComboBox.Name = "tiaCapComboBox"; this.tiaCapComboBox.Size = new System.Drawing.Size(121, 28); this.tiaCapComboBox.TabIndex = 1; // // tiaCapLabel // this.tiaCapLabel.AutoSize = true; this.tiaCapLabel.Location = new System.Drawing.Point(582, 54); this.tiaCapLabel.Name = "tiaCapLabel"; this.tiaCapLabel.Size = new System.Drawing.Size(127, 20); this.tiaCapLabel.TabIndex = 6; this.tiaCapLabel.Text = "TIA Capacitance"; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(741, 648); this.Controls.Add(this.tabControl1); this.ForeColor = System.Drawing.SystemColors.Desktop; this.Margin = new System.Windows.Forms.Padding(2); this.Name = "Form1"; this.Text = "AFE4404"; this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.chart1)).EndInit(); this.tabPage2.ResumeLayout(false); this.tabPage2.PerformLayout(); this.tabPage3.ResumeLayout(false); this.tabPage3.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.led2CurrentNumericUpDown)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.DataVisualization.Charting.Chart chart1; private System.Windows.Forms.ComboBox comPortComboBox; private System.Windows.Forms.Button Start; private System.Windows.Forms.Button Save; private System.Windows.Forms.ComboBox baudRateComboBox; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label1; private System.Windows.Forms.TabPage tabPage3; private System.Windows.Forms.NumericUpDown led2CurrentNumericUpDown; private System.Windows.Forms.Button updateRegistersButton; private System.Windows.Forms.Label led2CurrentLabel; private System.Windows.Forms.Label tiaGainLabel; private System.Windows.Forms.ComboBox tiaGainComboBox; private System.Windows.Forms.Label tiaCapLabel; private System.Windows.Forms.ComboBox tiaCapComboBox; } }
Please log in to post comments.