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
* 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]
--- /dev/null
+/* (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);
+}
--- /dev/null
+#ifndef __MK450_JOYSTICK_H
+#define __MK450_JOYSTICK_H
+
+extern void mk450_init();
+extern uint16_t mk450_getx();
+extern uint16_t mk450_gety();
+
+#endif
+
* 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
/* 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)
/* 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
#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)
+
+
+
printf("PC:%p\n",frame->pc);
printf("PSR:%p\n",frame->psr);
- //for(;;);
+ for(;;);
}
/* Initialize interrupt vector */
#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()
{
* by the more accurate RTC.
systick_init();
*/
+
/* Set up a very small libc library */
init_printf(NULL, putc);
led_init();
/* Real time clock */
- //rtc_init();
+ rtc_init();
/* Eeprom Driver
eeprom_at24c_init();
/* 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(;;) {
#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
} */
// 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 */
}