Exemple #1
0
RES_CODE esp8266_module::wifi_echo_off(bool lowlevel, uint32_t indx)
{
	RES_CODE res;

	res = RES_ERROR;
	for(int i=0; i < 3; i++)
	{
		rcv_hnd.close();
		snd_hnd.close();
		if(lowlevel)
			return RES_OK;
		tsk_sleep(50);
		if(rcv_hnd.tsk_open(drv_info->iface_driver_index, drv_info->iface_mode_stru[indx]) &&
			snd_hnd.tsk_open(drv_info->iface_driver_index, drv_info->iface_mode_stru[indx])	)
		{
			//wait until rx signals get stable
			tsk_sleep(50);

			//turn off echo
			if(wifi_send_cmd("E0", 1) & WIFI_CMD_STATE_OK)
			{
				res = RES_OK;
				break;
			}
		}
	}
	return res;
}
Exemple #2
0
WEAK void backlight_thread(LCD_MODULE *lcd)
{
    ALLOCATE_SIGNAL(SIG_BACKLIGHT_TASK);

    PIO_CfgOutput1(lcd->pins[BKLT_PIN_INDX]);
    while(1)
    {
     	PIO_SetOutput(lcd->pins[BKLT_PIN_INDX]);
     	if(tsk_wait_signal(SIG_BACKLIGHT_TASK, backlight_time ))
     		continue;
     	if(backlight_time)
     	{
			// reduce the current consumption to 5%
			int t = 20;
			while(!tsk_test_signal(SIG_BACKLIGHT_TASK))
			{
				PIO_SetOutput(lcd->pins[BKLT_PIN_INDX]);
				tsk_sleep(t);
				PIO_ClrOutput(lcd->pins[BKLT_PIN_INDX]);
				tsk_sleep(20 - t--);
				if(!t)
					t=1;
			}
     	}
       	tsk_get_signal(SIG_BACKLIGHT_TASK);
    }
}
Exemple #3
0
/**
 * try to open in endless loop
 * @param index
 * @param m
 */
void CHandle::tsk_safe_open(DRIVER_INDEX index, const void * m)
{
	while(!tsk_open(index, m))
	{
		tsk_sleep(10);
	}
}
Exemple #4
0
RES_CODE HAL_ETH_ReadPHYRegister(ETH_TypeDef* mac, const eth_mac_cfg_t* cfg, uint16_t PHYReg, uint32_t *RegValue)
{
  uint32_t tmpreg;

  /* Get the ETHERNET MACMIIAR value */
  tmpreg = mac->ETH_MACMIIAR;

  /* Keep only the CSR Clock Range CR[2:0] bits value */
  tmpreg &= ETH_MACMIIAR_CR;

  /* Prepare the MII address register value */
  tmpreg |= cfg->phy_address<<11;		/* Set the PHY device address */
  tmpreg |= PHYReg<<6;                 	/* Set the PHY register address */
  tmpreg |= ETH_MACMIIAR_MB;            /* Set the MII Busy bit */


  /* Write the result value into the MII Address register */
  mac->ETH_MACMIIAR = tmpreg;

  /* Check for the Busy flag */
  tmpreg = 0;
  while(mac->ETH_MACMIIAR & ETH_MACMIIAR_MB)
  {
	  if(++tmpreg >= PHY_READ_TOT)
		  return NET_ERR_PHY_NOT_READY;
	  tsk_sleep(1);
  }

  /* Get MACMIIDR value */
  *RegValue = mac->ETH_MACMIIDR;

  return RES_OK;
}
Exemple #5
0
void handle_segfault (int signo)
{
	if (signo) {
		write_string ("ooppppssssssss ....! System crashed ..."
				"Am going to sleep for 10 secs debug the image\n");
		tsk_sleep (10);
		exit (0);
	}
}
Exemple #6
0
void HAL_ETH_Start(ETH_TypeDef* mac)
{
	/* Enable transmit state machine of the MAC for transmission on the MII */
	mac->ETH_MACCR |= ETH_MACCR_TE;
	tsk_sleep(ETH_REG_WRITE_DELAY);

	/* Enable receive state machine of the MAC for reception from the MII */
	mac->ETH_MACCR |= ETH_MACCR_RE;
	tsk_sleep(ETH_REG_WRITE_DELAY);

	/* Flush Transmit FIFO */
	mac->ETH_DMAOMR |= ETH_DMAOMR_FTF;
	tsk_sleep(ETH_REG_WRITE_DELAY);

	/* Start DMA transmission */
	mac->ETH_DMAOMR |= ETH_DMAOMR_ST;

	/* Start DMA reception */
	mac->ETH_DMAOMR |= ETH_DMAOMR_SR;
}
Exemple #7
0
void LCD_MODULE::lcd_init(GUI_CB splash)
{
#if GUI_DISPLAYS > 1
	if(display == 1)
#endif
	{
		usr_task_init_static(&backlight_task_desc, false);
		backlight_task.sp->r0.as_voidptr = this;
		usr_task_schedule(backlight_task_desc.tsk);
	}

	// LCD Reset
	PIO_CfgOutput0(pins[RST_PIN_INDX]);
	tsk_sleep(20);
	PIO_SetOutput(pins[RST_PIN_INDX]);
	tsk_sleep(20);

    //LCD Handle initialization (LCD attached to SPI)
    lcd_hnd->tsk_safe_open(lcd_hnd->drv_index, lcd_hnd->mode.as_voidptr);
    lcd_reset();
}
Exemple #8
0
/**
 * WDT helper task
 * @param drv_info
 */
