How Can I change objects name by a loop in C lang? - c

How Can I change objects name by a loop?
I want create a light effect like knight-rider's one. With a PIC
I thought instead of turning on and off manually to use a loop for change RB line number.
I want to change the last number of this Port line name: like RB01 RB02 like this
my code is like this
for(int i = 0; i>6 ; i++ ){
PORTB = 0X00;
RB+i = 1;
}
Are there any kind of method do something like this? thanks

Assuming RB01, RB02, etc are just convenient #defines for accessing the bits in PORTB, you can write the loop with bitwise arithmetic and not use RB0* at all.
for ( int i = 0; i != 6; ++ i ) {
PORTB = 1 << i; /* one light at a time */
/* or */
PORTB = ( 1 << i + 1 ) - 1; /* light all in sequence */
}

It's not very elegant, but one way is to do it like this:
PORTB = 0x00;
for (i = 0; i < 6; ++i)
{
RB00 = (i == 0);
RB01 = (i == 1);
RB02 = (i == 2);
RB03 = (i == 3);
RB04 = (i == 4);
RB05 = (i == 5);
// note: you probably want to put a delay in here, e.g. 200 ms
}
If you want to keep the previous LEDs on each time you turn on a new one then you can do that like this:
PORTB = 0x00;
for (i = 0; i < 6; ++i)
{
RB00 = (i >= 0);
RB01 = (i >= 1);
RB02 = (i >= 2);
RB03 = (i >= 3);
RB04 = (i >= 4);
RB05 = (i >= 5);
// note: you probably want to put a delay in here, e.g. 200 ms
}

No, there is no way to "generate" symbol names that way. You can use bit masks for manipulating the latch register of the port in question.

I would probably use a table:
struct portbits
{
sometype bit; // Not quite sure what "RB0..RB5" actually translate to.
};
struct portbits bits[] =
{
RB00,
RB01,
RB02,
RB03,
RB04,
RB05,
RB06,
RB07,
};
for(i = 0; i < 7; i++)
{
bits[i] = 1;
}

Related

Losing data bit when reading from GPIO by libgpiod on Linux

I am using Debian (8.3.0-6) on an embedded custom board and working on the dht11 sensor.
Briefly,
I need to read 40 bits from a GPIO pin and each bit can take a max 70 microseconds. When bit-level is high for max 28us or 70us, it means is logic 0 or 1, respectively. (So I have a timeout controller for each bit and if a bit takes more than 80us, I need to stop the process.).
In my situation, sometimes I can read all 40 bits correctly but sometimes I can't do it and the function of libgpiod gpiod_line_get_value(line); is missing the bit (my code is below). I am trying to figure out that why I cant read and lose a bit, what is the reason for that. But I haven't found a sensible answer yet. So I was wondering What am I missing out?, What is the proper way to GPIO programming?
Here is what I wanted to show you, How do I understand what I am missing a bit? Whenever I catch a bit, I am setting and resetting another GPIO pin at the rising and falling edge of a bit (So I can see which bit missing). Moreover, as far as I see I am always missing the two edges on one bit or one edge on two bits consecutively (rising and falling or falling and rising). In the first picture, you can see which bit I missed, the second is when I read all bits correctly.
Here it is my code:
//********************************************************* Start reading data bit by low level (50us) ***************************
for (int i = 0; i < DHT_DATA_BYTE_COUNT ; i++) //DHT_DATA_BYTE_COUNT = 5
{
for (int J = 7; J > -1; J--)
{
GPIO_SetOutPutPin(testPin); //gpiod_line_set_value(testPin, 1);
int ret;
start = micros();
do
{
ret = GPIO_IsInputPinSet(dht11pin);//gpiod_line_get_value(dht11pin);
delta = micros() - start;
if(ret == -1)
{
err_step.step = 9;
err_step.ret_val = -1;
return -1;
}
if(delta > DHT_START_BIT_TIMEOUT_US) //80us
{
err_step.step = 10;
err_step.ret_val = -2;
err_step.timestamp[is] = delta;
err_step.indx[is].i = i;
err_step.indx[is++].j = J;
GPIO_ResetOutPutPin(testPin);
return -2;
}
}while(ret == 0);
GPIO_ResetOutPutPin(testPin);
err_step.ret_val = 10;
GPIO_SetOutPutPin(testPin);
start = micros();
do
{
ret = GPIO_IsInputPinSet(dht11pin);
delta = micros() - start;
if(ret == -1)
{
err_step.step = 11;
err_step.ret_val = -1;
return -1;
}
if(delta > DHT_BEGIN_RESPONSE_TIMEOUT_US) //80us
{
err_step.step = 12;
err_step.ret_val = -2;
err_step.timestamp[is] = delta;
err_step.indx[is].i = i;
err_step.indx[is++].j = J;
return -2;
}
}while(ret == 1);
err_step.timestamp[is] = delta;
err_step.indx[is].i = i;
err_step.indx[is++].j = J;
GPIO_ResetOutPutPin(testPin);
err_step.ret_val = 10;
(delta > DHT_BIT_SET_DATA_DETECT_TIME_US) ? bitWrite(dht11_byte[i],J,1) : bitWrite(dht11_byte[i],J,0);
}
}

