diff --git a/Scan/CapSense/matrix_scan.c b/Scan/CapSense/matrix_scan.c index 2808ec1..0bbcac6 100644 --- a/Scan/CapSense/matrix_scan.c +++ b/Scan/CapSense/matrix_scan.c @@ -64,10 +64,125 @@ CLIDict_Def( matrixCLIDict, "Matrix Module Commands" ) = { // ----- Functions ----- +// TODO +// - Support multiple ADCs +// - Channel/Mux setup +void ADC_setup( ADC adc ) +{ + + // Enable ADC clock +#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) + SIM_SCGC6 |= SIM_SCGC6_ADC0; +#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) + SIM_SCGC6 |= SIM_SCGC6_ADC0; + SIM_SCGC3 |= SIM_SCGC3_ADC1; +#endif + + // Lookup base ADC register + volatile unsigned int *ADC_SC1A = (unsigned int*)(&ADC_reg_offset_map[adc]); + + // Calculate Register offsets + volatile unsigned int *ADC_CFG1 = (unsigned int*)(&ADC_SC1A) + 0x08; + volatile unsigned int *ADC_CFG2 = (unsigned int*)(&ADC_SC1A) + 0x0C; + volatile unsigned int *ADC_SC2 = (unsigned int*)(&ADC_SC1A) + 0x20; + volatile unsigned int *ADC_SC3 = (unsigned int*)(&ADC_SC1A) + 0x24; + volatile unsigned int *ADC_PG = (unsigned int*)(&ADC_SC1A) + 0x2C; + volatile unsigned int *ADC_CLPS = (unsigned int*)(&ADC_SC1A) + 0x38; + volatile unsigned int *ADC_CLP4 = (unsigned int*)(&ADC_SC1A) + 0x3C; + volatile unsigned int *ADC_CLP3 = (unsigned int*)(&ADC_SC1A) + 0x40; + volatile unsigned int *ADC_CLP2 = (unsigned int*)(&ADC_SC1A) + 0x44; + volatile unsigned int *ADC_CLP1 = (unsigned int*)(&ADC_SC1A) + 0x48; + volatile unsigned int *ADC_CLP0 = (unsigned int*)(&ADC_SC1A) + 0x4C; + + // Make sure calibration has stopped + *ADC_SC3 = 0; + + // - CFG1 - + // ADIV: (input)/2 divider + // ADICLK: (bus)/2 divider + // MODE: 16-bit + // ADLSMP: Long sample + //ADC_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(3) | ADC_CFG1_ADLSMP; + // ADIV: (input)/8 divider + *ADC_CFG1 = ADC_CFG1_ADIV(3) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(3) | ADC_CFG1_ADLSMP; + + // - CFG2 - + // ADLSTS: 6 extra ADCK cycles; 10 ADCK cycles total sample time + //ADC_CFG2 = ADC_CFG2_ADLSTS(2); + // ADLSTS: 20 extra ADCK cycles; 24 ADCK cycles total sample time + *ADC_CFG2 = ADC_CFG2_ADLSTS(0); + + // - SC2 - + // REFSEL: Use default 3.3V reference + *ADC_SC2 = ADC_SC2_REFSEL(0); + /* + // Setup VREF to 1.2 V + VREF_TRM = 0x60; + VREF_SC = 0xE1; // Enable 1.2 volt ref + // REFSEL: Use 1.2V reference VREF + *ADC_SC2 = ADC_SC2_REFSEL(1); + */ + + // - SC3 - + // CAL: Start calibration + // AVGE: Enable hardware averaging + // AVGS: 32 samples averaged + // 32 sample averaging + *ADC_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(3); + + // Wait for calibration + while ( *ADC_SC3 & ADC_SC3_CAL ); + + // Apply computed calibration offset + // XXX Note, for single-ended, only the plus side offsets have to be applied + // For differential the minus side also has to be set as well + + __disable_irq(); // Disable interrupts while reading/setting offsets + + // Set calibration + // ADC Plus-Side Gain Register + // See Section 31.4.7 in the datasheet (mk20dx256vlh7) for details + uint16_t sum = *ADC_CLPS + *ADC_CLP4 + *ADC_CLP3 + *ADC_CLP2 + *ADC_CLP1 + *ADC_CLP0; + sum = (sum / 2) | 0x8000; + *ADC_PG = sum; + + __enable_irq(); // Re-enable interrupts + + // Start ADC reading loop + // - SC1A - + // ADCH: Channel DAD0 (A10) + // AIEN: Enable interrupt + //*ADC_SC1A = ADC_SC1_AIEN | ADC_SC1_ADCH(0); + + // Enable ADC0 IRQ Vector + //NVIC_ENABLE_IRQ( IRQ_ADC0 ); +} + +// TODO +// - Enable/Disable strobe detection (IBM) +// - Setup strobe matrix +void Strobe_setup() +{ +} + +// TODO +// - Setup ADCs +// - Setup ADC muxes +// - Setup voltage stab +void Sense_setup() +{ +} + void Matrix_setup() { // Register Matrix CLI dictionary CLI_registerDictionary( matrixCLIDict, matrixCLIDictName ); + + // Setup sense + Sense_setup(); + + // Setup strobes + Strobe_setup(); } // Scan the matrix for keypresses diff --git a/Scan/CapSense/matrix_scan.h b/Scan/CapSense/matrix_scan.h index 3c7efb9..a0b9bb5 100644 --- a/Scan/CapSense/matrix_scan.h +++ b/Scan/CapSense/matrix_scan.h @@ -27,8 +27,145 @@ // ----- Enums ----- +// Freescale MK20s have GPIO ports A...E +typedef enum Port { + Port_A = 0, + Port_B = 1, + Port_C = 2, + Port_D = 3, + Port_E = 4, +} Port; + +// Each port has a possible 32 pins +typedef enum Pin { + Pin_0 = 0, + Pin_1 = 1, + Pin_2 = 2, + Pin_3 = 3, + Pin_4 = 4, + Pin_5 = 5, + Pin_6 = 6, + Pin_7 = 7, + Pin_8 = 8, + Pin_9 = 9, + Pin_10 = 10, + Pin_11 = 11, + Pin_12 = 12, + Pin_13 = 13, + Pin_14 = 14, + Pin_15 = 15, + Pin_16 = 16, + Pin_17 = 17, + Pin_18 = 18, + Pin_19 = 19, + Pin_20 = 20, + Pin_21 = 21, + Pin_22 = 22, + Pin_23 = 23, + Pin_24 = 24, + Pin_25 = 25, + Pin_26 = 26, + Pin_27 = 27, + Pin_28 = 28, + Pin_29 = 29, + Pin_30 = 30, + Pin_31 = 31, +} Pin; + +// Depending on the microcontroller, it can have 1 or more ADCs +typedef enum ADC { +#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) + ADC_0 = 0, +#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) + ADC_0 = 0, + ADC_1 = 1, +#endif +} ADC; + +// ADC Register offset map +unsigned int *ADC_reg_offset_map[] = { +#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) + (unsigned int*)(&ADC0_SC1A), +#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) + (unsigned int*)(&ADC0_SC1A), + (unsigned int*)(&ADC1_SC1A), +#endif +}; + +// Each ADC has a possible 32 channels +typedef enum Channel { + Channel_0 = 0, + Channel_1 = 1, + Channel_2 = 2, + Channel_3 = 3, + Channel_4 = 4, + Channel_5 = 5, + Channel_6 = 6, + Channel_7 = 7, + Channel_8 = 8, + Channel_9 = 9, + Channel_10 = 10, + Channel_11 = 11, + Channel_12 = 12, + Channel_13 = 13, + Channel_14 = 14, + Channel_15 = 15, + Channel_16 = 16, + Channel_17 = 17, + Channel_18 = 18, + Channel_19 = 19, + Channel_20 = 20, + Channel_21 = 21, + Channel_22 = 22, + Channel_23 = 23, + Channel_24 = 24, + Channel_25 = 25, + Channel_26 = 26, + Channel_27 = 27, + Channel_28 = 28, + Channel_29 = 29, + Channel_30 = 30, + Channel_31 = 31, +} Channel; + +// Type of pin +typedef enum Type { + Type_StrobeOn, + Type_StrobeOff, + Type_StrobeSetup, + Type_Sense, + Type_SenseSetup, +} Type; + +// Keypress States +typedef enum KeyPosition { + KeyState_Off = 0, + KeyState_Press = 1, + KeyState_Hold = 2, + KeyState_Release = 3, + KeyState_Invalid, +} KeyPosition; + + + // ----- Structs ----- +// Struct container for defining Strobe pins +typedef struct GPIO_Pin { + Port port; + Pin pin; +} GPIO_Pin; + +// Struct container for defining Sense pins +typedef struct ADC_Pin { + Port port; + Pin pin; + ADC adc; + Channel ch; +} ADC_Pin; + + + // ----- Functions ----- void Matrix_setup(); diff --git a/Scan/CapSense/matrix_setup.h b/Scan/CapSense/matrix_setup.h index 20b6068..c52e712 100644 --- a/Scan/CapSense/matrix_setup.h +++ b/Scan/CapSense/matrix_setup.h @@ -16,5 +16,12 @@ #pragma once -// TODO +// ----- Macros ----- + +// Convenience Macros +#define gpio( port, pin ) { Port_##port, Pin_##pin } +#define sense( port, pin, adc, ch ) { Port_##port, Pin_##pin, ADC_##adc, Channel_##ch } +#define Matrix_colsNum sizeof( Matrix_cols ) / sizeof( GPIO_Pin ) +#define Matrix_rowsNum sizeof( Matrix_rows ) / sizeof( GPIO_Pin ) +#define Matrix_maxKeys sizeof( Matrix_scanArray ) / sizeof( KeyState ) diff --git a/Scan/CapTest1/matrix.h b/Scan/CapTest1/matrix.h index eb92a4b..bb30999 100644 --- a/Scan/CapTest1/matrix.h +++ b/Scan/CapTest1/matrix.h @@ -25,8 +25,39 @@ // ----- Matrix Definition ----- +// CapTest +// (TODO) +// +// Strobe +// PTB0..3,16,17 +// PTC4,5 +// PTD0 +// +// Sense +// PTD1..7 + + +// -- Strobes -- +// Format +// gpio( , ) +// Freescale ARM MK20's support GPIO PTA, PTB, PTC, PTD and PTE 0..31 +// Not all chips have access to all of these pins (most don't have 160 pins :P) +// + +GPIO_Pin Matrix_strobe[] = { gpio(B,0), gpio(B,1), gpio(B,2), gpio(B,3), gpio(B,16), gpio(B,17), gpio(C,4), gpio(C,5), gpio(D,0) }; + + +// -- Sense -- +// Format +// sense( , , , ) +// Freescale ARM MK20's support 32 ADC channels +// However, not every channel is useful for reading from an input pin. +// +// NOTE: Be careful that you are not using a strobe and a sense at the same time! +// + +ADC_Pin Matrix_sense[] = { sense(B,4,0,5) }; + // TODO -// Define possible strobes -// Define possible senses // Misc pins required for control