Skip to content

Commit

Permalink
add vectorscope touch badge hack
Browse files Browse the repository at this point in the history
  • Loading branch information
joeycastillo committed Oct 16, 2024
1 parent d20b175 commit 64a5072
Show file tree
Hide file tree
Showing 34 changed files with 4,297 additions and 0 deletions.
5 changes: 5 additions & 0 deletions boards/vectorscope_touch/board.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CHIP = saml21
LDSCRIPT = saml21j18

DEFINES += \
-D__SAML21G18B__ \
48 changes: 48 additions & 0 deletions boards/vectorscope_touch/pins.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once

#include "hal_gpio.h"
#include "spi.h"
#include "i2c.h"
#include "uart.h"

// Analog pins
HAL_GPIO_PIN(YOUT, A, 2)
HAL_GPIO_PIN(XOUT, A, 5)

// Buttons
HAL_GPIO_PIN(STOP_LIVE, A, 1)
HAL_GPIO_PIN(PLAY_PAUSE, B, 2)
HAL_GPIO_PIN(RECORD, A, 27)
HAL_GPIO_PIN(SLOWER, A, 0)
HAL_GPIO_PIN(FASTER, B, 3)

// LEDs
HAL_GPIO_PIN(LED_BLUE, A, 12)
HAL_GPIO_PIN(LED_YELLOW, A, 13)
HAL_GPIO_PIN(LED_GREEN, A, 14)
HAL_GPIO_PIN(LED_RED, A, 15)

// Touch matrix
HAL_GPIO_PIN(X0, A, 16)
HAL_GPIO_PIN(X1, A, 17)
HAL_GPIO_PIN(X2, A, 18)
HAL_GPIO_PIN(X3, A, 19)
HAL_GPIO_PIN(X4, A, 20)
HAL_GPIO_PIN(X5, A, 21)
HAL_GPIO_PIN(X6, A, 22)
HAL_GPIO_PIN(X7, A, 23)
HAL_GPIO_PIN(Y0, A, 3)
HAL_GPIO_PIN(Y1, A, 6)
HAL_GPIO_PIN(Y2, A, 8)
HAL_GPIO_PIN(Y3, A, 9)
HAL_GPIO_PIN(Y4, A, 10)
HAL_GPIO_PIN(Y5, A, 11)
HAL_GPIO_PIN(Y6, B, 10)
HAL_GPIO_PIN(Y7, B, 11)

// UART
HAL_GPIO_PIN(TX, B, 22)
HAL_GPIO_PIN(RX, A, 23)
#define UART_SERCOM 5
#define UART_SERCOM_TXPO UART_TXPO_2
#define UART_SERCOM_RXPO UART_RXPO_3
22 changes: 22 additions & 0 deletions examples/vectorscope_tapedeck/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Keep this first line.
GOSSAMER_PATH = ../..

# If your firmware targets a specific board, specify it here,
# or omit it and provide it on the command line (make BOARD=foo).
BOARD=vectorscope_touch

# Leave this line here.
include $(GOSSAMER_PATH)/make.mk

SRCS += \
./app.c \
./qtouch/touch.c \
./qtouch/hal_atomic.c \
./qtouch/utils_list.c \

LIBS += ./qtouch/lib/gcc/libqtm_acq_saml21_0x0026.a \
./qtouch/lib/gcc/libqtm_surface_cs_cm0p_0x0021.a \
./qtouch/lib/gcc/libqtm_touch_key_cm0p_0x0002.a

# Finally, leave this line at the bottom of the file.
include $(GOSSAMER_PATH)/rules.mk
208 changes: 208 additions & 0 deletions examples/vectorscope_tapedeck/app.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#include "app.h"
#include "tc.h"
#include "dac.h"
#include "dma.h"
#include "eic.h"
#include "delay.h"
#include "qtouch/touch.h"
#include <stdio.h>
#include <math.h>

void eic_callback(uint8_t channel);
void reset_to_bootloader(void);

extern volatile uint8_t measurement_done_touch;

// needed for arc4random to work
int getentropy(void *buffer, size_t length);
int getentropy(void *buffer, size_t length) {
(void)buffer;
(void)length;
return 0;
}

// x and y values are a union of two 16-bit values
typedef union {
struct {
uint16_t x;
uint16_t y;
} position;
uint32_t data;
} touch_val_t;

touch_val_t live_touch_value;

void app_init(void) {
// set up 4 MHz clock for touch controller
GCLK->GENCTRL[1].reg = GCLK_GENCTRL_DIV(2) |
GCLK_GENCTRL_SRC_OSC16M |
GCLK_GENCTRL_RUNSTDBY |
GCLK_GENCTRL_GENEN;
}