Optimizing a read statement

I have build a led cube using transistors, shift registers and an arduino nano (and it kinda works). I know shift registers may be a poor design choice but I have to work with what I got so please don't get stuck on that in your answers.
There is this piece of code:
bool input[32];
void resetLeds()
{
input[R1] = 0;
input[G1] = 0;
input[B1] = 0;
input[R2] = 0;
input[G2] = 0;
input[B2] = 0;
input[R3] = 0;
input[G3] = 0;
input[B3] = 0;
input[R4] = 0;
input[G4] = 0;
input[B4] = 0;
input[X1Z1] = 1;
input[X1Z2] = 1;
input[X1Z3] = 1;
input[X1Z4] = 1;
input[X2Z1] = 1;
input[X2Z2] = 1;
input[X2Z3] = 1;
input[X2Z4] = 1;
input[X3Z1] = 1;
input[X3Z2] = 1;
input[X3Z3] = 1;
input[X3Z4] = 1;
input[X4Z1] = 1;
input[X4Z2] = 1;
input[X4Z3] = 1;
input[X4Z4] = 1;
}
void loop()
{
T = micros();
for(int I = 0; I < 100; I++)
{
counter++;
if(counter >= 256 / DIVIDER) counter = 0;
for(int i = 0; i < 64; i += 4)
{
x = i / 16;
z = (i % 16) / 4;
resetLeds();
input[XZ[x][z]] = 0;
for(y = 0; y < 4; y++)
{
index = i + y;
if(counter < xyz[index][0]) input[Y[y][RED]] = 1;
if(counter < xyz[index][1]) input[Y[y][GREEN]] = 1;
if(counter < xyz[index][2]) input[Y[y][BLUE]] = 1;
}
PORTB = 0;
for(int j = 0; j < 32; j++)
{
bitWrite(OUT_PORT, 4, 0);
bitWrite(OUT_PORT, 3, input[j]);
PORTB = OUT_PORT;
bitWrite(OUT_PORT, 4, 1);
PORTB = OUT_PORT;
}
bitWrite(OUT_PORT, 0, 1);
PORTB = OUT_PORT;
}
}
T = micros() - T;
Serial.println(T / 100);
}
The runtime of a single iteration is reported to be 1274 microseconds, but I need it to be even lower to build a pwm function of sorts (manually turning a transistor on and off through a shift register). While optimizing I found this strange behavior I cannot explain. There is this line in the code:
bitWrite(OUT_PORT, 3, input[j]);
When I remove this line or change input[j] to 0 the runtime is halved. Apparently, an array lookup takes about 20 microseconds. But I find it very weird since I am indexing this array in more places in the code (when writing) and there it takes 23 microseconds for 28 writes.
Can somebody please explain to me what is going on and/or how to make this piece of code run faster? I guess you can do writes in a pipelined manner but a read stalls the code completely since you cannot continue before you receive the value from cache. But then again, I hardly doubt a read from cache should take 23 whole microseconds.
[EDIT 27/10/2020 16:55]
The part of the code that writes to the shiftregisters has a lot of bitWrites which are time consuming. Instead of writing the bits every time I implemented preconfigured options for the byte to write to PORTB:
PORTB = LATCH_LOW;
for(int j = 0; j < 32; j++)
{
if(input[j] == 0)
{
PORTB = CLOCK_OFF_DATA_0;
PORTB = CLOCK_ON_DATA_0;
}
else
{
PORTB = CLOCK_OFF_DATA_1;
PORTB = CLOCK_ON_DATA_1;
}
}
PORTB = LATCH_HIGH;
This cuts my running time roughly in half, which is kind of fast enough but I wonder I could get it to run even faster. When I remove everything from the loop except for the writing to the shift registers and I remove the input[j] read, I get a runtime of 200 microseconds. This means that if I could remove dependence on the input[j] read and compute its value inline I should be able to get at least another 2 times speed up. To achieve 8 bit PWM I calculated I need the running time to be 40 microseconds or less so I am going to stick with 16 (instead of 256) brightness levels for now to prevent flicker.
[EDIT 28/10/2020 19:38]
I went into the platform.txt and change the optimization flag to -Ofast. This got my iteration time down another 200 microseconds!

