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
00121
00122 #include "board.h"
00123
00124 #include <USBDescriptors.h>
00125 #include <USBRequests.h>
00126 #include "USBD.h"
00127 #include <USBD_HAL.h>
00128 #include <USBDDriver.h>
00129 #include <VIDEODescriptors.h>
00130 #include <USBVideo.h>
00131
00132 #include <stdint.h>
00133 #include <stdio.h>
00134 #include <string.h>
00135 #include <assert.h>
00136
00137
00138
00139
00140
00141
00142 #define TWCK 400000
00143
00144
00145 #define BOARD_PINS_TWI_ISI PINS_TWI0
00146
00147
00148 #define BOARD_ID_TWI_ISI ID_TWIHS0
00149
00150 #define BOARD_BASE_TWI_ISI TWIHS0
00151
00152
00153 #define ISI_BASE SDRAM_CS_ADDR
00154
00155
00156
00157 #define ISI_MAX_PREV_BUFFER 12
00158
00159
00160
00161
00162
00163 extern const USBDDriverDescriptors usbdDriverDescriptors;
00164
00165
00166
00167
00168
00169
00170 const Pin pinsTWI[] = BOARD_PINS_TWI_ISI;
00171 const Pin pin_ISI_RST = BOARD_ISI_RST;
00172 const Pin pin_ISI_PWD = BOARD_ISI_PWD;
00173 const Pin pPinsISI[] = {BOARD_ISI_PINS};
00174
00175
00176 static Twid twid;
00177
00178 COMPILER_WORD_ALIGNED
00179 ISI_FrameBufferDescriptors preBufDescList[ISI_MAX_PREV_BUFFER ];
00180
00181 COMPILER_WORD_ALIGNED
00182 static uint8_t pXfrBuffers[FRAME_PACKET_SIZE_HS * (ISO_HIGH_BW_MODE + 1)][1];
00183
00184
00185 static uint32_t frmMaxPktSize = FRAME_PACKET_SIZE_HS * (ISO_HIGH_BW_MODE + 1);
00186
00187
00188 static uint8_t bAlternateInterfaces[4];
00189
00190
00191
00192 static USBVideoProbeData viddProbeData = {
00193 0,
00194 0x01,
00195 0x01,
00196 FRAME_INTERVALC(4),
00197 0,
00198 0,
00199 10000,
00200 0,
00201 100,
00202 FRAME_BUFFER_SIZEC(800, 600),
00203 FRAME_PACKET_SIZE_FS
00204 };
00205
00206
00207
00208 static uint8_t pControlBuffer[32];
00209
00210
00211 static uint32_t frmI = 0;
00212
00213 static uint32_t frmC;
00214
00215
00216 static uint32_t frmW = 320, frmH = 240;
00217
00218
00219 static uint8_t bFrameXfring = 0;
00220
00221
00222 static volatile uint8_t bVideoON = 0;
00223 static volatile uint8_t bVidON = 0;
00224 static volatile uint8_t IsiPrevBuffIndex;
00225 static volatile uint8_t UsbPrevBuffIndex;
00226 static volatile uint32_t delay;
00227 static volatile uint32_t displayFrameAddr;
00228
00229
00230 static uint32_t wImageWidth, wImageHeight;
00231
00232
00233 static sensorOutputFormat_t wImageFormat;
00234
00235 extern const sensorProfile_t ov2643Profile;
00236 extern const sensorProfile_t ov5640Profile;
00237 extern const sensorProfile_t ov7740Profile;
00238 extern const sensorProfile_t ov9740Profile;
00239
00240 static const sensorProfile_t *sensorProfiles[] = {
00241 &ov2643Profile, &ov5640Profile, &ov7740Profile, &ov9740Profile
00242 };
00243
00244 static const char sensorName[][8] = {
00245 "OV2643", "OV5640", "OV7740", "OV9740"
00246 };
00247
00248
00249
00250 static uint8_t *pVideoBufffers = (uint8_t *)ISI_BASE;
00251
00252
00253
00254
00255
00256
00257
00258 void TWIHS0_Handler(void)
00259 {
00260 TWID_Handler(&twid);
00261 }
00262
00263
00264
00265
00266 void ISI_Handler(void)
00267 {
00268
00269 if (ISI_StatusRegister() & ISI_SR_PXFR_DONE) {
00270
00271 displayFrameAddr = preBufDescList[IsiPrevBuffIndex].Current;
00272 IsiPrevBuffIndex++;
00273
00274 if (IsiPrevBuffIndex == ISI_MAX_PREV_BUFFER)
00275 IsiPrevBuffIndex = 0;
00276 }
00277 }
00278
00279
00280
00281
00282 static void _isi_AllocateFBD(void)
00283 {
00284 uint32_t i;
00285 uint32_t framebufOffset;
00286 framebufOffset = FRAME_BUFFER_SIZEC(frmW, frmH);
00287
00288 for (i = 0; i < ISI_MAX_PREV_BUFFER; i++) {
00289 preBufDescList[i].Current = (uint32_t)ISI_BASE + (i * framebufOffset);
00290 preBufDescList[i].Control = ISI_DMA_P_CTRL_P_FETCH;
00291 preBufDescList[i].Next = (uint32_t)&preBufDescList[i + 1];
00292 }
00293
00294 preBufDescList[i - 1].Next = (uint32_t)&preBufDescList[0];
00295 SCB_CleanDCache_by_Addr((uint32_t *)&preBufDescList, sizeof(preBufDescList));
00296 }
00297
00298
00299
00300
00301 static void _twiInit(void)
00302 {
00303
00304 PIO_Configure(pinsTWI, PIO_LISTSIZE(pinsTWI));
00305
00306 PMC_EnablePeripheral(BOARD_ID_TWI_ISI);
00307
00308 TWI_ConfigureMaster(BOARD_BASE_TWI_ISI, TWCK, BOARD_MCK);
00309 TWID_Initialize(&twid, BOARD_BASE_TWI_ISI);
00310
00311
00312 NVIC_ClearPendingIRQ(TWIHS0_IRQn);
00313 NVIC_EnableIRQ(TWIHS0_IRQn);
00314 }
00315
00316
00317
00318
00319 static void _isiPckInit(void)
00320 {
00321
00322 PIO_Configure(pPinsISI, PIO_LISTSIZE(pPinsISI));
00323
00324
00325 REG_PMC_SCDR = PMC_SCER_PCK0;
00326
00327 PMC->PMC_PCK[0] = PMC_PCK_CSS_MCK | (4 << 4);
00328
00329 REG_PMC_SCER = PMC_SCER_PCK0;
00330
00331
00332 while ((REG_PMC_SR & PMC_SR_PCKRDY0) == 0);
00333
00334
00335 PIO_Clear(&pin_ISI_PWD);
00336 PIO_Clear(&pin_ISI_RST);
00337 }
00338
00339
00340
00341
00342 static void _isiInit(void)
00343 {
00344
00345 PMC_EnablePeripheral(ID_ISI);
00346
00347 _isi_AllocateFBD();
00348
00349 ISI_Reset();
00350
00351 ISI_SetBlank(0, 0);
00352
00353 ISI_SetSensorSize(wImageWidth, wImageHeight);
00354
00355 ISI_setInputStream(RGB_INPUT);
00356
00357
00358 ISI_setPreviewSize(frmW, frmH);
00359
00360 ISI_calcScalerFactor();
00361
00362 ISI_setDmaInPreviewPath((uint32_t)&preBufDescList[0],
00363 ISI_DMA_P_CTRL_P_FETCH, (uint32_t)ISI_BASE);
00364 ISI_RgbPixelMapping(ISI_CFG2_RGB_CFG_MODE3);
00365 }
00366
00367
00368 void TC0_Handler(void)
00369 {
00370 REG_TC0_SR0;
00371 }
00372
00373
00374
00375
00376 static void _ConfigureTc(void)
00377 {
00378 uint32_t div;
00379 uint32_t tcclks;
00380
00381
00382 PMC_EnablePeripheral(ID_TC0);
00383
00384 TC_FindMckDivisor(4, BOARD_MCK, &div, &tcclks, BOARD_MCK);
00385
00386 TC_Configure(TC0, 0, tcclks | TC_CMR_CPCTRG);
00387 TC0->TC_CHANNEL[ 0 ].TC_RC = (BOARD_MCK / div) / 4;
00388
00389
00390 NVIC_ClearPendingIRQ(TC0_IRQn);
00391 NVIC_EnableIRQ(TC0_IRQn);
00392
00393 TC0->TC_CHANNEL[ 0 ].TC_IER = TC_IER_CPCS;
00394 TC_Start(TC0, 0);
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404 static void VIDD_UpdateHighBWMaxPacketSize(void)
00405 {
00406
00407 #if (ISO_HIGH_BW_MODE == 1 || ISO_HIGH_BW_MODE == 2)
00408 uint32_t frmSiz = frmW * frmH * 2 + FRAME_PAYLOAD_HDR_SIZE;
00409 uint32_t pktSiz = FRAME_PACKET_SIZE_HS * (ISO_HIGH_BW_MODE + 1);
00410 uint32_t nbLast = frmSiz % pktSiz;
00411
00412 while (1) {
00413 nbLast = frmSiz % pktSiz;
00414
00415 if (nbLast == 0 || nbLast > (FRAME_PACKET_SIZE_HS * ISO_HIGH_BW_MODE))
00416 break;
00417
00418 pktSiz --;
00419 }
00420
00421 frmMaxPktSize = pktSiz;
00422 #else
00423 frmMaxPktSize = FRAME_PACKET_SIZE_HS;
00424 #endif
00425 }
00426
00427
00428
00429
00430 static void VIDD_StatusStage(void)
00431 {
00432 USBVideoProbeData *pProbe = (USBVideoProbeData *)pControlBuffer;
00433 viddProbeData.bFormatIndex = pProbe->bFormatIndex;
00434 viddProbeData.bFrameIndex = pProbe->bFrameIndex;
00435 viddProbeData.dwFrameInterval = pProbe->dwFrameInterval;
00436
00437
00438 switch (pProbe->bFrameIndex) {
00439 case 1: frmW = VIDCAMD_FW_1; frmH = VIDCAMD_FH_1; break;
00440
00441 case 2: frmW = VIDCAMD_FW_2; frmH = VIDCAMD_FH_2; break;
00442
00443 case 3: frmW = VIDCAMD_FW_3; frmH = VIDCAMD_FH_3; break;
00444 }
00445
00446 VIDD_UpdateHighBWMaxPacketSize();
00447 USBD_Write(0, 0, 0, 0, 0);
00448 }
00449
00450
00451
00452
00453 static void VIDD_SetCUR(const USBGenericRequest *pReq)
00454 {
00455 uint8_t bCS = USBVideoRequest_GetControlSelector(pReq);
00456 uint32_t len;
00457 TRACE_INFO_WP("SetCUR(%d) ", pReq->wLength);
00458
00459 if (pReq->wIndex == VIDCAMD_StreamInterfaceNum) {
00460 TRACE_INFO_WP("VS ");
00461
00462 switch (bCS) {
00463 case VS_PROBE_CONTROL:
00464 TRACE_INFO_WP("PROBE ");
00465 len = sizeof(USBVideoProbeData);
00466
00467 if (pReq->wLength < len) len = pReq->wLength;
00468
00469 USBD_Read(0, pControlBuffer, len, (TransferCallback)VIDD_StatusStage, 0);
00470 break;
00471
00472 case VS_COMMIT_CONTROL:
00473 TRACE_INFO_WP("COMMIT ");
00474 len = sizeof(USBVideoProbeData);
00475
00476 if (pReq->wLength < len) len = pReq->wLength;
00477
00478 USBD_Read(0, pControlBuffer, len, (TransferCallback)VIDD_StatusStage, 0);
00479
00480 default: USBD_Stall(0);
00481 }
00482 } else if (pReq->wIndex == VIDCAMD_ControlInterfaceNum){
00483 TRACE_INFO_WP("VC ");
00484 } else {
00485 USBD_Stall(0);
00486 }
00487 }
00488
00489
00490
00491
00492 static void VIDD_GetCUR(const USBGenericRequest *pReq)
00493 {
00494 uint8_t bCS = USBVideoRequest_GetControlSelector(pReq);
00495 uint32_t len;
00496 TRACE_INFO_WP("GetCUR(%d) ", pReq->wLength);
00497
00498 if (pReq->wIndex == VIDCAMD_StreamInterfaceNum) {
00499 TRACE_INFO_WP("VS ");
00500
00501 switch (bCS) {
00502 case VS_PROBE_CONTROL:
00503 TRACE_INFO_WP("PROBE ");
00504 len = sizeof(USBVideoProbeData);
00505
00506 if (pReq->wLength < len) len = pReq->wLength;
00507
00508 USBD_Write(0, &viddProbeData, len, 0, 0);
00509 break;
00510
00511 case VS_COMMIT_CONTROL:
00512 TRACE_INFO_WP("COMMIT ");
00513 USBD_Write(0, &bAlternateInterfaces[VIDCAMD_StreamInterfaceNum], 1, 0, 0);
00514 break;
00515
00516 default: USBD_Stall(0);
00517 }
00518 } else if (pReq->wIndex == VIDCAMD_ControlInterfaceNum) {
00519 TRACE_INFO_WP("VC ");
00520 } else {
00521 USBD_Stall(0);
00522 }
00523 }
00524
00525
00526
00527
00528 static void VIDD_GetDEF(const USBGenericRequest *pReq)
00529 {
00530 printf("GetDEF(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00531 }
00532
00533
00534
00535
00536 static void VIDD_GetINFO(const USBGenericRequest *pReq)
00537 {
00538 printf("GetINFO(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00539 }
00540
00541
00542
00543
00544 static void VIDD_GetMIN(const USBGenericRequest *pReq)
00545 {
00546 printf("GetMin(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00547 VIDD_GetCUR(pReq);
00548
00549 }
00550
00551
00552
00553
00554 static void VIDD_GetMAX(const USBGenericRequest *pReq)
00555 {
00556 printf("GetMax(%x,%x,%d)\n\r", pReq->wIndex, pReq->wValue, pReq->wLength);
00557 VIDD_GetCUR(pReq);
00558 }
00559
00560
00561
00562
00563 static void VIDD_GetRES(const USBGenericRequest *pReq)
00564 {
00565 printf("GetRES(%x,%x,%d) ", pReq->wIndex, pReq->wValue, pReq->wLength);
00566 }
00567
00568
00569
00570
00571 static void VIDD_PayloadSent(void *pArg, uint8_t bStat)
00572 {
00573 uint32_t pktSize;
00574 pArg = pArg; bStat = bStat;
00575 uint8_t *pX = pXfrBuffers[0];
00576
00577 uint32_t frmSize = FRAME_BUFFER_SIZEC(frmW, frmH);
00578 uint8_t *pV = pVideoBufffers;
00579 USBVideoPayloadHeader *pHdr = (USBVideoPayloadHeader *)pX;
00580 uint32_t maxPktSize = USBD_IsHighSpeed() ? (frmMaxPktSize)
00581 : (FRAME_PACKET_SIZE_FS);
00582 pktSize = frmSize - frmI;
00583 pHdr->bHeaderLength = FRAME_PAYLOAD_HDR_SIZE;
00584 pHdr->bmHeaderInfo.B = 0;
00585
00586 if (pktSize > maxPktSize - pHdr->bHeaderLength)
00587 pktSize = maxPktSize - pHdr->bHeaderLength;
00588
00589 pV = &pV[frmI];
00590 frmI += pktSize;
00591 pHdr->bmHeaderInfo.bm.FID = (frmC & 1);
00592
00593 if (frmI >= frmSize) {
00594 frmC ++;
00595 frmI = 0;
00596 pHdr->bmHeaderInfo.bm.EoF = 1;
00597
00598 if (bFrameXfring)
00599 bFrameXfring = 0;
00600 } else {
00601 pHdr->bmHeaderInfo.bm.EoF = 0;
00602
00603 if (bFrameXfring == 0) {
00604 bFrameXfring = 1;
00605
00606 while (UsbPrevBuffIndex == IsiPrevBuffIndex)
00607 memory_barrier();
00608
00609 UsbPrevBuffIndex = IsiPrevBuffIndex;
00610 pVideoBufffers = (uint8_t *)displayFrameAddr;
00611 memory_barrier();
00612 }
00613 }
00614
00615 pHdr->bmHeaderInfo.bm.EOH = 1;
00616
00617 USBD_HAL_WrWithHdr(VIDCAMD_IsoInEndpointNum, pHdr,
00618 pHdr->bHeaderLength, pV, pktSize);
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628 static void _ConfigureUotghs(void)
00629 {
00630
00631
00632 PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00633
00634 PMC->PMC_USB = PMC_USB_USBS;
00635
00636 PMC_EnablePeripheral(ID_USBHS);
00637 USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00638
00639 PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00640
00641
00642 while (!(PMC->PMC_SR & PMC_SR_LOCKU));
00643
00644
00645 NVIC_EnableIRQ(USBHS_IRQn);
00646 }
00647
00648
00649
00650
00651
00652 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00653 {
00654 USBDDriver *pUsbd = USBD_GetDriver();
00655
00656
00657 if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS) {
00658 USBDDriver_RequestHandler(pUsbd, request);
00659 return;
00660 }
00661
00662
00663 TRACE_INFO_WP("Vid ");
00664
00665 switch (USBGenericRequest_GetRequest(request)) {
00666 case VIDGenericRequest_SETCUR: VIDD_SetCUR (request); break;
00667
00668 case VIDGenericRequest_GETCUR: VIDD_GetCUR (request); break;
00669
00670 case VIDGenericRequest_GETDEF: VIDD_GetDEF (request); break;
00671
00672 case VIDGenericRequest_GETINFO: VIDD_GetINFO(request); break;
00673
00674 case VIDGenericRequest_GETMIN: VIDD_GetMIN (request); break;
00675
00676 case VIDGenericRequest_GETMAX: VIDD_GetMAX (request); break;
00677
00678 case VIDGenericRequest_GETRES: VIDD_GetRES (request); break;
00679
00680 default:
00681 TRACE_WARNING("REQ: %x %x %x %x\n\r",
00682 USBGenericRequest_GetType(request),
00683 USBGenericRequest_GetRequest(request),
00684 USBGenericRequest_GetValue(request),
00685 USBGenericRequest_GetLength(request));
00686 USBD_Stall(0);
00687 }
00688
00689 TRACE_INFO_WP("\n\r");
00690 }
00691
00692
00693
00694
00695
00696
00697
00698 void USBDDriverCallbacks_InterfaceSettingChanged(uint8_t interface,
00699 uint8_t setting)
00700 {
00701 if (interface != VIDCAMD_StreamInterfaceNum) return;
00702
00703 if (setting) {
00704 bVideoON = 1;
00705 frmC = 0; frmI = 0;
00706 } else {
00707 bVideoON = 0;
00708 bFrameXfring = 0;
00709 }
00710
00711 memory_sync();
00712 USBD_HAL_ResetEPs(1 << VIDCAMD_IsoInEndpointNum, USBRC_CANCELED, 1);
00713 }
00714
00715
00716
00717
00718 static void _PreviewMode(void)
00719 {
00720 IsiPrevBuffIndex = 0;
00721 UsbPrevBuffIndex = 0;
00722 ISI_SetSensorSize(frmW, frmH);
00723 ISI_setPreviewSize(frmW, frmH);
00724
00725 ISI_calcScalerFactor();
00726 ISI_DisableInterrupt(0xFFFFFFFF);
00727 ISI_DmaChannelDisable(ISI_DMA_CHDR_C_CH_DIS);
00728 ISI_DmaChannelEnable(ISI_DMA_CHER_P_CH_EN);
00729 ISI_EnableInterrupt(ISI_IER_PXFR_DONE);
00730
00731 NVIC_ClearPendingIRQ(ISI_IRQn);
00732 NVIC_EnableIRQ(ISI_IRQn);
00733 ISI_Enable();
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 extern int main(void)
00746 {
00747 uint8_t i = 0;
00748 USBDDriver *pUsbd = USBD_GetDriver();
00749
00750
00751 SCB_EnableICache();
00752 SCB_EnableDCache();
00753
00754 TimeTick_Configure();
00755
00756 BOARD_ConfigureSdram();
00757
00758 WDT_Disable(WDT);
00759
00760
00761 printf("-- USB VIDEO Example %s --\n\r", SOFTPACK_VERSION);
00762 printf("-- %s\n\r", BOARD_NAME);
00763 printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ ,
00764 COMPILER_NAME);
00765
00766 __enable_irq();
00767
00768
00769 _twiInit();
00770
00771
00772 _isiPckInit();
00773 PIO_Set(&pin_ISI_RST);
00774
00775 while (1) {
00776 if (sensor_setup(&twid, sensorProfiles[i], QVGA) == SENSOR_OK) {
00777 printf("\n\r-I- Sensor %s setup succeed.\n\r", sensorName[i]);
00778 break;
00779 }
00780
00781 if (i < (sizeof(sensorProfiles) / sizeof(sensorProfiles[0])))
00782 i++;
00783 else {
00784 printf("\n\r-E- Sensor setup failed.\n\r");
00785
00786 while (1);
00787 }
00788 }
00789
00790
00791 sensor_get_output(&wImageFormat, &wImageWidth, &wImageHeight, QVGA);
00792
00793 if (wImageFormat == MONO_12_BIT) {
00794 printf("-I- Monochrome sensor do not support in this example!");
00795
00796 while (1);
00797 }
00798
00799 if (wImageFormat == RAW_BAYER_12_BIT || wImageFormat == RAW_BAYER_10_BIT)
00800 wImageFormat = (sensorOutputFormat_t)RGB_INPUT;
00801 else
00802 wImageFormat = (sensorOutputFormat_t)YUV_INPUT;
00803
00804
00805 _isiInit();
00806
00807
00808 NVIC_SetPriority(ISI_IRQn, 0);
00809 NVIC_SetPriority(USBHS_IRQn, 2);
00810
00811
00812 _ConfigureUotghs();
00813
00814
00815 USBDDriver_Initialize(pUsbd, &usbdDriverDescriptors, bAlternateInterfaces);
00816 USBD_Init();
00817
00818
00819 USBD_Connect();
00820
00821 _ConfigureTc();
00822
00823 while (1) {
00824 if (USBD_GetState() < USBD_STATE_CONFIGURED)
00825 continue;
00826
00827 if (bVidON && !bVideoON) {
00828 bVidON = 0;
00829 ISI_Disable();
00830 printf("vidE \n\r");
00831 }
00832
00833 if (!bVidON && bVideoON) {
00834 bVidON = 1;
00835 NVIC_ClearPendingIRQ(USBHS_IRQn);
00836 NVIC_DisableIRQ(USBHS_IRQn);
00837 _PreviewMode();
00838
00839 USBD_HAL_SetTransferCallback(VIDCAMD_IsoInEndpointNum,
00840 (TransferCallback)VIDD_PayloadSent, 0);
00841 NVIC_EnableIRQ(USBHS_IRQn);
00842 VIDD_PayloadSent(NULL, USBD_STATUS_SUCCESS);
00843 printf("vidS\n\r");
00844 }
00845 }
00846 }