Esempio n. 1
0
/**
 * \brief Configure output parameters of a group of pins
 *
 * Sets the output configuration and drive strength, of or a set of GPIO pins
 * for a set of GPIO pins in output mode.
 *
 * @param[in] gpioport GPIO block register address base @ref gpio_reg_base
 * @param[in] otype Output driver configuration (@ref gpio_output_type) \n
 *		    - GPIO_OTYPE_PP -- Configure pin driver as push-pull \n
 *		    - GPIO_OTYPE_OD -- Configure pin driver as open drain
 * @param[in] drive Pin drive strength (@ref gpio_drive_strength) \n
 *		    - GPIO_DRIVE_2MA -- 2mA drive \n
 *		    - GPIO_DRIVE_4MA -- 4mA drive \n
 *		    - GPIO_DRIVE_8MA -- 8mA drive \n
 *		    - GPIO_DRIVE_8MA_SLEW_CTL -- 8mA drive with slew rate
 *						 control
 * @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified
 *		    by OR'ing then together
 */
void gpio_set_output_config(uint32_t gpioport, enum gpio_output_type otype,
			     enum gpio_drive_strength drive, uint8_t gpios)
{
	if (otype == GPIO_OTYPE_OD) {
		GPIO_ODR(gpioport) |= gpios;
	} else {
		GPIO_ODR(gpioport) &= ~gpios;
	}

	/*
	 * Setting a bit in the GPIO_DRxR register clears the corresponding bit
	 * in the other GPIO_DRyR registers, and vice-versa.
	 */
	switch (drive) {
	case GPIO_DRIVE_8MA_SLEW_CTL:
		GPIO_DR8R(gpioport) |= gpios;
		GPIO_SLR(gpioport) |= gpios;
		break;
	case GPIO_DRIVE_8MA:
		GPIO_DR8R(gpioport) |= gpios;
		GPIO_SLR(gpioport) &= ~gpios;
		break;
	case GPIO_DRIVE_4MA:
		GPIO_DR4R(gpioport) |= gpios;
		break;
	case GPIO_DRIVE_2MA:	/* Fall through */
	default:
		GPIO_DR2R(gpioport) |= gpios;
		break;
	}
}
Esempio n. 2
0
void leds_arch_set(unsigned char leds)
{
	u32 reg = GPIO_ODR(LED_DISCO_PORT);
	reg &= ~(LED_DISCO_PIN_GREEN | LED_DISCO_PIN_BLUE);
	if (leds & LEDS_GREEN) {
		reg |= LED_DISCO_PIN_GREEN;
	}
	if (leds & LEDS_BLUE) {
		reg |= LED_DISCO_PIN_BLUE;
	}
	GPIO_ODR(LED_DISCO_PORT) = reg;
}
Esempio n. 3
0
/**
 * Test end-switches &
 * @param num    - motor number
 * @param curpos - end-switches data for motor
 * @return 0 if we can move further, 1 if there's the end
 */