void app_setup(void) {
// configure EIC
eic_init();
eic_enable();

// Configure buttons as EIC inputs with pullups
HAL_GPIO_STOP_LIVE_in();
HAL_GPIO_STOP_LIVE_pullup();
HAL_GPIO_STOP_LIVE_pmuxen(HAL_GPIO_PMUX_EIC);
eic_configure_pin(HAL_GPIO_STOP_LIVE_pin(), INTERRUPT_TRIGGER_FALLING);
eic_enable_interrupt(HAL_GPIO_STOP_LIVE_pin());

HAL_GPIO_PLAY_PAUSE_in();
HAL_GPIO_PLAY_PAUSE_pullup();
HAL_GPIO_PLAY_PAUSE_pmuxen(HAL_GPIO_PMUX_EIC);
eic_configure_pin(HAL_GPIO_PLAY_PAUSE_pin(), INTERRUPT_TRIGGER_FALLING);
eic_enable_interrupt(HAL_GPIO_PLAY_PAUSE_pin());

HAL_GPIO_RECORD_in();
HAL_GPIO_RECORD_pullup();
HAL_GPIO_RECORD_pmuxen(HAL_GPIO_PMUX_EIC);
eic_configure_pin(HAL_GPIO_RECORD_pin(), INTERRUPT_TRIGGER_FALLING);
eic_enable_interrupt(HAL_GPIO_RECORD_pin());

HAL_GPIO_FASTER_in();
HAL_GPIO_FASTER_pullup();
HAL_GPIO_FASTER_pmuxen(HAL_GPIO_PMUX_EIC);
eic_configure_pin(HAL_GPIO_FASTER_pin(), INTERRUPT_TRIGGER_FALLING);
eic_enable_interrupt(HAL_GPIO_FASTER_pin());

HAL_GPIO_SLOWER_in();
HAL_GPIO_SLOWER_pullup();
HAL_GPIO_SLOWER_pmuxen(HAL_GPIO_PMUX_EIC);
eic_configure_pin(HAL_GPIO_SLOWER_pin(), INTERRUPT_TRIGGER_FALLING);
eic_enable_interrupt(HAL_GPIO_SLOWER_pin());

eic_configure_callback(eic_callback);

// configure DACs
HAL_GPIO_XOUT_pmuxen(HAL_GPIO_PMUX_DAC);
HAL_GPIO_YOUT_pmuxen(HAL_GPIO_PMUX_DAC);
dac_init();
dac_enable(DAC_CHANNEL_BOTH);
live_touch_value.position.x = 2048;
live_touch_value.position.y = 2048;

// Configure LEDs
HAL_GPIO_LED_BLUE_out();
HAL_GPIO_LED_GREEN_out();
HAL_GPIO_LED_YELLOW_out();
HAL_GPIO_LED_RED_out();

// Configure touch pads
HAL_GPIO_X0_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X0_out();
HAL_GPIO_X1_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X1_out();
HAL_GPIO_X2_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X2_out();
HAL_GPIO_X3_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X3_out();
HAL_GPIO_X4_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X4_out();
HAL_GPIO_X5_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X5_out();
HAL_GPIO_X6_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X6_out();
HAL_GPIO_X7_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_X7_out();
HAL_GPIO_Y0_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y0_in();
HAL_GPIO_Y1_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y1_in();
HAL_GPIO_Y2_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y2_in();
HAL_GPIO_Y3_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y3_in();
HAL_GPIO_Y4_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y4_in();
HAL_GPIO_Y5_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y5_in();
HAL_GPIO_Y6_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y6_in();
HAL_GPIO_Y7_pmuxen(HAL_GPIO_PMUX_PTC);
HAL_GPIO_Y7_in();

// enable PTC clock
GCLK->PCHCTRL[PTC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
MCLK->APBDMASK.bit.PTC_ = 1;

// set up the TC4 interrupt handler to call touch_timer_handler
tc_init(4, GENERIC_CLOCK_0, TC_PRESCALER_DIV1024); // 8 MHz / 1024 = 7182
tc_set_wavegen(4, TC_WAVE_WAVEGEN_MFRQ); // Match frequency mode, overflow at CC0
tc_count16_set_cc(4, 0, 156); // 7182 / 156 roughly equals 50 Hz or once every 20 ms
TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // enable overflow interrupt
NVIC_EnableIRQ(TC4_IRQn);
tc_enable(4);

// Configure qtouch library
touch_init();
}

double i = 0;

bool app_loop(void) {
touch_process();
if (measurement_done_touch == 1) {
measurement_done_touch = 0;
}

uint8_t status = get_surface_status();
if (status & 1) {
// if there is a touch, the DAC outputs a voltage proportional to the touch position
live_touch_value.position.x = (255 - get_surface_position(VER_POS)) << 4;
live_touch_value.position.y = (get_surface_position(HOR_POS)) << 4;
} else {
// otherwise, the DAC outputs a random voltage on both channels
live_touch_value.position.x = arc4random() % 4096;
live_touch_value.position.y = arc4random() % 4096;
}

// plot the live position on each loop, UNLESS the play/pause button is being held down.
// this will freeze the vectorscope's dot at the current position.
if (HAL_GPIO_PLAY_PAUSE_read()) {
dac_set_analog_value(0, live_touch_value.position.x);
dac_set_analog_value(1, live_touch_value.position.y);
}

return false;
}

void irq_handler_tc4(void);
void irq_handler_tc4(void) {
touch_timer_handler();
HAL_GPIO_LED_BLUE_toggle();
TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF;
}

void eic_callback(uint8_t channel) {
switch (channel) {
case 1: // stop/live
break;
case 2: // play/pause
break;
case 15: // record
// if both STOP and PLAY are also held down, reset to bootloader
if (!HAL_GPIO_STOP_LIVE_read() && !HAL_GPIO_PLAY_PAUSE_read()) {
reset_to_bootloader();
}
break;
case 3: // faster
// if both STOP and PLAY are also held down, just reset
if (!HAL_GPIO_STOP_LIVE_read() && !HAL_GPIO_PLAY_PAUSE_read()) {
NVIC_SystemReset();
}
break;
case 0: // slower
break;
}
}

void reset_to_bootloader(void) {
volatile uint32_t *dbl_tap_ptr = ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4));
*dbl_tap_ptr = 0xf01669ef; // from the UF2 bootloaer: uf2.h line 255
NVIC_SystemReset();
}
35 changes: 35 additions & 0 deletions examples/vectorscope_tapedeck/qtouch/atmel_start_pins.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Code generated from Atmel Start.
*
* This file will be overwritten when reconfiguring your Atmel Start project.
* Please copy examples or other code you want to keep to a separate file
* to avoid losing it when reconfiguring.
*/
#ifndef ATMEL_START_PINS_H_INCLUDED
#define ATMEL_START_PINS_H_INCLUDED

