repo time
Dependencies: mbed MAX14720 MAX30205 USBDevice
Diff: HspGuiSourceV301/HSPGui/CustomControls/RegisterView.cs
- Revision:
- 20:6d2af70c92ab
diff -r 002c398f14cc -r 6d2af70c92ab HspGuiSourceV301/HSPGui/CustomControls/RegisterView.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HspGuiSourceV301/HSPGui/CustomControls/RegisterView.cs Tue Apr 06 06:41:40 2021 +0000 @@ -0,0 +1,765 @@ +/******************************************************************************* +* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved. +* +* This software is protected by copyright laws of the United States and +* of foreign countries. This material may also be protected by patent laws +* and technology transfer regulations of the United States and of foreign +* countries. This software is furnished under a license agreement and/or a +* nondisclosure agreement and may only be used or reproduced in accordance +* with the terms of those agreements. Dissemination of this information to +* any party or parties not specified in the license agreement and/or +* nondisclosure agreement is expressly prohibited. +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* 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 MAXIM INTEGRATED 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. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +******************************************************************************* +*/ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using System.IO; + +using HealthSensorPlatform.DeviceDescriptions; +using HealthSensorPlatform.CustomControls; +using RPCSupport.DeviceSupport; +//using Maxim.MAX30101GUI.DeviceDescriptions; +//using Maxim.MAX30101; + +namespace Maxim.CustomControls +{ + public partial class RegisterView : UserControl, IDeviceView + { + private bool connected = false; + public bool Connected + { + get + { + return connected; + } + set + { + connected = value; + } + } + + public string DeviceName; + + public DeviceController Controller + { + get { return controller; } + } + private DeviceController controller; + + + /// <summary> + /// Value of current selected register + /// </summary> + int RegisterValue; + + Label[] bitLabels = new Label[24]; + + Font RegularFont; + Font BoldFont; + + public event RegisterWriteCompleteHandler RegisterWriteComplete; + public delegate void RegisterWriteCompleteHandler(object sender, RegisterArgs e); + + public event CellBeginEditHandler CellBeginEdit; + public delegate void CellBeginEditHandler(object sender, DataGridViewCellCancelEventArgs e); + + public RegisterView() + { + //accelDevice = new AccelDevice(); + InitializeComponent(); + + // Initialize font styles for label + RegularFont = new Font(lblBit00.Font, FontStyle.Regular); + BoldFont = new Font(lblBit00.Font, FontStyle.Bold); + + // References to all bit labels + for(int i = 0; i < 24; i++) + { + string labelName = "lblBit" + i.ToString("D2"); + bitLabels[i] = (Label)panelRegisterBits.Controls[labelName]; + } + + dgv_Registers.CellBeginEdit += OnCellBeginEdit; // Pass thru event + dgv_Registers.SelectionChanged += dgv_Registers_SelectionChanged; + dgv_Registers.CellEndEdit += dgv_Registers_CellEndEdit; + } + + public void SetController(DeviceController controller) + { + Clear(); + this.controller = controller; + } + + /// <summary> + /// RegisterInfo register value to string + /// </summary> + /// <param name="reg"></param> + /// <returns></returns> + private string FormatData(RegisterInfo reg) + { + return reg.dataField.ToString("X" + (reg.numBytes * 2).ToString()); + } + + /// <summary> + /// Populate register tables + /// </summary> + public void DisplayRegisters() + { + if (dgv_Registers.RowCount == 0) + { + //add rows to table + foreach (RegisterInfo reg in controller.InfoArray) + { + //get the number of bytes of the register + int numBytes = reg.numBytes; + + String dataStr = FormatData(reg); + //add a row to the table with the register address, name, and value + dgv_Registers.Rows.Add(reg.address.ToString("X2") + "h", reg.detailedName, dataStr); + } + + //resize length of table to the number of rows + if (dgv_Registers.RowCount > 8) + { + dgv_Registers.Height = (dgv_Registers.RowCount - 1) * 23 + 42; + dgv_RegDes.Height = dgv_Registers.Height; + } + else + { + dgv_Registers.Height = 7 * 23 + 42; + dgv_RegDes.Height = dgv_Registers.Height; + } + } + else //the table has already been populated with rows + { + //update the value column with the new value in the ADC registers + for (int i = 0; i < dgv_Registers.Rows.Count; i++) + { + RegisterInfo reg = controller.InfoArray[i]; + int numBytes = reg.numBytes; + String dataStr = FormatData(reg); + //add a row to the table with the register address, name, and value + dgv_Registers[col_Value.Index, i].Value = dataStr; + } + } + } + + public void Clear() + { + dgv_Registers.Rows.Clear(); + dgv_Registers.Refresh(); + } + + public string RegistersToString() + { + //RegisterProcess registerProcess; + StringBuilder sb = new StringBuilder(); + string dataStr; + string[][] bitDescriptions; + int longestRow; + + //registerProcess = new RegisterProcess(controller.InfoArray); + + bitDescriptions = new string[controller.InfoArray.Length + 4][]; + + UpdateRegisterIndexWidth(); + + // Generate register data to string + for (int i = 0; i < controller.InfoArray.Length; i++) + { + RegisterInfo reg = controller.InfoArray[i]; + + bitDescriptions[i] = new string[reg.description.list.Count]; + + for (int k = 0; k < reg.description.list.Count; k++) + { + RegisterBitDescriptions.RegisterBitDescription b = reg.description.list[k]; + int bitValue = (reg.dataField >> b.Index) & ((1 << b.Width) - 1); // MAX30001 only + bitDescriptions[i][k] = b.name + " = " + bitValue.ToString("X") + "h"; + } + } + + // Find longest row for how deep to loop to print out all registers bits + longestRow = controller.InfoArray.Length + 1; + for (int j = 0; j < controller.InfoArray.Length; j++ ) + { + if (controller.InfoArray[j].description.list.Count > longestRow) + { + longestRow = controller.InfoArray[j].description.list.Count + 1; + } + } + + for (int i = 0; i < longestRow; i++) + { + if (i < controller.InfoArray.Length) // register map + { + RegisterInfo reg = controller.InfoArray[i]; + + dataStr = FormatData(reg); + + sb.Append(this.DeviceName); + sb.Append(", "); + sb.Append(reg.address.ToString("X2")); + sb.Append("h, "); + sb.Append(reg.detailedName); + sb.Append(", "); + sb.Append(dataStr); + sb.Append("h"); + sb.Append(", "); + sb.Append(", "); + } + else // finished with register map, just have descriptions + { + sb.Append(", "); + sb.Append(", "); + sb.Append(", "); + sb.Append(", "); + sb.Append(", "); + } + + if (i == 0) // Register name and values + { + for (int k = 0; k < controller.InfoArray.Length; k++) + { + if (controller.InfoArray[k].type != RegisterInfo.RegisterType.WriteOnly) + { + sb.Append(controller.InfoArray[k].name); + sb.Append(" = "); + sb.Append(FormatData(controller.InfoArray[k])); + sb.Append("h"); + sb.Append(", "); + } + } + } + else // descriptions + { + for (int k = 0; k < controller.InfoArray.Length; k++) + { + if (controller.InfoArray[k].type != RegisterInfo.RegisterType.WriteOnly) + { + if (i - 1 < bitDescriptions[k].Length) + { + sb.Append(bitDescriptions[k][i - 1]); + } + sb.Append(','); + } + } + } + sb.Append(Environment.NewLine); + } + + /* + foreach(RegisterInfo reg in controller.InfoArray) + { + if (reg.address == 1 || reg.address == 8 || reg.address == 9 || reg.address == 10) + continue; + + sb.Append("% "); + sb.Append(reg.name); + sb.Append(" ("); + sb.Append(reg.address.ToString("X2")); + sb.Append("h)"); + sb.Append(" = "); + sb.Append(FormatData(reg)); + sb.Append("h\n"); + + foreach(RegisterBitDescriptions.RegisterBitDescription b in reg.description.list) + { + int bitValue = (RegisterData(reg) >> b.Index) & ((1 << b.Width) - 1); // MAX30001 only + sb.Append("% "); + sb.Append(b.name); + sb.Append(" = "); + sb.Append(bitValue.ToString("X")); + sb.Append("h\n"); + } + } + */ + return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray()); + } + + /// <summary> + /// Register selection change display register description and update display bits + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void dgv_Registers_SelectionChanged(object sender, EventArgs e) + { + UpdateRegisters(); + } + + private void UpdateRegisters() + { + //get the index of the row selected + int row = dgv_Registers.CurrentRow.Index; + + //make sure there is bit description info and then display it + if (controller.InfoArray[row].description != null) + { + lbl_bitDes.Text = "Bit Description: " + controller.InfoArray[row].name + " Register"; + UpdateRegisterDesTable(controller.InfoArray[row].description); + RegisterValue = Int32.Parse((string)(dgv_Registers[2, row].Value), System.Globalization.NumberStyles.HexNumber); + UpdateRegisterBits(controller.InfoArray[row].description, RegisterValue); + } + } + + /// <summary> + /// Fill register description table + /// </summary> + /// <param name="bitsDes"></param> + public void UpdateRegisterDesTable(RegisterBitDescriptions bitsDes) + { + //int numBits = bitsDes.Count; + + dgv_RegDes.Rows.Clear(); + + foreach (RegisterBitDescriptions.RegisterBitDescription b in bitsDes.list) + { + dgv_RegDes.Rows.Add(b.bit, b.name, b.description); + } + + } + + public void UpdateRegisterBits() + { + int row; + + if (dgv_Registers.CurrentRow != null) + { + row = dgv_Registers.CurrentRow.Index; + + if (controller.InfoArray[row].description != null) + { + RegisterValue = Int32.Parse((string)(dgv_Registers[2, row].Value), System.Globalization.NumberStyles.HexNumber); + UpdateRegisterBits(controller.InfoArray[row].description, RegisterValue); + } + } + } + + public void UpdateRegisterIndexWidth() + { + RegisterInfo[] info = controller.InfoArray; + + foreach(RegisterInfo regInfo in info) // Registers + { + foreach (RegisterBitDescriptions.RegisterBitDescription b in regInfo.description.list) // Bits + { + string[] numbers = Regex.Split(b.bit, @"\D+"); // Bits [20:17] + string registerBitName; + int number1 = -1; + int number2 = -1; + + // Find Bit Range + foreach (string value in numbers) + { + if (value != String.Empty) + { + if (number1 == -1) // First number found + number1 = Int32.Parse(value); + else // Second number found + number2 = Int32.Parse(value); + } + } + + if (number2 == -1) // Single Number: single bit field (example: Bit 20) + { + b.Width = 1; + b.Index = number1; + } + else // Multiple Bits: multiple bit field (example: Bit [20:17]) + { + registerBitName = Regex.Replace(b.name, @"\[\d+:\d+\]", String.Empty); // Remove [#.#] from bit field name + + for (int i = number1; i >= number2; i--) + { + bitLabels[i].Text = registerBitName + "[" + (i - number2) + "]"; // Calculate bit field number + } + + b.Index = number2; + b.Width = number1 - number2 + 1; + + } + } + } + } + + /// <summary> + /// Fill bit table + /// </summary> + /// <param name="bitDes"></param> + /// <param name="regValue"></param> + public void UpdateRegisterBits(RegisterBitDescriptions bitDes, int regValue) + { + // Reset Bit State + for (int i = 0; i < 24; i++ ) + { + bitLabels[i].Text = "-"; + + // Set label based on bit state + if (((regValue >> i) & 0x01) == 0x01) + bitLabels[i].Font = BoldFont; + else + bitLabels[i].Font = RegularFont; + } + + foreach (RegisterBitDescriptions.RegisterBitDescription b in bitDes.list) + { + string[] numbers = Regex.Split(b.bit, @"\D+"); // Bits [20:17] + string registerBitName; + int number1 = -1; + int number2 = -1; + + // Find Bit Range + foreach (string value in numbers) + { + if (value != String.Empty) + { + if (number1 == -1) // First number found + number1 = Int32.Parse(value); + else // Second number found + number2 = Int32.Parse(value); + } + } + + if (number2 == -1) // Single Number: single bit field (example: Bit 20) + { + bitLabels[number1].Text = b.name; + } + else // Multiple Bits: multiple bit field (example: Bit [20:17]) + { + registerBitName = Regex.Replace(b.name, @"\[\d+:\d+\]", String.Empty); // Remove [#.#] from bit field name + + for (int i = number1; i >= number2; i--) + { + bitLabels[i].Text = registerBitName + "[" + (i - number2) + "]"; // Calculate bit field number + } + + } + } + } + + /// <summary> + /// Parse user input and write register + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void dgv_Registers_CellEndEdit(object sender, DataGridViewCellEventArgs e) + { + //check if hardware is connected + //if (online && !COMMConnected()) + // return; + + RegisterInfo reg = controller.InfoArray[e.RowIndex]; + byte address = (byte)reg.address; + byte numBytes = (byte)reg.numBytes; + + int[] data = reg.data; + + string value = (string)dgv_Registers[col_Value.Index, e.RowIndex].Value; + string error = ValidateHexValue(value, numBytes); + + if (error == "Valid") + { + //erase error text if one exist + if (dgv_Registers[col_Value.Index, e.RowIndex].ErrorText != String.Empty) + dgv_Registers[col_Value.Index, e.RowIndex].ErrorText = String.Empty; + + //convert string hex to number hex + int hex = Int32.Parse(value, System.Globalization.NumberStyles.HexNumber); + + //write value back to GUI with correct number of characters + dgv_Registers[col_Value.Index, e.RowIndex].Value = hex.ToString("X" + numBytes * 2); + + WriteRegister(reg, hex); + + if (RegisterWriteComplete != null) + { + RegisterWriteComplete(this, new RegisterArgs { Register = address }); + } + + } + else//value is not valid + { + byte zero = 0; + dgv_Registers[col_Value.Index, e.RowIndex].Value = zero.ToString("X" + numBytes * 2); //enter zeros with correct number of characters + dgv_Registers[col_Value.Index, e.RowIndex].ErrorText = error; //add error text + } + + UpdateRegisters(); + } + + /// <summary> + /// Write data to register + /// </summary> + /// <param name="reg"></param> + /// <param name="hex"></param> + public void WriteRegister(RegisterInfo reg, int hex) + { + byte numBytes = (byte)reg.numBytes; + int[] data = reg.data; + + switch (numBytes) + { + case 4: + data[0] = (byte)(hex >> 24); + data[1] = (byte)(hex >> 16); + data[2] = (byte)(hex >> 8); + data[3] = (byte)hex; + break; + case 3: + hex &= 0x00FFFFFF;//clear bits not used + data[0] = (byte)(hex >> 16); + data[1] = (byte)(hex >> 8); + data[2] = (byte)hex; + break; + case 2: + hex &= 0x0000FFFF;//clear bits not used + data[0] = (byte)(hex >> 8); + data[1] = (byte)hex; + break; + case 1: + hex &= 0x000000FF;//clear bits not used + data[0] = (byte)hex; + break; + } + controller.WriteRegister(reg); + } + + /// <summary> + /// Verify hex + /// </summary> + /// <param name="value"></param> + /// <param name="numBytes"></param> + /// <returns></returns> + public String ValidateHexValue(String value, byte numBytes) + { + char[] character = new char[numBytes * 2]; + String error = "Valid"; + + if (value == null) + { + error = "Empty Value"; + return error; + } + + //check to see if too many characters were entered + if (value.Length > numBytes * 2) + error = "Too many characters"; + else + { + character = value.ToCharArray(); //split string into character array + + for (int i = 0; i < value.Length; i++) + { + if (Char.IsLetterOrDigit(character[i])) //check for letter and digits + { + if (Char.IsLower(character[i])) + character[i] = Char.ToUpper(character[i]); //changed letter to upper case + + //check A-F + if (character[i] > 'F') + error = "Invalid Letter"; + } + else + error = "Invalid Character"; + } + } + return error; + } + + public void WriteAll() + { + if (Connected) + controller.WriteAll(); + DisplayRegisters(); + } + + /// <summary> + /// Read all button handler + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void btn_ReadAll_Click(object sender, EventArgs e) + { + ReadAll(); + } + + /// <summary> + /// Read all registers and display results + /// </summary> + public void ReadAll() + { + if (Connected) + controller.ReadAll(); + DisplayRegisters(); + UpdateRegisterBits(); + } + + public RegisterInfo RegisterAddress(int address) + { + for(int i = 0; i < controller.InfoArray.Length; i++) + { + if (controller.InfoArray[i].address == address) + return controller.InfoArray[i]; + } + + return null; + } + + /// <summary> + /// Read register handler + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void btnRead_Click(object sender, EventArgs e) + { + if (connected) + { + controller.ReadRegister(controller.InfoArray[dgv_Registers.SelectedRows[0].Index]); + DisplayRegisters(); + UpdateRegisterBits(); + } + } + + /// <summary> + /// Toggle register bit handler + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void lblBit_Click(object sender, EventArgs e) + { + Label lbl = (Label)sender; + + string[] number = Regex.Split(lbl.Name, @"\D+"); + + if (lbl.Font.Bold == true) + lbl.Font = RegularFont; + else + lbl.Font = BoldFont; + + foreach(string value in number) + { + if (value != String.Empty) + { + int bitNumber = Int32.Parse(value); + + RegisterValue &= ~(1 << bitNumber); // clear bit + RegisterValue |= ((lbl.Font.Bold == true ? 1 : 0) << bitNumber); // set bit + } + } + } + + /// <summary> + /// Write register button handler + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void btnWrite_Click(object sender, EventArgs e) + { + if (connected) + { + WriteRegister(controller.InfoArray[dgv_Registers.SelectedRows[0].Index], RegisterValue); + controller.ReadRegister(controller.InfoArray[dgv_Registers.SelectedRows[0].Index]); + DisplayRegisters(); + } + } + + /// <summary> + /// On cell begin edit + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void OnCellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) + { + if (CellBeginEdit != null) + { + CellBeginEdit(sender, e); + } + } + + private void DataGridViewColumns(DataGridView listview, SizeF factor) + { + foreach (DataGridViewColumn column in listview.Columns) + { + column.Width = (int)Math.Round(column.Width * factor.Width); + } + } + + protected override void ScaleControl(SizeF factor, BoundsSpecified specified) + { + base.ScaleControl(factor, specified); + DataGridViewColumns(dgv_RegDes, factor); + DataGridViewColumns(dgv_Registers, factor); + } + /* + public class RegisterProcess + { + RegisterBit[][] Data; + + public RegisterProcess(RegisterInfo[] info) + { + Data = new RegisterBit[info.Length][]; + + for (int i = 0; i < info.Length; i++) + { + Data[i] = new RegisterBit[info[i].description.list.Count]; + + for (int j = 0; j < info[i].description.list.Count; j++) + { + int fieldValue; + fieldValue = (info[i].dataField >> info[i].description.list[j].Index) & info[i].description.list[j].Width; + Data[i][j] = new RegisterBit(info[i].description.list[j].name, fieldValue); + } + } + } + + class RegisterBit + { + string Name; + int Data; + + public RegisterBit(string name, int data) + { + Name = name; + Data = data; + } + } + } + */ + + public class RegisterArgs : EventArgs + { + public int Register; + } + + + } +}