Esempio n. 1
0
void gpsTask(void *unused)
{
    gpsData.serial = serialOpen(USART1, 9600);
    gpsData.mode = MODE_NMEA;   // NMEA

    while (1) {
        CoTickDelay(25);

        while (uartAvailable(gpsData.serial)) {
            switch (gpsData.mode) {
            case MODE_NMEA:    // NMEA
                gpsData.validFrames += gpsNewFrameNMEA(uartRead(gpsData.serial));
                break;

            case MODE_UBX:     // UBX
                gpsData.validFrames += gpsNewFrameUBLOX(uartRead(gpsData.serial));
                break;

            case MODE_MTK:     // MTK
                break;

            case MODE_PASSTHROUGH:     // GPS -> UART bridge
                // TODO
                // usbSerialWrite(uartRead(gpsData.serial));
                break;
            }
        }
    }
}
Esempio n. 2
0
/*读两个字节组成一个16位数*/
int16_t ReadW(void)
{
unsigned char BufC;
int16_t BufW;
    
  BufC = uartRead();
  BufW = (uint16_t)BufC;
  BufC = uartRead();
  BufW = (int16_t)(((uint16_t)BufC  << 8) | BufW);
  return BufW;
}
Esempio n. 3
0
int HardwareSerial::read(void)
{
    if(available()) {
        return uartRead(_uart);
    }
    return -1;
}
Esempio n. 4
0
 void sim300Receive(){
     while(uartRead(SIM300_PORT,&simch,1)){
            sim300RcvFeed(&simrcv_t,simch);   
            simrcv_t.idle_ticks=0;
            simrcv_t.received_flag = 1;
     }
   
}
Esempio n. 5
0
int	sio_recv_frame(unsigned char* buf, int size)
{
	int	i, s, c;

	for (i = 0; i < size; i++) {
		while (1) {
			s = uartRead(LSR);		// get status
			if (s & 0x1f) {			// Rx ready
				c = uartRead(RHR);	// read from FIFO
				if (!(s & 0x1e)) {	// no error
					*buf++ = c;
					break;
				}
			}
		}
	}

	return i;
}
Esempio n. 6
0
void SIM300Receive(){
     uint8_t ch;
     while(uartRead(SIM300_PORT,&ch,1)){
         simrcv_t.buf[simrcv_t.index++] = ch;
         simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
         simState.idle_ticks=0;
         simState.received_flag = 1;
    }
            
}
int8_t MG2639_Cell::readBetween(char begin, char end, char * rsp, 
                                 unsigned int timeout)
{
	unsigned long timeIn = millis(); // timeIn stores timestamp where we enter
	bool inString = false; // Flag to keep track of whether we've seen [begin]
	char c = 0; // Char to store currently read character
	int index = 0;
	
	//clearBuffer();
	while (timeIn + timeout > millis()) // While we haven't timed out
	{
		if (inString == false) // Waiting for beginning character
		{
			if (dataAvailable()) // If data is available on UART RX
			{
				c = uartRead();  // Read from UART RX
				if (c == begin)  // If c is the [begin] character
					inString = true; // Set inString to true
			}
		}
		else // in the string
		{
			if (dataAvailable()) // If data is available on UART RX
			{
				c = uartRead();  // Read data in from UART RX
				if (c == end)    // If c is the [end] char, we're done
				{
					rsp[index] = 0; // Terminate the string
					return 1;      // Return success
				}
				else
				{	// Else we add to the response string
					rsp[index++] = c;
				}
			}
		}
	}
	
	// Return fail if we timed out
	//! TODO: Could be a more verbose response. Did we see [begin]? Timeout?
	return 0;
}
Esempio n. 8
0
int	sio_send_frame(const unsigned char *buf, int size)
{
	int	i;

	for (i = 0; i < size; i++) {
		while(!(uartRead(LSR) & 0x20));		// wait for Tx ready
		uartWrite(THR, *buf++);
	}

	return i;
}
Esempio n. 9
0
static void getPos(void)
{
    bool valid_pos = false;
    uint32_t timeout = millis();

    do
    {
        if (uartAvailable())
            valid_pos = gpsDecode((char)uartRead());

    } while((millis() - timeout < VALID_POS_TIMEOUT) && !valid_pos);
}
unsigned int MG2639_Cell::readByteToBuffer()
{
	// Read the data in
	char c = uartRead();	// uart0.read();
	
	// Store the data in the buffer
	rxBuffer[bufferHead] = c;
	//! TODO: Don't care if we overflow. Should we? Set a flag or something?
	bufferHead = (bufferHead + 1) % RX_BUFFER_LENGTH;
	
	return 1;
}
int MG2639_Cell::readUntil(char * dest, char end, int maxChars, 
                            unsigned int timeout)
{
	unsigned long timeIn = millis();
	char c = 0;
	int index = 0;
	
	while ((timeIn + timeout > millis()) && (index < maxChars))
	{
		if (dataAvailable())
		{
			c = uartRead();
			if (c == end)
				return index;
			else
				dest[index++] = c;
		}
	}
	
	if (index >= maxChars)
		return ERROR_OVERRUN_PREVENT;
	
	return ERROR_TIMEOUT;
}
Esempio n. 12
0
int main(void)
{
unsigned char BufC;
uint16_t BufW; 

  /* 系统初始化*/
  systemInit();

  delay_ms(300);
  printf("LEADIY-M3 TEST V2\r\n");

  while (1)
  {
    if(uartAvailable()) //检测是否收到LEADIY-M3数据
    {  
      BufC = uartRead(); //读一个字节
      if(BufC==0xA7){  //判断是否为帧 头
        BufC = uartRead(); //读一个字节
        if (BufC==0x7A) { //判断是否为帧头
          BufC = uartRead(); //读一个字节
          switch(BufC) //帧类型判断
          {
            case 0x70: //标识为角速度帧
              BufC = uartRead(); //帧长度,可不用
              BufC = uartRead(); //效验位
              Gyro[0] = ReadW();      //X轴
              Gyro[1] = ReadW();      //Y轴
              Gyro[2] = ReadW();      //Z轴

              /*GYRO的量程为2000度每秒*/
              /* 得到以"dps" ("度/秒")为单位的角速度值*/
              GyroDPS[0] = (float)Gyro[0]*4/16.4;
              GyroDPS[1] = (float)Gyro[1]*4/16.4;
              GyroDPS[2] = (float)Gyro[2]*4/16.4;

              printf("GYRO X:%d  Y:%d  Z:%d\r\n", Gyro[0], Gyro[1], Gyro[2]);
              printf("GyroDPS X: %.2f, Y: %.2f, Z: %.2f\r\n", GyroDPS[0], GyroDPS[1], GyroDPS[2]);
              break;
            case 0x71: //标识为加速度帧
              BufC = uartRead(); //帧长度,可不用
              BufC = uartRead(); //效验位
              Acc[0] = ReadW();      //X轴
              Acc[1] = ReadW();      //Y轴
              Acc[2] = ReadW();      //Z轴

              /*ACC的量程为8G*/
              /*得到以"g"为单位的加速度*/
              AccG[0] = (float)Acc[0] / 4096;
              AccG[1] = (float)Acc[1] / 4096;
              AccG[2] = (float)Acc[2] / 4096;
              printf("ACC X:%d  Y:%d  Z:%d\r\n", Acc[0], Acc[1], Acc[2]);
              printf("AccG X:%.2f  Y:%.2f  Z:%.2f\r\n", AccG[0], AccG[1], AccG[2]);
              break;
            case 0x72: //标识为姿态帧
              BufC = uartRead(); //帧长度,可不用
              BufC = uartRead(); //效验位
              Angle[0] = ReadW();   //X轴角度(横滚)
              Angle[1] = ReadW();   //Y轴角度(俯仰)
              Angle[2] = ReadW();   //Z轴角度(偏航)

              AngleDeg[0] = (float)Angle[0] / 100;
              AngleDeg[1] = (float)Angle[1] / 100;
              AngleDeg[2] = (float)Angle[2] / 100;
              if (AngleDeg[2]<0) AngleDeg[2] += 360; //将航向值转化到0---360度区间
              printf("ANGLE X:%d  Y:%d  Z:%d \r\n", Angle[0], Angle[1], Angle[2]);
              printf("AngleDeg X:%.2f  Y:%.2f  Z:%.2f \r\n", AngleDeg[0], AngleDeg[1], AngleDeg[2]);
              break;
            case 0x73: //标识为 地磁帧
              BufC = uartRead(); //帧长度,可不用
              BufC = uartRead(); //效验位
              Mag[0] = ReadW();   //X轴
              Mag[1] = ReadW();   //Y轴
              Mag[2] = ReadW();   //Z轴

              /*地磁设置为2.5Ga*/
              /*得到以"Gauss"为单位的地磁*/
              MagGauss[0] = (float)Mag[0] / 660; 
              MagGauss[1] = (float)Mag[1] / 660; 
              MagGauss[2] = (float)Mag[2] / 660; 
              printf("Mag X:%d  Y:%d  Z:%d \r\n", Mag[0], Mag[1], Mag[2]);
              printf("MagGauss X:%.2f  Y:%.2f  Z:%.2f \r\n", MagGauss[0], MagGauss[1], MagGauss[2]);
              break;
            case 0x74: //标识为温度、气压帧
              BufC = uartRead(); //帧长度,可不用
              BufC = uartRead(); //效验位
              Temper = ReadW() / 10;   //X轴
              BufW = ReadW();   //气压低16位
              Pressure = (int32_t)(((uint32_t)(ReadW() << 16))|BufW); 
              printf("Temperature(Degree):%.2f  Pressure(Pa):%d \r\n", Temper, Pressure);
              break;
            case 0x75: // 标识为高度帧
              BufC = uartRead(); //帧长度,可不用
              BufC = uartRead(); //效验位
              BufW = ReadW();   //高度低16位

              /*得到以"CM"为单位的海拔高度*/
              Altitude = (int32_t)(((uint32_t)(ReadW() << 16))|BufW); 
              printf("Altitude(cm):%d \r\n", Altitude);
              break;
            default:  break;
          }
        }
      }
    }
  }

}
Esempio n. 13
0
int8_t sim300Prepare(uint16_t which_mark,uint16_t num_send){
    uint8_t i;
    char * tmp;
    uint8_t tmpch;
    
    gsm_pw = 0;   //GSM 断电信号
    
    PTEDD |= 0x63;
    PTED  |= 0x02;
    
      
        OSTimeDly(OS_TICKS_PER_SEC*5);
    
    
           
            SIM300_PWRKEY_LOW; 
            OSTimeDly(OS_TICKS_PER_SEC);
            SIM300_PWRKEY_HIGH;
            OSTimeDly(OS_TICKS_PER_SEC*8); 
            SIM300_PWR_OFF;
     OSTimeDly(OS_TICKS_PER_SEC*5);
    
    uartInit(SIM300_PORT,9600,0,'n');
 #if (SIM300_DEBUG == 1)    
    uartInit(0,9600,0,'n'); 
#endif   
    sim300RcvInit();
    sim300RcvFlush();
    sim300RcvUartClr();
    
    SIM300_PWR_ON;
    SIM300_PWRKEY_HIGH;
    OSTimeDly(OS_TICKS_PER_SEC*3);    
    SIM300_PWRKEY_LOW; 
    OSTimeDly(OS_TICKS_PER_SEC*2);
    SIM300_PWRKEY_HIGH;
    
    
    sim_state_machine = SIM_S_IDLE;  
    udp_backed = 0;   //是否有udp接收帧
    
    //取得RDY信号
   
   
   
    for(i=0;i<3;i++){
          
          OSTimeDly(OS_TICKS_PER_SEC*10);
           while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
        tmp = strstr((char *)simrcv_t.buf,"Call"); 
        if(NULL == tmp){
#if (SIM300_DEBUG == 1)    
        uartWrite(0,"not RDY\r\n",9);
#endif             
        }else{
            i = 5;   
        }
    }
    if( 3 == i){   // 没有正常RDY
            return ERROR_RDY;
    }
    
    //RDY判断结束
    //发送AT复位   
    for(i=0;i<3;i++){
        
        uartWrite(SIM300_PORT,AT,strlen(AT));
        OSTimeDly(OS_TICKS_PER_SEC*3);
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
        tmp = strstr((char *)simrcv_t.buf,"OK"); 
        if(NULL == tmp){
    #if (SIM300_DEBUG == 1)    
            uartWrite(0,"at ok error\r\n",13);
    #endif             
         }else{
                i = 5;   
         }  
    }
    if( 3 == i){   // 没有正常AT
            return ERROR_AT;
    }
    //AT 正常回复
    gsm_pw = 1;   //GSM 供电信号
    
    //设置回显模式
    uartWrite(SIM300_PORT, "ATE0\r\n",6);
    OSTimeDly(OS_TICKS_PER_SEC*2);
    
    uartWrite(SIM300_PORT, CMGF,strlen(CMGF));
    OSTimeDly(OS_TICKS_PER_SEC*2);
    
       //设置ip报头模式
    uartWrite(SIM300_PORT, "AT+CIPHEAD=1\r\n",14);
    OSTimeDly(OS_TICKS_PER_SEC*3);
    sim300RcvUartClr();
    OSTimeDly(OS_TICKS_PER_SEC);  
    






#if  (1 == MULTI_IP)
    uartWrite(SIM300_PORT, CIPMUX,strlen(CIPMUX));
    OSTimeDly(OS_TICKS_PER_SEC*2);  
#endif 
    //链接CMNET
     for(i=0;i<3;i++){
        uartWrite(SIM300_PORT,CSTT,strlen(CSTT));
        OSTimeDly(OS_TICKS_PER_SEC*5);
            sim300RcvFlush();
           while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
            tmp = strstr((char *)simrcv_t.buf,"OK"); 
            if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CSTT error\r\n",15);
        #endif             
             }else{
                    i = 5;   
             }  
    }
    if( 3 == i){   // 没有正常AT
            return ERROR_CSTT;
    }  
    
    
    
    //链接CMNET结束   
    //启动gprs网络     //需要等待时间比较长,
        uartWrite(SIM300_PORT,CIICR,strlen(CIICR));
        sim300RcvFlush();
        for(i=0;i<3;i++){
        
        OSTimeDly(OS_TICKS_PER_SEC*7);
        
       while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
         tmp = strstr((char *)simrcv_t.buf,"OK"); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CIICR error\r\n",16);
        #endif             
         }else{
#if (SIM300_DEBUG == 1)           
                    uartWrite(0,"CIICR OK\r\n",10);
#endif                     
                    i = 5;   
         }  
    }
    if( 3 == i){   // 没有正常AT
            return ERROR_CIICR;
    }
    
    //设置ip报头模式
