Mask 4Bit Ports bitwise

Off topic discussions that do not fit into any of the above can go here. Please keep it clean and respectful.
User avatar
RemoRitzmann
Member++
Posts: 23
Joined: Wed Feb 03, 2010 10:23 pm

Mask 4Bit Ports bitwise

Post by RemoRitzmann »

Do you know a source sample that shows how to use a 4 bit in port or a 4 bit out port bitwise?

Somehow like this:
on stdcore [0]: in port p_spi_miso = (XS1_PORT_4F << 3);
on stdcore [0]: out port p_spi_mosi = (XS1_PORT_4E & 0b0001);

Is there a way to mask them? I found nothing like that in the samples so far.

Furthermore - is it possible to define some bits as out and others as in from the same 4bit port?
It might be good enough to change in and out on runtime. Is this possible?


User avatar
paul
XCore Addict
Posts: 169
Joined: Fri Jan 08, 2010 12:13 am

Post by paul »

A ports pins can only be used together. You can't mask off pins and use them individually. If you want to do this then you need to do it yourself in software - this obviously will only work for slow protocols!

Changes in direction on a port are possible. Just define the port without the "in" or "out" keywords and you can change the direction when using the <: and :> operators for inputting and outputting on ports.

Hope that helps,
Paul
Paul

On two occasions I have been asked, 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
User avatar
RemoRitzmann
Member++
Posts: 23
Joined: Wed Feb 03, 2010 10:23 pm

Post by RemoRitzmann »

Dear Paul

Thanks - yes that helps! Fortunately speed has not my major focus on these signals.

Regards Remo
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

Whilst you can't use individual bits of a 4 bit port for inputs and outputs, so long as the bits are either all inputs or all outputs, you can, of course mask the bits. Here's examples of how to do it for both input and output.

So reading a port would be something like this:

Code: Select all

#define maskBitA 1
#define maskBitB 2
#define maskBitC 4
#define maskBitD 8

mixedInPort :> mixedPortRead;
if (mixedPortRead & maskBitB) {
  // Do something here
} else {
  // Do something else here
}
And writing a port would be something like this:

Code: Select all

// Keep track of what is output on that port
int mixedOutVal = 0; // Global, just like the port

...
driveMixedOut (bitValue, mask) { // bitValue is 1 or 0; mask is 1,2,4,8
  mixedOutVal = mixedOutVal  & (0xf - mask);
  if (bitValue == 1) {
    mixedOutVal += mask;
  }
  mixedOutPort <: mixedOutVal;
}
User avatar
RemoRitzmann
Member++
Posts: 23
Joined: Wed Feb 03, 2010 10:23 pm

Post by RemoRitzmann »

Hi paul and Woody

You helped me a lot - with your suggestions you preserved me from a lot of rewiring work!
I already had nightmares about changing 56 signals on 4 XC-2 boards.

I connected both your ideas by reading a port first and rewrite it only by changing specific bits.
So I'm able to write and read single bits in a 4bit port. Thanks for your fast reply.

Regards
Remo
User avatar
RemoRitzmann
Member++
Posts: 23
Joined: Wed Feb 03, 2010 10:23 pm

Post by RemoRitzmann »

To finish this Topic, I post the SPI code where I use 4bit ports:

Code: Select all

#define HALF_CLK_PERIOD	49     //490 ns
#define delay_10ns 		1	// 10ns
#define BIT3 0x08
#define BIT2 0x04
#define BIT1 0x02
#define BIT0 0x01

on stdcore [3]: port p_CS03_SDO03_SCK02_CS02 = XS1_PORT_4A; //  P4A3 / P4A2 / P4A1 / P4A0
on stdcore [3]: port p_IRQ03_SDO02_SDI02_IRQ02 = XS1_PORT_4B; //  P4B3 / P4B2 / P4B1 / P4B0

