Ejemplo n.º 1
0
int I2C_init( void ) {

  twi_options_t opt;
  twi_slave_fct_t twi_slave_fct;
  int status;
  double total = 0;

  // Initialize and enable interrupt
  irq_initialize_vectors();
  cpu_irq_enable();

  // TWI gpio pins configuration
  gpio_enable_module(TWI_GPIO_MAP, sizeof(TWI_GPIO_MAP) / sizeof(TWI_GPIO_MAP[0]));
  
  // initialize the interrupt flag for alerting the Pi of new data (TWI = Three Wire Interface for us)
  ioport_enable_pin(I2C_FLAG);
  ioport_set_pin_dir(I2C_FLAG,IOPORT_DIR_OUTPUT);
  ioport_set_pin_level(I2C_FLAG,false);

  // options settings
  opt.pba_hz = FOSC0;
  opt.speed = TWI_SPEED;
  opt.chip = EEPROM_ADDRESS;

  // initialize TWI driver with options
  twi_slave_fct.rx = &twi_slave_rx;
  twi_slave_fct.tx = &twi_slave_tx;
  twi_slave_fct.stop = &twi_slave_stop;
  status = twi_slave_init(&AVR32_TWI, &opt, &twi_slave_fct );
 
  return (&s_memory[0] );
}
Ejemplo n.º 2
0
int main()
{
	DDRB = 0x20;
	PORTC = 1 << 4 | 1 << 5;
	stdout = &mystdout;
	stdin = &mystdin;

	uart_init();
	puts("Slave Transmit!");
	
	twi_slave_init(0x08);
	printf("Enter char to send: ");
	while (1)
	{
		char c = getchar();
		twi_write(c);
		printf("Status: %x\n", TW_STATUS);

		if (TW_STATUS != TW_ST_DATA_ACK)
			break;
		PINB = 0x20;
	}

	puts("Disconnected");
	return 0;
}
Ejemplo n.º 3
0
u8 init_slave(void) {
  static twi_slave_fct_t twi_slave_fct;
  opt.pba_hz = FPBA_HZ;
  opt.speed = TWI_SPEED;
  opt.chip = addr;
  twi_slave_fct.rx = &slave_rx;
  twi_slave_fct.tx = &slave_tx;
  twi_slave_fct.stop = &slave_stop;
  return twi_slave_init(&AVR32_TWI, &opt, &twi_slave_fct );
}
Ejemplo n.º 4
0
/**
 * \brief Application entry point for TWI Slave example.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	uint32_t i;

	/* Initialize the SAM system */
	sysclk_init();

#if (SAM4S || SAM4E)
	/* Select PB4 and PB5 function, this will cause JTAG discconnect */
	REG_CCFG_SYSIO |= CCFG_SYSIO_SYSIO4;
	REG_CCFG_SYSIO |= CCFG_SYSIO_SYSIO5;
#endif

	/* Initialize the board */
	board_init();

	/* Initialize the console UART */
	configure_console();

	/* Output example information */
	puts(STRING_HEADER);

#if (SAMG55)
	/* Enable the peripheral and set TWI mode. */
	flexcom_enable(BOARD_FLEXCOM_TWI);
	flexcom_set_opmode(BOARD_FLEXCOM_TWI, FLEXCOM_TWI);
#else
	/* Enable the peripheral clock for TWI */
	pmc_enable_periph_clk(BOARD_ID_TWI_SLAVE);
#endif

	for (i = 0; i < MEMORY_SIZE; i++) {
		emulate_driver.uc_memory[i] = 0;
	}
	emulate_driver.us_offset_memory = 0;
	emulate_driver.uc_acquire_address = 0;
	emulate_driver.us_page_address = 0;

	/* Configure TWI as slave */
	puts("-I- Configuring the TWI in slave mode\n\r");
	twi_slave_init(BOARD_BASE_TWI_SLAVE, SLAVE_ADDRESS);

	/* Clear receipt buffer */
	twi_read_byte(BOARD_BASE_TWI_SLAVE);

	/* Configure TWI interrupts */
	NVIC_DisableIRQ(BOARD_TWI_IRQn);
	NVIC_ClearPendingIRQ(BOARD_TWI_IRQn);
	NVIC_SetPriority(BOARD_TWI_IRQn, 0);
	NVIC_EnableIRQ(BOARD_TWI_IRQn);
	twi_enable_interrupt(BOARD_BASE_TWI_SLAVE, TWI_SR_SVACC);

	while (1) {
	}
}
Ejemplo n.º 5
0
int main(void) {
	// Set clock @ 8Mhz
	CPU_PRESCALE(1);

	sei();

	twi_slave_init();
	twi_slave_enable();

	for (;;);
}
Ejemplo n.º 6
0
/*! \brief Main function.
 */
