static void tvm_set_alarm (ECTX ectx) { struct itimerval timeout; unsigned int t; WORD now; if (alarm_set && TIME_AFTER(ectx->tnext, alarm_time)) { return; } now = ectx->get_time (ectx); t = ectx->tnext - now; if (TIME_AFTER(now, ectx->tnext) || (t == 0)) { ectx->modify_sync_flags (ectx, SFLAG_TQ, 0); alarm_set = 0; } timeout.it_interval.tv_sec = 0; timeout.it_interval.tv_usec = 0; timeout.it_value.tv_sec = t / 1000000; timeout.it_value.tv_usec = t % 1000000; alarm_set = 1; alarm_time = ectx->tnext; if (setitimer (ITIMER_REAL, &timeout, NULL) != 0) { /* Behave like busy-wait if setitimer fails. */ ectx->modify_sync_flags (ectx, SFLAG_TQ, 0); alarm_set = 0; } }
/* service ep0 IN transaction */ static void ctr_write(void) { int xfer_size = (ctrlep[DIR_IN].cnt > 64) ? 64 : ctrlep[DIR_IN].cnt; unsigned int timeout = current_tick + HZ/10; while (TX0BUF & (1<<0)) /* TX0FULL flag */ { if(TIME_AFTER(current_tick, timeout)) break; } TX0STAT = xfer_size; /* size of the transfer */ TX0DMALM_IADDR = (uint32_t)ctrlep[DIR_IN].buf; /* local buffer address */ TX0DMAINCTL = (1<<1); /* start DMA */ TX0CON &= ~(1<<2); /* clear NAK */ /* Decrement by max packet size is intentional. * This way if we have final packet short one we will get negative len * after transfer, which in turn indicates we *don't* need to send * zero length packet. If the final packet is max sized packet we will * get zero len after transfer which indicates we need to send * zero length packet to signal host end of the transfer. */ ctrlep[DIR_IN].cnt -= 64; ctrlep[DIR_IN].buf += xfer_size; }
static void int_write(int ep) { int ep_num = EP_NUM(ep); int max = usb_drv_port_speed() ? 1024 : 64; int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt; unsigned int timeout = current_tick + HZ/10; while (IIN_TXBUF(ep_num) & (1<<0)) /* TXFULL flag */ { if(TIME_AFTER(current_tick, timeout)) break; } IIN_TXSTAT(ep_num) = xfer_size; /* size of the transfer */ IIN_DMAINLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; /* buf address */ IIN_DMAINCTL(ep_num) = (1<<0); /* start DMA */ IIN_TXCON(ep_num) &= ~(1<<2); /* clear NAK */ /* Decrement by max packet size is intentional. * This way if we have final packet short one we will get negative len * after transfer, which in turn indicates we *don't* need to send * zero length packet. If the final packet is max sized packet we will * get zero len after transfer which indicates we need to send * zero length packet to signal host end of the transfer. */ endpoints[ep_num].cnt -= max; endpoints[ep_num].buf += xfer_size; }
void sim_thread(void) { struct queue_event ev; long last_broadcast_tick = current_tick; int num_acks_to_expect; while (1) { queue_wait(&sim_queue, &ev); switch(ev.id) { case SIM_SCREENDUMP: screen_dump(); #ifdef HAVE_REMOTE_LCD remote_screen_dump(); #endif break; case SIM_USB_INSERTED: /* from firmware/usb.c: */ /* Tell all threads that they have to back off the storage. We subtract one for our own thread. Expect an ACK for every listener for each broadcast they received. If it has been too long, the user might have entered a screen that didn't ACK when inserting the cable, such as a debugging screen. In that case, reset the count or else USB would be locked out until rebooting because it most likely won't ever come. Simply resetting to the most recent broadcast count is racy. */ if(TIME_AFTER(current_tick, last_broadcast_tick + HZ*5)) { num_acks_to_expect = 0; last_broadcast_tick = current_tick; } num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1; DEBUGF("USB inserted. Waiting for %d acks...\n", num_acks_to_expect); break; case SYS_USB_CONNECTED_ACK: if(num_acks_to_expect > 0 && --num_acks_to_expect == 0) { DEBUGF("All threads have acknowledged the connect.\n"); } else { DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect); } break; case SIM_USB_EXTRACTED: /* in usb.c, this is only done for exclusive storage * do it here anyway but don't depend on the acks */ queue_broadcast(SYS_USB_DISCONNECTED, 0); break; default: DEBUGF("sim_tasks: unhandled event: %ld\n", ev.id); break; } } }
/* Call periodically to have the OSD timeout and hide itself */ static void _osd_monitor_timeout(struct osd *osd) { if (osd->status <= OSD_HIDDEN) return; /* Already hidden/disabled */ if (osd->timeout > 0 && TIME_AFTER(*rb->current_tick, osd->hide_tick)) _osd_show(osd, OSD_HIDE); }
PLUGIN_HEADER enum plugin_status plugin_start(const void* parameter) { (void)parameter; bool done = false; bool boost = false; int count = 0; int last_count = 0; int last_tick = *rb->current_tick; int per_sec = 0; rb->lcd_setfont(FONT_SYSFIXED); while (!done) { int j,x; for (j=1; j<100000; j++) x = j*11; rb->screens[0]->clear_display(); rb->screens[0]->putsf(0, 0, "%s: %d",boost?"boost":"normal",count); if (TIME_AFTER(*rb->current_tick, last_tick+HZ)) { last_tick = *rb->current_tick; per_sec = count-last_count; last_count = count; } rb->screens[0]->putsf(0, 1, "loops/s: %d", per_sec); rb->screens[0]->update(); count++; switch (rb->get_action(CONTEXT_STD, TIMEOUT_NOBLOCK)) { #ifdef HAVE_ADJUSTABLE_CPU_FREQ case ACTION_STD_PREV: if (!boost) { rb->cpu_boost(true); boost = true; } break; case ACTION_STD_NEXT: if (boost) { rb->cpu_boost(false); boost = false; } break; #endif case ACTION_STD_CANCEL: done = true; break; } } return PLUGIN_OK; }
/* Return USB_HANDLED if session took place else return USB_EXTRACTED */ static int handle_usb(int connect_timeout) { static struct event_queue q SHAREDBSS_ATTR; struct queue_event ev; int usb = USB_EXTRACTED; long end_tick = 0; if (!usb_plugged()) return USB_EXTRACTED; queue_init(&q, true); usb_init(); usb_start_monitoring(); printf("USB: Connecting"); if (connect_timeout != TIMEOUT_BLOCK) end_tick = current_tick + connect_timeout; while (1) { /* Sleep no longer than 1/2s */ queue_wait_w_tmo(&q, &ev, HZ/2); if (ev.id == SYS_USB_CONNECTED) { /* Switch to verbose mode if not in it so that the status updates * are shown */ verbose = true; /* Got the message - wait for disconnect */ printf("Bootloader USB mode"); usb = USB_HANDLED; usb_acknowledge(SYS_USB_CONNECTED_ACK); usb_wait_for_disconnect(&q); break; } if (connect_timeout != TIMEOUT_BLOCK && TIME_AFTER(current_tick, end_tick)) { /* Timed out waiting for the connect - will happen when connected * to a charger instead of a host port and the charging pin is * the same as the USB pin */ printf("USB: Timed out"); break; } if (!usb_plugged()) break; /* Cable pulled */ } usb_close(); queue_delete(&q); return usb; }
static void init_tagcache(void) { bool clear = false; #if CONFIG_CODEC == SWCODEC long talked_tick = 0; #endif tagcache_init(); while (!tagcache_is_initialized()) { int ret = tagcache_get_commit_step(); if (ret > 0) { #if CONFIG_CODEC == SWCODEC /* hwcodec can't use voice here, as the database commit * uses the audio buffer. */ if(global_settings.talk_menu && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+7*HZ))) { talked_tick = current_tick; talk_id(LANG_TAGCACHE_INIT, false); talk_number(ret, true); talk_id(VOICE_OF, true); talk_number(tagcache_get_max_commit_step(), true); } #endif #ifdef HAVE_LCD_BITMAP if (lang_is_rtl()) { splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(), str(LANG_TAGCACHE_INIT)); } else { splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret, tagcache_get_max_commit_step()); } #else lcd_double_height(false); lcd_putsf(0, 1, " DB [%d/%d]", ret, tagcache_get_max_commit_step()); lcd_update(); #endif clear = true; } sleep(HZ/4); } tagtree_init(); if (clear) { backlight_on(); show_logo(); } }
static int handle_usb_events(void) { #if (CONFIG_STORAGE & STORAGE_MMC) int next_update=0; #endif /* STORAGE_MMC */ /* Don't return until we get SYS_USB_DISCONNECTED or SYS_TIMEOUT */ while(1) { int button; #ifdef USB_ENABLE_HID if (usb_hid) { button = get_hid_usb_action(); /* On mode change, we need to refresh the screen */ if (button == ACTION_USB_HID_MODE_SWITCH_NEXT || button == ACTION_USB_HID_MODE_SWITCH_PREV) { break; } } else #endif { button = button_get_w_tmo(HZ/2); /* hid emits the event in get_action */ send_event(GUI_EVENT_ACTIONUPDATE, NULL); } switch(button) { case SYS_USB_DISCONNECTED: usb_acknowledge(SYS_USB_DISCONNECTED_ACK); return 1; case SYS_CHARGER_DISCONNECTED: /*reset rockbox battery runtime*/ global_status.runtime = 0; break; case SYS_TIMEOUT: break; } #if (CONFIG_STORAGE & STORAGE_MMC) /* USB-MMC bridge can report activity */ if(TIME_AFTER(current_tick,next_update)) { if(usb_inserted()) { led(mmc_usb_active(HZ)); } next_update=current_tick+HZ/2; } #endif /* STORAGE_MMC */ } return 0; }
void radio_start(void) { const struct fm_region_data *fmr; bool start_paused; if(radio_status == FMRADIO_PLAYING) return; fmr = &fm_region_data[global_settings.fm_region]; start_paused = radio_status & FMRADIO_START_PAUSED; /* clear flag before any yielding */ radio_status &= ~FMRADIO_START_PAUSED; if(radio_status == FMRADIO_OFF) tuner_power(true); curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min; tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */ if(radio_status == FMRADIO_OFF) { #ifdef HAVE_RADIO_REGION tuner_set(RADIO_REGION, global_settings.fm_region); #endif tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono); } tuner_set(RADIO_FREQUENCY, curr_freq); #ifdef HAVE_RADIO_MUTE_TIMEOUT { unsigned long mute_timeout = current_tick + HZ; if (radio_status != FMRADIO_OFF) { /* paused */ mute_timeout += HZ; } while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED)) { if(TIME_AFTER(current_tick, mute_timeout)) break; yield(); } } #endif /* keep radio from sounding initially */ if(!start_paused) tuner_set(RADIO_MUTE, 0); radio_status = FMRADIO_PLAYING; } /* radio_start */
bool skin_render_alternator(struct skin_element* element, struct skin_draw_info *info) { bool changed_lines = false; struct line_alternator *alternator = (struct line_alternator*)element->data; unsigned old_refresh = info->refresh_type; if (info->refresh_type == SKIN_REFRESH_ALL) { alternator->current_line = element->children_count-1; changed_lines = true; } else if (TIME_AFTER(current_tick, alternator->next_change_tick)) { changed_lines = true; } if (changed_lines) { struct skin_element *current_line = element->children[alternator->current_line]; int start = alternator->current_line; int try_line = start; bool suitable = false; int rettimeout = DEFAULT_SUBLINE_TIME_MULTIPLIER*TIMEOUT_UNIT; /* find a subline which has at least one token in it, * and that line doesnt have a timeout set to 0 through conditionals */ do { try_line++; if (try_line >= element->children_count) try_line = 0; if (element->children[try_line]->children_count != 0) { current_line = element->children[try_line]; rettimeout = get_subline_timeout(info->gwps, current_line->children[0]); if (rettimeout > 0) { suitable = true; } } } while (try_line != start && !suitable); if (suitable) { alternator->current_line = try_line; alternator->next_change_tick = current_tick + rettimeout; } info->refresh_type = SKIN_REFRESH_ALL; info->force_redraw = true; } bool ret = skin_render_line(element->children[alternator->current_line], info); info->refresh_type = old_refresh; return changed_lines || ret; }
void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct viewport *vp) { struct screen * display = bar->display; if (!display) return; #ifdef HAVE_LCD_CHARCELLS int val; (void)force_redraw; /* The Player always has "redraw" */ (void)vp; #endif /* HAVE_LCD_CHARCELLS */ bar->info.battlevel = battery_level(); #ifdef HAVE_USB_POWER bar->info.usb_inserted = usb_inserted(); #endif #if CONFIG_CHARGING bar->info.inserted = (charger_input_state == CHARGER); if (bar->info.inserted) { bar->info.battery_state = true; #if CONFIG_CHARGING >= CHARGING_MONITOR /* zero battery run time if charging */ if (charge_state > DISCHARGING) lasttime = current_tick; /* animate battery if charging */ if ((charge_state == DISCHARGING) || (charge_state == TRICKLE)) { bar->info.batt_charge_step = -1; } else { #else /* CONFIG_CHARGING < CHARGING_MONITOR */ lasttime = current_tick; { #endif /* CONFIG_CHARGING < CHARGING_MONITOR */ /* animate in (max.) 4 steps, starting near the current charge level */ if (TIME_AFTER(current_tick, bar->battery_icon_switch_tick)) { if (++bar->info.batt_charge_step > 3) bar->info.batt_charge_step = bar->info.battlevel / 34; bar->battery_icon_switch_tick = current_tick + HZ; } } } else #endif /* CONFIG_CHARGING */ {
/* display number of tracks inserted into playlists. Used for directory insert */ static void display_insert_count(int count) { static long talked_tick = 0; if(global_settings.talk_menu && count && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+5*HZ))) { talked_tick = current_tick; talk_number(count, false); talk_id(LANG_PLAYLIST_INSERT_COUNT, true); } splashf(0, str(LANG_PLAYLIST_INSERT_COUNT), count, str(LANG_OFF_ABORT)); }
int dma_wait_completion(unsigned chan, unsigned tmo) { tmo += current_tick; volatile uint32_t *sema; if(APB_IS_APBX_CHANNEL(chan)) sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); else sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)); while(*sema & HW_APB_CHx_SEMA__PHORE_BM && !TIME_AFTER(current_tick, tmo)) udelay(10); return __XTRACT_EX(*sema, HW_APB_CHx_SEMA__PHORE); }
static void usb_mode(int connect_timeout) { int button; usb_init(); usb_start_monitoring(); /* Wait for threads to connect or cable is pulled */ printf("USB: Connecting"); long end_tick = current_tick + connect_timeout; while(1) { button = button_get_w_tmo(HZ/10); if(button == SYS_USB_CONNECTED) break; /* Hit */ if(TIME_AFTER(current_tick, end_tick)) { /* Timed out waiting for the connect - will happen when connected * to a charger through the USB port */ printf("USB: Timed out"); break; } if(usb_detect() == USB_EXTRACTED) break; /* Cable pulled */ } if(button == SYS_USB_CONNECTED) { /* Got the message - wait for disconnect */ printf("Bootloader USB mode"); usb_acknowledge(SYS_USB_CONNECTED_ACK); while(1) { button = button_get_w_tmo(HZ/2); if(button == SYS_USB_DISCONNECTED) break; } } /* Put drivers initialized for USB connection into a known state */ usb_close(); }
/* Add at head */ void TcbEnqueue( IN Tcb_T *pTcb ) { Tcb_T *pEntry; /* The queue is empty update head and tail */ if (gCore.pHead == NULL && gCore.pTail == NULL) { gCore.pHead = pTcb; gCore.pTail = pTcb; pTcb->pNext = NULL; pTcb->pPrev = NULL; return; } /* Traverse the queue */ for (pEntry = gCore.pHead; pEntry; pEntry = pEntry->pNext) { /* Is the current pEntry after the new pTcb entry */ if (TIME_AFTER(pEntry->Expire, pTcb->Expire)) { /* Insert new pTcb entry before current pEntry */ if (pEntry->pPrev) { pEntry->pPrev->pNext = pTcb; pTcb->pPrev = pEntry->pPrev; pEntry->pPrev = pTcb; pTcb->pNext = pEntry; } else { pEntry->pPrev = pTcb; pTcb->pNext = pEntry; pTcb->pPrev = NULL; gCore.pHead = pTcb; } return; } } /* The queue end was found, insert at tail */ gCore.pTail->pNext = pTcb; pTcb->pPrev = gCore.pTail; gCore.pTail = pTcb; pTcb->pNext = NULL; return; }
void touchscreen_scan_device() { static long last_touch_read = 0; static int touch_data_index = 0; int saveADCDLY; /* check touch state */ if(ADCDAT1 & (1<<15)) { return; } if (TIME_AFTER(current_tick, last_touch_read + 1)) { /* resets the index if the last touch could not be read 5 times */ touch_data_index = 0; } /* read touch data */ saveADCDLY = ADCDLY; ADCDLY = 40000; /*delay ~0.8ms (1/50M)*4000 */ ADCTSC = (1<<3)|(1<<2); /* pullup disable, seq x,y pos measure */ /* start adc */ ADCCON|= 0x1; /* wait for start and end */ while(ADCCON & 0x1); while(!(ADCCON & 0x8000)); x[touch_data_index] = ADCDAT0&0x3ff; y[touch_data_index] = ADCDAT1&0x3ff; ADCTSC = 0xd3; /* back to interrupt mode */ ADCDLY = saveADCDLY; touch_data_index++; if (touch_data_index > NO_OF_TOUCH_DATA - 1) { /* coordinates 5 times read */ touch_available = true; touch_data_index = 0; } last_touch_read = current_tick; }
static void button_queue_wait(struct queue_event *evp, int timeout) { /* Loop once after wait time if boosted in order to unboost and wait the full remaining time */ do { int ticks = timeout; if (ticks == 0) /* TIMEOUT_NOBLOCK */ ; else if (ticks > 0) { if (button_boosted && ticks > BUTTON_UNBOOST_TMO) ticks = BUTTON_UNBOOST_TMO; timeout -= ticks; } else /* TIMEOUT_BLOCK (ticks < 0) */ { if (button_boosted) ticks = BUTTON_UNBOOST_TMO; } queue_wait_w_tmo(&button_queue, evp, ticks); if (evp->id != SYS_TIMEOUT) { /* GUI boost build gets immediate kick, otherwise at least 3 messages had to be there */ #ifndef HAVE_GUI_BOOST if (queue_count(&button_queue) >= 2) #endif button_boost(true); break; } if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick)) button_boost(false); } while (timeout); }
void sb_skin_update(enum screen_type screen, bool force) { struct wps_data *data = skin_get_gwps(CUSTOM_STATUSBAR, screen)->data; static long next_update[NB_SCREENS] = {0}; int i = screen; if (!data->wps_loaded) return; if (TIME_AFTER(current_tick, next_update[i]) || force) { #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) /* currently, all remotes are readable without backlight * so still update those */ if (lcd_active() || (i != SCREEN_MAIN)) #endif { bool full_update = skin_do_full_update(CUSTOM_STATUSBAR, screen); skin_update(CUSTOM_STATUSBAR, screen, force || full_update ? SKIN_REFRESH_ALL : SKIN_REFRESH_NON_STATIC); } next_update[i] = current_tick + update_delay; /* don't update too often */ } }
/*{{{ tvm_sleep */ static void tvm_sleep (void) { WORD now = firmware->get_time (firmware); WORD timeout = 0; int set = 0; if (firmware->tptr != NOT_PROCESS_P) { timeout = firmware->tnext; set++; } if (user->tptr != NOT_PROCESS_P) { if (!set || TIME_BEFORE(user->tnext, timeout)) { timeout = user->tnext; set++; } } if (set && TIME_AFTER(timeout, now)) { unsigned int period = timeout - now; if (period > 0) { #if defined(HAVE_NANOSLEEP) struct timespec to; to.tv_sec = (period / 1000000); to.tv_nsec = ((period % 1000000) * 1000); nanosleep (&to, 0); #elif defined(HAVE_SLEEP) Sleep (period / 1000); #else #warning "Don't know how to sleep..." #endif } } }
static void handle_scroll_wheel(int new_scroll) { static const signed char scroll_state[4][4] = { {0, 1, -1, 0}, {-1, 0, 0, 1}, {1, 0, 0, -1}, {0, -1, 1, 0} }; static int prev_scroll = -1; static int direction = 0; static int count = 0; static long next_backlight_on = 0; int wheel_keycode = BUTTON_NONE; int scroll; static unsigned long wheel_delta = 1ul << 24; static unsigned long wheel_velocity = 0; static unsigned long last_wheel_usec = 0; static int prev_keypost = BUTTON_NONE; unsigned long usec; unsigned long v; if ( prev_scroll == -1 ) { prev_scroll = new_scroll; return; } scroll = scroll_state[prev_scroll][new_scroll]; prev_scroll = new_scroll; if (direction != scroll) { /* direction reversal or was hold - reset all */ direction = scroll; count = 0; prev_keypost = BUTTON_NONE; wheel_velocity = 0; wheel_delta = 1ul << 24; return; } /* poke backlight every 1/4s of activity */ if (TIME_AFTER(current_tick, next_backlight_on)) { backlight_on(); reset_poweroff_timer(); next_backlight_on = current_tick + HZ/4; } if (++count < WHEEL_BASE_SENSITIVITY) return; count = 0; /* Mini 1st Gen wheel has inverse direction mapping * compared to 1st..3rd Gen wheel. */ switch (direction) { case 1: wheel_keycode = BUTTON_SCROLL_FWD; break; case -1: wheel_keycode = BUTTON_SCROLL_BACK; break; default: /* only happens if we get out of sync */ break; } /* have a keycode */ usec = USEC_TIMER; v = usec - last_wheel_usec; /* calculate deg/s based upon sensitivity-adjusted interrupt period */ if ((long)v <= 0) { /* timer wrapped (no activity for awhile), skip acceleration */ v = 0; wheel_delta = 1ul << 24; } else { if (v > 0xfffffffful/WHEELCLICKS_PER_ROTATION) { v = 0xfffffffful/WHEELCLICKS_PER_ROTATION; /* check overflow below */ } v = 360000000ul*WHEEL_BASE_SENSITIVITY / (v*WHEELCLICKS_PER_ROTATION); if (v > 0xfffffful) v = 0xfffffful; /* limit to 24 bits */ } if (v < WHEEL_SMOOTHING_VELOCITY) { /* very slow - no smoothing */ wheel_velocity = v; /* ensure backlight never gets stuck for an extended period if tick * wrapped such that next poke is very far ahead */ next_backlight_on = current_tick - 1; } else { /* some velocity filtering to smooth things out */ wheel_velocity = (7*wheel_velocity + v) / 8; } if (queue_empty(&button_queue)) { int key = wheel_keycode; if (v >= WHEEL_REPEAT_VELOCITY && prev_keypost == key) { /* quick enough and same key is being posted more than once in a * row - generate repeats - use unsmoothed v to guage */ key |= BUTTON_REPEAT; } prev_keypost = wheel_keycode; /* post wheel keycode with wheel data */ queue_post(&button_queue, key, (wheel_velocity >= WHEEL_ACCEL_START ? (1ul << 31) : 0) | wheel_delta | wheel_velocity); /* message posted - reset delta */ wheel_delta = 1ul << 24; } else { /* skipped post - increment delta and limit to 7 bits */ wheel_delta += 1ul << 24; if (wheel_delta > (0x7ful << 24)) wheel_delta = 0x7ful << 24; } last_wheel_usec = usec; }
void charging_algorithm_step(void) { #if IMX233_SUBTARGET >= 3780 bool is_5v_present = usb_detect() == USB_INSERTED; /* initial state & 5v -> battery transition */ if(!is_5v_present && charge_state != DISCHARGING) { logf("pwrmgmt: * -> discharging"); logf("pwrmgmt: disable charger and 4p2"); /* 5V has been lost: disable 4p2 power rail */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); BF_WR(POWER_DCDC4P2, ENABLE_DCDC, 0); BF_WR(POWER_DCDC4P2, ENABLE_4P2, 0); BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); charge_state = DISCHARGING; } /* battery -> 5v transition */ else if(is_5v_present && charge_state == DISCHARGING) { logf("pwrmgmt: discharging -> trickle"); logf("pwrmgmt: begin charging 4p2"); /* 5V has been detected: prepare 4.2V power rail for activation */ BF_WR(POWER_DCDC4P2, ENABLE_4P2, 1); BF_SET(POWER_CHARGE, ENABLE_LOAD); BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT, 1); BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2);// FIXME: manual error ? BF_WR(POWER_DCDC4P2, ENABLE_DCDC, 1); timeout_4p2_ilimit_increase = current_tick + HZ / 100; charge_state = TRICKLE; } else if(charge_state == TRICKLE && TIME_AFTER(current_tick, timeout_4p2_ilimit_increase)) { /* if 4.2V current limit has not reached 780mA, increase it slowly to * charge the 4.2V capacitance */ if(BF_RD(POWER_5VCTRL, CHARGE_4P2_ILIMIT) != 0x3f) { //logf("pwrmgmt: incr 4.2 ilimit"); HW_POWER_5VCTRL += BF_POWER_5VCTRL_CHARGE_4P2_ILIMIT(1); timeout_4p2_ilimit_increase = current_tick + HZ / 100; } /* we've reached the maximum, take action */ else { logf("pwrmgmt: enable dcdc and charger"); logf("pwrmgmt: trickle -> charging"); BF_CLR(POWER_5VCTRL, DCDC_XFER); BF_SET(POWER_5VCTRL, ENABLE_DCDC); /* enable battery charging */ BF_CLR(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGING; timeout_charging = current_tick + IMX233_CHARGING_TIMEOUT; } } else if(charge_state == CHARGING && TIME_AFTER(current_tick, timeout_charging)) { /* we have charged for a too long time, declare charger broken */ logf("pwrmgmt: charging timeout exceeded!"); logf("pwrmgmt: charging -> error"); /* stop charging */ BF_SET(POWER_5VCTRL, PWD_CHARGE_4P2); /* goto error state */ charge_state = CHARGE_STATE_ERROR; } else if(charge_state == CHARGING && !BF_RD(POWER_STS, CHRGSTS)) { logf("pwrmgmt: topping off"); logf("pwrmgmt: charging -> topoff"); charge_state = TOPOFF; timeout_topping_off = current_tick + IMX233_TOPOFF_TIMEOUT; } else if(charge_state == TOPOFF && TIME_AFTER(current_tick, timeout_topping_off)) { logf("pwrmgmt: charging finished"); logf("pwrmgmt: topoff -> disabled"); /* stop charging */ BF_SET(POWER_CHARGE, PWD_BATTCHRG); charge_state = CHARGE_STATE_DISABLED; } #endif }
void radio_screen(void) { bool done = false; int button; bool stereo = false, last_stereo = false; int update_type = 0; bool screen_freeze = false; bool keep_playing = false; bool talk = false; #ifdef FM_RECORD_DBLPRE int lastbutton = BUTTON_NONE; unsigned long rec_lastclick = 0; #endif #if CONFIG_CODEC != SWCODEC int timeout = current_tick + HZ/10; #if !defined(SIMULATOR) unsigned int last_seconds = 0; unsigned int seconds = 0; struct audio_recording_options rec_options; #endif /* SIMULATOR */ #endif /* CONFIG_CODEC != SWCODEC */ #ifndef HAVE_NOISY_IDLE_MODE int button_timeout = current_tick + (2*HZ); #endif /* change status to "in screen" */ push_current_activity(ACTIVITY_FM); in_screen = true; if(radio_preset_count() <= 0) { radio_load_presets(global_settings.fmr_file); } skin_get_global_state()->id3 = NULL; #ifdef HAVE_ALBUMART radioart_init(true); #endif if(radio_status == FMRADIO_OFF) audio_stop(); fms_fix_displays(FMS_ENTER); #ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC rec_create_directory(); audio_init_recording(); sound_settings_apply(); /* Yes, we use the D/A for monitoring */ peak_meter_playback(true); peak_meter_enable(true); rec_init_recording_options(&rec_options); rec_options.rec_source = AUDIO_SRC_LINEIN; rec_set_recording_options(&rec_options); audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); #endif /* CONFIG_CODEC != SWCODEC */ #endif /* ndef SIMULATOR */ /* turn on radio */ #if CONFIG_CODEC == SWCODEC /* This should be done before touching audio settings */ while (!pcm_is_initialized()) sleep(0); audio_set_input_source(AUDIO_SRC_FMRADIO, (radio_status == FMRADIO_PAUSED) ? SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING); #else if (radio_status == FMRADIO_OFF) radio_start(); #endif if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN))) presets_scan(NULL); preset_set_current(preset_find(curr_freq)); if(radio_current_preset() != -1) radio_mode = RADIO_PRESET_MODE; /* Load/update the skin at last, when fully initialzed, so that it can * display the right content from the beginning */ FOR_NB_SCREENS(i) skin_update(FM_SCREEN, i, SKIN_REFRESH_ALL); #ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(true); #endif while(!done) { if(search_dir != 0) { curr_freq = step_freq(curr_freq, search_dir); update_type = SKIN_REFRESH_ALL; if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq)) { preset_set_current(preset_find(curr_freq)); remember_frequency(); end_search(); talk = true; } trigger_cpu_boost(); } if (!update_type) { cancel_cpu_boost(); } button = fms_do_button_loop(update_type>0); #ifndef HAVE_NOISY_IDLE_MODE if (button != ACTION_NONE) { cpu_idle_mode(false); button_timeout = current_tick + (2*HZ); } #endif switch(button) { case ACTION_FM_STOP: #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) if(audio_status() == AUDIO_STATUS_RECORD) { audio_stop(); } else #endif { done = true; if(presets_have_changed()) { if(yesno_pop(ID2P(LANG_SAVE_CHANGES))) { presets_save(); } } } update_type = SKIN_REFRESH_NON_STATIC; break; #ifdef FM_RECORD case ACTION_FM_RECORD: #ifdef FM_RECORD_DBLPRE if (lastbutton != ACTION_FM_RECORD_DBLPRE) { rec_lastclick = 0; break; } if (current_tick - rec_lastclick > HZ/2) { rec_lastclick = current_tick; break; } #endif /* FM_RECORD_DBLPRE */ #ifndef SIMULATOR if(audio_status() == AUDIO_STATUS_RECORD) { rec_command(RECORDING_CMD_START_NEWFILE); update_type = SKIN_REFRESH_ALL; } else { rec_command(RECORDING_CMD_START); update_type = SKIN_REFRESH_ALL; } #if CONFIG_CODEC != SWCODEC last_seconds = 0; #endif #endif /* SIMULATOR */ break; #endif /* #ifdef FM_RECORD */ case ACTION_FM_EXIT: #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) if(audio_status() == AUDIO_STATUS_RECORD) audio_stop(); #endif keep_playing = true; done = true; if(presets_have_changed()) { if(yesno_pop(ID2P(LANG_SAVE_CHANGES))) { presets_save(); } } break; case ACTION_STD_PREV: case ACTION_STD_NEXT: next_station(button == ACTION_STD_PREV ? -1 : 1); end_search(); update_type = SKIN_REFRESH_ALL; talk = true; break; case ACTION_STD_PREVREPEAT: case ACTION_STD_NEXTREPEAT: { int dir = search_dir; search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1; if (radio_mode != RADIO_SCAN_MODE) { preset_next(search_dir); end_search(); talk = true; } else if (dir == 0) { /* Starting auto scan */ tuner_set(RADIO_MUTE, 1); } update_type = SKIN_REFRESH_ALL; break; } case ACTION_SETTINGS_INC: case ACTION_SETTINGS_INCREPEAT: global_settings.volume++; setvol(); update_type = SKIN_REFRESH_NON_STATIC; break; case ACTION_SETTINGS_DEC: case ACTION_SETTINGS_DECREPEAT: global_settings.volume--; setvol(); update_type = SKIN_REFRESH_NON_STATIC; break; case ACTION_FM_PLAY: if (radio_status == FMRADIO_PLAYING) radio_pause(); else radio_start(); update_type = SKIN_REFRESH_NON_STATIC; talk = false; talk_shutup(); break; case ACTION_FM_MENU: fms_fix_displays(FMS_EXIT); do_menu(&radio_settings_menu, NULL, NULL, false); preset_set_current(preset_find(curr_freq)); fms_fix_displays(FMS_ENTER); update_type = SKIN_REFRESH_ALL; break; #ifdef FM_PRESET case ACTION_FM_PRESET: if(radio_preset_count() < 1) { splash(HZ, ID2P(LANG_FM_NO_PRESETS)); update_type = SKIN_REFRESH_ALL; break; } fms_fix_displays(FMS_EXIT); handle_radio_presets(); fms_fix_displays(FMS_ENTER); update_type = SKIN_REFRESH_ALL; break; #endif /* FM_PRESET */ #ifdef FM_FREEZE case ACTION_FM_FREEZE: if(!screen_freeze) { splash(HZ, str(LANG_FM_FREEZE)); screen_freeze = true; } else { update_type = SKIN_REFRESH_ALL; screen_freeze = false; } break; #endif /* FM_FREEZE */ case SYS_USB_CONNECTED: #if CONFIG_CODEC != SWCODEC /* Only accept USB connection when not recording */ if(audio_status() != AUDIO_STATUS_RECORD) #endif { default_event_handler(SYS_USB_CONNECTED); screen_freeze = true; /* Cosmetic: makes sure the radio screen doesn't redraw */ done = true; } break; #ifdef FM_MODE case ACTION_FM_MODE: if(radio_mode == RADIO_SCAN_MODE) { /* Force scan mode if there are no presets. */ if(radio_preset_count() > 0) radio_mode = RADIO_PRESET_MODE; } else radio_mode = RADIO_SCAN_MODE; update_type = SKIN_REFRESH_ALL; cond_talk_ids_fq(radio_mode ? LANG_PRESET : LANG_RADIO_SCAN_MODE); talk = true; break; #endif /* FM_MODE */ #ifdef FM_NEXT_PRESET case ACTION_FM_NEXT_PRESET: preset_next(1); end_search(); update_type = SKIN_REFRESH_ALL; talk = true; break; #endif #ifdef FM_PREV_PRESET case ACTION_FM_PREV_PRESET: preset_next(-1); end_search(); update_type = SKIN_REFRESH_ALL; talk = true; break; #endif case ACTION_NONE: update_type = SKIN_REFRESH_NON_STATIC; break; /* this case is used by the softlock feature * it requests a full update here */ case ACTION_REDRAW: skin_request_full_update(FM_SCREEN); break; default: default_event_handler(button); #ifdef HAVE_RDS_CAP if (tuner_get(RADIO_EVENT)) update_type = SKIN_REFRESH_ALL; #endif if (!tuner_get(RADIO_PRESENT)) { #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) if(audio_status() == AUDIO_STATUS_RECORD) audio_stop(); #endif keep_playing = false; done = true; if(presets_have_changed()) { if(yesno_pop(ID2P(LANG_SAVE_CHANGES))) { radio_save_presets(); } } /* Clear the preset list on exit. */ preset_list_clear(); } break; } /*switch(button)*/ #ifdef FM_RECORD_DBLPRE if (button != ACTION_NONE) lastbutton = button; #endif #if CONFIG_CODEC != SWCODEC peak_meter_peek(); #endif if(!screen_freeze) { /* Only display the peak meter when not recording */ #if CONFIG_CODEC != SWCODEC if(TIME_AFTER(current_tick, timeout)) { timeout = current_tick + HZ; #else /* SWCODEC */ { #endif /* CONFIG_CODEC == SWCODEC */ /* keep "mono" from always being displayed when paused */ if (radio_status != FMRADIO_PAUSED) { stereo = tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono; if(stereo != last_stereo) { update_type = SKIN_REFRESH_ALL; last_stereo = stereo; } } } #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) seconds = audio_recorded_time() / HZ; if (update_type || seconds > last_seconds) { last_seconds = seconds; #else if (update_type) { #endif FOR_NB_SCREENS(i) skin_update(FM_SCREEN, i, update_type); if (update_type == (int)SKIN_REFRESH_ALL) skin_request_full_update(CUSTOM_STATUSBAR); } } update_type = 0; if (global_settings.talk_file && talk && radio_status == FMRADIO_PAUSED) { talk = false; bool enqueue = false; if (radio_mode == RADIO_SCAN_MODE) { talk_value_decimal(curr_freq, UNIT_INT, 6, enqueue); enqueue = true; } if (radio_current_preset() >= 0) preset_talk(radio_current_preset(), radio_mode == RADIO_PRESET_MODE, enqueue); } #if CONFIG_CODEC != SWCODEC if(audio_status() & AUDIO_STATUS_ERROR) { done = true; } #endif #ifndef HAVE_NOISY_IDLE_MODE if (TIME_AFTER(current_tick, button_timeout)) { cpu_idle_mode(true); } #endif } /*while(!done)*/ #ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC if(audio_status() & AUDIO_STATUS_ERROR) { splash(0, str(LANG_DISK_FULL)); audio_error_clear(); while(1) { button = get_action(CONTEXT_FM|ALLOW_SOFTLOCK, TIMEOUT_BLOCK); if(button == ACTION_FM_STOP) break; } } audio_init_playback(); #endif /* CONFIG_CODEC != SWCODEC */ sound_settings_apply(); #endif /* SIMULATOR */ if(keep_playing) { /* Catch FMRADIO_PLAYING status for the sim. */ #ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC /* Enable the Left and right A/D Converter */ audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); mas_codec_writereg(6, 0x4000); #endif end_search(); #endif /* SIMULATOR */ } else { #if CONFIG_CODEC == SWCODEC audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); #else radio_stop(); #endif } #ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(false); #endif fms_fix_displays(FMS_EXIT); pop_current_activity(); in_screen = false; } /* radio_screen */ void toggle_mono_mode(bool mono) { tuner_set(RADIO_FORCE_MONO, mono); } void set_radio_region(int region) { #ifdef HAVE_RADIO_REGION tuner_set(RADIO_REGION, region); #endif next_station(0); remember_frequency(); (void)region; }
static int browser(void* param) { int ret_val; #ifdef HAVE_TAGCACHE struct tree_context* tc = tree_get_context(); #endif int filter = SHOW_SUPPORTED; char folder[MAX_PATH] = "/"; /* stuff needed to remember position in file browser */ static char last_folder[MAX_PATH] = "/"; /* and stuff for the database browser */ #ifdef HAVE_TAGCACHE static int last_db_dirlevel = 0, last_db_selection = 0; #endif switch ((intptr_t)param) { case GO_TO_FILEBROWSER: filter = global_settings.dirfilter; if (global_settings.browse_current && last_screen == GO_TO_WPS && current_track_path[0]) { strcpy(folder, current_track_path); } else if (!strcmp(last_folder, "/")) { strcpy(folder, global_settings.start_directory); } else { #ifdef HAVE_HOTSWAP bool in_hotswap = false; /* handle entering an ejected drive */ int i; for (i = 0; i < NUM_VOLUMES; i++) { char vol_string[VOL_ENUM_POS + 8]; if (!storage_removable(i)) continue; /* VOL_NAMES contains a %d */ snprintf(vol_string, sizeof(vol_string), "/"VOL_NAMES, i); /* test whether we would browse the external card */ if (!storage_present(i) && (strstr(last_folder, vol_string) #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN || (i == 0) #endif )) { /* leave folder as "/" to avoid crash when trying * to access an ejected drive */ strcpy(folder, "/"); in_hotswap = true; break; } } if (!in_hotswap) #endif strcpy(folder, last_folder); } break; #ifdef HAVE_TAGCACHE case GO_TO_DBBROWSER: if (!tagcache_is_usable()) { bool reinit_attempted = false; /* Now display progress until it's ready or the user exits */ while(!tagcache_is_usable()) { struct tagcache_stat *stat = tagcache_get_stat(); /* Allow user to exit */ if (action_userabort(HZ/2)) break; /* Maybe just needs to reboot due to delayed commit */ if (stat->commit_delayed) { splash(HZ*2, ID2P(LANG_PLEASE_REBOOT)); break; } /* Check if ready status is known */ if (!stat->readyvalid) { splash(0, str(LANG_TAGCACHE_BUSY)); continue; } /* Re-init if required */ if (!reinit_attempted && !stat->ready && stat->processed_entries == 0 && stat->commit_step == 0) { /* Prompt the user */ reinit_attempted = true; static const char *lines[]={ ID2P(LANG_TAGCACHE_BUSY), ID2P(LANG_TAGCACHE_FORCE_UPDATE)}; static const struct text_message message={lines, 2}; if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO) break; int i; FOR_NB_SCREENS(i) screens[i].clear_display(); /* Start initialisation */ tagcache_rebuild(); } /* Display building progress */ static long talked_tick = 0; if(global_settings.talk_menu && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+7*HZ))) { talked_tick = current_tick; if (stat->commit_step > 0) { talk_id(LANG_TAGCACHE_INIT, false); talk_number(stat->commit_step, true); talk_id(VOICE_OF, true); talk_number(tagcache_get_max_commit_step(), true); } else if(stat->processed_entries) { talk_number(stat->processed_entries, false); talk_id(LANG_BUILDING_DATABASE, true); } } if (stat->commit_step > 0) { if (lang_is_rtl()) { splashf(0, "[%d/%d] %s", stat->commit_step, tagcache_get_max_commit_step(), str(LANG_TAGCACHE_INIT)); } else { splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), stat->commit_step, tagcache_get_max_commit_step()); } } else { splashf(0, str(LANG_BUILDING_DATABASE), stat->processed_entries); } } } if (!tagcache_is_usable()) return GO_TO_PREVIOUS; filter = SHOW_ID3DB; tc->dirlevel = last_db_dirlevel; tc->selected_item = last_db_selection; break; #endif case GO_TO_BROWSEPLUGINS: filter = SHOW_PLUGINS; strlcpy(folder, PLUGIN_DIR, MAX_PATH); break; } ret_val = rockbox_browse(folder, filter); switch ((intptr_t)param) { case GO_TO_FILEBROWSER: if (!get_current_file(last_folder, MAX_PATH) || (!strchr(&last_folder[1], '/') && global_settings.start_directory[1] != '\0')) { last_folder[0] = '/'; last_folder[1] = '\0'; } break; #ifdef HAVE_TAGCACHE case GO_TO_DBBROWSER: last_db_dirlevel = tc->dirlevel; last_db_selection = tc->selected_item; break; #endif } return ret_val; }
void main (void) { UWORD tbc_length = 0; BYTE *tbc_data = NULL; tbc_t *tbc = NULL; nx_systick_wait_ms (1000); nx__avr_init (); nx_systick_wait_ms (1000); tvm_init (&tvm); for (;;) { U8 buffer[NX_USB_PACKET_SIZE]; WORD usb = 0; U32 pos = 0; U32 i; int running = 1; nx_display_clear (); nx_display_string ("I am the TVM."); nx_display_end_line (); if (tbc != NULL) { nx_display_string ("OK to reload."); nx_display_end_line (); } nx_usb_read (buffer, NX_USB_PACKET_SIZE); while (usb == 0) { if ((pos = nx_usb_data_read ()) >= 8) { if ((tbc_length = valid_tbc_header (buffer))) { tbc_length += 8; tbc_data = (BYTE *) mem_pool; tbc = NULL; for (i = 0; i < pos; ++i) { tbc_data[i] = buffer[i]; } usb = tbc_length - pos; } } else { switch (nx_avr_get_button ()) { case BUTTON_OK: if (tbc != NULL) { usb = -1; } break; case BUTTON_CANCEL: nx__avr_power_down (); break; default: nx_systick_wait_ms (100); break; } } } if (usb > 0) { nx_display_cursor_set_pos (0, 1); nx_display_string ("Got header ("); nx_display_uint (tbc_length); nx_display_string (")"); nx_display_end_line (); nx_display_cursor_set_pos (0, 2); nx_display_uint (usb); nx_display_string (" "); } else { nx_display_string ("Reload TBC ("); nx_display_uint (tbc_length); nx_display_string (")"); nx_display_end_line (); } while (usb > 0) { U32 tmp; if (usb >= NX_USB_PACKET_SIZE) { nx_usb_read (&(tbc_data[pos]), NX_USB_PACKET_SIZE); } else { nx_usb_read (&(tbc_data[pos]), usb); } while (!(tmp = nx_usb_data_read ())) continue; pos += tmp; usb -= tmp; nx_display_cursor_set_pos (0, 2); nx_display_uint (usb); nx_display_string (" "); } nx_display_cursor_set_pos (0, 2); nx_display_string ("Got TBC. "); nx_display_end_line (); nx_systick_wait_ms (200); tvm_ectx_init (&tvm, &context); context.mem_pool = mem_pool + tbc_length; context.get_time = nxt_get_time; context.modify_sync_flags = nxt_modify_sync_flags; context.sffi_table = sffi_table; context.sffi_table_length = sffi_table_length; tlsf_init_memory_pool (NX_USERSPACE_SIZE - tbc_length, (void *) context.mem_pool); if ((tbc = load_context_with_tbc (&context, tbc, tbc_data, tbc_length)) == NULL) { nx_display_string ("Decode failed!"); nx_systick_wait_ms (3000); continue; } nx_display_string ("Running..."); nx_display_end_line (); nx_systick_wait_ms (1000); nx_display_clear (); while (running) { int ret = tvm_run (&context); switch (ret) { case ECTX_PREEMPT: case ECTX_TIME_SLICE: { /* Safe to continue. */ break; } case ECTX_SLEEP: { WORD next = context.tnext; WORD now = nxt_get_time (&context); while (TIME_AFTER (next, now)) { nx_systick_wait_ms (next - now); now = nxt_get_time (&context); } break; } case ECTX_INTERRUPT: { //clear_pending_interrupts (); break; } case ECTX_EMPTY: { //if (!waiting_on_interrupts ()) { //terminate("deadlock", NULL); //} nx_display_end_line (); nx_display_string ("Deadlock."); break; } case ECTX_SHUTDOWN: { nx_display_end_line (); nx_display_string ("End of program."); running = 0; break; } default: { nx_display_end_line (); nx_display_string ("Error = "); nx_display_uint (ret); running = 0; break; } } } for (i = 0; i < 3; ++i) nx_motors_stop (i, FALSE); for (i = 0; i < 4; ++i) nx__sensors_disable (i); nx_systick_wait_ms (3000); } /* NOTREACHED */ }
enum yesno_res gui_syncyesno_run(const struct text_message * main_message, const struct text_message * yes_message, const struct text_message * no_message) { int i; int button; int result=-1; bool result_displayed; struct gui_yesno yn[NB_SCREENS]; struct viewport vp[NB_SCREENS]; long talked_tick = 0; FOR_NB_SCREENS(i) { yn[i].main_message=main_message; yn[i].result_message[YESNO_YES]=yes_message; yn[i].result_message[YESNO_NO]=no_message; yn[i].display=&screens[i]; yn[i].vp = &vp[i]; viewportmanager_theme_enable(i, true, yn[i].vp); screens[i].stop_scroll(); gui_yesno_draw(&(yn[i])); } while (result==-1) { /* Repeat the question every 5secs (more or less) */ if (global_settings.talk_menu && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5))) { talked_tick = current_tick; talk_text_message(main_message, false); } button = get_action(CONTEXT_YESNOSCREEN, HZ*5); switch (button) { case ACTION_YESNO_ACCEPT: result=YESNO_YES; break; case ACTION_NONE: case SYS_CHARGER_DISCONNECTED: /* ignore some SYS events that can happen */ continue; default: if(default_event_handler(button) == SYS_USB_CONNECTED) return(YESNO_USB); result = YESNO_NO; } } FOR_NB_SCREENS(i) result_displayed=gui_yesno_draw_result(&(yn[i]), result); if (global_settings.talk_menu) { talk_text_message((result == YESNO_YES) ? yes_message : no_message, false); talk_force_enqueue_next(); } if(result_displayed) sleep(HZ); FOR_NB_SCREENS(i) { screens[i].scroll_stop(yn[i].vp); viewportmanager_theme_undo(i, true); } return(result); }
static void power_thread(void) { long next_power_hist; /* Delay reading the first battery level */ #ifdef MROBE_100 while (_battery_voltage() > 4200) /* gives false readings initially */ #elif defined(DX50) || defined(DX90) while (_battery_voltage() < 1) /* can give false readings initially */ #endif { sleep(HZ/100); } #if CONFIG_CHARGING /* Initialize power input status before calling other routines. */ power_thread_inputs = power_input_status(); #endif /* initialize voltage averaging (if available) */ average_init(); /* get initial battery level value (in %) */ init_battery_percent(); /* get some initial data for the power curve */ collect_power_history(); /* call target specific init now */ powermgmt_init_target(); next_power_hist = current_tick + HZ*60; while (1) { #if CONFIG_CHARGING unsigned int pwr = power_input_status(); #ifdef HAVE_BATTERY_SWITCH if ((pwr ^ power_thread_inputs) & POWER_INPUT_BATTERY) { sleep(HZ/10); reset_battery_filter(_battery_voltage()); } #endif power_thread_inputs = pwr; if (!detect_charger(pwr)) #endif /* CONFIG_CHARGING */ { /* Steady state */ sleep(POWER_THREAD_STEP_TICKS); /* Do common power tasks */ power_thread_step(); } /* Perform target tasks */ charging_algorithm_step(); /* check if some idle or sleep timer wears off */ handle_auto_poweroff(); if (TIME_AFTER(current_tick, next_power_hist)) { /* increment to ensure there is a record for every minute * rather than go forward from the current tick */ next_power_hist += HZ*60; collect_power_history(); } } } /* power_thread */
int mmc_init(void) { mutex_init(&mmc_mutex); imx233_ssp_start(MMC_SSP); imx233_ssp_softreset(MMC_SSP); imx233_ssp_set_mode(MMC_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC); #ifdef SANSA_FUZEPLUS /** Sansa Fuze+ has an internal eMMC 8-bit wide flash, power gate is pin PWM3 * and power up time is 20ms */ imx233_set_pin_function(1, 29, PINCTRL_FUNCTION_GPIO); imx233_enable_gpio_output(1, 29, true); imx233_set_gpio_output(1, 29, false); sleep(HZ / 5); imx233_ssp_setup_ssp2_sd_mmc_pins(true, 8, PINCTRL_DRIVE_8mA); #endif /* SSPCLK @ 96MHz * gives bitrate of 96000 / 240 / 1 = 400kHz */ imx233_ssp_set_timings(MMC_SSP, 240, 0, 0xffff); imx233_ssp_sd_mmc_power_up_sequence(MMC_SSP); imx233_ssp_set_bus_width(MMC_SSP, 1); imx233_ssp_set_block_size(MMC_SSP, 9); /* go to idle state */ int ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 0, 0, SSP_NO_RESP, NULL, 0, false, false, NULL); if(ret != 0) return -1; /* send op cond until the card respond with busy bit set; it must complete within 1sec */ unsigned timeout = current_tick + HZ; do { uint32_t ocr; ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 1, 0x40ff8000, SSP_SHORT_RESP, NULL, 0, false, false, &ocr); if(ret == 0 && ocr & (1 << 31)) break; }while(!TIME_AFTER(current_tick, timeout)); if(ret != 0) return -2; /* get CID */ uint32_t cid[4]; ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 2, 0, SSP_LONG_RESP, NULL, 0, false, false, cid); if(ret != 0) return -3; /* Set RCA */ uint32_t status; ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 3, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status); if(ret != 0) return -4; /* Select card */ ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 7, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status); if(ret != 0) return -5; /* Check TRAN state */ ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 13, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status); if(ret != 0) return -6; if(((status >> 9) & 0xf) != 4) return -7; /* Switch to 8-bit bus */ ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 6, 0x3b70200, SSP_SHORT_RESP, NULL, 0, true, false, &status); if(ret != 0) return -8; /* switch error ? */ if(status & 0x80) return -9; imx233_ssp_set_bus_width(MMC_SSP, 8); /* Switch to high speed mode */ ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 6, 0x3b90100, SSP_SHORT_RESP, NULL, 0, true, false, &status); if(ret != 0) return -10; /* switch error ?*/ if(status & 0x80) return -11; /* SSPCLK @ 96MHz * gives bitrate of 96 / 2 / 1 = 48MHz */ imx233_ssp_set_timings(MMC_SSP, 2, 0, 0xffff); #ifdef SANSA_FUZEPLUS /** * The Fuze+ uses a strange layout: is has a first MBR at sector 0 with four entries: * 1) Actual user partition * 2) Sigmatel boot partition * 3)4) Other (certificate related ?) partitions * The partition 1) has type 1 but it's actually a type 5 (logical partition) with * a second partition table with usually one entry which is the FAT32 one. * The first table uses 512-byte sector size and the second one usually uses * 2048-byte logical sector size. * * We restrict mmc window to the user partition */ uint8_t mbr[512]; mmc_window_start = 0; mmc_window_end = INT_MAX; ret = mmc_read_sectors(IF_MD2(0,) 0, 1, mbr); if(ret != 0) return -100; if(mbr[510] != 0x55 || mbr[511] != 0xAA) return -101; /* invalid MBR */ /* sanity check that the first partition is greater than 2Gib */ uint8_t *ent = &mbr[446]; mmc_window_start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24; mmc_window_end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24) + mmc_window_start; if(ent[4] == 0x53) return -102; /* sigmatel partition */ if((mmc_window_end - mmc_window_start) < 4 * 1024 * 1024) return -103; /* partition too small */ #endif return 0; }
static int rockblox_loop (void) { int button; #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE) int lastbutton = BUTTON_NONE; #endif long next_down_tick = *rb->current_tick + level_speed(rockblox_status.level); if (rockblox_menu()) { return 1; } resume = false; resume_file = false; while (1) { #ifdef HAS_BUTTON_HOLD if (rb->button_hold ()) { /* Turn on backlight timeout (revert to settings) */ backlight_use_settings(); rb->splash(0, "Paused"); while (rb->button_hold ()) rb->sleep(HZ/10); /* Turn off backlight timeout */ backlight_ignore_timeout(); /* get rid of the splash text */ rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT); show_details (); #ifdef HIGH_SCORE_Y show_highscores (); #endif draw_next_block (); refresh_board (); } #endif button = rb->button_get_w_tmo (MAX(next_down_tick - *rb->current_tick, 1)); switch (button) { #ifdef ROCKBLOX_RC_OFF case ROCKBLOX_RC_OFF: #endif case ROCKBLOX_OFF: #ifdef ROCKBLOX_OFF_PRE if (lastbutton != ROCKBLOX_OFF_PRE) break; #endif resume = true; return 0; break; #if defined(ROCKBLOX_ROTATE) case ROCKBLOX_ROTATE: #endif case ROCKBLOX_ROTATE_CCW: case ROCKBLOX_ROTATE_CCW | BUTTON_REPEAT: #ifdef HAVE_SCROLLWHEEL /* if the wheel is disabled, add an event to the stack. */ if(wheel_enabled == false) wheel_events++; /* if it's enabled, go ahead and rotate.. */ if(wheel_enabled) #endif #ifdef ROCKBLOX_ROTATE_CCW2 /* fallback */ case ROCKBLOX_ROTATE_CCW2: #endif move_block (0, 0, (rockblox_status.co + 1) % figures[rockblox_status.cf].max_or); break; case ROCKBLOX_ROTATE_CW: case ROCKBLOX_ROTATE_CW | BUTTON_REPEAT: #ifdef HAVE_SCROLLWHEEL if(wheel_enabled == false) wheel_events++; if(wheel_enabled) #endif #ifdef ROCKBLOX_ROTATE_CW2 /* fallback */ case ROCKBLOX_ROTATE_CW2: #endif move_block (0, 0, (rockblox_status.co + figures[rockblox_status.cf].max_or - 1) % figures[rockblox_status.cf].max_or); break; case ROCKBLOX_DOWN: case ROCKBLOX_DOWN | BUTTON_REPEAT: move_block (0, 1, rockblox_status.co); break; case ROCKBLOX_RIGHT: case ROCKBLOX_RIGHT | BUTTON_REPEAT: move_block (1, 0, rockblox_status.co); break; case ROCKBLOX_LEFT: case ROCKBLOX_LEFT | BUTTON_REPEAT: move_block (-1, 0, rockblox_status.co); break; case ROCKBLOX_DROP: #ifdef ROCKBLOX_DROP_PRE if (lastbutton != ROCKBLOX_DROP_PRE) break; #endif while (canMoveTo (rockblox_status.cx, rockblox_status.cy + 1, rockblox_status.co)) move_block (0, 1, rockblox_status.co); rockblox_status.dropped = true; break; #ifdef ROCKBLOX_RESTART case ROCKBLOX_RESTART: rb->splash (HZ * 1, "Restarting..."); init_rockblox (false); break; #endif default: if (rb->default_event_handler (button) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; } #if defined(ROCKBLOX_OFF_PRE) || defined(ROCKBLOX_DROP_PRE) if (button != BUTTON_NONE) lastbutton = button; #endif #ifdef HAVE_SCROLLWHEEL /* check if we should enable the scroll wheel, if events * begin to stack up... */ if(wheel_enabled == false) { /* stopped rotating the wheel, reset the count */ if(wheel_events == last_wheel_event) { last_wheel_event = 0; wheel_events = 0; } /* rotated the wheel a while constantly, enable it. */ else if(wheel_events > 3) { wheel_enabled = true; } /* this evens out the last event and the "current" event. * if we get an event next time through button reading, it will * remain ahead of last_event. if we don't, they'll end up equaling * each other.. thus, the scroll count will be reset. */ if(wheel_enabled == false && wheel_events > last_wheel_event) last_wheel_event++; } #endif if (TIME_AFTER(*rb->current_tick, next_down_tick)) { move_down (); next_down_tick += level_speed(rockblox_status.level); if (TIME_AFTER(*rb->current_tick, next_down_tick)) /* restart time "raster" when we had to wait longer than usual * (pause, game restart etc) */ next_down_tick = *rb->current_tick + level_speed(rockblox_status.level); } if (rockblox_status.gameover) { #if LCD_DEPTH >= 2 rb->lcd_set_foreground (LCD_BLACK); #endif show_game_over(); resume = false; return 0; } refresh_board (); } return 0; }
enum yesno_res gui_syncyesno_run(const struct text_message * main_message, const struct text_message * yes_message, const struct text_message * no_message) { int button; int result=-1; bool result_displayed; struct gui_yesno yn[NB_SCREENS]; struct viewport vp[NB_SCREENS]; long talked_tick = 0; FOR_NB_SCREENS(i) { yn[i].main_message=main_message; yn[i].result_message[YESNO_YES]=yes_message; yn[i].result_message[YESNO_NO]=no_message; yn[i].display=&screens[i]; yn[i].vp = &vp[i]; #ifdef HAVE_LCD_CHARCELLS /* Quick fix. Viewports should really be enabled proper for charcell */ viewport_set_defaults(yn[i].vp, i); #else viewportmanager_theme_enable(i, true, yn[i].vp); #endif screens[i].stop_scroll(); gui_yesno_draw(&(yn[i])); } /* make sure to eat any extranous keypresses */ while (get_action(CONTEXT_STD+99, TIMEOUT_NOBLOCK)) action_wait_for_release(); while (result==-1) { /* Repeat the question every 5secs (more or less) */ if (global_settings.talk_menu && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5))) { talked_tick = current_tick; talk_text_message(main_message, false); } button = get_action(CONTEXT_YESNOSCREEN, HZ*5); switch (button) { #ifdef HAVE_TOUCHSCREEN case ACTION_TOUCHSCREEN: { short int x, y; if (action_get_touchscreen_press_in_vp(&x, &y, yn[0].vp) == BUTTON_TOUCHSCREEN) { if (y > yn[0].vp->height/2) { if (x <= yn[0].vp->width/2) result = YESNO_YES; else result = YESNO_NO; } } } break; #endif case ACTION_YESNO_ACCEPT: result=YESNO_YES; break; case ACTION_NONE: case SYS_CHARGER_DISCONNECTED: case SYS_BATTERY_UPDATE: /* ignore some SYS events that can happen */ continue; default: if(default_event_handler(button) == SYS_USB_CONNECTED) return(YESNO_USB); result = YESNO_NO; } } FOR_NB_SCREENS(i) result_displayed=gui_yesno_draw_result(&(yn[i]), result); if (global_settings.talk_menu) { talk_text_message((result == YESNO_YES) ? yes_message : no_message, false); talk_force_enqueue_next(); } if(result_displayed) sleep(HZ); FOR_NB_SCREENS(i) { screens[i].scroll_stop(yn[i].vp); viewportmanager_theme_undo(i, true); } return(result); }