1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
4 * 2019/9/11 - ROBIN KRENS
8 * Dual Axis XY Joystick controller
9 * Uses DMA to store converted input channels. The Analog to Digital
10 * converter (ADC1) is in scan mode and continuously monitors input
11 * channel 0 and 1. There is only one busy-wait for initial calibration
12 * of the ADC. The reference voltage here is 3300 mV. For 2500 mV (idle
13 * state of the joystick) this rougly translate to a value of 3100
14 * (or 0xC1C) in the 12-bit data register (ADC1_DR).
15 * Active and non-active (or left and right, up or down for the joystick)
16 * are 0x0 and 0xFFF respectively.
19 * Use getx and gety to get the current X and Y values of the joystick.
20 * How to use for games: TODO (description)
29 #include <sys/robsys.h>
31 #include <lib/regfunc.h>
32 #include <lib/string.h>
33 #include <lib/tinyprintf.h>
35 #include <drivers/mk450_joystick.h>
37 /* X and Y values of the joystick
38 * Updated continiously */
39 uint16_t xyvalues[2] = {0,0};
43 * ~0xC1C mv means y is idle state
46 uint16_t mk450_gety() {
52 /* X return values (see y)
55 uint16_t mk450_getx() {
61 /* Initiate joystock module and DMA */
65 rsetbitsfrom(RCC_CFGR, 14, 0x3);
67 /* Peripherial init */
68 rsetbit(RCC_APB2ENR, 2); // enable GPIOA
69 rwrite(GPIOA_CRL, 0x44444400); // analog input on GPIOA0
70 rsetbit(RCC_APB2ENR, 9); // enable ADC1
73 rsetbit(RCC_AHBENR, 0); // enable clock on DMA1
74 rwrite(DMA_CPAR1, (uint32_t) ADC1_DR);
75 rwrite(DMA_CMAR1, (uint32_t) xyvalues);
76 rwrite(DMA_CNDTR1, 2); // two values X and Y values
77 rsetbitsfrom(DMA_CCR1, 8, 0x1); // 16-bit
78 rsetbitsfrom(DMA_CCR1, 10, 0x1); // 16-bit
79 rsetbit(DMA_CCR1, 7); // memory increment mode
80 rsetbit(DMA_CCR1, 5); // circular mode
81 rsetbit(DMA_CCR1, 0); // channel enable
83 /* Scan mode for two input channels */
84 rsetbitsfrom(ADC1_SQR1, 20, 0x1); // 2 channels
85 rsetbitsfrom(ADC1_SQR3, 0, 0x0); // ADC1_IN0
86 rsetbitsfrom(ADC1_SQR3, 5, 0x1); // ADC1_IN1
87 rsetbit(ADC1_CR1, 8); // scan mode
89 /* Software start and channel config */
90 rsetbitsfrom(ADC1_CR2, 17, 0x7); // swstart config
91 rsetbit(ADC1_CR2, 20); // trigger enable
92 rsetbitsfrom(ADC1_SMPR2, 0, 0x7); // 237 cycles
93 rsetbitsfrom(ADC1_SMPR2, 3, 0x7); // 237 cycles
94 rsetbit(ADC1_CR2, 1); // continious mode
97 rsetbit(ADC1_CR2, 2); // calibrate
100 /* Wakeup TODO: check datasheet for double init */
101 rsetbit(ADC1_CR2, 8); // enable DMA
102 rsetbit(ADC1_CR2, 0); // enable ADC
103 rsetbit(ADC1_CR2, 22); // swstart go!