static void IntActUse( void ) { long int RetValue; char KeyBuff; U8 KeyCode; BOOL Running = TRUE; BOOL GlitchAct = FALSE; ST_ErrorCode_t StoredError = ST_NO_ERROR; ST_ErrorCode_t ReturnError; U32 PCRFrequency = CLK_FREQUENCY; U32 STCFrequency; U32 MarkValue; BOOL JumpInPCR = FALSE; U32 BaseB32 = 0; U32 PCRBase; U32 PCRExtd; U32 STCBase; U32 STCExtd; clock_t CurrTime, PrevTime, ElapTime; clock_t PCRTicks, STCTicks; STTBX_Print(( "\nHarness Software Revision is %s\n\n", HarnessRev )); STTBX_Print(( "==========================================================\n" )); STTBX_Print(( "Commencing IntActUse Test Function for Legacy PTI....\n" )); STTBX_Print(( "==========================================================\n" )); STCTicks = time_now(); /* Initialize the sub-subordinate PIO Driver for Port1 only (PWM access enable) */ /* Initialize the sub-subordinate PIO Driver for Port1 only (PWM access enable) */ #if defined (ST_5514) || defined (ST_5516) || defined (ST_5517) /* for Port2 only (PWM access enable) */ strcpy( PIODevNam, "Port2" ); PIOInitPars_s.BaseAddress = (U32*)PIO_2_BASE_ADDRESS; PIOInitPars_s.InterruptNumber = PIO_2_INTERRUPT; PIOInitPars_s.InterruptLevel = PIO_2_INTERRUPT_LEVEL; #else /* for Port1 only (PWM access enable) */ strcpy( PIODevNam, "Port1" ); PIOInitPars_s.BaseAddress = (U32*)PIO_1_BASE_ADDRESS; PIOInitPars_s.InterruptNumber = PIO_1_INTERRUPT; PIOInitPars_s.InterruptLevel = PIO_1_INTERRUPT_LEVEL; #endif PIOInitPars_s.DriverPartition = TEST_PARTITION_1; STTBX_Print(( "Calling STPIO_Init() ................\n" )); ReturnError = STPIO_Init( PIODevNam, &PIOInitPars_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Initialize the sub-ordinate PWM Driver for Channel 0 only (VCXO fine control) */ strcpy( PWMDevNam, "STPWM" ); PWMInitPars_s.Device = STPWM_C4; PWMInitPars_s.C4.BaseAddress = (U32*)PWM_BASE_ADDRESS; PWMInitPars_s.C4.PrescaleFactor = STPWM_PRESCALE_MIN; strcpy( PWMInitPars_s.C4.PIOforPWM0.PortName, PIODevNam ); #if defined (ST_5514) || defined (ST_5516) || defined (ST_5517) PWMInitPars_s.C4.PIOforPWM0.BitMask = PIO_BIT_7; #else PWMInitPars_s.C4.PIOforPWM0.BitMask = PIO_BIT_3; #endif PWMInitPars_s.C4.PIOforPWM1.PortName[0] = '\0'; PWMInitPars_s.C4.PIOforPWM1.BitMask = 0; PWMInitPars_s.C4.PIOforPWM2.PortName[0] = '\0'; PWMInitPars_s.C4.PIOforPWM2.BitMask = 0; STTBX_Print(( "Calling STPWM_Init() for VCXO Channel\n" )); ReturnError = STPWM_Init( PWMDevNam, &PWMInitPars_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Initialize the sub-ordinate EVT Driver */ strcpy( EVTDevNam, "STEVT" ); EVTInitPars_s.EventMaxNum = 3; EVTInitPars_s.ConnectMaxNum = 2; EVTInitPars_s.SubscrMaxNum = 9; /*3; modified for new bom */ EVTInitPars_s.MemoryPartition = TEST_PARTITION_2; EVTInitPars_s.MemorySizeFlag = STEVT_UNKNOWN_SIZE; STTBX_Print(( "Calling STEVT_Init()\n" )); ReturnError = STEVT_Init( EVTDevNam, &EVTInitPars_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Call STEVT_Open() so that we can subscribe to events */ STTBX_Print(( "Calling STEVT_Open() ................\n" )); ReturnError = STEVT_Open( EVTDevNam, &EVTOpenPars_s, &EVTHandle ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Subscribe to PCR Events now so that we can get callbacks when events are registered */ STTBX_Print(( "Calling STEVT_Subscribe(STCLKRV_PCR_VALID_EVT) .....\n" )); ReturnError = STEVT_Subscribe( EVTHandle, STCLKRV_PCR_VALID_EVT, &EVTSubscrParams ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); STTBX_Print(( "Calling STEVT_Subscribe(STCLKRV_PCR_DISCONTINUITY_EVT) ...\n" )); ReturnError = STEVT_Subscribe( EVTHandle, STCLKRV_PCR_DISCONTINUITY_EVT, &EVTSubscrParams ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); STTBX_Print(( "Calling STEVT_Subscribe(STCLKRV_PCR_GLITCH_EVT) ....\n" )); ReturnError = STEVT_Subscribe( EVTHandle, STCLKRV_PCR_GLITCH_EVT, &EVTSubscrParams ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Initialize our native Clock Recovery Driver */ strcpy( DeviceNam, "STCLKRV" ); strcpy( InitParams_s.PWMDeviceName, PWMDevNam ); InitParams_s.VCXOChannel = STCLKRVT_VCXO_CHANNEL; InitParams_s.InitialMark = STCLKRV_INIT_MARK_VALUE; InitParams_s.MinimumMark = STCLKRV_MIN_MARK_VALUE; InitParams_s.MaximumMark = STCLKRV_MAX_MARK_VALUE; InitParams_s.PCRMaxGlitch = STCLKRV_PCR_MAX_GLITCH; InitParams_s.PCRDriftThres = STCLKRV_PCR_DRIFT_THRES; InitParams_s.TicksPerMark = STCLKRV_TICKS_PER_MARK; InitParams_s.MinSampleThres = STCLKRV_MIN_SAMPLE_THRESHOLD; InitParams_s.MaxWindowSize = STCLKRV_MAX_WINDOW_SIZE; InitParams_s.Partition_p = TEST_PARTITION_2; InitParams_s.DeviceType = STCLKRV_DEVICE_PWMOUT; strcpy( InitParams_s.EVTDeviceName, EVTDevNam ); STTBX_Print(( "Calling STCLKRV_Init() ..............\n" )); ReturnError = STCLKRV_Init( DeviceNam, &InitParams_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Open the Clock Recovery Driver */ STTBX_Print(( "Calling STCLKRV_Open() ..............\n" )); ReturnError = STCLKRV_Open( DeviceNam, &OpenParams_s, &Handle ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); PCRTicks = CurrTime = time_now(); STTBX_Print(( "==========================================================\n" )); STTBX_Print(( "Keys are as follows (case insensitive apart from U & D):\n" )); STTBX_Print(( "U - Up PCR frequency D - Down PCR frequency\n" )); STTBX_Print(( "E - Expected PCR jump J - Jump in PCR (unexpected)\n" )); STTBX_Print(( "G - Glitch in PCR clock Q - Quit InterActive Test\n" )); STTBX_Print(( "==========================================================\n" )); while( Running ) { ReturnError = STCLKRV_PwmGetRatio( Handle, &MarkValue ); STCFrequency = CLK_FREQUENCY + ( STCLKRV_TICKS_PER_MARK * ( MarkValue - STCLKRV_INIT_MARK_VALUE ) ); STTBX_Print(( "PCR = %dHz\tSTC = %dHz\tPWM = %3d\t", PCRFrequency, STCFrequency, MarkValue )); if( NewEventRxd == TRUE ) { if( EventRxd == STCLKRV_PCR_VALID_EVT ) { STTBX_Print(( "Last event = PCR Valid \t\r" )); } else if( EventRxd == STCLKRV_PCR_DISCONTINUITY_EVT ) { STTBX_Print(( "Last event = PCR Discontinuity\t\r" )); } else if( EventRxd == STCLKRV_PCR_GLITCH_EVT ) { STTBX_Print(( "Last event = PCR Glitch \t\r" )); } } else { STTBX_Print(( " \t\r" )); } PrevTime = CurrTime; CurrTime = time_now(); ElapTime = time_minus( CurrTime, PrevTime ); PCRTicks += ( (PCRFrequency * (ElapTime/200)) / (ST_GetClocksPerSecond()/200) ); STCTicks += ( ( STCFrequency * (ElapTime/200) ) / (ST_GetClocksPerSecond()/200) ); /* Glitch is due to late arrival of PCR */ if( GlitchAct ) { /*PCRBase = PCRExtd = 0;*/ STCBase = STCExtd = 0; } else { STCBase = STCTicks / CONV90K_TO_27M; STCExtd = STCTicks - ( STCBase * CONV90K_TO_27M ); } PCRBase = PCRTicks / CONV90K_TO_27M; PCRExtd = PCRTicks - ( PCRBase * CONV90K_TO_27M ); (*ActionPCR)( JumpInPCR, BaseB32, PCRBase, PCRExtd, BaseB32, STCBase, STCExtd ); JumpInPCR = FALSE; GlitchAct = FALSE; RetValue = STTBX_InputPollChar(( &KeyBuff )); /* STTBX_Print(( "RetValue=%ld, KeyBuff=%ld\n", RetValue, KeyBuff )); */ if( RetValue != 0L ) { KeyCode = (U8)KeyBuff; /* STTBX_Print(( "KeyCode=%d\n", ((U32) KeyCode) )); */ switch( KeyCode ) { case 'q': case 'Q': STTBX_Print(( "\nTerminating Interactive Test\n" )); Running = FALSE; break; case 'e': /* JF added */ case 'E': JumpInPCR = TRUE; PCRTicks = CurrTime; break; case 'j': case 'J': PCRTicks = CurrTime; break; case 'u': PCRFrequency += SMALL_PCR_NUDGE; break; case 'U': PCRFrequency += LARGE_PCR_NUDGE; break; case 'd': PCRFrequency -= SMALL_PCR_NUDGE; break; case 'D': PCRFrequency -= LARGE_PCR_NUDGE; break; case 'g': case 'G': GlitchAct = TRUE; /* ***NO BREAK*** */ default: break; } } } /* Close Clock Recovery explicitly */ STTBX_Print(( "Calling STCLKRV_Close() .............\n" )); ReturnError = STCLKRV_Close( Handle ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Unforced Clock Recovery Termination */ TermParams_s.ForceTerminate = FALSE; STTBX_Print(( "Calling STCLKRV_Term() unforced .....\n" )); ReturnError = STCLKRV_Term( DeviceNam, &TermParams_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Terminate the subordinate PWM Driver */ PWMTermPars_s.ForceTerminate = FALSE; STTBX_Print(( "Calling STPWM_Term() unforced .......\n" )); ReturnError = STPWM_Term( PWMDevNam, &PWMTermPars_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Terminate the sub-subordinate PIO Driver */ PIOTermPars_s.ForceTerminate = FALSE; STTBX_Print(( "Calling STPIO_Term() ................\n" )); ReturnError = STPIO_Term( PIODevNam, &PIOTermPars_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); /* Terminate the subordinate EVT Driver */ EVTTermPars_s.ForceTerminate = TRUE; STTBX_Print(( "Calling STEVT_Term() ................\n" )); ReturnError = STEVT_Term( EVTDevNam, &EVTTermPars_s ); ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); STTBX_Print(( "\nOverall test result is " )); ReturnError = StoredError; ErrorReport( &StoredError, ReturnError, ST_NO_ERROR ); }
/****************************************************************************** Function Name : TESTEVT_ConcNotify Description : Evaluate simultaneous STEVT_Notify performance, to see how much locking harms it. There are many scenarios we could try, but as the locking so far proposed is at the driver level, one registrant being simultaneously used by many threads to notify the same event is what we do. Parameters : ******************************************************************************/ ST_ErrorCode_t TESTEVT_ConcNotify( void ) { ST_ErrorCode_t Error, LastError = ST_NO_ERROR; #if defined( ST_OSLINUX ) pthread_attr_t attr; pthread_t notify_th[NUM_THREADS]; struct sched_param sparam; int ret; #endif STEVT_InitParams_t InitParam; STEVT_TermParams_t TermParam; STEVT_Handle_t HandleReg; STEVT_Handle_t HandleSubs[NUM_SUBSCR]; STEVT_EventID_t EventID; STEVT_SubscribeParams_t SubscrParam; task_t *NotifyTasks[NUM_THREADS]; NotifyThreadInfo_t NotifyInfo[NUM_THREADS]; clock_t t1, t2, dt; S32 i; SubscrParam.NotifyCallback = NotifyCB; TermParam.ForceTerminate = TRUE; InitParam.EventMaxNum = 1; InitParam.SubscrMaxNum = NUM_SUBSCR; InitParam.ConnectMaxNum = NUM_SUBSCR+1; #ifdef ST_OS21 InitParam.MemoryPartition = system_partition; #else InitParam.MemoryPartition = (ST_Partition_t *)SystemPartition; #endif InitParam.MemorySizeFlag = STEVT_UNKNOWN_SIZE; /* Initialise EVT device */ Error = STEVT_Init("DevConcNotify", &InitParam); if (Error != ST_NO_ERROR) { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "DevConcNotify initialisation failed")) STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "Received error 0x%08X",Error)); return Error; } /* Open registrant handle */ Error = STEVT_Open("DevConcNotify", NULL, &HandleReg); if (Error != ST_NO_ERROR) { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "ConcNotify: Opening Registrant Handle failed\n")); STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "Received error 0x%08X",Error)); return Error; } /* Register the event */ Error = STEVT_Register (HandleReg, STEVT_DRIVER_BASE, &EventID); if (Error != ST_NO_ERROR) { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "ConcNotify: event registration failed")); STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "Received error 0x%08X",Error)); return Error; } /* subscribe NUM_SUBSCR */ for (i = 0; i < NUM_SUBSCR; ++i) { Error = STEVT_Open("DevConcNotify", NULL, &(HandleSubs[i])); if (Error != ST_NO_ERROR) { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "ConcNotify: Opening subscriber %d failed\n",i)); STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "Received error 0x%08X",Error)); return Error; } Error = STEVT_Subscribe (HandleSubs[i], STEVT_DRIVER_BASE, &SubscrParam); if (Error != ST_NO_ERROR) { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "ConcNotify: subscription %d failed",i)); STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "Received error 0x%08X",Error)); return Error; } } /* set up the notification tasks - because we pre-empt them, we will set them off together. Note they're all at the same priority */ #if defined( ST_OSLINUX ) pthread_attr_init(&attr); sparam.sched_priority = THREAD_PRIORITY; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, &sparam); #endif for (i = 0; i < NUM_THREADS; ++i) { NotifyInfo[i].Handle = HandleReg; NotifyInfo[i].EventId = EventID; #if defined( ST_OSLINUX ) ret = pthread_create(¬ify_th[i],&attr,NotifyThread, (void*)&NotifyInfo[i]); if (ret != 0) #else NotifyTasks[i] = task_create(NotifyThread, (void*)&NotifyInfo[i], STACK_SIZE, THREAD_PRIORITY, "NotifyThread", 0); #endif if (NotifyTasks[i] == NULL) { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "ConcNotify: couldn't create NotifyTask %i",i)); return TESTEVT_ERROR_TASK; } } /* wait for tasks to complete */ /* obscure behaviour: just adding the following halts GX1, unless you also add "NotifyThread returning" above. Without either, zero time is reported, with both 80 ms */ /*STEVT_Print(("Releasing %i tasks...\n", NUM_THREADS));*/ t1 = time_now(); for (i = 0; i < NUM_THREADS; ++i) { Error = STOS_TaskWait (&NotifyTasks[i], TIMEOUT_INFINITY ); if ( Error != ST_NO_ERROR ) { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "ConcNotify: error %d calling task_wait (NotifyTasks[%i])",Error,i)); LastError = TESTEVT_ERROR_TASK; } } t2 = time_now(); dt = time_minus(t2, t1); for (i = 0; i < NUM_THREADS; ++i) { #if defined( ST_OSLINUX ) if (0 != pthread_join(notify_th[i],NULL)) #else if (0 != task_delete(NotifyTasks[i])) #endif { STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "ConcNotify: error deleting NotifyTask %i",i)); LastError = TESTEVT_ERROR_TASK; } } Error = STEVT_Term("DevConcNotify", &TermParam); if (Error != ST_NO_ERROR) { STEVT_Report(( STTBX_REPORT_LEVEL_ERROR, "Device termination failed")) STEVT_Report((STTBX_REPORT_LEVEL_ERROR, "Received error 0x%08X",Error)); LastError = Error; } /* nb STEVT_Term calls omitted on previous error cases */ for (i = 0; i < NUM_THREADS; ++i) { /* propogate errors from notification tasks */ if (NotifyInfo[i].Error != ST_NO_ERROR) { LastError = NotifyInfo[i].Error; } } if (LastError == ST_NO_ERROR) { STEVT_Print(("%i threads concurrently performaing %i notifications each" " to %i subscribers:\n Total time %lu ms (%lu ticks)\n", NUM_THREADS, NUM_NOTIFIES, NUM_SUBSCR, (dt*1000)/ST_GetClocksPerSecond(), dt)); } return LastError; }
int main(int argc, char **argv) { stm_display_plane_t *pPlane; stm_display_buffer_t buffer_setup; char *fbuffer; void *fbufferphys; interrupt_t *vsync_interrupt=0; interrupt_t *hdmi_interrupt=0; int err; int seconds; int clip; int rgb; int dvi; stm_plane_id_t planeid; osclock_t lasttime; kernel_initialize(NULL); kernel_start(); kernel_timeslice(OS21_TRUE); framerate_sem = semaphore_create_fifo(0); frameupdate_sem = semaphore_create_fifo(0); hotplug_sem = semaphore_create_fifo(0); task_create(displayupdate_task_fn, 0, OS21_DEF_MIN_STACK_SIZE, MAX_USER_PRIORITY, "displayupdate", 0); pDev = stm_display_get_device(0); if(!pDev) { printf("Unable to create device instance\n"); return 1; } if(argc<2) usage(); argc--; argv++; seconds = 60; rgb = 0; dvi = 0; clip = 0; while(argc>0) { switch(**argv) { case 'C': { printf("Clipping video signal selected\n"); clip = 1; break; } case 'd': { printf("Setting DVI mode on HDMI output\n"); dvi = 1; break; } case 'h': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing HD vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 50: printf("Setting 1280x720-50\n"); MODE = STVTG_TIMING_MODE_720P50000_74250; STANDARD = STM_OUTPUT_STD_SMPTE296M; framerate = 50; break; case 59: printf("Setting 1280x720-59\n"); MODE = STVTG_TIMING_MODE_720P59940_74176; STANDARD = STM_OUTPUT_STD_SMPTE296M; framerate = 60; break; case 60: printf("Setting 1280x720-60\n"); MODE = STVTG_TIMING_MODE_720P60000_74250; STANDARD = STM_OUTPUT_STD_SMPTE296M; framerate = 60; break; default: fprintf(stderr,"Unsupported HD vertical refresh frequency\n"); usage(); } break; } case 'r': { printf("Setting Component RGB Outputs\n"); rgb = 1; break; } case 'p': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing 1080p vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 23: printf("Setting 1920x1080-23\n"); MODE = STVTG_TIMING_MODE_1080P23976_74176; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 24; break; case 24: printf("Setting 1920x1080-24\n"); MODE = STVTG_TIMING_MODE_1080P24000_74250; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 24; break; case 25: printf("Setting 1920x1080-25\n"); MODE = STVTG_TIMING_MODE_1080P25000_74250; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 25; break; case 29: printf("Setting 1920x1080-29\n"); MODE = STVTG_TIMING_MODE_1080P29970_74176; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 30; break; case 30: printf("Setting 1920x1080-30\n"); MODE = STVTG_TIMING_MODE_1080P30000_74250; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 30; break; case 50: printf("Setting 1920x1080-50\n"); MODE = STVTG_TIMING_MODE_1080P50000_148500; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 50; break; case 59: printf("Setting 1920x1080-59\n"); MODE = STVTG_TIMING_MODE_1080P59940_148352; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 60; break; case 60: printf("Setting 1920x1080-60\n"); MODE = STVTG_TIMING_MODE_1080P60000_148500; STANDARD = STM_OUTPUT_STD_SMPTE274M; framerate = 60; break; default: fprintf(stderr,"Unsupported HD vertical refresh frequency\n"); usage(); } break; } case 's': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing SD vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 50: printf("Setting 720x576-50\n"); MODE = STVTG_TIMING_MODE_576P50000_27000; STANDARD = STM_OUTPUT_STD_SMPTE293M; framerate = 50; break; case 59: printf("Setting 720x480-59\n"); MODE = STVTG_TIMING_MODE_480P59940_27000; STANDARD = STM_OUTPUT_STD_SMPTE293M; framerate = 60; break; case 60: printf("Setting 720x480-60\n"); MODE = STVTG_TIMING_MODE_480P60000_27027; STANDARD = STM_OUTPUT_STD_SMPTE293M; framerate = 60; break; default: fprintf(stderr,"Unsupported SD vertical refresh frequency\n"); usage(); } break; } case 't': { argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing seconds\n"); usage(); } seconds = atoi(*argv); if(seconds<0) usage(); break; } case 'v': { int refresh; argc--; argv++; if(argc <= 0) { fprintf(stderr,"Missing vertical refresh frequency\n"); usage(); } refresh = atoi(*argv); switch(refresh) { case 59: printf("Setting 640x480-59\n"); MODE = STVTG_TIMING_MODE_480P59940_25180; STANDARD = STM_OUTPUT_STD_VESA; framerate = 60; break; case 60: printf("Setting 640x480-60\n"); MODE = STVTG_TIMING_MODE_480P60000_25200; STANDARD = STM_OUTPUT_STD_VESA; framerate = 60; break; default: fprintf(stderr,"Unsupported vertical refresh frequency\n"); usage(); } break; } default: fprintf(stderr,"Unknown option '%s'\n",*argv); usage(); } argc--; argv++; } planeid = OUTPUT_GDP1; vsync_interrupt = get_main_vtg_interrupt(); setup_soc(); if(!vsync_interrupt) { printf("Cannot find VSYNC interrupt handler\n"); return 1; } err = interrupt_install(vsync_interrupt, vsync_isr, pDev); err += interrupt_enable(vsync_interrupt); if(err>0) { printf("Unable to install and enable VSYNC interrupt\n"); return 1; } fbuffer = (char *)malloc(FBSIZE); if(!fbuffer) { printf("Unable to allocate framebuffer\n"); return 1; } memset(fbuffer, 0x00, FBSIZE); create_test_pattern(fbuffer, FBWIDTH, FBHEIGHT, FBSTRIDE); cache_purge_data(fbuffer, FBSIZE); pOutput = stm_display_get_output(pDev, 0); if(!pOutput) { printf("Unable to get output\n"); return 1; } setup_analogue_voltages(pOutput); stm_display_output_set_control(pOutput, STM_CTRL_SIGNAL_RANGE, clip?STM_SIGNAL_VIDEO_RANGE:STM_SIGNAL_FILTER_SAV_EAV); pDVO = get_dvo_output(pDev); { pHDMI = get_hdmi_output(pDev); if(pHDMI) { /* * Now we have a HDMI output pointer to handle hotplug interrupts, * we can enable the interrupt handlers. */ hdmi_interrupt = get_hdmi_interrupt(); if(hdmi_interrupt) { err = interrupt_install(hdmi_interrupt, hdmi_isr, pHDMI); err += interrupt_enable(hdmi_interrupt); } if(err>0) { printf("Unable to install and enable hdmi interrupts\n"); return 1; } stm_display_output_set_control(pHDMI, STM_CTRL_SIGNAL_RANGE, clip?STM_SIGNAL_VIDEO_RANGE:STM_SIGNAL_FILTER_SAV_EAV); } else { printf("Hmmm, no HDMI output available\n"); } } pModeLine = stm_display_output_get_display_mode(pOutput, MODE); if(!pModeLine) { printf("Unable to use requested display mode\n"); return 1; } pPlane = stm_display_get_plane(pDev, planeid); if(!pPlane) { printf("Unable to get graphics plane\n"); return 1; } if(stm_display_plane_connect_to_output(pPlane, pOutput)<0) { printf("Unable to display plane on output\n"); return 1; } if(stm_display_plane_lock(pPlane)<0) { printf("Unable to lock plane's buffer queue\n"); return 1; } memset(&buffer_setup, 0, sizeof(buffer_setup)); vmem_virt_to_phys(fbuffer, &fbufferphys); buffer_setup.src.ulVideoBufferAddr = (ULONG)fbufferphys; buffer_setup.src.ulVideoBufferSize = FBSIZE; buffer_setup.src.ulStride = FBSTRIDE; buffer_setup.src.ulPixelDepth = FBDEPTH; buffer_setup.src.ulColorFmt = FBPIXFMT; buffer_setup.src.Rect.width = FBWIDTH; buffer_setup.src.Rect.height = FBHEIGHT; buffer_setup.dst.Rect.width = FBWIDTH; buffer_setup.dst.Rect.height = FBHEIGHT; buffer_setup.info.ulFlags = STM_PLANE_PRESENTATION_PERSISTENT; printf("Clock is running at %ld ticks per second\n",(long)time_ticks_per_sec()); ULONG format=0; format = rgb?STM_VIDEO_OUT_RGB:STM_VIDEO_OUT_YUV; stm_display_output_set_control(pOutput, STM_CTRL_VIDEO_OUT_SELECT, format); if(pHDMI) { ULONG format = 0; format |= rgb?STM_VIDEO_OUT_RGB:STM_VIDEO_OUT_YUV; format |= dvi?STM_VIDEO_OUT_DVI:STM_VIDEO_OUT_HDMI; stm_display_output_set_control(pHDMI, STM_CTRL_VIDEO_OUT_SELECT, format); } if(stm_display_output_start(pOutput, pModeLine, STANDARD)<0) { printf("Unable to start display\n"); return 1; } if(pDVO) { printf("Info: Attempting to start DVO\n"); if(stm_display_output_start(pDVO, pModeLine, STANDARD)<0) { printf("Info: Unable to start DVO\n"); } } lasttime = time_now(); // VTG Start time (approx) if(stm_display_plane_queue_buffer(pPlane, &buffer_setup)<0) { printf("Unable to queue framebuffer for display on graphics plane\n"); return 1; } task_create(hotplug_task_fn, 0, OS21_DEF_MIN_STACK_SIZE, MIN_USER_PRIORITY, "hotplug", 0); if(seconds == 0) { task_delay(time_ticks_per_sec()*5); task_priority_set(NULL,MIN_USER_PRIORITY); silent_hotplug = 1; err = get_yesno(); } else { while(seconds>0) { osclock_t now,delta; semaphore_wait(framerate_sem); now = time_now(); delta = time_minus(now,lasttime); printf("%d frames took %ld ticks.\n",framerate, (long)delta); lasttime = now; seconds--; } err = 0; } stm_display_plane_flush(pPlane); stm_display_plane_disconnect_from_output(pPlane, pOutput); stm_display_output_stop(pOutput); interrupt_disable(vsync_interrupt); interrupt_disable(hdmi_interrupt); stm_display_plane_release(pPlane); if(pDVO) stm_display_output_release(pDVO); if(pHDMI) stm_display_output_release(pHDMI); stm_display_output_release(pOutput); stm_display_release_device(pDev); return err; }
/******************************************************************************* Name : STDVMi_ServiceTask() Description : STDVM service task Parameters : void *NULL_p NOT USED Return Value : *******************************************************************************/ static void STDVMi_ServiceTask(void *NULL_p) { ST_ErrorCode_t ErrorCode; STDVMi_Handle_t *Handle_p; STDVMi_Handle_t **MsgReceived; clock_t Time2Wait; U32 StartTimeInMs, CurrentTimeInMs, EndTimeInMs; S32 RemainingTime; S32 AudioTrickTime; U32 i; while(STDVMi_ServiceTaskState == TASK_RUNNING) { /* wait on message queue to receive message otherwise check end of file for audio trick mode */ Time2Wait = time_plus(time_now(), ST_GetClocksPerSecond()/10); MsgReceived = message_receive_timeout(STDVMi_ServiceTaskMQ_p, &Time2Wait); if(STDVMi_ServiceTaskState != TASK_RUNNING) { if(MsgReceived != NULL) { message_release(STDVMi_ServiceTaskMQ_p, MsgReceived); } break; } if(MsgReceived != NULL) { Handle_p = *MsgReceived; message_release(STDVMi_ServiceTaskMQ_p, MsgReceived); if(Handle_p->PidChangeState == PID_CHANGE_CHANGING) { /* TODO: Get a copy of the PIDs list or protect Handle_p, since it may be invalid when we reach here */ ErrorCode = STDVM_PlayChangePids((STDVM_Handle_t)Handle_p, Handle_p->StreamInfo_p->ProgramInfo->NbOfPids, Handle_p->StreamInfo_p->ProgramInfo->Pids); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STDVMi_ServiceTask: STDVM_PlayChangePids()=%08X\n", ErrorCode)); } Handle_p->PidChangeState = PID_CHANGE_IDLE; } } else /* Audio trick mode */ { for(i = 0; i < STDVMi_NbOfHandles; i++) { Handle_p = &STDVMi_Handles_p[i]; if((Handle_p->HandleInUse == TRUE) && (Handle_p->ObjectType == STDVM_OBJECT_PLAYBACK) && (Handle_p->AudioOnlyProg == TRUE) && (Handle_p->AudioInTrickMode == TRUE) && (Handle_p->AudioInPause == FALSE) && (Handle_p->AudioTrickEndOfFile == FALSE)) { ErrorCode = STPRM_PlayGetTime(Handle_p->PRM_Handle, &StartTimeInMs, &CurrentTimeInMs, &EndTimeInMs); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STPRM_PlayGetTime : %08X\n", ErrorCode)); continue; } AUDIO_TRICK_ACCESS_MUTEX_LOCK(Handle_p); if(Handle_p->AudioTrickStartTime != 0) { AudioTrickTime = (S32)(((float)time_minus(time_now(), Handle_p->AudioTrickStartTime) * \ Handle_p->CurrentSpeed * 10) / ST_GetClocksPerSecond()); } else { AudioTrickTime = 0; } CurrentTimeInMs = Handle_p->CurrentTime + AudioTrickTime; RemainingTime = (Handle_p->CurrentSpeed > 0) ? (EndTimeInMs - CurrentTimeInMs) : (CurrentTimeInMs - StartTimeInMs); AUDIO_TRICK_ACCESS_MUTEX_RELEASE(Handle_p); if(RemainingTime <= 0) { STPRM_PlayStatus_t PlayStatus; STPRM_RecordStatus_t RecordStatus; U32 HandleIndex; ErrorCode = STPRM_PlayGetStatus(Handle_p->PRM_Handle, &PlayStatus); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STPRM_PlayGetStatus : %08X\n", ErrorCode)); break; } for(HandleIndex = 0; HandleIndex < STDVMi_NbOfHandles; HandleIndex++) { if((STDVMi_Handles_p[HandleIndex].HandleInUse == TRUE) && /* handle is allocated */ (STDVMi_Handles_p[HandleIndex].ObjectType == STDVM_OBJECT_RECORD) && (STDVMi_Handles_p[HandleIndex].StreamInfo_p->Signature == STDVMi_SIGNATURE)) /* object type is record */ { ErrorCode = STPRM_RecordGetStatus(STDVMi_Handles_p[HandleIndex].PRM_Handle, &RecordStatus); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STPRM_RecordGetStatus : %08X\n", ErrorCode)); continue; } if(!(strcmp(PlayStatus.SourceName,RecordStatus.DestinationName))) { ErrorCode = STPRM_PlaySeek(Handle_p->PRM_Handle, EndTimeInMs, STPRM_PLAY_SEEK_SET); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STPRM_PlaySeek : %08X\n", ErrorCode)); break; } ErrorCode = STPRM_PlayResume(Handle_p->PRM_Handle); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STPRM_PlayResume : %08X\n", ErrorCode)); break; } Handle_p->CurrentSpeed = STDVM_PLAY_SPEED_ONE; Handle_p->AudioTrickStartTime = 0; Handle_p->AudioInTrickMode = FALSE; break; } } } if(HandleIndex == STDVMi_NbOfHandles) { Handle_p->CurrentTime = (Handle_p->CurrentSpeed > 0) ? EndTimeInMs : StartTimeInMs; Handle_p->AudioTrickStartTime = 0; Handle_p->AudioTrickEndOfFile = TRUE; ErrorCode = STDVMi_NotifyEvent(STDVM_EVT_END_OF_FILE, Handle_p); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STDVMi_NotifyEvent : %08X\n", ErrorCode)); } ErrorCode = STDVMi_NotifyEvent(STDVM_EVT_END_OF_PLAYBACK, Handle_p); if(ErrorCode != ST_NO_ERROR) { STTBX_Report((STTBX_REPORT_LEVEL_ERROR, "STDVMi_NotifyEvent : %08X\n", ErrorCode)); } } } } }/* for */ } }/* while */ }