Pic Display cycle between 5 and 0 - c++

Here is our code. We tried to make the display cycle between 5-0, but it's stuck at 5.
void main()
{
unsigned char count=0;
unsigned char table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
TRISC=0;
while(1) {
for(count=0;count<6;count++) {
PORTC=table[count];
delay_ms(59);
if(count==5 && count>=0)
{
count -= count;
}
}
}
}
It goes to 5, but it's not coming back to 0.
Our proteus design and other stuff is true. The only problem is in the code we wrote.
Pic 16F877A

Your if-statement decreases the count from 5 to 4, but the for-loop then increases the value back to 5. Once the count reaches 5, this will repeat forever. You'll need to re-design the logic to get an up-ramp/down-ramp behavior (that cycles between 0 and 5). Try something like this:
void main()
{
unsigned char count=0;
unsigned char table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
TRISC=0;
bool increment = true;
while(1) {
PORTC=table[count];
delay_ms(59);
// Increment or decrement.
count += increment ? 1 : -1;
// Switch from incrementing to decrementing (or vice versa).
if (count >= 5 || count <= 0) {
increment = !increment;
}
}
}
This defines a boolean flag increment to designate whether we are incrementing or decrementing the count variable. When count gets to the upper or lower bound, the increment flag gets inverted.

Related

Is there a "not equal compare and exchange" or "fetch add on not equal" for C++?

Or any way to implement?
Let's have an atomic:
std::atomic<int> val;
val = 0;
Now I want to update val only if val is not zero.
if (val != 0) {
// <- Caveat if val becomes 0 here by another thread.
val.fetch_sub(1);
}
So maybe:
int not_expected = 0;
val.hypothetical_not_compare_exchange_strong(not_expected, val - 1);
Actually the above also will not work because val may get updated between val - 1 and the hypothetical function.
Maybe this:
int old_val = val;
if (old_val == 0) {
// val is zero, don't update val. some other logic.
} else {
int new_val = old_val - 1;
bool could_update = val.compare_exchange_strong(old_val, new_val);
if (!could_update) {
// repeat the above steps again.
}
}
Edit:
val is a counter variable, not related to destruction of an object though. It's supposed to be an unsigned (since count can never be negative).
From thread A: if type 2 is sent out, type 1 cannot be sent out unless type 2 counter is 0.
while(true) {
if counter_1 < max_type_1_limit && counter_2 == 0 && somelogic:
send_request_type1();
counter_1++;
if some logic && counter_2 == 0:
send_request_type2();
counter_2++;
}
thread B & C: handle response:
if counter_1 > 0:
counter_1--
// (provided that after this counter_1 doesn't reduce to negative)
else
counter_2--
The general way to implement not available atomic operations is using a CAS loop; in your case it would look like this:
/// atomically decrements %val if it's not zero; returns true if it
/// decremented, false otherwise
bool decrement_if_nonzero(std::atomic_int &val) {
int old_value = val.load();
do {
if(old_value == 0) return false;
} while(!val.compare_exchange_weak(old_value, old_value-1));
return true;
}
So, Thread B & C would be:
if(!decrement_if_nonzero(counter_1)) {
counter_2--
}
and thread A could use plain atomic loads/increments - thread A is the only one who increments the counters, so its check about counter_1 being under a certain threshold will always hold, regardless of what thread B and C do.
The only "strange" thing I see is the counter_2 fixup logic - in thread B & C it's decremented without checking for zero, while in thread A it's incremented only if it's zero - it looks like a bug. Did you mean to clamp it to zero in thread B/C as well?
That being said, atomics are great and all, but are trickier to get right, so if I were implementing this kind of logic I'd start out with a mutex, and then move to atomics if profiling pointed out that the mutex was a bottleneck.

while greater than negative number not working

I have a very trivial piece of code that basically needs to count down from a certain number, and use that count as an index to an array.
auto bigSize = BigArray.size() - 1;
while(bigSize > -1) {
auto thing = arr[bigSize ];
bigSize--;
}
However the code never seems to hit anything inside the loop. I've also tried with a for loop:
auto bigSize = BigArray.size() - 1;
for(int i = bigSize ; i >= 0 && i < bigSize ; --i) {
auto thing = arr[i];
}
I feel like I'm doing something incorrect, but I can't seem to find it.
while(bigSize > -1) {
auto thing = arr[bigSize ];
bigSize--;
}
This will never stop. bigSize is unsigned which means it can't contain negative values. The moment bigSize is 0 and you try to decrement it it becomes std::numeric_limits<type>::max(). (underflow, not negative) So it'll keep on looping.
Either change your condition or make bigSize explicitly an int.
std::Container.size() always returns an unsigned number. An unsigned number will always be greater than a negative number, even if you underflow.

Efficient way to retrieve count of number of times a flag set since last n seconds

