#define __16f88 #include"pic/pic16f88.h" /* Yves Usson - october 2008 Mono keyboard scanner firmware v1.00 for 8x8 matrix (FATAR,BONTEMPI) 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 GATELED OUT GATE LED RA5 MCLR IN RESET RA6 UNUSED1 OUT RA7 UNUSED2 OUT TRISA = 0b00100111 PORTB IN OUT RB0 ADDR0 OUT RB0 TO RB5 ADDRESS TO 4051 AND DAC RB1 ADDR1 OUT RB2 ADDR2 OUT RB3 ADDR3 OUT RB4 ADDR4 OUT RB5 ADDR5 OUT RB6 DAC_CS OUT DAC LATCH CONTROL (LATCHES ON RISE) RB7 GATEOUT OUT GATE OUTPUT 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 0b00111111 #define XIRTAM_KSAM 0b11000000 #define MAXKEYS 61 // Set various port bits #define StatusLEDOn RA3 = 1 #define GateLEDOn RA4 = 1 #define DAC_CS_High RB6 = 1 #define GateOn RB7 = 1 // Unset various port bits #define StatusLEDOff RA3 = 0 #define GateLEDOff RA4 = 0 #define DAC_CS_Low RB6 = 0 #define GateOff 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 v) { ubyte by1 = PORTB & XIRTAM_KSAM; ubyte by2 = (ubyte)(v & MASK_MATRIX); PORTB = (by1 | by2); } void WriteDAC(void) { DAC_CS_Low; // when down latches are transparent //Delay100us(); DAC_CS_High; // when high latches are frozen } void Test() { ubyte i; short j; GateOff; j = 0; for (i = 1; i < 5; i++) { StatusLEDOn; SetMatrix(j); WriteDAC(); Delay100ms(); SetMatrix(j+4); WriteDAC(); Delay100ms(); StatusLEDOff; SetMatrix(j+7); WriteDAC(); Delay100ms(); SetMatrix(j+4); WriteDAC(); Delay100ms(); j += 12; } SetMatrix(0); WriteDAC(); } ubyte ScanDown() { short i; i = MAXKEYS-1; // set key index to highest value do { SetMatrix(i); // check ith key if (IsKeyOn) // test if key is depressed and do whatever is to be done { if (i != old_key) { WriteDAC(); // lock key into DAC if (!legato_flag && gate_flag) // if not in legato mode and another key was previously on break GATE { GateOff; GateLEDOff; Delay500us(); } } GateOn; GateLEDOn; gate_flag = 1; old_key = i; return 1; // leave the function as soon as a key was detected } i--; // otherwise decrement key index } while (i > -1); // end of keyboard reached return 0; } ubyte ScanUp() { short i; i = 0; // set key index to lowest value do { SetMatrix(i); // check ith key if (IsKeyOn) // test if key is depressed and do whatever is to be done { if (i != old_key) { WriteDAC(); // lock key into DAC if (!legato_flag && gate_flag) // if not in legato mode and an other key was previously on break GATE { GateOff; GateLEDOff; Delay500us(); } } GateOn; GateLEDOn; gate_flag = 1; old_key = i; return 1; // leave the function as soon as a key was detected } i++; // otherwise increment key index } 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; GateLEDOff; gate_flag = 0; } } }