CamDue.ino 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "Arduino.h"
  2. #include <Wire.h>
  3. #include "registers.h"
  4. #define I2C_ADDR 0x21
  5. #define RESET 33
  6. #define VSYNC 52 //PortB.21
  7. #define PCLK 32 //PortD.10
  8. #define XCLK 7 //PWML6
  9. //Pin from 51 to 44 are on PortC
  10. #define D0 51 //12
  11. #define D1 50 //13
  12. #define D2 49 //14
  13. #define D3 48 //15
  14. #define D4 47 //16
  15. #define D5 46 //17
  16. #define D6 45 //18
  17. #define D7 44 //19
  18. #define WIDTH 320
  19. #define HEIGHT 240
  20. byte frame[HEIGHT][WIDTH];
  21. void writeReg(byte regID, byte regVal){
  22. Wire.beginTransmission(I2C_ADDR);
  23. Wire.write(regID);
  24. Wire.write(regVal);
  25. if (Wire.endTransmission(true)) {
  26. SerialUSB.print(F("ERROR REG 0x"));
  27. SerialUSB.println(regID,HEX);
  28. }
  29. delay(20);
  30. }
  31. byte readReg(byte regID){
  32. byte regVal;
  33. Wire.beginTransmission(I2C_ADDR);
  34. Wire.write(regID);
  35. Wire.endTransmission(true);
  36. Wire.requestFrom(I2C_ADDR,1);
  37. while (Wire.available() == 0);
  38. regVal = Wire.read();
  39. delay(20);
  40. return regVal;
  41. }
  42. void setup() {
  43. pinMode(RESET,OUTPUT);
  44. digitalWrite(RESET,HIGH);
  45. digitalWrite(RESET,LOW);
  46. digitalWrite(RESET,HIGH);
  47. pinMode(D0, INPUT);
  48. pinMode(D1, INPUT);
  49. pinMode(D2, INPUT);
  50. pinMode(D3, INPUT);
  51. pinMode(D4, INPUT);
  52. pinMode(D5, INPUT);
  53. pinMode(D6, INPUT);
  54. pinMode(D7, INPUT);
  55. pinMode(VSYNC, INPUT);
  56. pinMode(PCLK, INPUT);
  57. int32_t PWM_pin = digitalPinToBitMask(XCLK);
  58. REG_PMC_PCER1 = 1 << 4; // Enable peripheral ID 36 (PWM) in the peripheral clock enable register - see 28.15.23
  59. REG_PIOC_PDR |= PWM_pin; // Allow peripheral control for PWM_pin
  60. REG_PIOC_ABSR |= PWM_pin; // Select peripheral B
  61. REG_PWM_CPRD6 = 8; // Period: 84 MHz / 8 = 10.5 MHz - see 38.6.2.2 of datasheet
  62. REG_PWM_CDTY6 = 4; // Duty Cycle: 8 / 4 = 0.5
  63. REG_PWM_ENA = 1 << 6; // Enable PWML6 (pin 7) - see 38.5.1 and 38.7.5 of datasheet for more info
  64. SerialUSB.begin(0);
  65. while(!SerialUSB);
  66. Wire.begin();
  67. setupDefault();
  68. setupQVGA();
  69. setupYUV422();
  70. writeReg(R_CLKRC,0x06); //Use external clock
  71. SerialUSB.print(F("PID=0x"));
  72. SerialUSB.println(readReg(R_PID),HEX); //PID should be 0x76
  73. SerialUSB.print(F("VER=0x"));
  74. SerialUSB.println(readReg(R_VER),HEX); //VER should be 0x73
  75. SerialUSB.println(F("READY"));
  76. }
  77. void setupDefault() {
  78. writeReg(R_COM7, 0x80); //Reset OV7670 registers
  79. writeReg(R_TSLB, 0x04); //Line Buffer Test Option
  80. writeReg(R_COM10,1 << 5); //PLCK does not toggle during horizontal blank
  81. writeReg(R_RSVD_35,0x84); //Hue correction - undocumented
  82. writeReg(R_HSYST, 0x00); //disable some delays
  83. writeReg(R_HSYEN, 0x00);
  84. writeReg(R_COM8, 0xC5); //Enables auto gain, auto white balance and auto exposure
  85. writeReg(R_HAECC1, 0x78); //Histogram-based AEC/AGC controls
  86. writeReg(R_HAECC2, 0x68);
  87. writeReg(R_HAECC3, 0xD8);
  88. writeReg(R_HAECC4, 0xD8);
  89. writeReg(R_HAECC5, 0xF0);
  90. writeReg(R_HAECC6, 0x90);
  91. writeReg(R_HAECC7, 0x94);
  92. writeReg(R_COM9, 0x18); // 4x Gain
  93. }
  94. void setupQVGA() {
  95. //setup for QVGA
  96. writeReg(R_COM3, 0x04);
  97. writeReg(R_COM14, 0x19);
  98. writeReg(R_HSTART,0x16);
  99. writeReg(R_HSTOP, 0x04);
  100. writeReg(R_HREF, 0x24);
  101. writeReg(R_VSTRT, 0x02);
  102. writeReg(R_VSTOP, 0x7A);
  103. writeReg(R_VREF, 0x0A);
  104. writeReg(R_SCALING_DCWCTR, 0x11);
  105. writeReg(R_SCALING_PCLK_DIV, 0xF1);
  106. }
  107. void setupYUV422() {
  108. //setup for YUV422
  109. writeReg(R_COM15,0xC0); //Data format, output range from [00] to [FF]
  110. writeReg(R_COM9, 0X6A); //128x gain ceiling
  111. writeReg(R_MTX1, 0x80); //Matrix coefficient
  112. writeReg(R_MTX2, 0x80); //Matrix coefficient
  113. writeReg(R_MTX3, 0x00); //Matrix coefficient
  114. writeReg(R_MTX4, 0x22); //Matrix coefficient
  115. writeReg(R_MTX5, 0x5E); //Matrix coefficient
  116. writeReg(R_MTX6, 0x80); //Matrix coefficient
  117. writeReg(R_COM13,0x40); //UV Saturation auto-adjust
  118. }
  119. void loop() {
  120. char buffer_USB[3];
  121. if(SerialUSB.available() > 0) {
  122. SerialUSB.readBytes(buffer_USB,3);
  123. if(buffer_USB[0] != 0xD0 && buffer_USB[1] == 0xD0) {
  124. SerialUSB.println(readReg(buffer_USB[0]));
  125. } else if (buffer_USB[0] != 0xD0 && buffer_USB[1] !=0xD0) {
  126. writeReg(buffer_USB[0],buffer_USB[1]);
  127. } else {
  128. captureImg(WIDTH,HEIGHT,0);
  129. if (buffer_USB[2] == 0x01) {
  130. captureImg(WIDTH,HEIGHT,1);
  131. }
  132. }
  133. }
  134. }
  135. void captureImg(uint16_t width, uint16_t height, bool chroma){
  136. uint16_t x,y;
  137. noInterrupts();
  138. while(!(REG_PIOB_PDSR & (1 << 21))); //wait VSYNC high - pin 52 = bit 21 on PortB
  139. while((REG_PIOB_PDSR & (1 << 21))); //wait VSYNC low
  140. y = height;
  141. while (y--) {
  142. x = width;
  143. while (x--){
  144. while ((REG_PIOD_PDSR & (1 << 10))); //wait PCLK low - pin 32 = bit 10 on PortD
  145. if (!chroma) {frame[y][x] = (REG_PIOC_PDSR & 0xFF000) >> 12;} //read Y
  146. while (!(REG_PIOD_PDSR & (1 << 10))); //wait PCLK high
  147. while ((REG_PIOD_PDSR & (1 << 10))); //wait PCLK low
  148. if (chroma) {frame[y][x] = (REG_PIOC_PDSR & 0xFF000) >> 12;} //read Cb or Cr
  149. while (!(REG_PIOD_PDSR & (1 << 10))); //wait PCLK high
  150. }
  151. }
  152. for(y = 0;y < height;y++){
  153. for(x = 0; x < width;x++){
  154. SerialUSB.write(frame[y][x]);
  155. }
  156. }
  157. interrupts();
  158. }