PIC C18: Reading bits from a byte - bit-manipulation

I have a very elementary question. However, what ever I tried, I couldn't successfully implement this.
I have a shift register (74LS164) connected to PIC18F2550 with the following hardware configuration:
// Data pin
#define SCLCD_DATA LATBbits.LATB7
#define SCLCD_DATA_TRIS TRISBbits.TRISB7
// Clock pin
#define SCLCD_CLOCK LATBbits.LATB6
#define SCLCD_CLOCK_TRIS TRISBbits.TRISB6
LEDs are connected to the output pins of 74LS164 to view its status. I have an 8-bit variable declared as unsigned char. I want to send the bits of this variable to the shift register. The shift register has internal flip-flops whose outputs are named as Q0-Q7. The first sent bit loads into Q0, when you send a second bit, previous Q0 shifts to Q1 and the newly sent bit comes to Q0, and this goes so on as you send succeeding bits. When the sending is completed, LSB of the variable is supposed to be on the Q0 of the shift register, and MSB will be on Q7.
My code is like this (Language is C18):
void SCLCD_SendSerialBits(unsigned char unRegister)
{
// ucRegister is always passed as 0b10101010 for test
for (i=0; i<8; i++)
{
SCLCD_CLOCK = 0;
SCLCD_DATA = ((ucRegister & 0b10000000) == 0b10000000) ? 1 : 0;
ucRegister = ucRegister << 1;
SCLCD_CLOCK = 1;
}
}
The code above doesn't run as I want to. When I run it, all the LEDs light on, as if I had loaded 0b11111111 into the ucRegister variable.
However, the following one works very well:
void SCLCD_SendSerialBits(void)
{
SCLCD_CLOCK = 0; SCLCD_DATA = 1; SCLCD_CLOCK = 1;
SCLCD_CLOCK = 0; SCLCD_DATA = 0; SCLCD_CLOCK = 1;
SCLCD_CLOCK = 0; SCLCD_DATA = 1; SCLCD_CLOCK = 1;
SCLCD_CLOCK = 0; SCLCD_DATA = 0; SCLCD_CLOCK = 1;
SCLCD_CLOCK = 0; SCLCD_DATA = 1; SCLCD_CLOCK = 1;
SCLCD_CLOCK = 0; SCLCD_DATA = 0; SCLCD_CLOCK = 1;
SCLCD_CLOCK = 0; SCLCD_DATA = 1; SCLCD_CLOCK = 1;
SCLCD_CLOCK = 0; SCLCD_DATA = 0; SCLCD_CLOCK = 1;
}
What is wrong with my code? I thing the error is most likely to be on the line SCLCD_DATA = ((ucRegister & 0b10000000) == 0b10000000) ? 1 : 0;, but no matter how much I look at it, it looks perfectly OK to me. What is wrong with my code?
Any help will be appreciated.

Your code looks like it should work. I would write it like this to be more readable and efficient (assuming your system has a barrel shifter):
for (i=7; i>=0; i--)
{
SCLCD_CLOCK = 0;
SCLCD_DATA = ((ucRegister >> i) & 1);
SCLCD_CLOCK = 1;
}
For systems without a barrel shifter, a variation of your code
unsigned char ucMask = 0x80;
for (i=0; i<8; i++)
{
SCLCD_CLOCK = 0;
SCLCD_DATA = (ucRegister & ucMask) ? 1:0;
ucMask >>= 1;
SCLCD_CLOCK = 1;
}
If my first or second examples work, then it sounds like the compiler is not handling the constant values or compares correctly in your original code.

Might just be a typo, but your parameter is unRegister not ucRegister. Is it possible that ucRegister is a global which is 0b11111111?

Related

CreateTruncOrBitCast or CreateAnd

I am using LLVM for code instrumentation, where each byte of a variable needs to be extracted. I have two alternatives:
for (int i = 0; i < 8; i++)
{
Value* cur_byte = CreateTruncOrBitCast(var, Int8Ty);
cur_byte = IRB.CreateZExt(cur_byte, Int64Ty);
/* do something */
var = IRB.CreateLShr(var, 8);
}
Or
for (int i = 0; i < 8; i++)
{
Value* cur_byte = CreateAnd(var, 0xFF);
/* do something */
var = IRB.CreateLShr(var, 8);
I would like to consult which method is faster, or is there any other better method?

Corrupted value in Arduino array

The program's supposed to constantly listen for 433 MHz messages coming from soil moisture sensors in plant pots and decide whether or not to activate a pump based on those readings.
Additionally it's supposed to check wired water sensors while it's listening.
All 433 MHz Received Messages should be stored within the array sensor_data[i].
At startup the positions 1to NUM_Sensors(in this case 3) is filled with the constant int NO_DATA (500).
The Problem is, that for some reason I get corrupted Number in the array number 3:
Serial Print:
Wired Flower Pots Checked
All Sensors or Timeout reached
Array_Print: 500
Array_Print: 500
Array_Print: 30001
In this case the 30001 appears in the array with no specific reason (I guess).. there's no received message.
Here's the code changed to the minimum so that the error occurs:
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
//Receiver Setup for wireless soil moisture readings
unsigned long last_ground_check = 0;
const int NUM_SENSORS = 3;
const uint32_t SENSOR_TIMEOUT = 30000;
int sensor_data[NUM_SENSORS];
uint32_t last_message_time = 0;
uint32_t elapsed = 0;
float total_value = 0;
float real_value = 0;
int count = 0;
const int NO_DATA = 500;
boolean received = false;
//###################//
void setup()
{
Serial.begin(9600);
mySwitch.enableReceive(INT1); // Interrupt 2 = Pin 2
delay(1500);
Serial.println("<><><><><><><><><><><><>");
Serial.println(" Start ");
Serial.println("<><><><><><><><><><><><>");
for (int i = 0; i <= NUM_SENSORS; i++) {
sensor_data[i] = NO_DATA;
}
} // Setup END
void loop()
{
if (received == false) {
if (millis() - last_ground_check > 10000) {
Serial.println("Checking Wired Flower Pot");
}
Serial.println("Wired Flower Pots Checked");
last_ground_check = millis();
}
if (mySwitch.available()) { // Start whenever a 433 MHz Message is received
received = true;
double value = mySwitch.getReceivedValue();
delay(1000);
int sensor_id = 1;
int sensor_value = 2;
if (sensor_value >= 0 && sensor_value <= 100) {
sensor_data[sensor_id] = sensor_value;
last_message_time = millis();
mySwitch.resetAvailable();
}
}
byte sensors_reported = 0;
for (int i = 0; i <= NUM_SENSORS; i++) {
if (NO_DATA != sensor_data[i]) {
sensors_reported += 1; // CODE Gets here because of corrupted Array Value although no message was received
}
}
if (sensors_reported != 0) {
uint32_t elapsed = millis() - last_message_time;
if (NUM_SENSORS == sensors_reported || elapsed > SENSOR_TIMEOUT) {
Serial.println("All Sensors or Timeout reached");
for (int i = 1; i <= NUM_SENSORS; i++) {
Serial.print("Array_Print: ");
Serial.println(sensor_data[i]);
}
for (int i = 1; i <= NUM_SENSORS; i++) {
if (sensor_data[i] < NO_DATA) {
count++;
total_value += sensor_data[i];
}
}
real_value = total_value / count;
Serial.print("Soil Moisture: ");
Serial.println(real_value);
if (real_value <= 20) {
//Set Pump ON
}
for (int i = 1; i <= NUM_SENSORS; i++) {
sensor_data[i] = NO_DATA;
}
total_value = 0;
real_value = 0;
sensors_reported = 0;
count = 0;
received = false;
Serial.println("RESET #### RESET ####");
delay(5000);
}
}
} //LOOP
You first allocate an array of size NUM_SENSORS=3, and then you continue to use it as if it was of size 4.
Your array has 3 elements sensor_data[0], [1] and [2]. Your loop condition i <= NUM_SENSORS results in accessing sensor_data[3] which is just some memory after your last array element. Even if you set sensor_data[3] in your setup, if the same memory is referenced by some other variable, the NO_DATA will be overwritten.
Index your loops over the data array from i = 0 to i < NUM_SENSORS.

How to set a timeout in a function that is running in a thread

I'm doing a blocking communication with a server using a client. the function is running in a thread. I would like to set a time out functionality. I'm not using boost or something like that. I'm using windows threading library.
Here is the function that I want to set a time out functionality in it.
bool S3W::IWFSData::WaitForCompletion(unsigned int timeout)
{
if (m_Buffer)
{
while (!m_Buffer.IsEmpty())
{
unsigned int i = 0;
char gfname[255]; // must be changed to SBuffer
char minHeightArr[8], maxHeightArr[8], xArr[8], yArr[8];
m_PingTime += timeout;
if (m_PingTime > PONG_TIMEOUT)
{
m_PingTime = 0;
return false;
}
while (m_Buffer[i] != '\0')
{
gfname[i] = m_Buffer[i];
i++;
}
gfname[i] = '\0';
for (unsigned int j = 0; j < 8; j++)
{
minHeightArr[j] = m_Buffer[i++];
}
for (unsigned int j = 0; j < 8; j++)
{
maxHeightArr[j] = m_Buffer[i++];
}
double minH = *(double*)minHeightArr;
double maxH = *(double*)maxHeightArr;
for (unsigned int j = 0; j < 8; j++)
{
xArr[j] = m_Buffer[i++];
}
for (unsigned int j = 0; j < 8; j++)
{
yArr[j] = m_Buffer[i++];
}
double x = *(double*)xArr;
double y = *(double*)yArr;
OGRFeature *poFeature = OGRFeature::CreateFeature(m_Layer->GetLayerDefn());
if(poFeature)
{
poFeature->SetField("gfname", gfname);
poFeature->SetField("minHeight", minH);
poFeature->SetField("maxHeight", maxH);
OGRPoint point;
point.setX(x);
point.setY(y);
poFeature->SetGeometry(&point);
if (m_Layer->CreateFeature(poFeature) != OGRERR_NONE)
{
std::cout << "error inserting an area" << std::endl;
}
else
{
std::cout << "Created a feature" << std::endl;
}
}
OGRFeature::DestroyFeature(poFeature);
m_Buffer.Cut(0, i);
}
}
return true;
}
There is a thread that is setting the data to the buffer
int S3W::ImplConnection::Thread(void * pData)
{
SNet::SAutoLock lockReader(m_sLock);
// RECEIVE DATA
SNet::SBuffer buffer;
m_data->SrvReceive(buffer);
// Driver code for inserting data into the buffer in blocking communication
SNet::SAutoLock lockWriter(m_sLockWriter);
m_data->SetData("ahmed", strlen("ahmed"));
double minHeight = 10;
double maxHeight = 11;
double x = 4;
double y = 2;
char minHeightArr[sizeof(minHeight)];
memcpy(&minHeightArr, &minHeight, sizeof(minHeight));
char maxHeightArr[sizeof(maxHeight)];
memcpy(&maxHeightArr, &maxHeight, sizeof(maxHeight));
char xArr[sizeof(x)];
memcpy(&xArr, &x, sizeof(x));
char yArr[sizeof(y)];
memcpy(&yArr, &y, sizeof(y));
m_data->SetData(minHeightArr, sizeof(minHeightArr));
m_data->SetData(maxHeightArr, sizeof(maxHeightArr));
m_data->SetData(xArr, sizeof(xArr));
m_data->SetData(yArr, sizeof(yArr));
m_data->WaitForCompletion(1000);
return LOOP_TIME;
}
In general, you should not use threads for these purposes, because when terminating a thread like this, the process and the other threads could be left in an unknown state. Look here for the explanation.
Therefore, consider using procceses instead. Read here about opening processes in c++.
If you do want to use threads, you can exit the thread after the time passed.
Make a loop (as you have) that will break when some time has elapsed.
#include <ctime>
#define NUM_SECONDS_TO_WAIT 5
// outside your loop
std::time_t t1 = std::time(0);
// and in your while loop, each iteration:
std::time_t t2 = std::time(0);
if ((t2 - t1) >= NUM_SECONDS_TO_WAIT)
{
break; // ...
}
You can have a class member which holds a time stamp (when to timeout, set its value to currentTime + intervalToTimeout). In WaitForCompletion(), get current time and compare with the timeout time.
I assume in your code, m_PingTime is the time you start communication. You want to timeout after 1000 ms. What you need to do is, in WaitForCompletion():
while (!m_Buffer.IsEmpty())
{
...
long time = getCurrentTime(); // fake code
if (m_PingTime + timeout < time)
{
m_PingTime = 0;
return false;
}
...
}
Here is something I did, if you want to implement it yourself:
clock_t startTime = clock();
clock_t timeElapsed;
double counter;
while(true){
if(counter>=10){
//do what you want upon timeout, in this case it is 10 secs
}
startTime = clock();
}

extracting binary data out of 8-bit byte and converting it to primitive types [C++]

I have a vector of integers vector<int> that has 48 items in it. I want to extract binary data out of this(not sure if this is correct way to call it please edit it if it's wrong) i.e. a sequence of one or more bits and then convert them to a primitive type like int. I have come up with this solution:
int extractValue(vector<int> v, int startBit, int endBit) {
int beginByteIndex = (startBit / 8);
int endByteIndex = (endBit / 8);
vector<bool> bits;
bits.clear();
int startIndex = startBit % 8;
int endIndex = endBit % 8;
int value = v[beginByteIndex];
value = (value << startIndex);
int temp = 8;
if (beginByteIndex == endByteIndex) {
temp = endIndex + 1;
}
for (int i = startIndex; i < temp; i++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
for (int i = beginByteIndex + 1; i < endByteIndex; i++) {
value = v[i];
for (int j = 0; j < 8; j++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
}
if (endByteIndex > beginByteIndex) {
value = v[endByteIndex];
for (int i = 0; i <= endIndex; i++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
}
int size = bits.size();
int p = 1;
int result = 0;
for (int i = size - 1; i >= 0; i--) {
result += (bits[i] * p);
p *= 2;
}
return result;
}
but this function is long, difficult to read and is done in C style. could someone please suggest a C++ way of doing this. I'm almost certain that C++ has a good, short and elegant way of doing this. also please edit the question so others with similar problem can benefit from it. Unfortunately My English is not that good to express it in a more general way.
EDIT:
as requested in comments for example I want to extract following information with following positions and length:
int year = extractValue(data, 0, 6);
int month = extractValue(data, 7, 10);
int day = extractValue(data, 11, 15);
a simple solution:
convert each byte to hex string (ostringstream or even sprintf can help), you got 2 digits, range is 0 to F.
for each hex digit you can create the bitmap like this:
0 = 0000,
1 = 0001,
2 = 0010,
...,
F = 1111,
add bits to the vector according to the bitmap
to recover - you take 4 bits and translate it back to digit, then take 2 digits and convert back to byte (say by adding 0x to the hex, isringstream to byte).

Qt QImage pixel manipulation problems

I'm currently in the process of writing a steganography application with Qt. I am trying to hide my message bits in the least significant bit of the blue colour of the pixel.
From debugging I can tell that this section is working as it should. However after hiding my bits in the message I then save the image and then reopen it. This is where the problem develops.
When I read in the (reopened) image the scanLines that I read in are not the same as the ones I wrote previously, and I can't figure out why. Maybe it's just me being stupid, or maybe I'm missing something. Any help would be much appreciated.
The code I have so far is as follows
void MainWindow::Encrypt(QImage image, QString message) {
if(image.isNull()) {
qDebug() << "PROBLEM";
}
image = image.convertToFormat(QImage::Format_ARGB32);
QVector<bool> bvec;
QByteArray bytes = message.toAscii();
char mask;
QRgb tempPix;
for(int i = 0; i < bytes.size(); i++) {
for(int j = 0; j < 8; j++) {
mask = (0x01 << j);
bvec.push_back((bytes[i] & mask) == mask);
}
}
if(image.height() < bvec.size()) {
qDebug() << "Not enough space in image";
}
for(int j = 0; j < bvec.size(); j++) {
QRgb *pixel = (QRgb *)image.scanLine(j);
tempPix = *pixel;
int blue = qBlue(tempPix);
blue &= 0xFE;
blue |= (bvec[j] == 1) ? 0x01 : 0x00;
*pixel = qRgba(qRed(tempPix), qGreen(tempPix), blue, qAlpha(tempPix));
}
if(image.save(filename) != true) {
emit addToStatusLog("Did not save. Error");
}
}
void MainWindow::Decrypt(QImage image) {
char temp = 0x00;
qint8 mask = 0x01;
QVector<bool> bvec;
QRgb *pixel;
int blue;
image = image.convertToFormat(QImage::Format_ARGB32);
for(int i = 0; i < image.height(); i++) {
pixel = (QRgb *)image.scanLine(i);
blue = qBlue(*pixel);
bvec.push_back((blue & mask) == mask);
}
for(int j = 0; j < bvec.size(); j++) {
if(j % 8 == 0 && j != 0) {
qDebug() << temp;
temp = 0x00;
}
temp |= (bvec[j]) ? (0x01 << (j%8)) : 0x00;
}
qDebug() << temp;
}
Thanks
Make sure you're not saving using a lossy format, such as JPEG.