' C328 Camera Test Program ' Copyright 2007 Raymond Allen ' Thanks to Harrison for posting working demo code for the C328 { Pin Setup --------- 4 - SD 5 - SD 6 - SD 7 - SD 0 - Camera TX (Yellow) [Prop RX] 1 - Camera RX (Green) [Prop TX] 24 - mouse base 16 - vga base } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 'number of custom interleaved characters nuchars = 80 'you must put the correct # here for alignment later cols = 32 'number of columss on the screen rows = 22 'number of rows on the screen screensize = cols * rows OBJ ser : "FullDuplexSerialExtended" ' required for packet sizes > 16 sd: "fsrw" num: "numbers" vga : "vga" 'need the vga driver mouse : "mouse" VAR byte PicBuf[506] long col, row, color 'working variables for output to screen word user_charbase PUB start|i '64 byte align the user characters user_charbase := @uchar & $FFC0 'destination longmove(user_charbase,@uchar,16*nuchars) 'start mouse driver mouse.start(24, 25) 'use pins 24 and 25 'Start the VGA driver vga_videobase := @screen vga_colorbase := @vgacolors vga.start(@vga_parameters) color:=0 'Set color to Red on Black CLS 'clear the screen 'try full speed first (might remember if power not cycled) str(string("Trying 115200 baud...",13)) ser.start(0, 1, %0000, 115200) ser.rxflush 'connect to camera if (CheckSync) str(string("Connected at 115200 baud.",13)) else repeat str(string("Attempt $")) hex(++i,3) out(13) ser.stop delay_ms(10) ser.start(0, 1, %0000, 115200) ser.rxflush if (CheckSync) str(string("Connected at 115200 baud.",13)) quit 'set light frequency SendCommandGetAck(@Light60Hz) 'show preview until left mouse cls repeat until(mouse.button(0)) 'until left-button down TakeShowPreview(@PreviewBmp, @Init2BitPreview, 0, 0) delay_ms(10) 'save picture cls 'mount sd card if (\sd.mount(4)<>0) str(string("Failed to Mount SD Card",13)) repeat if (TakeSaveJPG(STRING("Test2.jpg"),@InitJPG640)==true) str(string("Picture Saved.",13)) else str(string("Picture Error.",13)) repeat PUB TakeShowPreview(pBitmap, pInit, x, y) SendCommandGetAck(pInit) row:=12 col:=0 'str(string("Taking preview",13)) delay_ms(10) SendCommandGetAck(@GetPreview) delay_ms(10) StorePreview(pBitmap) Bitmap2Bit(pBitmap, 2, 2, 10, 8, 21) PUB TakeSaveJPG(sFilename,pInit) if NOT SendCommandGetAck(pInit) return false if NOT SendCommandGetAck(@Package512) return false 'delay_ms(1000) 'let camera get warmed up... str(string("Taking picture",13)) if NOT SendCommandGetAck(@Snapshot) return false if NOT SendCommandGetAck(@GetPicture) return false return SaveJPG(sFilename) PUB StorePreview(pBitmap)|address, i, type, size, x,y,z,r,j address:=pBitmap+user_charbase-@uchar 'actual address of bitmap repeat 1 'Why is this sent twice? if (ser.rxcheck==$AA) if (ser.rxcheck==$0A) type:=ser.rx size:=ser.rx+ser.rx<<8+ser.rx<<16 'This size is wrong! Why? repeat 6 ser.rx repeat i from 0 to 4800-1 '=160x120/4 PreviewBuffer[i]:=ser.rx i:=0 repeat y from 0 to 7 repeat x from 0 to 10-1 repeat z from 0 to 16-1 if (y<7) or (z<8) repeat j from 0 to 3 r:=PreviewBuffer[((y*16+z)*10+x)*4+j] r><=8 byte[address+(i++)]:=r else long[address+i]:=0 i+=4 'str(STRING("Preview Recieved",13)) SendCommand(@DonePreview) Pub SaveJPG(sFilename)|type,size, n,i, p,j delay_ms(10) if (ser.rx<>$AA) return false if (ser.rx<>$0A) return false type:=ser.rx size:=ser.rx+ser.rx<<8+ser.rx<<16 sd.popen(sFilename, "w") str(STRING("Type: ")) str(num.tostr(type,num#dec)) out(13) str(STRING("Size: ")) str(num.tostr(size,num#dec)) out(13) p:=0 SendAckPackage(p) delay_ms(10) n:=0 repeat ser.rx ser.rx p++ 'new package i:=ser.rx+ser.rx<<8 repeat j from 0 to i-1 PicBuf[j]:=ser.rx sd.pwrite(@PicBuf,i) n+=i ser.rx ser.rx delay_ms(1) SendAckPackage(p) if (n==size) str(STRING("Done. ")) str(num.tostr(size,num#dec)) str(STRING(" bytes")) out(13) SendCommand(@DonePicture) sd.pclose return true Pub SendAckPackage(nPackage) ser.tx($AA) ser.tx($0E) ser.tx($00) ser.tx($00) ser.tx(nPackage//256) ser.tx(nPackage/256) Pub SendCommandGetAck(pCmd):bAck SendCommand(pCmd) delay_ms(10) bAck:=GetAck(pCmd) if (bAck) 'str(string("Command Accepted",13)) else str(string("Command Failed",13)) return bAck PUB CheckSync:bSyncd ser.rxflush repeat 60 delay_ms(100) SendCommand(@Sync)'send_sync delay_ms(100) if (GetAck(@Sync)==true) delay_ms(100) if (GetSync==true) delay_ms(100) SendAck(@Sync) return true return false PUB SendAck(pCmd) ser.tx($AA) ser.tx($0E) ser.tx(byte[pCmd]) ser.tx(0) ser.tx(0) ser.tx(0) PUB GetAck(pCmd):bGot|i repeat 100 if (ser.rxcheck==$AA) if (ser.rxcheck==$0E) if (ser.rxcheck==byte[pCmd])'$0D) if (ser.rxcheck>0) if (ser.rxcheck==0) if (ser.rxcheck==0) return true return false PUB GetSync:bGot repeat 100 if (ser.rxcheck==$AA) if (ser.rxcheck==$0D) if (ser.rxcheck==$00)'$0D) if (ser.rxcheck==$00) if (ser.rxcheck==$00) if (ser.rxcheck==$00) return true return false PRI SendCommand(pCmd)|i ser.tx($AA) repeat i from 0 to 4 ser.tx(byte[pCmd+i]) PRI delay_ms(Duration) waitcnt(((clkfreq / 1_000 * Duration - 3932)) + cnt) PRI str(ptr) repeat while byte[ptr] out(byte[ptr++]) PUB out(c) | i, k case c $0E..$FF: 'character? k := color << 1 + c & 1 i := k << 10 + $200 + c & $FE screen[row * cols + col] := i screen[(row + 1) * cols + col] := i | 1 if ++col == cols newline $100: 'clear screen? wordfill(@screen, $200, screensize) col := row := 0 $08: 'backspace? if col col-- $0D: 'return? newline PRI newline : i col := 0 if (row += 2) == rows row -= 2 'scroll lines repeat i from 0 to rows-3 wordmove(@screen[i*cols], @screen[(i+2)*cols], cols) 'clear new line wordfill(@screen[(rows-2)*cols], $200+ $20+color<<11, cols<<1) PUB hex(value, digits) '' Print a hexadecimal number value <<= (8 - digits) << 2 repeat digits out(lookupz((value <-= 4) & $F : "0".."9", "A".."F")) PUB CLS 'clear the screen wordfill(@screen, $200+ $20+color<<11, screensize) col := row := 0 PRI Bitmap2Bit(pBitmap, xPos, yPos, xSize, ySize, clr)|c,i,j,BmpAddress row:=yPos col:=xPos c:=0 BmpAddress:=pBitmap+user_charbase-@uchar repeat j from 0 to (ySize-1) repeat i from 0 to (xSize-1) screen[row * cols + col] := clr<<10 + BmpAddress>>6 +c c++ col++ row++ col:=xPos DAT Sync byte $0D,$00,$00,$00,$00 Ack byte $0E,$0D,$00,$00,$00 DataAck byte $00 'respond to data present B115200 byte $07,$0F,$01,$00,$00 B14400 byte $07,$7F,$01,$00,$00 Init2BitPreview byte $01,$00,$01,$03,$00 'Initialize to 2-bit grayscale 160x120 InitJPG640 byte $01,$00,$07,$00,$07 'Initialize to 640x480 jpg Package512 byte $06,$08,$00,$02,$00 'Set data package size to 512 bytes Reset byte $08,$00,$00,$00,$00 SnapShot byte $05,$00,$00,$00,$00 'Take compressed picture GetPicture byte $04,$01,$00,$00,$00 'Command to start sending picture data GetPreview byte $04,$02,$00,$00,$00 DonePicture byte $0E,$00,$00,$F0,$F0 DonePreview byte $0E,$0A,$00,$00,$00 Light60Hz byte $13,$01,$00,$00,$00 padding LONG 7[16] 'alignment padding for the following user defined characters uchar long PreviewBmp LONG file "PreviewPlace.dat" PreviewBuffer byte 0[4800] vgacolors long 'NOTE: need two longs to define each screen text color (due to character interleaving) long $FC08FC08 '0 'white on blue text color #0 long $FCFC0808 '1 long $08A808A8 '2 'green text color #1 long $0808A8A8 '3 long $50005000 '4 'blue text color #2 long $50500000 '5 long $FC00FC00 '6 'white text color #3 long $FCFC0000 '7 long $FF80FF80 '8 'white on red text color #4 long $FFFF8080 '9 long $FF20FF20 '10 'white on green long $FFFF2020 '11 long $FF28FF28 '12 'cyan/white long $FFFF2828 '13 long $00A800A8 '14 'grey/black long $0000A8A8 '15 long $C0408080 '16 'redbox 'Only need one long for graphics colors spcl long $30100020 '17 'greenbox long $3C142828 '18 'cyanbox long $FC54A8A8 '19 'greybox long $3C14FF28 '20 'cyanbox+underscore gray long %%3330_1110_2220_0000 '21 screen word word 0[screensize] 'this array holds the characters to display at every position on the screen vga_parameters 'input parameters for VGA driver (21 contiguous longs) long 0 'status: off/visible/invisible read-only long 1 'enable: off/on write-only long %010_111 'pins: byte(2),topbit(3) write-only long %011 'mode: interlace,hpol,vpol write-only vga_videobase long 0 'video base @word write-only vga_colorbase long 0 'color base @long write-only long cols 'hc 'horizontal cells write-only long rows 'vc 'vertical cells write-only long 1 'hx 'horizontal cell expansion write-only long 1 'vx 'vertical cell expansion write-only long 0 'ho 'horizontal offset write-only long 0 'vo 'vertical offset write-only long 512 'hd 'horizontal display pixels write-only long 16 'hf 'horizontal front-porch pixels write-only long 96 'hs 'horizontal sync pixels write-only long 48 'hb 'horizontal back-porch pixels write-only long 380 'vd 'vertical display lines write-only long 11 'vf 'vertical front-porch lines write-only long 2 'vs 'vertical sync lines write-only long 31 'vb 'vertical back-porch lines write-only long 20_000_000 'rate 'pixel rate (Hz) write-only