mirowire_master_address_size=address_size;// save address size
mirowire_master_organization_x16=organization_x16;// save organisation
// setup GPIO
rcc_periph_clock_enable(RCC_GPIO(MICROWIRE_MASTER_SDO_PORT));// enable clock for GPIO domain for SDO signal
gpio_set_mode(GPIO(MICROWIRE_MASTER_SDO_PORT),GPIO_MODE_OUTPUT_10_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,GPIO(MICROWIRE_MASTER_SDO_PIN));// set SDO signal as output (controlled by the master)
gpio_clear(GPIO(MICROWIRE_MASTER_SDO_PORT),GPIO(MICROWIRE_MASTER_SDO_PIN));// SDO is idle low
rcc_periph_clock_enable(RCC_GPIO(MICROWIRE_MASTER_SDI_PORT));// enable clock for GPIO domain for SDI signal
gpio_set_mode(GPIO(MICROWIRE_MASTER_SDI_PORT),GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT,GPIO(MICROWIRE_MASTER_SDI_PIN));// set SDI signal as output (controlled by the slave)
rcc_periph_clock_enable(RCC_GPIO(MICROWIRE_MASTER_SCK_PORT));// enable clock for GPIO domain for SCK signal
gpio_set_mode(GPIO(MICROWIRE_MASTER_SCK_PORT),GPIO_MODE_OUTPUT_10_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,GPIO(MICROWIRE_MASTER_SCK_PIN));// set SCK signal as output (controlled by the master)
gpio_clear(GPIO(MICROWIRE_MASTER_SCK_PORT),GPIO(MICROWIRE_MASTER_SCK_PIN));// SCK is idle low
// setup timer to generate timing for the signal
rcc_periph_clock_enable(RCC_TIM(MICROWIRE_MASTER_TIMER));// enable clock for timer domain
timer_reset(TIM(MICROWIRE_MASTER_TIMER));// reset timer state
timer_set_mode(TIM(MICROWIRE_MASTER_TIMER),TIM_CR1_CKD_CK_INT,TIM_CR1_CMS_EDGE,TIM_CR1_DIR_UP);// set timer mode, use undivided timer clock, edge alignment (simple count), and count up
uint16_tprescaler=rcc_ahb_frequency/(frequency*2)/(uint32_t)(1<<16)+1;// calculate prescaler for most accurate timing for this speed
timer_set_prescaler(TIM(MICROWIRE_MASTER_TIMER),prescaler-1);// set calculated prescaler
uint16_tperiod=(rcc_ahb_frequency/prescaler)/(frequency*2);// calculate period to get most accurate timing based on the calculated prescaler
timer_set_period(TIM(MICROWIRE_MASTER_TIMER),period-1);// set calculated period
timer_update_on_overflow(TIM(MICROWIRE_MASTER_TIMER));// only use counter overflow as UEV source (use overflow as timeout)
SCB_SCR|=SCB_SCR_SEVEONPEND;// enable wake up on event (instead of using ISR)
timer_enable_irq(TIM(MICROWIRE_MASTER_TIMER),TIM_DIER_UIE);// enable update interrupt for timer
}
/** wait for clock tick used to synchronise communication */
staticvoidmicrowire_master_wait_clock(void)
{
while(!timer_get_flag(TIM(MICROWIRE_MASTER_TIMER),TIM_SR_UIF)){// wait for timer overflow event for clock change
__asm__("wfe");// go to sleep and wait for event
}
timer_clear_flag(TIM(MICROWIRE_MASTER_TIMER),TIM_SR_UIF);// clear timer flag
nvic_clear_pending_irq(NVIC_TIM_IRQ(MICROWIRE_MASTER_TIMER));// clear IRQ flag (else event doesn't wake up)
}
/** send bit over microwire
*@param[in]bitbittosend(true='1',false='0')
*/
staticvoidmicrowire_master_send_bit(boolbit)
{
if(bit){
gpio_set(GPIO(MICROWIRE_MASTER_SDO_PORT),GPIO(MICROWIRE_MASTER_SDO_PIN));// set '1' on output
}else{
gpio_clear(GPIO(MICROWIRE_MASTER_SDO_PORT),GPIO(MICROWIRE_MASTER_SDO_PIN));// set '0' on output
}
microwire_master_wait_clock();// wait for clock timing
gpio_set(GPIO(MICROWIRE_MASTER_SCK_PORT),GPIO(MICROWIRE_MASTER_SCK_PIN));// make rising edge for slave to sample
microwire_master_wait_clock();// keep output signal stable while clock is high
gpio_clear(GPIO(MICROWIRE_MASTER_SCK_PORT),GPIO(MICROWIRE_MASTER_SCK_PIN));// put clock back to idle
}
/** initialize microwire communication and send header (with leading start bit '1')