I have defined some values, see below, and I can`t use them properly.
#define add 000001
#define sub 000010
#define jmp 000111
#define IMM 10000
#define ADDR 10001
In my code, I set an address in hex.
parameter1 = false;
parameter1 = false;
uint64_t data = 0xffffffff05001e00;
uint16_t vector[4];
memcpy(vector, &data, sizeof(uint64_t));
int currentPosition = 0;
while (currentPosition < 4) {
header = vector[currentPosition];//header
opcode = header >> 0xA & 0x3F;
src1 = header >> 0x5 & 0x1F;
src2 = header & 0x1F;
if (src1 == ADDR || src1 == IMM) { parameter1 = true; }
if (src2 == ADDR || src2 == IMM) { parameter2 = true; }
....
currentPosition++;
}
header = 1e00 in this case ( because it`s vector[0] )
Forward it will do:
opcode = 0x7, src1 =0x10, src2= 0x0.
That means in binary: 000111 10000 00000 -> jmp IMM NULL
When first if is called, parameter1 should get the value true; but this never happend. Why is that happening?
I have not defined correctly IMM value?
Thanks!!!
None of your defined numbers are binary numbers
#define add 000001 // octal literals because it starts with 0
#define sub 000010
#define jmp 000111
#define IMM 10000 // decimal literals
#define ADDR 10001
None of them are binary representations as you assume in your code.
Since C++14 you can write a binary literal as (example from https://en.cppreference.com/w/cpp/language/integer_literal):
int b = 0b101010; // C++14
In general I would strongly advise you to not use #define, unless you deliberatly choose to get all the trouble that come with using macros.
To access the defined values I just re-write them like this:
#define add 0x1
#define sub 0x2
#define jmp 0x7
#define IMM 0x10
#define ADDR 0x11
And now it`s working fine.
I am working on a Motorola HCS08 µCU in CodeWarrior V10.6, I am trying to create an extern bitfield which has bits from existing registers. The way the bitfields are created in the µCU header is like
typedef unsigned char byte;
typedef union {
byte Byte;
struct {
byte PTAD0 :1;
byte PTAD1 :1;
byte PTAD2 :1;
byte PTAD3 :1;
byte PTAD4 :1;
byte PTAD5 :1;
byte PTAD6 :1;
byte PTAD7 :1;
} Bits;
} PTADSTR;
extern volatile PTADSTR _PTAD #0x00000000;
#define PTAD _PTAD.Byte
#define PTAD_PTAD0 _PTAD.Bits.PTAD0
#define PTAD_PTAD1 _PTAD.Bits.PTAD1
#define PTAD_PTAD2 _PTAD.Bits.PTAD2
#define PTAD_PTAD3 _PTAD.Bits.PTAD3
#define PTAD_PTAD4 _PTAD.Bits.PTAD4
#define PTAD_PTAD5 _PTAD.Bits.PTAD5
#define PTAD_PTAD6 _PTAD.Bits.PTAD6
#define PTAD_PTAD7 _PTAD.Bits.PTAD7
Which will let the register value be changed either by PTAD = 0x01, or PTAD_PTAD0 = 1, for example. This definition is basically the same for PTAD, PTBD, PTCD, ... PTGD, the only thing changing is the address.
My attemp to create a custom bitfield out of the previous existing variables is
typedef union {
byte Byte;
struct {
byte *DB0;
byte *DB1;
byte *DB2;
byte *DB3;
byte *DB4;
byte *DB5;
byte *DB6;
byte *DB7;
} Bits;
} LCDDSTR;
I would create and initialize the bitfield as LCDDSTR lcd = {{&PTGD_PTGD6, &PTBD_PTBD5, ...}}, because by some reason, the initialization like LCDSTR lcd = {*.Bits.DB0 = &PTGD_PTGD6, *.Bits.DB1 = &PTBD_PTBD5, ...} (treating it as a struct, please correct me again) advice in How to initialize a struct in accordance with C programming language standards does not work with this compiler (it does work on an online compiler).
However, as you may see I am sort of grouping the bits, and (if it would work) I would be able to change the values of the actual register by doing *lcd.Bits.DB0 = 1, or something like that, but if I do lcd.Byte = 0x00, I would be changing the last (I think) byte of the memory address contained in lcd.Bits.DB0, you know, because the struct doesn't actually contains the data, but the pointers instead.
How would I go on achieving a struct that is able to contain and modify bits from several registers? (I guess the problem here is that in memory the bits are not one next to the other, which I guess would make it easier). Is it even possible? I hope it is.
How would I go on achieving a struct that is able to contain and modify bits from several registers? (I guess the problem here is that in memory the bits are not one next to the other..
I don't think you can do it with a struct. That is because bitfields by definition have to occupy the same or contiguous addresses.
However macros may be useful here
#define DB0 PTGD_PTGD6
#define DB1 PTBD_PTBD5
....
And to clear the bits to all 0's or set to all 1's you can use a multiline macro
#define SET_DB(x) do { \
PTGD_PTGD6 = x; \
PTBD_PTBD5 = x; \
...... \
} while(0)
How would I go on achieving a struct that is able to contain and modify bits from several registers?
You can't.
A structure must represent a single, continuous block of memory -- otherwise, operations like taking the sizeof the structure, or performing operations on a pointer to one would make no sense.
If you want to permute the bits of a value, you will need to find some way of doing so explicitly. If the order of your bits is relatively simple, this may be possible with a few bitwise operations; if it's weirder, you may need to use a lookup table.
Beyond that: bitfields in C are pretty limited. The language does not make a lot of guarantees about how a structure containing bitfields will end up laid out in memory; they are generally best avoided for portable code. (Which doesn't apply here, as you're writing code for a specific compiler/microcontroller combination, but it's worth keeping in mind in general.)
Your union does unfortunately not make any sense, because it forms a union of one byte and 8 byte*. Since a pointer is 16 bit on HCS08, this ends up as 8*2 = 16 bytes of data, which can't be used in any meaningful way.
Please note that the C structure called bit-fields is very poorly specified by the standard and therefore should be avoided in any program. See this.
Please note that the Codewarrior register maps aren't remotely close to following the C standard (nor MISRA-C).
Please note that structs in general are problematic for hardware register mapping, since structs can contain padding. You don't have that problem on HCS08 specifically, since it doesn't require alignment of data. But most MCUs do require that.
It is therefore better to roll out your own register map in standard C if you have that option. The port A data register could simply be defined like this:
#define PTAD (*(volatile uint8_t*)0x0000U)
#define PTAD7 (1U << 7)
#define PTAD6 (1U << 6)
#define PTAD5 (1U << 5)
#define PTAD4 (1U << 4)
#define PTAD3 (1U << 3)
#define PTAD2 (1U << 2)
#define PTAD1 (1U << 1)
#define PTAD0 (1U << 0)
As we can tell, defining the bit masks is mostly superfluous anyway, as PTAD |= 1 << 7; is equally readable to PTAD |= PTAD7;. This is because this was a pure I/O port. Defining textual bit masks for status and control registers on the other hand, increases the readability of the code significantly.
If you want to modify bits from several registers, you'd do something like the following:
Assume we have a RGB (red-green-blue) LED, common cathode, with 3 colors connected to 3 different pins on 3 different ports. Instead of beating up the PCB designer, you could do this:
#define RGB_RED_PTD PTAD
#define RGB_RED_PTDD PTADD
...
#define RGB_BLUE_PTD PTBD
#define RGB_BLUE_PTDD PTBDD
...
#define RGB_GREEN_PTD PTDD
#define RGB_GREEN PTDD PTDDD
#define RGB_RED_PIN 1
#define RGB_BLUE_PIN 5
#define RGB_GREEN_PIN 3
You can now set these independently of where they happen to be located on the hardware:
void rgb_init (void)
{
RGB_RED_PTDD |= (1 << RGB_RED_PIN);
RGB_BLUE_PTDD |= (1 << RGB_BLUE_PIN);
RGB_GREEN_PTDD |= (1 << RGB_GREEN_PIN);
}
void rgb_yellow (void)
{
RGB_RED_PTD |= (1 << RGB_RED_PIN);
RGB_BLUE_PTD &= ~(1 << RGB_BLUE_PIN);
RGB_GREEN_PTD |= (1 << RGB_GREEN_PIN);
}
And so on. Examples were for HCS08 but the same can of course be used universally on any MCU with direct port I/O.
It sounds like an approach such as the following is along the lines of where you would like to go with a solution.
I have not tested this as I do not have the hardware however this should provide an alternative to look at.
This assumes that you want to turn on particular pins or turn off particular pins but there will not be a case where you will want to turn on some pins and turn off other pins for a particular device in a single operation. If that should be the case I would consider making the type of RegPinNo be an unsigned short to include an op code for each register/pin number combination.
This also assumes that timing of operations is not a critical constraint and that the hardware has sufficient horsepower such that small loops are not much of a burden on throughput and hogging CPU time needed for other things. So this code may need changes to improve optimization if that is a consideration.
I assume that you want some kind of a easily readable way of expressing a command that will turn on and off a series of bits scattered across several areas of memory.
The first thing is to come up with a representation of what such a command would look like and it seems to me that borrowing from a char array to represent a string would suffice.
typedef byte RegPinNo; // upper nibble indicates register number 0 - 7, lower nibble indicates pin number 0 - 7
const byte REGPINNOEOS = 0xff; // the end of string for a RegPinNo array.
And these would be used to define an array of register/pin numbers as in the following.
RegPinNo myLed[] = { 0x01, 0x12, REGPINNOEOS }; // LED is addressed through Register 0, Pin 0 and Register 1, Pin 1 (zero based)
So at this point we have a way to describe that a particular device, an LED in this case, is addressed through a series of register/pin number items.
Next lets create a small library of functions that will use this representation to actually modify the specific pins in specific registers by traversing this array of register/pin numbers and performing an operation on it such as setting the bit in the register or clearing the bit in the register.
typedef unsigned char byte;
typedef union {
byte Byte;
struct {
byte PTAD0 : 1;
byte PTAD1 : 1;
byte PTAD2 : 1;
byte PTAD3 : 1;
byte PTAD4 : 1;
byte PTAD5 : 1;
byte PTAD6 : 1;
byte PTAD7 : 1;
} Bits;
} PTADSTR;
// Define a pointer to the beginning of the register area. This area is composed of
// 8 different registers each of which is one byte in size.
// We will address these registers as Register 0, Register 1, ... Register 7 which just happens
// to be how C does its zero based indexing.
// The bits representing pins on the PCB we will address as Pin 0, Pin 1, ... Pin 7.
extern volatile PTADSTR (* const _PTAD) = 0x00000000;
void SetRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte |= pins[bPinNo];
}
}
void ClearRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte &= ~pins[bPinNo];
}
}
void ToggleRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte ^= pins[bPinNo];
}
}
You would use the above something like the following. Not sure what a time delay function would look like in your environment so I am using a function Sleep() which takes an argument as to the number of milliseconds to delay or sleep.
void LightLed (int nMilliSeconds)
{
RegPinNo myLed[] = { 0x01, 0x12, REGPINNOEOS }; // LED is addressed through Register 0, Pin 0 and Register 1, Pin 1 (zero based)
SetRegPins(myLed); // turn on the LED
Sleep(nMilliSeconds); // delay for a time with the LED lit
ClearRegPins(myLed); // turn the LED back off
}
Edit - A Refinement
A more efficient implementation that would allow multiple pins to be set in a particular register at the same time would be to define the use of RegPinNo as being an unsigned short` with the upper byte being the register number and the lower byte being the pins to manipulate as a bit mask for the byte.
With this approach you would have a SetRegPins() function that would look like the following. A similar change would be needed for the other functions.
void SetRegPins(RegPinNo *x)
{
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 8) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0xFF; // get the pin mask
_PTAD[bRegNo].Byte |= bPinNo;
}
}
And the typedefs would look like:
typedef unsigned short RegPinNo; // upper byte indicates register number 0 - 7, lower byte provides pin mask
const byte REGPINNOEOS = 0xffff; // the end of string for a RegPinNo array.
And these elements would be used like:
void LightLed (int nMilliSeconds)
{
RegPinNo myLed[] = { 0x0002, 0x0103, REGPINNOEOS }; // LED is addressed through Register 0, Pin 1 and Register 1, Pin 0 and Pin 1 (zero based)
SetRegPins(myLed); // turn on the LED
Sleep(nMilliSeconds); // delay for a time with the LED lit
ClearRegPins(myLed); // turn the LED back off
}
I have been measuring clock cycle count on the cortex m4 and would now like to do it on the cortex m7. The board I use is STM32F746ZG.
For the m4 everything worked with:
volatile unsigned int *DWT_CYCCNT;
volatile unsigned int *DWT_CONTROL;
volatile unsigned int *SCB_DEMCR;
void reset_cnt(){
DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register
DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register
SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register
*SCB_DEMCR = *SCB_DEMCR | 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CONTROL = 0;
}
void start_cnt(){
*DWT_CONTROL = *DWT_CONTROL | 0x00000001 ; // enable the counter
}
void stop_cnt(){
*DWT_CONTROL = *DWT_CONTROL & 0xFFFFFFFE ; // disable the counter
}
unsigned int getCycles(){
return *DWT_CYCCNT;
}
The problem is that the DWT_CTRL register isn't changed when I run on the m7 and remains 0x40000000 instead of changing to 0x40000001 so the cycle count is always zero. From what I have read in other posts it seems like you need to set the FP_LAR register to 0xC5ACCE55 to be able to change DWT_CTRL.
I added these defines (have tried both FP_LAR_PTR addresses below):
#define FP_LAR_PTR ((volatile unsigned int *) 0xe0000fb0) //according to reference
//#define FP_LAR_PTR ((volatile unsigned int *) 0xe0002fb0) //according to guy on the internet
// Lock Status Register lock status bit
#define DWT_LSR_SLK_Pos 1
#define DWT_LSR_SLK_Msk (1UL << DWT_LSR_SLK_Pos)
// Lock Status Register lock availability bit
#define DWT_LSR_SLI_Pos 0
#define DWT_LSR_SLI_Msk (1UL << DWT_LSR_SLI_Pos)
// Lock Access key, common for all
#define DWT_LAR_KEY 0xC5ACCE55
and this function:
void dwt_access_enable(unsigned int ena){
volatile unsigned int *LSR;
LSR = (volatile unsigned int *) 0xe0000fb4;
uint32_t lsr = *LSR;;
//printf("LSR: %.8X - SLI MASK: %.8X\n", lsr, DWT_LSR_SLI_Msk);
if ((lsr & DWT_LSR_SLI_Msk) != 0) {
if (ena) {
//printf("LSR: %.8X - SLKMASK: %.8X\n", lsr, DWT_LSR_SLK_Msk);
if ((lsr & DWT_LSR_SLK_Msk) != 0) { //locked: access need unlock
*FP_LAR_PTR = DWT_LAR_KEY;
printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
}
} else {
if ((lsr & DWT_LSR_SLK_Msk) == 0) { //unlocked
*FP_LAR_PTR = 0;
//printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
}
}
}
}
When I call the uncommented print I get 0xC5ACCE55 but when I printed it after the return of the function I get 0x00000000 and I have no idea why. Am I on the right track or is this completely wrong?
Edit: I think it also would be good to mention that I have tried without all the extra code in the function and only tried to change the LAR register.
BR
Gustav
Looking at the docs again, I'm now incredibly suspicious of a typo or copy-paste error in the ARM TRM. 0xe0000fb0 is given as the address of ITM_LAR, DWT_LAR and FP_LSR (and equivalently for *_LSR). Since all the other ITM registers are in page 0xe0000000, it looks an awful lot like whoever was responsible for that part of the Cortex-M7 documentation took the Cortex-M4 register definitions, added the new LAR and LSR to the ITM page, then copied them to the DWT and FPB pages updating the names but overlooking to update the addresses.
I'd bet my dinner that you're unwittingly unlocking ITM_LAR (or the real FP_LAR), and DWT_LAR is actually at 0xe0001fb0.
EDIT by dwelch
Somebody owes somebody a dinner.
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
PUT32(0xE000EDFC,0x01000000);
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
PUT32(0xE0001000,0x40000001);
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
PUT32(0xE0001FB0,0xC5ACCE55);
PUT32(0xE0001000,0x40000001);
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
output
00000000
00000000
00000000
00000000
00000003
40000000
00000000
00000000
00000003
40000000
00000000
00000000
00000001
40000001
0000774F
0000B311
The table in the TRM is funny looking and as the other documentation shows you add the 0xFB0 and 0xFB4 to the base, the rest of the DWT for the Cortex-M7 is 0xE0001xxx and indeed it appears that the LAR and LSR are ate 0xE0001FB0 and 0xE0001FB4.
I would advise against creating your own register definitions when they are defined as part of the CMSIS - to do so requires that both the documentation and your interpretation of it are correct. In this case it appears that the documentation is indeed incorrect, but that the CMSIS headers are correct. It is a lot easier to validate the CMSIS headers automatically than it is to verify the documentation is correct, so I would trust the CMSIS every time.
I am not sure what register FP_LAR might refer to, but your address assignment refers to ITM_LAR, but it seems more likely that you intended DWT_LAR which Cortex-M4 lacks.
Despite my advice to trust it, CMSIS 4.00 omits to define masks for DWT_LSR/SWT_LAR, but I believe they are identical to the corresponding ITM masks.
Note also that the LAR is a write-only register - any attempt to read it is meaningless.
Your code using CMSIS would be:
#include "core_cm7.h" // Applies to all Cortex-M7
void reset_cnt()
{
CoreDebug->DEMCR |= 0x01000000;
DWT->CYCCNT = 0; // reset the counter
DWT->CTRL = 0;
}
void start_cnt()
{
DWT->CTRL |= 0x00000001 ; // enable the counter
}
void stop_cnt()
{
DWT->CTRL &= 0xFFFFFFFE ; // disable the counter
}
unsigned int getCycles()
{
return DWT->CYCCNT ;
}
// Not defined in CMSIS 4.00 headers - check if defined
// to allow for possible correction in later versions
#if !defined DWT_LSR_Present_Msk
#define DWT_LSR_Present_Msk ITM_LSR_Present_Msk
#endif
#if !defined DWT_LSR_Access_Msk
#define DWT_LSR_Access_Msk ITM_LSR_Access_Msk
#endif
#define DWT_LAR_KEY 0xC5ACCE55
void dwt_access_enable( unsigned ena )
{
uint32_t lsr = DWT->LSR;;
if( (lsr & DWT_LSR_Present_Msk) != 0 )
{
if( ena )
{
if ((lsr & DWT_LSR_Access_Msk) != 0) //locked: access need unlock
{
DWT->LAR = DWT_LAR_KEY;
}
}
else
{
if ((lsr & DWT_LSR_Access_Msk) == 0) //unlocked
{
DWT->LAR = 0;
}
}
}
}
I'm working on code to compute CRC32 using the hardware CRC support that's built into the ARM Cortex-M4 processor. For reference, there's an application note that describes the hardware here:
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00068118.pdf
Basically, you write 32-bits of data at a time to a memory-mapped register (CRC_DR), and then you read the resulting CRC back from the same address. However, the CRC this produces is quite different than the standard result that the software CRC32 libraries produce. I finally found someone who had written code that manipulates the Cortex result to produce the "standard" result:
http://www.cnblogs.com/shangdawei/p/4603948.html
My code (shown below and adapted from the above solution) now produces the "standard" result, but I suspect there are more calls to function ReverseBits than are actually necessary. I'm hoping someone can tell me if it can be simplified.
Thanks!
Dan
#define RCC_BASE 0x40023800
#define RCC_AHB1ENR *((uint32_t *) (RCC_BASE + 0x30))
#define CRC_BASE 0x40023000
#define CRC_DR *((volatile uint32_t *) (CRC_BASE + 0x00))
#define CRC_IDR *((volatile uint32_t *) (CRC_BASE + 0x04))
#define CRC_CR *((volatile uint32_t *) (CRC_BASE + 0x08))
uint32_t ARMcrc32(void *data, uint32_t bytes)
{
uint32_t *p32 = data ;
uint32_t crc, crc_reg ;
RCC_AHB1ENR |= 1 << 12 ; // Enable CRC clock
CRC_CR |= 0x00000001 ; // Reset the CRC calculator
while (bytes >= 4)
{
CRC_DR = ReverseBits(*p32++) ;
bytes -= 4 ;
}
crc_reg = CRC_DR ;
crc = ReverseBits(crc_reg) ;
if (bytes > 0)
{
uint32_t bits = 8 * bytes ;
uint32_t xtra = 32 - bits ;
uint32_t mask = (1 << bits) - 1 ;
CRC_DR = crc_reg ;
CRC_DR = ReverseBits((*p32 & mask) ^ crc) >> xtra ;
crc = (crc >> bits) ^ ReverseBits(CRC_DR);
}
return ~crc ;
}
I built a virtual machine in C. And for this I have the Instruction
pushc <const>
I saved the command and the value in 32 Bit. The First 8 Bit are for the command and the rest for the value.
8 Bit -> Opcode
24 Bit -> Immediate value
For this I make a macro
#define PUSHC 1 //1 is for the command value in the Opcode
#define IMMEDIATE(x) ((x) & 0x00FFFFFF)
UPDATE:
**#define SIGN_EXTEND(i) ((i) & 0x00800000 ? (i) | 0xFF000000 : (i))**
Then I load for testing this in a unsigned int array:
Update:
unsigned int code[] = { (PUSHC << 24 | IMMEDIATE(2)),
(PUSHC << 24 | SIGN_EXTEND(-2)),
...};
later in my code I want to get the Immediate value of the pushc command and push this value to a stack...
I get every Instruction (IR) from the array and built my stack.
UPDATE:
void exec(unsigned int IR){
unsigned int opcode = (IR >> 24) & 0xff;
unsigned int imm = (IR & 0xffffff);
switch(opcode){
case PUSHC: {
stack[sp] = imm;
sp = sp + 1;
break;
}
}
...
}
}
Just use a bitwise AND to mask out the lower 24 bits, then use it in the case:
const uint8_t opcode = (IR >> 24) & 0xff;
const uint32_t imm = (IR & 0xffffff);
switch(opcode)
{
case PUSHC:
stack[sp] = imm;
break;
}
I shifted around the extraction of the opcode to make the case easier to read.