mk450: x and y axis basic implementation
authorRobin Krens <robin@robinkrens.nl>
Fri, 13 Sep 2019 10:28:21 +0000 (17:28 +0700)
committerRobin Krens <robin@robinkrens.nl>
Fri, 13 Sep 2019 10:28:21 +0000 (17:28 +0700)
Makefile
README.md
drivers/mk450_joystick.c [new file with mode: 0644]
include/drivers/mk450_joystick.h [new file with mode: 0644]
include/sys/mmap.h
ivt.c
main.c
rtc.c

index 949e287..3eb5eed 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ _OBJ = ivt.o systick.o sysinfo.o term.o main.o clock.o rtc.o
 OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))
 
 DDIR = obj/drivers
-_DRIVERS = uart.o tm1637.o led.o tsensor.o at24c.o
+_DRIVERS = uart.o tm1637.o led.o tsensor.o at24c.o mk450_joystick.o
 DRIVERS = $(patsubst %, $(DDIR)/%,$(_DRIVERS))
 
 LDIR = obj/lib
index 8e7ec46..42da980 100644 (file)
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ port this code to any Cortex M0/M3/M4/M7 board.
        * LED segment display: drivers/tm1637.c [COMPLETED]
        * Temperature sensor: drivers/tsensor.c [COMPLETED]
        * OLED display [PLANNED]
-       * Joystick [PLANNED]
+       * Joystick: drivers/mk450_joystick.c [IN PROGRESS] 
 * Memory Management [IN PROGRESS] -- FILE: lib/pool.c
 * User Mode [PLANNED]
 * System Call PendV implementation [PLANNED]
diff --git a/drivers/mk450_joystick.c b/drivers/mk450_joystick.c
new file mode 100644 (file)
index 0000000..a4c01d3
--- /dev/null
@@ -0,0 +1,115 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/9/11 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Dual Axis XY Joystick controller
+ * 
+ * $USAGE$
+ *
+ * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/mmap.h>
+#include <sys/robsys.h>
+
+#include <lib/regfunc.h>
+#include <lib/string.h>
+#include <lib/tinyprintf.h>
+
+#include <drivers/mk450_joystick.h>
+
+/* X and Y values of the joystick 
+ * Updated continiously */
+uint16_t xyvalues[2] = {0,0};
+
+
+/* Y return values is mV
+ * ~2500 mv means y is idle state 
+ * ~0 far left
+ * ~5000 far right */
+uint16_t mk450_gety() {
+
+       int y = xyvalues[1];
+       return y;
+}
+
+/* X return values (see y) */
+uint16_t mk450_getx() {
+
+       int x = xyvalues[0];
+       return x;
+}
+
+void mk450_init() {
+
+       // clock prescaler
+       rsetbitsfrom(RCC_CFGR, 14, 0x3);
+
+       rsetbit(RCC_APB2ENR, 2); // enable GPIOA
+       rwrite(GPIOA_CRL, 0x44444400); // analog input on GPIOA0
+       rsetbit(RCC_APB2ENR, 9); // enable ADC1
+
+       /* DMA init */
+       rsetbit(RCC_AHBENR, 0); // enable clock on DMA1
+       rwrite(DMA_CPAR1, (uint32_t) ADC1_DR);
+       rwrite(DMA_CMAR1, xyvalues);
+       rwrite(DMA_CNDTR1, 2); // two values X and Y values
+       rsetbitsfrom(DMA_CCR1, 8, 0x1); // 16-bit
+       rsetbitsfrom(DMA_CCR1, 10, 0x1); // 16-bit
+       rsetbit(DMA_CCR1, 7); // memory increment mode
+       rsetbit(DMA_CCR1, 5); // circular mode
+
+       /* DMA Interrupt */
+       //ivt_set_gate(27, dma_interrupt, 0);
+       //rsetbit(NVIC_ISER0, 11);
+       //rsetbit(DMA_CCR1, 1);
+
+       rsetbit(DMA_CCR1, 0); // channel enable
+       
+       /* Scan mode for two input channels*/
+       rsetbitsfrom(ADC1_SQR1, 20, 0x1); // 2 channels
+       rsetbitsfrom(ADC1_SQR3, 0, 0x0); // ADC1_IN0
+       rsetbitsfrom(ADC1_SQR3, 5, 0x1); // ADC1_IN1
+       rsetbit(ADC1_CR1, 8); // scan mode
+       
+       rsetbitsfrom(ADC1_CR2, 17, 0x7); // swstart config
+       rsetbit(ADC1_CR2, 20); // trigger enable
+       rsetbitsfrom(ADC1_SMPR2, 0, 0x7); // 237 cycles
+       rsetbitsfrom(ADC1_SMPR2, 3, 0x7); // 237 cycles
+       rsetbit(ADC1_CR2, 1); // continious mode
+
+       /* Calibrate */
+       rsetbit(ADC1_CR2, 2); // calibrate
+       _block(500);
+
+       /* Interrupt End of conversion (group!) */
+       //ivt_set_gate(34, eoc_interrupt, 0);
+       //rsetbit(NVIC_ISER0, 18);
+       //rsetbit(ADC1_CR1, 5);
+
+       rsetbit(ADC1_CR2, 8); // enable DMA     
+       rsetbit(ADC1_CR2, 0); // enable ADC
+       rsetbit(ADC1_CR2, 22); // swstart go!
+
+}
+
+/* End of conversion interrupt */
+void * eoc_interrupt() {
+       printf("SR1: %p\n", *ADC1_SR1);
+       printf("CR1: %p\n", *ADC1_CR1);
+       printf("CR2: %p\n", *ADC1_CR2);
+       printf("DR: %p\n", *ADC1_DR); // reading data registers clear interrupt flag
+}
+
+/* DMA interrupt */
+void * dma_interrupt() {
+       printf("DMA Interrupt!\n");
+       printf("Values: %x:%x\n", xyvalues[0], xyvalues[1] );
+       rsetbit(DMA_IFCR, 1);
+}
diff --git a/include/drivers/mk450_joystick.h b/include/drivers/mk450_joystick.h
new file mode 100644 (file)
index 0000000..5604626
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __MK450_JOYSTICK_H
+#define __MK450_JOYSTICK_H
+
+extern void mk450_init();
+extern uint16_t mk450_getx();
+extern uint16_t mk450_gety();
+
+#endif
+
index d33b17e..4275bc7 100644 (file)
@@ -5,7 +5,7 @@
  * Initial version 
  * 
  * $DESCRIPTION$
