Hardware hacking

A project log for Camera badge for Supercon 2017

Conference badge for the 2017 Hackaday Superconference Features: camera module, 128x128 OLED display, MicroSD card socket and accelerometer

Mike Harrison 10/11/2017 at 11:043 Comments

Expansion header and hardware test/access points

DXF of board layout for mechanical dims

PIC32MX1xx datasheet

PIC32MX1xx errata

Expansion header pins

See Datasheet section 11.3 for pin remapping details. Only functions that don't clash with existing badge functionality are listed below. IC - input capture, OC = Output compare (e.g.  PWM)
10VGround. Also on ISP header pin 3 and TTL232 header pin 1
Also available on several pads around prototype area
2I2C SDA2.8v levels.
Used onboard by accelerometer and camera
Also available at edge of prototyping area
2.8v levels
Used onboard by accelerometer and camera
Also available at edge of prototyping area
4+2.8VLogic supply. Also on ISP header pin 2
Also available at edge of prototyping area
5RA2/RPA2PIC pin 30. I/O or mappable peripheral RPA2
Set to output by default
RPA2 can be mapped to inputs INT2,T4CK,IC1,IC5,OCFB, and outputs SDO1,SDO2,OC4,OC5,REFCLKO
6RB4/RPB4PIC Pin 33. I/O or mappable peripheral RB4
Set to output by default.
RPB4 can be mapped to inputs INT4,T2CLK,IC4,REFCLKI and outputs U1TX,OC1,C2OUT
7RB0/RPB0/PGD1/AN2PIC pin 21. I/O or remappable peripheral
Configured as UART2 TXD by default.
Also on ISP header pin 4 and TTL232 header pin 5
Shared with ISP, so add at least 2K2 in series if driving pin to avoid interfering withe programming functionality.
RPB0 can be mapped to inputs INT1,T5CK,IC2,OCFA and outputs U2TX,OC3,C1OUT
Analogue channel 2 ( need to set ANSELB bit 0)
8RC5/RPC5PIC pin 38. I/O or remappable peripheral.
5V Tolerant.
Configured as output by default. Reconfigured as UART1 TXD the first time u1txbyte() is called.
Note as this pin is shared with PMA3, it is subject to device errata.
TL;DR : no problems if used as mappable peripheral or input, but to use as output you need to set the corresponding bit in PMAEN and write the output value to PMADDR instead of LATC 
RPC5 can be mapped to inputs INT4,T2CK,IC4,REFCKI and outputs U1TX,OC1,C2OUT
9+3.3VOutput of 3.3v boost regulator.
Note that if the incoming supply is >3.3v, this pin will rise to the input voltage!

10RC3/RPC3PIC pin 36
Configured as input with pullup by default. UART1 RXD by default.
Reconfigured as UART1 RXD the first time u1txbyte() is called.
RPC3 can be mapped to inputs INT2,T4CK,IC1,IC5,U1RX,SDI2 and outputs SDO1,SDO2,OC4,OC5,REFCLKO
11VBATUnswitched battery supply
12RB1/RPB1/PGC1/AN3PIC pin 22
Configured as UART2 RXD by default.
Also on ISP header pin 5 and via 2k2 resistor R10 to TTL232 pin 4
Shared with ISP, so add at least 2K2 in series if driving pin to avoid interfering with  programming functionality.
RPB1 can be mapped to inputs INT3,T3CK,IC3,U2RX,SDI1 and outputs SDO1,SDO2,OC2,C3OUT.
Analogue channel 3 ( need to set ANSELB bit 1)

Sugested maximum draw from +3.3v or +2.8v is 200mA, maybe 300mA for brief periods.
If the OLED starts dimming, you're pulling too much!
Power may be fed into VBAT if batteries are not fitted, however note that if the supplied voltage exceeds 3.3v, the 3.3v rail will output the incoming supply voltage. This is not a problem for the badge up to about 5V, but be aware of possible dissipation issues in the 2.8v regulator if you are also pulling a lot from 2.8v.
If you have 3.3v -only devices and want to supply from >3.3v ( e.g. lipo), you should use your own 3.3v regulator. You can use the 2.8V rail as an enable to switch your local 3.3v supply if needed.

Firmware support for hardware

All I/O used by the badge is intialised in inithardware() in hardware.c


u1txbyte(c) and u2txbyte(c) Send 1 byte to UART1 and UART2 respectively. Baudrates are initialised with values in cambadge.h
UART1 is not mapped to pins at startup, but is mapped, and the UART configured, on the first call to u1txbyte()
A simple receive handler is set up for UART2 - this is in serial.c - see code for more details.

I2C :

On-board I2C device addresses : Camera 0x60 Accelerometer 0x3A (8  bit addresses).

The accelerometer is read on every 20mS tick period. 

The following routines are provided for I2C access. See globals.h for more info

unsigned int iistart(unsigned char iiadr)  Starts I2C command, iiadr - device address ( 8 bit). Returns zero if device does't acknowledge
unsigned int iisend(unsigned char byte) Sends 1 byte, returns zero if no acknowledge
void iirestart(unsigned char iiadr) Send Restart condition for read operationunsigned
int getiic(unsigned int ack) Read 1 byte, ack=1 to acknowledge ( set to 0 for last byte ).
void iistop(void)   Send I2C stop condition

Accessing hardware directly

I/O ports :

Set bit 2 on PORTA : LATASET=1<<2
Clear bit 2 on PORTA : LATACLR=1<<2
Invert bit 2 on PORTA : LATAINV=1<<2
Read bit 2 on PORTA : a=PORTAbits.RA2
Set bit 2 on PORTA to input ( output) TRISAbits,TRISA2=1 (0)
Write bit<value> to PORTA bit 2 : LATAbits.LATA2=<value>

Some peripheral functions can be mapped to RxP pins - see the "Peripheral Pin Select" section in the PIC datasheet.
e.g. to put Output Compare 4 on RA2 : 

RPA2Rbits.RPA2R=5;  // 5 is OC4 from Table 11-2 in datasheet

To set input capture 1 on RA2 : 

IC1Rbits.IC1R=0; // 0 is RA2 from Table 11-1 in datasheet

See hardware.c for more examples.

PIC resources used by badge firmware

Items marked * are used within the main polling loop. Others are only used by applications and may be used by other applications with care if their other functions are not being used.

ADC* : battery read.
Parallel Master Port : Camera.
I2C2* : Camera and accelerometer
Timer 1 : Used for delays via delayus()
Timer 2 : Used by camera and browser applications for frame-rates
Timer 3 : Used by camera capture task to count pixel clocks
Timer 4* : Used for system tick
REFO : Used to clock camera ( do not disable - camera will screw up I2C bus)
SPI1 : Display
SPI2 : SD card and SRAM
UART1 : Can be used for debug output
UART2 : Debug output and serial remote control


Mike Harrison wrote 10/23/2017 at 22:18 point

The SPI clock pins are annoyingly at fixed locations and not remappable. Turning the SPI module on switches them from being I/O. This overrides TRIS and any port remapping on that pin.

You can't get SPI on the header without a bodge wire, though you can always bit-bash it of course.

If you really really need a burst of high speed SPI, you could do it by mapping an output compare to a header pin to be the clock, and using the compare module's timer overflow to trigger a DMA to write data to the pin. This is rather involved as you need to pre-format the SPI data in a RAM buffer with 1 bit per byte. Stopping the clock at exactly the right time is also an interesting problem which I did a video on a while ago. 

  Are you sure? yes | no

zakqwy wrote 10/24/2017 at 19:46 point

thanks for the info! 

  Are you sure? yes | no

zakqwy wrote 10/22/2017 at 06:08 point

Thanks for putting together such good hardware documentation. I'm new to the PIC world so the whole idea of reassigning peripherals to I/O pins is delightful; having said that, the SPI port hardware initialization is a bit confusing. For example, in pindefs.h, the SD card setup is defined in this macro:

#define iosetup_sd TRISACLR=1<<0;CNPDAbits.CNPDA0=1;CNPUBbits.CNPUB13=1; \           RPA1Rbits.RPA1R=4;SDI2Rbits.SDI2R=3; //A1 = SDO2, B13 = SDI2, CS pulldown for card det

From what I can gather from the datasheet (section 11.3) and your comments, RPA1Rbits.RPA1R=4 sets pin 20 to  SDO2 (the MOSI pin for SPI2), and SDI2Rbits.SDI2R=3 sets SDI2 (the MISO pin for SPI2) to 0b0011, or RPB13 (pin 11).

However, I'm having trouble figuring out how the clock pins get set -- the schematic suggests RPB15 (pin 15) is the SPI2 clock pin, for example, but it's never referenced in pindefs.h or any other code I was able to locate.

As you can probably imagine I'm hoping to reuse one of the SPI ports for something else, but I need to assign both the data lines _and_ the clock pin to the breakout header. Can you offer any tips?

  Are you sure? yes | no