2 *----------------------------------------------------------------------------
3 * Sonixcam Tool for Poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include <proto/dos.h>
11 #include <proto/exec.h>
12 #include <proto/poseidon.h>
13 #include <proto/intuition.h>
14 #include <proto/graphics.h>
15 #include <proto/diskfont.h>
17 #include "SonixcamTool.h"
23 #define ARGS_INTERVAL 1
26 #define ARGS_SHARPEN 4
29 #define ARGS_FONTSIZE 7
33 const char SonixcamTool_prgname
[] = "SonixcamTool";
34 static const char *template = "TO/A,INTERVAL/N,UPTO/N/K,GAMMA/K,SHARPEN/S,TEXT/K,FONT/K,FONTSIZE/N/K,UNIT/N/K";
35 const char SonixcamTool_version
[] = "$VER: SonixcamTool 1.3 (12.06.09) by Chris Hodges <chrisly@platon42.de>";
36 static IPTR ArgsArray
[ARGS_SIZEOF
];
37 static struct RDArgs
*ArgsHook
= NULL
;
39 static UWORD gammaredtab
[256];
40 static UWORD gammagreentab
[256];
41 static UWORD gammabluetab
[256];
43 struct RastPort fontrp
;
44 struct RastPort picrp
;
45 struct TextAttr avenirta
;
46 struct TextFont
*avenirfont
= NULL
;
47 struct BitMap
*fontbm
= NULL
;
48 ULONG tlength
, theight
;
52 AROS_UFP3(void, releasehook
,
53 AROS_UFPA(struct Hook
*, hook
, A0
),
54 AROS_UFPA(APTR
, pab
, A2
),
55 AROS_UFPA(struct NepClassSonixcam
*, nch
, A1
));
57 AROS_UFP3(void, nInReqHook
,
58 AROS_UFPA(struct Hook
*, hook
, A0
),
59 AROS_UFPA(struct IOUsbHWRTIso
*, urti
, A2
),
60 AROS_UFPA(struct IOUsbHWBufferReq
*, ubr
, A1
));
62 AROS_UFP3(void, nInDoneHook
,
63 AROS_UFPA(struct Hook
*, hook
, A0
),
64 AROS_UFPA(struct IOUsbHWRTIso
*, urti
, A2
),
65 AROS_UFPA(struct IOUsbHWBufferReq
*, ubr
, A1
));
67 struct NepClassSonixcam
* SetupSonixcam(void);
68 struct NepClassSonixcam
* AllocSonixcam(struct NepClassSonixcam
*nch
);
69 void FreeSonixcam(struct NepClassSonixcam
*nch
);
74 void CreateGammaTab(void)
77 UWORD red
, green
, blue
;
80 if(!ArgsArray
[ARGS_GAMMA
])
84 gamma
= atof((char *) ArgsArray
[ARGS_GAMMA
]);
85 gammaredtab
[0] = gammagreentab
[0] = gammabluetab
[0] = 0;
94 y
= pow((x
/256.0), gamma
)*255.0;
95 red
= (UWORD
) (y
*1.08);
97 blue
= (UWORD
) (y
*0.95);
98 gammaredtab
[i
] = red
< 256 ? red
: 255;
99 gammagreentab
[i
] = green
;
100 gammabluetab
[i
] = blue
;
104 AROS_UFH3(void, releasehook
,
105 AROS_UFHA(struct Hook
*, hook
, A0
),
106 AROS_UFHA(APTR
, pab
, A2
),
107 AROS_UFHA(struct NepClassSonixcam
*, nch
, A1
))
110 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) prgname,
111 "Sonixcam killed!");*/
112 Signal(nch
->nch_Task
, SIGBREAKF_CTRL_C
);
116 AROS_UFH3(void, nInReqHook
,
117 AROS_UFHA(struct Hook
*, hook
, A0
),
118 AROS_UFHA(struct IOUsbHWRTIso
*, urti
, A2
),
119 AROS_UFHA(struct IOUsbHWBufferReq
*, ubr
, A1
))
123 struct NepClassSonixcam
*nch
= (struct NepClassSonixcam
*) hook
->h_Data
;
125 ubr
->ubr_Buffer
= (UBYTE
*) &nch
->nch_CurrIsoBuf
[nch
->nch_IsoBufPos
];
126 if(ubr
->ubr_Length
+ nch
->nch_IsoBufPos
> nch
->nch_RawBufSize
)
134 AROS_UFH3(void, nInDoneHook
,
135 AROS_UFHA(struct Hook
*, hook
, A0
),
136 AROS_UFHA(struct IOUsbHWRTIso
*, urti
, A2
),
137 AROS_UFHA(struct IOUsbHWBufferReq
*, ubr
, A1
))
141 struct NepClassSonixcam
*nch
= (struct NepClassSonixcam
*) hook
->h_Data
;
143 UBYTE
*bufptr
= &nch
->nch_CurrIsoBuf
[nch
->nch_IsoBufPos
];
144 //KPRINTF(10, ("%ld\n", ubr->ubr_Length));
148 if(nch
->nch_IsoBufPos
> nch
->nch_HeaderSize
)
150 if(nch
->nch_IsoBufPos
== 320*240+nch
->nch_HeaderSize
)
153 nch
->nch_LastDoneNum
= nch
->nch_IsoBufNum
;
154 nch
->nch_BufState
[nch
->nch_IsoBufNum
] = BUF_READY
;
155 Signal(nch
->nch_Task
, 1UL<<nch
->nch_ImgDoneSig
);
156 if(++nch
->nch_IsoBufNum
== 3)
158 nch
->nch_IsoBufNum
= 0;
160 if(nch
->nch_BufState
[nch
->nch_IsoBufNum
] == BUF_BUSY
)
162 if(++nch
->nch_IsoBufNum
== 3)
164 nch
->nch_IsoBufNum
= 0;
167 KPRINTF(10, ("Next Img: %ld\n", nch
->nch_IsoBufNum
));
168 nch
->nch_CurrIsoBuf
= nch
->nch_RawBuf
[nch
->nch_IsoBufNum
];
170 KPRINTF(10, ("Restart at %ld/%ld\n", nch
->nch_IsoBufPos
, nch
->nch_FrameCnt
));
172 nch
->nch_IsoBufPos
= 0;
176 if(nch
->nch_IsoBufPos
)
178 nch
->nch_IsoBufPos
+= ubr
->ubr_Length
;
180 if((*((ULONG
*) bufptr
) == 0xffff00c4) && (*((UWORD
*) &bufptr
[4]) == 0xc496))
182 //KPRINTF(10, ("Started!\n"));
183 nch
->nch_IsoBufPos
+= ubr
->ubr_Length
;
184 nch
->nch_FrameCnt
= 0;
191 BOOL
WriteReg(struct NepClassSonixcam
*nch
, ULONG index
, ULONG value
)
196 //Printf("Writing register 0x%02lx with value 0x%02lx\n", index, value);
197 psdPipeSetup(nch
->nch_EP0Pipe
, URTF_OUT
|URTF_VENDOR
|URTF_INTERFACE
,
198 CMDID_WRITE_REG
, index
, nch
->nch_IfNum
);
199 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, &buf
, 1);
202 Printf("Error writing register 0x%02lx with value 0x%02lx, errorcode=%ld\n", index
, value
, ioerr
);
205 nch
->nch_Reg
[index
& 0xff] = value
;
209 BOOL
WriteRegs(struct NepClassSonixcam
*nch
, ULONG index
, ULONG len
, UBYTE
*buf
)
214 //Printf("Writing registers 0x%02lx with value 0x%02lx\n", index, *buf);
215 psdPipeSetup(nch
->nch_EP0Pipe
, URTF_OUT
|URTF_VENDOR
|URTF_INTERFACE
,
216 CMDID_WRITE_REG
, index
, nch
->nch_IfNum
);
217 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, buf
, len
);
220 Printf("Error writing registers 0x%02lx - 0x%02lx, errorcode=%ld\n", index
, index
+len
-1, ioerr
);
223 for(cnt
= 0; cnt
< len
; cnt
++)
225 nch
->nch_Reg
[(index
+ cnt
) & 0xff] = buf
[cnt
];
230 ULONG
ReadReg(struct NepClassSonixcam
*nch
, ULONG index
)
235 //Printf("Reading register 0x%02lx\n", index);
236 psdPipeSetup(nch
->nch_EP0Pipe
, URTF_IN
|URTF_VENDOR
|URTF_INTERFACE
,
237 CMDID_READ_REG
, index
, nch
->nch_IfNum
);
238 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, &buf
, 1);
241 Printf("Error reading register 0x%02lx, errorcode=%ld\n", index
, ioerr
);
247 BOOL
WaitI2C(struct NepClassSonixcam
*nch
, BOOL read
)
251 UBYTE cmpval
= read
? 0x04 : 0x0c;
255 reg
= ReadReg(nch
, SXREG_I2C_CTRL
);
260 if((reg
& 0x0c) == cmpval
)
262 Printf("%s I2C error %02lx\n", read
? "Read" : "Write", reg
);
271 PutStr("I2C timeout\n");
275 BOOL
WriteI2C_Raw(struct NepClassSonixcam
*nch
, UBYTE
*cmd
)
279 /*Printf("Writing RAW I2C: %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx\n",
280 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]);*/
282 psdPipeSetup(nch
->nch_EP0Pipe
, URTF_OUT
|URTF_VENDOR
|URTF_INTERFACE
,
283 CMDID_WRITE_REG
, SXREG_I2C_CTRL
, nch
->nch_IfNum
);
284 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, cmd
, 8);
287 Printf("Error writing I2C Reg 0x%2lx with value 0x%02lx, errorcode=%ld\n", cmd
[2], cmd
[3], ioerr
);
290 res
= WaitI2C(nch
, FALSE
);
293 Printf("Error writing I2C Reg 0x%2lx with value 0x%02lx during wait\n", cmd
[2], cmd
[3]);
298 BOOL
WriteI2C(struct NepClassSonixcam
*nch
, ULONG index
, ULONG value
)
303 cmd
[1] = nch
->nch_I2CAddr
;
310 return(WriteI2C_Raw(nch
, cmd
));
313 ULONG
ReadI2C(struct NepClassSonixcam
*nch
, ULONG index
)
319 cmd
[1] = nch
->nch_I2CAddr
;
326 psdPipeSetup(nch
->nch_EP0Pipe
, URTF_OUT
|URTF_VENDOR
|URTF_INTERFACE
,
327 CMDID_WRITE_REG
, SXREG_I2C_CTRL
, nch
->nch_IfNum
);
328 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, cmd
, 8);
331 Printf("Error reading I2C Reg 0x%2lx (phase 1), errorcode=%ld\n", index
, ioerr
);
334 if(!WaitI2C(nch
, FALSE
))
340 psdPipeSetup(nch
->nch_EP0Pipe
, URTF_OUT
|URTF_VENDOR
|URTF_INTERFACE
,
341 CMDID_WRITE_REG
, SXREG_I2C_CTRL
, nch
->nch_IfNum
);
342 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, cmd
, 8);
345 Printf("Error reading I2C Reg 0x%2lx (phase 2), errorcode=%ld\n", index
, ioerr
);
349 if(!WaitI2C(nch
, TRUE
))
354 psdPipeSetup(nch
->nch_EP0Pipe
, URTF_IN
|URTF_VENDOR
|URTF_INTERFACE
,
355 CMDID_READ_REG
, SXREG_I2C_CTRL
, nch
->nch_IfNum
);
356 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, cmd
, 8);
359 Printf("Error reading I2C Regs 0x%2lx (phase 3), errorcode=%ld\n", index
, ioerr
);
362 /*Printf("%02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx\n",
363 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]);*/
369 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
370 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x02, 0x03, 0x0a, 0x28, 0x1e, 0x68, 0xC9, 0x20, 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
372 //0x00, 0x00, 0x02, 0x03, 0x0a, 0x28, 0x1e, 0x68, 0xc9, 0x50, 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
373 //shift one pixel 0x02 is 0x01 at start
376 UBYTE ov7630_sensor_init
[] =
378 0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10,
379 0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10,
380 0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10,
381 0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10,
382 0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10,
383 0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10,
384 0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10,
385 0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10,
386 0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10,
387 0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10,
388 0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10,
389 0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10,
390 0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10,
391 0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10,
392 0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10,
393 0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10,
394 0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10, //
395 0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16, // exposure
396 0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16,
397 0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16,
398 0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15, //gain
399 //0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d,//a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630
400 0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x10,
404 BOOL
SenseOV7631(struct NepClassSonixcam
*nch
)
407 UBYTE
*regs
= initOv7630
;
408 UBYTE
*sensinit
= ov7630_sensor_init
;
410 WriteReg(nch
, SXREG_CTRL
, 0x01); // reset
411 WriteReg(nch
, SXREG_CTRL
, 0x00); // release reset
412 WriteReg(nch
, SXREG_VID_CTRL_1
, 0x28); // init
414 nch
->nch_I2CAddr
= 0x21;
416 pid
= (ReadI2C(nch
, 0x0a)<<8)|ReadI2C(nch
, 0x0b);
422 WriteReg(nch
, 0x14, 0x00);
423 WriteReg(nch
, SXREG_VID_CTRL_1
, 0x60);
424 WriteReg(nch
, SXREG_VID_CTRL_2
, 0x0f);
425 WriteReg(nch
, SXREG_VID_CTRL_3
, 0x50); // uncompressed, compressed 0x20
427 WriteReg(nch
, SXREG_WINDOW_LEFT
, 1);
428 WriteReg(nch
, SXREG_WINDOW_TOP
, 1);
429 WriteReg(nch
, SXREG_WINDOW_WIDTH
, 640>>4);
430 WriteReg(nch
, SXREG_WINDOW_HEIGHT
, 480>>4);
432 WriteI2C(nch
, 0x12, 0x8d);
433 WriteI2C(nch
, 0x12, 0x0d);
434 WriteI2C(nch
, 0x11, 0x00);
435 WriteI2C(nch
, 0x15, 0x35);
436 WriteI2C(nch
, 0x16, 0x03);
437 WriteI2C(nch
, 0x17, 0x1c);
438 WriteI2C(nch
, 0x18, 0xbd);
439 WriteI2C(nch
, 0x19, 0x06);
440 WriteI2C(nch
, 0x1a, 0xf6);
441 WriteI2C(nch
, 0x1b, 0x04);
442 WriteI2C(nch
, 0x20, 0x44);
443 WriteI2C(nch
, 0x23, 0xee);
444 WriteI2C(nch
, 0x26, 0xa0);
445 WriteI2C(nch
, 0x27, 0x9a);
446 WriteI2C(nch
, 0x28, 0x20);
447 WriteI2C(nch
, 0x29, 0x30);
448 WriteI2C(nch
, 0x2f, 0x3d);
449 WriteI2C(nch
, 0x30, 0x24);
450 WriteI2C(nch
, 0x32, 0x86);
451 WriteI2C(nch
, 0x60, 0xa9);
452 WriteI2C(nch
, 0x61, 0x42);
453 WriteI2C(nch
, 0x65, 0x00);
454 WriteI2C(nch
, 0x69, 0x38);
455 WriteI2C(nch
, 0x6f, 0x88);
456 WriteI2C(nch
, 0x70, 0x0b);
457 WriteI2C(nch
, 0x71, 0x00);
458 WriteI2C(nch
, 0x74, 0x21);
459 WriteI2C(nch
, 0x7d, 0xf7);
461 WriteReg(nch
, SXREG_CTRL
, (ULONG
) nch
->nch_Reg
[SXREG_CTRL
]|0x04);
463 WriteReg(nch
, SXREG_CTRL
, (ULONG
) regs
[SXREG_CTRL
]);
464 WriteReg(nch
, SXREG_VID_CTRL_1
, (ULONG
) regs
[SXREG_VID_CTRL_1
]);
465 WriteRegs(nch
, SXREG_CTRL
, 0x1f, ®s
[SXREG_CTRL
]);
469 WriteI2C_Raw(nch
, sensinit
);
473 WriteReg(nch
, SXREG_WINDOW_LEFT
, 2);
474 WriteReg(nch
, SXREG_WINDOW_TOP
, 3);
475 WriteReg(nch
, SXREG_WINDOW_WIDTH
, 640>>4);
476 WriteReg(nch
, SXREG_WINDOW_HEIGHT
, 480>>4);
477 WriteReg(nch
, SXREG_VID_CTRL_1
, 0x28);
478 WriteReg(nch
, SXREG_VID_CTRL_2
, 0x1F);
479 WriteReg(nch
, SXREG_VID_CTRL_3
, 0x50); // 0x33
484 BOOL
SenseOV7648(struct NepClassSonixcam
*nch
)
487 UBYTE
*regs
= initOv7630
;
488 UBYTE
*sensinit
= ov7630_sensor_init
;
490 WriteReg(nch
, SXREG_CTRL
, 0x01); // reset
491 WriteReg(nch
, SXREG_CTRL
, 0x00); // release reset
492 WriteReg(nch
, SXREG_VID_CTRL_1
, 0x28); // init
494 nch
->nch_I2CAddr
= 0x21;
496 pid
= (ReadI2C(nch
, 0x0a)<<8)|ReadI2C(nch
, 0x0b);
501 WriteReg(nch
, SXREG_CTRL
, (ULONG
) regs
[SXREG_CTRL
]);
502 WriteReg(nch
, SXREG_VID_CTRL_1
, (ULONG
) regs
[SXREG_VID_CTRL_1
]);
503 WriteRegs(nch
, SXREG_CTRL
, 0x1f, ®s
[SXREG_CTRL
]);
507 WriteI2C_Raw(nch
, sensinit
);
511 WriteReg(nch
, SXREG_WINDOW_LEFT
, 2);
512 WriteReg(nch
, SXREG_WINDOW_TOP
, 3);
513 WriteReg(nch
, SXREG_WINDOW_WIDTH
, 640>>4);
514 WriteReg(nch
, SXREG_WINDOW_HEIGHT
, 480>>4);
515 WriteReg(nch
, SXREG_VID_CTRL_1
, 0x28);
516 WriteReg(nch
, SXREG_VID_CTRL_2
, 0x1F);
517 WriteReg(nch
, SXREG_VID_CTRL_3
, 0x50); // 0x33
521 BOOL
SenseHV7131R(struct NepClassSonixcam
*nch
)
526 WriteReg(nch
, SXREG_CTRL
, 0x01); // reset
527 WriteReg(nch
, SXREG_CTRL
, 0x00); // release reset
528 WriteReg(nch
, SXREG_VID_CTRL_1
, 0x28); // init
530 //nch->nch_I2CAddr = 0x11;
531 nch
->nch_I2CAddr
= 0x5d;
533 val0
= ReadI2C(nch
, 0x00);
534 val1
= ReadI2C(nch
, 0x01);
535 Printf("PID=0x%02lx, Version=0x%02lx\n", val0
, val1
);
546 struct AutoBindData CamBinds
[] =
548 { 0x0c45, 0x6001, BRIDGE_SN9C102
},
549 { 0x0c45, 0x6005, BRIDGE_SN9C102
},
550 { 0x0c45, 0x6007, BRIDGE_SN9C102
},
551 { 0x0c45, 0x6009, BRIDGE_SN9C102
},
552 { 0x0c45, 0x6011, BRIDGE_SN9C102
},
553 { 0x0c45, 0x600d, BRIDGE_SN9C102
},
554 { 0x0c45, 0x6019, BRIDGE_SN9C102
},
555 { 0x0c45, 0x6024, BRIDGE_SN9C102
},
556 { 0x0c45, 0x6025, BRIDGE_SN9C102
},
557 { 0x0c45, 0x6028, BRIDGE_SN9C102
},
558 { 0x0c45, 0x6029, BRIDGE_SN9C102
},
559 { 0x0c45, 0x602a, BRIDGE_SN9C102
},
560 { 0x0c45, 0x602b, BRIDGE_SN9C102
},
561 { 0x0c45, 0x602c, BRIDGE_SN9C102
},
562 { 0x0c45, 0x602d, BRIDGE_SN9C102
},
563 { 0x0c45, 0x602e, BRIDGE_SN9C102
},
564 { 0x0c45, 0x6030, BRIDGE_SN9C102
},
565 { 0x0c45, 0x603f, BRIDGE_SN9C102
},
567 { 0x0c45, 0x6080, BRIDGE_SN9C103
},
568 { 0x0c45, 0x6082, BRIDGE_SN9C103
},
569 { 0x0c45, 0x6083, BRIDGE_SN9C103
},
570 { 0x0c45, 0x6088, BRIDGE_SN9C103
},
571 { 0x0c45, 0x608a, BRIDGE_SN9C103
},
572 { 0x0c45, 0x608b, BRIDGE_SN9C103
},
573 { 0x0c45, 0x608c, BRIDGE_SN9C103
},
574 { 0x0c45, 0x608e, BRIDGE_SN9C103
},
575 { 0x0c45, 0x608f, BRIDGE_SN9C103
},
576 { 0x0c45, 0x60a0, BRIDGE_SN9C103
},
577 { 0x0c45, 0x60a2, BRIDGE_SN9C103
},
578 { 0x0c45, 0x60a3, BRIDGE_SN9C103
},
579 { 0x0c45, 0x60a8, BRIDGE_SN9C103
},
580 { 0x0c45, 0x60aa, BRIDGE_SN9C103
},
581 { 0x0c45, 0x60ab, BRIDGE_SN9C103
},
582 { 0x0c45, 0x60ac, BRIDGE_SN9C103
},
583 { 0x0c45, 0x60ae, BRIDGE_SN9C103
},
584 { 0x0c45, 0x60af, BRIDGE_SN9C103
},
585 { 0x0c45, 0x60b0, BRIDGE_SN9C103
},
586 { 0x0c45, 0x60b2, BRIDGE_SN9C103
},
587 { 0x0c45, 0x60b3, BRIDGE_SN9C103
},
588 { 0x0c45, 0x60b8, BRIDGE_SN9C103
},
589 { 0x0c45, 0x60ba, BRIDGE_SN9C103
},
590 { 0x0c45, 0x60bb, BRIDGE_SN9C103
},
591 { 0x0c45, 0x60bc, BRIDGE_SN9C103
},
592 { 0x0c45, 0x60be, BRIDGE_SN9C103
},
594 { 0x045e, 0x00f5, BRIDGE_SN9C105
},
595 { 0x045e, 0x00f7, BRIDGE_SN9C105
},
596 { 0x0471, 0x0327, BRIDGE_SN9C105
},
597 { 0x0471, 0x0328, BRIDGE_SN9C105
},
598 { 0x0c45, 0x60c0, BRIDGE_SN9C105
},
599 { 0x0c45, 0x60c2, BRIDGE_SN9C105
},
600 { 0x0c45, 0x60c8, BRIDGE_SN9C105
},
601 { 0x0c45, 0x60cc, BRIDGE_SN9C105
},
602 { 0x0c45, 0x60ea, BRIDGE_SN9C105
},
603 { 0x0c45, 0x60ec, BRIDGE_SN9C105
},
604 { 0x0c45, 0x60ef, BRIDGE_SN9C105
},
605 { 0x0c45, 0x60fa, BRIDGE_SN9C105
},
606 { 0x0c45, 0x60fb, BRIDGE_SN9C105
},
607 { 0x0c45, 0x60fc, BRIDGE_SN9C105
},
608 { 0x0c45, 0x60fe, BRIDGE_SN9C105
},
610 { 0x0458, 0x7025, BRIDGE_SN9C120
},
611 { 0x0458, 0x7034, BRIDGE_SN9C120
},
612 { 0x0c45, 0x6102, BRIDGE_SN9C120
},
613 { 0x0c45, 0x6108, BRIDGE_SN9C120
},
614 { 0x0c45, 0x610f, BRIDGE_SN9C120
},
615 { 0x0c45, 0x6130, BRIDGE_SN9C120
},
616 { 0x0c45, 0x6138, BRIDGE_SN9C120
},
617 { 0x0c45, 0x613a, BRIDGE_SN9C120
},
618 { 0x0c45, 0x613b, BRIDGE_SN9C120
},
619 { 0x0c45, 0x613c, BRIDGE_SN9C120
},
620 { 0x0c45, 0x613e, BRIDGE_SN9C120
},
621 { 0x0000, 0x0000, 0 }
625 struct NepClassSonixcam
* SetupSonixcam(void)
627 struct NepClassSonixcam
*nch
;
628 struct PsdDevice
*pd
= NULL
;
629 struct PsdAppBinding
*pab
;
631 struct AutoBindData
*abd
;
633 if(ArgsArray
[ARGS_UNIT
])
635 unit
= *((ULONG
*) ArgsArray
[ARGS_UNIT
]);
644 pd
= psdFindDevice(pd
,
645 DA_VendorID
, abd
->abd_VendID
,
646 DA_ProductID
, abd
->abd_ProdID
,
666 PutStr("No Sonixcam found!\n");
669 if((nch
= psdAllocVec(sizeof(struct NepClassSonixcam
))))
671 nch
->nch_Device
= pd
;
672 nch
->nch_BridgeID
= abd
->abd_BridgeID
;
673 nch
->nch_ReleaseHook
.h_Entry
= (APTR
) releasehook
;
675 pab
= psdClaimAppBinding(ABA_Device
, pd
,
676 ABA_ReleaseHook
, &nch
->nch_ReleaseHook
,
678 ABA_ForceRelease
, TRUE
,
682 if(AllocSonixcam(nch
))
686 PutStr("Couldn't allocate Sonixcam...\n");
688 psdReleaseAppBinding(pab
);
690 PutStr("Couldn't claim binding!\n");
694 PutStr("Hohum...\n");
699 struct RastPort
* SetupText(void)
701 STRPTR text
= (STRPTR
) ArgsArray
[ARGS_TEXT
];
702 InitRastPort(&fontrp
);
703 if(ArgsArray
[ARGS_FONT
])
705 avenirta
.ta_Name
= (STRPTR
) ArgsArray
[ARGS_FONT
];
706 if(ArgsArray
[ARGS_FONTSIZE
])
708 avenirta
.ta_YSize
= *((ULONG
*) ArgsArray
[ARGS_FONTSIZE
]);
710 avenirta
.ta_YSize
= 8;
712 avenirta
.ta_Style
= 0L;
713 avenirta
.ta_Flags
= 0L;
714 if(!(avenirfont
= OpenDiskFont(&avenirta
)))
716 Printf("Couldn't open font!\n");
718 SetFont(&fontrp
, avenirfont
);
721 tlength
= TextLength(&fontrp
, text
, (ULONG
) strlen(text
));
722 theight
= fontrp
.Font
->tf_YSize
;
723 if(!(fontbm
= AllocBitMap(tlength
, theight
, 1L, BMF_CLEAR
, NULL
)))
725 Printf("Couldn't allocate font bitmap memory (%ldx%ld)", tlength
, theight
);
728 fontrp
.BitMap
= fontbm
;
729 //printf("String: %s\nLength: %d\n",(char *)argsarray[ARGS_TEXT], tlength);
730 Move(&fontrp
, 0, (LONG
) fontrp
.Font
->tf_Baseline
);
731 Text(&fontrp
, text
, (ULONG
) strlen(text
));
744 CloseFont(avenirfont
);
749 void PasteText(struct SCImageHeader
*scih
, UBYTE
*output
)
753 LONG vw
= scih
->scih_ImgWidth
;
759 tarx
= (vw
-tlength
) >> 1;
763 tary
= (scih
->scih_ImgHeight
-theight
-theight
);
764 for(y
= 0; y
< theight
; y
++)
766 for(x
= 0; (x
< tlength
) && (x
+tarx
+2 < vw
); x
++)
768 pix
= ReadPixel(&fontrp
, x
, y
);
771 op
= &output
[((tary
+y
)*vw
+tarx
+x
)*3];
787 for(y
= 0; y
< theight
; y
++)
789 for(x
= 0; (x
< tlength
) && (x
+tarx
+2 < vw
); x
++)
791 pix
= ReadPixel(&fontrp
, x
, y
);
794 op
= &output
[((tary
+y
)*vw
+tarx
+x
)*3];
803 struct NepClassSonixcam
* AllocSonixcam(struct NepClassSonixcam
*nch
)
806 nch
->nch_Task
= FindTask(NULL
);
808 nch
->nch_Interface
= psdFindInterface(nch
->nch_Device
, NULL
,
811 if(!nch
->nch_Interface
)
813 PutStr("No interfaces?\n");
817 psdGetAttrs(PGA_INTERFACE
, nch
->nch_Interface
,
818 IFA_InterfaceNum
, &nch
->nch_IfNum
,
820 if((nch
->nch_TaskMsgPort
= CreateMsgPort()))
822 nch
->nch_ImgDoneSig
= AllocSignal(-1L);
823 if((nch
->nch_EP0Pipe
= psdAllocPipe(nch
->nch_Device
, nch
->nch_TaskMsgPort
, NULL
)))
825 psdSetAltInterface(nch
->nch_EP0Pipe
, nch
->nch_Interface
);
826 nch
->nch_IsoEP
= psdFindEndpoint(nch
->nch_Interface
, NULL
,
828 EA_TransferType
, USEAF_ISOCHRONOUS
,
832 nch
->nch_InReqHook
.h_Entry
= (HOOKFUNC
) nInReqHook
;
833 nch
->nch_InReqHook
.h_Data
= nch
;
834 nch
->nch_InDoneHook
.h_Entry
= (HOOKFUNC
) nInDoneHook
;
835 nch
->nch_InDoneHook
.h_Data
= nch
;
836 nch
->nch_RTIso
= psdAllocRTIsoHandler(nch
->nch_IsoEP
,
837 RTA_InRequestHook
, &nch
->nch_InReqHook
,
838 RTA_InDoneHook
, &nch
->nch_InDoneHook
,
842 foundsensor
= SenseOV7631(nch
);
845 foundsensor
= SenseHV7131R(nch
);
850 switch(nch
->nch_BridgeID
)
853 nch
->nch_HeaderSize
= 12;
857 nch
->nch_HeaderSize
= 18;
862 nch
->nch_HeaderSize
= 62;
866 nch
->nch_RawBufSize
= 320*240 + nch
->nch_HeaderSize
;
867 nch
->nch_RawBuf
[0] = psdAllocVec(nch
->nch_RawBufSize
* 3);
868 if(nch
->nch_RawBuf
[0])
870 nch
->nch_RawBuf
[1] = nch
->nch_RawBuf
[0] + nch
->nch_RawBufSize
;
871 nch
->nch_RawBuf
[2] = nch
->nch_RawBuf
[1] + nch
->nch_RawBufSize
;
872 nch
->nch_ImgBufSize
= 320*240*3;
873 nch
->nch_ImgBuf
= psdAllocVec(nch
->nch_ImgBufSize
);
878 Printf("Couldn't allocate %ld bytes of memory.\n", nch
->nch_ImgBufSize
);
880 psdFreeVec(nch
->nch_RawBuf
[0]);
882 Printf("Couldn't allocate %ld bytes of memory.\n", nch
->nch_RawBufSize
* 3);
885 PutStr("Failed to init sensor\n");
887 psdFreeRTIsoHandler(nch
->nch_RTIso
);
889 PutStr("Couldn't allocate RT Iso Handler.\n");
892 PutStr("No iso endpoint?\n");
894 psdFreePipe(nch
->nch_EP0Pipe
);
896 PutStr("Couldn't allocate default pipe\n");
898 FreeSignal(nch
->nch_ImgDoneSig
);
899 DeleteMsgPort(nch
->nch_TaskMsgPort
);
904 void FreeSonixcam(struct NepClassSonixcam
*nch
)
907 psdFreeVec(nch
->nch_ImgBuf
);
908 psdFreeVec(nch
->nch_RawBuf
[0]);
909 psdFreeRTIsoHandler(nch
->nch_RTIso
);
910 psdGetAttrs(PGA_DEVICE
, nch
->nch_Device
,
913 psdReleaseAppBinding(pab
);
914 psdFreePipe(nch
->nch_EP0Pipe
);
915 FreeSignal(nch
->nch_ImgDoneSig
);
916 DeleteMsgPort(nch
->nch_TaskMsgPort
);
920 /**************************************************************************/
922 void bayer_unshuffle(struct SCImageHeader
*scih
, UBYTE
*raw
, UBYTE
*output
)
925 ULONG vw
= scih
->scih_ImgWidth
;
926 ULONG vh
= scih
->scih_ImgHeight
;
927 ULONG w3
= vw
+ vw
+vw
;
931 /* Byte Order. Each cell is one byte.
932 start + 0: B00 G01 B02 G03
933 start + 4: G10 R11 G12 R13
934 start + 8: B20 G21 B22 G23
935 start + 12: G30 R31 G32 R33 */
937 /* Byte Order. Each cell is one byte.
938 start + 0: G00 B01 G02 B03
939 start + 4: R10 G11 R12 G13
940 start + 8: G20 B21 G22 B23
941 start + 12: R30 G31 R32 G33 */
944 for(y
= 0; y
< vh
; y
++)
946 oline
= output
+ 1 - (y
& 1); // start with green on even, red on odd
950 *oline
= *raw
++; // green on even, red on odd
952 *oline
= *raw
++; // blue on even, green on odd
959 void bayer_demosaic(struct SCImageHeader
*scih
, UBYTE
*output
)
966 op
= output
+ 3 + vw3
;
973 /* 11 green. red lr, blue tb */
974 *op
= (((UWORD
) op
[-3]) + ((UWORD
) op
[3])) >> 1; /* Set red */
975 op
[2] = (((UWORD
) op
[2-vw3
]) + ((UWORD
) op
[2+vw3
]) + 1) >> 1; /* Set blue */
977 /* 10 red. green lrtb, blue diagonals */
978 op
[1] = (((UWORD
) op
[-2]) + ((UWORD
) op
[4]) +
979 ((UWORD
) op
[1-vw3
]) + ((UWORD
) op
[1+vw3
]) + 2) >> 2; /* Set green */
980 op
[2] = (((UWORD
) op
[-1-vw3
]) + ((UWORD
) op
[5-vw3
]) +
981 ((UWORD
) op
[-1+vw3
]) + ((UWORD
) op
[5+vw3
]) + 2) >> 2; /* Set blue */
988 /* 01 blue. green lrtb, red diagonals */
989 op
[1] = (((UWORD
) op
[-2]) + ((UWORD
) op
[4]) +
990 ((UWORD
) op
[1-vw3
]) + ((UWORD
) op
[1+vw3
]) + 2) >> 2; /* Set green */
991 *op
= (((UWORD
) op
[-3-vw3
]) + ((UWORD
) op
[3-vw3
]) +
992 ((UWORD
) op
[-3+vw3
]) + ((UWORD
) op
[3+vw3
]) + 2) >> 2; /* Set red */
994 /* 00 green. blue lr, red tb */
995 op
[2] = (((UWORD
) op
[-1]) + ((UWORD
) op
[5]) + 1) >> 1; /* Set blue */
996 *op
= (((UWORD
) op
[-vw3
]) + ((UWORD
) op
[vw3
]) + 1) >> 1; /* Set red */
1033 void gammacorrection(struct SCImageHeader
*scih
, UBYTE
*output
)
1035 ULONG cnt
= scih
->scih_ImgWidth
*scih
->scih_ImgHeight
;
1038 *output
= gammaredtab
[*output
];
1040 *output
= gammagreentab
[*output
];
1042 *output
= gammabluetab
[*output
];
1047 void sharpen5x5(struct SCImageHeader
*scih
, UBYTE
*input
, UBYTE
*output
)
1050 LONG vw
= scih
->scih_ImgWidth
;
1051 LONG vw3
= vw
+vw
+vw
;
1053 LONG vh
= scih
->scih_ImgHeight
;
1062 for(y
= 2; y
< vh
-2; y
++)
1064 op
= &input
[((y
-2)*vw
)*3];
1065 linem2
[0] = *op
++; // -2
1068 linem2
[0] += *op
++; // -1
1071 linem2
[0] += *op
++; // 0
1074 linem2
[0] += *op
++; // 1
1077 linem2
[0] += *op
++; // 2
1081 op
= &input
[((y
-1)*vw
+1)*3];
1082 linem1
[0] = *op
++; // -1
1085 linem1
[0] += *op
++; // 0
1088 linem1
[0] += *op
++; // 1
1091 linem1
[0] += linem1
[0]+linem1
[0];
1092 linem1
[1] += linem1
[1]+linem1
[1];
1093 linem1
[2] += linem1
[2]+linem1
[2];
1094 linem1
[0] += *op
++; // 2
1097 linem1
[0] += op
[-15]; // -2
1098 linem1
[1] += op
[-14];
1099 linem1
[2] += op
[-13];
1101 op
= &input
[((y
+1)*vw
+1)*3];
1102 linep1
[0] = *op
++; // -1
1105 linep1
[0] += *op
++; // 0
1108 linep1
[0] += *op
++; // 1
1111 linep1
[0] += linep1
[0]+linep1
[0];
1112 linep1
[1] += linep1
[1]+linep1
[1];
1113 linep1
[2] += linep1
[2]+linep1
[2];
1114 linep1
[0] += *op
++; // 2
1117 linep1
[0] += op
[-15]; // -2
1118 linep1
[1] += op
[-14];
1119 linep1
[2] += op
[-13];
1121 op
= &input
[((y
+2)*vw
)*3];
1122 linep2
[0] = *op
++; // -2
1125 linep2
[0] += *op
++; // -1
1128 linep2
[0] += *op
++; // 0
1131 linep2
[0] += *op
++; // 1
1134 linep2
[0] += *op
++; // 2
1138 op
= &input
[(y
*vw
+ 2)*3];
1139 oop
= &output
[(y
*vw
+ 2)*3];
1140 for(x
= 2; x
< vw
-2; x
++) /* work out pixel type */
1143 val
[0] = op
[-3] + op
[3];
1144 val
[1] = op
[-2] + op
[4];
1145 val
[2] = op
[-1] + op
[5];
1146 val
[0] += val
[0] + val
[0] + op
[-6] + op
[6] + linem2
[0] + linem1
[0] + linep1
[0] + linep2
[0];
1147 val
[1] += val
[1] + val
[1] + op
[-5] + op
[7] + linem2
[1] + linem1
[1] + linep1
[1] + linep2
[1];
1148 val
[2] += val
[2] + val
[2] + op
[-4] + op
[8] + linem2
[2] + linem1
[2] + linep1
[2] + linep2
[2];
1149 val
[0] -= op
[0] * 56;
1150 val
[1] -= op
[1] * 56;
1151 val
[2] -= op
[2] * 56;
1154 *oop
++ = (val
[0] > 0) ? 0 : ((val
[0] < -MAXVAL
) ? 255 : (-val
[0]+8)>>4);
1155 *oop
++ = (val
[1] > 0) ? 0 : ((val
[1] < -MAXVAL
) ? 255 : (-val
[1]+8)>>4);
1156 *oop
++ = (val
[2] > 0) ? 0 : ((val
[2] < -MAXVAL
) ? 255 : (-val
[2]+8)>>4);
1158 /* Update line y-2 */
1159 linem2
[0] -= op
[-vw6
-6];
1160 linem2
[0] += op
[-vw6
+9];
1161 linem2
[1] -= op
[-vw6
-5];
1162 linem2
[1] += op
[-vw6
+10];
1163 linem2
[2] -= op
[-vw6
-4];
1164 linem2
[2] += op
[-vw6
+11];
1166 /* Update line y-1 */
1167 linem1
[0] -= op
[-vw3
-6];
1168 linem1
[0] -= op
[-vw3
-3]<<1;
1169 linem1
[0] += op
[-vw3
+6]<<1;
1170 linem1
[0] += op
[-vw3
+9];
1171 linem1
[1] -= op
[-vw3
-5];
1172 linem1
[1] -= op
[-vw3
-2]<<1;
1173 linem1
[1] += op
[-vw3
+7]<<1;
1174 linem1
[1] += op
[-vw3
+10];
1175 linem1
[2] -= op
[-vw3
-4];
1176 linem1
[2] -= op
[-vw3
-1]<<1;
1177 linem1
[2] += op
[-vw3
+8]<<1;
1178 linem1
[2] += op
[-vw3
+11];
1180 /* Update line y+1 */
1181 linep1
[0] -= op
[vw3
-6];
1182 linep1
[0] -= op
[vw3
-3]<<1;
1183 linep1
[0] += op
[vw3
+6]<<1;
1184 linep1
[0] += op
[vw3
+9];
1185 linep1
[1] -= op
[vw3
-5];
1186 linep1
[1] -= op
[vw3
-2]<<1;
1187 linep1
[1] += op
[vw3
+7]<<1;
1188 linep1
[1] += op
[vw3
+10];
1189 linep1
[2] -= op
[vw3
-4];
1190 linep1
[2] -= op
[vw3
-1]<<1;
1191 linep1
[2] += op
[vw3
+8]<<1;
1192 linep1
[2] += op
[vw3
+11];
1194 /* Update line y-2 */
1195 linep2
[0] -= op
[vw6
-6];
1196 linep2
[0] += op
[vw6
+9];
1197 linep2
[1] -= op
[vw6
-5];
1198 linep2
[1] += op
[vw6
+10];
1199 linep2
[2] -= op
[vw6
-4];
1200 linep2
[2] += op
[vw6
+11];
1206 APTR
GetVideoSnap(struct NepClassSonixcam
*nch
, struct SCImageHeader
*scih
)
1213 scih
->scih_ImgWidth
= 320;
1214 scih
->scih_ImgHeight
= 240;
1215 scih
->scih_ImgSize
= scih
->scih_ImgWidth
* scih
->scih_ImgHeight
* 3;
1217 nch
->nch_BufState
[2] = nch
->nch_BufState
[1] = nch
->nch_BufState
[0] = BUF_EMPTY
;
1219 nch
->nch_CurrIsoBuf
= nch
->nch_RawBuf
[0];
1220 nch
->nch_IsoBufNum
= 0;
1221 nch
->nch_IsoBufPos
= 0;
1223 ioerr
= psdStartRTIso(nch
->nch_RTIso
);
1226 Printf("Error starting RT Iso errorcode=%ld\n", ioerr
);
1232 sigs
= Wait((1UL<<nch
->nch_ImgDoneSig
)|SIGBREAKF_CTRL_C
);
1233 lastdone
= nch
->nch_LastDoneNum
;
1234 if(nch
->nch_BufState
[lastdone
] == BUF_READY
)
1238 } while(!(sigs
& SIGBREAKF_CTRL_C
));
1240 ioerr
= psdStopRTIso(nch
->nch_RTIso
);
1242 if(sigs
& SIGBREAKF_CTRL_C
)
1247 nch
->nch_BufState
[lastdone
] = BUF_BUSY
;
1248 bayer_unshuffle(scih
, nch
->nch_RawBuf
[lastdone
] + nch
->nch_HeaderSize
, nch
->nch_ImgBuf
);
1249 nch
->nch_BufState
[lastdone
] = BUF_EMPTY
;
1250 bayer_demosaic(scih
, nch
->nch_ImgBuf
);
1252 if(ArgsArray
[ARGS_SHARPEN
])
1254 newimgbuf
= psdAllocVec(nch
->nch_ImgBufSize
);
1257 sharpen5x5(scih
, nch
->nch_ImgBuf
, newimgbuf
);
1258 psdFreeVec(nch
->nch_ImgBuf
);
1259 nch
->nch_ImgBuf
= newimgbuf
;
1262 if(ArgsArray
[ARGS_GAMMA
])
1264 gammacorrection(scih
, nch
->nch_ImgBuf
);
1266 if(ArgsArray
[ARGS_TEXT
])
1268 PasteText(scih
, nch
->nch_ImgBuf
);
1270 return(nch
->nch_ImgBuf
);
1273 int main(int argc
, char *argv
[])
1275 struct NepClassSonixcam
*nch
;
1276 struct SCImageHeader scih
;
1283 if(!(ArgsHook
= ReadArgs(template, ArgsArray
, NULL
)))
1285 PutStr("Wrong arguments!\n");
1286 return(RETURN_FAIL
);
1288 ps
= OpenLibrary("poseidon.library", 4);
1292 return(RETURN_FAIL
);
1294 if(ArgsArray
[ARGS_TEXT
])
1300 return(RETURN_ERROR
);
1303 if(!(nch
= SetupSonixcam()))
1308 return(RETURN_ERROR
);
1314 /*PutStr("Waiting for CTRL-C before downloading.\n"
1315 "This is your chance to remove the cam to check if the machine crashes.\n");
1316 Wait(SIGBREAKF_CTRL_C); */
1317 imgbuf
= GetVideoSnap(nch
, &scih
);
1320 psdSafeRawDoFmt(buf
, 256, (STRPTR
) ArgsArray
[ARGS_TO
], imgcount
);
1321 outfile
= Open(buf
, MODE_NEWFILE
);
1324 FPrintf(outfile
, "P6\n%ld %ld\n255\n", scih
.scih_ImgWidth
, scih
.scih_ImgHeight
);
1326 Write(outfile
, imgbuf
, scih
.scih_ImgSize
);
1328 Printf("Wrote image into '%s'.\n", buf
);
1331 Printf("Could not open file '%s' for writing!\n", buf
);
1336 /*PutStr("Finished. Waiting for another CTRL-C.\n");*/
1337 sigs
= SetSignal(0, 0);
1338 if(sigs
& SIGBREAKF_CTRL_C
)
1342 if(ArgsArray
[ARGS_INTERVAL
])
1344 if(ArgsArray
[ARGS_UPTO
])
1346 if(imgcount
> *((ULONG
*) ArgsArray
[ARGS_UPTO
]))
1351 Delay(*((ULONG
*) ArgsArray
[ARGS_INTERVAL
]));
1353 if(ArgsArray
[ARGS_UPTO
])
1355 if(imgcount
> *((ULONG
*) ArgsArray
[ARGS_UPTO
]))
1363 sigs
= SetSignal(0, 0);
1364 if(sigs
& SIGBREAKF_CTRL_C
)