- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am using the Term_v2_2 component, USB_UART mode.
1. I am trying to configure that I will receive a prompt message '#' when I turn the unit ON, I tried to use '\n' and '\r' but for some reason its not working.
2. I want the user to type the command and finish it with the "ENTER" key [currently it is defined as 10 digits].
Please your support, this is my current code:
int main()
{
char rdBuffer[RD_BUFFER_LEN];
char newString[10][10];
//char prompt[4]="\r# ";
/* Enable Global interrupts - used for USB communication */
CyGlobalIntEnable;
SPIM_Start();
LCD_Char_Start();
ADC_SAR_0_Start();
DVDAC_1_Start();
DVDAC_2_Start();
Opamp_1_Start();
Opamp_2_Start();
/* When implementing a <=5 channel mux, the Analog sequencing Mux is faster
* on an average than the Analog Hardware mux. However, additional code is
* required to select channels non-sequentially.
*/
AMux_0_Start();
Term_Start();
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
CySysTickStart();
CySysTickSetCallback(0,&isr_systick_0);
/* Start of forever loop */
for(;;)
{
char rdValue;
int r=0;
int t=10;
int i=0;
int j=0;
int ctr=0;
uint8 y=0;
for(r=0; r<65;r++)
{
rdBuffer
}
//while(Term_GetChar()!=' ');
//Term_PutString(prompt);
while(t>0)
{
if((rdValue=Term_GetChar())!='\0')
{
//PIN_LED_BLUE_Write(1);
//CyDelay(100);
rdBuffer=rdValue;
i++;
t--;
Term_PutChar(rdValue);
Term_PutString("");
rdValue='\0';
//PIN_LED_BLUE_Write(0);
//CyDelay(100);
}
}
//while(Term_GetChar()!='\r');
/* Split the command by space into words */
for(y=0;y<=(strlen(rdBuffer));y++)
{
// if space or NULL found, assign NULL into newString[ctr]
if(rdBuffer
{
newString[ctr]
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr]
j++;
}
}
/* The splited command will be directed to the relevant path.
If read, the function prints the relevant port's hex value.
If write, the function activate the port in accordance to the command and returns '#' */
Command(newString[0], newString[1], newString[2], newString[3]);
} /* End forever loop */
Solved! Go to Solution.
- Labels:
-
PSoC 5 Architecture
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Motoo,
Thank you very much for your time and helpful support, especially for troubleshooting together using zoom application
I will share my code in here so other people can use it also:
#Introduction to the code:
Using both USBUART, UART communications [by using Term_v2_2 component made by LePo_1062026].
Perform analog input measurements.
Perform digital input indication.
Perform digital output 5V, 3V3, 1V8.
Prompt message & command architecture definition.
main.c
===================================================================
/* ALL THE CODE SUPPORT LIBRARIES *********************************************/
#include "project.h"
#include <version.h>
#include <device.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
/* END OF ALL THE CODE SUPPORT LIBRARIES **************************************/
/* ALL THE CODE SUPPORT PARAMETERS ********************************************/
#if defined (__GNUC__)
/* Add an explicit reference to the floating point printf library */
/* to allow the usage of floating point conversion specifiers. */
/* This is not linked in by default with the newlib-nano library. */
asm (".global _printf_float");
#endif
#define RD_BUFFER_LEN (64u)
#define WR_BUFFER_LEN (64u)
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
_Bool sec_1 = 0;
#define NL '\n'
#define CR '\r'
#define BS '\b'
char rdBuffer[RD_BUFFER_LEN+1] ;
int rd_index = 0 ;
/* END OF ALL THE CODE SUPPORT PARAMETERS *************************************/
/*******************************************************************************
* Function Name: cls
********************************************************************************
*
** Summary:
* 1. Performs reset.
* 2. Performs clear screen.
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
void cls(void)
{
Term_PutString("\033c") ; /* reset */
CyDelay(20) ;
Term_PutString("\033[2J") ; /* clear screen */
CyDelay(20) ;
}
/*******************************************************************************
* Function Name: splash
********************************************************************************
*
** Summary:
* 1. Prints the project's name.
* 2. Prints today's date.
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
void splash(char *prog_name)
{
cls() ;
if (prog_name && *prog_name)
{
Term_PutString(prog_name) ;
}
Term_PutString(" [") ;
Term_PutString(__DATE__) ;
Term_PutString(" ") ;
Term_PutString(__TIME__) ;
Term_PutString("]\n\r") ;
}
/*******************************************************************************
* Function Name: prompt
********************************************************************************
*
** Summary:
* Prints a prompt char "# ".
*
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
void prompt(void)
{
Term_PutString("# ") ;
}
/*******************************************************************************
* Function Name: get_line
********************************************************************************
*
** Summary:
* Collect the chars / command into a string.
*
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
int get_line(void)
{
uint8_t c ;
int result = 0 ;
if ((c = Term_GetChar()) != 0)
{
/* got some chars */
switch(c)
{
case NL:
case CR:
rdBuffer[rd_index] = 0 ;
rd_index = 0 ;
result = 1 ;
Term_PutChar(c) ;
break ;
case BS:
if (rd_index > 0)
{
rd_index-- ;
rdBuffer[rd_index] = 0 ;
Term_PutString("\b \b") ;
}
break ;
default:
Term_PutChar(c) ;
rdBuffer[rd_index] = c ;
rd_index++ ;
if ((uint8)rd_index >= RD_BUFFER_LEN)
{
// buffer overflow
rdBuffer[RD_BUFFER_LEN] = 0 ;
rd_index = 0 ;
result = -1 ;
}
break ;
}
}
return( result ) ;
}
/*******************************************************************************
* Function Name: CY_ISR
********************************************************************************
*
* Summary:
*
*
*
* Parameters:
*
*
* Return:
*
*
*******************************************************************************/
CY_ISR(isr_systick_0)
{
static int16_t i = 0;
i++;
if(i >= 1000) {sec_1 = 1; i=0; }
}
/*******************************************************************************
* Function Name: Command
********************************************************************************
*
** Summary:
* 1. The splited command will be directed to the relevant path.
* 2. If read, the function prints the relevant port's hex value.
* 3. If write, the function activate the port in accordance to the command and returns '#'.
* 4. Chooses mux channel to be read according to UART/USBUART data .
* 5. Reads ADC converted data, sends this data to the UART/USBUART.
* 6. Displays ADC converted data on Character LCD for debugging.
*
** Parameters:
* Function: ain, din, dout, coil
* Action: r, w
* Port: 0-9 max
* Value: 0-9 max
*
** Return:
*
*
*******************************************************************************/
void Command( char* function, char* action, char* port, char* value)
{
/* adcReading holds the converted 16-bit data from the ADC */
uint16 adcReading = 0u;
char LCDBuffer[9];
char ain[]="ain";
char din[]="din";
char dout[]="dout";
char coil[]="coil";
char read[] ="r";
char write[]="w";
uint8 temp;
char x[10];
/* ANALOG INPUTS ************************************************************/
if(!strcmp(function,ain))
{
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=7)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
AMux_0_FastSelect((uint8)atoi(port));
ADC_SAR_0_StartConvert();
ADC_SAR_0_IsEndConversion(ADC_SAR_0_WAIT_FOR_RESULT);
adcReading = ADC_SAR_0_GetResult16();
sprintf(x,"0x%x",adcReading);
Term_PutString("\r\n");
Term_PutString(x);
Term_PutString("\r\n");
//Term_PutString("# ");
/* For verification purposes, display the adcReading on the LCD *****/
LCD_Char_ClearDisplay();
sprintf(LCDBuffer,"%d",adcReading);
LCD_Char_Position(0,0);
LCD_Char_PrintString(LCDBuffer);
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF READ THE VALUE IN THE PORT ************************************/
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* currently nothing to write in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
/* CLEAR THE TRANSMIT BUFFER BEFORE NEXT READING ************************/
SPIM_ClearTxBuffer();
temp = SPIM_ReadTxStatus();
/* VERIFY PREVIOUS SPI READ IS DONE/SPI IS IDLE BEFORE SENDING DATA *****/
if((temp & (SPIM_STS_SPI_DONE | SPIM_STS_SPI_IDLE)))
{
SPIM_WriteTxData(adcReading);
}
/* END OF VERIFY PREVIOUS SPI READ IS DONE/IDLE *************************/
}
/* END OF ANALOG INPUTS *****************************************************/
/* DIGITAL INPUTS ***********************************************************/
if(!strcmp(function,din))
{
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* currently nothing to write in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=7)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
if((uint8)atoi(port)==0)
sprintf(x,"0x%x",DIN_O1_Read());
/*
will be defined with the prototype.
if((uint8)atoi(port)==1)
sprintf(x,"0x%x",DIN_O2_Read());
if((uint8)atoi(port)==2)
sprintf(x,"0x%x",DIN_O3_Read());
if((uint8)atoi(port)==3)
sprintf(x,"0x%x",DIN_O4_Read());
if((uint8)atoi(port)==4)
sprintf(x,"0x%x",DIN_O5_Read());
if((uint8)atoi(port)==5)
sprintf(x,"0x%x",DIN_O6_Read());
if((uint8)atoi(port)==6)
sprintf(x,"0x%x",DIN_O7_Read());
*/
Term_PutString("\r\n");
Term_PutString(x);
Term_PutString("\r\n");
//Term_PutString("# ");
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF READ THE VALUE IN THE PORT ************************************/
}
/* END OF DIGITAL INPUTS ****************************************************/
/* DIGITAL OUTPUTS **********************************************************/
if(!strcmp(function,dout))
{
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* currently nothing to read in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF READ THE VALUE IN THE PORT ************************************/
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=7)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
/* VERIFY ONLY VALID VALUE HAS BEEN REQUESTED *******************/
if((uint8)atoi(value)>=6)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID VALUE HAS BEEN REQUESTED ************/
/* VALID VALUE FROM THE USER ************************************/
else
{
if((uint8)atoi(port)==0)
DOUT_I1_Write((uint8)atoi(value));
/*
if((uint8)atoi(port)==5)
{
//0xCE4 - 3V3
if((uint8)atoi(value)==1)
DVDAC_1_SetValue(0xCE4);
if((uint8)atoi(value)==0)
DVDAC_1_SetValue(0x0);
}
if((uint8)atoi(port)==6)
{
//0x708 - 1V8
if((uint8)atoi(value)==1)
DVDAC_2_SetValue(0x708);
if((uint8)atoi(value)==0)
DVDAC_2_SetValue(0x0);
}
will be defined with the prototype.
if((uint8)atoi(port)==1)
DOUT_I2_Write((uint8)atoi(value));
if((uint8)atoi(port)==2)
DOUT_I3_Write((uint8)atoi(value));
if((uint8)atoi(port)==3)
DOUT_I4_Write((uint8)atoi(value));
if((uint8)atoi(port)==4)
DOUT_I5_Write((uint8)atoi(value));
*/
Term_PutString("\r\n");
//Term_PutString("# ");
}
/* END OF VALID VALUE FROM THE USER *****************************/
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
}
/* END OF DIGITAL OUTPUTS ***************************************************/
/* RELAY GPIO SWITCH ********************************************************/
if(!strcmp(function,coil))
{
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* currently nothing to read in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF READ THE VALUE IN THE PORT ************************************/
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=5)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
/* VERIFY ONLY VALID VALUE HAS BEEN REQUESTED *******************/
if((uint8)atoi(value)>=2)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID VALUE HAS BEEN REQUESTED ************/
/* VALID VALUE FROM THE USER ************************************/
else
{
if((uint8)atoi(port)==0)
COIL1_Write((uint8)atoi(value));
/*
will be defined with the prototype.
if((uint8)atoi(port)==1)
COIL2_Write((uint8)atoi(value));
if((uint8)atoi(port)==2)
COIL3_Write((uint8)atoi(value));
if((uint8)atoi(port)==3)
COIL4_Write((uint8)atoi(value));
if((uint8)atoi(port)==4)
COIL5_Write((uint8)atoi(value));
*/
Term_PutString("\r\n");
//Term_PutString("# ");
}
/* END OF VALID VALUE FROM THE USER *****************************/
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
}
/* END OF RELAY GPIO SWITCH *************************************************/
/* VALID FUNCTION FROM THE USER *********************************************/
if(strcmp(function,din) & strcmp(function,dout) & strcmp(function,ain) & strcmp(function,coil))
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VALID FUNCTION FROM THE USER **************************************/
}
/* END OF COMMAND **************************************************************/
/*******************************************************************************
* Function Name: main
********************************************************************************
*
* Summary:
** The main function performs the following actions:
** UART/RS232:
*
*
*
*
*
** USB UART:
* 1. Starts all used components.
* 2. Enumerates and handles data transfer between PC and PSoC via USBUART.
*
** Functionality:
* Sends the received command to the "Command" function.
*
*
* Parameters:
* None.
*
* Return:
* None.
*
*******************************************************************************/
int main()
{
/* ENABLE GLOBAL INTERRUPTS ***********************************************/
/* USED FOR USB COMMUNICATION */
CyGlobalIntEnable;
/* END OF ENABLE GLOBAL INTERRUPTS ****************************************/
/*
// DRAFT FOR UART/USBUART SWITCH
#define COM_UART 1
#define COM_USBUART 2
int com_used = COM_USBUART ;
if (TermUSB_Start() == TIMEOUT) {
com_used = COM_UART ;
TermUART_Start() ;
}
uint8_t my_GetChar(void)
{
if (com_used == COM_UART) {
return( Term_1_GetChar() ) ;
} else if (com_used == COM_USBUART) {
return( Term_GetChar() ) ;
}
}
void my_PutChar(uint8_t c)
{
if (com_used == COM_UART) {
return( TermUART_PutChar(c) ) ;
} else if (com_used == COM_USBUART) {
return( TermUSB_PutChar(c) ) ;
}
}
void my_PutString(uint8_t *str)
{
if (com_used == COM_UART) {
return( TermUART_PutString(str) ) ;
} else if (com_used == COM_USBUART) {
return( TermUSBtString(str) ) ;
}
}
*/
/* START OF INITIALIZATION/STARTUP CODE ***********************************/
CySysTickStart();
CySysTickSetCallback(0,&isr_systick_0);
AMux_0_Start();
Term_Start();
Term_1_Start();
SPIM_Start();
LCD_Char_Start();
ADC_SAR_0_Start();
DVDAC_1_Start();
DVDAC_2_Start();
Opamp_1_Start();
Opamp_2_Start();
/* END OF INITIALIZATION/STARTUP CODE *************************************/
/* INITIAL MESSAGES AND PROMPT "# " ***************************************/
/* PRINT THE PROJECT'S NAME AND FULL DATE */
CyDelay(1000);
splash("PSoC 5LP command & prompt test");
/* PRINT A PROMPT "# " */
prompt();
/* END OF INITIAL MESSAGES AND PROMPT "# " ********************************/
/* START OF FOREVER LOOP **************************************************/
for(;;)
{
/* COLLECT THE CHARS / COMMAND INTO A STRING **************************/
if (get_line())
{
int j=0;
int ctr=0;
uint8 y=0;
char newString[10][10];
/* SPLIT THE COMMAND INTO WORDS BY SPACE **************************/
for(y=0;y<=(strlen(rdBuffer));y++)
{
// if space or NULL found, assign NULL into newString[ctr]
if(rdBuffer
{
newString[ctr]
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr]
j++;
}
}
/* END OF SPLIT THE COMMAND INTO WORDS BY SPACE *******************/
/* SEND THE SPLITED COMMAND INTO THE COMMAND FUNCTION */
Command(newString[0], newString[1], newString[2], newString[3]);
/* PRINT A PROMPT "# " */
prompt();
}
/* END OF COLLECT THE CHARS / COMMAND INTO A STRING *******************/
}
/* END OF FOREVER LOOP ****************************************************/
}
/* [] END OF MAIN *************************************************************/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have posted a few sample projects with the similar theme.
Although they are not using Term_v2_2 component, I hope that the idea should be similar.
Hopefully, they can be some hints for you.
Polling mode not using user interrupt
A simple UART sample without using interrupt for CY8CKIT-044
Interrupt driven, may be difficult to port to USB_UART.
Re: tty_utils a utility sample for CLI type program
Sample of prompt, commands
MCU Tester, a Swiss Army Knife for PSoC (CY8CKIT-059 version)
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Moto,
I will check the links you mentioned, thank you very much
Thanks,
Roy Roif
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Roy,
I wrote the Term component. In general, the Term component is a UART-like API interface for the USB_UART HW. The major intent for the component was that if you successfully wrote your code using the UART component, it was virtually trivial to substitute the Term component for the UART component, call it the same name, and change the configuration to USB_UART.
I'll try to help. However, I need some clarification from you.
If I understood correctly from your original post, if the user types "#ENTER" (where ENTER = \r\n) you want the LED to turn on. Is this the correct understanding?
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Len,
No, Currently I am using a "while(t>0)" with t=10 so the loop is over only after the user enter 10 digits.
I want to replace the "while(t>0)", so once the user press the "ENTER" key the loop is over.
For some reason when I try to use "while(Term_GetChar()!='\n')" the terminal window become really really slow and the enter key
doesnt make any difference.
Thanks,
Roy Roif
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I would modify your forever loop something like below
==========================
char rdBuffer[RD_BUFFER_LEN+1] ; // 1 for NULL terminator
int string_received = 0 ;
/* Start of forever loop */
for(;;) {
if ((rdValue = Term_GetChar()) != 0) { /* got some char(s) */
switch(rdValue) {
case '\n':
case '\r':
rdBuffer = 0 ; // terminate the string
i = 0 ;
string_received = 1 ;
Term_PutChar(rdValue) ;
break ;
case '\b': // backspace
if (i > 0) {
i-- ;
rdBuffer = 0 ; // delete 1 char
Term_PutString("\b \b") ;
}
break ;
default:
Term_PutChar(rdValue) ;
rdBuffer = rdValue ;
i++ ;
if (i >= RD_BUFFER_LEN) { // buffer overflow
rdBuffer[RD_BUFFER_LEN] = 0 ;
i = 0 ;
string_received = -1 ;
}
break ;
}
}
if (string_received) {
// do what you want to do with the string
// if string_received == 1, normal string
// ir string_received == -1, buffer overflow happened
string_received = 0 ; // after processing the string, clear the received flag
}
}
==========================
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Moto,
I will try that code thank you very much
Thanks,
Roy Roif
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Moto,
The code doesn't work
Is it ok with you if we meet in zoom so I can share the screen with you?
Thanks,
Roy Roif
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, Roy-san,
> The code doesn't work
That's too bad.
It's 20:16 in Japan.
I will be available for a few hours from now on.
Let me know if you startup zoom.
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I re-organized my main.c a little more.
Since I'm having a little difficulty using Term_v2.0, I'm using UART as Term.
But all the source code after the function "init_hardware()" should work with the Term_v2.0 lib. (I hope)
You need to replace the call of "init_hardware()" with your initialization.
I'm using CY8CKIT-059 for this project.
After receiving a line, the program calls "do_something()",
where you can do whatever you like with the line entered.
In this example I just printed the line with "String Recived: ".
The output of the program in Tera Term looks like
main.c
======================
#include "project.h"
#include "stdio.h"
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
Term_Start() ;
}
#define NL '\n'
#define CR '\r'
#define BS '\b'
#define RD_BUFFER_LEN 64
char rdBuffer[RD_BUFFER_LEN+1] ;
int rd_index = 0 ;
void cls(void)
{
Term_PutString("\033c") ; /* reset */
CyDelay(20) ;
Term_PutString("\033[2J") ; /* clear screen */
CyDelay(20) ;
}
void splash(char *prog_name)
{
cls() ;
if (prog_name && *prog_name) {
Term_PutString(prog_name) ;
}
Term_PutString(" (") ;
Term_PutString(__DATE__) ;
Term_PutString(" ") ;
Term_PutString(__TIME__) ;
Term_PutString(")\n") ;
}
void prompt(void)
{
Term_PutString("# ") ;
}
int get_line(void)
{
uint8_t c ;
int result = 0 ;
if ((c = Term_GetChar()) != 0) { /* got some chars */
switch(c) {
case NL:
case CR:
rdBuffer[rd_index] = 0 ;
rd_index = 0 ;
result = 1 ;
Term_PutChar(c) ;
break ;
case BS:
if (rd_index > 0) {
rd_index-- ;
rdBuffer[rd_index] = 0 ;
Term_PutString("\b \b") ;
}
break ;
default:
Term_PutChar(c) ;
rdBuffer[rd_index] = c ;
rd_index++ ;
if (rd_index >= RD_BUFFER_LEN) { // buffer overflow
rdBuffer[RD_BUFFER_LEN] = 0 ;
rd_index = 0 ;
result = -1 ;
}
break ;
}
}
return( result ) ;
}
void do_something(void)
{
Term_PutString("String Recived: ") ;
Term_PutString(rdBuffer) ;
Term_PutString("\n\r") ;
}
int main(void)
{
init_hardware() ;
splash("PSoC 5LP command & prompt test") ;
prompt() ;
for(;;) {
if (get_line()) {
do_something() ;
prompt() ;
}
}
}
======================
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Motoo,
Thank you very much for your time and helpful support, especially for troubleshooting together using zoom application
I will share my code in here so other people can use it also:
#Introduction to the code:
Using both USBUART, UART communications [by using Term_v2_2 component made by LePo_1062026].
Perform analog input measurements.
Perform digital input indication.
Perform digital output 5V, 3V3, 1V8.
Prompt message & command architecture definition.
main.c
===================================================================
/* ALL THE CODE SUPPORT LIBRARIES *********************************************/
#include "project.h"
#include <version.h>
#include <device.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
/* END OF ALL THE CODE SUPPORT LIBRARIES **************************************/
/* ALL THE CODE SUPPORT PARAMETERS ********************************************/
#if defined (__GNUC__)
/* Add an explicit reference to the floating point printf library */
/* to allow the usage of floating point conversion specifiers. */
/* This is not linked in by default with the newlib-nano library. */
asm (".global _printf_float");
#endif
#define RD_BUFFER_LEN (64u)
#define WR_BUFFER_LEN (64u)
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
_Bool sec_1 = 0;
#define NL '\n'
#define CR '\r'
#define BS '\b'
char rdBuffer[RD_BUFFER_LEN+1] ;
int rd_index = 0 ;
/* END OF ALL THE CODE SUPPORT PARAMETERS *************************************/
/*******************************************************************************
* Function Name: cls
********************************************************************************
*
** Summary:
* 1. Performs reset.
* 2. Performs clear screen.
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
void cls(void)
{
Term_PutString("\033c") ; /* reset */
CyDelay(20) ;
Term_PutString("\033[2J") ; /* clear screen */
CyDelay(20) ;
}
/*******************************************************************************
* Function Name: splash
********************************************************************************
*
** Summary:
* 1. Prints the project's name.
* 2. Prints today's date.
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
void splash(char *prog_name)
{
cls() ;
if (prog_name && *prog_name)
{
Term_PutString(prog_name) ;
}
Term_PutString(" [") ;
Term_PutString(__DATE__) ;
Term_PutString(" ") ;
Term_PutString(__TIME__) ;
Term_PutString("]\n\r") ;
}
/*******************************************************************************
* Function Name: prompt
********************************************************************************
*
** Summary:
* Prints a prompt char "# ".
*
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
void prompt(void)
{
Term_PutString("# ") ;
}
/*******************************************************************************
* Function Name: get_line
********************************************************************************
*
** Summary:
* Collect the chars / command into a string.
*
*
** Parameters:
*
*
*
** Return:
*
*
*
*******************************************************************************/
int get_line(void)
{
uint8_t c ;
int result = 0 ;
if ((c = Term_GetChar()) != 0)
{
/* got some chars */
switch(c)
{
case NL:
case CR:
rdBuffer[rd_index] = 0 ;
rd_index = 0 ;
result = 1 ;
Term_PutChar(c) ;
break ;
case BS:
if (rd_index > 0)
{
rd_index-- ;
rdBuffer[rd_index] = 0 ;
Term_PutString("\b \b") ;
}
break ;
default:
Term_PutChar(c) ;
rdBuffer[rd_index] = c ;
rd_index++ ;
if ((uint8)rd_index >= RD_BUFFER_LEN)
{
// buffer overflow
rdBuffer[RD_BUFFER_LEN] = 0 ;
rd_index = 0 ;
result = -1 ;
}
break ;
}
}
return( result ) ;
}
/*******************************************************************************
* Function Name: CY_ISR
********************************************************************************
*
* Summary:
*
*
*
* Parameters:
*
*
* Return:
*
*
*******************************************************************************/
CY_ISR(isr_systick_0)
{
static int16_t i = 0;
i++;
if(i >= 1000) {sec_1 = 1; i=0; }
}
/*******************************************************************************
* Function Name: Command
********************************************************************************
*
** Summary:
* 1. The splited command will be directed to the relevant path.
* 2. If read, the function prints the relevant port's hex value.
* 3. If write, the function activate the port in accordance to the command and returns '#'.
* 4. Chooses mux channel to be read according to UART/USBUART data .
* 5. Reads ADC converted data, sends this data to the UART/USBUART.
* 6. Displays ADC converted data on Character LCD for debugging.
*
** Parameters:
* Function: ain, din, dout, coil
* Action: r, w
* Port: 0-9 max
* Value: 0-9 max
*
** Return:
*
*
*******************************************************************************/
void Command( char* function, char* action, char* port, char* value)
{
/* adcReading holds the converted 16-bit data from the ADC */
uint16 adcReading = 0u;
char LCDBuffer[9];
char ain[]="ain";
char din[]="din";
char dout[]="dout";
char coil[]="coil";
char read[] ="r";
char write[]="w";
uint8 temp;
char x[10];
/* ANALOG INPUTS ************************************************************/
if(!strcmp(function,ain))
{
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=7)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
AMux_0_FastSelect((uint8)atoi(port));
ADC_SAR_0_StartConvert();
ADC_SAR_0_IsEndConversion(ADC_SAR_0_WAIT_FOR_RESULT);
adcReading = ADC_SAR_0_GetResult16();
sprintf(x,"0x%x",adcReading);
Term_PutString("\r\n");
Term_PutString(x);
Term_PutString("\r\n");
//Term_PutString("# ");
/* For verification purposes, display the adcReading on the LCD *****/
LCD_Char_ClearDisplay();
sprintf(LCDBuffer,"%d",adcReading);
LCD_Char_Position(0,0);
LCD_Char_PrintString(LCDBuffer);
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF READ THE VALUE IN THE PORT ************************************/
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* currently nothing to write in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
/* CLEAR THE TRANSMIT BUFFER BEFORE NEXT READING ************************/
SPIM_ClearTxBuffer();
temp = SPIM_ReadTxStatus();
/* VERIFY PREVIOUS SPI READ IS DONE/SPI IS IDLE BEFORE SENDING DATA *****/
if((temp & (SPIM_STS_SPI_DONE | SPIM_STS_SPI_IDLE)))
{
SPIM_WriteTxData(adcReading);
}
/* END OF VERIFY PREVIOUS SPI READ IS DONE/IDLE *************************/
}
/* END OF ANALOG INPUTS *****************************************************/
/* DIGITAL INPUTS ***********************************************************/
if(!strcmp(function,din))
{
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* currently nothing to write in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=7)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
if((uint8)atoi(port)==0)
sprintf(x,"0x%x",DIN_O1_Read());
/*
will be defined with the prototype.
if((uint8)atoi(port)==1)
sprintf(x,"0x%x",DIN_O2_Read());
if((uint8)atoi(port)==2)
sprintf(x,"0x%x",DIN_O3_Read());
if((uint8)atoi(port)==3)
sprintf(x,"0x%x",DIN_O4_Read());
if((uint8)atoi(port)==4)
sprintf(x,"0x%x",DIN_O5_Read());
if((uint8)atoi(port)==5)
sprintf(x,"0x%x",DIN_O6_Read());
if((uint8)atoi(port)==6)
sprintf(x,"0x%x",DIN_O7_Read());
*/
Term_PutString("\r\n");
Term_PutString(x);
Term_PutString("\r\n");
//Term_PutString("# ");
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF READ THE VALUE IN THE PORT ************************************/
}
/* END OF DIGITAL INPUTS ****************************************************/
/* DIGITAL OUTPUTS **********************************************************/
if(!strcmp(function,dout))
{
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* currently nothing to read in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF READ THE VALUE IN THE PORT ************************************/
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=7)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
/* VERIFY ONLY VALID VALUE HAS BEEN REQUESTED *******************/
if((uint8)atoi(value)>=6)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID VALUE HAS BEEN REQUESTED ************/
/* VALID VALUE FROM THE USER ************************************/
else
{
if((uint8)atoi(port)==0)
DOUT_I1_Write((uint8)atoi(value));
/*
if((uint8)atoi(port)==5)
{
//0xCE4 - 3V3
if((uint8)atoi(value)==1)
DVDAC_1_SetValue(0xCE4);
if((uint8)atoi(value)==0)
DVDAC_1_SetValue(0x0);
}
if((uint8)atoi(port)==6)
{
//0x708 - 1V8
if((uint8)atoi(value)==1)
DVDAC_2_SetValue(0x708);
if((uint8)atoi(value)==0)
DVDAC_2_SetValue(0x0);
}
will be defined with the prototype.
if((uint8)atoi(port)==1)
DOUT_I2_Write((uint8)atoi(value));
if((uint8)atoi(port)==2)
DOUT_I3_Write((uint8)atoi(value));
if((uint8)atoi(port)==3)
DOUT_I4_Write((uint8)atoi(value));
if((uint8)atoi(port)==4)
DOUT_I5_Write((uint8)atoi(value));
*/
Term_PutString("\r\n");
//Term_PutString("# ");
}
/* END OF VALID VALUE FROM THE USER *****************************/
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
}
/* END OF DIGITAL OUTPUTS ***************************************************/
/* RELAY GPIO SWITCH ********************************************************/
if(!strcmp(function,coil))
{
/* READ THE VALUE IN THE PORT *******************************************/
if(!strcmp(action,read))
{
/* currently nothing to read in the digital outputs */
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF READ THE VALUE IN THE PORT ************************************/
/* WRITE THE VALUE TO THE PORT ******************************************/
if(!strcmp(action,write))
{
/* VERIFY ONLY VALID PORT HAS BEEN REQUESTED ************************/
if((uint8)atoi(port)>=5)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID PORT HAS BEEN REQUESTED *****************/
/* VALID PORT FROM THE USER *****************************************/
else
{
/* VERIFY ONLY VALID VALUE HAS BEEN REQUESTED *******************/
if((uint8)atoi(value)>=2)
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VERIFY ONLY VALID VALUE HAS BEEN REQUESTED ************/
/* VALID VALUE FROM THE USER ************************************/
else
{
if((uint8)atoi(port)==0)
COIL1_Write((uint8)atoi(value));
/*
will be defined with the prototype.
if((uint8)atoi(port)==1)
COIL2_Write((uint8)atoi(value));
if((uint8)atoi(port)==2)
COIL3_Write((uint8)atoi(value));
if((uint8)atoi(port)==3)
COIL4_Write((uint8)atoi(value));
if((uint8)atoi(port)==4)
COIL5_Write((uint8)atoi(value));
*/
Term_PutString("\r\n");
//Term_PutString("# ");
}
/* END OF VALID VALUE FROM THE USER *****************************/
}
/* END OF VALID PORT FROM THE USER **********************************/
}
/* END OF WRITE THE VALUE TO THE PORT ***********************************/
}
/* END OF RELAY GPIO SWITCH *************************************************/
/* VALID FUNCTION FROM THE USER *********************************************/
if(strcmp(function,din) & strcmp(function,dout) & strcmp(function,ain) & strcmp(function,coil))
{
Term_PutString("\r\n");
Term_PutString("Input Error!\r\n");
//Term_PutString("# ");
LCD_Char_ClearDisplay();
LCD_Char_PrintString("Input Error");
}
/* END OF VALID FUNCTION FROM THE USER **************************************/
}
/* END OF COMMAND **************************************************************/
/*******************************************************************************
* Function Name: main
********************************************************************************
*
* Summary:
** The main function performs the following actions:
** UART/RS232:
*
*
*
*
*
** USB UART:
* 1. Starts all used components.
* 2. Enumerates and handles data transfer between PC and PSoC via USBUART.
*
** Functionality:
* Sends the received command to the "Command" function.
*
*
* Parameters:
* None.
*
* Return:
* None.
*
*******************************************************************************/
int main()
{
/* ENABLE GLOBAL INTERRUPTS ***********************************************/
/* USED FOR USB COMMUNICATION */
CyGlobalIntEnable;
/* END OF ENABLE GLOBAL INTERRUPTS ****************************************/
/*
// DRAFT FOR UART/USBUART SWITCH
#define COM_UART 1
#define COM_USBUART 2
int com_used = COM_USBUART ;
if (TermUSB_Start() == TIMEOUT) {
com_used = COM_UART ;
TermUART_Start() ;
}
uint8_t my_GetChar(void)
{
if (com_used == COM_UART) {
return( Term_1_GetChar() ) ;
} else if (com_used == COM_USBUART) {
return( Term_GetChar() ) ;
}
}
void my_PutChar(uint8_t c)
{
if (com_used == COM_UART) {
return( TermUART_PutChar(c) ) ;
} else if (com_used == COM_USBUART) {
return( TermUSB_PutChar(c) ) ;
}
}
void my_PutString(uint8_t *str)
{
if (com_used == COM_UART) {
return( TermUART_PutString(str) ) ;
} else if (com_used == COM_USBUART) {
return( TermUSBtString(str) ) ;
}
}
*/
/* START OF INITIALIZATION/STARTUP CODE ***********************************/
CySysTickStart();
CySysTickSetCallback(0,&isr_systick_0);
AMux_0_Start();
Term_Start();
Term_1_Start();
SPIM_Start();
LCD_Char_Start();
ADC_SAR_0_Start();
DVDAC_1_Start();
DVDAC_2_Start();
Opamp_1_Start();
Opamp_2_Start();
/* END OF INITIALIZATION/STARTUP CODE *************************************/
/* INITIAL MESSAGES AND PROMPT "# " ***************************************/
/* PRINT THE PROJECT'S NAME AND FULL DATE */
CyDelay(1000);
splash("PSoC 5LP command & prompt test");
/* PRINT A PROMPT "# " */
prompt();
/* END OF INITIAL MESSAGES AND PROMPT "# " ********************************/
/* START OF FOREVER LOOP **************************************************/
for(;;)
{
/* COLLECT THE CHARS / COMMAND INTO A STRING **************************/
if (get_line())
{
int j=0;
int ctr=0;
uint8 y=0;
char newString[10][10];
/* SPLIT THE COMMAND INTO WORDS BY SPACE **************************/
for(y=0;y<=(strlen(rdBuffer));y++)
{
// if space or NULL found, assign NULL into newString[ctr]
if(rdBuffer
{
newString[ctr]
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr]
j++;
}
}
/* END OF SPLIT THE COMMAND INTO WORDS BY SPACE *******************/
/* SEND THE SPLITED COMMAND INTO THE COMMAND FUNCTION */
Command(newString[0], newString[1], newString[2], newString[3]);
/* PRINT A PROMPT "# " */
prompt();
}
/* END OF COLLECT THE CHARS / COMMAND INTO A STRING *******************/
}
/* END OF FOREVER LOOP ****************************************************/
}
/* [] END OF MAIN *************************************************************/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi MoTa_728816,
Thank you for taking your time to set up a debugging session with RoRo_4659551 to resolve the issue. Your efforts are greatly appreciated
Regards,
Bragadeesh
Bragadeesh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Roy,
I was planning on helping you by providing some example code. However, my PSoC Creator stopped working.
Hopefully I can get back up and working soon.
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Roy,
Here is a very simple and compact program that uses the Term and MenuCmds components. It is a demo program that allows the user to control the LED (on the CY8CKIT_059 board is on P2.1).
It has a single-character driven menu:
?=> display FULL help list
h=> display minimized help list
b=> display Build info
#=> Turn LED ON 100%
$=> Turn LED OFF
5=> Toggle LED 50% ON 50% OFF
1=> Toggle LED 10% ON 90% OFF
This is not exactly what you were asking about. I'm working on that.
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Len,
Yes I saw this code.
Ok thank you
Thanks,
Roy Roif
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Roy,
Here is a project similar to my MenuCmds version of LED control. It uses the same characters to control the LED however it waits for a '\n' or a '\r' to process the LED control. Note: ONLY the last character input is queued! This should be closer to what you are enquiring.
Here is a list of the commands available:
?=>display FULL help list
h=>display minimized help list
#=>Turn LED ON 100%
$=>Turn LED OFF
5=>Toggle LED 50% ON 50% OFF
1=>Toggle LED 10% ON 90% OFF
Note: ONLY the last character input is queued!
Len
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Len,
I cant see it, where is it attached?
Thanks,
Roy Roif
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Roy,
I can see it on the post and downloaded it. Hmm.
When I first saved the post, it didn't contain the attached file. I edited the post and attached it.
Try a refresh of this discussion.
Len
"Engineering is an Art. The Art of Compromise."