Mercurial > louis > kiibohd-controller
view Scan/ADCTest/scan_loop.c @ 308:ab4515606277
Fix whitespace
Use a consistent standard - Tabs in front for indenting, spaces after for anything else. This way everything stays nice and lined up while also letting users change there prefered indent level. Most of the new files from Haata where already in this format.
author | Rowan Decker <Smasher816@gmail.com> |
---|---|
date | Sun, 08 Mar 2015 18:40:01 -0700 |
parents | 9afed592bcb5 |
children |
line wrap: on
line source
/* Copyright (C) 2014 by Jacob Alexander * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // ----- Includes ----- // Compiler Includes #include <Lib/ScanLib.h> // Project Includes #include <cli.h> #include <led.h> #include <print.h> // Local Includes #include "scan_loop.h" // ----- Defines ----- // ADC Clock divisor settings (F_BUS == 48000000) #define ADC_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) #define ADC_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) #define ADC_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // ----- Macros ----- // ----- Function Declarations ----- void cliFunc_adc ( char* args ); void cliFunc_adcInit( char* args ); void cliFunc_dac ( char* args ); void cliFunc_dacVref( char* args ); void cliFunc_echo ( char* args ); // ----- Variables ----- // Buffer used to inform the macro processing module which keys have been detected as pressed volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER]; volatile uint8_t KeyIndex_BufferUsed; // Scan Module command dictionary char scanCLIDictName[] = "ADC Test Module Commands"; const CLIDictItem scanCLIDict[] = { #if defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM { "adc", "Read the specified number of values from the ADC at the given pin: <pin> [# of reads]" NL "\t\t See \033[35mLib/pin_map.teensy3\033[0m for ADC0 channel number.", cliFunc_adc }, { "adcInit", "Intialize/calibrate ADC: <ADC Resolution> <Vref> <Hardware averaging samples>" NL "\t\tADC Resolution -> 8, 10, 12, 16 (bit)" NL "\t\t Vref -> 0 (1.2 V), 1 (External)" NL "\t\tHw Avg Samples -> 0 (disabled), 4, 8, 16, 32", cliFunc_adcInit }, #endif #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1 { "dac", "Set DAC output value, from 0 to 4095 (1/4096 Vref to Vref).", cliFunc_dac }, { "dacVref", "Set DAC Vref. 0 is 1.2V. 1 is 3.3V.", cliFunc_dacVref }, #endif { "echo", "Example command, echos the arguments.", cliFunc_echo }, { 0, 0, 0 } // Null entry for dictionary end }; // ----- Functions ----- // Setup inline void Scan_setup() #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR { // Register Scan CLI dictionary CLI_registerDictionary( scanCLIDict, scanCLIDictName ); } #elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM { // Register Scan CLI dictionary CLI_registerDictionary( scanCLIDict, scanCLIDictName ); // ADC Setup VREF_TRM = 0x60; VREF_SC = 0xE1; // Enable 1.2V Vref #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1 // DAC Setup SIM_SCGC2 |= SIM_SCGC2_DAC0; DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 #endif } #endif // Main Detection Loop inline uint8_t Scan_loop() { return 0; } // Signal KeyIndex_Buffer that it has been properly read void Scan_finishedWithBuffer( uint8_t sentKeys ) { } // Signal that the keys have been properly sent over USB void Scan_finishedWithUSBBuffer( uint8_t sentKeys ) { } // Reset Keyboard void Scan_resetKeyboard() { } // ----- CLI Command Functions ----- // XXX Just an example command showing how to parse arguments (more complex than generally needed) void cliFunc_echo( char* args ) { char* curArgs; char* arg1Ptr; char* arg2Ptr = args; // Parse args until a \0 is found while ( 1 ) { print( NL ); // No \r\n by default after the command is entered curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); // Stop processing args if no more are found if ( *arg1Ptr == '\0' ) break; // Print out the arg dPrint( arg1Ptr ); } } void cliFunc_adc( char* args ) #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR { } #elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM { // Parse code from argument // NOTE: Only first argument is used char* arg1Ptr; char* arg2Ptr; CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); // Set the ADC Channel uint8_t channel = numToInt( arg1Ptr ); __disable_irq(); ADC0_SC1A = channel; __enable_irq(); // Number of ADC samples to display CLI_argumentIsolation( arg2Ptr, &arg1Ptr, &arg2Ptr ); int displayedADC = 1; // Default to 1 read if ( arg1Ptr ) // If there is an argument, use that instead { displayedADC = numToInt( arg1Ptr ); } // Poll ADC until it gets a value, making sure to serve interrupts on each attempt while ( displayedADC > 0 ) { __disable_irq(); // ADC Sample is ready if ( (ADC0_SC1A & ADC_SC1_COCO) ) { int result = ADC0_RA; print( NL ); printInt32( result ); displayedADC--; // Prepare for another read if ( displayedADC > 0 ) { ADC0_SC1A = channel; } } __enable_irq(); yield(); // Make sure interrupts actually get serviced } } #endif void cliFunc_adcInit( char* args ) #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR { } #elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM { // Parse code from argument // NOTE: Only first argument is used char* arg1Ptr; char* arg2Ptr; CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); // Make sure calibration has stopped ADC0_SC3 = 0; // Select bit resolution int bitResolution = numToInt( arg1Ptr ); switch ( bitResolution ) { case 8: // 8-bit ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0); ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); break; case 10: // 10-bit ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); break; case 12: // 12-bit ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); break; case 16: // 16-bit ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); break; default: return; // Do nothing, invalid arg } // Select Vref CLI_argumentIsolation( arg2Ptr, &arg1Ptr, &arg2Ptr ); int vRef = numToInt( arg1Ptr ); switch ( vRef ) { case 0: // 1.2V internal Vref ADC0_SC2 = ADC_SC2_REFSEL(1); break; case 1: // Vcc/Ext Vref ADC0_SC2 = ADC_SC2_REFSEL(0); break; default: return; // Do nothing, invalid arg } // Hardware averaging (and start calibration) CLI_argumentIsolation( arg2Ptr, &arg1Ptr, &arg2Ptr ); int hardwareAvg = numToInt( arg1Ptr ); switch ( hardwareAvg ) { case 0: // No hardware averaging ADC0_SC3 = ADC_SC3_CAL; // Just start calibration break; case 4: // 4 sample averaging ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); break; case 8: // 8 sample averaging ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); break; case 16: // 16 sample averaging ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); break; case 32: // 32 sample averaging ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); break; default: return; // Do nothing, invalid arg } // Wait for calibration while ( ADC0_SC3 & ADC_SC3_CAL ); // Set calibration uint16_t sum; // XXX Why is PJRC doing this? Is the self-calibration not good enough? -HaaTa // ADC Plus-Side Gain Register __disable_irq(); // Disable interrupts sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; sum = (sum / 2) | 0x8000; ADC0_PG = sum; print( NL ); info_msg("Calibration ADC0_PG (Plus-Side Gain Register) set to: "); printInt16( sum ); // ADC Minus-Side Gain Register // XXX I don't think this is necessary when doing single-ended (as opposed to differential) -HaaTa // K20P64M72SF1RM.pdf 31.3.10 pg. 666 sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0; sum = (sum / 2) | 0x8000; ADC0_MG = sum; print( NL ); info_msg("Calibration ADC0_MG (Minus-Side Gain Register) set to: "); printInt16( sum ); __enable_irq(); // Re-enable interrupts } #endif void cliFunc_dac( char* args ) { #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1 // Parse code from argument // NOTE: Only first argument is used char* arg1Ptr; char* arg2Ptr; CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); int dacOut = numToInt( arg1Ptr ); // Make sure the value is between 0 and 4096, otherwise ignore if ( dacOut >= 0 && dacOut <= 4095 ) { *(int16_t *) &(DAC0_DAT0L) = dacOut; } #endif } void cliFunc_dacVref( char* args ) { #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1 // Parse code from argument // NOTE: Only first argument is used char* arg1Ptr; char* arg2Ptr; CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); switch ( numToInt( arg1Ptr ) ) { case 0: DAC0_C0 = DAC_C0_DACEN; // 1.2V Vref is DACREF_1 break; case 1: DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 break; } #endif }