unsigned M02SPIGet(unsigned int adr){ // aaaaaaa
	unsigned int ret = 0;
	unsigned int i = 0;
	unsigned int time = 0;
	unsigned int OutVal;
	unsigned int inVal;
	
	adr = adr | 0b10000000; // 1aaaaaa(read) = 0x80
	adr = adr << 24;  // 1aaaaaa 00000000 00000000 00000000 = 0x80 00 00 00
	adr = bitrev(adr);		 // MSBit first 0x80 00 00 00 -> 0x00 00 00 a1
	p_CS03_SDO03_SCK02_CS02 :> OutVal;			// chip select to 0 und falling Edge
	OutVal = OutVal & 0b1100;						// ...
	p_CS03_SDO03_SCK02_CS02 <: OutVal;			// chip select to 0 and falling Edge
	p_IRQ03_SDO02_SDI02_IRQ02 :> OutVal;				// set SDI = 0 / needs 240 ns
	OutVal = OutVal & (0x0f - BIT1); 					// ...
	p_IRQ03_SDO02_SDI02_IRQ02 <: OutVal @ time;		// set SDI = 0 / takes time
	time += 50*delay_10ns; // compensates for loop
	for(i = 0; i < 16;i++){
		p_CS03_SDO03_SCK02_CS02 :> OutVal;				// falling Edge
		p_CS03_SDO03_SCK02_CS02 @ time <: (OutVal & (0xF - BIT1));	// falling Edge
		if(i < 16){
			driveOutIRQ03_SDO02_SDI02_IRQ02((adr >> i), BIT1); // set adress bit on SDI
		}
		time += HALF_CLK_PERIOD;			// adds time
		p_CS03_SDO03_SCK02_CS02 :> OutVal;			// rising Edge
		OutVal += BIT1;									// ...
		p_CS03_SDO03_SCK02_CS02 @ time <: OutVal ;	//  rising Edge
		p_IRQ03_SDO02_SDI02_IRQ02 :> inVal; // Ports lesen // 3333 3333 B3B3 BB3B (for 0x88)
		inVal =(inVal & BIT2) >> 2;			// read SDO // 0000 0000 1010 1101 (for 0x88)
		ret = ret +(inVal << i);				// read SDO // AD0000 (for 0x88)	
        time += HALF_CLK_PERIOD; - 24*delay_10ns;
	}
	ret = bitrev(ret) >> 16;			// MSB first  // 0x00 00 00 AD  / 1010 1101 = AD
	ret = ret & 0xFF;
	p_CS03_SDO03_SCK02_CS02 :> OutVal;					// falling Edge
	p_CS03_SDO03_SCK02_CS02 @ time <: (OutVal & (0xF - BIT1));	// falling Edge
	driveOutIRQ03_SDO02_SDI02_IRQ02(0, BIT1); // SDI to 0
	driveOutCS03_SDO03_SCK02_CS02(1, BIT0); // chip select to 1 (active low)
	return ret;
}


void driveOutCS03_SDO03_SCK02_CS02(unsigned int bitValue, unsigned int mask) { // bitValue is 1 or 0; mask is 1,2,4,8
	unsigned int OutVal = 0;
	p_CS03_SDO03_SCK02_CS02 :> OutVal;
	OutVal = OutVal & (0x0F - mask); // vvvv &(1111 - 1) = vvvv & 1110 = vvv0
	if((bitValue & 0x01) == BIT0) {
		OutVal += mask; // vvv0 += 0001
	}
	p_CS03_SDO03_SCK02_CS02 <: OutVal; // 0001
}


void driveOutIRQ03_SDO02_SDI02_IRQ02(unsigned int bitValue, unsigned int mask) { // bitValue is 1 or 0; mask is 1,2,4,8
	unsigned int OutVal = 0;
	p_IRQ03_SDO02_SDI02_IRQ02 :> OutVal; 
	OutVal = OutVal & (0x0F - mask);
	if((bitValue & 0x01) == BIT0) {
		OutVal += mask;
	}
	p_IRQ03_SDO02_SDI02_IRQ02 <: OutVal;
}
The trick is to read the port shortly before writing it with the changed bits.
Please leave a short comment, when it helped you or when you know something for improvement.