Fill an array at index n with m times data without bit-fields

I try to send a maximum of 8 bytes of data. The first 4 bytes are always the same and involve defined commands and an address. The last 4 bytes should be variable.
So far I'm using this approach. Unfortunatly I was told to not use any for loops in this case.
// Construct data
local_transmit_buffer[0] = EEPROM_CMD_WREN;
local_transmit_buffer[1] = EEPROM_CMD_WRITE;
local_transmit_buffer[2] = High(MSQ_Buffer.address);
local_transmit_buffer[3] = Low(MSQ_Buffer.address);
uint_fast8_t i = 0;
for(i = 0; i < MSQ_Buffer.byte_lenght || i < 4; i++){ // assign data
local_transmit_buffer[i + 4] = MSQ_Buffer.dataPointer[i];
}
This is some test code I'm trying to solve my problem:
#include <stdio.h>
__UINT_FAST8_TYPE__ local_transmit_buffer[8];
__UINT_FAST8_TYPE__ MSQ_Buffer_data[8];
void print_local(){
for (int i = 0; i < 8; i++)
{
printf("%d ", local_transmit_buffer[i]);
}
printf("\n");
}
void print_msg(){
for (int i = 0; i < 8; i++)
{
printf("%d ", MSQ_Buffer_data[i]);
}
printf("\n");
}
int main(){
// assign all local values to 0
for (int i = 0; i < 8; i++)
{
local_transmit_buffer[i] = 0;
} print_local();
// assign all msg values to 1
for (int i = 0; i < 8; i++)
{
MSQ_Buffer_data[i] = i + 1;
} print_msg();
*(local_transmit_buffer + 3) = (__UINT_FAST32_TYPE__)MSQ_Buffer_data;
printf("\n");
print_local();
return 0;
}
The first loops fills up the local_transmit_buffer with 0's and the MSQ_Buffer with 0,1,2,...
local_transmit_buffer -> 0 0 0 0 0 0 0 0
MSQ_Buffer_data -> 1 2 3 4 5 6 7 8
Now i want to assign the first 4 values of MSQ_Buffer_data to local_transmit_buffer like this:
local_transmit_buffer -> 0 0 0 0 1 2 3 4
Is there another way of solving this problem without using for loops or a bit_field?
Solved:
I used the memcpy function to solve my problem
// uint_fast8_t i = 0;
// for(i = 0; i < MSQ_Buffer.byte_lenght || i < 4; i++){ // assign data
// local_transmit_buffer[i + 4] = MSQ_Buffer.dataPointer[i];
// }
// copy a defined number data from the message to the local buffer to send
memcpy(&local_transmit_buffer[4], &MSQ_Buffer.dataPointer, local_save_data_length);
Either just unroll the loop manually by typing out each line, or simply use memcpy. In this case there's no reason why you need abstraction layers, so I'd write the sanest possible code, which is just manual unrolling (and get rid of icky macros):
uint8_t local_transmit_buffer [8];
...
local_transmit_buffer[0] = EEPROM_CMD_WREN;
local_transmit_buffer[1] = EEPROM_CMD_WRITE;
local_transmit_buffer[2] = (uint8_t) ((MSQ_Buffer.address >> 8) & 0xFFu);
local_transmit_buffer[3] = (uint8_t) (MSQ_Buffer.address & 0xFFu);
local_transmit_buffer[4] = MSQ_Buffer.dataPointer[0];
local_transmit_buffer[5] = MSQ_Buffer.dataPointer[1];
local_transmit_buffer[6] = MSQ_Buffer.dataPointer[2];
local_transmit_buffer[7] = MSQ_Buffer.dataPointer[3];
It is not obvious why you can't use a loop though, this doesn't look like the actual EEPROM programming (where overhead code might cause hiccups), but just preparations for it. Start to question such requirements.
Also note that you should not use __UINT_FAST8_TYPE__ but uint8_t. Never use homebrewed types but always stdint.h. But you should not be using fast types for a RAM buffer used for EEPROM programming, because it cannot be allowed to contain padding, ever. This is a bug.