int main(void)
{
  static const gpio_map_t TWI_GPIO_MAP =
  {
    {AVR32_TWI_SDA_0_0_PIN, AVR32_TWI_SDA_0_0_FUNCTION},
    {AVR32_TWI_SCL_0_0_PIN, AVR32_TWI_SCL_0_0_FUNCTION}
  };
  twi_options_t opt;
  twi_slave_fct_t twi_slave_fct;
  int status;

  // Switch to oscillator 0
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

  // Init debug serial line
  init_dbg_rs232(FOSC0);

  // Initialize and enable interrupt
  irq_initialize_vectors();
  cpu_irq_enable();

  // Display a header to user
  print_dbg("\x0C\r\nTWI Example\r\nSlave!\r\n");

  // TWI gpio pins configuration
  gpio_enable_module(TWI_GPIO_MAP, sizeof(TWI_GPIO_MAP) / sizeof(TWI_GPIO_MAP[0]));

  // options settings
  opt.pba_hz = FOSC0;
  opt.speed = TWI_SPEED;
  opt.chip = EEPROM_ADDRESS;

  // initialize TWI driver with options
  twi_slave_fct.rx = &twi_slave_rx;
  twi_slave_fct.tx = &twi_slave_tx;
  twi_slave_fct.stop = &twi_slave_stop;
  status = twi_slave_init(&AVR32_TWI, &opt, &twi_slave_fct );
  // check init result
  if (status == TWI_SUCCESS)
  {
    // display test result to user
    print_dbg("Slave start:\tPASS\r\n");
  }
  else
  {
    // display test result to user
    print_dbg("slave start:\tFAIL\r\n");
  }

  while(1);
}
Ejemplo n.º 7
0
void TwoWire::begin(uint8_t address) {
	if (onBeginCallback != nullptr)
	{
		onBeginCallback();
	}

	// Disable PDC channel
	twi->TWI_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;

	twi_slave_init(twi, address);
	status = SLAVE_IDLE;
	twi_enable_interrupt(twi, TWI_IER_SVACC);
	//| TWI_IER_RXRDY | TWI_IER_TXRDY	| TWI_IER_TXCOMP);
}
Ejemplo n.º 8
0
void wm_init(unsigned char * id, unsigned char * button_data, unsigned char * cal_data, unsigned int cal_data_length/*, void (*function)(void)*/)
{
	/*
	// link user function
	wm_sample_event = function;
	*/

	// start state
	wm_newaction(button_data);
	twi_reg[0xF0] = 0; // disable encryption

	// set id
	for(unsigned int i = 0, j = 0xFA; i < 6; i++, j++)
	{
		twi_reg[j] = id[i];
	}

	// set calibration data
	for(unsigned int i = 0, j = 0x20; i < cal_data_length; i++, j++)
	{
		twi_reg[j] = cal_data[i];
	}

	/*
	// initialize device detect pin
	dev_detect_port &= 0xFF ^ _BV(dev_detect_pin);
	dev_detect_ddr |= _BV(dev_detect_pin);
	_delay_ms(500); // delay to simulate disconnect
	*/

	// ready twi bus, no pull-ups
	twi_port &= 0xFF ^ _BV(twi_scl_pin);
	twi_port &= 0xFF ^ _BV(twi_sda_pin);

	// start twi slave, link events
	twi_slave_init(0x52);

	/*
	// make the wiimote think something is connected
	dev_detect_port |= _BV(dev_detect_pin);
	*/
}
Ejemplo n.º 9
0
int main (void)
{
    // Configure pins to the default states.
    config_pin_defaults();

    // Initialize the watchdog module.
    watchdog_init();

    // First, initialize registers that control servo operation.
    registers_init();

    // Initialize the PWM module.
    pwm_init();

    // Initialize the ADC module.
    adc_init();

    // Initialize the PID algorithm module.
    pid_init();

#if CURVE_MOTION_ENABLED
    // Initialize curve motion module.
    motion_init();
#endif

    // Initialize the power module.
    power_init();

#if PULSE_CONTROL_ENABLED
    pulse_control_init();
#endif

#if ENCODER_ENABLED
    // Initialize software I2C to talk with encoder.
    swi2c_init();
#endif

    // Initialize the TWI slave module.
    twi_slave_init(registers_read_byte(REG_TWI_ADDRESS));

    // Finally initialize the timer.
    timer_set(0);

    // Enable interrupts.
    sei();

    // Wait until initial position value is ready.
    {
        int16_t position;
        // Get start-up position
#if ENCODER_ENABLED
        position=(int16_t) enc_get_position_value();
#else
        while (!adc_position_value_is_ready());
        position=(int16_t) adc_get_position_value();
#endif

#if CURVE_MOTION_ENABLED
        // Reset the curve motion with the current position of the servo.
        motion_reset(position);
#endif

        // Set the initial seek position and velocity.
        registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, position);
        registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0);
    }


    // XXX Enable PWM and writing.  I do this for now to make development and
    // XXX tuning a bit easier.  Constantly manually setting these values to
    // XXX turn the servo on and write the gain values get's to be a pain.
    pwm_enable();
    registers_write_enable();

    // This is the main processing loop for the servo.  It basically looks
    // for new position, power or TWI commands to be processed.
    for (;;)
    {
        uint8_t tick;
        int16_t pwm;
        int16_t position;
        // Is ADC position value ready?
        // NOTE: Even when the encoder is enabled, we still need the ADC potmeasurement as the
        //       clock because that is how the original firmware was written.
        tick=adc_position_value_is_ready();
        if(tick)
        {
#if PULSE_CONTROL_ENABLED
            // Give pulse control a chance to update the seek position.
            pulse_control_update();
#endif

#if CURVE_MOTION_ENABLED
            // Give the motion curve a chance to update the seek position and velocity.
            motion_next(10);
#endif
        }

        // Get the new position value.
        if(tick)
        {
            position = (int16_t) adc_get_position_value(); // NOTE: For encoder builds, this is the clock: clear the flag
#if ENCODER_ENABLED
        } // Always run the encoder (faster PID to PWM loop = better?)
        position = (int16_t) enc_get_position_value();
        if (position >= 0)
        {
#endif
            // Call the PID algorithm module to get a new PWM value.
            pwm = pid_position_to_pwm(position, tick);

            // Update the servo movement as indicated by the PWM value.
            // Sanity checks are performed against the position value.
            pwm_update(position, pwm);
        }

        // Is a power value ready?
        if (adc_power_value_is_ready())
        {
            // Get the new power value.
            uint16_t power = adc_get_power_value();

            // Update the power value for reporting.
            power_update(power);
        }

        // Was a command recieved?
        if (twi_data_in_receive_buffer())
        {
            // Handle any TWI command.
            handle_twi_command();
        }

#if MAIN_MOTION_TEST_ENABLED
        // This code is in place for having the servo drive itself between
        // two positions to aid in the servo tuning process.  This code
        // should normally be disabled in config.h.
#if CURVE_MOTION_ENABLED
        if (motion_time_left() == 0)
        {
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
        }
#else
        {
            // Get the timer.
            uint16_t timer = timer_get();

            // Reset the timer if greater than 800.
            if (timer > 800) timer_set(0);

            // Look for specific events.
            if (timer == 0)
            {
                registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0100);
            }
            else if (timer == 400)
            {
                registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0300);
            }
        }
