cancel
Showing results for 
Search instead for 
Did you mean: 

Code Examples

Len_CONSULTRON
Honored Contributor II

To all,

I've enhanced some of my previously submitted code shares (Terminal Component - Simplifies UART or USBUART communication and GetString() function that supports input character filtering.  Includes menu-driven commands. ).

I've now expanded these previous submits and placed them in a Component Library that can be easily shared with all your projects and with other users.

Here is a list of the components in the library:

  • Term - Terminal (UART) replacement that can be configured as UART or USBUART types.
  • String_Funcs - This is an enhancement of the GetString() function.  It is easier to use.
  • MenuCmds - This feature was included in the GetString demo code I shared earlier.  It is now a component with some improvements.

With each of the Components, I have include at least one demo project for each component to illustrate how these components can be used.

I've also included datasheets for the Components, the demo projects and a instructional on how to install a library/component to be shared across all your projects.

All the components have the source code included for educational purposes.  If you know how to write component code, you can modify it.

The components String_Funcs and MenuCmds are designed to work with ANY PSoC. (They are mostly library functions.)

The Term component currently only works with the PSoC5.

I hope everyone who download's this component will find it useful.

Len

Message was edited by: Len Update: Added PSoC6 and PSoC4 demo code examples.

Message was edited by: Len  Update: Added two more PSoC4 demo code examples. Both using the SCB_UART component and one of them with a Bootladable (-049 kit).

Message was edited by: Leonard Poma This library includes the latest version (2.3) of Term. Attached is also two demo examples of using Term.

Len
"Engineering is an Art. The Art of Compromise."
1 Solution
Ekta
Moderator
Moderator

Hello Len,

Thank you for providing Terminal Support Component Library.

The datasheet provided with all the three components are detailed.

They contain all the information necessary to use the components.

I appreciate your valuable input on this.

Thanks and Regards

Ekta

View solution in original post

0 Likes
27 Replies
Ekta
Moderator
Moderator

Hello Len,

Thank you for providing Terminal Support Component Library.

The datasheet provided with all the three components are detailed.

They contain all the information necessary to use the components.

I appreciate your valuable input on this.

Thanks and Regards

Ekta

View solution in original post

0 Likes
Len_CONSULTRON
Honored Contributor II

Ekta,

Thank you for your commendation.  I want to help out the PSoC community by providing some tools to make using the PSoC easier.

I have used both MenuCmds and String_Funcs in nearly all my projects.  It makes creating a user interface much faster and using the help commands of '?' and 'h' make it easier not to have to remember what each command is.

Len

Len
"Engineering is an Art. The Art of Compromise."
Len_CONSULTRON
Honored Contributor II

To all,

Attached is a ModusToolbox (MTB) version of the String_Funcs_Demo.  (It uses the String_Funcs and MenuCmds components)

Import the project into a MTB workspace.

It has six BSP build targets:

  • CY8CPROTO-062-4343W
  • CY8CPROTO-062S3-4343W
  • CY8CKIT-062-WiFi-BT
  • CY8CKIT-062-BLE
  • CY8CPROTO-063-BLE
  • CY8CKIT-062S2-43012

Chose the one that matches your Kit.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
RoRo_4659551
New Contributor II

Hi Len,

Thank you very much for these libraries.

I am designing a DAQ board using the PSoC CY8C5467AXI-LP108.

I have designed both USB2.0 and RS232 connectors for UART communication [USB as virtual COM].

According to Term_v2_2 datasheet UART and USBUART has the same Term_PutString command.

How can i add an "if" function that checks which COM is open [USB or RS232] so i can proceed in accordance?

Thanks,

Roy Roif

0 Likes
Len_CONSULTRON
Honored Contributor II

Roy,

Thank you for your post and your excellent question!

According to Term_v2_2 datasheet UART and USBUART has the same Term_PutString command.

How can i add an "if" function that checks which COM is open [USB or RS232] so i can proceed in accordance?

Here's the dilemma:

The Term component was intended to simplify standard "old-school" serial comm using UART-style API calls even if you chose the USBUART.  This is why the UART API calls don't have an inherent "Hey.  Are you there and awake?" function call.