/*    uartWrite(SIM300_PORT, "AT+CIPMUX=0\r\n",13);
    OSTimeDly(OS_TICKS_PER_SEC*4);
    sim300RcvUartClr();    */
    //启动gprs网络结束
    //获取IP地址
    for(i=0;i<3;i++){
        uartWrite(SIM300_PORT,CIFSR,strlen(CIFSR));
        OSTimeDly(OS_TICKS_PER_SEC*5);
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
         tmp = strstr((char *)simrcv_t.buf,"."); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CIFSR error\r\n",16);
        #endif             
         }else{
                    i = 5;   
         }  
    }
    if( 3 == i){   // 没有正常AT
            return ERROR_CIFSR;
    } 
    //获取IP地址结束   
    //创建udp链接
       
#if  (1 == MULTI_IP)
//第一个站点开始
    for(i=0;i<3;i++){
    uartWrite(SIM300_PORT,CIPSTART_M0,strlen(CIPSTART_M0));
    uartWrite(SIM300_PORT,"\"",1);
    uartWrite(SIM300_PORT,ipaddress,strlen(ipaddress));
    uartWrite(SIM300_PORT,"\",",2);
    uartWrite(SIM300_PORT,udpport,strlen(udpport));
    uartWrite(SIM300_PORT,"\r\n",2);
    
     OSTimeDly(OS_TICKS_PER_SEC*5+(mcu_time_count&0x000000ff));
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
         tmp = strstr((char *)simrcv_t.buf,"OK"); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CIPSTART error\r\n",19);
        #endif             
         } else{
                    i = 5;   
         }  
    }
    
    OSTimeDly(OS_TICKS_PER_SEC*3+(mcu_time_count&0x000000ff));
    uartWrite(SIM300_PORT,CIPSEND36_M0,strlen(CIPSEND36_M0));
    
    hex_BCD(num_send);
    uartWrite(SIM300_PORT,ASC_buf,3);
    uartWrite(SIM300_PORT,"\r",1);
    
    OSTimeDly(OS_TICKS_PER_SEC*2);
           
           
       if(which_mark==0)
       {
        
           uartWrite(SIM300_PORT,prt_frame,num_send);
         
         if(0 == reUDPsend){
              reUDP_times = 1;  
         }
         
         task_active[TASKACTIVE_SAMPLE]++;
         SIM300Waiting(40);
         if(reUDP_times>0){
           reUDPsend = 1;
           reUDP_times--;  
         }else{
            reUDPsend = 0;
   
         }
         }else 
          uartWrite(SIM300_PORT,prt_frame,num_send);
          
           OSTimeDly(OS_TICKS_PER_SEC*5);
       
    ///第一个站点结束
    
    //第二个站点开始
    if((ipadd_other[0][0]>='0')&&(ipadd_other[0][0]<='9')) {
        
    for(i=0;i<3;i++){
    uartWrite(SIM300_PORT,CIPSTART_M1,strlen(CIPSTART_M1));
    uartWrite(SIM300_PORT,"\"",1);
    uartWrite(SIM300_PORT,ipadd_other[0],strlen(ipadd_other[0]));
    uartWrite(SIM300_PORT,"\",",2);
    uartWrite(SIM300_PORT,udpport,strlen(udpport));
    uartWrite(SIM300_PORT,"\r\n",2);
    
     OSTimeDly(OS_TICKS_PER_SEC*5+(mcu_time_count&0x000000ff));
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
         tmp = strstr((char *)simrcv_t.buf,"OK"); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CIPSTART error\r\n",19);
        #endif             
         } else{
                    i = 5;   
         }  
    }
    
    OSTimeDly(OS_TICKS_PER_SEC*3+(mcu_time_count&0x000000ff));
    uartWrite(SIM300_PORT,CIPSEND36_M1,strlen(CIPSEND36_M1));
        hex_BCD(num_send);
    uartWrite(SIM300_PORT,ASC_buf,3);
    uartWrite(SIM300_PORT,"\r",1);
    
    OSTimeDly(OS_TICKS_PER_SEC*2);
           
           
       if(which_mark==0)
       {
        
           uartWrite(SIM300_PORT,prt_frame,num_send);
       }else 
          uartWrite(SIM300_PORT,prt_frame,num_send); 
           OSTimeDly(OS_TICKS_PER_SEC*5);
         
     
    }
    ///第二个站点结束
    //第三个站点开始
    if((ipadd_other[1][0]>='0')&&(ipadd_other[1][0]<='9')) {
        
    for(i=0;i<3;i++){
    uartWrite(SIM300_PORT,CIPSTART_M2,strlen(CIPSTART_M2));
    uartWrite(SIM300_PORT,"\"",1);
    uartWrite(SIM300_PORT,ipadd_other[1],strlen(ipadd_other[1]));
    uartWrite(SIM300_PORT,"\",",2);
    uartWrite(SIM300_PORT,udpport,strlen(udpport));
    uartWrite(SIM300_PORT,"\r\n",2);
    
     OSTimeDly(OS_TICKS_PER_SEC*5+(mcu_time_count&0x000000ff));
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
         tmp = strstr((char *)simrcv_t.buf,"OK"); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CIPSTART error\r\n",19);
        #endif             
         } else{
                    i = 5;   
         }  
    }
    
    OSTimeDly(OS_TICKS_PER_SEC*3+(mcu_time_count&0x000000ff));
    uartWrite(SIM300_PORT,CIPSEND36_M2,strlen(CIPSEND36_M2));
           hex_BCD(num_send);
    uartWrite(SIM300_PORT,ASC_buf,3);
    uartWrite(SIM300_PORT,"\r",1);
    
    OSTimeDly(OS_TICKS_PER_SEC*2);
           
           
       if(which_mark==0)
       {
        
           uartWrite(SIM300_PORT,prt_frame,num_send);
       }else 
          uartWrite(SIM300_PORT,prt_frame,num_send);
           OSTimeDly(OS_TICKS_PER_SEC*5);

    }
    ///第三个站点结束
    //第四个站点开始
    if((ipadd_other[2][0]>='0')&&(ipadd_other[2][0]<='9')) {
        
    for(i=0;i<3;i++){
    uartWrite(SIM300_PORT,CIPSTART_M3,strlen(CIPSTART_M3));
    uartWrite(SIM300_PORT,"\"",1);
    uartWrite(SIM300_PORT,ipadd_other[2],strlen(ipadd_other[2]));
    uartWrite(SIM300_PORT,"\",",2);
    uartWrite(SIM300_PORT,udpport,strlen(udpport));
    uartWrite(SIM300_PORT,"\r\n",2);
    
     OSTimeDly(OS_TICKS_PER_SEC*5+(mcu_time_count&0x000000ff));
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
         tmp = strstr((char *)simrcv_t.buf,"OK"); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CIPSTART error\r\n",19);
        #endif             
         } else{
                    i = 5;   
         }  
    }
    
    OSTimeDly(OS_TICKS_PER_SEC*3+(mcu_time_count&0x000000ff));
    uartWrite(SIM300_PORT,CIPSEND36_M3,strlen(CIPSEND36_M3));
           hex_BCD(num_send);
    uartWrite(SIM300_PORT,ASC_buf,3);
    uartWrite(SIM300_PORT,"\r",1);
    
    OSTimeDly(OS_TICKS_PER_SEC*2);
           
           
       if(which_mark==0)
       {
        
           uartWrite(SIM300_PORT,prt_frame,num_send);
       }else 
          uartWrite(SIM300_PORT,prt_frame,num_send);
           OSTimeDly(OS_TICKS_PER_SEC*5);
         
    
    }
    ///第四个站点结束
#else
    
    for(i=0;i<3;i++){
    uartWrite(SIM300_PORT,CIPSTART1,strlen(CIPSTART1));
    uartWrite(SIM300_PORT,"\"",1);
    uartWrite(SIM300_PORT,ipaddress,strlen(ipaddress));
    uartWrite(SIM300_PORT,"\",",2);
    uartWrite(SIM300_PORT,udpport,strlen(udpport));
    uartWrite(SIM300_PORT,"\r\n",2);
    
     OSTimeDly(OS_TICKS_PER_SEC*5+(mcu_time_count&0x000000ff));
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
         tmp = strstr((char *)simrcv_t.buf,"OK"); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"at CIPSTART error\r\n",19);
        #endif             
         } else{
                    i = 5;   
         }  
    }
    if( 3 == i){   // 没有正常AT
            return ERROR_CIPSTART;
    } 
    
    
    OSTimeDly(OS_TICKS_PER_SEC*3+(mcu_time_count&0x000000ff));
    uartWrite(SIM300_PORT,CIPSEND36,strlen(CIPSEND36));
          OSTimeDly(OS_TICKS_PER_SEC*2);
           uartWrite(SIM300_PORT,(uint8_t *)&rtufile,38);
           OSTimeDly(OS_TICKS_PER_SEC*5);
         
            
