summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/adc_task.c343
-rw-r--r--source/adc_task.h19
-rw-r--r--source/com_task.c205
-rw-r--r--source/com_task.h130
-rw-r--r--source/gpio_ext.c141
-rw-r--r--source/gpio_ext.h73
-rw-r--r--source/main.c83
7 files changed, 973 insertions, 21 deletions
diff --git a/source/adc_task.c b/source/adc_task.c
new file mode 100644
index 0000000..67d5bd0
--- /dev/null
+++ b/source/adc_task.c
@@ -0,0 +1,343 @@
+/*
+ * adc_task.c
+ *
+ */
+
+#include "com_task.h"
+#include "adc_task.h"
+#include "fsl_adc16.h"
+#include "fsl_port.h"
+#include "errno.h"
+#include "stdlib.h"
+
+/*
+ * Apalis ADC0 -> PTB0 -> ADC0_SE8
+ * Apalis ADC1 -> PTB1 -> ADC0_SE9
+ * Apalis ADC2 -> PTB2 -> ADC0_SE12
+ * Apalis ADC3 -> PTB3 -> ADC0_SE13
+ *
+ * Touch screen:
+ * Force:
+ * PTE6 X+ hi-off
+ * PTB9 X- lo-off
+ * PTC5 Y+ hi-off
+ * PTC13 Y- lo-off
+ * Sense:
+ * PTB7 -> ADC1_SE13 X-
+ * PTB6 -> ADC1_SE12 X+
+ * PTC9 -> ADC1_SE5b Y-
+ * PTC8 -> ADC1_SE4b Y+
+ */
+const uint8_t adc0_channels[ADC0_CHANNEL_CNT] = {8, 9, 12, 13};
+const uint8_t tsc_channels[TSC0_CHANNEL_CNT] = {13, 12, 5, 4};
+
+static int adc_task_init(void)
+{
+ adc16_config_t adc_config;
+#ifdef BOARD_USES_ADC
+ ADC16_GetDefaultConfig(&adc_config);
+ adc_config.resolution = kADC16_ResolutionSE16Bit;
+ adc_config.longSampleMode = kADC16_LongSampleDisabled;
+ adc_config.clockDivider = kADC16_ClockDivider8;
+ ADC16_Init(ADC0, &adc_config);
+ ADC16_SetHardwareAverage(ADC0, kADC16_HardwareAverageDisabled);
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
+
+static int tsc_task_init(void)
+{
+ adc16_config_t adc_config;
+#ifdef BOARD_USES_ADC
+ ADC16_GetDefaultConfig(&adc_config);
+ adc_config.resolution = kADC16_ResolutionSE12Bit;
+ adc_config.longSampleMode = kADC16_LongSampleDisabled;
+ adc_config.clockDivider = kADC16_ClockDivider8;
+ ADC16_Init(ADC1, &adc_config);
+ ADC16_SetChannelMuxMode(ADC1, kADC16_ChannelMuxB);
+ ADC16_SetHardwareAverage(ADC1, kADC16_HardwareAverageCount32);
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
+
+#ifdef BOARD_USES_ADC
+static void ts_force_drive(uint8_t xm, uint8_t xp, uint8_t ym, uint8_t yp)
+{
+ if (xp == 0)
+ GPIO_SetPinsOutput(GPIOE, 1 << 6);
+ else
+ GPIO_ClearPinsOutput(GPIOE, 1 << 6);
+
+ if (xm > 0)
+ GPIO_SetPinsOutput(GPIOB, 1 << 9);
+ else
+ GPIO_ClearPinsOutput(GPIOB, 1 << 9);
+
+ if (yp == 0)
+ GPIO_SetPinsOutput(GPIOC, 1 << 5);
+ else
+ GPIO_ClearPinsOutput(GPIOC, 1 << 5);
+
+ if (ym > 0)
+ GPIO_SetPinsOutput(GPIOC, 1 << 13);
+ else
+ GPIO_ClearPinsOutput(GPIOC, 1 << 13);
+}
+
+static inline uint16_t do_adc_conversion(ADC_Type *base, adc16_channel_config_t *channel)
+{
+ ADC16_SetChannelConfig(base, 0, channel);
+ while(ADC16_GetChannelStatusFlags(base, 0) == 0){vTaskDelay(0);}
+ return (uint16_t)ADC16_GetChannelConversionValue(base, 0);
+}
+
+void adc_task(void *pvParameters)
+{
+ adc16_channel_config_t channel;
+ int i;
+ if (adc_task_init() < 0)
+ return;
+
+ channel.enableDifferentialConversion = false;
+ channel.enableInterruptOnConversionCompleted = false;
+
+ while(1) {
+ for (i = 0; i < ADC0_CHANNEL_CNT;i ++){
+ channel.channelNumber = adc0_channels[i];
+ gen_regs.adc[i] = do_adc_conversion(ADC0, &channel);
+ }
+ vTaskDelay(1);
+ }
+
+}
+
+enum touch_status {
+ PEN_UP,
+ PEN_DOWN
+};
+
+#define MIN_TOUCH_DET 5
+
+/* PTB7 -> ADC1_SE13 X-
+ * PTB6 -> ADC1_SE12 X+
+ * PTC9 -> ADC1_SE5b Y-
+ * PTC8 -> ADC1_SE4b Y+
+ */
+void tsc_task(void *pvParameters)
+{
+ adc16_channel_config_t channel;
+ port_pin_config_t pin_config_pd, pin_config_ana;
+ int old_status, status = PEN_UP;
+ int irq_stat = 0;
+ if (tsc_task_init() < 0)
+ return;
+
+ pin_config_pd.mux = kPORT_MuxAsGpio;
+ pin_config_pd.openDrainEnable = kPORT_OpenDrainDisable;
+ pin_config_pd.pullSelect = kPORT_PullDown;
+ pin_config_pd.slewRate = kPORT_FastSlewRate;
+ pin_config_pd.passiveFilterEnable = kPORT_PassiveFilterDisable;
+ pin_config_pd.driveStrength = kPORT_LowDriveStrength;
+ pin_config_pd.lockRegister = kPORT_UnlockRegister;
+
+ pin_config_ana.mux = kPORT_PinDisabledOrAnalog;
+ pin_config_ana.openDrainEnable = kPORT_OpenDrainDisable;
+ pin_config_ana.pullSelect = kPORT_PullDisable;
+ pin_config_ana.slewRate = kPORT_FastSlewRate;
+ pin_config_ana.passiveFilterEnable = kPORT_PassiveFilterDisable;
+ pin_config_ana.driveStrength = kPORT_LowDriveStrength;
+ pin_config_ana.lockRegister = kPORT_UnlockRegister;
+
+ channel.enableDifferentialConversion = false;
+ channel.enableInterruptOnConversionCompleted = false;
+
+ while(1) {
+ //Touch detect power Y+, enable pulldown on xp and read xp GPIO
+ ts_force_drive(0, 0, 0, 1);
+ PORT_SetPinConfig(PORTB, 6u, &pin_config_pd);
+ vTaskDelay(10);
+ old_status = status;
+ status = GPIO_ReadPinInput(GPIOB, 6u) ? PEN_DOWN:PEN_UP;
+ PORT_SetPinConfig(PORTB, 6u, &pin_config_ana);
+
+ if (status != old_status)
+ irq_stat = 0;
+
+ if (status == PEN_DOWN) {
+ //probe ym with power across Y plane
+ ts_force_drive(0, 0, 1, 1);
+ vTaskDelay(10);
+ channel.channelNumber = tsc_channels[0];
+ gen_regs.tsc_ym = do_adc_conversion(ADC1, &channel);
+
+ //probe yp with power across Y plane
+ channel.channelNumber = tsc_channels[1];
+ gen_regs.tsc_yp = do_adc_conversion(ADC1, &channel);
+
+ //probe xm with power across X plane
+ ts_force_drive(1, 1, 0, 0);
+ vTaskDelay(10);
+ channel.channelNumber = tsc_channels[2];
+ gen_regs.tsc_xm = do_adc_conversion(ADC1, &channel);
+
+ //probe xp with power across X plane
+ channel.channelNumber = tsc_channels[3];
+ gen_regs.tsc_xp = do_adc_conversion(ADC1, &channel);
+
+ if (irq_stat == 0) {
+ generate_irq(APALIS_TK1_K20_TSC_IRQ);
+ irq_stat = 1;
+ }
+ } else {
+ gen_regs.tsc_xm = 0;
+ gen_regs.tsc_xp = 0;
+ gen_regs.tsc_ym = 0;
+ gen_regs.tsc_yp = 0;
+ vTaskDelay(20);
+ if (irq_stat == 0) {
+ generate_irq(APALIS_TK1_K20_TSC_IRQ);
+ irq_stat = 1;
+ }
+ }
+ vTaskDelay(10);
+ }
+
+}
+
+int tsc_registers(uint8_t *rx_buf, uint8_t *tx_buf)
+{
+ if (rx_buf[0] == APALIS_TK1_K20_READ_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_TSCREG:
+ tx_buf[0] = 0x00;
+ return 1;
+ case APALIS_TK1_K20_TSC_XML:
+ tx_buf[0] = gen_regs.tsc_xm & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_TSC_XMH:
+ tx_buf[0] = (gen_regs.tsc_xm >> 8) & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_TSC_XPL:
+ tx_buf[0] = gen_regs.tsc_xp & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_TSC_XPH:
+ tx_buf[0] = (gen_regs.tsc_xp >> 8) & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_TSC_YML:
+ tx_buf[0] = gen_regs.tsc_ym & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_TSC_YMH:
+ tx_buf[0] = (gen_regs.tsc_ym >> 8) & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_TSC_YPL:
+ tx_buf[0] = gen_regs.tsc_yp & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_TSC_YPH:
+ tx_buf[0] = (gen_regs.tsc_yp >> 8) & 0xFF;
+ return 1;
+ default:
+ return -ENOENT;
+ }
+ } else if (rx_buf[0] == APALIS_TK1_K20_WRITE_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_TSCREG:
+ return -ENOENT;
+ default:
+ return -ENOENT;
+ }
+ } else if (rx_buf[0] == APALIS_TK1_K20_BULK_READ_INST) {
+ switch (rx_buf[1]){
+ case APALIS_TK1_K20_TSC_XML:
+ tx_buf[0] = gen_regs.tsc_xm & 0xFF;
+ tx_buf[1] = (gen_regs.tsc_xm >> 8) & 0xFF;
+ return 2;
+ case APALIS_TK1_K20_TSC_XPL:
+ tx_buf[0] = gen_regs.tsc_xp & 0xFF;
+ tx_buf[1] = (gen_regs.tsc_xp >> 8) & 0xFF;
+ return 2;
+ case APALIS_TK1_K20_TSC_YML:
+ tx_buf[0] = gen_regs.tsc_ym & 0xFF;
+ tx_buf[1] = (gen_regs.tsc_ym >> 8) & 0xFF;
+ return 2;
+ case APALIS_TK1_K20_TSC_YPL:
+ tx_buf[0] = gen_regs.tsc_yp & 0xFF;
+ tx_buf[1] = (gen_regs.tsc_yp >> 8) & 0xFF;
+ return 2;
+ default:
+ return -ENOENT;
+ }
+ }
+ return -ENOENT;
+}
+
+int adc_registers(uint8_t *rx_buf, uint8_t *tx_buf)
+{
+ if (rx_buf[0] == APALIS_TK1_K20_READ_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_ADCREG:
+ tx_buf[0] = 0x00;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH0L:
+ tx_buf[0] = gen_regs.adc[0] & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH0H:
+ tx_buf[0] = (gen_regs.adc[0] >> 8) & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH1L:
+ tx_buf[0] = gen_regs.adc[1] & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH1H:
+ tx_buf[0] = (gen_regs.adc[1] >> 8) & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH2L:
+ tx_buf[0] = gen_regs.adc[2] & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH2H:
+ tx_buf[0] = (gen_regs.adc[2] >> 8) & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH3L:
+ tx_buf[0] = gen_regs.adc[3] & 0xFF;
+ return 1;
+ case APALIS_TK1_K20_ADC_CH3H:
+ tx_buf[0] = (gen_regs.adc[3] >> 8) & 0xFF;
+ return 1;
+ default:
+ return -ENOENT;
+ }
+ } else if (rx_buf[0] == APALIS_TK1_K20_WRITE_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_ADCREG:
+ return -ENOENT;
+ default:
+ return -ENOENT;
+ }
+ } else if (rx_buf[0] == APALIS_TK1_K20_BULK_READ_INST) {
+ switch (rx_buf[1]){
+ case APALIS_TK1_K20_ADC_CH0L:
+ tx_buf[0] = gen_regs.adc[0] & 0xFF;
+ tx_buf[1] = (gen_regs.adc[0] >> 8) & 0xFF;
+ return 2;
+ case APALIS_TK1_K20_ADC_CH1L:
+ tx_buf[0] = gen_regs.adc[1] & 0xFF;
+ tx_buf[1] = (gen_regs.adc[1] >> 8) & 0xFF;
+ return 2;
+ case APALIS_TK1_K20_ADC_CH2L:
+ tx_buf[0] = gen_regs.adc[2] & 0xFF;
+ tx_buf[1] = (gen_regs.adc[2] >> 8) & 0xFF;
+ return 2;
+ case APALIS_TK1_K20_ADC_CH3L:
+ tx_buf[0] = gen_regs.adc[3] & 0xFF;
+ tx_buf[1] = (gen_regs.adc[3] >> 8) & 0xFF;
+ return 2;
+
+ default:
+ return -ENOENT;
+ }
+ }
+ return -ENOENT;
+}
+#endif
diff --git a/source/adc_task.h b/source/adc_task.h
new file mode 100644
index 0000000..3dafddb
--- /dev/null
+++ b/source/adc_task.h
@@ -0,0 +1,19 @@
+/*
+ * adc_task.h
+ *
+ */
+
+#ifndef SOURCE_ADC_TASK_H_
+#define SOURCE_ADC_TASK_H_
+#include "board.h"
+
+#ifdef BOARD_USES_ADC
+TaskHandle_t adc_task_handle;
+TaskHandle_t tsc_task_handle;
+void adc_task(void *pvParameters);
+void tsc_task(void *pvParameters);
+int adc_registers(uint8_t *rx_buf, uint8_t *tx_buf);
+int tsc_registers(uint8_t *rx_buf, uint8_t *tx_buf);
+#endif
+
+#endif /* SOURCE_ADC_TASK_H_ */
diff --git a/source/com_task.c b/source/com_task.c
new file mode 100644
index 0000000..348c3e1
--- /dev/null
+++ b/source/com_task.c
@@ -0,0 +1,205 @@
+
+#include "com_task.h"
+#include "gpio_ext.h"
+#include "adc_task.h"
+
+/* Put FW version at known address in binary. Make it 32-bit to have room for the future*/
+const uint32_t __attribute__((section(".FwVersion"))) fw_version = APALIS_TK1_K20_FW_VER;
+
+#define MAX_TRANSFER_SIZE 32U
+static dspi_slave_handle_t spi_handle;
+static uint8_t slaveRxData[MAX_TRANSFER_SIZE] = {0U};
+static uint8_t slaveTxData[MAX_TRANSFER_SIZE] = {0U};
+
+void generate_irq(uint8_t irq) {
+ gen_regs.irq = gen_regs.irq | BIT(irq);
+ /* Toggle INT1 pin */
+ GPIO_TogglePinsOutput(GPIOA, 1u << 16u);
+}
+
+void clear_irq_flag(uint8_t irq) {
+ gen_regs.irq = ~irq & gen_regs.irq;
+}
+
+uint8_t get_control_reg()
+{
+ return gen_regs.control;
+
+}
+
+void set_control_reg(uint8_t value)
+{
+ gen_regs.control = value;
+}
+
+uint8_t get_status_reg()
+{
+ return gen_regs.status;
+
+}
+
+void set_status_reg(uint8_t value)
+{
+ gen_regs.status = value;
+}
+
+uint8_t get_mask_reg()
+{
+ return gen_regs.irq_mask;
+
+}
+
+void set_mask_reg(uint8_t value)
+{
+ gen_regs.irq_mask = value;
+}
+
+uint8_t get_irq_reg()
+{
+ return gen_regs.irq;
+
+}
+
+void set_irq_reg(uint8_t value)
+{
+ /* Clear IRQ flag on 1 */
+ clear_irq_flag(value);
+
+}
+
+int inline general_registers(uint8_t *rx_buf, uint8_t * tx_buf) {
+
+ if (rx_buf[0] == APALIS_TK1_K20_READ_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_STAREG:
+ tx_buf[0] = get_status_reg();
+ return 1;
+ case APALIS_TK1_K20_REVREG:
+ tx_buf[0] = APALIS_TK1_K20_FW_VER;
+ return 1;
+ case APALIS_TK1_K20_IRQREG:
+ tx_buf[0] = get_irq_reg();
+ return 1;
+ case APALIS_TK1_K20_CTRREG:
+ tx_buf[0] = get_control_reg();
+ return 1;
+ case APALIS_TK1_K20_MSQREG:
+ tx_buf[0] = get_mask_reg();
+ return 1;
+ default:
+ return -ENOENT;
+ }
+ } else if (rx_buf[0] == APALIS_TK1_K20_WRITE_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_STAREG:
+ set_status_reg(rx_buf[2]);
+ return 0;
+ case APALIS_TK1_K20_REVREG:
+ return -ENOENT;
+ case APALIS_TK1_K20_IRQREG:
+ set_irq_reg(rx_buf[2]);
+ return 0;
+ case APALIS_TK1_K20_CTRREG:
+ set_control_reg(rx_buf[2]);
+ return 0;
+ case APALIS_TK1_K20_MSQREG:
+ set_mask_reg(rx_buf[2]);
+ return 0;
+ default:
+ return -ENOENT;
+ }
+ }
+
+
+ return -ENOENT;
+}
+
+static void SPI_callback(SPI_Type *base, dspi_slave_handle_t *handle, status_t status, void *userData)
+{
+ callback_message_t * cb = (callback_message_t*) userData;
+ BaseType_t reschedule = pdFALSE;
+
+ if (status == kStatus_Success)
+ {
+ xSemaphoreGiveFromISR(cb->sem, &reschedule);
+ }
+
+ if (status == kStatus_DSPI_Error)
+ {
+ __NOP();
+ }
+ portYIELD_FROM_ISR(reschedule);
+}
+
+static void SPI_init() {
+ dspi_slave_config_t slaveConfig;
+ /* Slave config */
+ slaveConfig.whichCtar = kDSPI_Ctar0;
+ slaveConfig.ctarConfig.bitsPerFrame = 8;
+ slaveConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
+ slaveConfig.ctarConfig.cpha = kDSPI_ClockPhaseSecondEdge;
+ slaveConfig.enableContinuousSCK = true;
+ slaveConfig.enableRxFifoOverWrite = false;
+ slaveConfig.enableModifiedTimingFormat = false;
+ slaveConfig.samplePoint = kDSPI_SckToSin0Clock;
+
+ DSPI_SlaveInit(SPI2, &slaveConfig);
+ DSPI_SlaveTransferCreateHandle(SPI2, &spi_handle, SPI_callback, spi_handle.userData);
+
+ /* Set dspi slave interrupt priority higher. */
+ NVIC_SetPriority(SPI2_IRQn, 5U);
+ GPIO_ClearPinsOutput(GPIOA, 1u << 29u); /* INT2 active */
+ PRINTF("SPI init done \r\n");
+
+}
+
+void spi_task(void *pvParameters) {
+ callback_message_t cb_msg;
+ dspi_transfer_t slaveXfer;
+ int ret;
+
+ cb_msg.sem = xSemaphoreCreateBinary();
+ spi_handle.userData = &cb_msg;
+ SPI_init();
+ GPIO_SetPinsOutput(GPIOA, 1u << 29u); /* INT2 idle */
+
+ while(1){
+ slaveXfer.txData = slaveTxData;
+ slaveXfer.rxData = slaveRxData;
+ slaveXfer.dataSize = 3;
+ slaveXfer.configFlags = kDSPI_SlaveCtar0;
+ /* Wait for instructions from SoC */
+ DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer);
+ xSemaphoreTake(cb_msg.sem, portMAX_DELAY);
+ if (slaveRxData[1] <= 0x05) {
+ ret = general_registers(slaveRxData, &slaveTxData[1]);
+#ifdef BOARD_USES_ADC
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_ADCREG) && (slaveRxData[1] <= APALIS_TK1_K20_ADC_CH3H)) {
+ ret = adc_registers(slaveRxData, &slaveTxData[1]);
+
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_TSCREG) && (slaveRxData[1] <= APALIS_TK1_K20_TSC_YPH)) {
+ ret = tsc_registers(slaveRxData, &slaveTxData[1]);
+#endif
+ } else if ((slaveRxData[1] >= APALIS_TK1_K20_GPIOREG) && (slaveRxData[1] <= APALIS_TK1_K20_GPIO_STA)) {
+ ret = gpio_registers(slaveRxData, &slaveTxData[1]);
+
+ } else {
+ /* Register not defined */
+ ret = -EINVAL;
+ }
+
+ if (ret < 0) {
+ slaveTxData[0] = TK1_K20_INVAL;
+ slaveTxData[1] = TK1_K20_INVAL;
+ } else {
+ slaveTxData[0] = TK1_K20_SENTINEL;
+ }
+
+ if (slaveRxData[0] == APALIS_TK1_K20_READ_INST || slaveRxData[0] == APALIS_TK1_K20_BULK_READ_INST)
+ {
+ slaveXfer.dataSize = (ret >= 0) ? (ret + 1):2; /* Extra byte is for sentinel */
+ DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer);
+ xSemaphoreTake(cb_msg.sem, portMAX_DELAY);
+ }
+ }
+}
diff --git a/source/com_task.h b/source/com_task.h
new file mode 100644
index 0000000..14c742e
--- /dev/null
+++ b/source/com_task.h
@@ -0,0 +1,130 @@
+/*
+ * com_task.h
+ */
+
+#ifndef COM_TASK_H_
+#define COM_TASK_H_
+
+#include "board.h"
+#include "fsl_debug_console.h"
+#include "fsl_dspi.h"
+#include "fsl_gpio.h"
+
+/* FreeRTOS kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "timers.h"
+#include "semphr.h"
+#include "errno.h"
+
+typedef struct _callback_message_t
+{
+ status_t async_status;
+ SemaphoreHandle_t sem;
+} callback_message_t;
+
+TaskHandle_t spi_task_handle;
+void generate_irq(uint8_t irq);
+void clear_irq_flag(uint8_t irq);
+void spi_task(void *pvParameters);
+
+#define BIT(nr) (1UL << (nr))
+
+
+/* Commands and registers used in SPI communication */
+
+/* Commands*/
+#define APALIS_TK1_K20_READ_INST 0x0F
+#define APALIS_TK1_K20_WRITE_INST 0xF0
+#define APALIS_TK1_K20_BULK_WRITE_INST 0x3C
+#define APALIS_TK1_K20_BULK_READ_INST 0xC3
+
+#define APALIS_TK1_K20_MAX_BULK (64)
+
+/* General registers*/
+#define APALIS_TK1_K20_STAREG 0x00 /* General status register RO */
+#define APALIS_TK1_K20_REVREG 0x01 /* FW revision register RO*/
+#define APALIS_TK1_K20_IRQREG 0x02 /* IRQ status RW(write of 1 will reset the bit) */
+#define APALIS_TK1_K20_CTRREG 0x03 /* General control register RW */
+#define APALIS_TK1_K20_MSQREG 0x04 /* IRQ mask register RW */
+
+/* CAN Registers */
+#define APALIS_TK1_K20_CANREG 0x10 /* CAN control & status register RW */
+#define APALIS_TK1_K20_CAN_BAUD_REG 0x11 /* CAN Baud set register RW */
+#define APALIS_TK1_K20_CAN_IN_BUF_CNT 0x12 /* CAN IN BUF Received Data Count RO */
+#define APALIS_TK1_K20_CAN_IN_BUF 0x13 /* CAN IN BUF RO */
+#define APALIS_TK1_K20_CAN_OUT_BUF_CNT 0x14 /* CAN OUT BUF Data Count WO, must be written before bulk write to APALIS_TK1_K20_CAN0_OUT_BUF_CNT */
+#define APALIS_TK1_K20_CAN_OUT_FIF0 0x15 /* CAN OUT BUF WO */
+
+#define APALIS_TK1_K20_CAN_DEV_OFFSET(x) (x ? 0:0x10)
+
+/* ADC Registers */
+#define APALIS_TK1_K20_ADCREG 0x30 /* ADC control & status register RW */
+#define APALIS_TK1_K20_ADC_CH0L 0x31 /* ADC Channel 0 LSB RO */
+#define APALIS_TK1_K20_ADC_CH0H 0x32 /* ADC Channel 0 MSB RO */
+#define APALIS_TK1_K20_ADC_CH1L 0x33 /* ADC Channel 1 LSB RO */
+#define APALIS_TK1_K20_ADC_CH1H 0x34 /* ADC Channel 1 MSB RO */
+#define APALIS_TK1_K20_ADC_CH2L 0x35 /* ADC Channel 2 LSB RO */
+#define APALIS_TK1_K20_ADC_CH2H 0x36 /* ADC Channel 2 MSB RO */
+#define APALIS_TK1_K20_ADC_CH3L 0x37 /* ADC Channel 3 LSB RO */
+#define APALIS_TK1_K20_ADC_CH3H 0x38 /* ADC Channel 3 MSB RO */
+/* Bulk read of LSB register can be use to read entire 16-bit in one command */
+
+/* TSC Register */
+#define APALIS_TK1_K20_TSCREG 0x40 /* TSC control & status register RW */
+#define APALIS_TK1_K20_TSC_XML 0x41 /* TSC X- data LSB RO */
+#define APALIS_TK1_K20_TSC_XMH 0x42 /* TSC X- data MSB RO */
+#define APALIS_TK1_K20_TSC_XPL 0x43 /* TSC X+ data LSB RO */
+#define APALIS_TK1_K20_TSC_XPH 0x44 /* TSC X+ data MSB RO */
+#define APALIS_TK1_K20_TSC_YML 0x45 /* TSC Y- data LSB RO */
+#define APALIS_TK1_K20_TSC_YMH 0x46 /* TSC Y- data MSB RO */
+#define APALIS_TK1_K20_TSC_YPL 0x47 /* TSC Y+ data LSB RO */
+#define APALIS_TK1_K20_TSC_YPH 0x48 /* TSC Y+ data MSB RO */
+/* Bulk read of LSB register can be use to read entire 16-bit in one command */
+#define APALIS_TK1_K20_TSC_ENA BIT(0)
+#define APALIS_TK1_K20_TSC_ENA_MASK 0xFE
+
+/* GPIO Registers */
+#define APALIS_TK1_K20_GPIOREG 0x50 /* GPIO control & status register RW */
+#define APALIS_TK1_K20_GPIO_NO 0x51 /* currently configured GPIO RW */
+#define APALIS_TK1_K20_GPIO_STA 0x52 /* Status register for the APALIS_TK1_K20_GPIO_NO GPIO RW */
+/* MSB | 0 ... 0 | VALUE | Output-1 / Input-0 | LSB */
+#define APALIS_TK1_K20_GPIO_STA_OE BIT(0)
+#define APALIS_TK1_K20_GPIO_STA_VAL BIT(1)
+
+/* Interrupt flags */
+#define APALIS_TK1_K20_GEN_IRQ 0
+#define APALIS_TK1_K20_CAN0_IRQ 1
+#define APALIS_TK1_K20_CAN1_IRQ 2
+#define APALIS_TK1_K20_ADC_IRQ 3
+#define APALIS_TK1_K20_TSC_IRQ 4
+#define APALIS_TK1_K20_GPIO_IRQ 5
+
+#define APALIS_TK1_K20_FW_VER 0x05
+
+#define FW_MINOR (APALIS_TK1_K20_FW_VER & 0x0F)
+#define FW_MAJOR ((APALIS_TK1_K20_FW_VER & 0xF0) >> 8)
+
+#define TK1_K20_SENTINEL 0x55
+#define TK1_K20_INVAL 0xAA
+
+#define ADC0_CHANNEL_CNT 4
+
+#define TSC0_CHANNEL_CNT 4
+
+/* Structure with general registers */
+struct register_struct {
+ uint8_t status;
+ uint8_t control;
+ uint8_t irq_mask;
+ uint8_t irq;
+ uint8_t gpio_no;
+ uint16_t adc[ADC0_CHANNEL_CNT];
+ uint16_t tsc_xm;
+ uint16_t tsc_xp;
+ uint16_t tsc_ym;
+ uint16_t tsc_yp;
+} gen_regs;
+
+#endif /* COM_TASK_H_ */
diff --git a/source/gpio_ext.c b/source/gpio_ext.c
new file mode 100644
index 0000000..5741cb5
--- /dev/null
+++ b/source/gpio_ext.c
@@ -0,0 +1,141 @@
+/*
+ * gpio_ext.c
+ *
+ */
+
+#include "gpio_ext.h"
+#include "com_task.h"
+#include "errno.h"
+
+
+static inline int port_type_to_int(PORT_Type *port)
+{
+ switch ((int) port) {
+ case PORTA_BASE:
+ return 0;
+ case PORTB_BASE:
+ return 1;
+ case PORTC_BASE:
+ return 2;
+ case PORTD_BASE:
+ return 3;
+ case PORTE_BASE:
+ return 4;
+ default:
+ return -EINVAL;
+ }
+}
+
+/* returns GPIO index in gpio_list table and -EINVAL
+ * if there is no entry for this gpio.
+ */
+int is_gpio_valid(uint8_t pin)
+{
+ uint16_t i;
+ int temp;
+ if (pin == 0xFF)
+ return -EINVAL;
+
+ for (i = 0; i < sizeof(gpio_list)/sizeof(struct gpio_id); i++){
+ temp = port_type_to_int(gpio_list[i].port) * 32;
+ temp += gpio_list[i].pin;
+ if ( temp == pin )
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+int set_gpio_status(uint8_t status, uint8_t pin)
+{
+ gpio_pin_config_t gpio_config;
+ int index;
+
+ gpio_config.pinDirection = (status & APALIS_TK1_K20_GPIO_STA_OE) ? kGPIO_DigitalOutput : kGPIO_DigitalInput;
+ gpio_config.outputLogic = (status & APALIS_TK1_K20_GPIO_STA_VAL);
+
+ index = is_gpio_valid(pin);
+
+ if (index >= 0)
+ GPIO_PinInit(gpio_list[index].gpio, gpio_list[index].pin, &gpio_config);
+ else
+ return index;
+
+ return 0;
+}
+
+
+uint8_t get_gpio_status(uint8_t pin)
+{
+ uint8_t status;
+ int index;
+ GPIO_Type *base;
+ uint32_t gpio_pin;
+
+ index = is_gpio_valid(pin);
+ if (index == -EINVAL)
+ return 0xFF;
+ base = gpio_list[index].gpio;
+ gpio_pin = gpio_list[index].pin;
+
+ if (((base->PDDR) >> gpio_pin) & 0x01U) {
+ status = APALIS_TK1_K20_GPIO_STA_OE;
+ status += (((base->PDOR) >> gpio_pin) & 0x01U) ? APALIS_TK1_K20_GPIO_STA_VAL : 0x00;
+ } else {
+ status = 0x00;
+ status += (((base->PDIR) >> gpio_pin) & 0x01U) ? APALIS_TK1_K20_GPIO_STA_VAL : 0x00;
+ }
+
+ return status;
+}
+
+int gpio_registers(uint8_t *rx_buf, uint8_t *tx_buf){
+ if (rx_buf[0] == APALIS_TK1_K20_READ_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_GPIOREG:
+ return -ENOENT;
+ break;
+ case APALIS_TK1_K20_GPIO_NO:
+ if (gen_regs.gpio_no != 0xFF){
+ tx_buf[0] = gen_regs.gpio_no;
+ return 1;
+ } else
+ return -ENOENT;
+ break;
+ case APALIS_TK1_K20_GPIO_STA:
+ if (gen_regs.gpio_no != 0xFF){
+ tx_buf[0] = get_gpio_status(gen_regs.gpio_no);
+ return 1;
+ } else
+ return -ENOENT;
+ break;
+ default:
+ return -ENOENT;
+ }
+ } else if (rx_buf[0] == APALIS_TK1_K20_WRITE_INST) {
+ switch (rx_buf[1]) {
+ case APALIS_TK1_K20_GPIOREG:
+ return -ENOENT;
+ break;
+ case APALIS_TK1_K20_GPIO_NO:
+ if (is_gpio_valid(rx_buf[2]) >= 0){
+ gen_regs.gpio_no = rx_buf[2];
+ return 0;
+ } else {
+ gen_regs.gpio_no = 0xFF;
+ return -ENOENT;
+ }
+ break;
+ case APALIS_TK1_K20_GPIO_STA:
+ return set_gpio_status(rx_buf[2], gen_regs.gpio_no);
+ break;
+ default:
+ return -ENOENT;
+ }
+ }
+ return -ENOENT;
+}
+
+
+
+
diff --git a/source/gpio_ext.h b/source/gpio_ext.h
new file mode 100644
index 0000000..5edbf3a
--- /dev/null
+++ b/source/gpio_ext.h
@@ -0,0 +1,73 @@
+/*
+ * gpio_ext.h
+ *
+ */
+
+#ifndef SOURCE_GPIO_EXT_H_
+#define SOURCE_GPIO_EXT_H_
+
+#include "fsl_device_registers.h"
+#include "fsl_debug_console.h"
+#include "board.h"
+
+struct gpio_id{
+ PORT_Type *port;
+ GPIO_Type *gpio;
+ uint32_t pin;
+};
+
+struct gpio_id gpio_list [] = {
+ {PORTA, GPIOA, 3},
+ {PORTA, GPIOA, 5},
+ {PORTA, GPIOA, 17},
+#ifndef BOARD_USES_ADC
+ {PORTB, GPIOB, 1},
+ {PORTB, GPIOB, 2},
+ {PORTB, GPIOB, 3},
+#endif
+#ifndef SDK_DEBUGCONSOLE
+ {PORTB, GPIOB, 10},
+ {PORTB, GPIOB, 11},
+#endif
+ {PORTB, GPIOB, 16},
+ {PORTB, GPIOB, 17},
+ {PORTB, GPIOB, 18},
+ {PORTB, GPIOB, 19},
+ {PORTC, GPIOC, 0},
+ {PORTC, GPIOC, 1},
+ {PORTC, GPIOC, 2},
+ {PORTC, GPIOC, 3},
+ {PORTC, GPIOC, 4},
+ {PORTC, GPIOC, 6},
+ {PORTC, GPIOC, 7},
+ {PORTD, GPIOD, 0},
+ {PORTD, GPIOD, 1},
+ {PORTD, GPIOD, 2},
+ {PORTD, GPIOD, 3},
+ {PORTD, GPIOD, 4},
+ {PORTD, GPIOD, 5},
+ {PORTD, GPIOD, 6},
+ {PORTD, GPIOD, 7},
+ {PORTD, GPIOD, 8},
+ {PORTD, GPIOD, 9},
+ {PORTD, GPIOD, 11},
+ {PORTD, GPIOD, 12},
+ {PORTD, GPIOD, 13},
+ {PORTD, GPIOD, 14},
+ {PORTD, GPIOD, 15},
+ {PORTE, GPIOE, 0},
+ {PORTE, GPIOE, 1},
+ {PORTE, GPIOE, 2},
+ {PORTE, GPIOE, 3},
+ {PORTE, GPIOE, 4},
+ {PORTE, GPIOE, 5},
+ {PORTE, GPIOE, 24},
+ {PORTE, GPIOE, 25}
+};
+
+int is_gpio_valid(uint8_t pin);
+int set_gpio_status(uint8_t status, uint8_t pin);
+uint8_t get_gpio_status(uint8_t pin);
+int gpio_registers(uint8_t *rx_buf, uint8_t *tx_buf);
+
+#endif /* SOURCE_GPIO_EXT_H_ */
diff --git a/source/main.c b/source/main.c
index 094da3a..e035d4e 100644
--- a/source/main.c
+++ b/source/main.c
@@ -37,7 +37,9 @@
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
-/*#include "fsl_debug_console.h"*/
+#include "fsl_debug_console.h"
+#include "com_task.h"
+#include "adc_task.h"
/* FreeRTOS kernel includes. */
#include "FreeRTOS.h"
@@ -46,38 +48,77 @@
#include "timers.h"
+#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI))
+#define CONTROLLER_ID kUSB_ControllerKhci0
+#endif
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+#define CONTROLLER_ID kUSB_ControllerEhci0
+#endif
+
/* Task priorities. */
-#define hello_task_PRIORITY (configMAX_PRIORITIES - 1)
+#define debug_task_PRIORITY 1
+#define USB_HOST_INTERRUPT_PRIORITY (5U)
+
+/* Task handles */
+
+TaskHandle_t usb_task_handle;
+#ifdef SDK_DEBUGCONSOLE
+TaskHandle_t debug_task_handle;
+#endif
+
/*!
- * @brief Task responsible for printing of "Hello world." message.
+ * @brief Debug task
*/
-static void hello_task(void *pvParameters) {
- for (;;) {
- /*PRINTF("Hello world.\r\n");*/
- /* Add your code here */
- vTaskSuspend(NULL);
- }
+#ifdef SDK_DEBUGCONSOLE
+static void debug_task(void *pvParameters) {
+ for (;;) {
+ vTaskDelay(10000);
+ }
}
-
+#endif
/*!
* @brief Application entry point.
*/
int main(void) {
- /* Init board hardware. */
- BOARD_InitPins();
- BOARD_BootClockRUN();
- BOARD_InitDebugConsole();
- /* Add your code here */
+ /* Init board hardware. */
+ BOARD_InitPins();
+ BOARD_BootClockRUN();
+ BOARD_InitDebugConsole();
+ PRINTF("Apalis K20 Firmware Version %d.%d\r\n", FW_MAJOR, FW_MINOR);
+
+ /* Create RTOS task */
+ if(xTaskCreate(spi_task, "SPI_task", 2000L / sizeof(portSTACK_TYPE), NULL, 4, &spi_task_handle) != pdPASS)
+ {
+ PRINTF("create SPI task error\r\n");
+ }
+
+#ifdef BOARD_USES_ADC
+ if(xTaskCreate(adc_task, "ADC_task", 2000L / sizeof(portSTACK_TYPE), NULL, 2, &adc_task_handle) != pdPASS)
+ {
+ PRINTF("create ADC task error\r\n");
+ }
+
+ if(xTaskCreate(tsc_task, "TSC_task", 2000L / sizeof(portSTACK_TYPE), NULL, 2, &tsc_task_handle) != pdPASS)
+ {
+ PRINTF("create TSC task error\r\n");
+ }
+#endif
+
+#ifdef SDK_DEBUGCONSOLE
+ if(xTaskCreate(debug_task, "Debug_task", configMINIMAL_STACK_SIZE, NULL, debug_task_PRIORITY, &debug_task_handle) != pdPASS)
+ {
+ PRINTF("create hello task error\r\n");
+ }
+#endif
- /* Create RTOS task */
- xTaskCreate(hello_task, "Hello_task", configMINIMAL_STACK_SIZE, NULL, hello_task_PRIORITY, NULL);
- vTaskStartScheduler();
+ NVIC_SetPriorityGrouping( 0 );
+ vTaskStartScheduler();
- for(;;) { /* Infinite loop to avoid leaving the main function */
- __asm("NOP"); /* something to use as a breakpoint stop while looping */
- }
+ for(;;) { /* Infinite loop to avoid leaving the main function */
+ __asm("NOP"); /* something to use as a breakpoint stop while looping */
+ }
}