This doesn't answer your question, but might make the code a little easier for you to debug. The case statements are really long and may not be the best way to explain what you are doing with your outputs. I make no guarantees that the code is operational (I have not run it at all), but this should get you thinking about file size and readability.
Your singleminutes case statement has a truth table like this:
// | out
// in| 0 1 2 3 4
// ---------------
// 0 | 0 0 0 0 0
// 1 | 0 1 0 0 0
// 2 | 0 1 1 0 0
// 3 | 0 1 1 1 0
// 4 | 0 1 1 1 1
which might be better represented with output-centric code like this:
if (singleminutes >= 1)
PPEins = 1;
else
PPEins = 0;
if (singleminutes >= 2)
PPZwei = 1;
else
PPZwei = 0;
if (singleminutes >= 3)
PPDrei = 1;
else
PPDrei = 0;
if (singleminutes >= 4)
PPVier = 1;
else
PPVier = 0;
The nfminutes is a little more complicated, but here is the Truth Table:
// | MHUhr PMFuenf PMZehn PMViertel PMZwanzig PMVor PMNach PMHalb | |
// --|--------------------------------------------------------------|--------|-----
// 0 | 1 0 0 0 0 0 0 0 | 1000 0 | 000
// 1 | 0 1 0 0 0 0 1 0 | 0100 0 | 010
// 2 | 0 0 1 0 0 0 1 0 | 0010 0 | 010
// 3 | 0 0 0 1 0 0 1 0 | 0001 0 | 010
// 4 | 0 0 0 0 1 0 1 0 | 0000 1 | 010
// 5 | 0 1 0 0 0 1 0 1 | 0000 0 | 101
// 6 | 0 0 0 0 0 0 0 1 | 0000 0 | 001
// 7 | 0 1 0 0 0 0 1 1 | 0100 0 | 011
// 8 | 0 0 0 0 1 1 0 0 | 0000 1 | 100
// 9 | 0 0 0 1 0 1 0 0 | 0001 0 | 100
//10 | 0 0 1 0 0 1 0 0 | 0010 0 | 100
//11 | 0 1 0 0 0 1 0 0 | 0100 0 | 100
and again some output-centric code:
// MHUhr PMFuenf PMZehn PMViertel PMZwanzig
if( nfminutes == 0 )
MHUhr = 1;
else
MHUhr = 0;
if(( nfminutes == 1 ) || (nfminutes == 5) || (nfminutes == 7) || (nfminutes == 11))
PMFuenf = 1;
else
PMFuenf = 0;
if(( nfminutes == 2 ) || (nfminutes == 10) )
PMZehn = 1;
else
PMZehn = 0;
if(( nfminutes == 3 ) || (nfminutes == 9) )
PMViertel = 1;
else
PMViertel = 0;
if(( nfminutes == 4 ) || (nfminutes == 8) )
PMZwanzig = 1;
else
PMZwanzig = 0;
// PMVor PMNach PMHalb
if( ((nfminutes >= 1 ) && (nfminutes <= 4 )) || (nfminutes == 7))
PMNach = 1;
else
PMNach = 0;
if( (nfminutes >= 5) && (nfminutes <= 7 )
PMHalb = 1;
else
PMHalb = 0;
if(nfminutes >=8)
PMVor = 1;
else
PMVor = 0;
The code above might do well with some #defines too
#define UHR 0
#define PHUENF_NACH 1
#define ZEHN_NACH 2
...
if(nfminutes == UHR)
Again for hours. Truth Table:
| 12 1 2 3 4 5 6 7 8 9 10 11
//----|------------------------------------
// 0 | 1 0 0 0 0 0 0 0 0 0 0 0
// 1 | 0 1 0 0 0 0 0 0 0 0 0 0
// 2 | 0 0 1 0 0 0 0 0 0 0 0 0
// 3 | 0 0 0 1 0 0 0 0 0 0 0 0
// 4 | 0 0 0 0 1 0 0 0 0 0 0 0
// 5 | 0 0 0 0 0 1 0 0 0 0 0 0
// 6 | 0 0 0 0 0 0 1 0 0 0 0 0
// 7 | 0 0 0 0 0 0 0 1 0 0 0 0
// 8 | 0 0 0 0 0 0 0 0 1 0 0 0
// 9 | 0 0 0 0 0 0 0 0 0 1 0 0
// 10 | 0 0 0 0 0 0 0 0 0 0 1 0
// 11 | 0 0 0 0 0 0 0 0 0 0 0 1
and code. Slightly different structure with all outputs being cleared, then only the correct output turned on.
// one-hot, clear all will not cause a glitch
PHZwoelf = 0;
PHEins = 0;
PHZwei = 0;
PHDrei = 0;
PHVier = 0;
PHFuenf = 0;
PHSechs = 0;
PHSieben = 0;
PHAcht = 0;
PHNeun = 0;
PHZehn = 0;
PHElf = 0;
if( hours == 0 )
PHZwoelf = 1;
if( hours == 1 )
PHEins = 1;
if( hours == 2 )
PHZwei = 1;
if( hours == 3 )
PHDrei = 1;
if( hours == 4 )
PHVier = 1;
if( hours == 5 )
PHFuenf = 1;
if( hours == 6 )
PHSechs = 1;
if( hours == 7 )
PHSieben = 1;
if( hours == 8 )
PHAcht = 1;
if( hours == 9 )
PHNeun = 1;
if( hours == 10 )
PHZehn = 1;
if( hours == 11 )
PHElf = 1;
All this also allows you to do your input calculations together before your case statements.
// update single minutes
int singleminutes = (int) (unbcd(tm.min)%5); // 1, 2, 3, 4
// update 5 minutes
int nfminutes = (int) (unbcd(tm.min)/5); // Fuenf Nach, Zehn Nach, ...
// update hours
int hours = (int) (unbcd(tm.hour)%12); // 12, 1, 2, 3, 4...
if(nfminutes>=5) hours++; // 7:25 = Fuenf Vor Halb Acht (8)
Best Answer
'L-value' and 'R-Value' describe attributes of the Left-hand side and Right-hand side, respectively, of an assignment. An R-value is a quantity of some kind (not necessarily numerical), usually the result of evaluating an expression, but also a constant, such as '5' or the string "Hello, World!\n". An L-value is a something that a program can assign an R-value to, such as a named variable, or a raw memory or port address. This WikiPedia article has a more complete description.
"lvalue required as left operand of assignment" simply means that the left side of your assignment isn't an assignable address or convertible to one. PA0 is #defined as a simple constant without l-value properties.
You're on the right track - here is an Arduino article about ports and the I/O registers associated with them, and direct manipulation of those registers. Despite its caveats, direct port manipulation is a useful technique for reducing both program size and timing-skew in some situations.
These statements:
will both define an l-value you can assign to (but note: it's a whole port, not just a pin) and change its value to turn on pin-0. The RED_ON expression reads: read PORTA, OR that with '1' (so you won't change any other bits in the port); the assignment writes the new value back to the port.
(Do note that your code as written - even assuming the assignment statement was correct - will repetitively turn on the LED, which is no different from turning it on once).