#endif         
/*    upd 接受处理,SIM300Waiting 实验屏蔽
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
           }
         tmp = strstr((char *)simrcv_t.buf,"+IPD"); 
         if(NULL == tmp){
        #if (SIM300_DEBUG == 1)    
                uartWrite(0,"no UDP data\r\n",13);
        #endif             
         } else{
         #if (SIM300_DEBUG == 1)  
                   uartWrite(0,"got UDP\r\n",9); 
         #endif
         
           UDPDecode(tmp);   
         }  */
         
         task_active[TASKACTIVE_SAMPLE]++;
         SIM300Waiting(40);
         SIM300msg();
         #if (SIM300_DEBUG == 1)
                msg_num += '0';    
                uartWrite(0,&msg_num,1);
        #endif          
         
         
    //       OSTimeDly(OS_TICKS_PER_SEC*5);
           
     //        SIM300_PWRKEY_LOW; 
     //       OSTimeDly(OS_TICKS_PER_SEC);
     //       SIM300_PWRKEY_HIGH;
     //       OSTimeDly(OS_TICKS_PER_SEC*8); 
     //       SIM300_PWR_OFF;
            return 0;          
    
    
    
}
Esempio n. 14
0
void loadEffectsFromHost(void)
{
	initializeEffects();
	
	uartInit();
	
	char received[500];
	for (int i = 0; i < 500; ++i)
	{
		received[i] = '\0';
	}
	
		
	int write = 0;
	bool done = _FALSE;
	while ((!done) && (write < 500))
	{
		while (!uartIsDataReady())
			;
		
		received[write] = uartRead();
		if (received[write] == ESCAPE_MESSAGE_END)
		{
			done = _TRUE;
		}
		
		write++;
	}
	
	if (write > 500) 
	{
		error("Received message is over 500 characters and contains no ESCAPE_MESSAGE_END character.");
	}

	int read = 0;
	int effect_idx = 0;
	while ((read < write) && (received[read] != ESCAPE_MESSAGE_END))
	{
		// First comes the effect's name
		effects[effect_idx].in_use = _TRUE;
		
		asciiToString(received, &read, effects[effect_idx].name, EFFECT_NAME_LENGTH);
		
		// We're now at the parameters
		
		int param_idx = 0;
		
		while (received[read] != ESCAPE_EFFECT_END)
		{
			// Parameter name
			asciiToString(received, &read, effects[effect_idx].params[param_idx].name, PARAM_NAME_LENGTH);

			// Parameter values, in order: min - regular - max
			effects[effect_idx].params[param_idx].min = asciiToInt2d(received, &read);
			effects[effect_idx].params[param_idx].regular = asciiToInt2d(received, &read);
			effects[effect_idx].params[param_idx].max = asciiToInt2d(received, &read);
			
			// Each parameters starts set at the regular value
			effects[effect_idx].params[param_idx].current = effects[effect_idx].params[param_idx].regular;
			
			effects[effect_idx].params[param_idx].in_use = _TRUE;
			param_idx++;
			
			// We're now at the next parameter (or next effect, or message ending)
		}
		
		effect_idx++;
		
		read++; // Advance to the next effect (or message ending)
	}
	
	numLoadedEffects = effect_idx;
}
Esempio n. 15
0
 //清除sim300串口接收fifo缓冲区
 void sim300RcvUartClr(){
    while(uartRead(SIM300_PORT,&simch,1)){
           ;
     }
 }
