//+---------------------------------------------------------------------------- // // File: kodak.cpp // // Module: // // Synopsis: // // Copyright (C) 1999-2000 Scott Gasch // // Created: 12 Jan 2000 // //+---------------------------------------------------------------------------- #include #include #include #include #include "global.h" #include "trace.h" #include "debug.h" #include "utils.h" #include "dc210camera.h" //+---------------------------------------------------------------------------- // // Function: CKodakDC210 // // Synopsis: // // Arguments: void // // Returns: void // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- CKodakDC210::CKodakDC210(char *szDevice, int iSpeed) { _fInitialized = false; _pSerialPort = NULL; _iMaxAttempts = 5; // // Open the serial port. // if (NULL == (_pSerialPort = new CSerialPort(szDevice))) { Trace("CKodakDC210: unable to open serial port, aborting."); return; } Trace("Port opened.\n"); // // Send the initialize command. // if (!Initialize()) { Trace("KodakDC210: unable to initialize camera communications, " "aborting.\n"); return; } Trace("Camera initialized.\n"); // // Set communications speed. // if (9600 != iSpeed) { if (!SetSpeed(g_iSpeed)) { Trace("InitiailzeCamera: Can't set baud rate.\n"); ASSERT(false); } } Trace("Speed set.\n"); // // Request a dump of properties. // if (!RefreshProperties()) { Trace("Unable to get properties of camera.\n"); ASSERT(FALSE); } Trace("Properties received.\n"); _fInitialized = true; } //+---------------------------------------------------------------------------- // // Function: ~CKodakDC210 // // Synopsis: // // Arguments: void // // Returns: void // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- CKodakDC210::~CKodakDC210(void) { // // Reset camera and serial port speed to default of 9600 bps. // if (!SetSpeed(9600)) { Trace("~CKodakDC210: Can't reset the baud rate to 9600."); } // // Close the serial port. // if (_pSerialPort) { delete _pSerialPort; } _fInitialized = false; } //+---------------------------------------------------------------------------- // // Function: Initialize // // Synopsis: // // Arguments: void // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::Initialize(void) { // // The "initialize" command really causes the camera to query battery // status but we send something here just to see if we can talk to the // camera and fail if not. Also if the camera is asleep this will wake // it up. // if (!SendCommand(DC210_INITIALIZE, 0, 0, 0, 0)) { Trace("Initialize: Initialize command failed -- camera could be " "asleep. Waiting 10 sec and retrying communications.\n"); usleep(100); SetSpeed(9600); // // According to the host interface spec the camera needs at most // ten seconds to wake up and be ready to process more commands. // sleep(10); if (!SendCommand(DC210_INITIALIZE, 0, 0, 0, 0)) { Trace("Initialize: Second try failed too, assuming bad " "connection.\n"); return(false); } } // // Like all commands, the DC210 returns a command-compete status code // to notify you when it's done. If it can't send a command-complete // code within three seconds it will send a busy code. // if (!CommandComplete()) { Trace("Initialize: Never received command complete signal.\n"); ASSERT(false); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: SetSpeed // // Synopsis: // // Arguments: int iBps // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::SetSpeed(int iBps) { BYTE bArg1, bArg2; // // Determine what arguments to send to the camera to communicate // the new speed. // switch (iBps) { case 9600: bArg1 = 0x96; bArg2 = 00; break; case 19200: bArg1 = 0x19; bArg2 = 0x20; break; case 38400: bArg1 = 0x38; bArg2 = 0x40; break; case 57600: bArg1 = 0x57; bArg2 = 0x60; break; case 115200: bArg1 = 0x11; bArg2 = 0x52; break; default: Trace("SetSpeed: illegal speed.\n"); return(false); } // // Send the command to the camera. There will be no response to this // command... // if (!SendCommand(DC210_SET_SPEED, bArg1, bArg2, 0, 0)) { Trace("SetSpeed: Camera communication error, speed not changed.\n"); return(false); } // // Sleep for a little while to let the camera switch speeds. // usleep(50); // // Change the rate at the serial port. // if (!_pSerialPort->SetBaudrate(iBps)) { Trace("SetSpeed: error switching serial port to new speed?\n"); return(false); } // // Sleep again to be sure everythign is done before another command // can execute. // usleep(150); // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: TakePicture // // Synopsis: // // Arguments: void // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::TakePicture(void) { // // Precondition: we are initialized. // ASSERT(_fInitialized == true); // // Send the command to the camera. // if (!SendCommand(DC210_TAKE_PICTURE, 0, 0, 0, 0)) { Trace("TakePicture: Failed to send command.\n"); return(false); } // // Wait for the camera's command complete code. // if (!CommandComplete()) { Trace("TakePicture: Did not receive command completion signal.\n"); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: RefreshProperties // // Synopsis: // // Arguments: void // // Returns: bool - true if command successful // // History: sgasch Created Header 8 Jun 1999 // //+---------------------------------------------------------------------------- bool CKodakDC210::RefreshProperties(void) { // // We do _not_ assert that we are initialized here because this routine // gets called in the constructor before we are initialized fully as // part of class startup. // // // Send the command to the camera. // if (!SendCommand(DC210_STATUS, 0, 0, 0, 0)) { Trace("RefreshProperties: Failed to send command.\n"); return(false); } // // Immediately after the ACK byte from the camera (which SendCommand // checks for) the camera will send us a 256 byte buffer (actually // one packet control byte, 256 data bytes and one checksum byte for // a total of 258 bytes on the serial line) This buffer is the one // with all the status data in it. // if (!ReadPacket(_bRawStatusData, 256)) { Trace("RefreshProperties: Did not get expected status buffer packet " "back.\n"); return(false); } // // After the buffer we get the usual command complete signal. // if (!CommandComplete()) { Trace("RefreshProperties: Did not get command completion signal.\n"); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: GetRawStatusData // // Synopsis: // // Arguments: BYTE *pData // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetRawStatusData(BYTE *pData) { if (RefreshProperties()) { memcpy(pData, _bRawStatusData, 256); return(true); } return(false); } //+---------------------------------------------------------------------------- // // Function: GetFirmwareVersion // // Synopsis: // // Arguments: int *piMajor, // int *piMinor // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetFirmwareVersion(int *piMajor, int *piMinor) { *piMajor = _bRawStatusData[2]; *piMinor = _bRawStatusData[3]; return(true); } //+---------------------------------------------------------------------------- // // Function: GetRomVersion // // Synopsis: // // Arguments: int *piMajor, // int *piMinor // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetRomVersion(int *piMajor, int *piMinor) { *piMajor = _bRawStatusData[4]; *piMinor = _bRawStatusData[5]; return(true); } //+---------------------------------------------------------------------------- // // Function: GetBatteryStatus // // Synopsis: // // Arguments: DC210_BATTERY_STATE *pState // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetBatteryStatus(DC210_BATTERY_STATE *pState) { switch(_bRawStatusData[8]) { case 0: *pState = battery_full; break; case 1: *pState = battery_low; break; case 2: *pState = battery_empty; break; default: ASSERT(false); *pState = battery_unknown; return(false); } return(true); } //+---------------------------------------------------------------------------- // // Function: IsAdapterAttached // // Synopsis: // // Arguments: bool *pfAttached // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsAdapterAttached(bool *pfAttached) { if (RefreshProperties()) { if (_bRawStatusData[9]) { *pfAttached = true; } else { *pfAttached = false; } return(true); } return(false); } //+---------------------------------------------------------------------------- // // Function: GetZoomState // // Synopsis: // // Arguments: DC210_ZOOM_STATE *pZoom // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetZoomState(DC210_ZOOM_STATE *pZoom) { if (RefreshProperties()) { switch(_bRawStatusData[16] & 0x0F) { case 0: *pZoom = zoom_fully_zoomed; break; case 1: *pZoom = zoom_3; break; case 2: *pZoom = zoom_2; break; case 3: *pZoom = zoom_1; break; case 4: *pZoom = zoom_wideangle; break; case 5: *pZoom = zoom_closeup; break; default: ASSERT(false); *pZoom = zoom_unknown; return(false); } return(true); } return(false); } //+---------------------------------------------------------------------------- // // Function: GetResolution // // Synopsis: // // Arguments: int *piWidth, // int *piHeight // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetResolution(int *piWidth, int *piHeight) { if (0 == _bRawStatusData[22]) { *piWidth = 640; *piHeight = 480; } else if (1 == _bRawStatusData[22]) { *piWidth = 1152; *piHeight = 864; } else { ASSERT(false); return(false); } return(true); } //+---------------------------------------------------------------------------- // // Function: IsFlashCharged // // Synopsis: // // Arguments: bool *pfCharged // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsFlashCharged(bool *pfCharged) { if (RefreshProperties()) { if (_bRawStatusData[18]) { *pfCharged = true; } else { *pfCharged = false; } return(true); } return(false); } //+---------------------------------------------------------------------------- // // Function: GetFlashState // // Synopsis: // // Arguments: DC210_FLASH_STATE *pState // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetFlashState(DC210_FLASH_STATE *pState) { switch (_bRawStatusData[20]) { case 0: *pState = flash_auto; break; case 1: *pState = flash_fill; break; case 2: *pState = flash_off; break; case 3: *pState = flash_auto_redeye; break; case 4: *pState = flash_fill_redeye; break; default: ASSERT(false); *pState = flash_unknown; return(false); } return(true); } //+---------------------------------------------------------------------------- // // Function: GetCompressionState // // Synopsis: // // Arguments: DC210_COMPRESSION_STATE *pState // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetCompressionState(DC210_COMPRESSION_STATE *pState) { switch (_bRawStatusData[19]) { case 0: *pState = compression_none; break; case 1: *pState = compression_low; break; case 2: *pState = compression_medium; break; case 3: *pState = compression_high; break; default: ASSERT(false); *pState = compression_unknown; return(false); } return(true); } //+---------------------------------------------------------------------------- // // Function: GetPictureFormat // // Synopsis: // // Arguments: DC210_FILE_FORMAT *eFormat // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetPictureFormat(DC210_FILE_FORMAT *eFormat) { if (2 == _bRawStatusData[23]) { *eFormat = format_raw; } else if (3 == _bRawStatusData[23]) { *eFormat = format_jpeg; } else if (4 == _bRawStatusData[23]) { *eFormat = format_flashpix; } else { *eFormat = format_unknown; ASSERT(false); return(false); } return(true); } //+---------------------------------------------------------------------------- // // Function: GetClock // // Synopsis: // // Arguments: int *piCameraClock // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetClock(int *piCameraClock) { if (RefreshProperties()) { *piCameraClock = _bRawStatusData[15] | (_bRawStatusData[14] << 8) | (_bRawStatusData[13] << 16) | (_bRawStatusData[12] << 24); return(true); } return(false); } //+---------------------------------------------------------------------------- // // Function: IsUsingJpeg // // Synopsis: // // Arguments: bool *pfJPEG // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsUsingJpeg(bool *pfJPEG) { if (3 == _bRawStatusData[23]) { *pfJPEG = true; } else if (4 == _bRawStatusData[23]) { *pfJPEG = false; } else if (2 == _bRawStatusData[23]) { *pfJPEG = false; } else { ASSERT(false); *pfJPEG = false; return(false); } return(true); } //+---------------------------------------------------------------------------- // // Function: IsUsingFlashPix // // Synopsis: // // Arguments: bool *pfFlashPix // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsUsingFlashPix(bool *pfFlashPix) { if (3 == _bRawStatusData[23]) { *pfFlashPix = false; } else if (4 == _bRawStatusData[23]) { *pfFlashPix = true; } else if (2 == _bRawStatusData[23]) { *pfFlashPix = false; } else { ASSERT(false); *pfFlashPix = false; return(false); } return(true); } //+---------------------------------------------------------------------------- // // Function: GetLifetimePictureCount // // Synopsis: // // Arguments: int *piPictures // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetLifetimePictureCount(int *piPictures) { *piPictures = _bRawStatusData[26] | (_bRawStatusData[25] << 8); return(true); } //+---------------------------------------------------------------------------- // // Function: GetLifetimeFlashCount // // Synopsis: // // Arguments: int *piFlashes // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetLifetimeFlashCount(int *piFlashes) { *piFlashes = _bRawStatusData[28] | (_bRawStatusData[27] << 8); return(true); } //+---------------------------------------------------------------------------- // // Function: IsTimerOn // // Synopsis: // // Arguments: bool *pfTimer // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsTimerOn(bool *pfTimer) { if (_bRawStatusData[29]) { *pfTimer = true; } else { *pfTimer = false; } return(true); } //+---------------------------------------------------------------------------- // // Function: IsMemoryCardInserted // // Synopsis: // // Arguments: bool *pfInserted // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsMemoryCardInserted(bool *pfInserted) { if (_bRawStatusData[30] & DC210_MEMORY_CARD_INSERTED) { *pfInserted = true; } else { *pfInserted = false; } return(true); } //+---------------------------------------------------------------------------- // // Function: IsMemoryCardWriteProtected // // Synopsis: // // Arguments: bool *pfWriteProt // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsMemoryCardWriteProtected(bool *pfWriteProt) { if (_bRawStatusData[30] & DC210_MEMORY_CARD_WRITE_PROTECTED) { *pfWriteProt = true; } else { *pfWriteProt = false; } return(true); } //+---------------------------------------------------------------------------- // // Function: IsMemoryCardIllegal // // Synopsis: // // Arguments: bool *pfIllegal // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsMemoryCardIllegal(bool *pfIllegal) { if (_bRawStatusData[30] & DC210_MEMORY_CARD_ILLEGAL) { *pfIllegal = true; } else { *pfIllegal = false; } return(true); } //+---------------------------------------------------------------------------- // // Function: IsMemoryCardFormatted // // Synopsis: // // Arguments: bool *pfFormatted // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsMemoryCardFormatted(bool *pfFormatted) { *pfFormatted = (_bRawStatusData[30] & DC210_MEMORY_CARD_FORMATTED); return(true); } //+---------------------------------------------------------------------------- // // Function: IsMemoryCardOpened // // Synopsis: // // Arguments: bool *pfOpened // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsMemoryCardOpened(bool *pfOpened) { *pfOpened = (_bRawStatusData[30] & DC210_MEMORY_CARD_OPENED); return(true); } //+---------------------------------------------------------------------------- // // Function: GetMemoryCardBitvector // // Synopsis: // // Arguments: BYTE *pbBitv // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetMemoryCardBitvector(BYTE *pbBitv) { *pbBitv = _bRawStatusData[30]; return(true); } //+---------------------------------------------------------------------------- // // Function: IsUsingNTSC // // Synopsis: // // Arguments: bool *pfNTSC // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsUsingNTSC(bool *pfNTSC) { *pfNTSC = (_bRawStatusData[31]); return(true); } //+---------------------------------------------------------------------------- // // Function: IsUsingPAL // // Synopsis: // // Arguments: bool *pfPAL // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::IsUsingPAL(bool *pfPAL) { *pfPAL = (_bRawStatusData[31]); return(true); } //+---------------------------------------------------------------------------- // // Function: GetNumberPictures // // Synopsis: // // Arguments: int *piNum // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetNumberPictures(int *piNum) { *piNum = _bRawStatusData[57] | (_bRawStatusData[56] << 8); return(true); } //+---------------------------------------------------------------------------- // // Function: GetRemainingPicturesLowCompression // // Synopsis: // // Arguments: int *piNum // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetRemainingPicturesLowCompression(int *piNum) { *piNum = _bRawStatusData[69] | (_bRawStatusData[68] << 8); return(true); } //+---------------------------------------------------------------------------- // // Function: GetRemainingPicturesMedCompression // // Synopsis: // // Arguments: int *piNum // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetRemainingPicturesMedCompression(int *piNum) { *piNum = _bRawStatusData[71] | (_bRawStatusData[70] << 8); return(true); } //+---------------------------------------------------------------------------- // // Function: GetRemainingPicturesHighCompression // // Synopsis: // // Arguments: int *piNum // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetRemainingPicturesHighCompression(int *piNum) { *piNum = _bRawStatusData[73] | (_bRawStatusData[72] << 8); return(true); } //+---------------------------------------------------------------------------- // // Function: GetMemoryCardVolumeLabel // // Synopsis: // // Arguments: char *szLabel // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetMemoryCardVolumeLabel(char *szLabel) { memcpy(szLabel, &(_bRawStatusData[77]), 11); szLabel[11] = 0; return(true); } //+---------------------------------------------------------------------------- // // Function: GetIdString // // Synopsis: // // Arguments: char *szId // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetIdString(char *szId) { memcpy(szId, &(_bRawStatusData[90]), 32); szId[32] = 0; return(true); } //+---------------------------------------------------------------------------- // // Function: GetTimeValue // // Synopsis: // // Arguments: int *piClock // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeValue(int *piClock) { if (RefreshProperties()) { *piClock = _bRawStatusData[15] | (_bRawStatusData[14] << 8) | (_bRawStatusData[13] << 16) | (_bRawStatusData[12] << 24); return(true); } return(false); } //+---------------------------------------------------------------------------- // // Function: GetTimeString // // Synopsis: // // Arguments: char *pszTime // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeString(char *pszTime) { static char buf[128]; int iCameraTime; int iTime; int iSize; memset(buf, 0, 128); GetTimeValue(&iCameraTime); iTime = 852094800 + (iCameraTime / 2); iSize = strftime(buf, 127, "%v %r", localtime( (time_t *) &iTime)); strcpy(pszTime, buf); return(true); } //+---------------------------------------------------------------------------- // // Function: GetTimeMinutes // // Synopsis: // // Arguments: int *piMin // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeMinutes(int *piMin) { int iCameraTime; int iTime; struct tm *pTime; (void) GetTimeValue(&iCameraTime); iTime = 852094800 + (iCameraTime / 2); pTime = localtime( (time_t *) &iTime); *piMin = pTime->tm_min; return(true); } //+---------------------------------------------------------------------------- // // Function: GetTimeHours // // Synopsis: // // Arguments: int *piHrs // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeHours(int *piHrs) { int iCameraTime; int iTime; struct tm *pTime; (void) GetTimeValue(&iCameraTime); iTime = 852094800 + (iCameraTime / 2); pTime = localtime( (time_t *) &iTime); *piHrs = pTime->tm_hour; return(true); } //+---------------------------------------------------------------------------- // // Function: GetTimeSeconds // // Synopsis: // // Arguments: int *piSec // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeSeconds(int *piSec) { int iCameraTime; int iTime; struct tm *pTime; (void) GetTimeValue(&iCameraTime); iTime = 852094800 + (iCameraTime / 2); pTime = localtime( (time_t *) &iTime); *piSec = pTime->tm_sec; return(true); } //+---------------------------------------------------------------------------- // // Function: GetTimeMonth // // Synopsis: // // Arguments: int *piMon // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeMonth(int *piMon) { int iCameraTime; int iTime; struct tm *pTime; (void) GetTimeValue(&iCameraTime); iTime = 852094800 + (iCameraTime / 2); pTime = localtime( (time_t *) &iTime); *piMon = pTime->tm_mon + 1; return(true); } //+---------------------------------------------------------------------------- // // Function: GetTimeDay // // Synopsis: // // Arguments: int *piDay // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeDay(int *piDay) { int iCameraTime; int iTime; struct tm *pTime; (void) GetTimeValue(&iCameraTime); iTime = 852094800 + (iCameraTime / 2); pTime = localtime( (time_t *) &iTime); *piDay = pTime->tm_mday; return(true); } //+---------------------------------------------------------------------------- // // Function: GetTimeYear // // Synopsis: // // Arguments: int *piYear // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetTimeYear(int *piYear) { int iCameraTime; int iTime; struct tm *pTime; (void) GetTimeValue(&iCameraTime); iTime = 852094800 + (iCameraTime / 2); pTime = localtime( (time_t *) &iTime); *piYear = pTime->tm_year + 1900; return(true); } //+---------------------------------------------------------------------------- // // Function: SetFlashState // // Synopsis: // // Arguments: bool fState // // Returns: bool // // History: sgasch Created Header 15 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::SetFlashState(bool fState) { DC210_FLASH_STATE eState; // // Precondition: we are initialized. // ASSERT(_fInitialized); // // Call the other SetFlashState routine. // (fState) ? eState = flash_fill : eState = flash_off; return(SetFlashState(eState)); } //+---------------------------------------------------------------------------- // // Function: SetFlashState // // Synopsis: // // Arguments: DC210_FLASH_STATE eState // // Returns: bool // // History: sgasch Created Header 15 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::SetFlashState(DC210_FLASH_STATE eState) { // // Pre: we are initialized. // ASSERT(_fInitialized); // // Send the command // if (!SendCommand(DC210_SET_FLASH, (BYTE) eState, 0, 0, 0)) { Trace("SetFlashState: unable to send command.\n"); ASSERT(false); return(false); } // // Await reply // if (!CommandComplete()) { Trace("SetFlashState: did not receive command complete " "signal.\n"); ASSERT(false); return(false); } // // Refresh status block // if (!RefreshProperties()) { Trace("SetFlashState: Failed to refresh status.\n"); ASSERT(false); return(false); } // // Success // return(true); } bool CKodakDC210::EraseAllPictures(void) { // // Precondition: we are initialized // ASSERT(_fInitialized); // // Send the command // if (!SendCommand(DC210_ERASE, 0xFF, 0xFF, 0, 0)) { Trace("EraseAllPictures: Failed to send command.\n"); ASSERT(false); return(false); } // // Wait for completion // if (!CommandComplete()) { Trace("EraseAllPictures: Failed to get command complete signal.\n"); ASSERT(false); return(false); } // // All pictures were supposedly deleted, let's refresh camera status... // if (!RefreshProperties()) { Trace("EraseAllPictures: Failed to refresh status.\n"); ASSERT(false); return(false); } // // Success // return(true); } bool CKodakDC210::SetResolution(int iWidth, int iHeight) { BYTE bResolutionCode; // code we need to send to the camera // // Preconditions: we are initialized and the resolution is supported // ASSERT(_fInitialized); // // DC210's support two resolutions, 640x480 and 1152x864. // if ((iHeight == 480) && (iWidth == 640)) { bResolutionCode = 0; } else if ((iHeight == 864) && (iWidth == 1152)) { bResolutionCode = 1; } else { Trace("SetResolution: Unsupported resolution. Supported " "settings are 640x480 and 1152x864.\n"); return(false); } // // Send the command // if (!SendCommand(DC210_SET_RESOLUTION, bResolutionCode, 0, 0, 0)) { Trace("SetResolution: Error sending command, aborting.\n"); ASSERT(false); return(false); } // // Await the command complete signal // if (!CommandComplete()) { Trace("SetResolution: Did not receive command completion " "signal, aborting.\n"); ASSERT(false); return(false); } // // Refresh status block // if (!RefreshProperties()) { Trace("SetResolution: Failed to refresh status.\n"); ASSERT(false); return(false); } // // Success. // return(true); } //+---------------------------------------------------------------------------- // // Function: Reset // // Synopsis: This command resets the camera to the system default settings: // // (1) Flash mode is auto // (2) No red-eye reduction flashes // (3) Wide angle zoom position // (4) Timer off // (5) Exposure compensation zero // (6) Compression low (lowest) // (7) Resolution high (1152x864) // (8) Video out mode NTSC // (9) Date/Time reset to 1/1/1997 0:00 // (10) Quickview on // (11) Preview off // (12) Baud rate 9600 // // Arguments: void // // Returns: bool - true if successful // // History: sgasch Created Header 8 Jun 1999 // //+---------------------------------------------------------------------------- bool CKodakDC210::Reset(void) { // // Precondition: we are initialized // ASSERT(_fInitialized); // // Send it... // if (!SendCommand(DC210_RESET, 0, 0, 0, 0)) { Trace("Reset: unable to send command.\n"); ASSERT(false); return(false); } // // Since they will change the serial baud rate to 9600, we will match. // if (!_pSerialPort->SetBaudrate(9600)) { Trace("Reset: Cannot set serial port baud rate to 9600.\n"); ASSERT(false); return(false); } // // Wait for completion. // if (!CommandComplete()) { Trace("Reset: command complete signal not received.\n"); ASSERT(false); return(false); } // // Refresh status block // if (!RefreshProperties()) { Trace("Reset: Failed to refresh status.\n"); ASSERT(false); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: SetCompressionState // // Synopsis: // // Arguments: DC210_COMPRESSION_STATE eCompression // // Returns: bool // // History: sgasch Created Header 15 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::SetCompressionState(DC210_COMPRESSION_STATE eCompression) { BYTE bCode; // // Precondition: we are initialized. // ASSERT(_fInitialized); switch (eCompression) { case compression_low: bCode = 1; break; case compression_medium: bCode = 2; break; case compression_high: bCode = 3; break; default: Trace("SetCompressionState: bad parameter.\n"); return(false); } // // Send the command to the camera. // if (!SendCommand(DC210_SET_COMPRESSION, bCode, 0, 0, 0)) { Trace("SetCompressionState: Failed to send command.\n"); ASSERT(FALSE); return(false); } // // Wait for the camera's command complete code. // if (!CommandComplete()) { Trace("SetCompressionState: Did not receive command completion " "signal.\n"); ASSERT(FALSE); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: SetZoomState // // Synopsis: // // Arguments: DC210_ZOOM_STATE eZoom // // Returns: bool // // History: sgasch Created Header 15 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::SetZoomState(DC210_ZOOM_STATE eZoom) { BYTE bCode; // // Pre: we are initialized. // ASSERT(_fInitialized); switch (eZoom) { case zoom_fully_zoomed: bCode = 0; break; case zoom_3: bCode = 1; break; case zoom_2: bCode = 2; break; case zoom_1: bCode = 3; break; case zoom_wideangle: bCode = 4; break; case zoom_closeup: bCode = 5; break; default: Trace("SetZoomState: invalid parameter.\n"); return(false); } // // Send the command to the camera. // if (!SendCommand(DC210_SET_ZOOM, bCode, 0, 0, 0)) { Trace("SetZoomState: Failed to send command.\n"); ASSERT(FALSE); return(false); } // // Wait for the camera's command complete code. // if (!CommandComplete()) { Trace("SetZoomState: Did not receive command completion signal.\n"); ASSERT(FALSE); return(false); } // // Success. // return(true); } //+---------------------------------------------------------------------------- // // Function: ToggleShutterDelay // // Synopsis: // // Arguments: BOOL fEnable // // Returns: bool // // History: sgasch Created Header 15 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::ToggleShutterDelay(BOOL fEnable) { BYTE bCode = fEnable; // // Pre: we are initialized. // ASSERT(_fInitialized); // // Send the command to the camera. // if (!SendCommand(DC210_SET_SHUTTER_DELAY, bCode, 0, 0, 0)) { Trace("ToggleShutterDelay: Failed to send command.\n"); ASSERT(FALSE); return(false); } // // Wait for the camera's command complete code. // if (!CommandComplete()) { Trace("ToggleShutterDelay: Did not receive command completion " "signal.\n"); ASSERT(FALSE); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: SetPictureFormat // // Synopsis: // // Arguments: DC210_FILE_FORMAT eFormat // // Returns: bool // // History: sgasch Created Header 15 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::SetPictureFormat(DC210_FILE_FORMAT eFormat) { int iParam = eFormat + 2; // // Send the command // if (!SendCommand(DC210_SET_FORMAT, iParam, 0, 0, 0)) { Trace("SetPictureFormat: unable to send command.\n"); ASSERT(FALSE); return(false); } // // Await reply // if (!CommandComplete()) { Trace("SetPictureFormat: did not receive command complete signal.\n"); ASSERT(FALSE); return(false); } // // Refresh status block // if (!RefreshProperties()) { Trace("SetPictureFormat: Failed to refresh status.\n"); ASSERT(FALSE); return(false); } // // Success // return(true); } bool CKodakDC210::SetExposureCompensationValue(float floatValue) { return(true); } bool CKodakDC210::FormatMemoryCard(void) { return(true); } bool CKodakDC210::SetIdString(char *szId) { return(true); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //+---------------------------------------------------------------------------- // // Function: SendCommand // // Synopsis: Send a command sequence to the camera. // // Arguments: char bCommand // // Returns: bool - true if command sent okay. // // History: sgasch Created Header 4 Jun 1999 // //+---------------------------------------------------------------------------- bool CKodakDC210::SendCommand(int bCommand, BYTE arg1, BYTE arg2, BYTE arg3, BYTE arg4) { BYTE buf[8]; // buffer for building cmd to camera // // Preconditions: the command is valid, we do _not_ assert that we // are initialized 'cause this can be called in the constructor before // we are fully initialized... // ASSERT(bCommand <= 0xFF); ASSERT(bCommand >= 0); // // Fill in the buffer with the command to the camera. // buf[0] = bCommand; buf[1] = 0; buf[2] = arg1; buf[3] = arg2; buf[4] = arg3; buf[5] = arg4; buf[6] = 0; buf[7] = 0x1A; // // Send the command to the port. // if (!_pSerialPort->Write(buf, 8)) { Trace("SendCommand: write error?!?\n"); ASSERT(false); return(false); } // // The camera should acknowledge us, if it got the command... // if (!GetAck()) { Trace("SendCommand: ACK not received from camera.\n" "SendCommand: %x is an illegal command.\n", bCommand); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: GetAck // // Synopsis: Read a command byte from the port and see if it's an ACK. // // Arguments: void // // Returns: bool - true if successful ACK received, false otherwise // // History: sgasch Created Header 4 Jun 1999 // //+---------------------------------------------------------------------------- bool CKodakDC210::GetAck(void) { BYTE buf; // buffer for byte from camera // // The next byte back from the camera is an ACK or a NAK // if (!_pSerialPort->Read(&buf, 1)) { Trace("GetAck: Read error.\n"); ASSERT(false); return(false); } if (DC210_COMMAND_ACK != buf) { printf("GetAck: Received %x, not ACK.\n", buf); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: CommandComplete // // Synopsis: Once we have sent a command string off to the camera and // it has replied with an ACK we have to wait until the camera // tells us that it's done doing the command. The host interface // spec says that if it is bust for more than two seconds it will // send BUSY signals so we know it's still there but working. // // Arguments: void // // Returns: bool - true if successful // // History: sgasch Created Header 8 Jun 1999 // //+---------------------------------------------------------------------------- bool CKodakDC210::CommandComplete(void) { BYTE bStatus; // a byte from the camera // // Get data from the camera and keep doing so while it's "busy"... // do { _pSerialPort->Read(&bStatus, 1); } while(bStatus == DC210_BUSY); // // If it didn't say "complete" then there was an error with the command. // if (DC210_COMMAND_COMPLETE != bStatus) { Trace("CommandComplete: Camera reports error code %x.\n", bStatus); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: ReadPacket // // Synopsis: // // Arguments: BYTE *buf, // int iPacketSize // // Returns: bool // // History: sgasch Created Header 13 Jan 2000 // //+---------------------------------------------------------------------------- bool CKodakDC210::ReadPacket(BYTE *buf, int iPacketSize) { BYTE bControl; // packet control byte from camera BYTE bChecksumFromCamera; // checksum from camera BYTE bChecksumComputed = 0; // checksum we compute from data int iAttempts = 0; // loop termination guarantor // // Preconditions: we are initialized, the packet size is good, and the // pointer is good. // ASSERT(GOOD_PTR(buf)); if ((iPacketSize != 1024) && (iPacketSize != 512) && (iPacketSize != 256) && (iPacketSize != 16)) { Trace("ReadPacket: Invalid packet size.\n"); return(false); } ASSERT(_pSerialPort); // // Loop reading packets until we get one with a checksum match. // do { // // Read the control byte first. // if (!_pSerialPort->Read(&bControl, 1)) { Trace("ReadPacket: Read error?\n"); ASSERT(false); return(false); } // // This byte must always be 0x01, according to the host // interface spec. // if (bControl != DC210_NORMAL_RECEIVE_PACKET) { Trace("ReadPacket: Illegal packet control byte from " "camera? (%x).\n", bControl); return(false); } // // Read the packet data itself. // if (!_pSerialPort->Read(buf, iPacketSize)) { Trace("ReadPacket: Read error?\n"); ASSERT(false); return(false); } // // Read the checksum the camera computed. // if (!_pSerialPort->Read(&bChecksumFromCamera, 1)) { Trace("ReadPacket: Error reading checksum from camera.\n"); ASSERT(false); return(false); } // // Compute the checksum based on the data and compare it to the // one the camera send... does it match? // ComputeChecksum(&bChecksumComputed, buf, iPacketSize); if (bChecksumComputed == bChecksumFromCamera) { // // Yes, it matched -- send "good packet" to the camera. // if (!_pSerialPort->WriteByte(DC210_CORRECT_PACKET)) { Trace("ReadPacket: Could not confirm packet reciept to the " "camera.\n"); ASSERT(false); return(false); } } else { // // No match, garbled packet, request a resend. // if (!_pSerialPort->WriteByte(DC210_ILLEGAL_PACKET)) { Trace("ReadPacket: Could not ask camera for resend.\n"); ASSERT(false); return(false); } } } // // Continue to loop while the packet is bad and we have not yet // reached the upper limit to how many attempts to make. // while ((bChecksumComputed != bChecksumFromCamera) && (++iAttempts < g_iMaxAttempts)); // // If we're here because of too many bad packets, tell the camera to // abort the send. // if (iAttempts >= _iMaxAttempts) { Trace("ReadPacket: Too many illegal packets received, giving up.\n"); if (!_pSerialPort->WriteByte(DC210_ABORT)) { Trace("ReadPacket: Could not abort the communication.\n"); } ASSERT(false); return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: SendPacket // // Synopsis: Send a packet of data to the camera given the packet size, // a control byte, and the data itself. // // Arguments: BYTE bControl - the control byte // BYTE *buf - the data // int iLength - how large is the packet // // Returns: bool - true on success // // History: sgasch Created Header 8 Jun 1999 // //+---------------------------------------------------------------------------- bool CKodakDC210::SendPacket(BYTE bControl, BYTE *buf, int iLength) { int iAttempts = 0; // loop termination guarantor BYTE bConfirm; // confirmation byte from camera BYTE bChecksum; // checksum we compute for packet // // Preconditions: we are initialized, the control byte is valid, the // buf ptr is good, and the length is good. // ASSERT(GOOD_PTR(buf)); if ((iLength != 58) && (iLength != 255)) { Trace("SendPacket: Invalid packet length, aborting.\n"); return(false); } if ((bControl != DC210_NORMAL_PACKET) && (bControl != DC210_FINAL_PACKET) && (bControl != DC210_ABORT_PACKET)) { Trace("SendPacket: Invalid control byte, aborting.\n"); return(false); } ASSERT(_fInitialized); ASSERT(_pSerialPort); // // Loop while the camera didn't get the packet. // do { // // Write the control byte first... this tells the camera if this // is just another packet or the last one. // if (!_pSerialPort->WriteByte(bControl)) { Trace("SendPacket: Error writing control byte, aborting.\n"); ASSERT(false); return(false); } // // Write the packet data. // if (!_pSerialPort->Write(buf, iLength)) { Trace("SendPacket: Write error sending packet, aborting.\n"); ASSERT(false); return(false); } // // Compute and send the checksum. // (void) ComputeChecksum(&bChecksum, buf, iLength); if (!_pSerialPort->WriteByte(bChecksum)) { Trace("SendPacket: Error writing checksum byte, aborting.\n"); ASSERT(false); return(false); } // // Receive acknowledgement or error from camera... this tells us // whether or not we have to resend the packet. // if (!_pSerialPort->Read(&bConfirm, 1)) { Trace("SendPacket: Did not receive an ack from camera?!?\n"); ASSERT(false); return(false); } } // // Continue to loop while the camera wants a resend (due to garbled data // causing mismatched checksums) or until we reach the limit of packet // errors. // while ((bConfirm != DC210_CORRECT_PACKET) && (++iAttempts < _iMaxAttempts)); // // If we're here because of many packet failures, tell the camera we // are aborting the transfer. // if (iAttempts >= g_iMaxAttempts) { Trace("SendPacket: Too many packet errors, aborting " "communications.\n"); if (!(_pSerialPort->WriteByte(DC210_ABORT_PACKET))) { Trace("WritePacket: Could not abort the communication.\n"); } return(false); } // // Success // return(true); } //+---------------------------------------------------------------------------- // // Function: ComputeChecksum // // Synopsis: Compute and return the checksum byte of a packet. This method // is called by ReadPacket to verify the camera's packet integrity // and by SendPacket to send a checksum for the camera to verify. // // Arguments: BYTE *pbChecksum - checksum computed // BYTE *buf - data ptr // int iSize - data length // // Returns: bool - true if successful // // History: sgasch Created Header 8 Jun 1999 // //+---------------------------------------------------------------------------- bool CKodakDC210::ComputeChecksum(BYTE *pbChecksum, BYTE *buf, int iSize) { BYTE bChecksum = *buf; // checksum begin as start byte int iCount = 1; // loop control // // Preconditions: byte ptr must be good, checksum ptr must be good, // size must be good. // ASSERT(GOOD_PTR(pbChecksum)); ASSERT(GOOD_PTR(buf)); if ((iSize <= 0) || (iSize > 10000)) { Trace("ComputeChecksum: illegal packet size.\n"); ASSERT(false); return(false); } // // Compute the checksum by serially XORing the data bytes together. // for (iCount = 1; iCount < iSize; iCount++) { bChecksum ^= *(buf + iCount); } *pbChecksum = bChecksum; // // Success // return(true); }