#include "rubi.h"
static uint8_t calc_current_operand = 0;
static char calc_operand_0[CALC_DIGITS+1] = "";
static char calc_operand_1[CALC_DIGITS+1] = "";
char calc_result[CALC_DIGITS+1] = "";
static char calc_status[CALC_DIGITS+1] = "";
static char calc_operator = ' ';
static bool calc_reset = false;
void calcBegin(void){
}
void calcUpdate(void){
if (calc_display_lines == 2) {
if((calc_current_operand == 1) || (calc_reset)){
strcpy(calc_status, calc_operand_0);
if((strlen(calc_operand_0)>0) || (strlen(calc_operand_1)>0)){
uint8_t len = strlen(calc_status);
if (!(calc_operator == 's' || calc_operator == 'r' || calc_operator == 'n')) {
calc_status[len] = calc_operator;
}
calc_status[len+1] = 0;
if(calc_reset
&& !(calc_operator == 's' || calc_operator == 'r' || calc_operator == 'n')){
strncat(calc_status, calc_operand_1, CALC_DIGITS-strlen(calc_status));
calc_operator = ' ';
}
}
strcpy(calc_status_display, calc_status);
}
} else if (calc_display_lines == 1) {
if(calc_reset
&& !(calc_operator == 's' || calc_operator == 'r' || calc_operator == 'n')){
calc_operator = ' ';
}
}
calc_operator_display = calc_operator;
strcpy(calc_result_display, calc_result);
}
void calcOperands(void){
float result = 0;
switch (calc_operator){
case '+':
result = strtod(calc_operand_0, NULL) + strtod(calc_operand_1, NULL);
break;
case '-':
result = strtod(calc_operand_0, NULL) - strtod(calc_operand_1, NULL);
break;
case '/':
result = strtod(calc_operand_0, NULL) / strtod(calc_operand_1, NULL);
break;
case '*':
result = strtod(calc_operand_0, NULL) * strtod(calc_operand_1, NULL);
break;
case 's':
result = sqrt(strtod(calc_operand_0, NULL));
break;
case 'r':
result = 1/(strtod(calc_operand_0, NULL));
break;
}
uint8_t magnitude = ceil(log10(result));
uint8_t max_decimals = CALC_DIGITS-magnitude-1;
if(max_decimals>7){
max_decimals = 7;
}
dtostrf(result, CALC_DIGITS, max_decimals, calc_result);
uint8_t i;
uint8_t dotpos = CALC_DIGITS+1;
for(i=0; i<strlen(calc_result); i++){
if(calc_result[i] == '.'){
dotpos = i;
break;
}
}
if(dotpos>=0){
for(i=strlen(calc_result)-1; i>=dotpos; i--){
if((calc_result[i] == '0') || (calc_result[i] == '.')){
calc_result[i] = 0;
}else{
break;
}
}
}
uint8_t spaces = 0;
for(i=0; i<strlen(calc_result); i++){
if(calc_result[i] == ' '){
spaces++;
}else{
break;
}
}
for(i=0; i<strlen(calc_result)-spaces; i++){
calc_result[i] = calc_result[i+spaces];
}
calc_result[strlen(calc_result)-spaces] = 0;
calcUpdate();
strcpy(calc_operand_0, calc_result);
calc_operand_1[0] = 0;
}
void calcInput(char input){
char *operand = calc_operand_0;
if(calc_current_operand == 1){
operand = calc_operand_1;
}
uint8_t len = strlen(operand);
if(
((input >= 48) && (input <= 57)) ||
(input == '.')
){
if(calc_reset == true){
calc_reset = false;
calc_current_operand = 0;
calc_operand_0[0] = 0;
calc_operand_1[0] = 0;
operand = calc_operand_0;
len = 0;
}
if(len<CALC_DIGITS){
operand[len] = input;
operand[len+1] = 0;
strcpy(calc_result, operand);
calcUpdate();
}
}else if(input == 'x'){
operand[len-1] = 0;
strcpy(calc_result, operand);
calcUpdate();
}else if(input == 'c'){
operand[0] = 0;
calc_operand_0[0] = 0;
calc_operand_1[0] = 0;
calc_operator = ' ';
calc_reset = true;
strcpy(calc_result, operand);
calcUpdate();
}else if((input == 'n') && (len>0)){
uint8_t i;
if(operand[0] == '-'){
for(i=1; i<=len; i++){
operand[i-1] = operand[i];
}
}else if(len<CALC_DIGITS){
for(i=0; i<=len; i++){
operand[len-i+1] = operand[len-i];
}
operand[0] = '-';
}
calc_operator = input;
strcpy(calc_result, operand);
calcUpdate();
}else if((input == '+') || (input == '-') || (input == '*') || (input == '/')){
if(calc_current_operand == 0){
calc_operator = input;
calc_current_operand = 1;
calcUpdate();
}else if(calc_reset){
calc_operator = input;
calc_reset = false;
calc_operand_1[0] = 0;
calcUpdate();
}else {
if (strlen(calc_operand_1)>0){
calcOperands();
}
calc_operand_1[0] = 0;
calc_operator = input;
calcUpdate();
}
}else if(input == '='){
if(calc_current_operand == 1){
calc_reset = true;
calcOperands();
}
}else if((input == 's') || (input == 'r')){
if(calc_current_operand == 1 && !calc_reset){
strcpy(calc_operand_0, calc_operand_1);
}
calc_current_operand = 1;
calc_operand_1[0] = 0;
calc_operator = input;
calc_reset = true; calcOperands();
}
}