added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Revision:
107:414e9c822e99
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_Atmel/TARGET_SAM_CortexM4/lp_ticker.c	Tue Apr 05 18:15:12 2016 +0100
@@ -0,0 +1,133 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cmsis.h"
+#include <stddef.h>
+#include "lp_ticker_api.h"
+#include "mbed_assert.h"
+#include "sleep_api.h"
+#include "compiler.h"
+#include "sysclk.h"
+#include "tc.h"
+#include "us_ticker_api.h"
+
+uint8_t lp_ticker_inited = 0;
+extern volatile uint8_t us_ticker_inited;
+extern uint8_t g_sys_init;
+extern volatile uint32_t overflow32bitcounter;
+volatile uint16_t lp_ticker_16bit_counter;
+volatile uint16_t lp_ticker_interrupt_counter;
+volatile uint16_t lp_ticker_interrupt_offset;
+volatile uint32_t lpoverflow32bitcounter = 0;
+
+#define TICKER_COUNTER_lp		TC0
+
+#define TICKER_COUNTER_CLK2     ID_TC2
+
+#define TICKER_COUNTER_CHANNEL2 2
+#define TICKER_COUNTER_IRQn2	TC2_IRQn
+#define TICKER_COUNTER_Handlr2  TC2_Handler
+
+#define OVERFLOW_16bit_VALUE    0xFFFF
+
+
+void TICKER_COUNTER_Handlr2(void)
+{
+    uint32_t status=tc_get_status(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
+    uint32_t interrupmask=tc_get_interrupt_mask(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
+
+    if (((status & interrupmask)  & TC_IER_CPCS)) {
+        if(lp_ticker_interrupt_counter) {
+            lp_ticker_interrupt_counter--;
+        } else {
+            if(lp_ticker_interrupt_offset) {
+                tc_stop(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
+                tc_write_rc(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, (uint32_t)lp_ticker_interrupt_offset);
+                tc_start(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
+                lp_ticker_interrupt_offset=0;
+            } else {
+                lp_ticker_irq_handler();
+            }
+        }
+    }
+}
+
+void lp_ticker_init(void)
+{
+    if(lp_ticker_inited)
+        return;
+    if (!us_ticker_inited)
+        us_ticker_init();
+    sysclk_enable_peripheral_clock(TICKER_COUNTER_CLK2);
+    tc_init(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, TC_CMR_TCCLKS_TIMER_CLOCK4);
+    lp_ticker_inited = 1;
+}
+
+uint32_t lp_ticker_read()
+{
+    if (!lp_ticker_inited)
+        lp_ticker_init();
+    return us_ticker_read();
+}
+
+void lp_ticker_set_interrupt(timestamp_t timestamp)
+{
+    uint32_t cur_time;
+    int32_t delta;
+
+    cur_time = lp_ticker_read();
+    delta = (int32_t)((uint32_t)timestamp - cur_time);
+    if (delta < 0) {
+        /* Event already occurred in past */
+        lp_ticker_irq_handler();
+        return;
+    }
+
+    uint16_t interruptat=0;
+
+    if(delta > OVERFLOW_16bit_VALUE) {
+        lp_ticker_interrupt_counter= (delta/OVERFLOW_16bit_VALUE) -1;
+        lp_ticker_interrupt_offset=delta%OVERFLOW_16bit_VALUE;
+        interruptat=OVERFLOW_16bit_VALUE;
+    } else {
+        lp_ticker_interrupt_counter=0;
+        lp_ticker_interrupt_offset=0;
+        interruptat=delta;
+    }
+
+    NVIC_DisableIRQ(TICKER_COUNTER_IRQn2);
+
+    tc_write_rc(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, (uint32_t)interruptat);
+
+    NVIC_ClearPendingIRQ(TICKER_COUNTER_IRQn2);
+    NVIC_SetPriority(TICKER_COUNTER_IRQn2, 0);
+    NVIC_EnableIRQ(TICKER_COUNTER_IRQn2);
+    tc_enable_interrupt(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, TC_IDR_CPCS );
+
+    tc_start(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
+}
+
+void lp_ticker_disable_interrupt(void)
+{
+    tc_stop(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
+    tc_disable_interrupt(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, TC_IDR_CPCS);
+    NVIC_DisableIRQ(TICKER_COUNTER_IRQn2);
+}
+
+void lp_ticker_clear_interrupt(void)
+{
+    NVIC_ClearPendingIRQ(TICKER_COUNTER_IRQn2);
+}