Traditionally the "old-school" serial comm doesn't normally directly validate if the other end of the comm chain is up and running.  At best, it indirectly validates the operation of the other side.  Traditionally, the transmitting sides just dumps the data out on the line HOPING the other side receives it.

Here are a few ways of the indirectly providing a kind of flow-control:

  • The use of HW signals of DTR (Data Terminal Ready [terminals])  and DCE (Data Communication Equipment ready [Modems].
  • The use of HW signals RTS (Ready To Send) and CTS (Clear To Send) for data rate control.
  • If remote echo is turned at the Rx-end, the Tx-end can readback the Rx which should be a perfect copy of what was sent.
  • A more complicated structure is to packetize the data (limited direct string transfer) that allows a ACK/NACK (Acknowledge/No Acknowledge) return packet for every packet sent.

As listed above, there is no ONE standardized method to verify the other comm end is open and ready to receive data.  This can be considered an advantage in some applications.

For example, imagine your application uses the comm port as a debugging dump (mostly Tx operations).  You can power up your application and dump debug data to an unopened terminal without waiting for the terminal to be open.

I use this condition to my advantage.  I've created a number of applications that dumps info to a PC terminal (when open) and accepts PC terminal commands (MenuCmds component).  I can turn on the PC terminal at any time without adversely affecting the running embedded application.  I can initiate a long testing phase of the application with the PC terminal then close the PC terminal program.  Days later, I can open the PC Terminal and monitor the current results of the running embedded application.

The USBUART on the other hand does have an official standard for determining if the other end (PC terminal) is up and running.

If you use the Term component and chose the USBUART as the port type, I provide a function that monitors if the other end is open and running.  It also supports BLOCKing and NON-BLOCKing operation.

/*--------------------------------------------------------------------------------*/

//_Bool USBUART_IsTxReady(_Bool allow_blocking)

// This prevents a lockup condition if the USB is unplugged or if the host-side has a closed port.

// The SysTick Timer must be enabled to detect that the USB is unplugged or the host port is not open.

//

// Parameters:

// allow_blocking = Boolean to determine if the function waits (blocking) or doesn't (non-blocking).

// This can be used as a blocking test function or a non-blocking implementation.  Non-blocking is useful for RTOSes

//

// Returns:

// TRUE = port ready to accept new data.

// FALSE = port unplugged or failed.  Do not send new data.

//---------------------------------------------------------

This only applies to the USBUART.  If you chose the UART port type, the results are unknown.

I'm open to create a new Term V2.3 with support of end-point validation for both the USBUART (already present) and UART.  We can give it a common API function call name.

Propose something.

Len

Len
"Engineering is an Art. The Art of Compromise."
RoRo_4659551
New Contributor II

Hi Len,

Yes if you can it will be very helpful - same as the USBUART monitor function.

In addition, i want the user to press the "ENTER" keyboard after writing a command in order to receive the feedback [currently i just sent back the command itself but it will be the desired analog input value].

How do i define the ENTER keyboard in my code? i tried '\n' but for some reason its not working.

This is my current debugging code:

int main(void)

{

char buffer[100];

    CyGlobalIntEnable; /* Enable global interrupts. */

Term_Start();

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

CySysTickStart();

CySysTickSetCallback(0,&isr_systick_0);

   

    for(;;)

    {

char c;

    char enter;

    int r=0;

    int t=10;

    int i=0;

       

        for(r=0; r<101;r++)

        {

        buffer=0;

        }

        while(t>0)

        //while(Term_GetChar()!='\n')

        {

            if((c=Term_GetChar())!='\0')

            {

                PIN_LED_BLUE_Write(1);

                //CyDelay(100);

                buffer=c;

                i++;

                t--;

                Term_PutChar(c);

                Term_PutString("");

                c='\0';

                PIN_LED_BLUE_Write(0);

                //CyDelay(100);

            }

        }

        while((enter=Term_GetChar())!='\n');                     /*having problems with this command*/

        PIN_LED_BLUE_Write(1);

        //CyDelay(100);

        Term_PutString("\r\n");

        //Term_PutString("TX:\r\n");

        Term_PutString(buffer);

        Term_PutString("\r\n");

        PIN_LED_BLUE_Write(0);

     }

}

0 Likes
Len_CONSULTRON
Honored Contributor II

Roy,

The USBUART version is easy and completed in the function USBUART_IsTxReady().  There is NO similar standard for UART serial.

Hence the request from you or others to propose what to use for the UART to detect end-to-end connection.

Until I get a consensus for a good solution, I will hold on a new Term version.

About detecting the ENTER key:   Here is an excerpt of a webpage about ENTER character(s) on different systems.

  • \r represents a line break on old Macs (OS 9 and before)
  • \n represents a line break on UNIX systems (OS X, Linux)
  • \r\n represents a line break on Windows.

The real issue is dependent on the Terminal program you're using.

The same way that I use is I look for a '\n' or a '\r' to cover ENTER on all systems.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
RoRo_4659551
New Contributor II

Hi Len,

Yes i tried to use '\n' in my code but for some reason its not working [I am using windows].

Any idea why its not working?

Thanks,

Roy Roif

0 Likes
Len_CONSULTRON
Honored Contributor II

Roy,

As I indicated, the real question to ask: What is the terminal program passing to the serial port when the ENTER key is pressed?

It's possible that the ENTER results in '\r' instead of '\n'.  Try looking for '\r'.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
RoRo_4659551
New Contributor II

Hi Len,

I have modified the "Term_Demo" project and changed the "int maid (void)" according to the code i sent above.

The "TopDesign" and the pins are configured the same as in "Term_Demo".

I want the user to type a command, for example:

royroif123

after the user press "ENTER" key the command will be sent.

after that the user will receive the string on the screen.

[currently for debugging process, afterwards i will send the user the required information for every command].

Thanks,

Roy Roif

0 Likes
RoRo_4659551
New Contributor II

Another question, where can i find the IsTxReady function?

Thanks,

Roy Roif.

0 Likes
Len_CONSULTRON
Honored Contributor II

Roy,

You named the Term component an instance_name in TopDesign.   Use that instance_name.c

Another way to find it is to search for "IsTxReady" with Find.

Len

Len
"Engineering is an Art. The Art of Compromise."
RoRo_4659551
New Contributor II

Found it, thank you very much

0 Likes
RoRo_4659551
New Contributor II

Hi Len,

I have defined 2 UART interfaces in my project [UART via RS232 connector or USBUART via USB connector, not simultaneously]

I am trying to define that the code will be able to identify if the user is using the USB connector or the RS232 connector.

In order to do so, I have though [with the support of MoTa_728816] to use the VBusPresent as indication.

Unfortunately I need to modify manually the "Term_USBUART_USBUART.h" from "0u" to "1u" before building:

#define Term_USBUART_USBUART_MON_VBUS               (1u)

and I am receiving these errors when I try to build:

pastedImage_0.png

Please your support so I can use the VBusPresent in the Term component.

Thanks,

Roy Roif

0 Likes
RoRo_4659551
New Contributor II

I have solved this issue using a different method with the great support of MoTa_728816​.

Thanks anyways Len

0 Likes
Len_CONSULTRON
Honored Contributor II

Roy,

I'm glad you found a workaround.  

I don't fully understand the difficulty you were having.

Is there a suggestion from you as to a future improvement to Term?

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
RoRo_4659551
New Contributor II

Hi Len,

Solved Issue:

I have used IsTxReady function instead as shown below:

   

     #define COM_UART 1

     #define COM_USBUART 2

    com_used = COM_USBUART

    Term_Start();   

    CyDelay(1000);

   

    if (!USBUART_IsTxReady(0))

    {

    Term_USBUART_Stop();

    com_used = COM_UART;

    UART_Start();

    }

And now its fully functional, I can use both UART options [via RS232 connector and via USB connector].

Suggestions:

Yes, In my project I have tried to use the 2 X Term components [Term_UART and Term_USBUART], unfortunately I received errors according to duplicates and according to that I used 1 X UART component and 1 X Term component in order to have both RS232 and USB supported.

I would suggest to add the possibility to have 2 X Term components so people could use it for a wide communication connectors projects.

Thanks,

Roy Roif

0 Likes
Len_CONSULTRON
Honored Contributor II

Roy,

Thanks for responding.

I'll take a look at the issue you pointed out about two Term components being populated in a design.

Len

Len
"Engineering is an Art. The Art of Compromise."
MotooTanaka
Esteemed Contributor

Dear Len-san,

While I was helping Roy-san last night, we found a few points that your Terminal library can be improved.

Although this can be redundant explanation, let me write what the Roy-san's use case.

- His system uses two Terminal Lib instances, one for UART and the other for USBUART.

- But only 1 of the Terminal Lib is supposed to be used, depending on the hardware connection at startup.

     If USB cable is connected, use USBUART, or if UART connection is available use UART.

     Note: as it seemed to be difficult to check if UART is connected, we tried to decide this by checking USBUART condition.

At first we were bewildered how to figure out if the USB connection is available.

So we thought that we can use USBUART_VBusPresent() function,

but it requires the USBUART_VBUS_MONITORING_ENABLE is set.

To set this, we need to access the advanced tab in the USBFS component configuration dialog.

But we could not find a way to access the configuration dialog of USBFS (USBUART) from Term component.

Improvement Request (1)

It would be nice, if we can open the component dialog of USBFS from the Term component.

Then Roy-san found that there is another usable function USBUART_IsTxReady(),

which can be used without changing the internal component's bits.

So we could solve the first problem we encountered.

After (we thought that) we could switch between Term_UART and Term_USBUART,

the project build failed, because of multiple definition of internal variable of Terminal Library,

the variable name seemed to start with ifc or itc something.

Improvement Request (2)

It would be nice, if we can have multiple instances of Term component.

So we changed one Term component to mare UART component.

The project could be built, and at first everything seems to be OK,

but Roy-san found that when using USBUART, getchar() is not working anymore.

Note: This one was the toughest one of last night.

After an hour or so, by seeing the register names,

I came up with an idea that the instance name Term_USBUART may be too long.

So I asked Roy-san to change the name from Term_USBUART to Term.

Then getchar() resumed to work again.

Improvement Request (3)

It would be nice, if the Terminal Lib can generate waring or error when the instance name is too long

or support longer name.

Best Regards,

18-Oct-2020

Motoo Tanaka

Len_CONSULTRON
Honored Contributor II

Motoo-san,

I have detected multiple issues with more than one instance of Term.   I have corrected one of the issues and I can get multiple instances of Term working independently.

The other issues for more featured operation require a bit more thought, coding and debugging.

I have questions regarding your Improvement Requests

Improvement Request (1)

It would be nice, if we can open the component dialog of USBFS from the Term component.

Can you be more specific about this part of the request?

Then Roy-san found that there is another usable function USBUART_IsTxReady(),

which can be used without changing the internal component's bits.

So we could solve the first problem we encountered.

Is USBUART_IsTxReady() solution sufficient?  Note:  There is no practical equivalent for UART functionality other than if the FIFO is full or not.

After (we thought that) we could switch between Term_UART and Term_USBUART,

the project build failed, because of multiple definition of internal variable of Terminal Library,

the variable name seemed to start with ifc or itc something.

The issue is naming uniqueness of these auxiliary components.  Oops!  A future fix is to make these components into components with shared library instances.  A bit more work to get it there.

Improvement Request (2)

It would be nice, if we can have multiple instances of Term component.

Working on that.   Hopefully there will be a fix soon.

So we changed one Term component to mare UART component.

The project could be built, and at first everything seems to be OK,

but Roy-san found that when using USBUART, getchar() is not working anymore.

Note: This one was the toughest one of last night.

After an hour or so, by seeing the register names,

I came up with an idea that the instance name Term_USBUART may be too long.

So I asked Roy-san to change the name from Term_USBUART to Term.

Then getchar() resumed to work again.

Interesting.  I've confirmed this is an issue.   I don't think it is because of the long names.   C can parse and operate with very long variable names.  Hmm.  I'll get back to you with an answer.

Improvement Request (3)

It would be nice, if the Terminal Lib can generate waring or error when the instance name is too long

or support longer name.

If issue highlighted in Improvement Request (3) is due to too long of instance name, I'll try to create a pre-compiler warning.

Motoo-san and Roy,

Thank you for using Term and I appreciate the feedback to make this a more useful component.

If either of you has created a component, you can appreciate that it can get complex quickly.   This is especially true when trying to make it work with multiple instances.  Bravo to Cypress for creating a great substructure of Creator to help designers minimize complex reusable code generation.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
MotooTanaka
Esteemed Contributor

Dear Len-san,

Thank you for your quick response.

> I have detected multiple issues with more than one instance of Term.  

> I have corrected one of the issues and I can get multiple instances of Term working independently.

That is a very nice news!

Improvement Request (1)

It would be nice, if we can open the component dialog of USBFS from the Term component.

> Can you be more specific about this part of the request?

So we wanted to check if the USB connector is connected, which means the project will use USBUART,

at first I was thinking of timeout, but we found a function "USBUART_VBusPresent()" which seems to be able to tell us if VBus is present.

But this function is not enabled unless we check VBUS Monitoring option in the USBUART Configure Dialog > Advanced tab.

And we could not find a way to call up this Dialog from Term Configuration Dialog.

001-USBUART_Config.JPG

So I wished if there were a way to invoke this dialog from Term Component Configuration Dialog.

> Is USBUART_IsTxReady() solution sufficient? 

> Note:  There is no practical equivalent for UART functionality other than if the FIFO is full or not.

If the "USBUART_VBusPresent()" function reports the status of VBus without initializing USBUART,

it would be preferable.

But for the time being, I hope that Roy-san can survive with USBUART_IsTxRead() function.

> The issue is naming uniqueness of these auxiliary components. 

> Oops!  A future fix is to make these components into components with shared library instances.  A bit more work to get it there.

Yes, that was what I was afraid.

Fortunately this time, the other UART can be a "real" UART, so Roy-san did not have to use Term lib for that uart channel.

> Working on that.   Hopefully there will be a fix soon.

If this will be supported it will be very nice.

But, IMHO, among these 3, (2) has the least priority.

> Interesting.  I've confirmed this is an issue.   I don't think it is because of the long names.  

> C can parse and operate with very long variable names.  Hmm.  I'll get back to you with an answer.

Agreed. But the generated internal Register names were very long.

Meantime, as Roy-san named the component "Term_USBUART", it might have affected the naming scheme of

Term component or USBUART component.

Anyway, I'm very interested in the real reason of this problem.

One thing I'd like to mention again is that, even with that name "Term_USBUART", PutString() was working OK.

Since GetChar() was not working, we could not confirm about PutChar() though.

> If issue highlighted in Improvement Request (3) is due to too long of instance name, I'll try to create a pre-compiler warning.

If it's the case, it will be a great help.

> Thank you for using Term and I appreciate the feedback to make this a more useful component.

You are very welcome.

And if not for this Library, handling both UART and USBUART at the same time could be much more difficult.

> If either of you has created a component, you can appreciate that it can get complex quickly. 

> This is especially true when trying to make it work with multiple instances. 

I have developed an ASIC Design System at HP, so I think that I can understand the difficulty.

(Although we could use C++ then, from Page 38...)

https://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1993-08.pdf

> Bravo to Cypress for creating a great substructure of Creator to help designers minimize complex reusable code generation.

Well I understand the basic concept, but I need lots more study to be able to handle it by myself.

Best Regards,

18-Oct-2020

Motoo Tanaka

0 Likes
Len_CONSULTRON
Honored Contributor II

Motoo-san,

Improvement Request (1)

It would be nice, if we can open the component dialog of USBFS from the Term component.

> Can you be more specific about this part of the request?

So we wanted to check if the USB connector is connected, which means the project will use USBUART,

at first I was thinking of timeout, but we found a function "USBUART_VBusPresent()" which seems to be able to tell us if VBus is present.

But this function is not enabled unless we check VBUS Monitoring option in the USBUART Configure Dialog > Advanced tab.

And we could not find a way to call up this Dialog from Term Configuration Dialog.

So I wished if there were a way to invoke this dialog from Term Component Configuration Dialog.

> Is USBUART_IsTxReady() solution sufficient?

> Note:  There is no practical equivalent for UART functionality other than if the FIFO is full or not.

If the "USBUART_VBusPresent()" function reports the status of VBus without initializing USBUART,

it would be preferable.

But for the time being, I hope that Roy-san can survive with USBUART_IsTxRead() function.

Let me update the Term 2.2 to 2.3 as a quick release to address most of the issues you and Roy pointed out.  I believe I can pass through the Advance tabs options.  However, you will notice that they are not implemented as Cypress customizer code using C#.  I wouldn't mind calling customizer C# code as a pass-through if you know how to do that.  For now, all configurable parameters will have to be implemented by Tabs with field-adjustable parameters.

There are additional improvements I'd like to add.  I can save it for another future version.

> Interesting.  I've confirmed this is an issue.   I don't think it is because of the long names. 

> C can parse and operate with very long variable names.  Hmm.  I'll get back to you with an answer.

Agreed. But the generated internal Register names were very long.

Meantime, as Roy-san named the component "Term_USBUART", it might have affected the naming scheme of

Term component or USBUART component.

Anyway, I'm very interested in the real reason of this problem.

One thing I'd like to mention again is that, even with that name "Term_USBUART", PutString() was working OK.

Since GetChar() was not working, we could not confirm about PutChar() though.

I found the solution as listed in the post below.  In summary:

change cyapicallbacks.h from:

#include <Term_cyapicallbacks.h>  

to match the new Term instance name:

#include <Term_USBUART_cyapicallbacks.h>  

Len

Len
"Engineering is an Art. The Art of Compromise."
Len_CONSULTRON
Honored Contributor II

Roy and Motoo,

I have a beta version of Term v2.3.  I think I have achieved pass-through the VBUS monitoring.  I'm not that familiar with this capability.

To test if it is working do I:

  • Use a CY8CKIT_059.
  • set Term to Term_type=USB_UART with:

001-USBUART_Config.JPG

  • Then I need to use KitProg connected for power.
  • Plugging and unplugging the USB cable on the target board will yield USBUART_VBusPresent() results.

Is this the correct steps to test if the VBUS monitoring is working?

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
MotooTanaka
Esteemed Contributor

Dear Len-san,

First of all, as I wrote before, we could not reach that far.

But the step you are mentioning seems to be correct to me.

What we (read this as "Roy-san") want to achieve is

to check if there is VBUS voltage applied for Term_USBUART

so that we can  proceed with Term_USBUART

or we need to switch to Term_UART.

Anyway, seeing the library is evolving rapidly is very nice.

Thank you!

Best Regards,

19-Oct-2020

Motoo Tanaka

0 Likes
Len_CONSULTRON
Honored Contributor II

Motoo-san,

My beta version seems to be working for VBUS monitoring detection based on my procedure above.

I have a few more checkouts to perform for unit testing.

If all goes well, I will release the new version to the forum.

Len

Len
"Engineering is an Art. The Art of Compromise."
Len_CONSULTRON
Honored Contributor II

Roy and Motoo-san,

Here is v2.3 of Term.  It also includes a few other components as well.

I've also attached two Term demos.  One that uses only one Term component.  The other uses 4 Term components with one of the Term instances as USBUART and the ability to use VBUS detect and SOF output.

Let me know if there is still issues.

Len

Len
"Engineering is an Art. The Art of Compromise."
Len_CONSULTRON
Honored Contributor II

Motoo-san and Roy,

So we changed one Term component to mare UART component.

The project could be built, and at first everything seems to be OK,

but Roy-san found that when using USBUART, getchar() is not working anymore.

Note: This one was the toughest one of last night.

After an hour or so, by seeing the register names,

I came up with an idea that the instance name Term_USBUART may be too long.

So I asked Roy-san to change the name from Term_USBUART to Term.

Then getchar() resumed to work again.

I reproduced the issue.  I renamed my Term component (as USBUART) to Term_USBUART.  Same results as you received.

The issue is that when you rename the Term component, you also need to change the line in the cyapicallbacks.h from:

#include <Term_cyapicallbacks.h>

to match the new Term instance name:

#include <Term_USBUART_cyapicallbacks.h>

Once this was changed, the _GetChar() function works again.

I did notice a strange issue.  A "Clean" of the project or a "Generate Build" does not remove the old Term_cyapicallbacks.h from the Generated_Source directory.  Hmm.  A Creator 'bug'? 

Len

Len
"Engineering is an Art. The Art of Compromise."