void wdt_thread(WDT_INFO drv_info)
{

	while(1)
	{

		wdt_feet(drv_info);

		//Sleep
		tsk_sleep(drv_info->feed_sleep);
	}

}
Exemple #9
0
HANDLE tsk_safe_open_new_hnd(DRIVER_INDEX index, const void * mode )
{
	CHandle *hnd;

	while(1)
	{
		if( (hnd = new CHandle()) )
		{
			if(hnd->tsk_open(index, mode))
				break;

			delete hnd;
		}
		tsk_sleep(10);
	}

	return (hnd);
}
Exemple #10
0
RES_CODE esp8266_module::process_write(CSocket* sock)
{
	unsigned size;//, newsize, id;
//	unsigned int start_size, write_size, sock_state;
	CSTRING cmd;
	unsigned char snd_pending;


	while(1)
	{
		size = sock->len;
		if(!size)
		{
		    TRACELN1("WIFI: write OK");
			return RES_SIG_OK;
		}
		if(size >1022)
			size = 1022;

		if(sock->sock_state != SOCKET_CONECTED)
			break;

		// Send command
		cmd.format("+CIPSEND=%u,%u", sock->sock_id, size);
	    TRACELN("WIFI: WRITE %d?", size);
	    cmd_state |= WIFI_CMD_STATE_HND;
	    if(wifi_send_cmd(cmd.c_str(), 20) != WIFI_CMD_STATE_RETURNED)
	    {
	    	wifi_net_error(NET_ERR_SOCK_WRITE);
	    	return RES_SIG_ERROR;
	    }


	    // Send data
		snd_pending = '>';
		do
		{
			process_input(rcv_hnd.signal, cmd.c_str(), snd_pending);
			if ( cmd_state >= WIFI_CMD_STATE_HND )
			{
				if ( cmd_state & WIFI_CMD_STATE_HND )
				{
					unsigned int mytime;

					cmd_state &= ~WIFI_CMD_STATE_HND;
					snd_pending = 0;

					rcv_hnd.tsk_start_read(&received_ch, 1);
					mytime = CURRENT_TASK->time;
					tsk_sleep(55); // data sheet recomendation
					if( snd_hnd.tsk_write(sock->src.as_voidptr, size, WIFI_WRITE_TOT) != RES_OK)
						break;
					CURRENT_TASK->time = mytime;

				} else
				{
					if ( cmd_state >= WIFI_CMD_STATE_OK )
						break; // command completed with OK, ERROR ..
				}
			}

		} while(tsk_resume_wait_signal(rcv_hnd.signal));

//	    wifi_on_blink_transfer(this, GPRS_TRANSFER_INDICATOR);

	    //Check the result
	    if(cmd_state & WIFI_CMD_STATE_OK)
	    {
			TRACE1(" done!");
			sock->src.as_byteptr += size;
			sock->len -= size;
			continue;
		}

	    if (cmd_state & WIFI_CMD_STATE_CMES)
	    {
	    	TRACE_ERROR("\r\nWIFI:%s write ERROR", sock->client.task->name);
	    }

    	break;
	}
	wifi_sleep(120);
	wifi_net_error(NET_ERR_SOCK_WRITE);
	return RES_SIG_ERROR;
}
Exemple #11
0
RES_CODE HAL_ETH_Init(ETH_TypeDef* mac, const eth_mac_cfg_t* cfg)
{
	uint32_t tmpreg;
	uint32_t res;
	RCC_ClocksTypeDef  clocks;


	TRACELN("ETH Init");
	/* Select MII or RMII Mode*/
	if(cfg->mac_cfg_flags & MAC_CFG_FLG_IFCE_MII_RMII)
	{
		tmpreg = 0;
		do
		{
			mac->ETH_DMABMR |= ETH_DMABMR_SR;
			SYSCFG->SYSCFG_PMC |= SYSCFG_PMC_MII_RMII;
			if(++tmpreg > PHY_CONFIG_DELAY)
			{
				TRACEPHY(mac, cfg, "ETH NO PHY CLK!!");
				break;
			}
			tsk_sleep(1);
		} while (!(SYSCFG->SYSCFG_PMC & SYSCFG_PMC_MII_RMII));
	}
	else
		SYSCFG->SYSCFG_PMC &= ~SYSCFG_PMC_MII_RMII;

	/* Ethernet Software reset */
	/* Set the SWR bit: resets all MAC subsystem internal registers and logic */
	/* After reset all the registers holds their respective reset values */
	mac->ETH_DMABMR |= ETH_DMABMR_SR;

	/* Wait for software reset */
	tmpreg = 0;
	while (mac->ETH_DMABMR & ETH_DMABMR_SR)
	{
		tsk_sleep(1);
		if(++tmpreg > PHY_CONFIG_DELAY)
		{
			TRACEPHY(mac, cfg, "ETH MAC RST!!");
			break;
		}
	}

	/*-------------------------------- MAC Initialization ----------------------*/

	TRACEPHY(mac, cfg, "ETH PHY:");

	/* Get the ETHERNET MACMIIAR value */
	tmpreg = mac->ETH_MACMIIAR;
	/* Clear CSR Clock Range CR[2:0] bits */
	tmpreg &= ~ETH_MACMIIAR_CR;

	/* Get hclk frequency value */
	RCC_GetClocksFreq (&clocks);

	/* Set CR bits depending on hclk value */
	if ((clocks.HCLK_Frequency >= 20000000) && (clocks.HCLK_Frequency < 35000000))
	{
		/* CSR Clock Range between 20-35 MHz */
		tmpreg |= ETH_MACMIIAR_CR_Div16;
	}
	else if ((clocks.HCLK_Frequency >= 35000000) && (clocks.HCLK_Frequency < 60000000))
	{
		/* CSR Clock Range between 35-60 MHz */
		tmpreg |= ETH_MACMIIAR_CR_Div26;
	}
	else if ((clocks.HCLK_Frequency >= 60000000) && (clocks.HCLK_Frequency < 100000000))
	{
		/* CSR Clock Range between 60-100 MHz */
		tmpreg |= ETH_MACMIIAR_CR_Div42;
	}
	else /* ((hclk >= 100000000)&&(hclk < 120000000)) */
	{
		/* CSR Clock Range between 100-120 MHz */
		tmpreg |= ETH_MACMIIAR_CR_Div62;
	}

	/* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */
	mac->ETH_MACMIIAR = tmpreg;

	/*-------------------- PHY initialization and configuration ----------------*/
	res = HAL_ETH_Init_PHY(mac, cfg);

	/* Config MAC and DMA */
	ETH_MACDMAConfig(mac, cfg);

	return res;
}
Exemple #12
0
static void ETH_MACDMAConfig(ETH_TypeDef* mac, const eth_mac_cfg_t* cfg)
{
  uint32_t tmpreg;


  	/*------------------------ ETHERNET MACCR Configuration --------------------*/
	tmpreg = mac->ETH_MACCR;
	/* Clear WD, PCE, PS, TE and RE bits */
	tmpreg &= ~(ETH_MACCR_WD | ETH_MACCR_JD | ETH_MACCR_IFG | ETH_MACCR_CSD |
	ETH_MACCR_FES | ETH_MACCR_ROD | ETH_MACCR_LM |
	ETH_MACCR_DM | ETH_MACCR_IPCO | ETH_MACCR_RD |
	ETH_MACCR_APCS | ETH_MACCR_BL | ETH_MACCR_DC);

	tmpreg |= cfg->ETH_MACCR;
	if (cfg->mac_data->mac_cfg & MAC_CFG_FLG_DUPLEX_MODE)
		tmpreg |= ETH_MACCR_DM;
	if (cfg->mac_data->mac_cfg & MAC_CFG_FLG_100M)
		tmpreg |= ETH_MACCR_FES;

	/* Write to ETHERNET MACCR */
	mac->ETH_MACCR = tmpreg;

	/* Wait until the write operation will be taken into account:
     at least four TX_CLK/RX_CLK clock cycles */
	tsk_sleep(ETH_REG_WRITE_DELAY);


  	/*----------------------- ETHERNET MACFFR Configuration --------------------*/
	mac->ETH_MACFFR = cfg->ETH_MACFFR;

	tsk_sleep(ETH_REG_WRITE_DELAY);

	/*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*/
	mac->ETH_MACHTHR = 0;

	mac->ETH_MACHTLR = 0;
	/*----------------------- ETHERNET MACFCR Configuration -------------------*/

	tmpreg = mac->ETH_MACFCR;
	tmpreg &= ~(ETH_MACFCR_PT | ETH_MACFCR_ZQPD | ETH_MACFCR_PLT |
	ETH_MACFCR_UPFD | ETH_MACFCR_RFCE | ETH_MACFCR_TFCE);
	tmpreg |= cfg->ETH_MACFCR;

	mac->ETH_MACFCR = tmpreg;

	tsk_sleep(ETH_REG_WRITE_DELAY);

	/*----------------------- ETHERNET MACVLANTR Configuration ----------------*/
	/* Set the ETV bit according to ETH VLANTagComparison value */
	/* Set the VL bit according to ETH VLANTagIdentifier value */
	mac->ETH_MACVLANTR = 0;

    tsk_sleep(ETH_REG_WRITE_DELAY);

    /* Ethernet DMA default initialization ************************************/

    /* Get the ETHERNET DMAOMR value */
    tmpreg = mac->ETH_DMAOMR;
    /* Clear xx bits */
    tmpreg &= ~(ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_DFRF |
    		ETH_DMAOMR_TSF | ETH_DMAOMR_TTC |
			ETH_DMAOMR_FEF | ETH_DMAOMR_FUGF | ETH_DMAOMR_RTC | ETH_DMAOMR_OSF);
    tmpreg |= cfg->ETH_DMAOMR;

    mac->ETH_DMAOMR = tmpreg;

    // Wait until the write operation will be taken into account
    tsk_sleep(ETH_REG_WRITE_DELAY);

    /*----------------------- ETHERNET DMABMR Configuration ------------------*/
    mac->ETH_DMABMR = cfg->ETH_DMABMR | ETH_DMABMR_USP; // Enable use of separate PBL for Rx and Tx

    // Wait until the write operation will be taken into account
    tsk_sleep(ETH_REG_WRITE_DELAY);

	/* Enable the Ethernet Rx Interrupt */
	mac->ETH_DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE;

     /* Initialize MAC address in ethernet MAC */
     ETH_MACAddressConfig(&mac->ETH_MACA0HR, cfg->mac_data->mac_adr);
}
Exemple #13
0
void key_drv_thread(KEY2_DRIVER_INFO* drv_info)
{
    unsigned int i, mask;
	unsigned char button_ticks[KEY_COUNT];
	unsigned int new_keys;
	CHandle keyrd_hnd;

	pio_open(&keyrd_hnd, &drv_info->pins);

	for(i=0; i<KEY_COUNT; i++)
        button_ticks[i] = 0;
    btns_pressed = 0;

    for(;;)
    {

        // scan keyboard every 5ms while some key is pressed
        do
        {
            tsk_sleep(KEY_POLLING_TIME-4);
            keyrd_hnd.tsk_read(&new_keys, 4);

			mask = 1;
			for(i=0; i<KEY_COUNT; i++)
			{
				if (new_keys & drv_info->key_codes[i])
				{
					button_ticks[i] = 0;
					if (mask & btns_pressed)
					{
						btns_pressed ^= mask;
						key_post(KEY_UP_CODE+i);
					}
				} else
				{//button pressed
					button_ticks[i]++;
					if(mask & btns_pressed)
					{ //button hold?
						if (button_ticks[i] > (KEY_REPEAT_TIME/KEY_POLLING_TIME))
						{
							button_ticks[i] = 0;
							key_post(KEY_REPEAT_CODE+i);
						}
					} else
					if (button_ticks[i] > (KEY_DEBOUNCE_TIME/KEY_POLLING_TIME))
					{
						button_ticks[i] = 0;
						btns_pressed |= mask;
						key_post(KEY_DOWN_CODE+i);
					}

				}

				mask <<=1;
			}
        } while(new_keys ^ drv_info->pins.mask);

		//wait for any key...
        keyrd_hnd.tsk_read_locked(&new_keys, 4);

    }
}
Exemple #14
0
void usbdrv_thread(USB_DRV_INFO drv_info)
{
    CHandle helper;
    CHandle req_hnd;
    USBGenericRequest request;
    bool requested = false;
	unsigned int sig=0;

    ALLOCATE_SIGNAL(USB_DRIVER_SIG);
	helper.tsk_safe_open(drv_info->info.drv_index, 0);
	helper.tsk_start_command(NULL, 0);
	req_hnd.tsk_safe_open(drv_info->info.drv_index, USB_DRV_MODE(EPT_0, EPT_0));
    while(1)
    {

    	sig |= tsk_get_signal(SIGNAL_ANY);


        // 2) get waiting clients
		if(sig & helper.signal)
        {
			HANDLE client;

			sig ^= helper.signal;
        	helper.res &= ~FLG_SIGNALED;
			client = (HANDLE)helper.dst.as_voidptr;
			if(client)
			{
				RES_CODE res;

				res = ((USB_API_FUNC)client->src.as_voidptr)(drv_info, client);
				if(res & FLG_SIGNALED)
				{
					tsk_HND_SET_STATUS(client, res);
				}
			}

			helper.tsk_start_command(NULL, 0);
        }
		if(sig & req_hnd.signal)
		{
			sig ^= req_hnd.signal;
        	req_hnd.res &= ~FLG_SIGNALED;
#if USB_ENABLE_DEVICE
			TRACE1_USB(" | req:");
			if(req_hnd.res == RES_OK)
			{
				drv_info->drv_data->device.RequestHandler(drv_info, &request, &req_hnd);
			} else
#endif
			{
				TRACE_USB(" res %x", req_hnd.res);
				tsk_sleep(5);
			}
			requested = false;
		}
		if(!requested)
		{
#if USB_ENABLE_HOST
			if(sig == USB_DRIVER_SIG)
			{
				if(drv_info->drv_data->otg_h_sig & OTG_H_SIG_CON)
				{
					do
					{
						sig = atomic_fetch((volatile int*)&drv_info->drv_data->otg_h_sig);
						sig &= ~OTG_H_SIG_CON;
					} while(atomic_store((volatile int*)&drv_info->drv_data->otg_h_sig, sig));

					//wait 1s for connect
					for(int retries =0; retries <10; ++retries)
					{
						if(drv_info->drv_data->otg_flags & USB_OTG_FLG_HOST_RST)
							break;
				    	sig = tsk_wait_signal(USB_DRIVER_SIG, 100);
				    	if (sig)
				    		break;
					}
					if( !(drv_info->drv_data->otg_h_sig & OTG_H_SIG_RST))
					{
						usb_api_otg_off(drv_info, NULL);
					}
				}
				if(drv_info->drv_data->otg_h_sig & OTG_H_SIG_RST)
				{
					do
					{
						sig = atomic_fetch((volatile int*)&drv_info->drv_data->otg_h_sig);
						sig &= ~OTG_H_SIG_RST;
					} while(atomic_store((volatile int*)&drv_info->drv_data->otg_h_sig, sig));

					if(drv_info->drv_data->otg_flags & USB_OTG_FLG_HOST_RST)
					{
						RES_CODE res;

						// Reset requested
						for(int retries =0; retries <3; ++retries)
						{
							tsk_sleep(100);
							res = usb_host_reset_bus(drv_info, &req_hnd);
							if( res == RES_OK)
								break;
						}
//						if(res != RES_OK)
//							usb_api_otg_off(drv_info, NULL);

					}
				}
				if(drv_info->drv_data->otg_h_sig & OTG_H_SIG_RESUME)
				{
					do
					{
						sig = atomic_fetch((volatile int*)&drv_info->drv_data->otg_h_sig);
						sig &= ~OTG_H_SIG_RESUME;
					} while(atomic_store((volatile int*)&drv_info->drv_data->otg_h_sig, sig));
					usb_hal_host_resume(drv_info);


				}
				sig = 0;
			}
			if(drv_info->drv_data->otg_flags & USB_OTG_FLG_DEV_OK)
			{

				req_hnd.mode.as_ushort[1] = drv_info->drv_data->drv_state_cnt;
#endif
				req_hnd.tsk_start_read(&request, 8);
				TRACE_USB_NAME(drv_info);
				TRACE1_USB(" st req:");
				requested = true;
#if USB_ENABLE_HOST
			}
#endif
		}

    }

}
Exemple #15
0
void gui_thread(GUI_DRIVER_INFO* drv_info)
{
    unsigned int res, tmp, redraw;
    WINDOW win;
    WINDOW top;
    WINDOW desktop;		//main_dlg;
    CHandle key_hnd;
    CHandle gui_hnd;

    //prevent these signals not to be used from task handles
    ALLOCATE_SIGNAL(SIG_GUI_TASK);

    //wait for static constructors (lcd object)
    while(!detect_displays(drv_info))
        tsk_sleep(10);

    // start desktop
    while( !(desktop = tsk_new_window(maindlg_cb)) )
    {
        tsk_sleep(10);
    }
    desktop->next = NULL;
    top = desktop;
    desktop->rect.x1 = drv_info->lcd[0]->size_x;
    desktop->rect.y1 = drv_info->lcd[0]->size_y;

    for(int i=0; i<GUI_DISPLAYS; i++)
    {
        if(drv_info->lcd[i])
        {
#if GUI_DISPLAYS > 1
            desktop->displays |= (1<<i);
#endif
            drv_info->lcd[i]->lcd_init((GUI_CB)splashdlg_cb);
        }
    }
    tsk_sleep(3000);


    init_main_menu();


    // start key handle
    key_hnd.tsk_safe_open(KEY_DRV_INDX, 0);
    key_hnd.src.as_int = 0;
    key_hnd.tsk_start_read(&key_hnd.src.as_int, 1);


    // start gui handle
    gui_hnd.tsk_safe_open(GUI_DRV_INDX, 0);			//mode = 1 - control handle
    gui_hnd.tsk_start_read(NULL, 0);

    for(;;)
    {
        res = tsk_wait_signal(-1u, 1000 - (CURRENT_TIME %1000));
        redraw = res>>8;;

        if(!res)
            redraw = 0xFF;

        // 1) get waiting objects
        if(res & gui_hnd.signal)
        {
            drv_info->lcd[0]->backlight_signal();
            gui_hnd.res &= ~FLG_SIGNALED;
            win = (WINDOW)gui_hnd.dst.as_voidptr;
            if(win)
            {
                top->next = win;
                do
                {
                    top = (WINDOW)top->next;
                    top->rect.x1 = desktop->rect.x1;
                    top->rect.y1 = desktop->rect.y1;
                    top->callback(NULL , WM_INIT);
#if GUI_DISPLAYS > 1
                    redraw |= top->displays;
#endif
                } while( top->next );
            }
            gui_hnd.tsk_start_read(NULL, 0);
#if GUI_DISPLAYS == 1
            redraw |= 1;
#endif
        }


        // 2) check keyboard
        if(res &  key_hnd.signal)
        {
            drv_info->lcd[0]->backlight_signal();
            key_hnd.res &= ~FLG_SIGNALED;
            //send to top
            tmp = top->callback(key_hnd.src.as_int , WM_KEY);
            if(tmp & FLG_BUSY)	//FLG_BUSY returned to redraw
            {
                tmp ^= FLG_BUSY;
#if GUI_DISPLAYS > 1
                redraw |= top->displays;
#else
                redraw |= 1;
#endif
            }
            top->mode1 = tmp;
            key_hnd.tsk_start_read(&key_hnd.src.as_int, 1);
        }

        // 3)  command loop
        top = NULL;
        win = desktop;
        do
        {
            // check for pending commands
            if(win->mode0 & FLG_OK)
            {
                locked_clr_byte(&win->mode0, FLG_OK);
                tmp = win->callback(win->dst.as_int, WM_USER);
                if(tmp & FLG_BUSY)	//FLG_BUSY returned to redraw
                {
                    tmp ^= FLG_BUSY;
#if GUI_DISPLAYS > 1
                    redraw |= win->displays;
#else
                    redraw |= 1;
#endif
                }
                win->mode1 |= tmp;

            }

            //check for complete (close object)
            if(top && ((win->mode0 | win->mode1) & FLG_SIGNALED) )
            {
                top->next = win->next;
#if GUI_DISPLAYS > 1
                redraw |= win->displays;
#else
                redraw |= 1;
#endif
                usr_HND_SET_STATUS(win, win->mode1 | FLG_SIGNALED);
                win = (WINDOW)top->next;
            } else
            {
                top = win;
                win = (WINDOW)win->next;
            }

        } while (win );

        // 3) draw loop
        for(int i=0; i<GUI_DISPLAYS; i++)
        {
            if( (redraw & (1<<i)) && drv_info->lcd[i])
            {
                drv_info->lcd[i]->redraw_screen(desktop);
            }
        }
    }

}