#include <stdio.h>
#include <avr\io.h>
#include <avr\interrupt.h>
#define LcdDATA_DDR		DDRD			// Portul pe care conectam firele de date la LCD-ul
#define LcdDATA_PORT	PORTD
#define LcdDATA_PIN		PIND
#define LcdCMD_DDR		DDRD			// Portul pe care conectam firele de comenzi la LCD
#define LcdCMD_PORT		PORTD
#define LcdCMD_PIN		PIND
#define LcdD4			PD0				// Pin-ul pentru firul de date D4 de pe LCD
#define LcdD5			PD1				// Pin-ul pentru firul de date D5 de pe LCD
#define LcdD6			PD2				// Pin-ul pentru firul de date D6 de pe LCD
#define LcdD7			PD3				// Pin-ul pentru firul de date D7 de pe LCD
#define LcdRS			PD4				// Pinul pentru selectare operatie (LCD)
#define LcdRW			PD5				// Pinul pentru Read/ Write (LCD)
#define LcdE			PD6				// Pinul de Enable (LCD)
#define LCD_INSTR_4wire 		0x28 	// 4 fire date, font 5x8
#define LCD_INSTR_display 		0x0C 	// Display On, Cursor On, Blinking On ( 1 Display Cursor Blink )
#define LCD_INSTR_clearDisplay 	0x01 	// Clear Display
#define LCD_INSTR_returnHome 	0x02 	// Return Cursor and LCD to Home Position
#define LCD_INSTR_nextLine 		0xC0 	// Return Cursor and LCD to Home Position
#define LCD_INSTR_gotoCGRAM		0x40	// go to Character Generator RAM
#define OFF						0
#define ON						1
#define HISTORY_LEN				1700
#define ZERO_ABS				127
#define nop() asm volatile("nop")
#define MAX_VOL 4//160
#define MIN_VOL 1//32
#define MAX_COUNT 2000
int FLAG_DISTORT;
int FLAG_ECHO;
int FLAG_CHORUS;
int FLAG_TREMOLO;
int vol=1,direction=0;
unsigned char freq[]={30,50,70,90};
int pas_curr = 0;
int index_freq = 0;
int count = 0;
int gain = 0;
unsigned char history[HISTORY_LEN];
void initHistory(){
	int i;
	for(i = 0;i<HISTORY_LEN;i++)
		history[i] = ZERO_ABS;
}
void addHistory(unsigned char amp){
	int i;
	for(i = HISTORY_LEN-1;i>0;i--)
		history[i] = history[i-1];
	history[0] = amp;
}
unsigned char getHistory(int idx){
	return history[idx];
}
void LCD_init();											// Initializare modul LCD.. trebuie apelata inainte de a se face orice operatie cu LCD-ul
void LCD_writeInstruction(unsigned char _instruction);		// Trimite o instructiune catre lcd (vezi datasheet)
void LCD_writeData(unsigned char _data);					// Trimite date catre LCD pentru afisare
void LCD_write(unsigned char _byte);						// trimite un bute catre LCD la modul general (nu conteaza daca e instructiune sau date)
void LCD_waitNotBusy();										// Asteptam pana cand lcd-ul devine disponibil pt o noua comanda
void LCD_waitInstructions(unsigned char _instructions);		// Asteapta un numar de cicli de tact.. loop
void LCD_print2(char* _msg1, char* _msg2);
void LCD_print(char* _msg);
// tine definitiile caracterelor pentru progress bar
// initializarea convertorului analog digital
void ADC_init()
{

	// AVCC cu condesator pe AREF; PA7 ca input single ended; rezultat left-adjusted (8 biti de date)
	ADMUX    |= _BV(MUX0); 	
	ADMUX    |= _BV(MUX1);
	ADMUX    |= _BV(MUX2);
	ADCSRA   |= _BV(ADEN);
	ADCSRA   |= _BV(ADSC);
	ADMUX    |= _BV(ADLAR);
	ADMUX    |= _BV(REFS0);
// activeaza ADC si intreruperea de conversie. Prescaler de ceas la maximum
	ADCSRA  |= _BV(ADPS0);
	ADCSRA  |= _BV(ADPS1);
	ADCSRA  |= _BV(ADPS2);
	ADCSRA  |= _BV(ADIE);
// pune pe input pinul intrarii de ADC (fara a modifica starea celorlalti pini)	
	DDRA   &= ~(_BV(PA7));
}
void SOUND_OUTPUT_init(){
	/* Pun pe output pinii PORTC0..7 */
	DDRC |= _BV(PC0);
	DDRC |= _BV(PC1);
	DDRC |= _BV(PC2);
	DDRC |= _BV(PA3);
	DDRC |= _BV(PC4);
	DDRC |= _BV(PC5);
	DDRC |= _BV(PC6);
	DDRC |= _BV(PC7);
}

