Potmeter FastPWM.h

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
vd
Date:
Tue Sep 19 16:52:01 2017 +0000
Commit message:
Potmeter FastPWM.h

Changed in this revision

Device/FastPWM_KLXX_K20D50M.cpp Show annotated file Show diff for this revision Revisions of this file
Device/FastPWM_KSDK.cpp Show annotated file Show diff for this revision Revisions of this file
Device/FastPWM_LPC11XX.cpp Show annotated file Show diff for this revision Revisions of this file
Device/FastPWM_LPC1768.cpp Show annotated file Show diff for this revision Revisions of this file
Device/FastPWM_LPC_SCT.cpp Show annotated file Show diff for this revision Revisions of this file
Device/FastPWM_STM_TIM.cpp Show annotated file Show diff for this revision Revisions of this file
Device/FastPWM_STM_TIM_PinOut.cpp Show annotated file Show diff for this revision Revisions of this file
FastPWM.h Show annotated file Show diff for this revision Revisions of this file
FastPWM_common.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 16be67f4d9ac Device/FastPWM_KLXX_K20D50M.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/FastPWM_KLXX_K20D50M.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,55 @@
+#if defined(TARGET_KLXX) || defined(TARGET_K20D50M)
+
+#include "FastPWM.h"
+
+void FastPWM::initFastPWM( void ) {
+    bits = 16;
+}
+
+void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
+    *(_pwm.CnV) = ticks;
+}
+
+void FastPWM::period_ticks( uint32_t ticks ) {
+    *(_pwm.MOD) = ticks - 1;
+}
+
+uint32_t FastPWM::getPeriod( void ) {
+    return *(_pwm.MOD) + 1;
+}
+
+uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
+        
+    //Yes this is ugly, yes I should feel bad about it
+    volatile uint32_t *TPM_SC = _pwm.MOD - 2;
+    
+    const char prescalers[] = {1, 2, 4, 8, 16, 32, 64, 128};
+    
+    //If prescaler is 0, return current one
+    if (reqScale == 0)
+        return (prescalers[(*TPM_SC) & 0x07]);
+    
+    uint32_t retval = 0;
+    char bin;
+    
+    for (bin = 0; bin<8; bin++) {
+        retval = prescalers[bin];
+        if (retval >= reqScale)
+            break;
+    }
+    if (bin == 8)
+        bin = 7;
+    
+    //Clear lower 5 bits, write new value:
+    char clockbits = *TPM_SC & (3<<3);
+    
+    //For some reason clearing them takes some effort
+    while ((*TPM_SC & 0x1F) != 0)
+        *TPM_SC &= ~0x1F;
+        
+    
+    *TPM_SC = bin + clockbits;
+    
+    return retval;   
+}
+#endif
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac Device/FastPWM_KSDK.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/FastPWM_KSDK.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,88 @@
+#if defined(TARGET_KPSDK_MCUS)
+
+#include "FastPWM.h"
+#include "fsl_ftm.h"
+
+
+#define PWM_CNV              (*(((fastpwm_struct*)fast_obj)->CnV))  
+#define PWM_MOD              (*(((fastpwm_struct*)fast_obj)->MOD))  
+#define PWM_SC               (*(((fastpwm_struct*)fast_obj)->SC))  
+#define PWM_SYNC             (*(((fastpwm_struct*)fast_obj)->SYNC))  
+
+typedef struct  {
+    __IO uint32_t *CnV;
+    __IO uint32_t *MOD;
+    __IO uint32_t *SC;
+    __IO uint32_t *SYNC;
+} fastpwm_struct;
+
+static uint32_t pwm_prescaler;
+static FTM_Type *const ftm_addrs[] = FTM_BASE_PTRS;
+
+void FastPWM::initFastPWM( void ) {
+    fast_obj = new fastpwm_struct;
+    bits = 16;
+
+    pwm_prescaler = SystemCoreClock / CLOCK_GetFreq(kCLOCK_BusClk);;
+
+    unsigned int ch_n = (_pwm.pwm_name & 0xF);
+    FTM_Type *ftm = ftm_addrs[_pwm.pwm_name >> TPM_SHIFT];
+    
+    ((fastpwm_struct*)fast_obj)->CnV = &ftm->CONTROLS[ch_n].CnV;
+    ((fastpwm_struct*)fast_obj)->MOD = &ftm->MOD;
+    ((fastpwm_struct*)fast_obj)->SC = &ftm->SC;
+    ((fastpwm_struct*)fast_obj)->SYNC = &ftm->SYNC;
+    
+    //Do not clear counter when writing new value, set end of period as loading value
+    ftm->SYNCONF &= ~FTM_SYNCONF_SWRSTCNT_MASK;
+    ftm->SYNC |= FTM_SYNC_CNTMAX_MASK;
+}
+
+void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
+    PWM_CNV = ticks;
+    PWM_SYNC |= FTM_SYNC_SWSYNC_MASK;
+}
+
+void FastPWM::period_ticks( uint32_t ticks ) {
+    PWM_MOD = ticks - 1;
+    PWM_SYNC |= FTM_SYNC_SWSYNC_MASK;  
+}
+
+uint32_t FastPWM::getPeriod( void ) {
+    return PWM_MOD + 1;
+}
+
+uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
+ 
+    uint32_t prescalers[] = {1, 2, 4, 8, 16, 32, 64, 128};
+    
+    for (int i = 0; i<8; i++)
+         prescalers[i] = prescalers[i] * pwm_prescaler;
+    
+    //If prescaler is 0, return current one
+    if (reqScale == 0)
+        return (prescalers[(PWM_SC) & 0x07]);
+    
+    uint32_t retval = 0;
+    char bin;
+    
+    for (bin = 0; bin<8; bin++) {
+        retval = prescalers[bin];
+        if (retval >= reqScale)
+            break;
+    }
+    if (bin == 8)
+        bin = 7;
+    
+    //Clear lower 5 bits, write new value:
+    char clockbits = PWM_SC & (3<<3);
+    
+    //For some reason clearing them takes some effort
+    while ((PWM_SC & 0x1F) != 0)
+        PWM_SC &= ~0x1F;
+        
+    
+    PWM_SC = bin + clockbits;
+    return retval;   
+}
+#endif
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac Device/FastPWM_LPC11XX.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/FastPWM_LPC11XX.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,103 @@
+#if defined(TARGET_LPC11UXX) || defined(TARGET_LPC11XX_11CXX)
+
+#include "FastPWM.h"
+
+#define PWM_MR              (*(((fastpwm_struct*)fast_obj)->MR))   
+#define PWM_TIMER           (((fastpwm_struct*)fast_obj)->timer)      
+
+typedef struct {
+    uint8_t timer;
+    uint8_t mr;
+} timer_mr;
+ 
+#ifdef TARGET_LPC11UXX
+typedef struct  {
+    __IO uint32_t *MR;
+    LPC_CTxxBx_Type *timer;
+} fastpwm_struct;
+
+static timer_mr pwm_timer_map[11] = {
+    {0, 0}, {0, 1}, {0, 2},
+    {1, 0}, {1, 1},
+    {2, 0}, {2, 1}, {2, 2},
+    {3, 0}, {3, 1}, {3, 2},
+};
+
+static LPC_CTxxBx_Type *Timers[4] = {
+    LPC_CT16B0, LPC_CT16B1,
+    LPC_CT32B0, LPC_CT32B1
+};
+#else           //LPC11XX
+typedef struct  {
+    __IO uint32_t *MR;
+    LPC_TMR_TypeDef *timer;
+} fastpwm_struct;
+
+static timer_mr pwm_timer_map[5] = {
+    {0, 0}, /* CT16B0, MR0 */
+    {0, 1}, /* CT16B0, MR1 */
+ 
+    {1, 0}, /* CT16B1, MR0 */
+    {1, 1}, /* CT16B1, MR1 */
+ 
+    {2, 2}, /* CT32B0, MR2 */
+};
+
+static LPC_TMR_TypeDef *Timers[3] = {
+    LPC_TMR16B0, LPC_TMR16B1,
+    LPC_TMR32B0
+};
+#endif
+
+
+void FastPWM::initFastPWM( void ) {
+    fast_obj = new fastpwm_struct;
+    timer_mr tid = pwm_timer_map[_pwm.pwm];
+    PWM_TIMER = Timers[tid.timer];
+    (((fastpwm_struct*)fast_obj)->MR) = &PWM_TIMER->MR[tid.mr];
+    
+    if (tid.timer < 2)
+        //16-bit timer
+        bits = 16;
+    else
+        //32-bit timer
+        bits = 32;  
+}
+
+void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
+    if (ticks)
+        PWM_MR = PWM_TIMER->MR3 - ticks;  //They inverted PWM on the 11u24
+    else
+        PWM_MR = 0xFFFFFFFF;           //If MR3 = ticks 1 clock cycle wide errors appear, this prevents that (unless MR3 = max).
+}
+
+void FastPWM::period_ticks( uint32_t ticks ) {  
+    PWM_TIMER->TCR = 0x02;
+    PWM_TIMER->MR3 = ticks;
+    PWM_TIMER->TCR = 0x01;   
+}
+
+uint32_t FastPWM::getPeriod( void ) {
+    return PWM_TIMER->MR3;
+}
+
+uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
+    //If 32-bit, disable auto-scaling, return 1
+    if (bits == 32) {
+        dynamicPrescaler = false;
+        return 1;
+    }
+    
+    //Else 16-bit timer:
+    if (reqScale == 0)
+        //Return prescaler
+        return PWM_TIMER->PR + 1;
+    if (reqScale > (uint32_t)(1<<16))
+        reqScale = 1<<16;
+    //Else set prescaler, we have to substract one from reqScale since a 0 in PCVAL is prescaler of 1
+    PWM_TIMER->PR = reqScale - 1;
+
+    return reqScale;
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac Device/FastPWM_LPC1768.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/FastPWM_LPC1768.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,34 @@
+#ifdef TARGET_LPC176X
+
+#include "FastPWM.h"
+
+void FastPWM::initFastPWM( void ) {
+    //Set clock source
+    LPC_SC->PCLKSEL0|=1<<12;
+    bits = 32;
+}
+
+void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
+    *(_pwm.MR) = ticks;
+    LPC_PWM1->LER |= 1 << _pwm.pwm;
+}
+
+void FastPWM::period_ticks( uint32_t ticks ) {
+    LPC_PWM1->MR0 = ticks;
+    LPC_PWM1->LER |= 1 << 0;
+}
+
+uint32_t FastPWM::getPeriod( void ) {
+    return LPC_PWM1->MR0;
+}
+
+//Maybe implemented later, but needing to change the prescaler for a 32-bit
+//timer used in PWM mode is kinda unlikely.
+//If you really need to do it, rejoice, you can make it run so slow a period is over 40,000 year
+uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
+    //Disable dynamic prescaling
+    dynamicPrescaler = false;
+    
+    return 1;
+}
+#endif
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac Device/FastPWM_LPC_SCT.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/FastPWM_LPC_SCT.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,63 @@
+//For targets which use the SCT
+#if defined(TARGET_LPC81X) || defined(TARGET_LPC82X)
+
+#ifdef TARGET_LPC82X
+#define CTRL_U CTRL
+#endif
+
+#include "FastPWM.h"
+
+void FastPWM::initFastPWM( void ) {
+    //Mbed uses the timer as a single unified 32-bit timer, who are we to argue with this, and it is easier
+    bits = 32;
+    
+    #ifdef TARGET_LPC82X
+    //The mbed lib uses the PWM peripheral slightly different, which is irritating. This sets it bck to the LPC81X
+        _pwm.pwm->EVENT[_pwm.pwm_ch + 1].CTRL  = (1 << 12) | (_pwm.pwm_ch + 1);     // Event_n on Match_n 
+        _pwm.pwm->EVENT[_pwm.pwm_ch + 1].STATE = 0xFFFFFFFF;                        // All states  
+        _pwm.pwm->OUT[_pwm.pwm_ch].SET = (1 << 0);                                  // All PWM channels are SET on Event_0 
+        _pwm.pwm->OUT[_pwm.pwm_ch].CLR = (1 << (_pwm.pwm_ch + 1));                  // PWM ch is CLRed on Event_(ch+1) 
+    #endif
+    
+    //With 32-bit we fix prescaler to 1
+    _pwm.pwm->CTRL_U |= (1 << 2) | (1 << 3);
+    _pwm.pwm->CTRL_U &= ~(0x7F << 5);
+    _pwm.pwm->CTRL_U &= ~(1 << 2);
+
+}
+
+void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
+    #ifdef TARGET_LPC81X
+    _pwm.pwm->MATCHREL[_pwm.pwm_ch + 1].U = ticks;
+    #else
+    _pwm.pwm->MATCHREL[_pwm.pwm_ch + 1] = ticks;
+    #endif
+}
+
+void FastPWM::period_ticks( uint32_t ticks ) {
+    #ifdef TARGET_LPC81X
+    _pwm.pwm->MATCHREL[0].U = ticks;
+    #else
+    _pwm.pwm->MATCHREL[0] = ticks;
+    #endif
+}
+
+uint32_t FastPWM::getPeriod( void ) {
+    #ifdef TARGET_LPC81X
+    return _pwm.pwm->MATCHREL[0].U;
+    #else
+    return _pwm.pwm->MATCHREL[0];
+    #endif
+}
+
+//Maybe implemented later, but needing to change the prescaler for a 32-bit
+//timer used in PWM mode is kinda unlikely.
+//If you really need to do it, rejoice, you can make it run so slow a period is over 40,000 year
+uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
+    //Disable dynamic prescaling
+    dynamicPrescaler = false;
+    
+    return 1;
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac Device/FastPWM_STM_TIM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/FastPWM_STM_TIM.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,75 @@
+//This should (hopefully) work on all STM targets which use TIM timers for PWM
+
+#ifdef TARGET_STM
+
+#include "FastPWM.h"
+
+typedef __IO uint32_t* CHANNEL_P_T;
+
+typedef struct  {
+    CHANNEL_P_T channel;
+    uint32_t clk_prescaler;
+} fastpwm_struct;
+
+#define PWM_CHANNEL         ((((fastpwm_struct*)fast_obj)->channel)) 
+#define PWM_CLK_PRESCALER   ((((fastpwm_struct*)fast_obj)->clk_prescaler))
+#define PWM_TIMER           ((TIM_TypeDef*)_pwm.pwm)
+
+#if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1)
+extern __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin);
+#endif
+
+void FastPWM::initFastPWM( void ) {
+    fast_obj = new fastpwm_struct;
+    #if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1)
+    PWM_CHANNEL = getChannel(PWM_TIMER, _pwm.pin);
+    #else
+    PWM_CHANNEL = (&PWM_TIMER->CCR1 + _pwm.channel - 1); 
+    #endif
+    
+    // Depending on the timer and the internal bus it is connected to, each STM timer
+    // can have a fixed prescaler from the clock, especially the faster devices.
+    // In order not to have to hardcode this in, we use knowledge that mbed lib sets
+    // default period to 20ms to reverse engineer the prescaler from this. 
+    uint32_t current_hz = SystemCoreClock / (PWM_TIMER->PSC + 1) / (PWM_TIMER->ARR+1);
+    PWM_CLK_PRESCALER = (current_hz + 1) / 50;  //50Hz is magic number it should be, +1 is to handle possible rounding errors in mbed setup
+    
+    //Sanity check in case a target does something different
+    if ( (PWM_CLK_PRESCALER == 0 ) || (PWM_CLK_PRESCALER > 16)) {
+        PWM_CLK_PRESCALER = 1;
+    }
+    
+    //Enable PWM period syncing for glitch free result
+    PWM_TIMER->CR1 |= TIM_CR1_ARPE;
+    
+    bits = 16;
+}
+
+void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
+    *PWM_CHANNEL = ticks;    
+}
+
+void FastPWM::period_ticks( uint32_t ticks ) {
+    PWM_TIMER->ARR = ticks - 1;
+}
+
+uint32_t FastPWM::getPeriod( void ) {
+    return PWM_TIMER->ARR + 1;
+}
+
+uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
+    if (reqScale == 0) {
+        //Return prescaler
+        return (PWM_TIMER->PSC + 1) * PWM_CLK_PRESCALER;
+    }
+    if (reqScale > (uint32_t)(PWM_CLK_PRESCALER<<16)) {
+        reqScale = PWM_CLK_PRESCALER<<16;
+    }
+    //Else set prescaler, we have to substract one from reqScale since a 0 in PCVAL is prescaler of 1
+    //Take into account PWM_CLK_PRESCALER, we need to make sure reqScale is always rounded up
+    PWM_TIMER->PSC = (reqScale + PWM_CLK_PRESCALER - 1)/PWM_CLK_PRESCALER - 1;
+
+    return setPrescaler(0);
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac Device/FastPWM_STM_TIM_PinOut.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/FastPWM_STM_TIM_PinOut.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,102 @@
+#include "mbed.h"
+
+#if defined (TARGET_NUCLEO_F030R8) || (TARGET_DISCO_F051R8)
+__IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) {
+    switch (pin) {
+        // Channels 1
+        case PA_4: case PA_6: case PB_1: case PB_4: case PB_8: case PB_9: case PB_14: case PC_6: case PB_6: case PB_7:
+            return &pwm->CCR1;
+            
+        // Channels 2
+        case PA_7: case PB_5: case PC_7:
+            return &pwm->CCR2;
+            
+        // Channels 3
+        case PB_0: case PC_8:
+            return &pwm->CCR3;
+            
+        // Channels 4
+        case PC_9:
+            return &pwm->CCR4;
+    }        
+    return NULL;
+}
+#endif
+
+#if defined (TARGET_NUCLEO_F103RB) || (TARGET_DISCO_F100RB)
+__IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) {
+    switch (pin) {
+        // Channels 1 : PWMx/1
+        case PA_6: case PA_8: case PA_15: case PB_4: case PC_6: case PB_13:
+            return &pwm->CCR1;
+        
+        // Channels 2 : PWMx/2
+        case PA_1: case PA_7: case PA_9: case PB_3: case PB_5: case PC_7: case PB_14:
+            return &pwm->CCR2;
+            
+        // Channels 3 : PWMx/3
+        case PA_2: case PA_10: case PB_0: case PB_10: case PC_8: case PB_15:
+            return &pwm->CCR3;
+ 
+        // Channels 4 : PWMx/4
+        case PA_3: case PA_11: case PB_1: case PB_11: case PC_9: 
+            return &pwm->CCR4;
+    }
+    return NULL;
+}
+#endif
+
+#if defined TARGET_NUCLEO_F072RB
+__IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) {
+    switch (pin) {
+        // Channels 1 : PWMx/1
+        case PA_2: case PA_6: case PA_4: case PA_7: case PA_8: case PB_1: case PB_4: case PB_8: case PB_9: case PB_14: case PC_6:
+        // Channels 1N : PWMx/1N
+        case PA_1: case PB_6: case PB_7: case PB_13:
+            return &pwm->CCR1;
+        
+        // Channels 2 : PWMx/2
+        case PA_3: case PA_9: case PB_5: case PC_7: case PB_15:
+            return &pwm->CCR2;
+            
+        // Channels 3 : PWMx/3
+        case PA_10: case PB_0: case PC_8: 
+            return &pwm->CCR3;
+ 
+        // Channels 4 : PWMx/4
+        case PA_11: case PC_9: 
+            return &pwm->CCR4;
+    }
+    return NULL;
+}
+#endif
+
+
+
+#if defined (TARGET_NUCLEO_L152RE)
+__IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) {
+    switch (pin) {
+        // Channels 1 : PWMx/1
+        case PA_6:  case PB_4: case PB_12: case PB_13: case PC_6:
+            return &pwm->CCR1;
+        
+        // Channels 2 : PWMx/2
+        case PA_1: case PA_7: case PB_3: case PB_5: case PB_14: case PB_7: case PC_7:
+            return &pwm->CCR2;
+            
+        // Channels 3 : PWMx/3
+        case PA_2: case PB_0: case PB_8: case PB_10: case PC_8:
+            return &pwm->CCR3;
+ 
+        // Channels 4 : PWMx/4
+        case PA_3: case PB_1:case PB_9: case PB_11: case PC_9: 
+            return &pwm->CCR4;
+        default:
+            /* NOP */
+            break;
+    }
+    return NULL;
+}
+#endif
+
+ 
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac FastPWM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FastPWM.h	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,150 @@
+/*
+    .---.           _....._
+   /  p  `\     .-""`:     :`"-.
+   |__   - |  ,'     .     '    ',
+    ._>    \ /:      :     ;      :,
+     '-.    '\`.     .     :     '  \
+        `.   | .'._.' '._.' '._.'.  |
+          `;-\.   :     :     '   '/,__,
+          .-'`'._ '     .     : _.'.__.'
+         ((((-'/ `";--..:..--;"` \
+             .'   /           \   \
+       jgs  ((((-'           ((((-'
+       
+Yeah ASCII art turtle more fun than copyright stuff
+*/
+
+
+#include "mbed.h"
+
+#ifndef FASTPWM_H
+#define FASTPWM_H
+
+/** Library that allows faster and/or higher resolution PWM output
+  *
+  * Library can directly replace standard mbed PWM library.
+  *
+  * Contrary to the default mbed library, this library takes doubles instead of floats. The compiler will autocast if needed,
+  * but do take into account it is done for a reason, your accuracy will otherwise be limitted by the floating point precision.
+  */
+class FastPWM : public PwmOut {
+public:
+    /**
+    * Create a FastPWM object connected to the specified pin
+    *
+    * @param pin - PWM pin to connect to
+    * @param prescaler - Clock prescaler, -1 is dynamic (default), 0 is bit random, everything else normal
+    */
+    FastPWM(PinName pin, int prescaler = -1);
+    ~FastPWM(); 
+    
+    /**
+    * Set the PWM period, specified in seconds (double), keeping the pulsewidth the same.
+    */
+    void period(double seconds);
+    
+    /**
+    * Set the PWM period, specified in milli-seconds (int), keeping the pulsewidth the same.
+    */
+    void period_ms(int ms);
+    
+    /**
+    * Set the PWM period, specified in micro-seconds (int), keeping the pulsewidth the same.
+    */
+    void period_us(int us);
+    
+    /**
+    * Set the PWM period, specified in micro-seconds (double), keeping the pulsewidth the same.
+    */
+    void period_us(double us);
+    
+    /**
+    * Set the PWM period, specified in clock ticks, keeping _pulse width_ the same.
+    *
+    * This function can be used if low overhead is required. Do take into account the result is
+    * board (clock frequency) dependent, and this does not keep an equal duty cycle!
+    */
+    void period_ticks(uint32_t ticks);
+    
+    /**
+    * Set the PWM pulsewidth, specified in seconds (double), keeping the period the same.
+    */
+    void pulsewidth(double seconds);
+    
+    /**
+    * Set the PWM pulsewidth, specified in milli-seconds (int), keeping the period the same.
+    */
+    void pulsewidth_ms(int ms);
+    
+    /**
+    * Set the PWM pulsewidth, specified in micro-seconds (int), keeping the period the same.
+    */
+    void pulsewidth_us(int us);
+    
+    /**
+    * Set the PWM pulsewidth, specified in micro-seconds (double), keeping the period the same.
+    */
+    void pulsewidth_us(double us);
+    
+    /**
+    * Set the PWM period, specified in clock ticks, keeping the period the same.
+    *
+    * This function can be used if low overhead is required. Do take into account the result is
+    * board (clock frequency) dependent!
+    */
+    void pulsewidth_ticks(uint32_t ticks);
+    
+    /**
+    * Set the ouput duty-cycle, specified as a percentage (double)
+    *
+    * @param duty - A double value representing the output duty-cycle, specified as a percentage.  The value should lie between 0.0 (representing on 0%) and 1.0 (representing on 100%).
+    */
+    void write(double duty);
+    
+    /**
+    * Return the ouput duty-cycle, specified as a percentage (double)
+    *
+    * @param return - A double value representing the output duty-cycle, specified as a percentage.
+    */
+    double read( void );
+    
+    /**
+    * An operator shorthand for write()
+    */
+    FastPWM& operator= (double value);
+    
+    /**
+    * An operator shorthand for read()
+    */
+    operator double();
+    
+    /**
+    * Set the PWM prescaler
+    *
+    * The period of all PWM pins on the same PWM unit have to be reset after using this!
+    *
+    * @param value - The required prescaler. Special values: 0 = lock current prescaler, -1 = use dynamic prescaler
+    * @param return - The prescaler which was set (can differ from requested prescaler if not possible)
+    */
+    int prescaler(int value);
+    
+private:
+    void initFastPWM(void);
+    
+    uint32_t setPrescaler( uint32_t reqScale );
+    int calcPrescaler(uint64_t clocks);
+    uint32_t getPeriod( void );
+    
+    void updateTicks( uint32_t prescaler );
+    uint32_t bits;
+    
+    double _duty;
+    
+    double dticks, dticks_us;
+    int iticks_ms, iticks_us;
+    
+    bool dynamicPrescaler;
+    
+    void *fast_obj;
+};
+#endif
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac FastPWM_common.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FastPWM_common.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,108 @@
+#include "FastPWM.h"
+
+FastPWM::FastPWM(PinName pin, int prescaler) : PwmOut(pin) {
+    fast_obj = NULL;
+    initFastPWM();
+    this->prescaler(prescaler);
+    
+    //Set duty cycle on 0%, period on 20ms
+    period(0.02);
+    write(0);
+    
+
+}
+
+FastPWM::~FastPWM( void ) {
+    if (fast_obj != NULL)
+        delete(fast_obj);
+} 
+
+void FastPWM::period(double seconds) {
+    if (dynamicPrescaler)
+        calcPrescaler((uint64_t)(seconds * (double) SystemCoreClock));
+
+     period_ticks(seconds * dticks + 0.5);
+}
+
+void FastPWM::period_ms(int ms) {
+    if (dynamicPrescaler)
+        calcPrescaler(ms * (SystemCoreClock / 1000));
+        
+    period_ticks(ms * iticks_ms);
+}
+
+void FastPWM::period_us(int us) {
+    if (dynamicPrescaler)
+        calcPrescaler(us * (SystemCoreClock / 1000000));
+    
+    period_ticks(us * iticks_us);
+}
+
+void FastPWM::period_us(double us) {
+    if (dynamicPrescaler)
+        calcPrescaler((uint64_t)(us * (double)(SystemCoreClock / 1000000)));
+        
+    period_ticks(us * dticks_us + 0.5);
+}
+
+void FastPWM::pulsewidth(double seconds) {
+    pulsewidth_ticks(seconds * dticks + 0.5);
+}
+
+void FastPWM::pulsewidth_ms(int ms) {
+    pulsewidth_ticks(ms * iticks_ms);
+}
+
+void FastPWM::pulsewidth_us(int us) {
+    pulsewidth_ticks(us * iticks_us);
+}
+
+void FastPWM::pulsewidth_us(double us) {
+    pulsewidth_ticks(us * dticks_us + 0.5);
+}
+
+void FastPWM::write(double duty) {
+    _duty=duty;
+    pulsewidth_ticks(duty*getPeriod());
+}
+
+double FastPWM::read( void ) {
+    return _duty;
+    }
+    
+FastPWM & FastPWM::operator= (double value) {
+    write(value);
+    return(*this);
+    }
+    
+FastPWM::operator double() {
+    return _duty;
+}
+
+int FastPWM::prescaler(int value) {
+    int retval;
+    if (value == -1) {
+        dynamicPrescaler = true;
+        value = 0;
+    }
+    else
+        dynamicPrescaler = false;
+    
+    retval = setPrescaler(value);
+    updateTicks(retval);
+    return retval;
+}
+
+void FastPWM::updateTicks( uint32_t prescaler ) {
+    dticks = SystemCoreClock / (double)prescaler;
+    dticks_us = dticks / 1000000.0f;
+    iticks_us = (int)(dticks_us + 0.5);
+    iticks_ms = (int)(dticks_us * 1000.0 + 0.5);
+}
+
+int FastPWM::calcPrescaler(uint64_t clocks) {
+    uint32_t scale = (clocks >> bits) + 1;
+    uint32_t retval = setPrescaler(scale);
+    updateTicks(retval);
+    return retval;
+}     
\ No newline at end of file
diff -r 000000000000 -r 16be67f4d9ac main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,42 @@
+#include "mbed.h"
+#include "FastPWM.h"
+
+//DigitalOut gpo(D0);
+//DigitalOut ledr(D8); //PTA0 doesn't work
+DigitalOut ledl(D9); 
+
+
+DigitalIn but1(D6); //D6
+DigitalIn but2(D7); // Don't use D8
+AnalogIn potmeter(A0);
+FastPWM ledr(D3);
+
+float PwnPeriod = 1.0/5000.0;
+    
+
+int main()
+{
+    ledr.period(PwnPeriod);
+    
+    
+    
+    while (true) {
+   //     gpo = !gpo; // toggle pin
+       // led = !led; // toggle led
+        
+        ledr = potmeter.read();
+        wait(0.1f);
+        
+       
+        //ledr = 0;
+        
+        //if (but1 == false) { 
+          //ledr = !ledr;
+          //}
+          
+           //if (but2 == false) { 
+          //ledl = !ledl;
+          //}
+        
+        }
+    }
diff -r 000000000000 -r 16be67f4d9ac mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Sep 19 16:52:01 2017 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/mbed_official/code/mbed/builds/675da3299148
\ No newline at end of file