I need to track how many times a flag is enabled in last n seconds. Below is the example code I can come up with.StateHandler maintains the value of the flag in active array for last n(360 here) seconds. In my case update function is called from outside every second. So when I need to know how many times it set since last 360 seconds I call getEnabledInLast360Seconds. Is it possible to do it more efficiently like not using an array size of n for booleans ?
#include <map>
#include <iostream>
class StateHandler
{
bool active[360];
int index;
public:
StateHandler() :
index(0),
active()
{
}
void update(bool value)
{
if (index >= 360)
{
index = 0;
}
active[index % 360] = value;
index++;
}
int getEnabledInLast360Seconds()
{
int value = 0;
for (int i = 0; i < 360; i++)
{
if (active[i])
{
value++;
}
}
return value;
}
};
int main()
{
StateHandler handler;
handler.update(true);
handler.update(true);
handler.update(true);
std::cout << handler.getEnabledInLast360Seconds();
}
Yes. Use the fact that numberOfOccurrences(0,360) and numberOfOccurrences(1,361) have 359 common terms. So remember the sum, calculate the common term, and calculate the new sum.
void update(bool value)
{
if (index >= 360)
{
index = 0;
}
// invariant: count reflects t-360...t-1
if (active[index]) count--;
// invariant: count reflects t-359...t-1
active[index] = value;
if (value) count++;
// invariant: count reflects t-359...t
index++;
}
(Note that the if block resetting index removes the need for the modulo operator % so I removed that)
Another approach would be to use subset sums:
subsum[0] = count(0...19)
subsum[1] = count(20...39)
subsum[17] = count(340...359)
Now you only have to add 18 numbers each time, and you can entirely replace a subsum every 20 seconds.
Instead of fixing the buffer, you can simply use std::set<timestamp> (Or perhaps std::queue). Every time you check, pop off the elements older than 360s and count the remaining ones.
If you check scarcely but update often, you might want to add the "popping" to the update itself, to prevent the set from growing too big.

Find minimum value different than zero given some conditions

I've started learning C++ Sets and Iterators and I can't figure if I'm doing this correctly since I'm relatively new to programming.
I've created a Set of a struct with a custom comparator that puts the items in a decreasing order. Before receiving the input I don't know how many items my Set will contain. It can contain any number of items from 0 to 1000.
Here are the Setdefinitions:
typedef struct Pop {
int value_one; int node_value;
} Pop;
struct comparator {
bool operator() (const Pop& lhs, const Pop& rhs) const {
if (rhs.value_one == lhs.value_one) {
return lhs.node_value < rhs.node_value;
} else { return rhs.value_one < lhs.value_one;}
}
};
set<Pop, comparator> pop;
set<Pop>::iterator it;
And this is the algorithm. It should find a minimum value and print that value. If it does not find (the function do_some_work(...) returns 0), it should print "Zero work found!\n":
int minimum = (INT_MAX) / 2; int result;
int main(int argc, char** argv) {
//....
//After reading input and adding values to the SET gets to this part
Pop next;
Pop current;
for (it = pop.begin(); it != pop.end() && minimum != 1; it++) {
current = *it;
temp_it = it;
temp_it++;
if (temp_it != pop.end()) {
next = *temp_it;
// This function returns a integer value that can be any number from 0 to 5000.
// Besides this, it checks if the value found is less that the minimum (declared as global) and different of 0 and if so
// updates the minimum value. Even if the set as 1000 items and at the first iteration the value
// found is 1, minimum is updated with 1 and we should break out of the for loop.
result = do_some_work(current.node_value);
if (result > 0 && next.value_one < current.value_one) {
break;
}
} else {
result = do_some_work(current.node_value);
}
}
if (minimum != (INT_MAX) / 2) {
printf("%d\n", minimum);
} else {
printf("Zero work found!\n");
}
return 0;
}
Here are some possible outcomes.
If the Set is empty it should print Zero work found!
If the Set as one item and do_some_work(current.node_value) returns a value bigger than 0 it should printf("%d\n", minimum); or Zero work found! otherwise.
Imagine I have this Set (first position value_one and second position node_value:
4 2
3 6
3 7
3 8
3 10
2 34
If in the first iteration do_some_work(current.node_value) returns a value bigger than 0, since all other items value_one are smaller, it should break the loop, print the minimum and exit the program.
If in the first iteration do_some_work(current.node_value) returns 0, I advance in the Set and since there are 4 items with value_one as 3 I must analyze this 4 items because any of these can return a possible valid minimum value. If any of these updates the minimum value to 1, it should break the loop, print the minimum and exit the program.
In this case, the last item of the Set is only analysed if all other items return 0 or minimum value is set to 1.
For me this is both an algorithmic problem and a programming problem.
With this code, am I analysing all the possibilities and if minimum is 1, breaking the loop since if 1 is returned there's no need to check any other items?

Recursion: subset sum algorithm setting value in parameters

How do I reset the value of blockIndex to its inital state when I call the method?
Say if I call it and pass in the value 4. I check if that value is greater than 9, if not I add the element at pos(0). But in tracing my function I see that it adds all the values of the vector. I just want it to add 1 element, then when it check if it is greater than 9, and it is not, revert it back to the initial value. How do I do this?
int NumCriticalVotes :: CountCriticalVotes(Vector<int> & blocks, int blockIndex)
{
if (blockIndex >= 9 && blocks.isEmpty())
{
return 1;
}
if (blocks.isEmpty()) //Fail case
{
return 0;
} else {
int element = blocks.get(0);
Vector<int> rest = blocks;
rest.remove(0);
return CountCriticalVotes(rest, blockIndex) || CountCriticalVotes(rest, blockIndex + element);
}
}