I slutet av videon ser man hur menyn är tänkt att fungera men som synes finns det lite buggar...

Videon är från några veckor sedan, koden nedan generar samma buggar men inte riktigt lika ofta. Vi har försökt kommentera bort eller ändra på tveksamma kodstycken i tur och ordning men vi får ingen vidare förbättring och börjar få slut på idéer... Är det kanske så att vi gör något man kanske inte bör göra i C? Vi är båda mest vana vid Java och assembler.
Kod: Markera allt
/****************************************************
* *
* Filename: IMSv1.2.c *
* Date: 2014-03-20 *
* *
* Author: Kalle Jonsson *
* *
*****************************************************
* *
* Processor: PIC16F690 *
* Compiler: MPLAB XC8 *
* *
****************************************************/
#include <xc.h>
#include <string.h>
#define _XTAL_FREQ 4000000
#define ENTMOD 0x06
#define FNCSET 0x38
#define DSPOFF 0x08
#define DSPON 0x0C
#define LCD_RS PORTCbits.RC0
#define LCD_E PORTCbits.RC1
#define LCD_BL PORTCbits.RC5
#define LED PORTAbits.RA4
#define BTN PORTAbits.RA1
#define SHT PORTCbits.RC7
__CONFIG(BOREN_OFF & CPD_OFF & CP_OFF & MCLRE_OFF & WDTE_OFF & PWRTE_OFF & FOSC_INTRCIO);
volatile bit A, B, BTN_pressed, BTN_released;
volatile signed char rotcnt = 0;
volatile unsigned char AB, BA, PORTCs;
volatile signed int cnt = 0;
volatile unsigned int BTN_Time = 0;
volatile unsigned long currentTime = 0, lastChange;
//Initialize IO pins
void IOInit()
{
BTN_released = 1;
TRISA = 0b00000111;
TRISB = 0b00000000;
TRISC = 0b01001100;
ANSEL = 0; //No analog pins
ANSELH = 0; //--------------
//ADCON0 = 0b00011000;
// 0------- Left justified
// -0------ VDD voltage ref
// --0110-- AN6
// ------0- GO/DONE
// -------1 ADON
//ADCON1 = 0x10; //AD Conversion Clock Fosc/8
}
//Initialize all interrupts
void interruptInit()
{
//ADIF = 0; //A/D Converter Interrupt Flag bit clear
//ADIE = 1; //A/D Converter Interrupt Enable bit set
IOCA = 0b000101; //Interrupt-on-change PORTA
RABIF = 0; //IOC Flag bit clear
RABIE = 1; //IOC Enabled
OPTION_REG =0b11010001; //TIMER 0: internal clock, prescaler 1:4
T0IF = 0; //TIMER 0 Interrupt Flag bit clear
T0IE = 1; //TIMER 0 Overflow Interrupt Enabled
//PEIE = 1; //Peripheral Interrupt Enable bit set
}
//Send an instruction to the LCD display
void LCD_cmd(char B)
{
LCD_RS = 0;
PORTB = B & 0xF0;
NOP();
LCD_E = 1;
__delay_us(50);
LCD_E = 0;
__delay_us(50);
PORTB = ((B & 0xF)<<4);
NOP();
LCD_E = 1;
__delay_us(50);
LCD_E = 0;
__delay_us(50);
}
//Clear and home the LCD display
void LCD_clr()
{
LCD_cmd(1);
__delay_ms(2);
LCD_cmd(2);
__delay_ms(2);
}
//Output a character onto the LCD display
void LCD_out(char c)
{
LCD_RS = 1;
PORTB = (c & 0xF0);
NOP();
LCD_E = 1;
__delay_us(50);
LCD_E = 0;
__delay_us(50);
PORTB = ((c & 0x0F)<<4);
NOP();
LCD_E = 1;
__delay_us(50);
LCD_E = 0;
__delay_us(50);
}
//Move the cursor on the LCD to the specified adress
void LCD_adr(char adr)
{
LCD_cmd(0x80 + adr);
}
//Output an integer with a specified number of digits
void LCD_int_places(unsigned int nbr, int places)
{
int i, j, out, temp;
for(i = places; i > 0; i--) {
out = nbr;
temp = 1;
for(j = i-1; j > 0; j--) {
out /= 10;
temp *= 10;
}
LCD_out('0' + out);
nbr = nbr-out*temp;
}
}
//Output a string on the LCD at the specified adress
void LCD_String(const char *ch, char adr)
{
LCD_adr(adr);
while(*ch!='\0')
{
LCD_out(*ch++);
}
}
//Initialize the LCD display
void LCD_Init() //Initialize LCD diplay
{
__delay_ms(100);
LCD_RS = 0;
LCD_E = 0;
PORTB = 0x20; //4-bit Mode
LCD_E = 1;
__delay_us(50);
LCD_E = 0;
__delay_ms(2);
LCD_cmd(0b00101000); //4-bit, two line, 5x8 font
__delay_ms(1);
LCD_cmd(0b00001100); //Display on, Cursor off, Blink off
__delay_ms(1);
LCD_cmd(0x01); //Clear display
__delay_ms(2);
LCD_cmd(0b0110); //Increment mode, shift off
PORTB = 0;
__delay_ms(100);
}
//Return 1 if the button has been pressed, else 0
char getBTN() {
if (BTN_pressed) {
BTN_pressed = 0;
return 1;
} else {
return 0;
}
}
//Return 1 or -1 if the rotary encoder has been moved, else 0
signed char getROT() {
if (rotcnt < 0) {
rotcnt++;
return -1;
} else if (rotcnt > 0) {
rotcnt--;
return 1;
} else {
return 0;
}
}
//Add or remove one from var and return
unsigned int useROT(unsigned int var, unsigned int max) {
signed char rotTemp = 0;
if (rotcnt < 0) {
rotcnt++;
rotTemp = -1;
} else if (rotcnt > 0) {
rotcnt--;
rotTemp = 1;
}
signed long temp = var + rotTemp;
if (temp <= max && temp >= 0) {
return temp;
} else {
return var;
}
}
void interrupt ISR()
{
GIE = 0;
if (T0IF && T0IE) { //Timer 0 overflow interrupt, once every ms
TMR0 += 6;
currentTime++; //Elapsed time in ms since reset
if (!BTN && BTN_released) {
BTN_pressed = 1;
BTN_released = 0;
} else if (BTN) {
BTN_released = 1;
}
T0IF = 0;
}
if (RABIF && RABIE) { //Interrupt-on-change
unsigned char PORTAcopy = PORTA;
// if ((currentTime - lastChange) > 2) {
// lastChange = currentTime;
A = PORTAcopy & 0b001;
B = (PORTAcopy & 0b100) >> 2;
AB = ((A << 1) + B);
char test = (BA ^ AB) & 0b11;
BA = ((B << 1) + A);
if (test == 0x01) {
cnt++;
if (cnt%4 == 0 && (rotcnt < 127)) {
rotcnt++;
cnt = 0;
}
} else if (test == 0x02) {
cnt++;
if (cnt%4 == 0 && rotcnt > -127) {
rotcnt--;
cnt = 0;
}
}
//}
RABIF = 0;
}
GIE = 1;
}
void main()
{
unsigned char shutterUnit='s', intervalUnit='s', sensorMode=2,
BLMode=3, trigger=1, battery = 0, BL = 100, sensor = 45, state = 0, btn,
arrowRow = 2, arrowPos = 0x40, nextUnit='s', openUnit='s';
unsigned int shutter=25, interval=10, next=24, open=19, pictures=389,
picturesTaken=145, sensorVal=25;
IOInit();
interruptInit();
LED = 1;
SHT = 0;
LCD_BL = 1; //Turn on LCD backlight
__delay_ms(500);
//LED = 0;
LCD_Init(); //Initialize LCD display
GIE = 1; //Turn on interrupts
LCD_clr(); //Clear display
char state = 0;
while (1) {
LED ^= 1;
switch (state) { //MAIN MENU print
case 0:
LCD_String(" --SETTINGS-- ", 0x1);
LCD_String("Shutter ", 0x41);
LCD_adr(0x4B);
LCD_int_places(shutter, 2);
LCD_adr(0x4D);
LCD_out(shutterUnit);
break;
case 1:
LCD_String("Shutter ", 0x1);
LCD_String("Interval ", 0x41);
LCD_adr(0xB);
LCD_int_places(shutter, 2);
LCD_adr(0xD);
LCD_out(shutterUnit);
LCD_adr(0x4B);
LCD_int_places(interval, 2);
LCD_adr(0x4D);
LCD_out(intervalUnit);
break;
case 2:
LCD_String("Interval ", 0x1);
LCD_String("Pictures ", 0x41);
LCD_adr(0xB);
LCD_int_places(interval, 2);
LCD_adr(0xD);
LCD_out(intervalUnit);
LCD_adr(0x4B);
LCD_int_places(pictures, 3);
break;
case 3:
LCD_String("Pictures ", 0x1);
LCD_String("Sensor ", 0x41);
LCD_adr(0xB);
LCD_int_places(pictures, 3);
LCD_adr(0x4B);
LCD_int_places(sensor, 3);
break;
case 4:
LCD_String("Sensor ", 0x1);
LCD_String("Sensor ", 0x41);
LCD_adr(0xB);
LCD_int_places(sensor, 3);
if (sensorMode == 1)
LCD_String("ON ", 0x4B);
else
LCD_String("OFF", 0x4B);
break;
case 5:
LCD_String("Sensor ", 0x1);
LCD_String("Trigger ", 0x41);
if (sensorMode == 1)
LCD_String("ON ", 0xB);
else
LCD_String("OFF", 0xB);
if (trigger == 1)
LCD_String("ON ", 0x4B);
else
LCD_String("OFF", 0x4B);
break;
case 6:
LCD_String("Trigger ", 0x1);
LCD_String("Backlight ", 0x41);
if (trigger == 1)
LCD_String("ON ", 0xB);
else
LCD_String("OFF", 0xB);
LCD_adr(0x4B);
LCD_int_places(BL, 3);
break;
case 7:
LCD_String("Backlight ", 0x1);
LCD_String("Backlight ", 0x41);
LCD_adr(0xB);
LCD_int_places(BL, 3);
if (BLMode == 1)
LCD_String("ON ", 0x4B);
else if(BLMode == 2)
LCD_String("OFF", 0x4B);
else
LCD_String("AUT", 0x4B);
break;
default:
break;
}
if (arrowPos == 0) { //Arrow printing and removing
LCD_adr(0);
LCD_out(0x7E);
LCD_adr(0x40);
LCD_out(' ');
} else {
LCD_adr(0);
LCD_out(' ');
LCD_adr(0x40);
LCD_out(0x7E);
}
signed char rotTemp = getROT(); //Check if the rotary encoder has been turned
if (rotTemp > 0 && arrowRow < 9){
if(arrowPos == 0)
arrowPos = 0x40;
else
state++;
arrowRow++;
} else if (rotTemp < 0 && arrowRow > 2) {
if(arrowPos == 0x40)
arrowPos = 0;
else
state--;
arrowRow--;
} else if (rotTemp < 0 && arrowRow == 2 && state == 1) {
state = 0;
arrowPos = 0x40;
}
if (getBTN()) { //Enable modifying value with button press
LCD_adr(0); //Remove arrows in the first column
LCD_out(' '); //-
LCD_adr(0x40); //-
LCD_out(' '); //-
LCD_adr(arrowPos + 0xA); //Output the arrow to the left of the value
LCD_out(0x7E); //-
while (!getBTN()) {
LED ^= 1;
unsigned int varTemp;
char unitTemp;
char type = 0; //Variable print type, 2 digit int, 3 digit int or string
switch (arrowRow) {
case 2:
shutter = useROT(shutter, 60);
varTemp = shutter;
unitTemp = shutterUnit;
type = 1;
break;
case 3:
interval = useROT(interval, 60);
varTemp = interval;
unitTemp = intervalUnit;
type = 1;
break;
case 4:
pictures = useROT(pictures, 999);
varTemp = pictures;
unitTemp = 0;
type = 2;
break;
case 5:
sensor = useROT(sensor, 255);
varTemp = sensor;
unitTemp = 0;
type = 2;
break;
case 6:
sensorMode = useROT(sensorMode, 3);
varTemp = sensorMode;
unitTemp = 0;
type = 3;
break;
default:
type = 0;
break;
}
LCD_adr(arrowPos + 0xB);
switch (type) {
case 0:
break;
case 1:
LCD_int_places(varTemp, 2);
LCD_adr(arrowPos + 0xD);
LCD_out(unitTemp);
break;
case 2:
LCD_int_places(varTemp, 3);
break;
case 3:
if (varTemp == 1)
LCD_String("ON ",arrowPos + 0xB);
else if (varTemp == 2)
LCD_String("OFF", arrowPos + 0xB);
else if (varTemp == 3)
LCD_String("AUT", arrowPos + 0xB);
break;
default:
break;
}
}
}
//while (rotcnt == 0 && BTN_pressed == 0);
}
}