mk450: x and y axis basic implementation
[cortex-from-scratch] / drivers / mk450_joystick.c
1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
2  * 
3  * $LOG$
4  * 2019/9/11 - ROBIN KRENS      
5  * Initial version 
6  * 
7  * $DESCRIPTION$
8  * Dual Axis XY Joystick controller
9  * 
10  * $USAGE$
11  *
12  * */
13
14 #include <stdbool.h>
15 #include <stddef.h>
16 #include <stdint.h>
17
18 #include <sys/mmap.h>
19 #include <sys/robsys.h>
20
21 #include <lib/regfunc.h>
22 #include <lib/string.h>
23 #include <lib/tinyprintf.h>
24
25 #include <drivers/mk450_joystick.h>
26
27 /* X and Y values of the joystick 
28  * Updated continiously */
29 uint16_t xyvalues[2] = {0,0};
30
31
32 /* Y return values is mV
33  * ~2500 mv means y is idle state 
34  * ~0 far left
35  * ~5000 far right */
36 uint16_t mk450_gety() {
37
38         int y = xyvalues[1];
39         return y;
40 }
41
42 /* X return values (see y) */
43 uint16_t mk450_getx() {
44
45         int x = xyvalues[0];
46         return x;
47 }
48
49 void mk450_init() {
50
51         // clock prescaler
52         rsetbitsfrom(RCC_CFGR, 14, 0x3);
53
54         rsetbit(RCC_APB2ENR, 2); // enable GPIOA
55         rwrite(GPIOA_CRL, 0x44444400); // analog input on GPIOA0
56         rsetbit(RCC_APB2ENR, 9); // enable ADC1
57
58         /* DMA init */
59         rsetbit(RCC_AHBENR, 0); // enable clock on DMA1
60         rwrite(DMA_CPAR1, (uint32_t) ADC1_DR);
61         rwrite(DMA_CMAR1, xyvalues);
62         rwrite(DMA_CNDTR1, 2); // two values X and Y values
63         rsetbitsfrom(DMA_CCR1, 8, 0x1); // 16-bit
64         rsetbitsfrom(DMA_CCR1, 10, 0x1); // 16-bit
65         rsetbit(DMA_CCR1, 7); // memory increment mode
66         rsetbit(DMA_CCR1, 5); // circular mode
67
68         /* DMA Interrupt */
69         //ivt_set_gate(27, dma_interrupt, 0);
70         //rsetbit(NVIC_ISER0, 11);
71         //rsetbit(DMA_CCR1, 1);
72
73         rsetbit(DMA_CCR1, 0); // channel enable
74         
75         /* Scan mode for two input channels*/
76         rsetbitsfrom(ADC1_SQR1, 20, 0x1); // 2 channels
77         rsetbitsfrom(ADC1_SQR3, 0, 0x0); // ADC1_IN0
78         rsetbitsfrom(ADC1_SQR3, 5, 0x1); // ADC1_IN1
79         rsetbit(ADC1_CR1, 8); // scan mode
80         
81         rsetbitsfrom(ADC1_CR2, 17, 0x7); // swstart config
82         rsetbit(ADC1_CR2, 20); // trigger enable
83         rsetbitsfrom(ADC1_SMPR2, 0, 0x7); // 237 cycles
84         rsetbitsfrom(ADC1_SMPR2, 3, 0x7); // 237 cycles
85         rsetbit(ADC1_CR2, 1); // continious mode
86
87         /* Calibrate */
88         rsetbit(ADC1_CR2, 2); // calibrate
89         _block(500);
90
91         /* Interrupt End of conversion (group!) */
92         //ivt_set_gate(34, eoc_interrupt, 0);
93         //rsetbit(NVIC_ISER0, 18);
94         //rsetbit(ADC1_CR1, 5);
95
96         rsetbit(ADC1_CR2, 8); // enable DMA     
97         rsetbit(ADC1_CR2, 0); // enable ADC
98         rsetbit(ADC1_CR2, 22); // swstart go!
99
100 }
101
102 /* End of conversion interrupt */
103 void * eoc_interrupt() {
104         printf("SR1: %p\n", *ADC1_SR1);
105         printf("CR1: %p\n", *ADC1_CR1);
106         printf("CR2: %p\n", *ADC1_CR2);
107         printf("DR: %p\n", *ADC1_DR); // reading data registers clear interrupt flag
108 }
109
110 /* DMA interrupt */
111 void * dma_interrupt() {
112         printf("DMA Interrupt!\n");
113         printf("Values: %x:%x\n", xyvalues[0], xyvalues[1] );
114         rsetbit(DMA_IFCR, 1);
115 }