Esempio n. 16
0
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
    uint32_t currentTime;

    /*!< At this stage the microcontroller clock setting is already configured,
         this is done through SystemInit() function which is called from startup
         file (startup_stm32f3xx.s) before to branch to application main.
         To reconfigure the default setting of SystemInit() function, refer to
          system_stm32f4xx.c file
    */

    systemReady = false;

    systemInit();

    systemReady = true;

    //evrPush(EVR_StartingMain, 0);

    /* Setup SysTick Timer for 1 msec interrupts.
       ------------------------------------------
      1. The SysTick_Config() function is a CMSIS function which configure:
         - The SysTick Reload register with value passed as function parameter.
         - Configure the SysTick IRQ priority to the lowest value (0x0F).
         - Reset the SysTick Counter register.
         - Configure the SysTick Counter clock source to be Core Clock Source (HCLK).
         - Enable the SysTick Interrupt.
         - Start the SysTick Counter.

      2. You can change the SysTick Clock source to be HCLK_Div8 by calling the
         SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8) just after the
         SysTick_Config() function call. The SysTick_CLKSourceConfig() is defined
         inside the misc.c file.

      3. You can change the SysTick IRQ priority by calling the
         NVIC_SetPriority(SysTick_IRQn,...) just after the SysTick_Config() function
         call. The NVIC_SetPriority() is defined inside the core_cm4.h file.

      4. To adjust the SysTick time base, use the following formula:

           Reload Value = SysTick Counter Clock (Hz) x  Desired Time base (s)

         - Reload Value is the parameter to be passed for SysTick_Config() function
         - Reload Value should not exceed 0xFFFFFF
     */

#if 1
    if (APRS_SLOT >= 0)
    {
        do
        {
/*
            while (!uartAvailable())
                sleep();
*/
        } while (!gpsDecode((char)uartRead()));

        next_aprs = millis() + 1000 * (APRS_PERIOD - (gps_seconds + APRS_PERIOD - APRS_SLOT) % APRS_PERIOD);
    }
    else
    {
        next_aprs = millis();
    }
#endif

    while (1)
    {
        //evrCheck();

        // Wait for sampling clock to overflow
        if (TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) != RESET)
        {
            ;
        }

#if 1
        if ((int32_t)(millis() - next_aprs) >= 0)
        {
            getPos();
            aprsSend();
            next_aprs += APRS_PERIOD * 1000L;

            while(afskBusy())
                ;

            //sleep();
#if DEBUG_MODEM
            afskDebug();
#endif
        }

        //sleep();
