+#include <MKL46Z4.h>\r
+\r
+#include <stdint.h>\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "timer_dma.h"\r
+\r
+/* Defines */\r
+enum {\r
+ TDMA_REQ_PTA = 49,\r
+ TDMA_REQ_PTC = 51,\r
+ TDMA_REQ_PTD = 52,\r
+};\r
+\r
+/* Port structure */\r
+struct tdma_t {\r
+ /* DMA channel */\r
+ struct {\r
+ uint32_t sar; // offset 0x00, Source Address Register\r
+ uint32_t dar; // offset 0x04, Destination Address Register\r
+ uint32_t dsr; // offset 0x08, DMA Status Register / Byte Count Register\r
+ uint32_t dcr; // offset 0x0C, DMA Control Register\r
+ } *dma;\r
+\r
+ /* DMA mux */\r
+ struct {\r
+ uint8_t cfg; // offset 0x00, Channel Configuration register\r
+ } *mux;\r
+\r
+ /* Pin names */\r
+ struct {\r
+ uint32_t pcr; // offset 0x00, Pin Control register\r
+ } *pin;\r
+\r
+ /* Time stamping */\r
+ uint32_t time[2];\r
+};\r
+\r
+/* Port data */\r
+static tdma_t tdma_ports[TDMA_NUM_CHAN];\r
+\r
+/* Global timer initialization */\r
+void tdma_init(void)\r
+{\r
+ // Enable DMA Cock\r
+ SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;\r
+ SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;\r
+ SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;\r
+ SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;\r
+ SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;\r
+\r
+ // Enable timer Clock\r
+ SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;\r
+\r
+ // Enable PIT\r
+ PIT->MCR = 0;\r
+\r
+ // Channel 0\r
+ PIT->CHANNEL[0].LDVAL = 0xFFFFFFFF;\r
+ PIT->CHANNEL[0].TCTRL = 0;\r
+\r
+ // Channel 1\r
+ PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;\r
+ PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK;\r
+\r
+ // Start timers\r
+ PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;\r
+ PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;\r
+}\r
+\r
+/* DMA Functions */\r
+tdma_t *tdma_open(tdma_chan_t chan, PinName pin, PinMode mode)\r
+{\r
+ int req = pin >= PTD0 ? TDMA_REQ_PTD :\r
+ pin >= PTC0 ? TDMA_REQ_PTC :\r
+ pin >= PTA0 ? TDMA_REQ_PTA : 0;\r
+\r
+ int ircq = mode == PullUp ? 2 : 1;\r
+\r
+ // Allocate port\r
+ tdma_t *port = &tdma_ports[chan];\r
+\r
+ // Setup port pointers\r
+ port->dma = (void*)&DMA0->DMA[chan];\r
+ port->mux = (void*)&DMAMUX0->CHCFG[chan];\r
+ port->pin = (void*)(PORTA_BASE + pin);\r
+\r
+ // Reset DMA channel\r
+ port->dma->dsr = DMA_DSR_BCR_DONE_MASK;\r
+\r
+ // Configure DMA channel\r
+ port->dma->dcr = DMA_DCR_SINC_MASK // Source increment\r
+ | DMA_DCR_DINC_MASK // Dest increment\r
+ | DMA_DCR_SSIZE(0) // 32-bit access\r
+ | DMA_DCR_DSIZE(0) // 32-bit access\r
+ | DMA_DCR_ERQ_MASK; // Enable port request\r
+\r
+ // Setup and enable DMA MUX\r
+ port->mux->cfg = DMAMUX_CHCFG_SOURCE(req) // Request source\r
+ | DMAMUX_CHCFG_ENBL_MASK; // Enable DMA mux\r
+\r
+ // Set pin to generate DMA req\r
+ port->pin->pcr = PORT_PCR_ISF_MASK // Clear ISR flag\r
+ | PORT_PCR_MUX(3) // Pin mapping\r
+ | PORT_PCR_IRQC(ircq) // DMA on falling edge\r
+ | mode; // Pin pull up/down\r
+\r
+ return port;\r
+}\r
+\r
+void tdma_reset(tdma_t *port)\r
+{\r
+ // Clear previous time\r
+ port->time[0] = 0;\r
+ port->time[1] = 0;\r
+\r
+ // Reset DMA channel\r
+ port->dma->dsr = DMA_DSR_BCR_DONE_MASK;\r
+\r
+ // Set addresses and size\r
+ port->dma->sar = (uint32_t)&PIT->LTMR64H; // Global timer\r
+ port->dma->dar = (uint32_t)&port->time; // Temp timer buffer\r
+ port->dma->dsr = DMA_DSR_BCR_BCR(8); // 64-bit timer\r
+}\r
+\r
+int tdma_stamp(tdma_t *port, uint64_t *time)\r
+{\r
+ if (port->dma->dsr & DMA_DSR_BCR_BCR_MASK)\r
+ return 0;\r
+\r
+ // Read the timestamp\r
+ *time = ((uint64_t)~port->time[0]) << 32\r
+ | ((uint64_t)~port->time[1]) << 0;\r
+\r
+ // Debug output..\r
+ //printf(" - sar:%08lx dar:%08lx pcr:%08lx dsr:%08lx time:%08lx:%08lx",\r
+ // port->dma->sar, port->dma->dar,\r
+ // port->pin->pcr, port->dma->dsr,\r
+ // (uint32_t)(*time >> 32), (uint32_t)*time);\r
+\r
+ return 1;\r
+}\r