#define __16f88 #include"pic/pic16f88.h" /* Yves Usson - october 2008 Mono keyboard scanner firmware v1.00 version for a 6x11 key matrix PORTA IN OUT RA0 MATRIXCOM IN COMMON PIN OF THE CD4051 MATRIX RA1 LEGATO IN LEGATO SWITCH RA2 PRIORITY IN PRIORITY SWITCH RA3 STATUS OUT STATUS LED RA4 GATEOUT OUT GATE OUT RA5 MCLR IN RESET RA6 UNUSED1 OUT RA7 UNUSED2 OUT TRISA = 0b00100111 PORTB IN OUT RB0 ADDR0 OUT RB0 TO RB2 ADDRESS TO 4051 AND DAC RB1 ADDR1 OUT RB2 ADDR2 OUT RB3 ADDR3 OUT RB3 TO RB6 ADDRESS TO 4067 AND DAC RB4 ADDR4 OUT RB5 ADDR5 OUT RB6 ADDR6 OUT RB7 DAC_CS OUT DAC LATCH CONTROL (LATCHES ON RISE) TRISB = 0b00000000 */ typedef unsigned char ubyte; typedef unsigned short ushort; typedef unsigned int word; // Set the __CONFIG word: // _CP_OFF no Flash program memory code protection // _CCP1_RB0 CCP1 function on pin RB0 // _DEBUG_OFF no ISCP debugging // _WRT_PROTECT_OFF no write protection // _CPD_OFF no Data EE memory code protection // _LVP_OFF no Low voltage programming // _BODEN_OFF Brown-out Reset Enable bit disabled // _MCLR_ON RA5 is MCLR // _PWRTE_OFF Power-up timer OFF // _WDT_OFF no watchdog // _INTRC_IO Internal clock, RA6 and RA7 in/out word at _CONFIG1 __CONFIG = _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF & _INTRC_IO; //word at _CONFIG2 __CONFIG = _IESO_OFF & _FCMEN_OFF; short legato_flag; short highest_flag; ubyte old_key; ubyte gate_flag; #define MASK_MATRIX 0b01111111 #define XIRTAM_KSAM 0b10000000 #define MAXKEYS 61 // Set various port bits #define StatusLEDOn RA3 = 1 #define GateOn RA4 = 1 #define DAC_CS_High RB7 = 1 // Unset various port bits #define StatusLEDOff RA3 = 0 #define GateOff RA4 = 0 #define DAC_CS_Low RB7 = 0 // Test various port bits #define IsKeyOn (RA0 == 1) #define IsLegatoOn (RA1 == 1) #define IsHighestPriorityOn (RA2 == 1) void Init_PIC(void) { OSCCON = 0b01111100; // osc at 8 MHz TRISA = 0b00100111; // positionnenemt I/O du port A TRISB = 0b00000000; // positionnenemt I/O du port B ANSEL = 0; //désactivation des convertisseurs A/N PORTB = 0; RA1 = 0; RA2 = 0; } void Delay100us(void) // 0.1 ms. at 8MHz { unsigned char i,j; for(i=0;i<5;i++) for(j=0;j<3;j++); } void Delay500us(void) // 0.5 ms. at 8MHz { unsigned char i,j; for(i=0;i<30;i++) for(j=0;j<3;j++); } void Delay100ms(void) // 0.1 s at 8MHz { unsigned short i,j; for(i=0;i<500;i++) for(j=0;j<35;j++); } void SetMatrix(short key,short bank) { ubyte by1 = PORTB & XIRTAM_KSAM; ubyte by2 = (ubyte)(key & MASK_MATRIX); ubyte by3 = (ubyte)((bank << 3) & MASK_MATRIX); PORTB = (by1 | by2 | by3); } void WriteDAC(short v) { ubyte by1 = PORTB & XIRTAM_KSAM; ubyte by2 = (ubyte)(v & MASK_MATRIX); PORTB = (by1 | by2); DAC_CS_Low; // when down latches transparent //Delay100us(); DAC_CS_High; // when high latches frozen } void Test() { ubyte i; short j; GateOff; j = 0; for (i = 1; i < 5; i++) { StatusLEDOn; WriteDAC(j); Delay100ms(); WriteDAC(j+4); Delay100ms(); StatusLEDOff; WriteDAC(j+7); Delay100ms(); WriteDAC(j+4); Delay100ms(); j += 12; } WriteDAC(0); } ubyte ScanDown() { short i,key,bank; i = MAXKEYS-1; // set key index to highest value key = 0; bank = 10; // key + (bank * 6) = i do { SetMatrix(key,bank); // check ith key if (IsKeyOn) // test if key is depressed and do whatever is to be done { if (i != old_key) { WriteDAC(i); // lock key into DAC if (!legato_flag && gate_flag) // if not in legato mode and another key was previously on break GATE { GateOff; StatusLEDOff; Delay500us(); } } GateOn; StatusLEDOn; gate_flag = 1; old_key = i; return 1; // leave the function as soon as a key was detected } i--; // otherwise decrement key index key--; if (key == -1) { key = 5; bank--;} } while (i > -1); // end of keyboard reached return 0; } ubyte ScanUp() { short i,key,bank; i = 0; // set key index to lowest value key = 0; bank = 0; do { SetMatrix(key,bank); // check ith key if (IsKeyOn) // test if key is depressed and do whatever is to be done { if (i != old_key) { WriteDAC(i); // lock key into DAC if (!legato_flag && gate_flag) // if not in legato mode and an other key was previously on break GATE { GateOff; StatusLEDOff; Delay500us(); } } GateOn; StatusLEDOn; gate_flag = 1; old_key = i; return 1; // leave the function as soon as a key was detected } i++; // otherwise increment key index key++; if (key == 6) { key = 0; bank++; } } while (i < MAXKEYS); // end of keyboard reached return 0; } void main(void) { ubyte report; Init_PIC(); Test(); gate_flag = 0; old_key = 0; // Infinite loop while(1) { // check the vaious switches and update the corresponding flags legato_flag = IsLegatoOn; highest_flag = IsHighestPriorityOn; // a full scan with no key depressed takes 61 * 25us + 100us = 1.6 ms if (highest_flag) report = ScanDown(); else report = ScanUp(); if (report == 0) { // no key depressed therefore set GATE to OFF GateOff; StatusLEDOff; gate_flag = 0; } } }