#endif
#endif
    }

    return 0;
}
Ejemplo n.º 10
0
Archivo: main.c Proyecto: mokis/MServo
int main (void)
{
	// Configure pins to the default states.
	config_pin_defaults();

    // Initialize the watchdog module.
    watchdog_init();

    // First, initialize registers that control servo operation.
    registers_init();

    // Initialize the PWM module.
    pwm_init();

    // Initialize the ADC module.
    adc_init();

#if ESTIMATOR_ENABLED
    // Initialize the state estimator module.
    estimator_init();
#endif

#if REGULATOR_MOTION_ENABLED
    // Initialize the regulator algorithm module.
    regulator_init();
#endif

#if PID_MOTION_ENABLED
    // Initialize the PID algorithm module.
    pid_init();
#endif

#if IPD_MOTION_ENABLED
    // Initialize the IPD algorithm module.
    ipd_init();
#endif

#if CURVE_MOTION_ENABLED
    // Initialize curve motion module.
    motion_init();
#endif

    // Initialize the power module.
    power_init();

#if PULSE_CONTROL_ENABLED
    pulse_control_init();
#endif

    // Initialize the TWI slave module.
    twi_slave_init(registers_read_byte(REG_TWI_ADDRESS));

    // Finally initialize the timer.
    timer_set(0);

    // Enable interrupts.
    sei();

    // Wait until initial position value is ready.
    while (!adc_position_value_is_ready());

#if CURVE_MOTION_ENABLED
    // Reset the curve motion with the current position of the servo.
    motion_reset(adc_get_position_value());
#endif

    // Set the initial seek position and velocity.
    registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, adc_get_position_value());
    registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0);

    // XXX Enable PWM and writing.  I do this for now to make development and
    // XXX tuning a bit easier.  Constantly manually setting these values to 
    // XXX turn the servo on and write the gain values get's to be a pain.
    pwm_enable();
    registers_write_enable();

    // This is the main processing loop for the servo.  It basically looks
    // for new position, power or TWI commands to be processed.
    for (;;)
    {
        // Is position value ready?
        if (adc_position_value_is_ready())
        {
            int16_t pwm;
            int16_t position;

#if PULSE_CONTROL_ENABLED
            // Give pulse control a chance to update the seek position.
            pulse_control_update();
#endif

#if CURVE_MOTION_ENABLED
            // Give the motion curve a chance to update the seek position and velocity.
            motion_next(10);
#endif

            // Get the new position value.
            position = (int16_t) adc_get_position_value();

#if ESTIMATOR_ENABLED
            // Estimate velocity.
            estimate_velocity(position);
#endif

#if PID_MOTION_ENABLED
            // Call the PID algorithm module to get a new PWM value.
            pwm = pid_position_to_pwm(position);
#endif

#if IPD_MOTION_ENABLED
            // Call the IPD algorithm module to get a new PWM value.
            pwm = ipd_position_to_pwm(position);
#endif

#if REGULATOR_MOTION_ENABLED
            // Call the state regulator algorithm module to get a new PWM value.
            pwm = regulator_position_to_pwm(position);
#endif

            // Update the servo movement as indicated by the PWM value.
            // Sanity checks are performed against the position value.
            pwm_update(position, pwm);
        }

        // Is a power value ready?
        if (adc_power_value_is_ready())
        {
            // Get the new power value.
            uint16_t power = adc_get_power_value();

            // Update the power value for reporting.
            power_update(power);
        }

        // Was a command recieved?
        if (twi_data_in_receive_buffer())
        {
            // Handle any TWI command.
            handle_twi_command();
        }

#if MAIN_MOTION_TEST_ENABLED
        // This code is in place for having the servo drive itself between 
        // two positions to aid in the servo tuning process.  This code 
        // should normally be disabled in config.h.
#if CURVE_MOTION_ENABLED
        if (motion_time_left() == 0)
        {
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
        }
#else
        {
            // Get the timer.
            uint16_t timer = timer_get();

            // Reset the timer if greater than 800.
            if (timer > 800) timer_set(0);

            // Look for specific events.
            if (timer == 0)
            {
                registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0100);
            }
            else if (timer == 400)
            {
                registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0300);
            }
        }
#endif
#endif
    }

    return 0;
}
Ejemplo n.º 11
0
// initialize application timer
extern void init_tc (void) {
	volatile avr32_tc_t *tc = APP_TC;

  // waveform options
	static const tc_waveform_opt_t waveform_opt = {
	.channel  = APP_TC_CHANNEL,  // channel
	.bswtrg   = TC_EVT_EFFECT_NOOP, // software trigger action on TIOB
	.beevt    = TC_EVT_EFFECT_NOOP, // external event action
	.bcpc     = TC_EVT_EFFECT_NOOP, // rc compare action
	.bcpb     = TC_EVT_EFFECT_NOOP, // rb compare
	.aswtrg   = TC_EVT_EFFECT_NOOP, // soft trig on TIOA
	.aeevt    = TC_EVT_EFFECT_NOOP, // etc
	.acpc     = TC_EVT_EFFECT_NOOP,
	.acpa     = TC_EVT_EFFECT_NOOP,
	// Waveform selection: Up mode with automatic trigger(reset) on RC compare.
	.wavsel   = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,
	.enetrg   = false,             // external event trig
	.eevt     = 0,                 // extern event select
	.eevtedg  = TC_SEL_NO_EDGE,    // extern event edge
	.cpcdis   = false,             // counter disable when rc compare
	.cpcstop  = false,            // counter stopped when rc compare
	.burst    = false,
	.clki     = false,
	// Internal source clock 5, connected to fPBA / 128.
	.tcclks   = TC_CLOCK_SOURCE_TC5
};

  // Options for enabling TC interrupts
static const tc_interrupt_t tc_interrupt = {
	.etrgs = 0,
	.ldrbs = 0,
	.ldras = 0,
	.cpcs  = 1, // Enable interrupt on RC compare alone
	.cpbs  = 0,
	.cpas  = 0,
	.lovrs = 0,
	.covfs = 0
};
  // Initialize the timer/counter.
tc_init_waveform(tc, &waveform_opt);

  // set timer compare trigger.
  // we want it to overflow and generate an interrupt every 1 ms
  // so (1 / fPBA / 128) * RC = 0.001
  // so RC = fPBA / 128 / 1000
  //  tc_write_rc(tc, APP_TC_CHANNEL, (FPBA_HZ / 128000));
tc_write_rc(tc, APP_TC_CHANNEL, (FPBA_HZ / 128000));

  // configure the timer interrupt
tc_configure_interrupts(tc, APP_TC_CHANNEL, &tc_interrupt);
  // Start the timer/counter.
tc_start(tc, APP_TC_CHANNEL);
}


extern void init_spi (void) {

	sysclk_enable_pba_module(SYSCLK_SPI);

	static const gpio_map_t SPI_GPIO_MAP = {
		{SPI_SCK_PIN,  SPI_SCK_FUNCTION },
		{SPI_MISO_PIN, SPI_MISO_FUNCTION},
		{SPI_MOSI_PIN, SPI_MOSI_FUNCTION},
		{SPI_NPCS0_PIN,  SPI_NPCS0_FUNCTION },
		{SPI_NPCS1_PIN,  SPI_NPCS1_FUNCTION },
		{SPI_NPCS2_PIN,  SPI_NPCS2_FUNCTION },
	};

  // Assign GPIO to SPI.
	gpio_enable_module(SPI_GPIO_MAP, sizeof(SPI_GPIO_MAP) / sizeof(SPI_GPIO_MAP[0]));


	spi_options_t spiOptions = {
		.reg = DAC_SPI,
		.baudrate = 2000000,
		.bits = 8,
		.trans_delay = 0,
		.spck_delay = 0,
		.stay_act = 1,
		.spi_mode = 1,
		.modfdis = 1
	};

  // Initialize as master.
	spi_initMaster(SPI, &spiOptions);
  // Set SPI selection mode: variable_ps, pcs_decode, delay.
	spi_selectionMode(SPI, 0, 0, 0);
  // Enable SPI module.
	spi_enable(SPI);

  // spi_setupChipReg( SPI, &spiOptions, FPBA_HZ );
	spi_setupChipReg(SPI, &spiOptions, sysclk_get_pba_hz() );


  // add ADC chip register
	spiOptions.reg          = ADC_SPI;
	spiOptions.baudrate     = 20000000;
	spiOptions.bits         = 16;
	spiOptions.spi_mode     = 2;
	spiOptions.spck_delay   = 0;
	spiOptions.trans_delay  = 5;
	spiOptions.stay_act     = 0;
	spiOptions.modfdis      = 0;

	spi_setupChipReg( SPI, &spiOptions, FPBA_HZ );


  // add OLED chip register
	spiOptions.reg          = OLED_SPI;
	spiOptions.baudrate     = 40000000;
	spiOptions.bits         = 8;
	spiOptions.spi_mode     = 3;
	spiOptions.spck_delay   = 0;
	spiOptions.trans_delay  = 0;
	spiOptions.stay_act     = 1;
	spiOptions.modfdis      = 1;

	spi_setupChipReg( SPI, &spiOptions, FPBA_HZ );
}


// initialize USB host stack
void init_usb_host (void) {
	uhc_start();
}


// initialize i2c
void init_i2c_master(void) {
	twi_options_t opt;

	int status;

	static const gpio_map_t TWI_GPIO_MAP = {
		{AVR32_TWI_SDA_0_0_PIN, AVR32_TWI_SDA_0_0_FUNCTION},
		{AVR32_TWI_SCL_0_0_PIN, AVR32_TWI_SCL_0_0_FUNCTION}
	};

	gpio_enable_module(TWI_GPIO_MAP, sizeof(TWI_GPIO_MAP) / sizeof(TWI_GPIO_MAP[0]));


	// options settings
	opt.pba_hz = FOSC0;
	opt.speed = TWI_SPEED;
	opt.chip = 0x50;

	// initialize TWI driver with options
	// status = twi_master_init(&AVR32_TWI, &opt);
	status = twi_master_init(TWI, &opt);
/*	// check init result
	if (status == TWI_SUCCESS)
		print_dbg("\r\ni2c init");
	else
		print_dbg("\r\ni2c init FAIL");
*/
}

void init_i2c_slave(void) {
	twi_options_t opt;
	twi_slave_fct_t twi_slave_fct;

	int status;

	static const gpio_map_t TWI_GPIO_MAP = {
		{AVR32_TWI_SDA_0_0_PIN, AVR32_TWI_SDA_0_0_FUNCTION},
		{AVR32_TWI_SCL_0_0_PIN, AVR32_TWI_SCL_0_0_FUNCTION}
	};

	gpio_enable_module(TWI_GPIO_MAP, sizeof(TWI_GPIO_MAP) / sizeof(TWI_GPIO_MAP[0]));


	// options settings
	opt.pba_hz = FOSC0;
	opt.speed = TWI_SPEED;
	opt.chip = 0x50;

	// initialize TWI driver with options
	twi_slave_fct.rx = &twi_slave_rx;
	twi_slave_fct.tx = &twi_slave_tx;
	twi_slave_fct.stop = &twi_slave_stop;
	status = twi_slave_init(&AVR32_TWI, &opt, &twi_slave_fct );
/*
	// check init result
	if (status == TWI_SUCCESS)
		print_dbg("\r\ni2c init");
	else
		print_dbg("\r\ni2c init FAIL");
*/
}
Ejemplo n.º 12
0
void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=P Bit1=P Bit0=P
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (1<<PORTC2) | (1<<PORTC1) | (1<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=In Bit0=In 
DDRD=(0<<DDD7) | (0<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=P Bit6=T Bit5=0 Bit4=0 Bit3=0 Bit2=T Bit1=T Bit0=T 
PORTD=(1<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Fast PWM top=0xFF
// OC0A output: Non-Inverted PWM
// OC0B output: Disconnected
// Timer Period: 0,016 ms
// Output Pulse(s):
// OC0A Period: 0,016 ms Width: 0 us
TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 4,096 ms
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Fast PWM top=0xFF
// OC2A output: Disconnected
// OC2B output: Non-Inverted PWM
// Timer Period: 0,016 ms
// Output Pulse(s):
// OC2B Period: 0,016 ms Width: 8,0314 us
ASSR=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (1<<COM2B1) | (0<<COM2B0) | (1<<WGM21) | (1<<WGM20);
TCCR2B=(0<<WGM22) | (0<<CS22) | (0<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);

// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=(0<<OCIE2B) | (0<<OCIE2A) | (0<<TOIE2);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);
UBRR0H=0x00;
UBRR0L=0x67;

// Analog Comparator initialization
// Analog Comparator: On
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
// Interrupt on Rising Output Edge
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=(0<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (1<<ACIE) | (0<<ACIC) | (1<<ACIS1) | (1<<ACIS0);
ADCSRB=(0<<ACME);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR1=(0<<AIN0D) | (0<<AIN1D);

// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// Mode: TWI Slave
// Match Any Slave Address: Off
// I2C Bus Slave Address: 0x21
twi_slave_init(false,0x21,twi_rx_buffer,sizeof(twi_rx_buffer),twi_tx_buffer,twi_rx_handler,twi_tx_handler);

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 0
// RD - PORTB Bit 7
// EN - PORTB Bit 1
// D4 - PORTB Bit 2
// D5 - PORTB Bit 3
// D6 - PORTB Bit 4
// D7 - PORTB Bit 5
// Characters/line: 16
lcd_init(16);
lcd_putsf("  WELCOME!   ");
// Global enable interrupts

ACSR |= (1<<ACIE); // включить перывания от компарат
ACSR &= ~(1<<ACIE); // выкл прер компар

vyh_t0 = 0;             // выкл таймер 0
TCCR0A &= ~(1<<CS00); 



procfreq = 16000000 ;
ton1 = fdel(1080);


for (n = 0; n < 32; n++) 
{
    sost[n] = esost[n];
    twi_tx_buffer[n] = sost[n];
} 
//PORTD.4 = 1;
//delay_ms(100);
//PORTD.4 = 0;
//PORTD.2 = 1;
#asm("sei")
//vyh_plus = 1;
OCR2B=0x00; // выключение преобразователя
//          time = 0;
//          while (time < 1000) #asm("wdr");  // задержка 25 мСек
//
// OCR2B=0x50; // выключение преобразователя
//
//          time = 0;
//          while (time < 1000) #asm("wdr");  // задержка 25 мСек
//
//OCR2B=0x50; // выключение преобразователя
//
//          time = 0;
//          while (time < 1000) #asm("wdr");  // задержка 25 мСек
// vyh_plus = 0;
// vyh_minus = 1;
//
//OCR2B=0xB0; // выключение преобразователя
//
//          time = 0;
//          while (time < 1000) #asm("wdr");  // задержка 25 мСек
//
//
//OCR2B=0xFF; // выключение преобразователя
//

    while (1)
    {   
      for (i = 0 ; i < 128 ; i++)
      {     
          if(kn1&kn3) nagh = 0;  // сброс флага нажатия при отпущеной кнопке      
          if(!kn1) 
          {
            if(!nagh)  // если кнопка только-что нажата 
            {            
                nagh = 1;
                lcd_gotoxy(3,0);
                if (fix)
                {
                    fix  = 0;         // если была включена фиксация, - выключить            
                    lcd_putchar(' ');
                }
                else
                {
                    fix = 1;         // включить фиксацию  
                    page = (i / 32); // на какой странице зафиксировано    
                    if (page == 0) page = 4; 
                    page--;
                    page *= 32;
                    pos = 0;
                    x_dysp = 5;
                    y_dysp = 0;
                    lcd_putchar('F');  
                }

            }               
            
          }    
          if(fix) 
          { 
            if(p10++ == 0)
            { 
            // отображение подч

                    lcd_gotoxy(x_dysp,y_dysp);   
                    lcd_putchar('_'); 
             
            }
            if(p10 == 8)
            {
                // отображение текущего состояние точки n

                                sig_bayt = (pos+page) / 4;    // текущий байт в слове состояния                 
                                sig_bit = ((pos + page) - (sig_bayt * 4)) * 2;   // текущая двухбитовая пара в слове состояния
                                lcd_gotoxy(x_dysp,y_dysp); 
                                if((sost[sig_bayt]&(1<<sig_bit)))
                                {
                                     if((sost[sig_bayt]&(1<<(sig_bit+1)))) lcd_putchar(255); 
                                     else  lcd_putchar('.'); 
                                } else lcd_putchar(' ');
                    
             
            }
            if(p10 > 16)
            {
                p10 = 0;

                if(!kn2)
                {      
                    if(++pos >  30) 
                    {
                        pos = 0;
                        x_dysp = 3;
                        y_dysp = 0;
                    } 
                    else if(pos == 15) pos++;
                    x_dysp++;
                    if(++x_dysp > 15) 
                    {
                        y_dysp++;
                        x_dysp = 1;
                    } 
                    
                } 
                if(!kn3)
                {    
                    if(!nagh)  // если кнопка только-что нажата 
                    {            
                    nagh = 1;
                     // включение - выключение охраны   
                    lcd_gotoxy(x_dysp,y_dysp); 
                                sig_bayt = (pos+page) / 4;    // текущий байт в слове состояния                 
                                sig_bit = ((pos + page) - (sig_bayt * 4)) * 2;   // текущая двухбитовая пара в слове состояния
                                if((sost[sig_bayt]&(1<<sig_bit)))
                                {
                                    sost[sig_bayt] &= ~(1<<sig_bit);     // выкл. охрану
                                    lcd_putchar(' ');
                                } else 
                                {   
                                    sost[sig_bayt] |= (1<<sig_bit);      // включаем охрану
                                    lcd_putchar('.');
                                }
                    }
                }  
            }
          }
          sig_bayt = i / 4;    // текущий байт в слове состояния                 
          sig_bit = (i - sig_bayt * 4) * 2;   // текущая двухбитовая пара в слове состояния               
          OCR0A=0x00;
          a = 49728;  
          TCCR0A |= (1<<CS00);  // включить таймер 0;
          TIMSK0 |= (1<<TOIE0); // 
          time = 0;
          while (time < 6) #asm("wdr");  // задержка 25 мСек
          zvuk = 0;  
          if(i == 0) while (time < 75) #asm("wdr"); // если первый шаг, задержка 300 мСек
          TIMSK0 &= ~(1<<TOIE0); // 
          OCR0A=0x00;
          a = 49728;  
          TCCR0A &= ~(1<<CS00);    // выкл таймер 0                       
          vyh_t0 = 0;            // переключить а вход 
          ACSR |= (1<<ACIE); // включить перывания от компарат   
          time = 0;
          while (time < 9) #asm("wdr");    // 25мСек + 12
          ACSR &= ~(1<<ACIE); // выкл прер компар  
          vyh_t0 = 1;            // переключить а вyход           
          if (flag435) // если был отлет 435 Гц
          { 
            switch (i)
            {
                case 31:  
                    // вывод первой половины на дисп  
                    if (!fix)
                    {
                        clear_lcd();
                        lcd_gotoxy(0,0);
                        lcd_putsf("1   ");
                        n = 1;
                        for (sig_bayt = 0; sig_bayt < 8 ; sig_bayt++)
                        {
                            for(sig_bit = 0; (sig_bayt == 3 || sig_bayt == 7)? sig_bit < 6: sig_bit < 8; sig_bit += 2)
                            {     
                                if(++n>10) n = 1;
                                lcd_putchar(47+n);
                                if((sost[sig_bayt]&(1<<sig_bit)))
                                {
                                     if((sost[sig_bayt]&(1<<(sig_bit+1)))) lcd_putchar(255); 
                                     else  lcd_putchar('.'); 
                                } else lcd_putchar(' ');
                            }
                        }  
                    } 
                    pit_ok = 1;      
                    while (time < 125) #asm("wdr");  // задержка до 0.5 сек
                    break;
                case 15:
                case 47: 
                case 63: 
                case 79: 
                case 95: 
                case 111: 
                case 127:
                    sinc_err = 1;      // ошибка синхронизации
                    zvuk = 1;
                    break;
                default:
                    if (sost[sig_bayt]&(1<<sig_bit))   // если под охраной
                    {    
                        if ((esost[sig_bayt]&(1<<sig_bit) == 0))
                        {
                            //если не был под охр. поставить под охрану.
                            OCR2B=0x50; // выдача на шим
                            vyh_plus = 1;  
                            vyh_t0 = 0;            // переключить а вход 
                            n = 0;
                            while(flag435) 
                            {
                                flag435 = 0; 
                                ACSR |= (1<<ACIE); // включить перывания от компарат   
                                time = 0;
                                while (time < 9) #asm("wdr");    // 25мСек + 12
                                ACSR &= ~(1<<ACIE); // выкл прер компар  
                                 
                                //Ждем прекращения сигнала
                                if (++n > 250) flag435 = 0;
                            }      
                            vyh_t0 = 1;            // переключить Hа вyход 
                                      
                            if(n < 251) 
                            {
                                esost[sig_bayt] |= (1<<sig_bit);      // включаем охрану если сигнал прервался
                                twi_tx_buffer[sig_bayt] = esost[sig_bayt]; // передача состояния
                            }
                            else sost[sig_bayt] &= ~(3<<sig_bit);    // если не взялась, - снять
                        }
                        else
                        {
                        // если объекм был по охраной тревога
                            sost[sig_bayt] |= (1<<(sig_bit+1));    
                            esost[sig_bayt] |= (1<<(sig_bit+1));    
                            twi_tx_buffer[sig_bayt] = esost[sig_bayt]; // передача состояния
                            trevoga = 1;  
                            zvuk = 1;
                        }
                        while(time<375) #asm("wdr");  
                        vyh_plus = 0;
                        OCR2B=0xFF;                 
                    } 
                    else  if (esost[sig_bayt]&(1<<sig_bit))  // не под охр, но был
                    {

                        esost[sig_bayt] &= ~(3<<sig_bit);      //  если был под охр. снять с охр. 

                        twi_tx_buffer[sig_bayt] = esost[sig_bayt]; // передача состояния
                        
                    }

            } 
          } 
          else      // если не было ответа
          { 
            switch (i)
            {
                case 31: 
                    // вкл питание
                     
                    if (!fix)
                    {
                        clear_lcd(); 
                        lcd_gotoxy(0,1);
                        lcd_putsf("Error Pitanie!!!");
                    } 
                    
                    pit_err = 1;
                    pit_ok = 0;
                    break;   
                case 63:  
                    // вывод второй половины на дисп  
                    if (!fix)
                    {
                        clear_lcd();
                        lcd_gotoxy(0,0);
                        lcd_putsf("31  ");
                        n = 1;
                        for (sig_bayt = 8; sig_bayt < 16 ; sig_bayt++)
                        {
                            for(sig_bit = 0; (sig_bayt == 11 || sig_bayt == 15)? sig_bit < 6: sig_bit < 8; sig_bit += 2)
                            {     
                                if(++n>10) n = 1;
                                lcd_putchar(47+n);
                                if((sost[sig_bayt]&(1<<sig_bit)))
                                {
                                     if((sost[sig_bayt]&(1<<(sig_bit+1)))) lcd_putchar(255); 
                                     else  lcd_putchar('.'); 
                                } else lcd_putchar(' ');
                            }
                        }  
                    } 
                    
                    break;
                case 95: 
                    // вывод третьей половины на дисп  
                    if (!fix)
                    {
                        clear_lcd();
                        lcd_gotoxy(0,0);
                        lcd_putsf("61  ");
                        n = 1;
                        for (sig_bayt = 16; sig_bayt < 24 ; sig_bayt++)
                        {
                            for(sig_bit = 0; (sig_bayt == 19 || sig_bayt == 23)? sig_bit < 6: sig_bit < 8; sig_bit += 2)
                            {     
                                if(++n>10) n = 1;
                                lcd_putchar(47+n);
                                if((sost[sig_bayt]&(1<<sig_bit)))
                                {
                                     if((sost[sig_bayt]&(1<<(sig_bit+1)))) lcd_putchar(255); 
                                     else  lcd_putchar('.'); 
                                } else lcd_putchar(' ');
                            }
                        }  
                    } 
                    break;
                case 127:  
                    // вывод четвертой половины на дисп  
                    if (!fix)
                    {
                        clear_lcd();
                        lcd_gotoxy(0,0);
                        lcd_putsf("91  ");
                        n = 1;
                        for (sig_bayt = 24; sig_bayt < 32; sig_bayt++)
                        {
                            for(sig_bit = 0; (sig_bayt == 27 || sig_bayt == 31)? sig_bit < 6: sig_bit < 8; sig_bit += 2)
                            {     
                                if(++n>10) n = 1;
                                lcd_putchar(47+n);
                                if((sost[sig_bayt]&(1<<sig_bit)))
                                {
                                     if((sost[sig_bayt]&(1<<(sig_bit+1)))) lcd_putchar(255); 
                                     else  lcd_putchar('.'); 
                                } else lcd_putchar(' ');
                            }
                        }  
                    } 
                    break;
                case 15: 
                case 47: 
                case 79: 
                case 111: 
                    break;
                default:
                    if ((sost[sig_bayt]&(1<<sig_bit)) == 0) 
                    {                                           
                        if (esost[sig_bayt]&(1<<sig_bit))  // не под охр, но был  
                        {
                            //если был под охр. снять с охр.  
                            esost[sig_bayt] &= ~(3<<sig_bit);      //  снять с охр.             
                            twi_tx_buffer[sig_bayt] = esost[sig_bayt]; // передача состояния
                        } 
                    } 
                    else  if ((esost[sig_bayt]&(1<<sig_bit)) == 0) //если под охраной, но не был
                    {
                        esost[sig_bayt] |= (1<<sig_bit);   // включаем охрану 
                        twi_tx_buffer[sig_bayt] = esost[sig_bayt]; // передача состояния
                    }                    
            }             
          } 
          flag435 = 0;             
          if (pit_ok)
          { 
            while (time < 125) #asm("wdr");
            pit_ok = 0;       
          }               
          
//          if (trevoga) //while (time < 375);
//          trevoga = 0;         
          if (sinc_err)  
          {
            sinc_err = 0;  
            if (!fix)
            {
                clear_lcd();
                lcd_gotoxy(0,1);
                lcd_putsf("  Error Sync!!! ");
            } else 
            {
                lcd_gotoxy(3,0); 
                lcd_putchar('F');   
            }
            break;
          }          
      }  
      

    }
    
}
Ejemplo n.º 13
0
int main (void)
{
    // Configure pins to the default states.
    config_pin_defaults();

    // Initialize the watchdog module.
    watchdog_init();

    // First, initialize registers that control servo operation.
    registers_init();

#if PWM_STD_ENABLED || PWM_ENH_ENABLED
    // Initialize the PWM module.
    pwm_init();
#endif

#if STEP_ENABLED
    // Initialise the stepper motor
    step_init();
#endif
    
    // Initialize the ADC module.
    adc_init();

    // Initialise the Heartbeart
    heartbeat_init();

    // Initialize the PID algorithm module.
    pid_init();

#if CURVE_MOTION_ENABLED
    // Initialize curve motion module.
    motion_init();
#endif

    // Initialize the power module.
    power_init();

#if PULSE_CONTROL_ENABLED
    pulse_control_init();
#endif

#if BACKEMF_ENABLED
    // Initialise the back emf module
    backemf_init();
#endif

#if ALERT_ENABLED
    //initialise the alert registers
    alert_init();
#endif

    // Initialize the TWI slave module.
    twi_slave_init(banks_read_byte(POS_PID_BANK, REG_TWI_ADDRESS));

    // Finally initialize the timer.
    timer_set(0);

    // Enable interrupts.
    sei();

    // Trigger the adc sampling hardware
    adc_start(ADC_CHANNEL_POSITION);

    // Wait until initial position value is ready.
    while (!adc_position_value_is_ready());

#if CURVE_MOTION_ENABLED
    // Reset the curve motion with the current position of the servo.
    motion_reset(adc_get_position_value());
#endif

    // Set the initial seek position and velocity.
    registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, adc_get_position_value());
    registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0);

    // XXX Enable PWM and writing.  I do this for now to make development and
    // XXX tuning a bit easier.  Constantly manually setting these values to
    // XXX turn the servo on and write the gain values get's to be a pain.
#if PWM_STD_ENABLED || PWM_ENH_ENABLED
    pwm_enable();
#endif
#if STEP_ENABLED
    step_enable();
#endif

    registers_write_enable();

    // This is the main processing loop for the servo.  It basically looks
    // for new position, power or TWI commands to be processed.
    for (;;)
    {
        static uint8_t emf_motor_is_coasting = 0;

        // Is the system heartbeat ready?
        if (heartbeat_is_ready())
        {
            static int16_t last_seek_position;
            static int16_t wait_seek_position;
            static int16_t new_seek_position;

            // Clear the heartbeat flag
            heartbeat_value_clear_ready();

#if PULSE_CONTROL_ENABLED
            // Give pulse control a chance to update the seek position.
            pulse_control_update();
#endif

#if CURVE_MOTION_ENABLED
            // Give the motion curve a chance to update the seek position and velocity.
            motion_next(10);
#endif

            // General call support
            // Check to see if we have the wait flag enabled. If so save the new position, and write in the
            // old position until we get the move command
            if (general_call_enabled()) 
            {
                //we need to wait for the go command before moving
                if (general_call_wait())
                {
                    // store the new position, but let the servo lock to the last seek position
                    wait_seek_position = (int16_t) registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO);
                    if (wait_seek_position != last_seek_position) // do we have a new position?
                    {
                        new_seek_position = wait_seek_position;
                        registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, last_seek_position);
                    }
                }
                last_seek_position = registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO);

                //check to make sure that we can start the move.
                if (general_call_start() || 
                    ( registers_read_byte(REG_GENERAL_CALL_GROUP_START) == banks_read_byte(CONFIG_BANK, REG_GENERAL_CALL_GROUP)))
                {
                    // write the new position with the previously saved position
                    registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, new_seek_position);  
                    general_call_start_wait_reset();  // reset the wait flag
                    general_call_start_reset();  // reset the start flag
                }
            }

