Skip to content

Instantly share code, notes, and snippets.

@shannonpeng
Created June 9, 2019 22:01
Show Gist options
  • Save shannonpeng/1657018d92a1b81b7fcb56381519141a to your computer and use it in GitHub Desktop.
Save shannonpeng/1657018d92a1b81b7fcb56381519141a to your computer and use it in GitHub Desktop.
6.115 Final Project - Grid Sequencer
/* ========================================
*
* Shannon Peng
* 6.115 Final Project -- Grid Sequencer
* Spring 2019
*
* ========================================
*/
#include <device.h>
#include <math.h>
#define NUM_COLS 8
#define NUM_ROWS 4
/* VARIABLES */
// persistent grid state. used to light LEDs and choose sounds to play
uint8 grid[NUM_COLS][NUM_ROWS];
// transient button states. used to detect a keyup event
uint8 button_states[NUM_COLS][NUM_ROWS];
// current highlighted column
uint8 current_col = 0;
// tempo -- number of timer interrupts needed before cycling to the next column
// 16-bit timer period = 2.731ms
uint16 num_interrupts = 140;
uint16 interrupt_count;
uint16 adcResult = 0; // read from potentiometer to set tempo
// toggle notes/drums mode here and in TopDesign.cysch
// 0 -- play notes (CDEF)
// 1 -- play drums (kick, hi hat, snare, clap)
uint8 notes = 0;
/* HELPER FUNCTIONS */
// starts a WaveDAC given an index i [0:3]
void startWaveDAC(uint8 i) {
if (i == 0) {
WaveDAC8_1_Start();
}
else if (i == 1) {
WaveDAC8_2_Start();
}
else if (i == 2) {
WaveDAC8_3_Start();
}
else if (i == 3) {
WaveDAC8_4_Start();
}
}
/* INTERRUPT HANDLERS */
// Timer interrupt
CY_ISR(timerInterrupt)
{
Timer_1_STATUS; // clear TC flag
interrupt_count++; // increment interrupt count
if (interrupt_count > num_interrupts) {
current_col += 1;
current_col = current_col % NUM_COLS; // cycle through columns
interrupt_count = 0;
if (notes) { // if in notes mode, WaveDACs need to be manually stopped
WaveDAC8_1_Stop();
WaveDAC8_2_Stop();
WaveDAC8_3_Stop();
WaveDAC8_4_Stop();
}
int i = 0; // start WaveDACs for selected sounds
for (i = 0; i < NUM_ROWS; i++) {
if (grid[current_col][i] > 0) {
startWaveDAC(i);
}
}
}
}
// Create interrupt handlers for stopping WaveDAC components.
// These are called when a drum sample has finished playing (on w1 rising edge for each component)
CY_ISR(wavInterrupt1)
{
WaveDAC8_1_Stop();
}
CY_ISR(wavInterrupt2)
{
WaveDAC8_2_Stop();
}
CY_ISR(wavInterrupt3)
{
WaveDAC8_3_Stop();
}
CY_ISR(wavInterrupt4)
{
WaveDAC8_4_Stop();
}
// Main loop of program
int main()
{
/* Global interrupt enable */
CyGlobalIntEnable;
/* Assign interrupt handlers to timer and WaveDAC components. */
TimerISR_StartEx(timerInterrupt);
wavisr_1_StartEx(wavInterrupt1);
wavisr_2_StartEx(wavInterrupt2);
wavisr_3_StartEx(wavInterrupt3);
wavisr_4_StartEx(wavInterrupt4);
/* Start the timer */
Timer_1_Start();
/* Start ADC conversion */
ADC_DelSig_1_Start();
ADC_DelSig_1_StartConvert();
while (1)
{
// Read value from potentiometer to set tempo
if( ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_WAIT_FOR_RESULT) ) {
adcResult = ADC_DelSig_1_GetResult16();
if (adcResult & 0x8000) {
adcResult = 0; // ignore negatives
}
else if (adcResult >= 0x0fff) {
adcResult = 0x0fff; // max
}
num_interrupts = 400 - (adcResult * 300 / 0xfff); // range 100 to 400 interrupts (220 to 55 bpm)
if (num_interrupts > 400) {
num_interrupts = 400;
}
else if (num_interrupts < 80) {
num_interrupts = 80;
}
}
// Scan button matrix and update LED matrix concurrently
int i = 0;
int j = 0;
for (i = 0; i < NUM_ROWS; i++) {
uint8 row_vals = 1u << (NUM_ROWS - 1 - i);
BUTTON_ROWS_Write(row_vals); // raise each row individually
uint8 button_col_val = BUTTON_COLS_Read(); // read the values of columns in this row
for (j = 0; j < NUM_COLS; j++) {
int b = (button_col_val >> (NUM_COLS - 1 - j)) & 1; // shift and only keep last bit
if (b == 0 && button_states[j][i] == 1) {
grid[j][i] = (~grid[j][i]) & 1; // toggle grid state at this button
}
button_states[j][i] = b;
uint8 r = grid[j][i] << (NUM_ROWS - 1 - i);
uint8 c = grid[j][i] << (NUM_COLS - 1 - j);
uint8 col_val = 1 << (NUM_COLS - 1 - current_col);
if (current_col == j) { // selected column
LED_ROWS_Write(0);
LED_COLS_Write(c | col_val);
}
else {
LED_ROWS_Write(~r);
LED_COLS_Write(c);
}
}
}
LED_ROWS_Write(0);
LED_COLS_Write(0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment