00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 #include "board.h"
00121
00122 #include <USBDescriptors.h>
00123 #include <USBRequests.h>
00124 #include "USBD.h"
00125 #include <USBD_HAL.h>
00126 #include <USBDDriver.h>
00127 #include <VIDEODescriptors.h>
00128 #include <USBVideo.h>
00129
00130 #include <stdint.h>
00131 #include <stdio.h>
00132 #include <string.h>
00133 #include <assert.h>
00134
00135
00136
00137
00138
00139 #define VIDEO_WIDTH 320
00140 #define VIDEO_HEIGHT 240
00141
00142
00143 #define TWCK 400000
00144
00145
00146 #define BOARD_PINS_TWI_ISI PINS_TWI0
00147
00148
00149 #define BOARD_ID_TWI_ISI ID_TWIHS0
00150
00151 #define BOARD_BASE_TWI_ISI TWIHS0
00152 #define CAMX_MT9V022_SLAVE_ADDR (0x30>>1)
00153
00154
00155 #define ISI_BASE SDRAM_CS_ADDR
00156
00157
00158 #define USB_BASE (ISI_BASE + VIDEO_WIDTH * VIDEO_HEIGHT)
00159
00160
00161
00162 #define ISI_MAX_PREV_BUFFER 10
00163
00164
00165
00166
00167
00168 extern const USBDDriverDescriptors usbdDriverDescriptors;
00169
00170
00171
00172
00173
00174
00175 const Pin pinsTWI[] = BOARD_PINS_TWI_ISI;
00176 const Pin pin_ISI_RST = BOARD_ISI_RST;
00177 const Pin pin_ISI_PWD = BOARD_ISI_PWD;
00178 const Pin pPinsISI[] = {BOARD_ISI_PINS};
00179
00180
00181 static Twid twid;
00182
00183 COMPILER_ALIGNED(32) ISI_FrameBufferDescriptors preBufDescList;
00184
00185 COMPILER_ALIGNED(32)
00186 static uint8_t pXfrBuffers[FRAME_PACKET_SIZE_HS * (ISO_HIGH_BW_MODE + 1)][1];
00187
00188
00189 static uint32_t frmMaxPktSize = FRAME_PACKET_SIZE_HS * (ISO_HIGH_BW_MODE + 1);
00190
00191
00192 static uint8_t bAlternateInterfaces[4];
00193
00194
00195
00196 static USBVideoProbeData viddProbeData = {
00197 0,
00198 0x01,
00199 0x01,
00200 FRAME_INTERVALC(4),
00201 0,
00202 0,
00203 10000,
00204 0,
00205 100,
00206 FRAME_BUFFER_SIZEC(800, 600),
00207 FRAME_PACKET_SIZE_FS
00208 };
00209
00210
00211
00212 COMPILER_ALIGNED(32) static uint8_t pControlBuffer[32];
00213
00214
00215 static uint32_t frmI = 0;
00216
00217 static uint32_t frmC;
00218
00219
00220 static uint32_t frmW = VIDEO_WIDTH, frmH = VIDEO_HEIGHT;
00221
00222
00223 static uint8_t bFrameXfring = 0;
00224
00225
00226 static volatile uint8_t bVideoON = 0;
00227 static volatile uint8_t bVidON = 0;
00228 static volatile uint8_t IsiPrevBuffIndex;
00229 static volatile uint8_t UsbPrevBuffIndex;
00230 static volatile uint32_t delay;
00231 static volatile uint32_t displayFrameAddr;
00232
00233
00234 static uint32_t wImageWidth, wImageHeight;
00235
00236
00237 static sensorOutputFormat_t wImageFormat;
00238
00239 extern const sensorProfile_t mt9v022Profile;
00240
00241
00242
00243 static uint8_t *pVideoBufffers = (uint8_t *)USB_BASE;
00244
00245
00246
00247
00248
00249
00250
00251 void TWIHS0_Handler(void)
00252 {
00253 TWID_Handler(&twid);
00254 }
00255
00256
00257
00258
00259 static void y2yuv(void)
00260 {
00261 uint16_t i, j;
00262 uint8_t *s;
00263 uint8_t *p;
00264 s = (uint8_t *)ISI_BASE;
00265 p = (uint8_t *)USB_BASE + IsiPrevBuffIndex * (VIDEO_WIDTH * VIDEO_HEIGHT * 2);
00266
00267 for (i = 0; i < wImageWidth; i++) {
00268 for (j = 0; j < wImageHeight; j++) {
00269 *p++ = *s++;
00270 *p++ = 0x80;
00271 }
00272 }
00273 }
00274
00275
00276
00277
00278 void ISI_Handler(void)
00279 {
00280 uint32_t status, imr;
00281 status = ISI->ISI_SR;
00282 imr = ISI->ISI_IMR;
00283
00284 if ((status & ISI_SR_PXFR_DONE) && (imr & ISI_IMR_PXFR_DONE)) {
00285 if (ISI->ISI_DMA_P_ADDR != (uint32_t)ISI_BASE + (wImageWidth * wImageHeight))
00286 return;
00287
00288 ISI_DisableInterrupt(ISI_IDR_PXFR_DONE);
00289 ISI_DmaChannelDisable(ISI_DMA_CHDR_P_CH_DIS);
00290 y2yuv();
00291 ISI_DmaChannelEnable(ISI_DMA_CHER_P_CH_EN);
00292 ISI_EnableInterrupt(ISI_IER_PXFR_DONE);
00293 IsiPrevBuffIndex++;
00294
00295 if (IsiPrevBuffIndex == ISI_MAX_PREV_BUFFER) IsiPrevBuffIndex = 0;
00296 }
00297 }
00298
00299
00300
00301
00302 static void _twiInit(void)
00303 {
00304
00305 PIO_Configure(pinsTWI, PIO_LISTSIZE(pinsTWI));
00306
00307 PMC_EnablePeripheral(BOARD_ID_TWI_ISI);
00308
00309 TWI_ConfigureMaster(BOARD_BASE_TWI_ISI, TWCK, BOARD_MCK);
00310 TWID_Initialize(&twid, BOARD_BASE_TWI_ISI);
00311
00312
00313 NVIC_ClearPendingIRQ(TWIHS0_IRQn);
00314 NVIC_EnableIRQ(TWIHS0_IRQn);
00315 }
00316
00317
00318
00319
00320 static void _isiPckInit(void)
00321 {
00322
00323 PIO_Configure(pPinsISI, PIO_LISTSIZE(pPinsISI));
00324
00325
00326 REG_PMC_SCDR = PMC_SCER_PCK0;
00327
00328 PMC->PMC_PCK[0] = PMC_PCK_CSS_PLLA_CLK | (9 << 4);
00329
00330 REG_PMC_SCER = PMC_SCER_PCK0;
00331
00332
00333 while ((REG_PMC_SR & PMC_SR_PCKRDY0) == 0);
00334
00335
00336 PIO_Clear(&pin_ISI_PWD);
00337 PIO_Clear(&pin_ISI_RST);
00338 }
00339
00340
00341
00342
00343 static void _isiInit(void)
00344 {
00345
00346 PMC_EnablePeripheral(ID_ISI);
00347
00348 ISI_Reset();
00349
00350 ISI_SetBlank(0, 0);
00351
00352 ISI_SetSensorSize(wImageWidth / 2, wImageHeight);
00353
00354 ISI_setPreviewSize(wImageWidth / 2, wImageHeight);
00355
00356 ISI_calcScalerFactor();
00357
00358 ISI_setInputStream(RGB_INPUT);
00359 ISI_RgbPixelMapping(1);
00360
00361 preBufDescList.Current = (uint32_t)ISI_BASE;
00362 preBufDescList.Control = ISI_DMA_P_CTRL_P_FETCH;
00363 preBufDescList.Next = (uint32_t)&preBufDescList;
00364 SCB_CleanDCache_by_Addr((uint32_t *)&preBufDescList, sizeof(preBufDescList));
00365 ISI_setDmaInPreviewPath((uint32_t)&preBufDescList, ISI_DMA_P_CTRL_P_FETCH,
00366 (uint32_t)ISI_BASE);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 static void VIDD_UpdateHighBWMaxPacketSize(void)
00376 {
00377
00378 #if (ISO_HIGH_BW_MODE == 1 || ISO_HIGH_BW_MODE == 2)
00379 uint32_t frmSiz = frmW * frmH * 2 + FRAME_PAYLOAD_HDR_SIZE;
00380 uint32_t pktSiz = FRAME_PACKET_SIZE_HS * (ISO_HIGH_BW_MODE + 1);
00381 uint32_t nbLast = frmSiz % pktSiz;
00382
00383 while (1) {
00384 nbLast = frmSiz % pktSiz;
00385
00386 if (nbLast == 0 || nbLast > (FRAME_PACKET_SIZE_HS * ISO_HIGH_BW_MODE))
00387 break;
00388
00389 pktSiz --;
00390 }
00391
00392 frmMaxPktSize = pktSiz;
00393 #else
00394 frmMaxPktSize = FRAME_PACKET_SIZE_HS;
00395 #endif
00396 }
00397
00398
00399
00400
00401 static void VIDD_StatusStage(void)
00402 {
00403 USBVideoProbeData *pProbe = (USBVideoProbeData *)pControlBuffer;
00404 viddProbeData.bFormatIndex = pProbe->bFormatIndex;
00405 viddProbeData.bFrameIndex = pProbe->bFrameIndex;
00406 viddProbeData.dwFrameInterval = pProbe->dwFrameInterval;
00407
00408
00409 switch (pProbe->bFrameIndex) {
00410 case 1: frmW = VIDCAMD_FW_1; frmH = VIDCAMD_FH_1; break;
00411
00412 case 2: frmW = VIDCAMD_FW_2; frmH = VIDCAMD_FH_2; break;
00413
00414 case 3: frmW = VIDCAMD_FW_3; frmH = VIDCAMD_FH_3; break;
00415 }
00416
00417 VIDD_UpdateHighBWMaxPacketSize();
00418 USBD_Write(0, 0, 0, 0, 0);
00419 }
00420
00421
00422
00423
00424 static void VIDD_SetCUR(const USBGenericRequest *pReq)
00425 {
00426 uint8_t bCS = USBVideoRequest_GetControlSelector(pReq);
00427 uint32_t len;
00428 TRACE_INFO_WP("SetCUR(%d) ", pReq->wLength);
00429
00430 if (pReq->wIndex == VIDCAMD_StreamInterfaceNum) {
00431 TRACE_INFO_WP("VS ");
00432
00433 switch (bCS) {
00434 case VS_PROBE_CONTROL:
00435 TRACE_INFO_WP("PROBE ");
00436 len = sizeof(USBVideoProbeData);
00437
00438 if (pReq->wLength < len) len = pReq->wLength;
00439
00440 USBD_Read(0, pControlBuffer, len, (TransferCallback)VIDD_StatusStage, 0);
00441 break;
00442
00443 case VS_COMMIT_CONTROL:
00444 TRACE_INFO_WP("COMMIT ");
00445 len = sizeof(USBVideoProbeData);
00446
00447 if (pReq->wLength < len) len = pReq->wLength;
00448
00449 USBD_Read(0, pControlBuffer, len, (TransferCallback)VIDD_StatusStage, 0);
00450
00451 default: USBD_Stall(0);
00452 }
00453 } else if (pReq->wIndex == VIDCAMD_ControlInterfaceNum) {
00454 TRACE_INFO_WP("VC ");
00455 }
00456 else USBD_Stall(0);
00457 }
00458
00459
00460
00461
00462 static void VIDD_GetCUR(const USBGenericRequest *pReq)
00463 {
00464 uint8_t bCS = USBVideoRequest_GetControlSelector(pReq);
00465 uint32_t len;
00466 TRACE_INFO_WP("GetCUR(%d) ", pReq->wLength);
00467
00468 if (pReq->wIndex == VIDCAMD_StreamInterfaceNum) {
00469 TRACE_INFO_WP("VS ");
00470
00471 switch (bCS) {
00472 case VS_PROBE_CONTROL:
00473 TRACE_INFO_WP("PROBE ");
00474 len = sizeof(USBVideoProbeData);
00475
00476 if (pReq->wLength < len) len = pReq->wLength;
00477
00478 USBD_Write(0, &viddProbeData, len, 0, 0);
00479 break;
00480
00481 case VS_COMMIT_CONTROL:
00482 TRACE_INFO_WP("COMMIT ");
00483 USBD_Write(0, &bAlternateInterfaces[VIDCAMD_StreamInterfaceNum], 1, 0, 0);
00484 break;
00485
00486 default: USBD_Stall(0);
00487 }
00488 } else if (pReq->wIndex == VIDCAMD_ControlInterfaceNum){
00489 TRACE_INFO_WP("VC ");
00490 }
00491 else USBD_Stall(0);
00492 }
00493
00494
00495
00496
00497 static void VIDD_GetDEF(const USBGenericRequest *pReq)
00498 {
00499 printf("GetDEF(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00500 }
00501
00502
00503
00504
00505 static void VIDD_GetINFO(const USBGenericRequest *pReq)
00506 {
00507 printf("GetINFO(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00508 }
00509
00510
00511
00512
00513 static void VIDD_GetMIN(const USBGenericRequest *pReq)
00514 {
00515 printf("GetMin(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00516 VIDD_GetCUR(pReq);
00517 }
00518
00519
00520
00521
00522 static void VIDD_GetMAX(const USBGenericRequest *pReq)
00523 {
00524 printf("GetMax(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00525 VIDD_GetCUR(pReq);
00526 }
00527
00528
00529
00530
00531 static void VIDD_GetRES(const USBGenericRequest *pReq)
00532 {
00533 printf("GetRES(%x,%x,%d) ", pReq->wIndex, pReq->wValue, pReq->wLength);
00534 }
00535
00536
00537
00538
00539 static void VIDD_PayloadSent(void *pArg, uint8_t bStat)
00540 {
00541 uint32_t pktSize;
00542 pArg = pArg; bStat = bStat;
00543 uint8_t *pX = pXfrBuffers[0];
00544
00545 uint32_t frmSize = FRAME_BUFFER_SIZEC(frmW, frmH);
00546 uint8_t *pV = pVideoBufffers;
00547 USBVideoPayloadHeader *pHdr = (USBVideoPayloadHeader *)pX;
00548 uint32_t maxPktSize = USBD_IsHighSpeed() ? (frmMaxPktSize)
00549 : (FRAME_PACKET_SIZE_FS);
00550 pktSize = frmSize - frmI;
00551 pHdr->bHeaderLength = FRAME_PAYLOAD_HDR_SIZE;
00552 pHdr->bmHeaderInfo.B = 0;
00553
00554 if (pktSize > maxPktSize - pHdr->bHeaderLength)
00555 pktSize = maxPktSize - pHdr->bHeaderLength;
00556
00557 pV = &pV[frmI];
00558 frmI += pktSize;
00559 pHdr->bmHeaderInfo.bm.FID = (frmC & 1);
00560
00561 if (frmI >= frmSize) {
00562 frmC ++;
00563 frmI = 0;
00564 pHdr->bmHeaderInfo.bm.EoF = 1;
00565
00566 if (bFrameXfring)
00567 bFrameXfring = 0;
00568 } else {
00569 pHdr->bmHeaderInfo.bm.EoF = 0;
00570
00571 if (bFrameXfring == 0) {
00572 bFrameXfring = 1;
00573 pVideoBufffers = (uint8_t *)USB_BASE + UsbPrevBuffIndex *
00574 (VIDEO_WIDTH * VIDEO_HEIGHT * 2);
00575 UsbPrevBuffIndex ++;
00576
00577 if (UsbPrevBuffIndex == ISI_MAX_PREV_BUFFER) UsbPrevBuffIndex = 0;
00578
00579 }
00580 }
00581
00582 pHdr->bmHeaderInfo.bm.EOH = 1;
00583 USBD_HAL_WrWithHdr(VIDCAMD_IsoInEndpointNum, pHdr,
00584 pHdr->bHeaderLength, pV, pktSize);
00585 }
00586
00587
00588
00589
00590 static void _ConfigureUotghs(void)
00591 {
00592
00593
00594 PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00595
00596 PMC->PMC_USB = PMC_USB_USBS;
00597
00598 PMC_EnablePeripheral(ID_USBHS);
00599 USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00600
00601 PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00602
00603
00604 while (!(PMC->PMC_SR & PMC_SR_LOCKU));
00605
00606
00607 NVIC_EnableIRQ(USBHS_IRQn);
00608 }
00609
00610
00611
00612
00613
00614 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00615 {
00616 USBDDriver *pUsbd = USBD_GetDriver();
00617
00618
00619 if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS) {
00620 USBDDriver_RequestHandler(pUsbd, request);
00621 return;
00622 }
00623
00624
00625 TRACE_INFO_WP("Vid ");
00626
00627 switch (USBGenericRequest_GetRequest(request)) {
00628 case VIDGenericRequest_SETCUR: VIDD_SetCUR (request); break;
00629
00630 case VIDGenericRequest_GETCUR: VIDD_GetCUR (request); break;
00631
00632 case VIDGenericRequest_GETDEF: VIDD_GetDEF (request); break;
00633
00634 case VIDGenericRequest_GETINFO: VIDD_GetINFO(request); break;
00635
00636 case VIDGenericRequest_GETMIN: VIDD_GetMIN (request); break;
00637
00638 case VIDGenericRequest_GETMAX: VIDD_GetMAX (request); break;
00639
00640 case VIDGenericRequest_GETRES: VIDD_GetRES (request); break;
00641
00642 default:
00643 TRACE_WARNING("REQ: %x %x %x %x\n\r",
00644 USBGenericRequest_GetType(request),
00645 USBGenericRequest_GetRequest(request),
00646 USBGenericRequest_GetValue(request),
00647 USBGenericRequest_GetLength(request));
00648 USBD_Stall(0);
00649 }
00650
00651 TRACE_INFO_WP("\n\r");
00652 }
00653
00654
00655
00656
00657
00658
00659
00660 void USBDDriverCallbacks_InterfaceSettingChanged(uint8_t interface,
00661 uint8_t setting)
00662 {
00663 if (interface != VIDCAMD_StreamInterfaceNum) return;
00664
00665 if (setting) {
00666 bVideoON = 1;
00667 frmC = 0; frmI = 0;
00668 } else {
00669 bVideoON = 0;
00670 bFrameXfring = 0;
00671 }
00672
00673 memory_sync();
00674 USBD_HAL_ResetEPs(1 << VIDCAMD_IsoInEndpointNum, USBRC_CANCELED, 1);
00675 }
00676
00677
00678
00679
00680 static void _PreviewMode(void)
00681 {
00682 IsiPrevBuffIndex = 0;
00683 UsbPrevBuffIndex = 0;
00684 ISI_SetSensorSize(frmW / 2, frmH);
00685 ISI_setPreviewSize(frmW / 2, frmH);
00686
00687 ISI_calcScalerFactor();
00688 ISI_DisableInterrupt(0xFFFFFFFF);
00689 ISI_DmaChannelDisable(ISI_DMA_CHDR_C_CH_DIS);
00690 ISI_DmaChannelEnable(ISI_DMA_CHER_P_CH_EN);
00691 ISI_EnableInterrupt(ISI_IER_PXFR_DONE);
00692
00693 NVIC_ClearPendingIRQ(ISI_IRQn);
00694 NVIC_EnableIRQ(ISI_IRQn);
00695 ISI_Enable();
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 extern int main(void)
00708 {
00709 uint8_t reg = 0x0;
00710 uint8_t val = 0xFD;
00711 USBDDriver *pUsbd = USBD_GetDriver();
00712
00713
00714 SCB_EnableICache();
00715 SCB_EnableDCache();
00716
00717
00718 BOARD_ConfigureSdram();
00719
00720 WDT_Disable(WDT);
00721
00722
00723 printf("-- USB VIDEO Gray Example %s --\n\r", SOFTPACK_VERSION);
00724 printf("-- %s\n\r", BOARD_NAME);
00725 printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ ,
00726 COMPILER_NAME);
00727
00728
00729 TimeTick_Configure();
00730
00731
00732 _twiInit();
00733
00734
00735 _isiPckInit();
00736 PIO_Set(&pin_ISI_RST);
00737
00738 TWID_Write(&twid, CAMX_MT9V022_SLAVE_ADDR, 0x03, 1, ®, 1, 0);
00739 TWID_Write(&twid, CAMX_MT9V022_SLAVE_ADDR, 1, 1, &val, 1, 0);
00740
00741 if (sensor_setup(&twid, &mt9v022Profile, QVGA) != SENSOR_OK) {
00742 printf("-E- Sensor setup failed.");
00743
00744 while (1);
00745 }
00746
00747
00748 sensor_get_output(&wImageFormat, &wImageWidth, &wImageHeight, QVGA);
00749 printf("wImageWidth = %d, %d ", (int)wImageWidth, (int)wImageHeight);
00750
00751
00752 _isiInit();
00753
00754
00755 NVIC_SetPriority(ISI_IRQn, 0);
00756 NVIC_SetPriority(USBHS_IRQn, 2);
00757
00758
00759 _ConfigureUotghs();
00760
00761
00762 USBDDriver_Initialize(pUsbd, &usbdDriverDescriptors, bAlternateInterfaces);
00763 USBD_Init();
00764
00765
00766 USBD_Connect();
00767
00768 while (1) {
00769 if (USBD_GetState() < USBD_STATE_CONFIGURED)
00770 continue;
00771
00772 if (bVidON && !bVideoON) {
00773 bVidON = 0;
00774 ISI_Disable();
00775 printf("vidE \n\r");
00776 }
00777
00778 if (!bVidON && bVideoON) {
00779 bVidON = 1;
00780 NVIC_ClearPendingIRQ(USBHS_IRQn);
00781 NVIC_DisableIRQ(USBHS_IRQn);
00782 _PreviewMode();
00783
00784 USBD_HAL_SetTransferCallback(VIDCAMD_IsoInEndpointNum,
00785 (TransferCallback)VIDD_PayloadSent, 0);
00786 NVIC_EnableIRQ(USBHS_IRQn);
00787 VIDD_PayloadSent(NULL, USBD_STATUS_SUCCESS);
00788 printf("vidS\n\r");
00789 }
00790 }
00791 }