#include #include #include #include #define PIC_CLK 20000000 #include "delay_alternative_enhanced_precision.h" //__CONFIG(WDTDIS & XT & UNPROTECT & LVPDIS); // freq. clock 4MHz //__CONFIG(WDTDIS & HS & UNPROTECT & LVPDIS); // freq. clock 20MHz __CONFIG(WDTDIS & PWRTEN & HS & UNPROTECT & DEBUGDIS & BORDIS & LVPDIS); #define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit)) static bit CSL @ PORTBIT(PORTA, 0); static bit DAT @ PORTBIT(PORTA, 1); static bit CLK @ PORTBIT(PORTA, 2); static bit IR @ PORTBIT(PORTB, 0); static bit WEN @ PORTBIT(PORTA, 3); static bit VUP @ PORTBIT(PORTB, 1); static bit VDW @ PORTBIT(PORTB, 2); static bit ENC_A @ PORTBIT(PORTB, 4); static bit ENC_B @ PORTBIT(PORTB, 5); static bit LCD_RS @ PORTBIT(PORTA, 2); static bit LCD_RW @ PORTBIT(PORTA, 4); static bit LCD_EN @ PORTBIT(PORTA, 5); //****************************************************************************** //* function declarationis & global variables //****************************************************************************** void DelayMs(unsigned char); void write_SPI(unsigned int, unsigned int); void LCD_init(void); void LCD_write_str(int, int, char *, int); void LCD_write_data(unsigned char); void LCD_write_cmd(unsigned char); void LCD_wait_busy(void); int byteToInt(unsigned char, unsigned char) ; int intToByte(int, unsigned char *, unsigned char *); void save_vol(int, int); void set_volume(int, int); void itoa(int, char *, int); void uitoa(unsigned int, char*, int); signed char rc5_receive(unsigned int *, unsigned int *) ; signed char encoder(void); void DelayBigUs(unsigned int cnt); void DelayBigMs(unsigned int cnt) ; unsigned char byte1, byte2, byte3, byte4; char tmp[30]; unsigned int RC5addr = 0, RC5data = 0; #define LOGO "AUDIODESIGNGUIDE" #define VOLUME "Volume dB" #define MAX_VOL (255) #define MIN_VOL (0) #define INC_VOL (2) #define MAX_VDB (31) #define MIN_VDB (-95) #define INC_VDB (1) void main() { int vol; int vdb; int volume_up = 0; int volume_down = 0; TRISA = 0b00000000; // All port A are output TRISB = 0b11111111; // All port B are input TRISC = 0b00000000; // All post C are output ADCON1 = 0x06; // All posts AN4-7 to digital PORTA = 0b00000000; PORTC = 0b00000000; DAT = 0; CLK = 0; WEN = 1; CSL = 1; //################################################## //# starup interrupts //################################################## INTEDG = 0; INTE = 1; GIE = 1; DelayMs(50); //################################################## //# display startup //################################################## LCD_init(); strcpy(tmp, LOGO); LCD_write_str( 1, 1, tmp, 16); //################################################## //# get and set last saved volume level //################################################## byte1 = EEPROM_READ(0x00); byte2 = EEPROM_READ(0x01); byte3 = EEPROM_READ(0x02); byte4 = EEPROM_READ(0x03); vol = byteToInt(byte1, byte2); vdb = byteToInt(byte3, byte4); if (vol == -1 || vdb == -1) { vol = MIN_VOL; vdb = MIN_VDB; } set_volume(vol, vdb); //################################################## //# main loop //################################################## while(1) { volume_up = volume_down = 0; //################################################## //# get data from infrared receiver //################################################## // 20: rc5 cd remote 10100 if (RC5addr == 20) { // 16: volume + 10000 // 17: volume - 10001 switch (RC5data) { case 16: volume_up = 1; break; case 17: volume_down = 1; break; } RC5data = 0; RC5addr = 0; } //################################################## //# get input from button //################################################## if (VUP == 0) volume_up = 1; if (VDW == 0) volume_down = 1; //################################################## //# get input from encder //################################################## #ifdef NO_ENCODER switch(encoder()) { case 1: volume_up = 1; break; case -1: volume_down = 1; break; } #endif //################################################## //# elaborate input //################################################## if (volume_up) { if (vol < (MAX_VOL - INC_VOL)) { vol += INC_VOL; vdb += INC_VDB; } else { vol = MAX_VOL; vdb = MAX_VDB; } set_volume(vol, vdb); save_vol(vol, vdb); volume_up = 0; } else if (volume_down) { if (vol > INC_VOL) { vol -= INC_VOL; vdb -= INC_VDB; } else { vol = 0; vdb = -95; } set_volume(vol, vdb); save_vol(vol, vdb); volume_down = 0; } } } //********************************************************************* //* LCD read and write //********************************************************************* void LCD_init() { char * ptr, curr; char LCDstr[] = { 0x3c, // 111100: 8bits, 2lines, 5x10dots 0x01, // clear display 0x0c, // 1100: display on, cursor off 0x06, // 110: auto-increment 0x00 }; ptr = LCDstr; while(*ptr) { LCD_write_cmd(*ptr); ptr++; } } void LCD_wait_busy() { unsigned char busy; int retry = 1000; TRISC = 0xff; LCD_RS = 0; LCD_RW = 1; // read asm("nop"); asm("nop"); do { LCD_EN = 1; asm("nop"); asm("nop"); busy = PORTC & 0x80; LCD_EN = 0; } while (busy && retry-- > 0); TRISC = 0x00; } void LCD_write_cmd(unsigned char c) { LCD_wait_busy(); LCD_RW = 0; LCD_RS = 0; PORTC = c; LCD_EN = 1; LCD_EN = 0; } void LCD_write_data(unsigned char c) { LCD_wait_busy(); LCD_RW = 0; LCD_RS = 1; PORTC = c; LCD_EN = 1; LCD_EN = 0; } void LCD_write_str(int line, int pos, char * str, int len) { char * ptr; unsigned char curr; int i; //************************************************* // set the posistion and line //************************************************* if (line == 1) curr = 0b10000000 + (pos - 1); else curr = 0b11000000 + (pos - 1); LCD_write_cmd(curr); //************************************************* // send the string //************************************************* ptr = str; for(i = 0; *ptr && i < len; i++) { LCD_write_data(*ptr); ptr++; } } void DelayMs(unsigned char cnt) { unsigned char i; do { i = 4; do { DelayUs(250); } while(--i); } while(--cnt); } void interrupt prv_int(void) { #define TIME_MIN (500) #define TIME_MAX (1100) #define TIME_STEP (200) int OnTime, OffTime, i, k; unsigned int data = 0, addr = 0; if (INTF == 0) return; INTF = 0; for (OffTime = 0; !IR && OffTime < TIME_MAX; OffTime += TIME_STEP) { DelayUs(TIME_STEP); tmp[0] = '0'; } if (OffTime > TIME_MAX) return; if (OffTime < TIME_MIN) return; for (OnTime = 0; IR && OnTime < TIME_MAX; OnTime += TIME_STEP) { DelayUs(TIME_STEP); tmp[1] = '1'; } if (OnTime > TIME_MAX) return; if (OnTime < TIME_MIN) return; for (k = 0; k < 25; k++) { if (IR) { for (i = 0; IR && i <= OnTime; i += TIME_STEP) { DelayUs(TIME_STEP); } tmp[k+2] = '1'; } else { for (i = 0; !IR && i <= OffTime; i += TIME_STEP) { DelayUs(TIME_STEP); } tmp[k+2] = '0'; } } tmp[k+2] = '\0'; addr = 0; data = 0; for (k = 0; k < 5; k++) { if (tmp[5 + (k * 2)] == '1') { addr <<= 1; addr |= 1; } else { addr <<= 1; } } for (; k < 11; k++) { if (tmp[5 + (k * 2)] == '1') { data <<= 1; data |= 1; } else { data <<= 1; } } RC5data = data; RC5addr = addr; return; } void set_volume(int vol, int vdb) { CSL = 0; write_SPI(vol, 8); write_SPI(vol, 8); CSL = 1; WEN = 0; write_SPI(203, 8); write_SPI(vol, 8); WEN = 1; strcpy(tmp, VOLUME); LCD_write_str( 2, 1, tmp, 16); //itoa(vol, tmp, 10); //LCD_write_str( 2, 1, tmp); itoa(vdb, tmp, 10); LCD_write_str( 2, 8, tmp, 16); } void save_vol(int vol, int vdb) { intToByte(vol, &byte1, &byte2); intToByte(vdb, &byte3, &byte4); EEPROM_WRITE(0x00, byte1); EEPROM_WRITE(0x01, byte2); EEPROM_WRITE(0x02, byte3); EEPROM_WRITE(0x03, byte4); } void write_SPI(unsigned int data, unsigned int n_bit) { unsigned int bit_mask; int i; bit_mask = 1 << (n_bit - 1); for (i = 0; i < n_bit; i++) { CLK = 0; if ((data & bit_mask) == 0) DAT = 0; else DAT = 1; CLK = 1; data <<= 1; } } //********************************************************************* //* ENCODER - Checks rotary encoder and returns the following: //* //* 0: no movement //* -1: ccw rotation //* 1: cw rotation //* from http://www.littlefishbicycles.com/preamp //********************************************************************* signed char encoder(void) { static unsigned char a, b; if (!a & !b) { if (ENC_A) { a = ENC_A; return (-1); } if (ENC_B) { b = ENC_B; return (1); } } if (a & !b) { if (!ENC_A) { a = ENC_A; return (1); } if (ENC_B) { b = ENC_B; return (-1); } } if (a & b) { if (!ENC_A) { a = ENC_A; return (-1); } if (!ENC_B) { b = ENC_B; return (1); } } if (!a & b) { if (ENC_A) { a = ENC_A; return (1); } if (!ENC_B) { b = ENC_B; return (-1); } } return (0); } int intToByte(int integer, unsigned char * byte1, unsigned char * byte2) { *byte1 = (char)(integer >> 8); *byte2 = (char)(integer); return 0; } int byteToInt(unsigned char byte1, unsigned char byte2) { int integer; integer = byte1; integer <<= 8; integer |= byte2; return integer; } #define NUMBER_OF_DIGITS 14 /* space for NUMBER_OF_DIGITS + '\0' */ void uitoa(unsigned int value, char* string, int radix) { unsigned char index, i; index = NUMBER_OF_DIGITS; i = 0; do { string[--index] = '0' + (value % radix); if ( string[index] > '9') string[index] += 'A' - ':'; /* continue with A, B,.. */ value /= radix; } while (value != 0); do { string[i++] = string[index++]; } while ( index < NUMBER_OF_DIGITS ); string[i] = 0; /* string terminator */ } void itoa(int value, char* string, int radix) { int val = value; if (val < 10 && val > -10) *string++ = ' '; if (val < 0 && radix == 10) { *string++ = '-'; uitoa(-val, string, radix); } else { *string++ = ' '; uitoa(val, string, radix); } }