#include <hal_gpio.h>

// SAML22 has 9 pin functions

#define GPIO_PIN_FUNCTION_A 0
#define GPIO_PIN_FUNCTION_B 1
#define GPIO_PIN_FUNCTION_C 2
#define GPIO_PIN_FUNCTION_D 3
#define GPIO_PIN_FUNCTION_E 4
#define GPIO_PIN_FUNCTION_F 5
#define GPIO_PIN_FUNCTION_G 6
#define GPIO_PIN_FUNCTION_H 7
#define GPIO_PIN_FUNCTION_I 8

#define PA02 GPIO(GPIO_PORTA, 2)
#define PA03 GPIO(GPIO_PORTA, 3)
#define PA10 GPIO(GPIO_PORTA, 10)
#define PA11 GPIO(GPIO_PORTA, 11)
#define PA27 GPIO(GPIO_PORTA, 27)
#define PA30 GPIO(GPIO_PORTA, 30)
#define PB08 GPIO(GPIO_PORTB, 8)
#define PB22 GPIO(GPIO_PORTB, 22)
#define PB23 GPIO(GPIO_PORTB, 23)

#endif // ATMEL_START_PINS_H_INCLUDED
66 changes: 66 additions & 0 deletions examples/vectorscope_tapedeck/qtouch/hal_atomic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* \file
*
* \brief Critical sections related functionality implementation.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/

#include "hal_atomic.h"

/**
* \brief Driver version
*/
#define DRIVER_VERSION 0x00000001u

/**
* \brief Disable interrupts, enter critical section
*/
void atomic_enter_critical(hal_atomic_t volatile *atomic)
{
*atomic = __get_PRIMASK();
__disable_irq();
__DMB();
}

/**
* \brief Exit atomic section
*/
void atomic_leave_critical(hal_atomic_t volatile *atomic)
{
__DMB();
__set_PRIMASK(*atomic);
}

/**
* \brief Retrieve the current driver version
*/
uint32_t atomic_get_version(void)
{
return DRIVER_VERSION;
}
Loading

0 comments on commit 64a5072

Please sign in to comment.