/*
QEImenu.c - handles the rotary encoder and menu.
Copyright (C) 2011 Paul Moody
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <p30f4012.h>
#include <stdio.h>
#include <qei.h>
#include "system.h"
unsigned int MenuState;
unsigned int MenuItemState;
unsigned int OptionState;
unsigned int OptionSelect;
extern double Fclock; //input clock frequency in KHz
extern struct VALSTORE valblock;
volatile int QEI_Dir;
volatile int QEI_Event;
extern void save_vars(void);
extern void read_vars(void);
extern int calc_cksum(int, int *);
extern int calc_EE_cksum(int, int *);
extern int cksum_OK(int, int *);
extern char lcdBuff30[30];
extern void lcd_clear(void);
extern void lcd_putc(const char);
extern void lcd_puts(const char *);
extern void lcd_goto(unsigned char);
extern void lcd_test(void);
extern void setup_lcd(void);
extern volatile unsigned int AUDIOrate;
/************************************************** *******************
* Function Name : QEIInterrupt()
* Description : handles rotary encoder interrupts
************************************************** *******************/
void __attribute__((__interrupt__, auto_psv)) _QEIInterrupt(void)
{
IFS2bits.QEIIF = 0; // clear interrupt
if(QEI_Event == 0) // only if there are no pending QEI events
{
QEI_Dir = QEICONbits.UPDN; // store up or down state
QEI_Event = 1; // flag QEI event
}
}
/************************************************** *******************
* Function Name : QEI_Setup()
* Description : initialises rotary encoder
************************************************** *******************/
void QEI_Setup(void)
{
QEICONbits.QEIM = 0; // Disable QEI Module
QEICONbits.CNTERR = 0; // Clear any count errors
QEICONbits.QEISIDL = 0; // Continue operation during sleep
QEICONbits.SWPAB = 0; // QEA and QEB not swapped
QEICONbits.PCDOUT = 0; // Normal I/O pin operation
QEICONbits.POSRES = 0; // pos counter reset by index disable
DFLTCONbits.CEID = 1; // Count error interrupts disabled
DFLTCONbits.QEOUT = 1; // Digital filters output enabled for QEn pins
DFLTCONbits.QECK = 7; // 1:256 clock divide for digital filter for QEn
POSCNT = 0; // Reset position counter
QEICONbits.QEIM = 5; // X4 mode with position counter reset by count
MAXCNT = 1;
IFS2bits.QEIIF = 0; // clear Interrupt flag
IEC2bits.QEIIE = 1; // Enable QEI Interupts
return;
}
/************************************************** *******************
* Function Name : process_QEI()
* Description : handles the rotary encoder and updates the LCD
************************************************** *******************/
void process_QEI(void)
{
if (MenuItemState == OPT)
{
switch ( OptionState )
{
case OptX1:
if(QEI_Dir == 0)
OptionState = OptNORM;
else
OptionState = OptX10;
break;
case OptX10:
if(QEI_Dir == 0)
OptionState = OptX1;
else
OptionState = OptX100;
break;
case OptX100:
if(QEI_Dir == 0)
OptionState = OptX10;
else
OptionState = OptSAVE;
break;
case OptSAVE:
if(QEI_Dir == 0)
OptionState = OptX100;
else
OptionState = OptNORM;
break;
case OptNORM:
if(QEI_Dir == 0)
OptionState = OptSAVE;
else
OptionState = OptX1;
break;
default:
lcd_clear();
lcd_goto(0);
lcd_puts("Option State Err\0");
while(1); //stop here
}//END switch
}//END if (MenuItemState == OPT)
if (MenuItemState == OPT)
{
switch ( OptionState )
{
case OptX1:
OptionSelect = EDIT;
lcd_clear();
lcd_goto(0);
lcd_puts("MODIFY VALUE\0");
lcd_goto(40);
lcd_puts("STEP = X1\0");
break;
case OptX10:
OptionSelect = EDIT;
lcd_clear();
lcd_goto(0);
lcd_puts("MODIFY VALUE\0");
lcd_goto(40);
lcd_puts("STEP = X10\0");
break;
case OptX100:
OptionSelect = EDIT;
lcd_clear();
lcd_goto(0);
lcd_puts("MODIFY VALUE\0");
lcd_goto(40);
lcd_puts("STEP = X100\0");
break;
case OptSAVE:
OptionSelect = SAVE;
lcd_clear();
lcd_goto(0);
lcd_puts("SAVE TO EEPROM\0");
break;
case OptNORM:
OptionSelect = RUN;
lcd_clear();
lcd_goto(0);
lcd_puts("EXIT\0");
break;
default:
lcd_clear();
lcd_goto(0);
lcd_puts("Option State Err\0");
while(1); //stop here
}//END switch
}//END if (MenuItemState == OPT)
/// set menu state to next state if not changing value///
if (MenuItemState == NORM)
{
switch ( MenuState )
{
case A:
if(QEI_Dir == 0)
MenuState = M;
else
MenuState = B;
break;
case B:
if(QEI_Dir == 0)
MenuState = A;
else
MenuState = C;
break;
case C:
if(QEI_Dir == 0)
MenuState = B;
else
MenuState = E;
break;
case E:
if(QEI_Dir == 0)
MenuState = C;
else
MenuState = F;
break;
case F:
if(QEI_Dir == 0)
MenuState = E;
else
MenuState = G;
break;
case G:
if(QEI_Dir == 0)
MenuState = F;
else
MenuState = H;
break;
case H:
if(QEI_Dir == 0)
MenuState = G;
else
MenuState = M;
break;
case M:
if(QEI_Dir == 0)
MenuState = H;
else
MenuState = A;
break;
default:
lcd_clear();
lcd_goto(0);
lcd_puts("Menu State Err\0");
while(1); //stop here
}
}//END if (MenuItemState == NORM)
///display menu for selected state ///
if (MenuItemState != OPT)
{
switch ( MenuState )
{
case A:
if(MenuItemState == EDIT)
{
if(QEI_Dir) //up
{
if(PTPER < (14740 - OptionState)) //OptionState contains the "multiplier" x1 x10 x100 etc
PTPER = PTPER + OptionState;
}
else
{
if(PTPER > (1474 + OptionState))
PTPER = PTPER - OptionState;
}
PDC2 = PTPER>>5; //LCD contrast option
}
if(MenuItemState == SAVE) //save to EEPROM
{
valblock.FREQ = PTPER; //store freq in ram block
save_vars(); //write ram block to EEPROM
MenuItemState = NORM; //leave SAVE state
}
lcd_clear();
lcd_goto(0);
sprintf(lcdBuff30,"TxF:%8.3lf Khz", (Fclock * 4)/PTPER);
lcd_puts(lcdBuff30);
lcd_goto(0x40);
sprintf(lcdBuff30,"Per:%8.3lf uS", (PTPER/(Fclock * 4))*1000);
lcd_puts(lcdBuff30);
break;
case B:
if(MenuItemState == EDIT)
{
if(QEI_Dir) //up
PDC1 = PDC1 + OptionState;
else
PDC1 = PDC1 - OptionState;
}
if(MenuItemState == SAVE) //save to EEPROM
{
valblock.PWM1 = PDC1; //store PWM1 in ram block
save_vars(); //write ram block to EEPROM
MenuItemState = NORM; //leave SAVE state
}
lcd_clear();
lcd_goto(0);
lcd_puts("TX1 PULSE PERIOD\0");
lcd_goto(0x40);
sprintf(lcdBuff30,"%.3lf uS", (PDC1/(Fclock *
)*1000);lcd_puts(lcdBuff30);
break;
case C:
//if(MenuItemState == EDIT)
//{
// if(QEI_Dir) //up
// PDC2 = PDC2 + OptionState;
// else
// PDC2 = PDC2 - OptionState;
//}
//if(MenuItemState == SAVE) //save to EEPROM
//{
// valblock.PWM2 = PDC2; //store PWM1 in ram block
// save_vars(); //write ram block to EEPROM
// MenuItemState = NORM; //leave SAVE state
//}
lcd_clear();
lcd_goto(0);
lcd_puts("TX2 PULSE PERIOD\0");
lcd_goto(0x40);
sprintf(lcdBuff30,"%.3lf uS", (PDC2/(Fclock *
)*1000);lcd_puts(lcdBuff30);
break;
case E:
if(MenuItemState == EDIT)
{
if(QEI_Dir) //up
OC1R = OC1R + OptionState;
else
OC1R = OC1R - OptionState;
}
if(MenuItemState == SAVE) //save to EEPROM
{
valblock.SP1ON = OC1R; //store samp puls 1 ON time in ram block
save_vars(); //write ram block to EEPROM
MenuItemState = NORM; //leave SAVE state
}
lcd_clear();
lcd_goto(0);
lcd_puts("S1 PULSE ON AT:\0");
lcd_goto(0x40);
sprintf(lcdBuff30,"%.3lf uS", (OC1R/Fclock)*2000);
lcd_puts(lcdBuff30);
break;
case F:
if(MenuItemState == EDIT)
{
if(QEI_Dir) //up
OC1RS = OC1RS + OptionState;
else
OC1RS = OC1RS - OptionState;
}
if(MenuItemState == SAVE) //save to EEPROM
{
valblock.SP1OFF = OC1RS; //store PWM1 in ram block
save_vars(); //write ram block to EEPROM
MenuItemState = NORM; //leave SAVE state
}
lcd_clear();
lcd_goto(0);
lcd_puts("S1 PULSE OFF AT:\0");
lcd_goto(0x40);
sprintf(lcdBuff30,"%.3lf uS", (OC1RS/Fclock)*2000);
lcd_puts(lcdBuff30);
break;
case G:
if(MenuItemState == EDIT)
{
if(QEI_Dir) //up
OC2R = OC2R + OptionState;
else
OC2R = OC2R - OptionState;
}
if(MenuItemState == SAVE) //save to EEPROM
{
valblock.SP2ON = OC2R; //store samp puls 2 ON time in ram block
save_vars(); //write ram block to EEPROM
MenuItemState = NORM; //leave SAVE state
}
lcd_clear();
lcd_goto(0);
lcd_puts("S2 PULSE ON AT:\0");
lcd_goto(0x40);
sprintf(lcdBuff30,"%.3lf uS", (OC2R/Fclock)*2000);
lcd_puts(lcdBuff30);
break;
case H:
if(MenuItemState == EDIT)
{
if(QEI_Dir) //up
OC2RS = OC2RS + OptionState;
else
OC2RS = OC2RS - OptionState;
}
if(MenuItemState == SAVE) //save to EEPROM
{
valblock.SP2OFF = OC2RS; //store samp puls 2 ON time in ram block
save_vars(); //write ram block to EEPROM
MenuItemState = NORM; //leave SAVE state
}
lcd_clear();
lcd_goto(0);
lcd_puts("S2 PULSE OFF AT:\0");
lcd_goto(0x40);
sprintf(lcdBuff30,"%.3lf uS", (OC2RS/Fclock)*2000);
lcd_puts(lcdBuff30);
break;
case M:
if(MenuItemState == EDIT)
{
if(QEI_Dir) //up
AUDIOrate = AUDIOrate + OptionState;
else
AUDIOrate = AUDIOrate - OptionState;
}
if(MenuItemState == SAVE) //save to EEPROM
{
valblock.AUDIOrate = AUDIOrate; //store audio rate val in ram block
save_vars(); //write ram block to EEPROM
MenuItemState = NORM; //leave SAVE state
}
lcd_clear();
lcd_goto(0);
lcd_puts("AUDIO RATE Value\0");
lcd_goto(0x40);
sprintf(lcdBuff30,"%u", AUDIOrate);
lcd_puts(lcdBuff30);
break;
default:
lcd_clear();
lcd_goto(0);
lcd_puts("Menu Display Err\0");
while(1); //stop here
}//END switch
}//END if (MenuItemState != OPT)
QEI_Event = 0; //reset the flag .. last thing we do
}//END function


Leave a comment: