📄 mca25.c
字号:
/*,-----------------------------------------------------------------------------------------.| io/mca25|-----------------------------------------------------------------------------------------| this file implements the communcation protocol used by sony ericcsons mca25 handy camera| - based on my mca25 code shipped with the rtl8019 webservercode| - enhanced by some ideas from jesper| - mca25 packetsize can be freely configured -> use full ethernet buffer -> faster|| BUGS:| - sometimes the camera hangs during mux7 etc -> but cam is then restartet| - retransfer if there was a lost packet is NOT TESTED !!|| Author : {{removed according to contest rules}}| -> circuitcellar.com avr design contest 2006| -> Entry #AT2616||-----------------------------------------------------------------------------------------| License:| This program is free software; you can redistribute it and/or modify it under| the terms of the GNU General Public License as published by the Free Software| Foundation; either version 2 of the License, or (at your option) any later| version.| This program is distributed in the hope that it will be useful, but|| WITHOUT ANY WARRANTY;|| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR| PURPOSE. See the GNU General Public License for more details.|| You should have received a copy of the GNU General Public License along with| this program; if not, write to the Free Software Foundation, Inc., 51| Franklin St, Fifth Floor, Boston, MA 02110, USA|| http://www.gnu.de/gpl-ger.html`-----------------------------------------------------------------------------------------*/#include "mca25.h"#include "led.h"//ACTIVATE DEBUG by editing this file:#include "debug.h"//start JPG magicPROGMEM char MCA25_START_JPG[] = {0xF9,0x81,0xEF,0x3F,0x83,0x00,0x82,0x71,0x00,0x58,0x3C,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x69,0x6E,0x67,0x2D,0x63,0x6F,0x6D,0x6D,0x61,0x6E,0x64,0x20,0x76,0x65,0x72,0x73,0x69,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x6F,0x6E,0x3D,0x22,0x31,0x2E,0x30,0x22,0x20,0x74,0x61,0x6B,0x65,0x2D,0x70,0x69,0x63,0x3D,0x22,0x4E,0x4F,0x22,0x20,0x73,0x65,0x6E,0x64,0x2D,0x70,0x69,0x78,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x65,0x6C,0x2D,0x73,0x69,0x7A,0x65,0x3D,0x22,0x36,0x34,0x30,0x2A,0x34,0x38,0x30,0x22,0x20,0x7A,0x6F,0x6F,0x6D,0x3D,0x22,0x31,0x30,0x22,0x2F,0x3E,0x42,0x00,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x21,0x78,0x2D,0x62,0x74,0x2F,0x69,0x6D,0x61,0x67,0x69,0x6E,0x67,0x2D,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x69,0x6E,0x67,0x2D,0x69,0x6D,0x61,0x67,0x65,0x00,0x8C,0xF9,0xF9,0x81,0xEF,0x0D,0x4C,0x00,0x06,0x06,0x01,0x80,0x4B,0xF9};//start capturing magicPROGMEM char MCA25_START_CAPTURING[] = {//part 10xF9,0x81,0xEF,0x3F,0x83,0x00,0x69,0x71,0x00,0x3F,0x3C,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x69,0x6E,0x67,0x2D,0x63,0x6F,0x6D,0x6D,0x61,0x6E,0x64,0x20,0x76,0x65,0x72,0x73,0x69,0x8C,0xF9,//part 20xF9,0x81,0xEF,0x3F,0x6F,0x6E,0x3D,0x22,0x31,0x2E,0x30,0x22,0x20,0x74,0x61,0x6B,0x65,0x2D,0x70,0x69,0x63,0x3D,0x22,0x59,0x45,0x53,0x22,0x20,0x7A,0x6F,0x6F,0x6D,0x3D,0x22,0x31,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x30,0x22,0x2F,0x3E,0x42,0x00,0x21,0x78,0x2D,0x62,0x74,0x2F,0x69,0x6D,0x61,0x67,0x69,0x6E,0x67,0x2D,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x69,0x6E,0x67,0x2D,0x8C,0xF9,//part 30xF9,0x81,0xEF,0x19,0x69,0x6D,0x61,0x67,0x65,0x00,0x4C,0x00,0x06,0x06,0x01,0x80,0x50,0xF9};//configure cam magicPROGMEM char MCA25_CONFIG_640x480[] = {0xF9,0x81,0xEF,0x3F,0x82,0x01,0x3B,0x01,0x00,0x03,0x49,0x01,0x35,0x3C,0x63,0x61,0x6D,0x65,0x72,0x61,0x2D,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x76,0x65,0x72,0x73,0x69,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x6F,0x6E,0x3D,0x22,0x31,0x2E,0x30,0x22,0x20,0x77,0x68,0x69,0x74,0x65,0x2D,0x62,0x61,0x6C,0x61,0x6E,0x63,0x65,0x3D,0x22,0x4F,0x46,0x46,0x22,0x20,0x63,0x6F,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x6C,0x6F,0x72,0x2D,0x63,0x6F,0x6D,0x70,0x65,0x6E,0x73,0x61,0x74,0x69,0x6F,0x6E,0x3D,0x22,0x31,0x33,0x22,0x20,0x66,0x75,0x6E,0x2D,0x6C,0x61,0x79,0x65,0x72,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x3D,0x22,0x30,0x22,0x3E,0x3C,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x69,0x6E,0x67,0x2D,0x66,0x6F,0x72,0x6D,0x61,0x74,0x20,0x65,0x6E,0x63,0x6F,0x64,0x69,0x6E,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x67,0x3D,0x22,0x45,0x42,0x4D,0x50,0x22,0x20,0x70,0x69,0x78,0x65,0x6C,0x2D,0x73,0x69,0x7A,0x65,0x3D,0x22,0x38,0x30,0x2A,0x36,0x30,0x22,0x20,0x63,0x6F,0x6C,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x6F,0x72,0x2D,0x64,0x65,0x70,0x74,0x68,0x3D,0x22,0x38,0x22,0x2F,0x3E,0x0D,0x0A,0x3C,0x74,0x68,0x75,0x6D,0x62,0x6E,0x61,0x69,0x6C,0x2D,0x66,0x6F,0x72,0x6D,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x61,0x74,0x20,0x65,0x6E,0x63,0x6F,0x64,0x69,0x6E,0x67,0x3D,0x22,0x45,0x42,0x4D,0x50,0x22,0x20,0x70,0x69,0x78,0x65,0x6C,0x2D,0x73,0x69,0x7A,0x65,0x3D,0x22,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x31,0x30,0x31,0x2A,0x38,0x30,0x22,0x20,0x63,0x6F,0x6C,0x6F,0x72,0x2D,0x64,0x65,0x70,0x74,0x68,0x3D,0x22,0x38,0x22,0x2F,0x3E,0x0D,0x0A,0x3C,0x6E,0x61,0x74,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x69,0x76,0x65,0x2D,0x66,0x6F,0x72,0x6D,0x61,0x74,0x20,0x65,0x6E,0x63,0x6F,0x64,0x69,0x6E,0x67,0x3D,0x22,0x22,0x20,0x70,0x69,0x78,0x65,0x6C,0x2D,0x73,0x69,0x8C,0xF9,0xF9,0x81,0xEF,0x3F,0x7A,0x65,0x3D,0x22,0x36,0x34,0x30,0x2A,0x34,0x38,0x30,0x22,0x2F,0x3E,0x0D,0x0A,0x3C,0x2F,0x63,0x61,0x6D,0x65,0x72,0x61,0x2D,0x73,0x65,0x74,0x74,0x69,0x6E,0x8C,0xF9,0xF9,0x81,0xEF,0x0B,0x67,0x73,0x3E,0x0D,0x0A,0xAF,0xF9};//global varsunsigned char mca25_pic_state;unsigned char mca25_allocated_for_socket;unsigned char mca25_allocated_timeout;unsigned char mca25_buffer[MCA25_COMM_BUFFER_LEN];unsigned char mca25_ready;unsigned char mca25_mux_buffer[6];unsigned long mca25_datapos;unsigned char mca25_jpg_state;unsigned char mca25_is_rev017;#if 0unsigned char mca25_brightness;//estimate picture brightness, might be used to switch led light only if necessaryvoid mca25_estimate_brightness(unsigned char val){ //pixel is rgb332, we use rgb222 only! unsigned char tmp = (((val&0xC0)>>6) + ((val&0x18)>>3) + (val&0x3)); mca25_brightness += tmp;}#endif//send data ackvoid mca25_send_data_ack(void){ mca25_puts_progmem("\xF9\x81\xEF\x07\x83\x00\x03\xA6\xF9");}//handle channel 0x23 datavoid mca25_handle_channel_x23(void){ if (mca25_mux_buffer[1] == 0xEF){ //UIH if (string_compare_progmem_plen("AT*ECUR=", mca25_buffer)){ //ack current request packets: // -> send mux "\r\nOK\r\n" packet: mca25_puts_progmem("\xF9\x21\xEF\x0D\x0D\x0A\x4F\x4B\x0D\x0A\x48\xF9"); }else{ #if MCA25_DEBUG softuart_putc('u'); #endif } }else if (mca25_mux_buffer[1] == 0x3F){ //SABM mca25_puts_progmem("\xF9\x23\x73\x01\x02\xF9"); }}//handle channel 0x03 datavoid mca25_handle_channel_x03(void){ if (mca25_mux_buffer[1] == 0xEF){ //UIH if (string_compare_progmem_plen("\xE1\x07\x23\x0C\x01", mca25_buffer)){ mca25_puts_progmem("\xF9\x01\xEF\x0B\xE3\x07\x23\x0C\x01\x79\xF9"); }else{ #if MCA25_DEBUG softuart_putc('v'); #endif } }else if (mca25_mux_buffer[1] == 0x3F){ //SABM mca25_puts_progmem("\xF9\x03\x73\x01\xD7\xF9"); }}//cleanup dead connection -> run this every second !void mca25_cleanup(void){ if (mca25_pic_state != MCA25_PIC_STATE_IDLE){ if (mca25_allocated_timeout == 0){ #if MCA25_DEBUG softuart_puts_progmem("CAM : allocation to socket "); softuart_put_uint8(mca25_allocated_for_socket); softuart_puts_progmem(" removed"); softuart_putnewline(); #endif mca25_pic_state = MCA25_PIC_STATE_IDLE; }else{ mca25_allocated_timeout--; } }}//grab jpg data & store in bufferunsigned int mca25_grab_data(char *buffer, unsigned int datalen, unsigned long pos, unsigned char socketnum){ int skip_count=0; unsigned char state=0; mca25_allocated_timeout = 5; //5sec timeout //cam is used by another user -> abort if ((mca25_pic_state != MCA25_PIC_STATE_IDLE) && (mca25_allocated_for_socket != socketnum)){ return 0xFFFE; } //cam is no longer working -> reset ! if ((mca25_pic_state == MCA25_PIC_STATE_CAM_ERROR) || (mca25_ready == 0)){ //cam not initialised or missing! #if MCA25_DEBUG softuart_puts_progmem("CAM : grab -> cam error -> retry init!"); softuart_putnewline(); #endif mca25_init_cam(); mca25_configure(); //return 0xFFFF; //-> abort this image ! } //we need to do a preview image: if (mca25_pic_state == MCA25_PIC_STATE_IDLE){ mca25_start_image_grab(socketnum); } #if 1 softuart_puts_progmem("CAM : req byte "); softuart_put_uint16(pos); softuart_puts_progmem(" cur pos is: "); softuart_put_uint16(mca25_datapos); softuart_putnewline(); //tcp stack requested data bytes we do no longer have... //hack: dont touch ethernetbuffer & hope that data is still available. // if buffer was used during last transfer -> picture will have errors... if (pos<mca25_datapos){ int adjust = (mca25_datapos-pos)-512; if (adjust == 0){ //perfect return 512; }else if(adjust > 0){ //we must shift the data: for(unsigned int a=0; a<512; a++){ if (a+adjust <= 512) buffer[a] = buffer[a+adjust]; } return adjust; //#adjusted bytes data }else{ //>512 bytes of data seems to be lost -> no way to fix it... //-> dont touch the buffer, maybe we can use the data later ... return (adjust%512); } }else if(pos>mca25_datapos){ //?! how could that happen ? //FIXME: //1) ignore the missing data & continue //2) skip camera data until we have the requestet data packet... //-> use (1), change to 2 later ?! }#endif #if MCA25_DEBUG /*softuart_puts_progmem("CAM : grab data starting at byte "); softuart_put_uint16(pos>>16); softuart_put_uint16(pos&0xFFFF); softuart_puts_progmem(", current pos is "); softuart_put_uint16(mca25_datapos>>16); softuart_put_uint16(mca25_datapos&0xFFFF); softuart_putnewline();*/ #endif unsigned int dcnt=0; unsigned int res=0; unsigned int bufpos=0; //we have received data -> send an ack ! if ((mca25_pic_state == MCA25_PIC_STATE_JPG_DATA) || (mca25_pic_state == MCA25_PIC_STATE_LAST_DATA)){ mca25_send_data_ack(); } //do the statemachine while (state != 100){ if (state == 0) res = mca25_read_mux_packet(&buffer[bufpos],6); else res = mca25_read_mux_packet(&buffer[bufpos],0); if (res == 0){ #if MCA25_DEBUG softuart_puts_progmem("TIMEOUT! (MUX J)"); softuart_putnewline(); softuart_puts_progmem("dcount="); softuart_put_uint16(dcnt); softuart_putnewline(); #endif //cam error, disable ! mca25_ready = 0; return 0xFFFF; //read failed -> exit!; } if (bufpos>datalen){ #if MCA25_DEBUG softuart_puts_progmem("CAM : buf overflow! "); softuart_put_uint16(skip_count); softuart_put_uint16(bufpos); softuart_putnewline(); #endif return 0xFFFF; } //new version, thanks to jesper ;) //softuart_put_uint8(mca25_buffer[1]); if ((mca25_mux_buffer[0] == 0x83) && (mca25_mux_buffer[1] == 0xEF) ){ //data channel & UIH packet dcnt++; switch (state){ case 0: //check how many bytes cam want to send skip_count = ((int)mca25_mux_buffer[4]<<8) + mca25_mux_buffer[5]; if (skip_count > datalen){ skip_count = datalen; } if (skip_count > 3){ //only handle data packets -> ignore packets smaller 3 bytes (=acks) skip_count -= ((mca25_mux_buffer[2])>>1); bufpos += (mca25_mux_buffer[2]>>1)-6; //last data packet ?! if (mca25_mux_buffer[3] == 0xA0){ mca25_pic_state = MCA25_PIC_STATE_LAST_DATA; //no more data }else{ mca25_pic_state = MCA25_PIC_STATE_JPG_DATA; //middle of pic } state = 1; if (skip_count <= 0){ //softuart_putc('.'); if (mca25_pic_state == MCA25_PIC_STATE_LAST_DATA){ mca25_send_data_ack(); //reconfigure mux channel (?!) mca25_puts_progmem("\xF9\x01\xEF\x0B\xE3\x07\x23\x0C\x01\x79\xF9"); mca25_pic_state = MCA25_PIC_STATE_IDLE; mca25_datapos += bufpos; return bufpos; }else{ mca25_datapos += bufpos; return 0; } } } break; case 2: case 1: skip_count -= ((mca25_mux_buffer[2])>>1); bufpos += (mca25_mux_buffer[2]>>1)-0; if (skip_count <= 0){ //softuart_putc('.'); if (mca25_pic_state == MCA25_PIC_STATE_LAST_DATA){ mca25_send_data_ack(); //reconfigure mux channel (?!) mca25_puts_progmem("\xF9\x01\xEF\x0B\xE3\x07\x23\x0C\x01\x79\xF9"); mca25_pic_state = MCA25_PIC_STATE_IDLE; mca25_datapos += bufpos; return bufpos; //last data packet ! }else{ mca25_datapos += bufpos; return 0; //state = 100; } } break; default: break; } //case //softuart_put_uint16(skip_count); }else if (mca25_mux_buffer[0] == 0x23){ //channel 0x23 mca25_handle_channel_x23(); }else if (mca25_mux_buffer[0] == 0x03){ //channel 0x03 mca25_handle_channel_x03(); }else{ /*for(unsigned char f=0; f<40; f++){ softuart_put_uint8(f); softuart_putc('>'); softuart_put_uint8(mca25_buffer[f]); softuart_putnewline(); }softuart_putnewline();softuart_putnewline();*/ } } //softuart_puts_progmem("count="); //softuart_put_uint16(dcnt); //preview image #i has been grabbed. #if MCA25_DEBUG softuart_putc(' '); #endif return 0xFFFF;}//start image grab, grab preview pictures and send jpg requestunsigned char mca25_start_image_grab(unsigned char socketnum){ unsigned char state; unsigned char datapos; int skip_count=0; //switch light on (slow fade in !) //mpf10_fade(MPF10_FADE_IN); //without soft fade in: MPF10_ENABLE(); //reset global data byte counter mca25_datapos = 0; //allocate cam to current socket mca25_allocated_for_socket = socketnum; //reset state mca25_pic_state = MCA25_PIC_STATE_IDLE; //not ready if (mca25_ready == 0){ //cam not initialised or missing! #if MCA25_DEBUG softuart_puts_progmem("CAM : cam not initialised or missing -> abort."); softuart_putnewline(); #endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -