예제 #1
0
파일: servo.cpp 프로젝트: chris-bo/Marlin
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA) {
  if (Channel[timer] < 0)
    *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
  else {
    if (SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive)
      digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
  }

  Channel[timer]++;    // increment to the next channel
  if (SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
    *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
    if (SERVO(timer,Channel[timer]).Pin.isActive)     // check if activated
      digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
  }
  else {
    // finished all channels so wait for the refresh period to expire before starting over
    if ( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) )  // allow a few ticks to ensure the next OCR1A not missed
      *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
    else
      *OCRnA = *TCNTn + 4;  // at least REFRESH_INTERVAL has elapsed
    Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
  }
}
예제 #2
0
uint8_t Servo::attach(int pin, int minimum, int maximum)
{
	if (servoIndex < MAX_SERVOS) {
		pinMode(pin, OUTPUT);
		servo_pin[servoIndex] = pin;
		servo_ticks[servoIndex] = usToTicks(DEFAULT_PULSE_WIDTH);
		servo_active_mask |= (1<<servoIndex);
		min_ticks = usToTicks(minimum);
		max_ticks = usToTicks(maximum);
		if (!(SIM_SCGC6 & SIM_SCGC6_PDB)) {
			SIM_SCGC6 |= SIM_SCGC6_PDB; // TODO: use bitband for atomic bitset
			PDB0_MOD = 0xFFFF;
			PDB0_CNT = 0;
			PDB0_IDLY = 0;
			PDB0_SC = PDB_CONFIG;
			// TODO: maybe this should be a higher priority than most
			// other interrupts (init all to some default?)
			PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
		}
		NVIC_ENABLE_IRQ(IRQ_PDB);
	}
	return servoIndex;
}
예제 #3
0
void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
  // clear interrupt
  tc->TC_CHANNEL[channel].TC_SR;
  if (Channel[timer] < 0)
    tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
  else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
    extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated

  Channel[timer]++;    // increment to the next channel
  if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
    tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
    if (SERVO(timer,Channel[timer]).Pin.isActive)    // check if activated
      extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
  }
  else {
    // finished all channels so wait for the refresh period to expire before starting over
    tc->TC_CHANNEL[channel].TC_RA =
      tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
        ? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed
        : tc->TC_CHANNEL[channel].TC_CV + 4;        // at least REFRESH_INTERVAL has elapsed
    Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
  }
}
예제 #4
0
파일: servo.c 프로젝트: AriZuu/micropython
static mp_obj_t servo_obj_angle(int n_args, const mp_obj_t *args) {
    pyb_servo_obj_t *self = args[0];
    if (n_args == 1) {
        // get
        float angle = map_uint_to_float(servo_ticks[self->servo_id],
                                        usToTicks(self->min_usecs),
                                        usToTicks(self->max_usecs),
                                        0.0, 180.0);
        return mp_obj_new_float(angle);
    }
    // Set
    float angle = mp_obj_get_float(args[1]);
    if (angle < 0.0F) {
        angle = 0.0F;
    }
    if (angle > 180.0F) {
        angle = 180.0F;
    }
    servo_ticks[self->servo_id] = map_float_to_uint(angle,
                                                    0.0F, 180.0F,
                                                    usToTicks(self->min_usecs),
                                                    usToTicks(self->max_usecs));
    return mp_const_none;
}
예제 #5
0
Servo::Servo()
{
	if (ServoCount < MAX_SERVOS)
	{
        /// TODO: Really, we need to search through servos[] for the first one
        /// that is not being used, rather than always use ServoCount as the 
        /// index. What happens if you create 24 servos, then destroy one
        /// and create another. Right now that would fail, even though you
        /// weren't actively using 24 servos.
		this->servoIndex = ServoCount++;									// assign a servo index to this instance
		servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH);	// store default to neutral position
  	}
	else
		this->servoIndex = INVALID_SERVO ;  // too many servos
}
예제 #6
0
파일: Servo.cpp 프로젝트: 14Ohm/Energia
void Servo::writeMicroseconds(int value)
{
  // calculate and store the values for the given channel
  byte channel = this->servoIndex;
  if( (channel < MAX_SERVOS) )   // ensure channel is valid
  {  
    if( value < SERVO_MIN() )          // ensure pulse width is valid
      value = SERVO_MIN();
    else if( value > SERVO_MAX() )
      value = SERVO_MAX();       
    value = value - TRIM_DURATION;
    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
    servos[channel].ticks = value; // this is atomic on a 16bit uC, no need to disable Interrupts
  } 
}
예제 #7
0
파일: servo.c 프로젝트: AriZuu/micropython
static mp_obj_t servo_obj_usecs(int n_args, const mp_obj_t *args) {
    pyb_servo_obj_t *self = args[0];
    uint usecs;
    if (n_args == 1) {
        // get
        return MP_OBJ_NEW_SMALL_INT(ticksToUs(servo_ticks[self->servo_id]));
    }
    // Set
    usecs = mp_obj_get_int(args[1]);

    if (self->min_usecs < self->max_usecs) {
        usecs = clamp(usecs, self->min_usecs, self->max_usecs);
    } else {
        usecs = clamp(usecs, self->max_usecs, self->min_usecs);
    }
    servo_ticks[self->servo_id] = usToTicks(usecs);
    return mp_const_none;
}
예제 #8
0
void Servo::writeMicroseconds(int value) {
  // calculate and store the values for the given channel
  byte channel = this->servoIndex;
  if (channel < MAX_SERVOS) {  // ensure channel is valid
    if (value < SERVO_MIN())   // ensure pulse width is valid
      value = SERVO_MIN();
    else if (value > SERVO_MAX())
      value = SERVO_MAX();

  	value = value - TRIM_DURATION;
    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009

    uint8_t oldSREG = SREG;
    cli();
    servos[channel].ticks = value;
    SREG = oldSREG;
  }
}
예제 #9
0
void Servo_writeMicroseconds(byte servoIndex, int value)
{
  if( (servoIndex < MAX_SERVOS) )   // ensure channel is valid
  {  
    if( value < SERVO_MIN() )          // ensure pulse width is valid
      value = SERVO_MIN();
    else if( value > SERVO_MAX() )
      value = SERVO_MAX();   
    
  	value = value - SERVO_TRIM_DURATION;
    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009

    uint8_t oldSREG = SREG;
    cli();
    servos[servoIndex].ticks = value;  
    SREG = oldSREG;   
  } 
}
예제 #10
0
파일: Servo.cpp 프로젝트: Diecore/Energia
void Servo::writeMicroseconds(int value)
{
  // calculate and store the values for the given channel
  byte channel = this->servoIndex;
  if( (channel < MAX_SERVOS) )   // ensure channel is valid
  {  
    if( value < SERVO_MIN() )          // ensure pulse width is valid
      value = SERVO_MIN();
    else if( value > SERVO_MAX() )
      value = SERVO_MAX();   
    
  	value = value - TRIM_DURATION;
    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009

    CCTL0 = 0; // disable interrupt to avoid race condition
    servos[channel].ticks = value;
    CCTL0 = CCIE;
  } 
}
예제 #11
0
//************************************************************************
void Servo::writeMicroseconds(int value)
{
	// calculate and store the values for the given channel
	byte channel = this->servoIndex;
	if ( (channel >= 0) && (channel < MAX_SERVOS) )	// ensure channel is valid
	{
		if ( value < SERVO_MIN() )			// ensure pulse width is valid
			value = SERVO_MIN();
		else if ( value > SERVO_MAX() )
			value = SERVO_MAX();

		value = value - TRIM_DURATION;
		value = usToTicks(value);			// convert to ticks after compensating for interrupt overhead 

		unsigned int status;
		status = disableInterrupts();
		servos[channel].ticks = value;
		restoreInterrupts(status);
	} 
}
예제 #12
0
/* 
   write(value, speed) - Just like write but at reduced speed. 
  
   value - Target position for the servo. Identical use as value of the function write. 
   speed - Speed at which to move the servo. 
           speed=0 - Full speed, identical to write 
           speed=1 - Minimum speed 
           speed=255 - Maximum speed 
 */ 
 void Servo::write(float value, uint8_t speed) { 
   // This fuction is a copy of write and writeMicroseconds but value will be saved 
   // in target instead of in ticks in the servo structure and speed will be save 
   // there too. 
 

   //double degrees = value; 
 
   if (speed) { 
     if (value < MIN_PULSE_WIDTH) { 
       // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds) 
           // updated to use constrain instead of if, pva 
          value = value * 10;//make the value tem times bigger, must after the if() detection or if() will fail
          value = constrain(value, 0, 1800); 
          value = map(value, 0, 1800, SERVO_MIN(),  SERVO_MAX());     
     } 

     // calculate and store the values for the given channel 
     byte channel = this->servoIndex; 
     if( (channel >= 0) && (channel < MAX_SERVOS) ) {   // ensure channel is valid 
           // updated to use constrain instead of if, pva 
           //value = constrain(value, SERVO_MIN(), SERVO_MAX()); 
      //Serial.println(value,DEC);
 
       //value = value - TRIM_DURATION; 
       value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009 
 
       // Set speed and direction 
       uint8_t oldSREG = SREG; 
       cli(); 
       servos[channel].target = value;   
       servos[channel].speed = speed;   
       SREG = oldSREG;    
     } 
   }  
   else { 
     write (value); 
   } 
} 
예제 #13
0
static void initISR(timer16_Sequence_t timer)
{  
    if( timer == _timer1){
        if( SRV_TAUxEN == 0 ){
#ifdef WORKAROUND_READ_MODIFY_WRITE
            SBI2( SRV_SFR2_PERx, SRV_SFR2_BIT_TAUxEN );        /* supplies input clock */
#else
            SRV_TAUxEN = 1U;          /* supplies input clock */
#endif
            SRV_TPSx   = TIMER_CLOCK;
        }

#ifdef WORKAROUND_READ_MODIFY_WRITE
        /* Set INTTM04 low priority */
        SBI( SRV_SFR_PR1xx, SRV_SFR_BIT_TMPR1xx );
        SBI( SRV_SFR_PR0xx, SRV_SFR_BIT_TMPR0xx );
        /* Mask channel 04 interrupt */
        CBI( SRV_SFR_MKxx, SRV_SFR_BIT_TMMKxx );    /* enable INTTM04 interrupt */
        CBI( SRV_SFR_IFxx, SRV_SFR_BIT_TMIFxx );    /* clear INTTM04 interrupt flag */
#else
        /* Set INTTM04 low priority */
        SRV_TMPR1xx = 1U;
        SRV_TMPR0xx = 1U;
        /* Mask channel 04 interrupt */
        SRV_TMMKxx  = 0U;    /* enable INTTM04 interrupt */
        SRV_TMIFxx  = 0U;    /* clear INTTM04 interrupt flag */
#endif
        /* Channel 0 used as interval timer */
        SRV_TMRxx   = 0x8000U;
        SRV_TDRxx   = (unsigned int)usToTicks(REFRESH_INTERVAL);
        SRV_TSx    |= SRV_CHx;     /* operation is enabled (start trigger is generated) */

        delay(1);
        
        Channel[timer] = -1;
        handle_interrupts(_timer1);   /* TDR0x setting */

    }
}
예제 #14
0
void Servo::writeMicroseconds(int value)
{
    // calculate and store the values for the given channel
    byte channel = this->servoIndex;
    if( (channel < MAX_SERVOS) )            // ensure channel is valid
    {
    	if( value < SERVO_MIN() )          // ensure pulse width is valid
            value = SERVO_MIN();
        else if( value > SERVO_MAX() )
            value = SERVO_MAX();
        
        value = value - TRIM_DURATION;
        value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009

#if defined(REL_GR_KURUMI)
        servos[channel].ticks = value;
#else
        noInterrupts();
        servos[channel].ticks = value;
        interrupts();
#endif
    } 
}
void init_servo(void)
{
	// for servo
	SIM_SCGC6 |= SIM_SCGC6_PDB;	// TODO: use bitband for atomic read-mod-write
	pinMode(12, OUTPUT);
	PDB0_MOD = 0xFFFF;
	PDB0_CNT = 0;
	PDB0_IDLY = 0;
	PDB0_SC = PDB_CONFIG;
	NVIC_ENABLE_IRQ(IRQ_PDB);
	// TODO: maybe this should be a higher priority than most
	// other interrupts (init all to some default?)
	PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;

	//servo_active_mask = 9;
	servo_active_mask = 8;
	//servo_pin[0] = 12;
	//servo_ticks[0] = usToTicks(600);
	servo_pin[3] = 11;
	servo_ticks[3] = usToTicks(2100);
	//pinMode(12, OUTPUT);
	pinMode(11, OUTPUT);
}
예제 #16
0
파일: servo.c 프로젝트: AriZuu/micropython
mp_obj_t pyb_Servo(void) {
    uint16_t mask;
    pyb_servo_obj_t *self = m_new_obj(pyb_servo_obj_t);
    self->base.type = &servo_obj_type;
    self->min_usecs = MIN_PULSE_WIDTH;
    self->max_usecs = MAX_PULSE_WIDTH;

    /* Find an unallocated servo id */

    self->servo_id = 0;
    for (mask=1; mask < (1<<MAX_SERVOS); mask <<= 1) {
        if (!(servo_allocated_mask & mask)) {
            servo_allocated_mask |= mask;
            servo_active_mask &= ~mask;
            servo_ticks[self->servo_id] = usToTicks(DEFAULT_PULSE_WIDTH);
            return self;
        }
        self->servo_id++;
    }
    m_del_obj(pyb_servo_obj_t, self);
    mp_raise_ValueError("No available servo ids");
    return mp_const_none;
}
예제 #17
0
// Value is a float, in us. and represents the on-time for this servo pin
// Pin is the pin number being changed
int32_t SoftPWMServoServoWrite(uint32_t Pin, float Value)
{
    SoftPWMServoRawWrite(Pin, usToTicks(Value), SOFTPWMSERVO_SERVO);
    
    return SOFTPWMSERVO_OK;
}
예제 #18
0
파일: user_main.c 프로젝트: mroavi/my-esp
void hwTimerCallback( void )
{
	int i, j;
	int logicState = 1;
	int logicStateLen = 0;
	bool repeatCode = false;

	/* stop the HW TIMER */
	RTC_REG_WRITE(FRC1_CTRL_ADDRESS, DIVDED_BY_16 | TM_EDGE_INT);

	//Set GPIO0 to LOW
	gpio_output_set(0, BIT0, BIT0, 0);

	/* load the HW TIMER for next IR message frame */
	uint32 ticks = usToTicks(70000);
	RTC_REG_WRITE(FRC1_LOAD_ADDRESS, ticks);

	/* derive the raw IR message frame */
	for( i = 0 ; i < ( edgeIndex - 1 ) ; i++)
	{
		/* find number of bits in current interval */
		logicStateLen = ( intervalArr[i] / minInterval );

		for( j = 0 ; j < logicStateLen ; j++)
		{
			rawIrMsg[ rawIrMsgLen ] = logicState;
			rawIrMsgLen++;
		}

		/* toggle state */
		logicState ^= 1;

#if 0
		os_printf( "\r\nDuration of interval %d: %d us\r\n", i, intervalArr[i] );
#endif
	}

#if 1
	/* print the received raw IR message frame */
	os_printf( "\r\nRAW IR CODE: ");
	for ( i = 0 ; i < rawIrMsgLen ; i++ )
	{
		os_printf( "%d", rawIrMsg[i] );
	}
#endif

	/**********************************************
	 * DECODE NEC MESSAGE FRAME!
	 * - every message frame contains 32 coded bits
	 **********************************************/

	/* set index to the beginning of the coded bits */

	/* the message frame starts with a burst of 16 logic 1's, skip them all */
	i = 0 ;
	while ( rawIrMsg[i] == 1 ) i++;

	/* the message frame continues with a burst of 8 logic 0's, skip them all */
	j = 0;
	while (rawIrMsg[i] == 0)
	{
		i++;
		j++;
	}

	/* if the number of zeros is 4, then ignore the current message frame since
	 * it corresponds to a "REPEATED CODE".
	 */
	if ( j <= 4 )
	{
#if 1
		os_printf( "\r\nREPEATED CODE");
#endif
		repeatCode = true;
	}

	/* decode raw message only if it is not a repeat code */
	if (repeatCode == false)
	{
		/* at this point 'i' contains the index of the beginning of the encoded bits */

		/* decode raw message
		 * - [1][0][0][0] 	represents a '1'
		 * - [1][0]			represents a '0'
		 */
		irCmd = 0;
		for (j = 0; j < 32; j++)
		{
			if (rawIrMsg[i + 2] == 0)
			{
				/* it is a '1', so left shift a '1' */
				irCmd = (irCmd << 1) | 1;

				/* move to the beginning of the next encoded bit
				 * (increment i until next 1 in raw message frame)
				 */
				do {i++;} while ( rawIrMsg[i] == 0 );
			}
			else {
				/* it is a '0', so left shift a '0' */
				irCmd = irCmd << 1;

				/* move to the beginning of the next encoded bit */
				i += 2;
			}
		}

#if 1
		/* print the received IR cmd */
		os_printf("\r\nIR CMD: %x", irCmd);
#endif
	}

	/**********************************************
	 * END - DECODE NEC MESSAGE FRAME!
	 * - every message frame contains 32 coded bits
	 **********************************************/

	/* reset index */
	edgeIndex = 0;

#if 1
	os_printf("\r\nEnd of IR message frame\r\n");
#endif

	return;
}
예제 #19
0
파일: user_main.c 프로젝트: mroavi/my-esp
// initialize the custom stuff that goes beyond esp-link
void user_init()
{
	// Initialize the GPIO subsystem.
	gpio_init();

	/* ====================================== */
	/* UART                                   */
	/* ====================================== */

	// Initialize UART0 and UART1
	/* NOTE: UART1 and I2S share same GPIO. Cannot use simultaneously. */
	uart_init( BIT_RATE_115200, BIT_RATE_115200 );

//	uart0_sendStr( "\nUART0 - USED TO PROGRAM THE MODULE\n" );

	os_printf("\n===================\nUART1 - DEBUG OUPUT\n===================\n");

	/* NOTE: PWM CANNOT BE USED SIMULTANEOUSLY WITH HW TIMER */
#if 0
	/* ====================================== */
	/* PWM                                    */
	/* ====================================== */

    uint32  pwm_period = 1000;
	uint32 pwm_duty[PWM_CHANNEL] = {0};


    uint32 io_info[][3] = {   {PWM_0_OUT_IO_MUX,PWM_0_OUT_IO_FUNC,PWM_0_OUT_IO_NUM},
    		                  {PWM_1_OUT_IO_MUX,PWM_1_OUT_IO_FUNC,PWM_1_OUT_IO_NUM},
    		              };

	/* PIN FUNCTION INIT FOR PWM OUTPUT */
	pwm_init(pwm_period, pwm_duty, PWM_CHANNEL, io_info);

	/* set pwm_duty cycle */
	pwm_set_duty (14185, 0);
	pwm_set_duty (22222, 1); // todo: explain why 22222 is the highest possible value

	/* start PWM */
	pwm_start(); // NOTE: PWM causes spikes in other GPIOs
#endif


	/* ====================================== */
	/* GPIO INTERRPUT                         */
	/* ====================================== */

	/* Set GPIO12 in GPIO mode */
	PIN_FUNC_SELECT( PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12 );

	/* Set GPIO12 as input */
	GPIO_DIS_OUTPUT( GPIO_ID_PIN(12) );

	/* Disable all GPIO interrupts */
	ETS_GPIO_INTR_DISABLE();

	/* Set a GPIO callback function */
	ETS_GPIO_INTR_ATTACH( gpioCallback, NULL );

	/* Configure the type of edge */
	gpio_pin_intr_state_set( GPIO_ID_PIN(12), GPIO_PIN_INTR_ANYEDGE );

	ETS_GPIO_INTR_ENABLE();


	/* ====================================== */
	/* SOFTWARE TIMER                         */
	/* ====================================== */

	// Set GPIO0 to output mode
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);

	//Set GPIO0 low
	gpio_output_set(0, RELAY_PIN, RELAY_PIN, 0);

	/* disarm timer */
	os_timer_disarm((ETSTimer*)&some_timer);

	/* set callback */
	os_timer_setfn((ETSTimer*)&some_timer, (os_timer_func_t *) softwareTimerCallback, NULL);

	/* arm the timer -> os_timer_arm(<pointer>, <period in ms>, <fire periodically>) */
	os_timer_arm((ETSTimer*)&some_timer, 10, 1);

	/* ====================================== */
	/* OS TASK                                */
	/* ====================================== */

	/* setup OS task */
//	system_os_task(user_procTask, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen);

	/* send a message to OS task (fire task) */
//	system_os_post(user_procTaskPrio, 0, 0 );


	/* ====================================== */
	/* HARDWARE TIMER                         */
	/* ====================================== */

	/* The hardware timer is used to indicate when a complete IR message frame should have
	 * arrived in order to process the received data and calculate the IR command.
	 *
	 * It is configured in "one-shot" mode. It is started when the beginning of an
	 * IR message frame is detected and stopped after the complete message frame has been read.
	 * This means that the duration of the HW timer should be longer than the duration of
	 * the longest message frame. In the NEC IR tranmission protocol all message frames have
	 * a duration of approximately 67.5ms.
	 */

	/* load the HW TIMER */
	uint32 ticks = usToTicks(70000); // 70ms
	RTC_REG_WRITE(FRC1_LOAD_ADDRESS, ticks);

	/* register callback function */
	ETS_FRC_TIMER1_INTR_ATTACH( hwTimerCallback, NULL );

	/* enable interrupts */
	TM1_EDGE_INT_ENABLE();
	ETS_FRC1_INTR_ENABLE();

	/* don't start timer yet */
	/* the timer is started inside the GPIO INT callback */


	/* ====================================== */
	/* UDP SERVER                         	  */
	/* ====================================== */

	/* usage:	echo <data> | nc -wl -u <ip address> <port>
	 * example: echo "foo" | nc -w1 -u 192.168.1.187 7777 */

	/* allocate space for server */
	pUdpServer = (struct espconn *) os_zalloc(sizeof(struct espconn));

	/* clear allocated memory */
	ets_memset(pUdpServer, 0, sizeof(struct espconn));

	/* create the server */
	espconn_create(pUdpServer);

	/* set the type of server */
	pUdpServer->type = ESPCONN_UDP;

	/* allocate memory for UDP settings */
	pUdpServer->proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));

	/* set the port that the server will be listening to */
	pUdpServer->proto.udp->local_port = 7777;

	/* register the callback */
	espconn_regist_recvcb(pUdpServer, udpServerRxCb);

	/* start listening */
	if (espconn_create(pUdpServer))
	{
		while (1) { os_printf("Error creating a UDP server\n"); }
	}


	/* ====================================== */
	/* WIFI                         	  	  */
	/* ====================================== */

	wifi_set_opmode(STATION_MODE);

	wifi_station_get_config_default(&stconf);

//	os_strncpy((char*) stconf.ssid, "TP-LINK_2.4GHz_FC2E51", 32);
//	os_strncpy((char*) stconf.password, "tonytony", 64);

	os_strncpy((char*) stconf.ssid, "WLAN-PUB", 32);
	os_strncpy((char*) stconf.password, "", 64);

//	os_strncpy((char*) stconf.ssid, "MAD air", 32);
//	os_strncpy((char*) stconf.password, "glioninlog", 64);

	stconf.bssid_set = 0;
	wifi_station_set_config(&stconf);

//	/* ====================================== */
//	/* WS2812 LED STRIP                	  	  */
//	/* ====================================== */
//
//	/* NOTE: UART1 and I2S share same GPIO. Cannot use simultaneously. */
//	ws2812_init();
//
//	/*						G		R		B			*/
//	uint8_t ledout[] = 	{
//							0xff,	0x00,	0x00, 		//4th
////							0xff,	0x00,	0x00,		//3rd
////							0x00,	0xff,	0x00,		//2nd
////							0x00,	0x00,	0xff, 		//1st
//						};
//
//#if 0
//		os_printf("\r\nB R G: %x %x %x\r\n", ledout[0], ledout[1],ledout[2]);
//#endif
//
//	ws2812_push( ledout, sizeof( ledout ) );

	/* ====================================== */
	/* TCP CONNECTION                    	  */
	/* ====================================== */

	/* allocate space for server */
	pTcpConn = (struct espconn *) os_zalloc(sizeof(struct espconn));

	/* clear allocated memory */
	ets_memset(pTcpConn, 0, sizeof(struct espconn));

	/* set the type of connection */
	pTcpConn->type = ESPCONN_TCP;

	/* set state to NONE */
	pTcpConn->state = ESPCONN_NONE;

	/* allocate memory for TCP settings */
	pTcpConn->proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp));

	/* set the port that the connection will be listening to */
	pTcpConn->proto.tcp->local_port = espconn_port();

	/* set the remote port and IP address */
	pTcpConn->proto.tcp->remote_port = 80;
	os_memcpy(pTcpConn->proto.tcp->remote_ip, server_ip_address, sizeof(server_ip_address));

	/* register callbacks */
	espconn_regist_connectcb(pTcpConn, tcpConnCb);
	espconn_regist_reconcb(pTcpConn, tcpReconnCb);

	/* disarm timer */
	os_timer_disarm((ETSTimer*)&wifi_setup_timer);

	/* set callback */
	os_timer_setfn((ETSTimer*)&wifi_setup_timer, (os_timer_func_t *) wifiConnectTimerCb, NULL);

	/* arm the timer -> os_timer_arm(<pointer>, <period in ms>, <fire periodically>) */
	os_timer_arm((ETSTimer*)&wifi_setup_timer, 5000, 1);

	return;

}