#else

        ///////////////////////////////

        if (frame_500Hz)
        {
            frame_500Hz = false;

            currentTime       = micros();
            deltaTime500Hz    = currentTime - previous500HzTime;
            previous500HzTime = currentTime;

            executionTime500Hz = micros() - currentTime;
        }

        ///////////////////////////////

        if (frame_100Hz)
        {
            frame_100Hz = false;

            currentTime       = micros();
            deltaTime100Hz    = currentTime - previous100HzTime;
            previous100HzTime = currentTime;

            executionTime100Hz = micros() - currentTime;
        }

        ///////////////////////////////

        if (frame_50Hz)
        {
            frame_50Hz = false;

            currentTime      = micros();
            deltaTime50Hz    = currentTime - previous50HzTime;
            previous50HzTime = currentTime;

#if 1
            while (uartAvailable())
            {
                gpsDecode((char)uartRead());
            }
#endif

            executionTime50Hz = micros() - currentTime;
        }

        ///////////////////////////////

        if (frame_10Hz)
        {
            frame_10Hz = false;

            currentTime      = micros();
            deltaTime10Hz    = currentTime - previous10HzTime;
            previous10HzTime = currentTime;

            cliCom();

            executionTime10Hz = micros() - currentTime;
        }

        ///////////////////////////////

        if (frame_5Hz)
        {
            frame_5Hz = false;

            currentTime     = micros();
            deltaTime5Hz    = currentTime - previous5HzTime;
            previous5HzTime = currentTime;

            executionTime5Hz = micros() - currentTime;
        }

        ///////////////////////////////

        if (frame_1Hz)
        {
            frame_1Hz = false;

            currentTime     = micros();
            deltaTime1Hz    = currentTime - previous1HzTime;
            previous1HzTime = currentTime;

            if (execUp == true) {
                ledToggle(LED0);
#ifdef DEBUG_MODEM
                afskDebug();
#endif
            }

            if (execUp == false)
                execUpCount++;

            if ((execUpCount == 5) && (execUp == false))
            {
                execUp = true;
                ledOFF(LED0);
            }

            executionTime1Hz = micros() - currentTime;
        }
#endif
    }
}
Esempio n. 17
0
uint8_t uartReadPoll(void)
{
    while (!uartAvailable()); // wait for some bytes
    return uartRead();
}
Esempio n. 18
0
void serialCom(void)
{
    uint8_t c;
    static uint8_t offset;
    static uint8_t dataSize;
    static enum _serial_state {
        IDLE,
        HEADER_START,
        HEADER_M,
        HEADER_ARROW,
        HEADER_SIZE,
        HEADER_CMD,
    } c_state = IDLE;

    // in cli mode, all uart stuff goes to here. enter cli mode by sending #
    if (cliMode) {
        cliProcess();
        return;
    }

    while (uartAvailable()) {
        c = uartRead();

        if (c_state == IDLE) {
            c_state = (c == '$') ? HEADER_START : IDLE;
            if (c_state == IDLE)
                evaluateOtherData(c); // evaluate all other incoming serial data
        } else if (c_state == HEADER_START) {
            c_state = (c == 'M') ? HEADER_M : IDLE;
        } else if (c_state == HEADER_M) {
            c_state = (c == '<') ? HEADER_ARROW : IDLE;
        } else if (c_state == HEADER_ARROW) {
            if (c > INBUF_SIZE) {       // now we are expecting the payload size
                c_state = IDLE;
                continue;
            }
            dataSize = c;
            offset = 0;
            checksum = 0;
            indRX = 0;
            checksum ^= c;
            c_state = HEADER_SIZE;      // the command is to follow
            guiConnected = true;
        } else if (c_state == HEADER_SIZE) {
            cmdMSP = c;
            checksum ^= c;
            c_state = HEADER_CMD;
        } else if (c_state == HEADER_CMD && offset < dataSize) {
            checksum ^= c;
            inBuf[offset++] = c;
        } else if (c_state == HEADER_CMD && offset >= dataSize) {
            if (checksum == c) {        // compare calculated and transferred checksum
                evaluateCommand();      // we got a valid packet, evaluate it
            }
            c_state = IDLE;
        }
    }
    if (!cliMode && !uartAvailable() && feature(FEATURE_TELEMETRY) && f.ARMED) { // The first 2 conditions should never evaluate to true but I'm putting it here anyway - silpstream
        sendTelemetry();
        return;
    }
}
Esempio n. 19
0
static BT_s32 file_read(BT_HANDLE hUart, BT_u32 ulFlags, BT_u32 ulSize, void *pBuffer) {
	return uartRead(hUart, ulFlags, ulSize, pBuffer);
}
Esempio n. 20
0
void serialCom(void)
{
    uint8_t c;
    bool HaveSomePacket = false;
    static uint8_t NumberSignCNT = 0, RcharCNT = 0, RetCNT = 0;

// START Common Stuff for serial protocols
    if (cfg.rssicut && rssi <= cfg.rssicut) rssi = 0;
// END Common Stuff for serial protocols
  
    if (cliMode)                                                                    // in cli mode, all uart stuff goes to here. enter cli mode by sending #####
    {
        cliProcess();
        return;
    }
    
    if (f.ARMED)                                                                    // Change Protocol according to armed state
    {
        switch(cfg.tele_prot)                                                       // 0=Keep Multiwii @CurrentUSB Baud, 1=Frsky @9600Baud, 2=Mavlink @CurrentUSB Baud, 3=Mavlink @57KBaud (like stock minimOSD wants it)
        {
        case 0:
            Currentprotocol = PROTOCOL_MWII21;
            break;
        case 1:                                                                     // Do Frsky here
            sendFRSKYTelemetry();
            break;
        case 2:
        case 3:
            Currentprotocol = PROTOCOL_MAVLINK;
            break;
        }
    }
    else                                                                            // Not armed engage autosensing here
    {
        if (!BlockProtocolChange && ((currentTimeMS - LastValidProtocolTimestampMS) > 4000))
        Currentprotocol = PROTOCOL_AUTOSENSE;                                       // Set Protocol to unknown after 4 Sek of garbage or no inputdata
    }

    switch(Currentprotocol)
    {
    case PROTOCOL_MAVLINK:
        baseflight_mavlink_send_updates();                                          // Sends Heartbeat as well
        break;
    case PROTOCOL_AUTOSENSE:
        baseflight_mavlink_send_1Hzheartbeat();                                     // It will time itself so no doubleheartbeat from sendupdates are here
    default:                                                                        // Mwii not specially done here because it just sends when asked to (see below)
        break;
    }
  
    while (uartAvailable())
    {
        c = uartRead();
        if (Currentprotocol == PROTOCOL_AUTOSENSE)                                  // Check for extra Data when no protocol active (that is only in disarmed state possible)
        {
            if (c == '#')
            {
                NumberSignCNT++;
                if (NumberSignCNT > 2) cliProcess();                                // This is a one way - reset - street
            }else NumberSignCNT = 0;

            if (c == 'R')
            {
                RcharCNT++;
                if (RcharCNT > 2) systemReset(true);                                // This is a one way - reset - street
            }else RcharCNT = 0;
        }

        if (!f.ARMED && c == '\r')                                                  // Check for 3 Times Return in a row
        {
            RetCNT++;
            if (RetCNT > 2) cliProcess();
        }else RetCNT = 0;

        switch(Currentprotocol)
        {
        case PROTOCOL_AUTOSENSE:                                                    // Current is Unsure
            if(baseflight_mavlink_receive(c))Currentprotocol = PROTOCOL_MAVLINK;
            else if(mwii_receive(c)) Currentprotocol = PROTOCOL_MWII21;
            if(Currentprotocol != PROTOCOL_AUTOSENSE) HaveSomePacket = true;        // Some protocol found
            break;
        case PROTOCOL_MWII21:                                                       // Current is Mwii
            HaveSomePacket = mwii_receive(c);
            break;
        case PROTOCOL_MAVLINK:                                                      // Current is Mavlink
            HaveSomePacket = baseflight_mavlink_receive(c);
            break;
        }
        if(HaveSomePacket) LastValidProtocolTimestampMS = currentTimeMS;
    }
}
Esempio n. 21
0
void serialCom(bool singlestep)                                                     // Singlestep means you can restrict to decoding just one dataset per run
{                                                                                   // Reason: Reduce priority when other tasks need more.
    uint8_t c;
    bool HaveSomePacket = false, Skipnow = false;
    static uint8_t NumberSignCNT = 0, RcharCNT = 0, RetCNT = 0, SingleStepCnt;

    if (singlestep) SingleStepCnt = min(SingleStepCnt+1, 4);
    else SingleStepCnt = 0;
    if (SingleStepCnt > 3) singlestep = false;                                      // Limit singlestep to max 3. in a row
// START Common Stuff for serial protocols
    if (cfg.rssicut && rssi <= cfg.rssicut) rssi = 0;
// END Common Stuff for serial protocols
    if (f.ARMED)                                                                    // Change Protocol according to armed state
    {
        switch(cfg.tele_prot)                                                       // 0=Keep Multiwii @CurrentUSB Baud, 1=Frsky @9600Baud, 2=Mavlink @CurrentUSB Baud, 3=Mavlink @57KBaud (like stock minimOSD wants it)
        {
        case 0:
            Currentprotocol = PROTOCOL_MWII21;
            break;
        case 1:                                                                     // Do Frsky here
            sendFRSKYTelemetry();
            break;
        case 2:
        case 3:
            Currentprotocol = PROTOCOL_MAVLINK;
            break;
        }
    }
    else                                                                            // Not armed engage autosensing here
    {
        if (AllowProtocolAutosense && ((currentTimeMS - LastValidProtocolTimestampMS) > 4000))
        Currentprotocol = PROTOCOL_AUTOSENSE;                                       // Set Protocol to unknown after 4 Sek of garbage or no inputdata
    }

    switch(Currentprotocol)
    {
    case PROTOCOL_MAVLINK:
        baseflight_mavlink_send_updates();                                          // Sends Heartbeat as well
        break;
    case PROTOCOL_AUTOSENSE:
        baseflight_mavlink_send_1Hzheartbeat();                                     // It will time itself so no doubleheartbeat from sendupdates are here
    default:                                                                        // Mwii not specially done here because it just sends when asked to (see below)
        break;
    }
  
    while (uartAvailable() && !Skipnow)
    {
        c = uartRead();
        if (Currentprotocol == PROTOCOL_AUTOSENSE)                                  // Check for extra Data when no protocol active (that is only in disarmed state possible)
        {
            if (c == '#')
            {
                NumberSignCNT++;
                if (NumberSignCNT > 2) cliProcess();                                // This is a one way - reset - street
            }else NumberSignCNT = 0;

            if (c == 'R')
            {
                RcharCNT++;
                if (RcharCNT > 2) systemReset(true);                                // This is a one way - reset - street
            }else RcharCNT = 0;
        }
        if (!f.ARMED && c == '\r')                                                  // Check for 3 Times Return in a row
        {
            RetCNT++;
            if (RetCNT > 2) cliProcess();
        }else RetCNT = 0;

        switch(Currentprotocol)
        {
        case PROTOCOL_AUTOSENSE:                                                    // Current is Unsure
            if(baseflight_mavlink_receive(c))Currentprotocol = PROTOCOL_MAVLINK;
            else if(mwii_receive(c)) Currentprotocol = PROTOCOL_MWII21;
            if(Currentprotocol != PROTOCOL_AUTOSENSE) HaveSomePacket = true;        // Some protocol found
            break;
        case PROTOCOL_MWII21:                                                       // Current is Mwii
            HaveSomePacket = mwii_receive(c);
            break;
        case PROTOCOL_MAVLINK:                                                      // Current is Mavlink
            HaveSomePacket = baseflight_mavlink_receive(c);
            break;
        }
        if(HaveSomePacket)
        {
            LastValidProtocolTimestampMS = currentTimeMS;
            if (singlestep) Skipnow = true;
        }
    }
}
Esempio n. 22
0
int8_t sim300FirstOn(){
  
    uint8_t i;
    char * tmp;
    uint8_t tmpch;
    
    gsm_pw = 0;   //GSM 断电信号
    
    PTEDD |= 0x63;
    PTED  |= 0x02;
    
    OSTimeDly(OS_TICKS_PER_SEC*5);
    
    
           
            SIM300_PWRKEY_LOW; 
            OSTimeDly(OS_TICKS_PER_SEC);
            SIM300_PWRKEY_HIGH;
            OSTimeDly(OS_TICKS_PER_SEC*8); 
            SIM300_PWR_OFF;
     OSTimeDly(OS_TICKS_PER_SEC*5);
    
    uartInit(SIM300_PORT,9600,0,'n');
 #if (SIM300_DEBUG == 1)    
    uartInit(0,9600,0,'n'); 
#endif   
    sim300RcvInit();
    sim300RcvFlush();
    sim300RcvUartClr();
    
    SIM300_PWR_ON;
    SIM300_PWRKEY_HIGH;
    OSTimeDly(OS_TICKS_PER_SEC*3);    
    SIM300_PWRKEY_LOW; 
    OSTimeDly(OS_TICKS_PER_SEC*2);
    SIM300_PWRKEY_HIGH;
    
    
    sim_state_machine = SIM_S_IDLE;  
    udp_backed = 0;   //是否有udp接收帧
    
    //取得RDY信号
    for(i=0;i<3;i++){
          
          OSTimeDly(OS_TICKS_PER_SEC*10);
           while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
        tmp = strstr((char *)simrcv_t.buf,"Call"); 
        if(NULL == tmp){
#if (SIM300_DEBUG == 1)    
        uartWrite(0,"not RDY\r\n",9);
#endif             
        }else{
            i = 5;   
        }
    }
    if( 3 == i){   // 没有正常RDY
            return ERROR_RDY;
    }
    
    //RDY判断结束
    //发送AT复位   
    for(i=0;i<3;i++){
        
        uartWrite(SIM300_PORT,AT,strlen(AT));
        OSTimeDly(OS_TICKS_PER_SEC*3);
        sim300RcvFlush();
        while(uartRead(SIM300_PORT,&tmpch,1)){
               if(0 != tmpch){
                simrcv_t.buf[simrcv_t.index++] = tmpch;
               simrcv_t.index = ((simrcv_t.index > (simrcv_t.buf_len-2))? (simrcv_t.buf_len-2):simrcv_t.index);
               }
           }
        tmp = strstr((char *)simrcv_t.buf,"OK"); 
        if(NULL == tmp){
    #if (SIM300_DEBUG == 1)    
            uartWrite(0,"at ok error\r\n",13);
    #endif             
         }else{
                i = 5;   
         }  
    }
    if( 3 == i){   // 没有正常AT
            return ERROR_AT;
    }
    //AT 正常回复
    gsm_pw = 1;   //GSM 供电信号
}
Esempio n. 23
0
File: cli.c Progetto: DuinoPilot/TMR
void cliProcess(void)
{
    if (!cliMode) {
        cliMode = 1;
        uartPrint("\r\nEntering CLI Mode, type 'exit' to return, or 'help'\r\n");
        cliPrompt();
    }

    while (uartAvailable()) {
        uint8_t c = uartRead();
        if (c == '\t' || c == '?') {
            // do tab completion
            const clicmd_t *cmd, *pstart = NULL, *pend = NULL;
            int i = bufferIndex;
            for (cmd = cmdTable; cmd < cmdTable + CMD_COUNT; cmd++) {
                if (bufferIndex && (strncasecmp(cliBuffer, cmd->name, bufferIndex) != 0))
                    continue;
                if (!pstart)
                    pstart = cmd;
                pend = cmd;
            }
            if (pstart) {    /* Buffer matches one or more commands */
                for (; ; bufferIndex++) {
                    if (pstart->name[bufferIndex] != pend->name[bufferIndex])
                        break;
                    if (!pstart->name[bufferIndex]) {
                        /* Unambiguous -- append a space */
                        cliBuffer[bufferIndex++] = ' ';
                        break;
                    }
                    cliBuffer[bufferIndex] = pstart->name[bufferIndex];
                }
            }
            if (!bufferIndex || pstart != pend) {
                /* Print list of ambiguous matches */
                uartPrint("\r\033[K");
                for (cmd = pstart; cmd <= pend; cmd++) {
                    uartPrint(cmd->name);
                    uartWrite('\t');
                }
                cliPrompt();
                i = 0;    /* Redraw prompt */
            }
            for (; i < bufferIndex; i++)
                uartWrite(cliBuffer[i]);
        } else if (!bufferIndex && c == 4) {
            cliExit(cliBuffer);
            return;
        } else if (c == 12) {
            // clear screen
            uartPrint("\033[2J\033[1;1H");
            cliPrompt();
        } else if (bufferIndex && (c == '\n' || c == '\r')) {
            // enter pressed
            clicmd_t *cmd = NULL;
            clicmd_t target;
            uartPrint("\r\n");
            cliBuffer[bufferIndex] = 0; // null terminate
            
            target.name = cliBuffer;
            target.param = NULL;
            
            cmd = bsearch(&target, cmdTable, CMD_COUNT, sizeof cmdTable[0], cliCompare);
            if (cmd)
                cmd->func(cliBuffer + strlen(cmd->name) + 1);
            else
                uartPrint("ERR: Unknown command, try 'help'");

            memset(cliBuffer, 0, sizeof(cliBuffer));
            bufferIndex = 0;

            // 'exit' will reset this flag, so we don't need to print prompt again
            if (!cliMode)
                return;
            cliPrompt();
        } else if (c == 127) {
            // backspace
            if (bufferIndex) {
                cliBuffer[--bufferIndex] = 0;
                uartPrint("\010 \010");
            }
        } else if (bufferIndex < sizeof(cliBuffer) && c >= 32 && c <= 126) {
            if (!bufferIndex && c == 32)
                continue;
            cliBuffer[bufferIndex++] = c;
            uartWrite(c);
        }
    }
}