REKLAMA

organ.zip

Klawiatura nożna do organów

Załączam kod. Jak się trochę pokombinuje, to można wywnioskować, jak są podłączone klawisze:) Mniej więcej tak: Matryca X-Y 4x8, X (drive): PC0-PC3 Y (sense): PD7-PD3, PB7-PB6, PB0. Każdy klawisz ma szeregową diodę w kierunku sense->drive. Tablica mapa_klawiszy (klawisze.c) definiuje, któremu klawiszowi przypisany jest jaki ton. Klawisze z wartościami ujemnymi to klawisze specjalne (ich funkcje wbite są "na sztywno" w kod programu). Kilka uwag: - Aktualna wersja oprogramowania nie obsługuje wejścia MIDI. - Po włączeniu program sprawdza stan klawiatury. Jeśli było wciśnięte najwyższe "C", cała klawiatura jest transponowana oktawę wyżej. Jeśli było wciśnięte najniższe "C", to cała klawiatura jest transponowana oktawę niżej. Pozwala to ustalić sobie przy włączaniu najwygodniejszy zakres. - Klawisze specjalne obsługują funkcje Hammonda; prawdopodobnie nie będą działać z innym sprzętem.


Pobierz plik - link do postu
  • organ.zip
    • klawisze.c
    • pedaly.aws
    • avrlibdefs.h
    • rs232.c
    • avrlibtypes.h
    • pedaly.aps
    • rs232.h
    • klawisze.h
    • pedaly.c
    • global.h


organ.zip > avrlibdefs.h

/*! \file avrlibdefs.h \brief AVRlib global defines and macros. */
//*****************************************************************************
//
// File Name : 'avrlibdefs.h'
// Title : AVRlib global defines and macros include file
// Author : Pascal Stang
// Created : 7/12/2001
// Revised : 9/30/2002
// Version : 1.1
// Target MCU : Atmel AVR series
// Editor Tabs : 4
//
// Description : This include file is designed to contain items useful to all
// code files and projects, regardless of specific implementation.
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************


#ifndef AVRLIBDEFS_H
#define AVRLIBDEFS_H

// Code compatibility to new AVR-libc
// outb(), inb(), inw(), outw(), BV(), sbi(), cbi(), sei(), cli()
#ifndef outb
#define outb(addr, data) addr = (data)
#endif
#ifndef inb
#define inb(addr) (addr)
#endif
#ifndef outw
#define outw(addr, data) addr = (data)
#endif
#ifndef inw
#define inw(addr) (addr)
#endif
#ifndef BV
#define BV(bit) (1 & lt; & lt; (bit))
#endif
#ifndef cbi
#define cbi(reg,bit) reg & = ~(BV(bit))
#endif
#ifndef sbi
#define sbi(reg,bit) reg |= (BV(bit))
#endif
#ifndef cli
#define cli() __asm__ __volatile__ ( " cli " ::)
#endif
#ifndef sei
#define sei() __asm__ __volatile__ ( " sei " ::)
#endif

// support for individual port pin naming in the mega128
// see port128.h for details
#ifdef __AVR_ATmega128__
// not currently necessary due to inclusion
// of these defines in newest AVR-GCC
// do a quick test to see if include is needed
#ifndef PD0
#include " port128.h "
#endif
#endif

// use this for packed structures
// (this is seldom necessary on an 8-bit architecture like AVR,
// but can assist in code portability to AVR)
#define GNUC_PACKED __attribute__((packed))

// port address helpers
#define DDR(x) ((x)-1) // address of data direction register of port x
#define PIN(x) ((x)-2) // address of input register of port x

// MIN/MAX/ABS macros
#define MIN(a,b) ((a & lt; b)?(a):(b))
#define MAX(a,b) ((a & gt; b)?(a):(b))
#define ABS(x) ((x & gt; 0)?(x):(-x))

// constants
#define PI 3.14159265359

