// Pin header footprint for a small RP2040-based controller board from AliExpress called "Pico Mini RP2040". // It has a similar footprint to the Pro Micro (NOT pin-compatible though!), but has an additional row of pins // on the short edge of the board (basically forming a "U"). // ------------------------------- // Params // orientation: if up (default), the controller will be on the front side of the PCB, otherwise on the back side module.exports = { params: { designator: 'MCU', orientation: 'up', // Left side of pins (with USB port at the top), top to bottom GP0: {type: 'net', value: 'GP0'}, GP1: {type: 'net', value: 'GP1'}, GP2: {type: 'net', value: 'GP2'}, GP3: {type: 'net', value: 'GP3'}, GP4: {type: 'net', value: 'GP4'}, GP5: {type: 'net', value: 'GP5'}, GP6: {type: 'net', value: 'GP6'}, GP7: {type: 'net', value: 'GP7'}, GP8: {type: 'net', value: 'GP8'}, GP9: {type: 'net', value: 'GP9'}, GP10: {type: 'net', value: 'GP10'}, GP11: {type: 'net', value: 'GP11'}, GP12: {type: 'net', value: 'GP12'}, GP13: {type: 'net', value: 'GP13'}, // Bottom side of pins, left to right (i.e. between GP13 and GP19) GP14: {type: 'net', value: 'GP14'}, GP15: {type: 'net', value: 'GP15'}, GP16: {type: 'net', value: 'GP16'}, GP17: {type: 'net', value: 'GP17'}, GP18: {type: 'net', value: 'GP18'}, // Right side of pins (with USB port at the top), top to bottom '5V': {type: 'net', value: '5V'}, // 5V USB voltage GND: {type: 'net', value: 'GND'}, RST: {type: 'net', value: 'RST'}, // Reset pin: Pull down to reset '3V3': {type: 'net', value: '3V3'}, // 3.3V voltage used by the MCU GP29: {type: 'net', value: 'GP29'}, // also: ADC4 GP28: {type: 'net', value: 'GP28'}, // also: ADC2 GP27: {type: 'net', value: 'GP27'}, // also: ADC1 GP26: {type: 'net', value: 'GP26'}, // also: ADC0 GP25: {type: 'net', value: 'GP25'}, GP23: {type: 'net', value: 'GP23'}, GP22: {type: 'net', value: 'GP22'}, GP21: {type: 'net', value: 'GP21'}, GP20: {type: 'net', value: 'GP20'}, GP19: {type: 'net', value: 'GP19'}, }, body: p => { let sign, side, mirror; if (p.orientation === 'down') { sign = -1; side = 'B'; mirror = 'mirror'; } else { sign = 1; side = 'F'; mirror = ''; } const pins_left = [ 'GP0', 'GP1', 'GP2', 'GP3', 'GP4', 'GP5', 'GP6', 'GP7', 'GP8', 'GP9', 'GP10', 'GP11', 'GP12', 'GP13', ]; const pins_bottom = [ 'GP14', 'GP15', 'GP16', 'GP17', 'GP18', ]; const pins_right = [ '5V', 'GND', 'RST', '3V3', 'GP29', 'GP28', 'GP27', 'GP26', 'GP25', 'GP23', 'GP22', 'GP21', 'GP20', 'GP19', ]; // Functions to map coordinates from a "pin grid" to actual X/Y coordinates. // The grid is defined as follows (assuming the board is in "up" orientation with the USB port on top): // - The X coordinates go from 0 (left) to 6 (right) // - The Y coordinates go from 0 (top) to 13 (bottom) // This means the pin rows are on these coordinates: // - Left side of pins: 0/0 to 0/13 // - Right side of pins: 6/0 to 6/13 // - Additional pins on the bottom (not counting the left and right pins): 1/13 to 5/13 // These grid coordinates have to be mapped to footprint coordinates so that the board is centered, meaning // the grid position 3/6.5 needs to be mapped to footprint coordinates 0/0. The grid is a standard 2.54mm grid. function pin_pos_x(pin_number) { // Use integers to avoid floating point issues return sign * (254 * (pin_number - 3)) / 100; } function pin_pos_y(pin_number) { // Use integers to avoid floating point issues return (254 * (pin_number - 7) + 127) / 100; } function pin_label(pin_name, pos_x, pos_y, pin_side) { let offset_x = 0; let offset_y = 0; let offset_rotation = 0; let justify = 'left'; if (pin_side === 'left') { offset_x = -1.3 * sign; justify = 'right'; } else if (pin_side === 'right') { offset_x = 1.3 * sign; } else if (pin_side === 'bottom') { offset_y = 1.7; offset_rotation = -90 * sign; } // Shorten the name of the "GPxx" pins to save a bit of space on the PCB if (pin_name.startsWith('GP')) { pin_name = pin_name.slice(2); } return ` (fp_text user ${pin_name} (at ${pin_pos_x(pos_x) + offset_x} ${pin_pos_y(pos_y) + offset_y} ${p.r + offset_rotation}) (unlocked yes) (layer ${side}.SilkS) (effects (font (size 0.8 0.8) (thickness 0.15)) (justify ${justify} ${mirror})) )`; } function pin_pad(pad_number, pos_x, pos_y, pin_name) { return ` (pad ${pad_number} thru_hole circle (at ${pin_pos_x(pos_x)} ${pin_pos_y(pos_y)} 0) (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.Mask) ${p[pin_name]} )`; } function render_pins() { let pin_label_body = ''; let pin_pad_body = ''; let pad_number = 1; for (let i = 0; i < pins_left.length; i++) { pin_label_body += pin_label(pins_left[i], 0, i, 'left'); pin_pad_body += pin_pad(pad_number++, 0, i, pins_left[i]); } for (let i = 0; i < pins_bottom.length; i++) { pin_label_body += pin_label(pins_bottom[i], 1 + i, 13, 'bottom'); pin_pad_body += pin_pad(pad_number++, 1 + i, 13, pins_bottom[i]); } for (let i = 0; i < pins_right.length; i++) { pin_label_body += pin_label(pins_right[i], 6, i, 'right'); pin_pad_body += pin_pad(pad_number++, 6, i, pins_right[i]); } return pin_pad_body + '\n' + pin_label_body; } return ` (module RP2040_PICO_MINI (layer F.Cu) (tedit 66FD3C6D) ${p.at /* parametric position */} ${'' /* footprint reference */} (fp_text reference "${p.ref}" (at 0 0) (layer ${side}.SilkS) ${p.ref_hide} (effects (font (size 1.27 1.27) (thickness 0.15))) ) (fp_text value "" (at 0 0) (layer ${side}.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))) ) ${'' /* component outline */} (fp_line (start -8.8 -18.0) (end 8.8 -18.0) (layer ${side}.SilkS) (width 0.15)) (fp_line (start 8.8 -18.0) (end 8.8 18.0) (layer ${side}.SilkS) (width 0.15)) (fp_line (start 8.8 18.0) (end -8.8 18.0) (layer ${side}.SilkS) (width 0.15)) (fp_line (start -8.8 18.0) (end -8.8 -18.0) (layer ${side}.SilkS) (width 0.15)) ${'' /* illustration of the USB port overhang */} (fp_line (start -4.3 -18.8) (end 4.3 -18.8) (layer Dwgs.User) (width 0.15)) (fp_line (start 4.3 -18.8) (end 4.3 -11.8) (layer Dwgs.User) (width 0.15)) (fp_line (start 4.3 -11.8) (end -4.3 -11.8) (layer Dwgs.User) (width 0.15)) (fp_line (start -4.3 -11.8) (end -4.3 -18.8) (layer Dwgs.User) (width 0.15)) ${'' /* pin labels and pads */} ${render_pins()} ) `; } }