- * Memory map for the Cortex-A3
+ * Memory map for the Cortex-M3
  * Implementations vary among manufacturers. This one is
  * a STM32F013RC6. Addresses of peripherals vary amongst 
  * manufacturers of boards with similar chips
@@ -45,6 +45,7 @@
 /* NESTED VECTOR INTERRUPT CONTROL REGISTER */
 #define NVIC_ISER0 MEM_ADDR(0xE000E100) // interrupt set enable register
 #define NVIC_ISER1 MEM_ADDR(0xE000E104) // interrupt set enable register
+#define NVIC_ISER2 MEM_ADDR(0xE000E108) // interrupt set enable register
 
 /* SYSTICK REGISTER */
 #define STK_CTRL MEM_ADDR(0xE000E010)
@@ -58,6 +59,7 @@
 
 /* SYSTEM CONTROL REGISTER */
 #define SYSCTRL_RCC MEM_ADDR(0x40021000)
+#define RCC_AHBENR MEM_ADDR(0x40021014) // enable DMA1
 #define RCC_APB1ENR MEM_ADDR(0x4002101C) // register to enable I2C
 #define RCC_APB1RSTR MEM_ADDR(0x40021010) // register to reset I2C
 #define RCC_APB2ENR MEM_ADDR(0x40021018) // register to enable USART1
@@ -68,6 +70,7 @@
 #define GPIOPA_AFSEL MEM_ADDR(0x40004420)
 
 #define GPIOA_CRH MEM_ADDR(0x40010804) // for USART1
+#define GPIOA_CRL MEM_ADDR(0x40010800) // for ADC1
 #define GPIOA_ODR MEM_ADDR(0x4001080C)
 #define GPIOB_CRL MEM_ADDR(0x40010C00) // low register (!) for I2C1
 #define GPIOB_BSRR MEM_ADDR(0x40010C10)
 /* BACKUP (CALIBR) REGISTERS */
 #define BKP_RTCCR MEM_ADDR(0x40006C2C) // RTC Calibration 
 