#endif


organ.zip > rs232.h

#define ROZMIAR_BUFORA_NAD 32
#define ROZMIAR_BUFORA_ODB 32

#define NIC 0
#define WCISNIECIE 1
#define PUSZCZENIE 2


void rs232_init();
void wyslij_bajt(char dana); //pakuje bajt do bufora i ew. szturcha port
void wyslij_napis(char* napis); //robi czaru-maru i napis l¹duje na terminalu
void wyslij_dane(char* dane, int dlugosc); //wysy³a bufor danych o podanej d³ugoœci
int czy_odebrano_dane(); //zwraca 1, jeœli coœ jest w buforze odczytu, i 0 jak nie ma
char odbierz_bajt(); //zwraca ostatni bajt z bufora odczytu

void wcisnij_klawisz(char nutka);
void pusc_klawisz(char nutka);
void wcisnij_klawisz_specjany(char numer);
void pusc_klawisz_specjany(char numer);


organ.zip > klawisze.h

void init_klawiszy();
unsigned long int czytaj_stan_klawiszy();
void procesuj_klawisze();


organ.zip > klawisze.c

#include & lt; avr/io.h & gt;
#include " global.h "
#include & lt; util/delay.h & gt;
#include & lt; avr/interrupt.h & gt;
#include " rs232.h "
#include " klawisze.h "


static signed char mapa_klawiszy[] = {21, 24, 22, -1, -2, -3, 25, 23,
13, 16, 14, 20, 18, 19, 17, 15,
12, 9, 11, 5, 7, 6, 8, 10,
4, 1, 3, -4, -5, -6, 0, 2};

volatile unsigned long int aktualny_stan_klawiszy; //32 bity
char czasy_oczekiwania[32];
char czas_oczekiwania = 10; //antydrgacz styków
char oktawa = 0; //przeuniêcie o oktawê w górê albo w dó³
volatile int czas_od_zmiany = 0;

void init_klawiszy()
{
int i;
unsigned long int stan_klawiszy;

PORTD |= 0xF8; //pullupy
PORTB |= 0xC1; //pullupy

PORTC |= 0x0F; //wybieracz
DDRC |= 0x0F;

aktualny_stan_klawiszy = 0xFFFFFFFF;
for (i = 0; i & lt; 32; i++)
czasy_oczekiwania[i] = 0;

stan_klawiszy = czytaj_stan_klawiszy();

if ((stan_klawiszy & (unsigned long int)1 & lt; & lt; 25) == 0) //dolne C
oktawa = -1;
if ((stan_klawiszy & (unsigned long int)1 & lt; & lt; 6) == 0) //górne C
oktawa = 1;



};

unsigned long int czytaj_stan_klawiszy()
{
int i;
unsigned long int wynik = 0;
for (i = 0; i & lt; 4; i++)
{
PORTC & = ~(1 & lt; & lt; i); //w³¹czamy wybierak

wynik = wynik & lt; & lt; 5;
wynik |= (PIND & gt; & gt; 3) & 0x1F;
wynik = wynik & lt; & lt; 2;
wynik |= (PINB & gt; & gt; 6) & 0x03;
wynik = wynik & lt; & lt; 1;
wynik |= PINB & 0x01;

PORTC |= 0x0F; //wy³¹czamy wybierak
}
return wynik;
}

