Beispiel #1
0
void TIMER_Write(const v810_timestamp_t &timestamp, uint32 A, uint8 V)
{
 if(A & 0x3)
 {
  puts("HWCtrl Bogus Write?");
  return;
 }

 TIMER_Update(timestamp);

 //if((A & 0xFF) <= 0x1C)
   //printf("Write: %d, %08x %02x\n", timestamp, A, V);

 switch(A & 0xFF)
 {
  case 0x18: TimerReloadValue &= 0xFF00;
	     TimerReloadValue |= V;
	     ReloadPending = true;
	     break;

  case 0x1C: TimerReloadValue &= 0x00FF;
	     TimerReloadValue |= V << 8;
	     ReloadPending = true;
	     break;

  case 0x20: if(V & TC_ZSTATCLR)
	     {
	      if((TimerControl & TC_TENABLE) && TimerCounter == 0)
	      {
	       //puts("Faulty Z-Stat-Clr");
	      }
	      else
	      {
	       TimerStatus = false;
	      }
	      TimerStatusShadow = false;
	     }
	     if((V & TC_TENABLE) && !(TimerControl & TC_TENABLE))
	     {
	      //TimerCounter = TimerReloadValue;
	      TimerDivider = (V & TC_TCLKSEL) ? 500 : 2000;
	     }
	     TimerControl = V & (0x10 | 0x08 | 0x01);

	     if(!(TimerControl & TC_TIMZINT))
	      TimerStatus = TimerStatusShadow = false;

             VBIRQ_Assert(VBIRQ_SOURCE_TIMER, TimerStatusShadow && (TimerControl & TC_TIMZINT));

	     if(TimerControl & TC_TENABLE)
	      VB_SetEvent(VB_EVENT_TIMER, timestamp + TimerDivider);
	     break;
 }
}
Beispiel #2
0
static void ForceEventUpdates(const pscpu_timestamp_t timestamp)
{
 PSX_SetEventNT(PSX_EVENT_GPU, GPU->Update(timestamp));
 PSX_SetEventNT(PSX_EVENT_CDC, CDC->Update(timestamp));

 PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(timestamp));

 PSX_SetEventNT(PSX_EVENT_DMA, DMA_Update(timestamp));

 PSX_SetEventNT(PSX_EVENT_FIO, FIO->Update(timestamp));

 CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time);
}
Beispiel #3
0
void EventLoop()
{
    CLOCK_ResetWatchdog();
    unsigned int time;

#ifdef HEAP_DEBUG
    static int heap = 0;
    int h = _sbrk_r(NULL, 0);
    if(h > heap) {
        printf("heap: %x\n", h);
        heap = h;
    }
#endif
#ifdef TIMING_DEBUG
    debug_timing(0, 0);
#endif
    priority_ready &= ~(1 << MEDIUM_PRIORITY);
    if(PWR_CheckPowerSwitch()) {
        if(! (BATTERY_Check() & BATTERY_CRITICAL)) {
            CONFIG_SaveModelIfNeeded();
            CONFIG_SaveTxIfNeeded();
        }
    	if(Transmitter.music_shutdown) {
	    MUSIC_Play(MUSIC_SHUTDOWN);
            // We wait ~1sec for shutdown music finished
            time = CLOCK_getms()+700;
            while(CLOCK_getms()<time);
	}

        PWR_Shutdown();
    }
    BUTTON_Handler();
    TOUCH_Handler();

    if (priority_ready & (1 << LOW_PRIORITY)) {
        priority_ready  &= ~(1 << LOW_PRIORITY);
        PAGE_Event();
        PROTOCOL_CheckDialogs();
        TIMER_Update();
        TELEMETRY_Alarm();
        BATTERY_Check();
        AUTODIMMER_Update();
#if DATALOG_ENABLED
        DATALOG_Update();
#endif
        GUI_RefreshScreen();
    }
#ifdef TIMING_DEBUG
    debug_timing(0, 1);
#endif
}
Beispiel #4
0
uint8 TIMER_Read(const v810_timestamp_t &timestamp, uint32 A)
{
 uint8 ret = 0;

 //if(A <= 0x1C)
 //printf("Read: %d, %08x\n", timestamp, A);
 TIMER_Update(timestamp);

 switch(A & 0xFF)
 {
  case 0x18: ret = TimerCounter;
	     break;

  case 0x1C: ret = TimerCounter >> 8;
	     break;

  case 0x20: ret = TimerControl | (0xE0 | TC_ZSTATCLR) | (TimerStatus ? TC_ZSTAT : 0);
	     break;

 }

 return(ret);
}
Beispiel #5
0
bool MDFN_FASTCALL PSX_EventHandler(const pscpu_timestamp_t timestamp)
{
 event_list_entry *e = events[PSX_EVENT__SYNFIRST].next;
#ifdef PSX_EVENT_SYSTEM_CHECKS
 pscpu_timestamp_t prev_event_time = 0;
#endif
#if 0
 {
   printf("EventHandler - timestamp=%8d\n", timestamp);
   event_list_entry *moo = &events[PSX_EVENT__SYNFIRST];
   while(moo)
   {
    printf("%u: %8d\n", moo->which, moo->event_time);
    moo = moo->next;
   }
 }
#endif

#ifdef PSX_EVENT_SYSTEM_CHECKS
 assert(Running == 0 || timestamp >= e->event_time);	// If Running == 0, our EventHandler 
#endif

 while(timestamp >= e->event_time)	// If Running = 0, PSX_EventHandler() may be called even if there isn't an event per-se, so while() instead of do { ... } while
 {
  event_list_entry *prev = e->prev;
  pscpu_timestamp_t nt;

#ifdef PSX_EVENT_SYSTEM_CHECKS
 // Sanity test to make sure events are being evaluated in temporal order.
  if(e->event_time < prev_event_time)
   abort();
  prev_event_time = e->event_time;
#endif

  //printf("Event: %u %8d\n", e->which, e->event_time);
#ifdef PSX_EVENT_SYSTEM_CHECKS
  if((timestamp - e->event_time) > 50)
   printf("Late: %u %d --- %8d\n", e->which, timestamp - e->event_time, timestamp);
#endif

  switch(e->which)
  {
   default: abort();

   case PSX_EVENT_GPU:
	nt = GPU->Update(e->event_time);
	break;

   case PSX_EVENT_CDC:
	nt = CDC->Update(e->event_time);
	break;

   case PSX_EVENT_TIMER:
	nt = TIMER_Update(e->event_time);
	break;

   case PSX_EVENT_DMA:
	nt = DMA_Update(e->event_time);
	break;

   case PSX_EVENT_FIO:
	nt = FIO->Update(e->event_time);
	break;
  }
#ifdef PSX_EVENT_SYSTEM_CHECKS
  assert(nt > e->event_time);
#endif

  PSX_SetEventNT(e->which, nt);

  // Order of events can change due to calling PSX_SetEventNT(), this prev business ensures we don't miss an event due to reordering.
  e = prev->next;
 }

#ifdef PSX_EVENT_SYSTEM_CHECKS
 for(int i = PSX_EVENT__SYNFIRST + 1; i < PSX_EVENT__SYNLAST; i++)
 {
  if(timestamp >= events[i].event_time)
  {
   printf("BUG: %u\n", i);

   event_list_entry *moo = &events[PSX_EVENT__SYNFIRST];

   while(moo)
   {
    printf("%u: %8d\n", moo->which, moo->event_time);
    moo = moo->next;
   }

   abort();
  }
 }
#endif

//#ifdef PSX_EVENT_SYSTEM_CHECKS
// abort();
//#endif

 return(Running);
}
Beispiel #6
0
void EventLoop()
{
    CLOCK_ResetWatchdog();

#ifdef HEAP_DEBUG
    static int heap = 0;
    int h = _sbrk_r(NULL, 0);
    if(h > heap) {
        printf("heap: %x\n", h);
        heap = h;
    }
#endif
#ifdef TIMING_DEBUG
    debug_timing(0, 0);
#endif
    priority_ready &= ~(1 << MEDIUM_PRIORITY);
#if !HAS_HARD_POWER_OFF
    if(PWR_CheckPowerSwitch()) {
        if(! (BATTERY_Check() & BATTERY_CRITICAL)) {
            PAGE_Test();
            CONFIG_SaveModelIfNeeded();
            CONFIG_SaveTxIfNeeded();
        }
    	if(Transmitter.music_shutdown) {
#if HAS_EXTENDED_AUDIO
        if(AUDIO_VoiceAvailable()) {
            MUSIC_Play(MUSIC_SHUTDOWN);
            while (CLOCK_getms() < audio_queue_time) {
                // Wait for voice to finished
                CLOCK_ResetWatchdog();
            }
        } else {
#else
        {
            // We wait ~1sec for shutdown buzzer music finished
            unsigned int time;
            MUSIC_Play(MUSIC_SHUTDOWN);
            time = CLOCK_getms()+700;
            while (CLOCK_getms() < time) {
                CLOCK_ResetWatchdog();
            }
#endif
        }
	}

        PWR_Shutdown();
    }
#endif
    BUTTON_Handler();
    TOUCH_Handler();
    INPUT_CheckChanges();

    if (priority_ready & (1 << LOW_PRIORITY)) {
        priority_ready  &= ~(1 << LOW_PRIORITY);
        PAGE_Event();
        PROTOCOL_CheckDialogs();
        TIMER_Update();
        TELEMETRY_Alarm();
        BATTERY_Check();
        AUTODIMMER_Update();
#if HAS_DATALOG
        DATALOG_Update();
#endif
#if HAS_VIDEO
        VIDEO_Update();
#endif
#if HAS_EXTENDED_AUDIO
        AUDIO_CheckQueue();
#endif
        GUI_RefreshScreen();
#if HAS_HARD_POWER_OFF
        if (PAGE_ModelDoneEditing())
            CONFIG_SaveModelIfNeeded();
        CONFIG_SaveTxIfNeeded();
#endif
    }
#ifdef TIMING_DEBUG
    debug_timing(0, 1);
#endif
}

void TOUCH_Handler() {
    if(! HAS_TOUCH)
        return;
    u32 pen_down=0;

    static u32 pen_down_last=0;
    static u32 pen_down_long_at=0;

    struct touch t;

    if(SPITouch_IRQ()) {
        pen_down=1;
        t=SPITouch_GetCoords();
        if (! pen_down_last)
            pen_down_long_at=CLOCK_getms()+500;
    } else {
        pen_down=0;
    }

    if(pen_down && (!pen_down_last)) {
        AUTODIMMER_Check();
        GUI_CheckTouch(&t, 0);
    }

    if(!pen_down && pen_down_last) {
        GUI_TouchRelease();
    }

    if(pen_down && pen_down_last) {
        if(CLOCK_getms()>pen_down_long_at) {
            GUI_CheckTouch(&t, 1);
            pen_down_long_at += 100;
        }
    }
    pen_down_last=pen_down;
}

#if HAS_VIDEO
void VIDEO_Update()
{
    static u8 video_enable = 0;
    static u32 check_standard_ms = 0;

    // Check if Video is turn on
    int enabled = MIXER_SourceAsBoolean(Model.videosrc);

    if (enabled != video_enable) {
        VIDEO_Enable(enabled);
        video_enable = enabled;
        if (enabled) {
            VIDEO_SetChannel(Model.videoch);
            VIDEO_Contrast(Model.video_contrast);
            VIDEO_Brightness(Model.video_brightness);
            check_standard_ms = CLOCK_getms() + 3000;
        }
        else
            check_standard_ms = 0;
    }

    if(video_enable &&
        check_standard_ms > 0
        && check_standard_ms < CLOCK_getms()) {
            u8 video_standard_current = VIDEO_GetStandard();
            if((video_standard_current > 0) &&
               (video_standard_current < 8)) {
                VIDEO_SetStandard(video_standard_current);
                check_standard_ms = 0;
            }
            else {
                check_standard_ms = CLOCK_getms() + 3000;
            }
        }

    if(video_enable)
        AUTODIMMER_Check();
}
#endif //HAS_VIDEO

#ifdef TIMING_DEBUG
void debug_timing(u32 type, int startend)
{
    static u32 last_time[2][100];
    static u32 loop_time[4][101];
    static u32 loop_pos[4] = {-1, -1, -1, -1};
    static u32 max_last[2];
    static u32 max_loop[4];
    static int save_priority;

    if (type == 0) {
        if (! startend)
            save_priority = priority_ready;
        if (save_priority & (1 << MEDIUM_PRIORITY))
            debug_timing(2, startend);
        if (save_priority & (1 << LOW_PRIORITY))
            debug_timing(1, startend);
        return;
    }
    type--;
    if (! startend) {
        u32 t = CLOCK_getms();
        loop_pos[type] = (loop_pos[type] + 1) % 100;
        if (type < 2) {
            last_time[type][loop_pos[type]] = t;
            if (t - last_time[type][(loop_pos[type] + 99) % 100] > max_last[type])
                max_last[type] = t - last_time[type][(loop_pos[type] + 99) % 100];
        }
        loop_time[type][100] = t;
    } else {
        loop_time[type][loop_pos[type]] = CLOCK_getms() - loop_time[type][100];
        if (loop_time[type][loop_pos[type]] > max_loop[type])
            max_loop[type] = loop_time[type][loop_pos[type]];
        if (type == 0 && loop_pos[0] == 99) {
            unsigned avg_loop[4] = {0, 0, 0, 0};
            unsigned avg_last[2] = {0, 0};
            for(int i = 0; i < 99; i++) {
                for(int t = 0; t < 2; t++) {
                    u32 delay = last_time[t][(i + loop_pos[t] + 2) % 100] - last_time[t][(i + loop_pos[t] + 1) % 100];
                    avg_last[t] += delay;
                }
                for(int t = 0; t < 4; t++)
                    avg_loop[t] += loop_time[t][i];
            }
            for(int t = 0; t < 4; t++)
                avg_loop[t] /= 99;
            avg_last[0] /= 99;
            avg_last[1] /= 99;
            printf("Avg: radio: %d mix: %d med: %d/%d low: %d/%d\n", avg_loop[3], avg_loop[2], avg_loop[1], avg_last[1], avg_loop[0], avg_last[0]);
            printf("Max: radio: %d mix: %d med: %d/%d low: %d/%d\n", max_loop[3], max_loop[2], max_loop[1], max_last[1], max_loop[0], max_last[0]);
            memset(max_loop, 0, sizeof(max_loop));
            max_last[0] = 0;
            max_last[1] = 0;
        }
    }
}
#endif

void debug_switches()
{
    s32 data[INP_LAST];
    for(int i = INP_HAS_CALIBRATION+1; i < INP_LAST; i++) {
        data[i] = CHAN_ReadRawInput(i);
    }
    while(1) {
        u32 changed = 0;
        for(int i = INP_HAS_CALIBRATION+1; i < INP_LAST; i++) {
            s32 val = CHAN_ReadRawInput(i);
            if (val != data[i]) {
                printf("%s=%d  ", INPUT_SourceName(tempstring, i), val);
                data[i] = val;
                changed = 1;
            }
        }
        if (changed) { printf("\n"); }
        if(PWR_CheckPowerSwitch()) PWR_Shutdown();
    }
}