/* Initializarea intrarilor(butoanele ce selecteaza efectul */
void SELECTOR_INPUT_init(){
	/* pun pe input pinii PORTB0..7 */
	DDRB = 0x00;
	/* activez rezistentele de pull-up */
	PORTB = 0xFF;

	/* initializez flag-urile */
	FLAG_DISTORT = OFF;
	FLAG_ECHO = OFF;
	FLAG_TREMOLO = OFF;
	FLAG_CHORUS = OFF;


}
unsigned char to_char(int a){
	if(a>255)
		return 255;
	if(a<0)
		return 0;
	return a;
}
/* efectele implementate */
/* efectul de echo */
unsigned char echo(int amplitude){
	int a = amplitude;
	a-=127;
	a +=(getHistory(HISTORY_LEN-1)-127)/4;
	a+=127;
	if(a>255)
		return 255;
	if(a<0)
		return 0;
	return a;
}
/* efectul de chorus */
unsigned char chorus(int amplitude){
	long a = amplitude;
	a-=127;

	a+=(getHistory(0)-127)/16;
	a+=(getHistory(7)-127)/32;
	a+=(getHistory(2)-127)/16;
	a+=(getHistory(4)-127)/16;

	a+=127;
	if(a>255)
		return 255;
	if(a<0)
		return 0;
	return a;

}
unsigned char compression(int amplitude){
	int a = amplitude;
	a = a-127;
		if((a>=-40)&&(a<=40)) return 127;
	return a+127;


}
unsigned char tremolo(int amp){
	long a = amp;

	count++;

	if(count == MAX_COUNT)
	{
		count = 0;
	
		if(direction == 1)
			gain++;
		else
			gain--;
	}

	if((gain>50) && (direction==1))
		direction = 0;
	if((gain< -50) && (direction==0))
		direction = 1;

	a+=gain;
	return to_char(a);

	/* alta varianta */

	/*long a = amp;
	pas_curr++;



	if(pas_curr==freq[index_freq]){
		pas_curr = 0;
		index_freq++;
		index_freq = index_freq%4;
	

		if(direction ==1)
			vol++;
		else
			vol--;
	
		if(vol >= MAX_VOL)
			direction=0;
		
		else	

if (vol ⇐ MIN_VOL)

				direction=1;
	}	

	a-=127;
	if(vol==1) a*=-2;
	if(vol==2) a/=-2;
	if(vol==3) a/=2;
	if(vol==4) a*=2;

	a += 127;
	return to_char(a);*/
}	
unsigned char distortion(int amplitude){
	int a;
	a = amplitude;

	a-=127;
	a*=2;
	a+=127;
	return to_char(a);
}
int adjustInputVolume(int a){
	if(a>255)
		a = 255;
	if(a<0)
		a = 0;
	
	/*atenuam semnalul de intrare */
	a-=127;
	a/=4;
	a+=127;

	return to_char(a);

}
// intreruperea de conversie
SIGNAL(SIG_ADC)
{
	int amp = 0;
	int a = 0;

//amp = amplitudinea de la intrare
	amp = ADCH;
//a = amplitudinea de la intrare
	a = adjustInputVolume(amp);

unsigned char tPINB;
//nop();
tPINB = PINB;
/* Actualizez flagurile daca este cazul */

	/* PINB0 - distors */
	/*primul buton este distortion */
		
if(tPINB & (1<<0))
	FLAG_DISTORT = ON;
else
	FLAG_DISTORT = OFF;
	
	/* PINB1 - compres */
	/* al 2-lea buton este compressor */
if(tPINB & (1<<1))
	FLAG_TREMOLO = ON;
else
	FLAG_TREMOLO = OFF;
		
	/* PINB2 - echo */
	/* al 3-lea buton este echo */
if(tPINB & (1<<2))
	FLAG_ECHO = ON;
else
	FLAG_ECHO = OFF;
		
	/* PINB3 -chorus */
	/* al 4-lea buton este chorus */
if(tPINB & (1<<3))
	FLAG_CHORUS = ON;
else
	FLAG_CHORUS = OFF;


if(FLAG_DISTORT){
	a = distortion(amp);
	addHistory(amp);
	goto ret;
}

if(FLAG_TREMOLO){
	a = tremolo(amp);
	addHistory(amp);
	goto ret;
}
	
if(FLAG_CHORUS){
	a = chorus(a);
	addHistory(a);
	goto ret;
}
	
if(FLAG_ECHO){
	a = echo(a);
	addHistory(echo(a));
	goto ret;
}
ret:
PORTC = to_char(a);
//PORTC = 200;
/* ADIE este bitul de Enable pentru întrerupere. 
Aceasta va fi generata automat la fiecare conversie 
daca bitul respectiv este setat.*/

ADCSRA  |= _BV(ADIE);

}
int main()
{
//	int i;

//LCD_init();
//LCD_writeInstruction(LCD_INSTR_clearDisplay);

//LCD_print2("Guitar            ","Effects              ");

/* Initializare convertor analog-digital */
ADC_init();

/* Initializare iesire digitala (catre DAC) */
SOUND_OUTPUT_init();

/* Initializare intrarile ce selecteaza efectele */
SELECTOR_INPUT_init();

/* initializare history */
initHistory();

/* Activare intreruperi */
sei();

/* Bucla programului */
for(;;)
{
	// cer ADC-ului sa faca o conversie
	
	/* scrierea acestui bit pe 1 
	va genera automat o conversie de 
	pe intrarea selectata. */
	
	
	ADCSRA |= _BV(ADSC);
}
return 0;
}
/************************************************************************ 
* IMPLEMENTARE API LCD.. implementare este in partea de jos a fisierului
************************************************************************/
void LCD_init()
{
LcdDATA_DDR |=  (1<<LcdD4)|(1<<LcdD5)|(1<<LcdD6)|(1<<LcdD7);	// setam pinii de date ca pini de iesire
LcdCMD_DDR  |=  (1<<LcdRS)|(1<<LcdRW)|(1<<LcdE);				// setam pinii de comenzi ca pini de iesire
LCD_waitNotBusy();

LcdCMD_PORT   &= ~(1<<LcdRS);								// Setam linia RS pe low
LcdCMD_PORT   &= ~(1<<LcdRW);								// Setam linia RW pe low (acum suntem in modul de trimis instructiuni)
LcdDATA_PORT  &= ~(1<<LcdD4)&~(1<<LcdD6)&~(1<<LcdD7); 		// Specificam ca vrem 4 fire de date, prima comanda (LcdD5 activ, restul nu)
LcdDATA_PORT  |=  (1<<LcdD5);								// setam pinii de comenzi ca pini de iesire

LcdCMD_PORT |=  (1<<LcdE);					// Setam linia E(nable) pe high; aceasta ii specifica LCD-ului sa preia datele
LCD_waitInstructions(6);					// Asteptam o perioada de timp T
LcdCMD_PORT &= ~(1<<LcdE );					// Setam linia E(nable) pe low; transferul s-a terminat
LCD_writeInstruction(LCD_INSTR_4wire); 		// Incarcam comanda: 4 bit data, 2 lines, 5x8 font
LCD_writeInstruction(LCD_INSTR_display); 	// Display On, Cursor On, Blinking On
LCD_writeInstruction(0x06);					// Increment, no shift
LCD_writeInstruction(0x01);					// Clear Display
}
void LCD_writeInstruction(unsigned char _instruction)
{
LCD_waitNotBusy();						// asteptam ca LCD-ul sa fie liber sa primeasca comenzile	
LcdCMD_PORT &= ~(1 << LcdRS);			// setam pinul RS pe low.. low=instructiuni, high=date
LcdCMD_PORT &= ~(1 << LcdRW);			// setam pinul RW pe low (suntem in modul de comenzi acum)
LCD_write(_instruction);				// apelam procedura ce trimite byte-ul pe firele de date
}
void LCD_writeData(unsigned char _data)
{
LCD_waitNotBusy();						// asteptam ca LCD-ul sa fie liber sa primeasca comenzile	
LcdCMD_PORT |= (1 << LcdRS);			// setam pinul RS pe high
LcdCMD_PORT &= ~(1 << LcdRW);			// setam pinul RW pe low (suntem in modul de comenzi acum)
LCD_write(_data);						// apelam procedura ce trimite byte-ul pe firele de date
}
void LCD_write(unsigned char _byte)
{
unsigned char _byte2;

_byte2 = _byte>>4;
LcdDATA_PORT &= ~(1<<LcdD4);
if ( bit_is_set( _byte2, 0 ) )
	LcdDATA_PORT |= (1<<LcdD4);
	
LcdDATA_PORT &= ~(1<<LcdD5);
if ( bit_is_set( _byte2, 1 ) )
	LcdDATA_PORT |= (1<<LcdD5);
LcdDATA_PORT &= ~(1<<LcdD6);
if ( bit_is_set( _byte2, 2 ) )
	LcdDATA_PORT |= (1<<LcdD6);
LcdDATA_PORT &= ~(1<<LcdD7);
if ( bit_is_set( _byte2, 3 ) )
	LcdDATA_PORT |= (1<<LcdD7);
LcdCMD_PORT |= (1<<LcdE);						// Setam Pinul E pe high
LCD_waitInstructions(6);						// Asteptam o perioada de timp T
LcdCMD_PORT &= ~(1<<LcdE);						// Setam Pinul E pe low
LCD_waitInstructions(6);						// Asteptam o perioada de timp T

LcdDATA_PORT &= ~(1<<LcdD4);
if ( bit_is_set( _byte, 0 ) )
	LcdDATA_PORT |= (1<<LcdD4);

LcdDATA_PORT &= ~(1<<LcdD5);
if ( bit_is_set( _byte, 1 ) )
	LcdDATA_PORT |= (1<<LcdD5);
LcdDATA_PORT &= ~(1<<LcdD6);
if ( bit_is_set( _byte, 2 ) )
	LcdDATA_PORT |= (1<<LcdD6);
LcdDATA_PORT &= ~(1<<LcdD7);
if ( bit_is_set( _byte, 3 ) )
	LcdDATA_PORT |= (1<<LcdD7);
LcdCMD_PORT |= (1<<LcdE);						// Setam Pinul E pe high
LCD_waitInstructions(6);						// Asteptam o perioada de timp T
LcdCMD_PORT &= ~(1<<LcdE);						// Setam Pinul E pe low
}
void LCD_waitNotBusy()
{
unsigned char _loop = 1;
while (_loop)
{
	LcdDATA_DDR &= ~(1<<LcdD4 | 1<<LcdD5 | 1<<LcdD6 | 1<<LcdD7);	// Setam pinii de date de la LCD pe in pt a citi busy flag
	LcdDATA_PORT &= ~(1<<LcdD4 | 1<<LcdD5 | 1<<LcdD6 | 1<<LcdD7); 	// Dezactivam pullup resistor pentru pinii de in
	
	LcdCMD_PORT &= ~(1<<LcdE);					// Setam pin-ul e pe low; ar trebui sa fie deja low, doar ne asiguram
	LcdCMD_PORT &= ~(1<<LcdRS);					// Setam pinul RS pe low
	LcdCMD_PORT |=  (1<<LcdRW);					// Setam pinul RW pe high (acum suntem in modul de interogare busy/adr)
	
	LcdCMD_PORT |= (1<<LcdE);						// Setam Pinul E pe high
	LCD_waitInstructions(6);						// Asteptam o perioada de timp T
	_loop = LcdDATA_PIN & (1<<LcdD7);				// Citim busy flag-ul
	LcdCMD_PORT &= ~(1<<LcdE);						// Setam Pinul E pe low
	
	LCD_waitInstructions(6);						// Asteptam o perioada de timp T
	
	LcdCMD_PORT |= (1<<LcdE);						// Setam Pinul E pe high
	LCD_waitInstructions(6);						// Asteptam o perioada de timp T
	LcdCMD_PORT &= ~(1<<LcdE);						// Setam Pinul E pe low
	LcdDATA_DDR |= (1<<LcdD4 | 1<<LcdD5 | 1<<LcdD6 | 1<<LcdD7); // Setam Portul de LCD ca port de iesire la loc
	}
}
void LCD_printDecimal2u(unsigned int _n)
{
unsigned char tmp=0;

// Extragem sutele
while(_n>=100)
	_n-=100;
while(_n>=10){
	tmp++;
	_n-=10;
}
LCD_writeData(tmp+'0');
LCD_writeData(_n+'0');
}
void LCD_printHexa(unsigned int _n)
{
unsigned char _tmp = _n>>4;
if (_tmp>9)
	_tmp += 'A'-10;
else
	_tmp += '0';
LCD_writeData( _tmp );
_tmp = _n & 0x0F;
if (_tmp>9)
	_tmp += 'A'-10;
else
	_tmp += '0';
LCD_writeData( _tmp );
}
void LCD_print(char* _msg)
{
unsigned char i=0;
for( ; _msg[i]!=0 && i<16; i++)
	LCD_writeData( _msg[i] );
}
void LCD_print2(char* _msg1, char* _msg2)
{
LCD_writeInstruction(LCD_INSTR_clearDisplay);
LCD_print(_msg1);
LCD_writeInstruction(LCD_INSTR_nextLine);
LCD_print(_msg2);
}
void LCD_waitInstructions(unsigned char _instructions)
{
while (_instructions--)
	;
}
pm/pm/prj2009/cc/effects.c.txt · Last modified: 2020/02/14 00:57 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0