void procesuj_klawisze()
{
int i;
unsigned long int nowy_stan_klawiszy;

nowy_stan_klawiszy = czytaj_stan_klawiszy();

for (i = 0; i & lt; 32; i++)
{
if (czasy_oczekiwania[i])
{
czasy_oczekiwania[i]--;
continue; //antydrgawka
}
//tu patrzymy na zmianê stanu
if ((nowy_stan_klawiszy & (unsigned long int)1 & lt; & lt; i) !=
(aktualny_stan_klawiszy & (unsigned long int)1 & lt; & lt; i)) //by³a zmiana
{
aktualny_stan_klawiszy ^= (unsigned long int)1 & lt; & lt; i;
czasy_oczekiwania[i] = czas_oczekiwania;
if (nowy_stan_klawiszy & (unsigned long int)1 & lt; & lt; i) //puszczony
{
if (mapa_klawiszy[i] & gt; = 0)
pusc_klawisz(23 + mapa_klawiszy[i] + (12*oktawa)); //32 eksperymentalnie, ¿eby by³o coœ s³ychaæ
else
pusc_klawisz_specjany(-mapa_klawiszy[i]);
}
else
{
if (mapa_klawiszy[i] & gt; = 0)
wcisnij_klawisz(23 + mapa_klawiszy[i] + (12*oktawa));
else
wcisnij_klawisz_specjany(-mapa_klawiszy[i]);
}
czas_od_zmiany = 0;
}
}
czas_od_zmiany++;
if (czas_od_zmiany & gt; 100)
{
czas_od_zmiany = 0;
wyslij_bajt(0xFE); //active sensing
}
}


organ.zip > pedaly.c

#include & lt; avr/io.h & gt;
#include " global.h "
#include & lt; util/delay.h & gt;
#include & lt; avr/interrupt.h & gt;
#include " rs232.h "
#include " klawisze.h "


int main()
{
// unsigned char licznik_nut = 24;

rs232_init();
sei();

_delay_ms(100);

init_klawiszy();

_delay_ms(100);

while(1)
{
procesuj_klawisze();
_delay_ms(1);
}

/* while (1)
{
wcisnij_klawisz(licznik_nut);

_delay_ms(250);

pusc_klawisz(licznik_nut);

_delay_ms(250);


licznik_nut++;
if (licznik_nut & gt; 48)
licznik_nut = 24;

}
*/


}


organ.zip > rs232.c

#include & lt; avr/io.h & gt;
#include " global.h "
#include & lt; util/delay.h & gt;
#include & lt; avr/interrupt.h & gt;
#include " rs232.h "



volatile char bufor_nad[ROZMIAR_BUFORA_NAD];
volatile int zapis_nad;
volatile int odczyt_nad;
volatile char port_aktywny;

volatile char bufor_odb[ROZMIAR_BUFORA_ODB];
volatile int zapis_odb;
volatile int odczyt_odb;

volatile char ostatnia_akcja = NIC;
volatile char kanal_midi = 0x02; //kana³ MIDI (3)
volatile char kanal_master = 0x01; //kana³ mastera (2) - do ró¿owych guzików

volatile char leslie_fast = 0;
volatile char vibrato = 0;

int czy_odebrano_dane()
{
if (zapis_odb != odczyt_odb)
return 1;
return 0;
}

char odbierz_bajt()
{
char wynik;
while (!czy_odebrano_dane()); //czekamy na dane

wynik = bufor_odb[odczyt_odb++];
if (odczyt_odb == ROZMIAR_BUFORA_ODB)
odczyt_odb = 0; //zawijamy bufor

return wynik;
}

void wyslij_dane(char* dane, int dlugosc)
{
int i;
for (i = 0; i & lt; dlugosc; i++)
wyslij_bajt(dane[i]);

}

void wyslij_napis(char* napis)
{
int indeks = 0;

while (napis[indeks])
wyslij_bajt(napis[indeks++]);
}


void wyslij_bajt(char dana)
{

while ( //jeœli bufor jest zapchany...
(zapis_nad == (odczyt_nad-1))
||
( (zapis_nad == (ROZMIAR_BUFORA_NAD-1)) & & (odczyt_nad == 0) )
);
// _delay_us(100); //...to czekamy



bufor_nad[zapis_nad++] = dana; //wpisanie danej do bufora
if (zapis_nad == ROZMIAR_BUFORA_NAD)
zapis_nad = 0; // " zawiniêcie " bufora


if (!port_aktywny) //jeœli port by³ nieaktywny, to szturchamy
{
port_aktywny = 1;
UDR = bufor_nad[odczyt_nad++];
if (odczyt_nad == ROZMIAR_BUFORA_NAD)
odczyt_nad = 0; //zawijamy bufor
}
}



