Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
main.cpp
- Committer:
- bgrissom
- Date:
- 2014-08-08
- Revision:
- 6:e4da8955cf65
- Parent:
- 5:9a662dec2ddb
File content as of revision 6:e4da8955cf65:
#include "mbed.h"
#define OK (0)
#define ERROR (-1)
#define PIN_41 PB_5
#define PIN_46 PB_9
#define PIN_32 PA_11
#define PIN_20 PB_2
#define HEX_ONE_THOUSAND (0x03E8)
DigitalOut ENA(PIN_41);
DigitalOut ENB(PIN_46);
DigitalOut ENC(PIN_32);
DigitalOut EnSclk(PIN_20);
// Forward Declarations
void pwmout_period_ns(pwmout_t* obj, int us);
int cmd_S0(uint16_t value);
void cmd_S1(void);
// Globals
bool gSpiMode = false;
SPI* gSpiPtr = NULL;
DigitalOut gbbTRANS(PA_4); // Global bit bang TRANS (data) line
const int SCLK_ENABLED = 0;
int main() {
ENA = 1;
ENB = 1;
ENC = 1;
EnSclk = SCLK_ENABLED;
// NOTE: 24MHz is half the 48MHz clock rate. The PWM registers
// seem to only allow 24MHz at this point, so I'm matching
// the SPI bus speed to be the same.
//
// 1/24MHz => 1/(24*10^6) => 41.6*10^-9 second period,
// which means 41.6ns period and 20.8ns pulse width at
// 50% duty cycle (which seems to be right for the SPI clock
// line as well as a reasonable choice for the PWM line).
// BAG ORIG: gbbTRANS = 1; // Start with TRANS high. It acts like a SPI slave select
// that is active-low.
gbbTRANS = 0;
// PWMCLK
pwmout_t outs;
pwmout_init(&outs, PB_4);
pwmout_period_ns(&outs, 2); // 24 MHz (not very clean on the scope)
// pwmout_period_ns(&outs, 40); // 1.2 MHz on the scope
// Very slow! pwmout_period_us(&outs, 2);
pwmout_write(&outs, 0.5f);
int ret = OK; // Return value
int i = 0;
printf("17:10\n");
//while (1) {
for (i=0; i<400; i++) {
ret = cmd_S0(0x0900);
// ORIG: ret = cmd_S0(0xFFFF);
if (ret != OK) {
printf("ERROR cmd_S0()\n");
return ERROR;
}
}
cmd_S1();
//}
}
// S0 Command:
// Needs only SCK and SIN (which are SPI_SCK and SPI_MOSI respectively).
// This is because TRANS can be 0 for this command according to the datasheet.
int cmd_S0(uint16_t value) {
// Command S0 and S1 share the same clock line, so we need to be
// careful which mode we are in. This avoids re-initializing these
// pins if we are already in SPI mode.
// WARNING: Re-initializing every time makes the MOSI line dirty and
// is wasteful for the CPU.
if ( gSpiMode == false &&
gSpiPtr == NULL)
{
// We are not using MISO, this is a one-way bus
gSpiPtr = new SPI(SPI_MOSI, NC, SPI_SCK);
if (gSpiPtr == NULL) {
printf("ERROR: Could not allocate SPI\n");
return ERROR;
}
// Note: Polarity and phase are both 0 for the TC62D723FNG
// For a graphical reminder on polarity and phase, visit:
// http://www.eetimes.com/document.asp?doc_id=1272534
gSpiPtr->format(16, 0);
// gSpiPtr->frequency(1000000); // 1.5 MHz on the scope
gSpiPtr->frequency(24000000); // 24 MHz
gSpiMode = true;
}
gbbTRANS = 0; // Like an SPI slave select
gSpiPtr->write(value);
gbbTRANS = 1; // Like an SPI slave select
// LONGTERM OPTIMIZATION: Evan suggests setting it
// wait_us(1);
// gbbTRANS = 0; // Set back low
return OK;
}
void cmd_S1(void) {
int i = 0;
int j = 0;
gbbTRANS = 0; // FIXME
if ( gSpiMode == true &&
gSpiPtr != NULL)
{
delete gSpiPtr;
gSpiPtr = NULL;
gSpiMode = false;
}
DigitalOut bbSCK (D13); // bit bang clock
bbSCK = 0; // Start off/low
gbbTRANS = 1; // Set high
// Loop 6 times = 3 clock cycles
for (j=0; j<6; j++) { // Always use an even number here!
// The order of these two lines matter!
i == 0 ? i = 1 : i = 0; // Toggle i
i == 0 ? bbSCK = 0 : bbSCK = 1; // Set SCK to the same value as i
}
gbbTRANS = 0; // Set low
}
/* USED FOR THE F030 BOARD
// This code is based off:
// mbed/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/pwmout_api.c pwmout_period_us()
void pwmout_period_ns_NOT_USED(pwmout_t* obj, int us) {
TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
float dc = pwmout_read(obj);
TIM_Cmd(tim, DISABLE);
obj->period = us;
TIM_TimeBaseStructure.TIM_Period = obj->period - 1;
// Orig code: TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
TIM_TimeBaseStructure.TIM_Prescaler = 0; // BAG 1 ns tick (?)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(tim, &TIM_TimeBaseStructure);
// Set duty cycle again
pwmout_write(obj, dc);
TIM_ARRPreloadConfig(tim, ENABLE);
TIM_Cmd(tim, ENABLE);
}
*/
static TIM_HandleTypeDef TimHandleBAG;
void pwmout_write_BAG(pwmout_t* obj, float value) {
TIM_OC_InitTypeDef sConfig;
int channel = 0;
int complementary_channel = 0;
TimHandleBAG.Instance = (TIM_TypeDef *)(obj->pwm);
if (value < (float)0.0) {
value = 0.0;
} else if (value > (float)1.0) {
value = 1.0;
}
obj->pulse = (uint32_t)((float)obj->period * value);
// Configure channels
sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.Pulse = obj->pulse;
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
sConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
switch (obj->pin) {
// Channels 1
case PA_2:
case PA_4:
case PA_6:
case PA_7:
case PA_8:
case PB_1:
case PB_4:
case PB_8:
case PB_9:
case PB_14:
case PC_6:
channel = TIM_CHANNEL_1;
break;
// Channels 1N
case PA_1:
case PB_6:
case PB_7:
case PB_13:
channel = TIM_CHANNEL_1;
complementary_channel = 1;
break;
// Channels 2
case PA_3:
case PA_9:
case PB_5:
case PB_15:
case PC_7:
channel = TIM_CHANNEL_2;
break;
// Channels 3
case PA_10:
case PB_0:
case PC_8:
channel = TIM_CHANNEL_3;
break;
// Channels 4
case PA_11:
case PC_9:
channel = TIM_CHANNEL_4;
break;
default:
return;
}
HAL_TIM_PWM_ConfigChannel(&TimHandleBAG, &sConfig, channel);
if (complementary_channel) {
HAL_TIMEx_PWMN_Start(&TimHandleBAG, channel);
} else {
HAL_TIM_PWM_Start(&TimHandleBAG, channel);
}
}
void pwmout_period_ns(pwmout_t* obj, int us) {
TimHandleBAG.Instance = (TIM_TypeDef *)(obj->pwm);
float dc = pwmout_read(obj);
__HAL_TIM_DISABLE(&TimHandleBAG);
// Update the SystemCoreClock variable
SystemCoreClockUpdate();
TimHandleBAG.Init.Period = us - 1;
// BAG Orig: TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
TimHandleBAG.Init.Prescaler = 0; // BAG 1 ns tick (?)
TimHandleBAG.Init.ClockDivision = 0;
TimHandleBAG.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_PWM_Init(&TimHandleBAG);
// Set duty cycle again
pwmout_write_BAG(obj, dc);
// Save for future use
obj->period = us;
__HAL_TIM_ENABLE(&TimHandleBAG);
}