Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 4 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
|
Have you ever wanted to play the 1987 classic Never Gonna Give You Up by Rick Astley, but your accordion was out of tune? Never fear, Tune Town is here (or should I say hear).
Rice University's very own Shepherd School of Music, one of the greatest music schools in the United States according to Wikipedia, wanted to hold a Zoom concert to demonstrate their extraordinary skills performing hit songs like Careless Whisper by George Michael, All Star by Smash Mouth, Sandstorm by Darude, Photograph by Nickelback, and the ultimate headbanger Fireflies by Owl City.
However, they ran into a huge problem. Their instruments were all out of tune! Facing this huge catastrophe, Shepherd commissioned Team Z.we11am to build a doohickey to help them tune their instruments.
We came up with Tune Town, a nifty little device that is demonstrated in the video below. It works by changing the frequency of the buzzer according to the rotation of the potentiometer.
Tune Town saved the day! The Shepherd Zoom concert was a smashing success, and Team Z.we11am got a thousand hugs from ten thousand lightning bugs.
With Tune Town, you'll be able to Rick Roll all day long. Because when the years start coming, and they don't stop coming, you'll wish your accordion was in tune.
int main(void) {
unsigned int volatile *pGPIODATA_PortE = (unsigned int *) (0x40024000 + 0x3FC);
int sample_ADC0,i;
float sample_voltage;
float potent_resist;
System_Clock_Init();
// Nice function that sets up the ADC for you :)
ADC0_InitSWTriggerSeq3_PE4();
// Set up the pointers to all of our registers.
unsigned int volatile *pRCGCGPIO = (unsigned int *) (0x400FE000 + 0x608);
unsigned int volatile *pGPIOLOCK_PortF = (unsigned int *)(0x40025000 + 0x520);
unsigned int volatile *pGPIOCR_PortF = (unsigned int *)(0x40025000 + 0x524);
unsigned int volatile *pGPIODIR_PortF = (unsigned int *) (0x40025000 + 0x400);
unsigned int volatile *pGPIOAFSEL_PortF = (unsigned int *) (0x40025000 + 0x420);
unsigned int volatile *pGPIODEN_PortF = (unsigned int *) (0x40025000 + 0x51C);
unsigned int volatile *pGPIODATA_PortF = (unsigned int *) (0x40025000 + 0x3FC);
// Set up Port F
*pRCGCGPIO = *pRCGCGPIO | 0x0020;
while ( (*pRCGCGPIO & 0x0020) == 0 ) ;
*pGPIOLOCK_PortF = 0x4C4F434B;
*pGPIOCR_PortF = *pGPIOCR_PortF | 0x1F;
// SET UP PIN 3 for the speaker.
*pGPIODIR_PortF = *pGPIODIR_PortF | 0x08;
*pGPIOAFSEL_PortF = *pGPIOAFSEL_PortF & ~0x08; // No alternative functions for this pin
*pGPIODEN_PortF = *pGPIODEN_PortF | 0x08; // Digital enable the pin
//Infinite loop that constantly changes the frequency of the buzzer according to the potentiometer
while(1)
{
sample_ADC0 = ADC0_Sample_Seq3();
sample_voltage = (3.3/4095.0) * (float) sample_ADC0;
potent_resist = (10000 * sample_voltage) / (3.3 - sample_voltage);
//The loop that checks the resistance of the potentiometer, and decides whether or not to change the frequency of the buzzer.
if (potent_resist <= 8000){
*pGPIODATA_PortF |= 0x08;
for (i = 0; i < 0.005 * potent_resist; i++){}
*pGPIODATA_PortF &= ~0x08;
for (i = 0; i < 0.005 * potent_resist; i++){}
}
}
return 0;
}
/*
* ADC0_registers.c
*
* Created on: Mar 28, 2016
* Author: Ray
*/
#include "ADC0_registers.h"
/*
* First define the pointers to the key registers needed for configuring the PLL
*/
// pRCC2 is a pointer to the Run-Mode Clock Configuration 2 Register (DS p 260)
unsigned int volatile *pRCC2 = (unsigned int *) (0x400FE000 + 0x070);
// pRIS is a pointer to the Raw Interrupt Status Register (DS p244)
unsigned int volatile *pRIS = (unsigned int *) (0x400FE000 + 0x050);
/*
* Next, define the pointers to the key registers needed for configuring
* PE4 as an analog input. Note that the use of volatile ensures that
* the compiler always carries out the memory accesses, rather than optimizing
* them out (for example, if the access is in a loop).
*/
// pRCGCGPIO is a pointer to the General-Purpose Input/Output Run Mode Clock Gating Control Register (DS p 340)
unsigned int volatile *pRCGCGPIO = (unsigned int *) (0x400FE000 + 0x608);
// pPRGPIO is a pointer to the General-Purpose Input/Output Peripheral Ready Register (DS p 406)
unsigned int volatile *pPRGPIO = (unsigned int *) (0x400FE000 + 0xA08);
// pGPIODIR_PortE is a pointer to the GPIO Direction register for port E on the APB bus (DS p 663)
unsigned int volatile *pGPIODIR_PortE = (unsigned int *) (0x40024000 + 0x400);
// pGPIOAFSEL_PortE is a pointer to the GPIO Alternate Function Select register for port E on the APB bus (DS p 672)
unsigned int volatile *pGPIOAFSEL_PortE = (unsigned int *) (0x40024000 + 0x420);
// pGPIODEN_PortE is a pointer to the GPIO Digital Enable register for port E on the APB bus (DS p 682)
unsigned int volatile *pGPIODEN_PortE = (unsigned int *) (0x40024000 + 0x51C);
// pGPIOAMSEL_PortE is a pointer to the GPIO Analog Mode Select register for port E on the APB bus (DS p 687)
unsigned int volatile *pGPIOAMSEL_PortE = (unsigned int *) (0x40024000 + 0x528);
/*
* Now define the memory mapped register addresses needed to configure A to D converter ADC0
*/
// pRCGCADC is a pointer to the Analog-to-Digital Converter Run Mode Clock Gating Control Register (DS p 352)
unsigned int volatile *pRCGCADC = (unsigned int *) (0x400FE000 + 0x638);
// pADCPC_ADC0 is a pointer to the ADC Peripheral Configuration Register for ADC0 (DS p 892)
unsigned int volatile *pADCPC_ADC0 = (unsigned int *) (0x40038000 + 0xFC4);
// pADCPCSSPRI_ADC0 is a pointer to the Sample Sequencer Priority Register for ADC0 (DS p 842)
unsigned int volatile *pADCSSPRI_ADC0 = (unsigned int *) (0x40038000 + 0x020);
// pADCACTSS_ADC0 is a pointer to the ADC Active Sample Sequencer Register for ADC0 (DS p 822)
unsigned int volatile *pADCACTSS_ADC0 = (unsigned int *) (0x40038000 + 0x0);
// pADCEMUX_ADC0 is a pointer to the ADC Event Multiplexer Select Register for ADC0 (DS p 834)
unsigned int volatile *pADCEMUX_ADC0 = (unsigned int *) (0x40038000 + 0x014);
// pADCSSMUX3_ADC0 is a pointer to the ADC Sample Sequence Input Multiplexer Select 3 Register for ADC0 (DS p 876)
unsigned int volatile *pADCSSMUX3_ADC0 = (unsigned int *) (0x40038000 + 0x0A0);
// pADCSSCTL3_ADC0 is a pointer to the ADC Sample Sequence Control 3 Register for ADC0 (DS p 877)
unsigned int volatile *pADCSSCTL3_ADC0 = (unsigned int *) (0x40038000 + 0x0A4);
// pADCIM_ADC0 is a pointer to the ADC Interrupt Mask3 Register for ADC0 (DS p 826)
unsigned int volatile *pADCIM_ADC0 = (unsigned int *) (0x40038000 + 0x08);
// pADCPSSI_ADC0 is a pointer to the ADC Processor Sample Sequence Initiate Register for ADC0 (DS p 846)
unsigned int volatile *pADCPSSI_ADC0 = (unsigned int *) (0x40038000 + 0x028);
// pADCRIS_ADC0 is a pointer to the ADC Raw Interrupt Status Register for ADC0 (DS p 824)
unsigned int volatile *pADCRIS_ADC0 = (unsigned int *) (0x40038000 + 0x04);
// pADCSSFIFO3_ADC0 is a pointer to the ADC Sample Sequence Result FIFO 3 Register for ADC0 (DS p 861)
unsigned int volatile *pADCSSFIFO3_ADC0 = (unsigned int *) (0x40038000 + 0x0A8);
// pADCISC_ADC0 is a pointer to the ADC Interrupt Status and Clear Register for ADC0 (DS p 829)
unsigned int volatile *pADCISC_ADC0 = (unsigned int *) (0x40038000 + 0x00C);
// pPRADC is a pointer to the Analog-to-Digital Converter Peripheral Ready Register (DS p 418)
unsigned int volatile *pPRADC = (unsigned int *) (0x400FE000 + 0xA38);
/*
* ADC0_registers.h
*
* Created on: Mar 28, 2016
* Author: Ray
*/
#ifndef ADC0_REGISTERS_H_
#define ADC0_REGISTERS_H_
/*
* First define the pointers to the key registers needed for configuring the PLL
*/
// pRCC2 is a pointer to the Run-Mode Clock Configuration 2 Register (DS p 260)
extern unsigned int volatile *pRCC2;
// pRIS is a pointer to the Raw Interrupt Status Register (DS p244)
extern unsigned int volatile *pRIS;
/*
* Next, define the pointers to the key registers needed for configuring
* PE4 as an analog input. Note that the use of volatile ensures that
* the compiler always carries out the memory accesses, rather than optimizing
* them out (for example, if the access is in a loop).
*/
// pRCGCGPIO is a pointer to the General-Purpose Input/Output Run Mode Clock Gating Control Register (DS p 340)
extern unsigned int volatile *pRCGCGPIO;
// pPRGPIO is a pointer to the General-Purpose Input/Output Peripheral Ready Register (DS p 406)
extern unsigned int volatile *pPRGPIO;
// pGPIODIR_PortE is a pointer to the GPIO Direction register for port E on the APB bus (DS p 663)
extern unsigned int volatile *pGPIODIR_PortE;
// pGPIOAFSEL_PortE is a pointer to the GPIO Alternate Function Select register for port E on the APB bus (DS p 672)
extern unsigned int volatile *pGPIOAFSEL_PortE;
// pGPIODEN_PortE is a pointer to the GPIO Digital Enable register for port E on the APB bus (DS p 682)
extern unsigned int volatile *pGPIODEN_PortE;
// pGPIOAMSEL_PortE is a pointer to the GPIO Analog Mode Select register for port E on the APB bus (DS p 687)
extern unsigned int volatile *pGPIOAMSEL_PortE;
/*
* Now define the memory mapped register addresses needed to configure A to D converter ADC0
*/
// pRCGCADC is a pointer to the Analog-to-Digital Converter Run Mode Clock Gating Control Register (DS p 352)
extern unsigned int volatile *pRCGCADC;
// pADCPC_ADC0 is a pointer to the ADC Peripheral Configuration Register for ADC0 (DS p 892)
extern unsigned int volatile *pADCPC_ADC0;
// pADCPCSSPRI_ADC0 is a pointer to the Sample Sequencer Priority Register for ADC0 (DS p 842)
extern unsigned int volatile *pADCSSPRI_ADC0;
// pADCACTSS_ADC0 is a pointer to the ADC Active Sample Sequencer Register for ADC0 (DS p 822)
extern unsigned int volatile *pADCACTSS_ADC0;
// pADCEMUX_ADC0 is a pointer to the ADC Event Multiplexer Select Register for ADC0 (DS p 834)
extern unsigned int volatile *pADCEMUX_ADC0;
// pADCSSMUX3_ADC0 is a pointer to the ADC Sample Sequence Input Multiplexer Select 3 Register for ADC0 (DS p 876)
extern unsigned int volatile *pADCSSMUX3_ADC0;
// pADCSSCTL3_ADC0 is a pointer to the ADC Sample Sequence Control 3 Register for ADC0 (DS p 877)
extern unsigned int volatile *pADCSSCTL3_ADC0;
// pADCIM_ADC0 is a pointer to the ADC Interrupt Mask3 Register for ADC0 (DS p 826)
extern unsigned int volatile *pADCIM_ADC0;
// pADCPSSI_ADC0 is a pointer to the ADC Processor Sample Sequence Initiate Register for ADC0 (DS p 846)
extern unsigned int volatile *pADCPSSI_ADC0;
// pADCRIS_ADC0 is a pointer to the ADC Raw Interrupt Status Register for ADC0 (DS p 824)
extern unsigned int volatile *pADCRIS_ADC0;
// pADCSSFIFO3_ADC0 is a pointer to the ADC Sample Sequence Result FIFO 3 Register for ADC0 (DS p 861)
extern unsigned int volatile *pADCSSFIFO3_ADC0;
// pADCISC_ADC0 is a pointer to the ADC Interrupt Status and Clear Register for ADC0 (DS p 829)
extern unsigned int volatile *pADCISC_ADC0;
// pPRADC is a pointer to the Analog-to-Digital Converter Peripheral Ready Register (DS p 418)
extern unsigned int volatile *pPRADC;
#endif /* ADC0_REGISTERS_H_ */
/*
* ADC0_Sample_Seq3.c
*
* Created on: Mar 28, 2016
* Author: Ray
*/
#include "ADC0_registers.h"
unsigned int
ADC0_Sample_Seq3(void)
{
unsigned int sample_ADC0;
// Step 1: Start collecting a single sample by writing a 1 to bit 3 of the ADCPSSI register.
*pADCPSSI_ADC0 = 0x08; // DS p 846
// Step 2: Wait for the conversion of the single sample we have requested. Bit 3 will be set when
// a sample has completed conversion. DS p 824
while ((*pADCRIS_ADC0 & 0x08) == 0){};
// Step 3: Now that conversion is complete, read the 12-bit digital sample from the FIFO for
// Sample Sequencer 3, the ADCSSFIFO3 register!!!
sample_ADC0 = *pADCSSFIFO3_ADC0 & 0x0FFF; // DS p 861
// Step 4: Acknowledge the we have complete the read. This will allow for the system to
// return to the state where it can process another sample, when requested. (DS p 829)
*pADCISC_ADC0 = 0x08;
return sample_ADC0;
}
Comments