ISR(USART_TXC_vect) //przerwanie nadawania
{
if (zapis_nad != odczyt_nad) //w buforze coœ jest
{
UDR = bufor_nad[odczyt_nad++]; //wysy³amy znak, zwiêkszamy indeks
if (odczyt_nad == ROZMIAR_BUFORA_NAD)
odczyt_nad = 0; //zawijamy bufor
}
port_aktywny = 0; //nasz port jest nieaktywny i ju¿ nie œle danych
}

ISR(USART_RXC_vect) //przerwanie odbioru
{
char odebrane;
odebrane = UDR;

if (!( //jeœli bufor NIE jest zapchany...
(zapis_odb == (odczyt_odb-1))
||
( (zapis_odb == (ROZMIAR_BUFORA_ODB-1)) & & (odczyt_odb == 0) )
))
{ //..to dodajemy nowy znak
bufor_odb[zapis_odb++] = odebrane; //odczyt i wpisanie danej do bufora
if (zapis_odb == ROZMIAR_BUFORA_ODB)
zapis_odb = 0; // " zawiniêcie " bufora
}

}


void rs232_init()
{
ostatnia_akcja = NIC;


zapis_nad = 0;
odczyt_nad = 0;
port_aktywny = 0;
zapis_odb = 0;
odczyt_odb = 0;


DDRD |= 0x02; //PD1 = TX ustawiamy na wyjœcie

UBRRH = 0;
UBRRL = 15; //31250 bps
UCSRC = 0b10000110;
UCSRB = 0b11011000;
//UCSRA = 0b00000010; //double speed
}

void wcisnij_klawisz(char nutka)
{
/* if (ostatnia_akcja != WCISNIECIE)
{
wyslij_bajt(0x90 | kanal_midi);
ostatnia_akcja = WCISNIECIE;
}*/
wyslij_bajt(0x90 | kanal_midi);

wyslij_bajt(nutka & 0x7F);
wyslij_bajt(0x7F); //velocity
}

void pusc_klawisz(char nutka)
{
/*if (ostatnia_akcja != PUSZCZENIE)
{
wyslij_bajt(0x80 | kanal_midi);
ostatnia_akcja = PUSZCZENIE;
}*/
wyslij_bajt(0x80 | kanal_midi);
wyslij_bajt(nutka & 0x7F);
wyslij_bajt(0x7F); //velocity - never mind
}

void wyslij_nrpn(u08 nrpnH, u08 nrpnL, u08 dataH, u08 dataL)
{
wyslij_bajt(0xB0 | kanal_master);
wyslij_bajt(0x63);
wyslij_bajt(nrpnH);

wyslij_bajt(0xB0 | kanal_master);
wyslij_bajt(0x62);
wyslij_bajt(nrpnL);

wyslij_bajt(0xB0 | kanal_master);
wyslij_bajt(0x06);
wyslij_bajt(dataH);

wyslij_bajt(0xB0 | kanal_master);
wyslij_bajt(0x26);
wyslij_bajt(dataL);
}