+/* TIMERS */
 #define TIM4_CR1 MEM_ADDR(0x40000800)
 #define TIM4_RCR MEM_ADDR(0x40000830)
 #define TIM4_ARR MEM_ADDR(0x4000082C)
 //#define TIM1_BDTR MEM_ADDR(0x40000844)
 #define TIM4_CCMR1 MEM_ADDR(0x40000818)
 #define TIM4_DIER MEM_ADDR(0x4000080C)
+
+/* ANALOG TO DIGITAL CONVERSION 
+ * (ADC1) */
+#define ADC1_SR1 MEM_ADDR(0x40012400)
+#define ADC1_CR1 MEM_ADDR(0x40012404)
+#define ADC1_CR2 MEM_ADDR(0x40012408)
+#define ADC1_SMPR2 MEM_ADDR(0x40012410)
+#define ADC1_HTR MEM_ADDR(0x40012424)
+#define ADC1_LTR MEM_ADDR(0x40012428)
+#define ADC1_SQR1 MEM_ADDR(0x4001242C)
+#define ADC1_SQR3 MEM_ADDR(0x40012434)
+#define ADC1_DR MEM_ADDR(0x4001244C)
+
+/* DMA1 Channel 1 */
+#define DMA_IFCR MEM_ADDR(0x40020004)
+#define DMA_CCR1 MEM_ADDR(0x40020008)
+#define DMA_CPAR1 MEM_ADDR(0x40020010)
+#define DMA_CMAR1 MEM_ADDR(0x40020014)
+#define DMA_CNDTR1 MEM_ADDR(0x4002000C)
+
+
+
diff --git a/ivt.c b/ivt.c
index d62a8dd..a271487 100644 (file)
--- a/ivt.c
+++ b/ivt.c
@@ -124,7 +124,7 @@ void * dummy_isr( struct interrupt_frame * frame ) {
        printf("PC:%p\n",frame->pc);
        printf("PSR:%p\n",frame->psr);
        
-       //for(;;);
+       for(;;);
 }
 
 /* Initialize interrupt vector  */
diff --git a/main.c b/main.c
index d2087d7..2526963 100644 (file)
--- a/main.c
+++ b/main.c
 
 #include <drivers/uart.h>
 #include <drivers/led.h>
-#include <drivers/tm1637.h>
+//#include <drivers/tm1637.h>
 //#include <drivers/at24c.h>
-#include <drivers/tsensor.h>
+//#include <drivers/tsensor.h>
+#include <drivers/mk450_joystick.h>
 
 void main()
 {
@@ -43,6 +44,7 @@ void main()
         * by the more accurate RTC.
        systick_init();
        */
+       
 
        /* Set up a very small libc library */
        init_printf(NULL, putc);
@@ -54,7 +56,7 @@ void main()
        led_init();
 
        /* Real time clock */
-       //rtc_init();
+       rtc_init();
 
        /* Eeprom Driver
        eeprom_at24c_init();
@@ -64,17 +66,21 @@ void main()
        /* LED Segment Driver */
        //tm1637_init();
 
+       /* ASM Blocking routine */
        //for (int i = 0; i < 1000; i++)
        //      _block(10000);
 
-       /* TEMP SENSOR */
+       /* TEMP SENSOR 
        tsensor_printid();
        uint16_t temp = tsensor_get_temp();
-       printf("Current temperature: %d °C\n", temp); 
+       printf("Current temperature: %d °C\n", temp); */
+
+       /* ADC Joystick module */
+       mk450_init();   
 
        /* Start up terminal */
        terminal();
-
+       
        /* Should not be here, endless loop */
        for(;;) {
 
diff --git a/rtc.c b/rtc.c
index 7765046..5490b22 100644 (file)
--- a/rtc.c
+++ b/rtc.c
@@ -27,6 +27,7 @@
 
 #include <drivers/led.h>
 #include <drivers/tm1637.h>
+#include <drivers/mk450_joystick.h>
 
 
 /* This handler is invoked each clock tick. I've included two examples 
@@ -58,9 +59,12 @@ void * rtc_handler() {
        } */
 
        // Simple LED blink 
-       uint32_t curr = *RTC_CNTL;
-       int even = *RTC_CNTL % 2;
-       (!even) ? led_off() : led_on();
+       //uint32_t curr = *RTC_CNTL;
+       //int even = *RTC_CNTL % 2;
+       //(!even) ? led_off() : led_on();
+       
+       printf("X: %x\n", mk450_getx());
+       printf("Y: %x\n", mk450_gety());
 
        rclrbit(RTC_CRL, 0); /* clear interrupt flag */
 }