#if BACKEMF_ENABLED
            // Quick and dirty check to see if pwm is active. This is done to make sure the motor doesn't
            // whine in the audible range while idling.
            uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA);
            uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB);
            if (pwm_a || pwm_b)
            {
                // Disable PWM
                backemf_coast_motor();
                emf_motor_is_coasting = 1;
            }
            else
            {
                // reset the back EMF value to 0
                banks_write_word(INFORMATION_BANK, REG_BACKEMF_HI, REG_BACKEMF_LO, 0);
                emf_motor_is_coasting = 0;
            }
#endif

#if ADC_ENABLED
            // Trigger the adc sampling hardware. This triggers the position and temperature sample
            adc_start(ADC_FIRST_CHANNEL);
#endif

        }
    
    
        // Wait for the samples to complete
#if TEMPERATURE_ENABLED
        if (adc_temperature_value_is_ready())
        {
            // Save temperature value to registers
            registers_write_word(REG_TEMPERATURE_HI, REG_TEMPERATURE_LO, (uint16_t)adc_get_temperature_value());
        }
#endif
#if CURRENT_ENABLED
        if (adc_power_value_is_ready())
        {

            // Get the new power value.
            uint16_t power = adc_get_power_value();

            // Update the power value for reporting.
            power_update(power);
        }