void wcisnij_klawisz_specjany(char numer)
{


switch (numer)
{
case 1: break; //nic nie ma
case 2: //klawisz 4
wyslij_bajt(0xC0 | kanal_master); //preset 2
wyslij_bajt(0x01);
break;
case 3: //klawisz 5
wyslij_bajt(0xC0 | kanal_master); //preset 3
wyslij_bajt(0x02);

break;
case 4: //klawisz 1
if (leslie_fast) //leslie fast
{
wyslij_nrpn(0x01, 0x09, 0x00, 0x00);
leslie_fast = 0;
}
else
{
wyslij_nrpn(0x01, 0x09, 0x01, 0x00);
leslie_fast = 1;
}
break;
case 5: //klawisz 2
if (vibrato) //vibrato 0/1
{
wyslij_nrpn(0x02, 0x09, 0x00, 0x00);
vibrato = 0;
}
else
{
wyslij_nrpn(0x02, 0x09, 0x01, 0x00);
vibrato = 1;
}

break;
case 6: //klawisz 3
wyslij_bajt(0xC0 | kanal_master); //preset 1
wyslij_bajt(0x00);
break;
default:
break;




}
}


void pusc_klawisz_specjany(char numer)
{
switch (numer)
{
case 1: break; //nic nie ma
case 2: //klawisz 4

break;
case 3: //klawisz 5

break;
case 4: //klawisz 1

break;
case 5: //klawisz 2

break;
case 6: //klawisz 3

break;
default:
break;




}
}


organ.zip > global.h

/*! \file global.h \brief AVRlib project global include. */
//*****************************************************************************
//
// File Name : 'global.h'
// Title : AVRlib project global include
// Author : Pascal Stang - Copyright (C) 2001-2002
// Created : 7/12/2001
// Revised : 9/30/2002
// Version : 1.1
// Target MCU : Atmel AVR series
// Editor Tabs : 4
//
// Description : This include file is designed to contain items useful to all
// code files and projects.
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************

#ifndef GLOBAL_H
#define GLOBAL_H

// global AVRLIB defines
#include " avrlibdefs.h "
// global AVRLIB types definitions
#include " avrlibtypes.h "

// project/system dependent defines

#ifndef F_CPU
// CPU clock speed
//#define F_CPU 16000000 // 16MHz processor
//#define F_CPU 14745000 // 14.745MHz processor
#define F_CPU 8000000 // 8MHz processor
//#define F_CPU 7372800 // 7.37MHz processor
//#define F_CPU 4000000 // 4MHz processor
//#define F_CPU 3686400 // 3.69MHz processor
#endif
#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond

#endif


organ.zip > avrlibtypes.h

/*! \file avrlibtypes.h \brief AVRlib global types and typedefines. */
//*****************************************************************************
//
// File Name : 'avrlibtypes.h'
// Title : AVRlib global types and typedefines include file
// Author : Pascal Stang
// Created : 7/12/2001
// Revised : 9/30/2002
// Version : 1.0
// Target MCU : Atmel AVR series
// Editor Tabs : 4
//
// Description : Type-defines required and used by AVRlib. Most types are also
// generally useful.
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************


#ifndef AVRLIBTYPES_H
#define AVRLIBTYPES_H

#ifndef WIN32
// true/false defines
#define FALSE 0
#define TRUE -1
#endif

// datatype definitions macros
typedef unsigned char u08;
typedef signed char s08;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned long u32;
typedef signed long s32;
typedef unsigned long long u64;
typedef signed long long s64;

/* use inttypes.h instead
// C99 standard integer type definitions
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned long uint32_t;
typedef signed long int32_t;
typedef unsigned long uint64_t;
typedef signed long int64_t;
*/
// maximum value that can be held
// by unsigned data types (8,16,32bits)
#define MAX_U08 255
#define MAX_U16 65535
#define MAX_U32 4294967295

// maximum values that can be held
// by signed data types (8,16,32bits)
#define MIN_S08 -128
#define MAX_S08 127
#define MIN_S16 -32768
#define MAX_S16 32767
#define MIN_S32 -2147483648
#define MAX_S32 2147483647

#ifndef WIN32
// more type redefinitions
typedef unsigned char BOOL;
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

typedef unsigned char UCHAR;
typedef unsigned int UINT;
typedef unsigned short USHORT;
typedef unsigned long ULONG;

typedef char CHAR;
typedef int INT;
typedef long LONG;
#endif

#endif