Read from array two bytes at a time?

I declare an array
uint8_t data_buffer[64];
I write into it, and then I need to iterate over it looking at the data it stores. The data is written in groups of two.
Right now I am doing something messy like this
for(int i = 1; i < BUFFER_LEN + 1; i += 2)
{
if(data_buffer[i] == 0xff && data_buffer[i+1] == 0xff)
{
write_led_states(i/2 + 1, OFF);
}
else
{
write_led_states(i/2 + 1, ON);
}
}
But I'd much prefer to be able to read two bytes of data at a time from the buffer so I could do something more like this:
for(int i = 1; i < BUFFER_LEN + 1; i++)
{
if(data_buffer[i] == 0xffff) // where data_buffer is being read two bytes at a time
{
write_led_states(i, OFF);
}
else
{
write_led_states(i, ON);
}
}
Another way of saying what I want to do is to remap the indices so they go from looking like this:
[1][2][3][4][5][6][7][8]
to like this:
[1...][2...][3...][4...]
Is this possible?
Change this:
uint8_t data_buffer[64];
to this:
uint16_t data_buffer[32];
uint_16_t uses 2 bytes (16 bits) per element (and adjust the size to half of 64).
PS: Your code seems to access an array out of bounds, which invokes Undefined Behavior, here:
for(int i = 1; i < BUFFER_LEN + 1; i += 2)
Array indexing starts from 0, so this should start from 0 and the condition should be i < BUFFER_LEN.
However, with my appraoch, you don't need to increment by two, so you simply do a clean for loop, like this:
for(int i = 0; i < BUFFER_LEN; ++i)
Simply use a uint16_t instead, which is 2 bytes per element,
uint16_t data_buffer[32];
be careful with endianness if it can be a problem.
Note: it appears that you don't know that arrays are 0 indexed, so
for (int i = 1; i < BUFFER_LEN + 1; i += 2)
shoul probably be (most likely),
for (int i = 0; i < BUFFER_LEN; i += 2)
And in case you do what I suggest, then each element is 2 bytes so you'd need half the number of elements and of course you would increment i by 1
for (int i = 0; i < BUFFER_LEN; ++i)
You can combine the two uint8_t elements into a single uint16_t by bhtshifting:
for (int i = 1; i < BUFFER_LEN + 1; i += 2) {
uint16_t pair = data_buffer[i] << 8 | data_buffer[i+1];
LEDState newLEDState = (pair == 0xffff) ? OFF : ON; // replace "LEDState" with the proper type
write_led_states(i/2 + 1, newLEDState);
}

C, can't compare two buffers

I am working with some C code and I'm totally stuck in this function. It should compare two buffers with some deviator. For example if EEPROM_buffer[1] = 80, so TxBuffer values from 78 to 82 should be correct!
So the problem is that it always returns -1. I checked both buffers, data is correct and they should match, but won't. Program just runs while until reach i = 3 and returns -1..
I compile with atmel studio 6.1, atmel32A4U microcontroller..
int8_t CheckMatching(t_IrBuff * tx_buffer, t_IrBuff * tpool)
{
uint8_t i = 0;
uint16_t * TxBuffer = (uint16_t*) tx_buffer->data;
while((TxBuffer->state != Data_match) || (i != (SavedBuff_count))) // Data_match = 7;
{
uint16_t * EEPROM_buffer = (uint16_t*) tpool[i].data;
for(uint16_t j = 0; j < tpool[i].usedSize; j++) // tpool[i].usedSize = 67;
{
if(abs(TxBuffer[j] - EEPROM_buffer[j]) > 3)
{
i++;
continue;
}
}
i++;
TxBuffer->state = Data_match; // state value before Data_match equal 6!
}
tx_buffer->state = Buffer_empty;
if(i == (SavedBuff_count)) // SavedBuff_count = 3;
{
return -1;
}
return i;
}
Both your TxBuffer elements and EEPROM_buffer elements are uint16_t. When deducting 81 from 80 as uint16_t it would give 0xffff, with no chance of abs to help you. Do a typecast to int32_t and you will be better off.

Resources