#endif
#if ADC_POSITION_ENABLED
        if (adc_position_value_is_ready())
        {
            int16_t position;
            // Get the new position value from the ADC module.
            position = (int16_t) adc_get_position_value();
#else
        if (position_value_is_ready())
        {
            int16_t position;
            // Get the position value from an external module.
            position = (int16_t) get_position_value();
#endif
            int16_t pwm;
#if BACKEMF_ENABLED
            if (emf_motor_is_coasting == 1)
            {
                uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA);
                uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB);

                // Quick and dirty check to see if pwm is active
                if (pwm_a || pwm_b)
                {
                    // Get the backemf sample.
                    backemf_get_sample();

                    // Turn the motor back on
                    backemf_restore_motor();
		    emf_motor_is_coasting = 0;
                }
            }
#endif

            // Call the PID algorithm module to get a new PWM value.
            pwm = pid_position_to_pwm(position);

#if ALERT_ENABLED
            // Update the alert status registers and do any throttling
            alert_check();
#endif

            // Allow any alerts to modify the PWM value.
            pwm = alert_pwm_throttle(pwm);

#if PWM_STD_ENABLED || PWM_ENH_ENABLED
            // Update the servo movement as indicated by the PWM value.
            // Sanity checks are performed against the position value.
            pwm_update(position, pwm);
#endif

#if STEP_ENABLED
            // Update the stepper motor as indicated by the PWM value.
            // Sanity checks are performed against the position value.
            step_update(position, pwm);
#endif
        }
    
        // Was a command recieved?
        if (twi_data_in_receive_buffer())
        {
            // Handle any TWI command.
            handle_twi_command();
        }

        // Update the bank register operations
        banks_update_registers();

#if MAIN_MOTION_TEST_ENABLED
        // This code is in place for having the servo drive itself between
        // two positions to aid in the servo tuning process.  This code
        // should normally be disabled in config.h.
#if CURVE_MOTION_ENABLED
        if (motion_time_left() == 0)
        {
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
        }
#else
        {
            // Get the timer.
            uint16_t timer = timer_get();

            // Reset the timer if greater than 800.
            if (timer > 800) timer_set(0);

            // Look for specific events.
            if (timer == 0)
            {
                registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0100);
            }
            else if (timer == 400)
            {
                registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0300);
            }
        }
#endif
#endif
    }

    return 0;
}