uint8_t test_stages_endpos(uint8_t num, uint8_t curpos){
	if(curpos == 0 || num < 3) return 0;
	// end-switches numbers for stages
	const uint8_t stage_plus[2] = {STAGE_CHECK(3, PLUS), STAGE_CHECK(4, PLUS)};
	const uint8_t stage_minus[2] = {STAGE_CHECK(3, MINUS), STAGE_CHECK(4, MINUS)};
	uint8_t negative_dir = 0;
	if((uint16_t)(GPIO_ODR(MOTOR_DIR_PORT) & MOTOR_DIR_PIN(num))){ // negative direction
		negative_dir = 1;
	}
	num -= 3; // convern num to index in arrays
	if(stage_plus[num] == curpos){ // we are on "+" end-switch
		if(!negative_dir){ // and wanna move to "+"
			ERR("End-switch +\n");
			return 1;
		}
	}else if(stage_minus[num] == curpos){ // we are on "-" end-switch
		if(negative_dir){ // and wanna move to "-"
			ERR("End-switch -\n");
			return 1;
		}
	}else{ // error: WTF is going up? curpos != 2 or 1
		ERR("Wrong current position: ");
		if(mode == BYTE_MODE){
			print_int(curpos, lastsendfun);
			lastsendfun('\n');
		}
		return 1;
	}
	return 0;
}
Esempio n. 4
0
void jack_setup(const struct jack_t *jack, volatile struct jacks_machine_t *machine)
{
	// turn on gpios and modes for the pins...
	gpio_set_mode(jack->en_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, jack->en_pin);
	// Explictly pull down.  This burns ~66uA per jack! // FIXME - make sure this all works properly!
	GPIO_ODR(jack->en_port) &= ~(jack->en_pin);
	gpio_set_mode(jack->power_port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, jack->power_pin);
	gpio_set_mode(jack->val_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, jack->val_pin);
	machine->step = jack_machine_step_off;
	machine->last_read_millis = 0;
	machine->step_entry_millis = 0;
	machine->jack = jack;
}
Esempio n. 5
0
int main(void){
	uint8_t *string; // string from UART2 & pointer to last full GPS answer
	uint8_t lastGPSans[UART_BUF_DATA_SIZE] = {0};
	int i;
	rcc_clock_setup_in_hse_8mhz_out_72mhz();
	// init systick (1ms)
	systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz
	systick_set_reload(STK_RVR_DEFAULT_VAL); // 9000 pulses: 1kHz
	systick_interrupt_enable();
	systick_counter_enable();

	GPIO_init();
/*
	// if PC11 connected to usb 1.5kOhm pull-up through transistor
	rcc_periph_clock_enable(RCC_GPIOC);
	gpio_set(GPIOC, GPIO11);
	gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
		      GPIO_CNF_OUTPUT_PUSHPULL, GPIO11);
*/
	usb_disconnect(); // turn off USB while initializing all
	usbkeybrd_setup();
	UART_init(USART2); // init GPS UART
	#ifdef ULTRASONIC
	tim2_init(); // ultrasonic timer
	#endif
	//tim4_init(); // beeper timer
/*
	for (i = 0; i < 0x80000; i++)
		__asm__("nop");
*/
	usb_connect(); // turn on USB
	GPS_send_start_seq();
	init_adc_sensor();
	// time (in milliseconds from MCU start) for trigger, adc & power LED status; power LED blink interval
	// blink time: (1000ms - powerLEDblink) - LED ON
	// GPSstatus_tm - timer for blinking by GPS LED if there's no GPS after timer is good
	// powerLEDblink - LED blinking time (depends on power level)
	uint32_t usbkbrdtm = 0, trigrtm = 0, powerLEDtm = 0, GPSstatus_tm = 0, powerLEDblink = 1;
	// istriggered == 1 after ANY trigger's event (set it to 1 at start to prevent false events)
	// GPSLEDblink - GPS LED blinking
	uint8_t  istriggered = 1, GPSLEDblink = 0;
	iwdg_set_period_ms(50); // set watchdog timeout to 50ms
	iwdg_start();
	while(1){
		if(Timer == 500) // turn off PPS LED after 500ms
			gpio_set(LEDS_Y_PORT, LEDS_Y2_PIN);
		poll_usbkeybrd();
		if(usbkbrdtm != msctr){ // process USB not frequently than once per 1ms
			process_usbkbrd();
			usbkbrdtm = msctr;
		}
		#ifdef ULTRASONIC
		poll_ultrasonic();
		#endif
		poll_ADC();
		if((string = check_UART2())){
			memcpy(lastGPSans, string, UART_BUF_DATA_SIZE);
			GPS_parse_answer(string);
		}
/*
if(msctr - trigrtm > 3000){
	trigrtm = msctr;
	for(i = 0; i < 3; ++i){ // IR or Laser
		P("ADC");
		put_char_to_buf('0' + i);
		P(" val: ");
		print_int(ADC_value[i]);
		newline();
	}
}*/
		if(istriggered){ // there was any trigger event
			if(msctr - trigrtm > TRIGGER_DELAY || trigrtm > msctr){ // turn off LED & beeper
				istriggered = 0;
				gpio_set(LEDS_Y_PORT, LEDS_Y1_PIN);
				gpio_set(BEEPER_PORT, BEEPER_PIN);
				trigger_ms = DIDNT_TRIGGERED;
				adc_ms[0] = DIDNT_TRIGGERED;
				adc_ms[1] = DIDNT_TRIGGERED;
				#ifdef ULTRASONIC
				ultrasonic_ms = DIDNT_TRIGGERED;
				#endif
			}
		}else{
			if(trigger_ms != DIDNT_TRIGGERED){ // Control Button pressed
				trigrtm = msctr;
				istriggered = 1;
				P("Button time: ");
				print_time(&trigger_time, trigger_ms);
				if(*lastGPSans){
					P("GPS last message: ");
					send_msg((char*)lastGPSans);
					newline();
				}
			}
			for(i = 0; i < 2; ++i){ // IR or Laser
				uint32_t adcms = adc_ms[i];
				if(adcms == DIDNT_TRIGGERED) continue;
				int32_t timediff = Timer - adcms;
				if(timediff < 0) timediff += 1000;
				// pause for noice removal
				if(timediff > ADC_NOICE_TIMEOUT && !istriggered){
					trigrtm = msctr;
					istriggered = 1;
					if(i == 0) P("Infrared");
					else P("Laser");
				/*	P(" trig val: ");
					print_int(ADC_trig_val[i]);*/
					put_char_to_buf(' ');
					//P(" time: ");
					print_time(&adc_time[i], adcms);
				}
			}
			#ifdef ULTRASONIC
			if(ultrasonic_ms != DIDNT_TRIGGERED && !istriggered){
				trigrtm = msctr;
				istriggered = 1;
				P("Ultrasonic time: ");
				print_time(&ultrasonic_time, ultrasonic_ms);
			}
			#endif
			if(istriggered){ // turn on Y1 LED
				gpio_clear(LEDS_Y_PORT, LEDS_Y1_PIN);
				//beep(); // turn on beeper
				gpio_clear(BEEPER_PORT, BEEPER_PIN);
			}
		}
		// check 12V power level (once per 1ms)
		if(powerLEDtm != msctr){
			uint16_t _12V = ADC_value[2];
			if(_12V < GOOD_POWER_LEVEL){ // insufficient power? - blink LED R2
				// calculate blink time only if there's [was] too low level
				if(_12V < POWER_ALRM_LEVEL || powerLEDblink){
					powerLEDblink = GOOD_POWER_LEVEL - _12V;
					// critical level: power LED is almost OFF
					if(_12V < POWER_CRITICAL_LEVEL) powerLEDblink = 990;
					//if(powerLEDblink > 990) powerLEDblink = 990; // shadow LED not more than 0.99s
				}
			}else{ // power restored - LED R2 shines
				if(powerLEDblink){
					gpio_clear(LEDS_R_PORT, LEDS_R2_PIN);
					powerLEDblink = 0;
				}
				powerLEDtm = msctr;
			}
			if(powerLEDblink){
				if(GPIO_ODR(LEDS_R_PORT) & LEDS_R2_PIN){ // LED is OFF
					if(msctr - powerLEDtm > powerLEDblink || msctr < powerLEDtm){ // turn LED ON
						powerLEDtm = msctr;
						gpio_clear(LEDS_R_PORT, LEDS_R2_PIN);
					}
				}else{
					if(msctr - powerLEDtm > (1000 - powerLEDblink) || msctr < powerLEDtm){ // turn LED OFF
						powerLEDtm = msctr;
						gpio_set(LEDS_R_PORT, LEDS_R2_PIN);
					}
				}
			}
		}
		// check GPS status to turn on/off GPS LED
		if(current_time.H < 24){ // timer OK
			if((GPS_status != GPS_VALID) || need_sync){
				GPSLEDblink = 1;
			}else{
				GPSLEDblink = 0;
				if((GPIO_ODR(LEDS_G_PORT) & LEDS_G1_PIN) == 0)
					gpio_clear(LEDS_G_PORT, LEDS_G1_PIN); // turn ON G1 LED
			}
			if(GPSLEDblink){
				if(msctr - GPSstatus_tm > 500 || msctr < GPSstatus_tm){
					GPSstatus_tm = msctr;
					if(GPIO_ODR(LEDS_G_PORT) & LEDS_G1_PIN){ // LED is OFF
						gpio_clear(LEDS_G_PORT, LEDS_G1_PIN);
					}else{
						gpio_set(LEDS_G_PORT, LEDS_G1_PIN);
					}
				}
			}
		}else{ // something bad with timer - turn OFF G1 LED
			if(!(GPIO_ODR(LEDS_G_PORT) & LEDS_G1_PIN)){
				gpio_set(LEDS_G_PORT, LEDS_G1_PIN);
			}
		}
	iwdg_reset(); // reset watchdog
	}
}
Esempio n. 6
0
/* On rare occassions, the I2C device will get confused, either because we missed
 * a timing requirement, or it is just stupid.  Regardless, it holds SDA low waiting
 * for some unknown action from the master.  This keeps the bus BUSY and prevents
 * any further communication.  This condition is fixed by manually clocking SCL
 * until SDA is released by the slave.  As far as it is concerned, we just completed
 * a normal transaction. */
static int i2c_force_clear_busy(struct i2c_dev *i2c) {
    if (!i2c) {
        return -1;
    }

    int count = 10000;

    switch (i2c->port) {
    case 1:
        /* Set pins to output/input */
        gpio_moder(GPIOB, I2C1_SCL, GPIO_MODER_OUT);
        gpio_moder(GPIOB, I2C1_SDA, GPIO_MODER_IN);

        /* Toggle clock until bus no longer busy */
        while (!(*GPIO_IDR(GPIOB) & GPIO_IDR_PIN(I2C1_SDA))) {
            if (!count--) {
                /* Out of time, perhaps the last ditch effort will save us. */
                break;
            }

            /* Toggle clock */
            *GPIO_ODR(GPIOB) ^= GPIO_ODR_PIN(I2C1_SCL);
            for (volatile int delay = 100; delay > 0; delay--);
        }

        gpio_moder(GPIOB, I2C1_SCL, GPIO_MODER_ALT);
        gpio_moder(GPIOB, I2C1_SDA, GPIO_MODER_ALT);
        for (volatile int delay = 100; delay > 0; delay--);

        break;
    case 2:
        /* Set pins to output/input */
        gpio_moder(GPIOB, I2C2_SCL, GPIO_MODER_OUT);
        gpio_moder(GPIOB, I2C2_SDA, GPIO_MODER_IN);

        /* Toggle clock until SDA raised */
        while (!(*GPIO_IDR(GPIOB) & GPIO_IDR_PIN(I2C2_SDA))) {
            if (!count--) {
                /* Out of time, perhaps the last ditch effort will save us. */
                break;
            }

            /* Toggle clock */
            *GPIO_ODR(GPIOB) ^= GPIO_ODR_PIN(I2C2_SCL);
            for (volatile int delay = 100; delay > 0; delay--);
        }

        gpio_moder(GPIOB, I2C2_SCL, GPIO_MODER_ALT);
        gpio_moder(GPIOB, I2C2_SDA, GPIO_MODER_ALT);
        for (volatile int delay = 100; delay > 0; delay--);

        break;
    default:
        return -1;
    }

    /* Make sure the peripheral recognizes that the bus is now free */
    if (*I2C_SR2(i2c->port) & I2C_SR2_BUSY) {
        /* Last ditch effort */
        if (i2c_reset(i2c) || (*I2C_SR2(i2c->port) & I2C_SR2_BUSY)) {
            /* Failed to reset */
            printk("I2C: BUSY flag failed to clear.\r\nI2C: I have tried everything I know :(. At this point, reset is your best option.\r\n");
            return -1;
        }
    }

    return 0;
}
Esempio n. 7
0
/** @brief Write to a Port

Write a value to the given GPIO port.

@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] data Unsigned int16. The value to be written to the GPIO port.
*/
void gpio_port_write(u32 gpioport, u16 data)
{
	GPIO_ODR(gpioport) = data;
}
Esempio n. 8
0
/** @brief Toggle a Group of Pins

Toggle one or more pins of the given GPIO port. This is not an atomic operation.

@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
             If multiple pins are to be changed, use logical OR '|' to separate them.
*/
void gpio_toggle(u32 gpioport, u16 gpios)
{
	GPIO_ODR(gpioport) ^= gpios;
}
Esempio n. 9
0
void tim2_isr ( void ) {

  //TIM2_SR &= ~TIM_SR_UIF;    //clearing update interrupt flag
  TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */

  /* ISR HAS TO DO SOMRTHING A LITTLE HEAVY
  // https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Problem%20with%20DMA-USART%20Rx%20on%20STM32F407VG&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=148
  // ie: after setting SR, you need to pause read/writes
  // ie: if the ISR is too quick, there may be a spurious re-invocation (tail chain), so you need to do a little something to avoid cpu race condition
  // -- another way to do it, is to do a SR read (which blocks until its 'set' finishes), thus stalling until the ISR is 'done':
  //void SPI2_IRQHandler(void)
  //{
  //  volatile unsigned int dummy;
  //  ... some code...
  //  SPI2_CR2 &= ~SPI_CR2_RXNEIE;  // Turn off RXE interrupt enable
  //  ...some code...
  //  dummy = SPI2_SR; // Prevent tail-chaining.
  //  return;
  //}
  */

  // VGA line logic
  //
  // line1
  // line2
  // ..
  // line600
  // front porch blank            1 line
  // vsync pulse                  4 lines
  // back porch blank             23 lines
  // \__> back to top
  //

  // handle vblank stuff
  // - front porch, leads to
  //  - vsync, leads to
  //   - back porch
  // vsync is normally HIGH, but goes to LOW during pulse
  done_sync = 0;
  if ( front_porch_togo ) {
    front_porch_togo --;
    vblank_active();

    if ( ! front_porch_togo ) { // on exit front porch, start vsync pulse
      vsync_go_low();
      vsync_togo = 2;
    }

    done_sync = 1;
    goto hsync;
    //return; // do nothing..
  }

  if ( vsync_togo ) {
    vsync_togo --;

    if ( ! vsync_togo ) { // on exit vsync pulse, start back porch
      vsync_go_high();
      back_porch_togo = 33;
    }

    done_sync = 1;
    goto hsync;
    //return;
  }

  if ( back_porch_togo ) {
    back_porch_togo --;

    if ( ! back_porch_togo ) {
      line_count = 1;
      vblank_inactive();
    }

    done_sync = 1;
    goto hsync;
    //return; // do nothing..
  }

 hsync:
  // hsync period..
  // should use timer/interupt to 'end the line' and go hsync?
  //

  /* horiz Front Porch */
  i = 16;
  while ( i-- ) {
    __asm__("nop");
  }

  /* Horizontal Sync pulse (low)  */
  hsync_go_low();
  i = 103;
  while ( i-- ) {
    __asm__("nop");
  }

  /* horiz Back Porch */
  hsync_go_high();
  i = 50;
  while ( i-- ) {
    __asm__("nop");
  }

  if ( done_sync ) {
    return;
  }

  // center horizontally; burn some time so image isn't fully on left
#ifndef VGA_DMA
  i = 40;
  while ( i-- ) {
    __asm__("nop");
  }
#endif

  // actual line data
  //
  // line data on/off/on/off..
  // off for hsync/porch business!

#if RENDER_ATALL // pull from array

  // center vertically .. dma seems blurry with this so only for non-DMA
#if 1
  if ( line_count < 40 ) {
    goto scanline_done;
  }
  i = (line_count-40)/2;
#else
  i = (line_count)/2;
#endif

  // done?
  if ( i >= FBHEIGHT ) {
    goto scanline_done;
  }

#ifdef VGA_DMA
  uint8_t *p = fb_active + ( i * FBWIDTH );

  dma_memcpy ( p, (unsigned char*) &(GPIO_ODR(GPIOC)) /*&GPIOC->ODR*/, FBWIDTH, DMA_MEMCPY_INCSRC );

 scanline_done:
#else

#define OLD_EMIT_PIXEL()      \
  GPIO_ODR(GPIOC) = *p++; \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");         \
  __asm__("nop");
 // 11 NOP's is pretty ideal

 unsigned char c;
#define EMIT_PIXEL()      \
  c = *p++;               \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;    \
  GPIO_ODR(GPIOC) = c;

  // paint the image
  uint8_t *p = fb_active + ( i * FBWIDTH );

  i = (FBWIDTH) / 16;
  while ( i-- ) {

    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL(); // 8

    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL();
    EMIT_PIXEL(); // 8

  }

  // disable all colour pins (dma does it itself in its isr)
  //GPIO_BSRR(GPIOC) = 0x00;

 scanline_done:
  gpio_clear ( GPIOC, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | GPIO5 );

#endif // DMA?

#endif

  // entering vblank period?
  //

  if ( line_count > VISIBLE_ROWS ) {
    front_porch_togo = 10;
    _vblank_count++; // entering vblank
    return; // entering front porch
  }

  line_count++;
}
Esempio n. 10
0
void gpio_port_write(uint32_t gpioport, uint16_t data)
{
	GPIO_ODR(gpioport) = data;
}
Esempio n. 11
0
void gpio_toggle(uint32_t gpioport, uint16_t gpios)
{
	GPIO_ODR(gpioport) ^= gpios;
}
Esempio n. 12
0
static void cs_low(void) {
    *GPIO_ODR(GPIOB) &= ~(GPIO_ODR_PIN(0));
}
Esempio n. 13
0
static void cs_high(void) {
    *GPIO_ODR(GPIOB) |= GPIO_ODR_PIN(0);
}