Compare commits

...

6 commits

Author SHA1 Message Date
Stephan I. Böttcher
aba1d1fbfd src/README 2024-04-03 06:04:57 +00:00
Stephan I. Böttcher
c4d5c17549 Sensor reading from blinkenlights, ported to ATtiny424
This compiles with an up to date toolchain pulled from git.

TODO:
- Use the SPI hardware to talk to the sensor.
- Send results via UART hardware.
- Setup the watchdog.
- Control power to the RF transmitter
- Light the LED.
- Readout the ADCs, thermistors.
- Readout the internal temperature sensor.
2024-04-03 07:55:02 +02:00
Stephan I. Böttcher
4380513dfc copy bate.c from blinkenlights 2024-04-02 15:34:19 +02:00
Stephan I. Böttcher
c3f4e25dc3 bottom assy mirrored 2024-03-19 16:18:18 +01:00
Stephan I. Böttcher
bb25de31c0 gerbv: RGB fix, bottom assy 2024-03-19 16:17:11 +01:00
Stephan I. Böttcher
da3c5d6842 soldermask fix 2024-02-19 13:52:26 +01:00
12 changed files with 615 additions and 29 deletions

6
.gitignore vendored
View file

@ -10,3 +10,9 @@ gerber/*.gbr
gerber/*.cnc
gerber/*.zip
gerber/*.pdf
*.d
*.hex
*.map
*.o
*.s

60
gerber/turbo-bot.gvp Normal file
View file

@ -0,0 +1,60 @@
(gerbv-file-version! "2.0A")
(define-layer! 9 (cons 'filename "turbo.bottommask.gbr")
(cons 'inverted #t)
(cons 'visible #f)
(cons 'color #(0 57568 6070))
(cons 'alpha #(21588))
)
(define-layer! 8 (cons 'filename "turbo.bottom.gbr")
(cons 'visible #t)
(cons 'color #(45177 46748 64893))
)
(define-layer! 7 (cons 'filename "turbo.bottomsilk.gbr")
(cons 'visible #t)
(cons 'color #(0 0 0))
)
(define-layer! 6 (cons 'filename "turbo.top.gbr")
(cons 'visible #f)
(cons 'color #(65535 29244 28836))
(cons 'alpha #(42662))
)
(define-layer! 5 (cons 'filename "turbo.toppaste.gbr")
(cons 'visible #f)
(cons 'color #(65535 0 6760))
)
(define-layer! 4 (cons 'filename "turbo.topmask.gbr")
(cons 'inverted #t)
(cons 'visible #f)
(cons 'color #(0 64984 7760))
(cons 'alpha #(13364))
)
(define-layer! 3 (cons 'filename "turbo.plated-drill.cnc")
(cons 'visible #t)
(cons 'color #(61307 61307 61307))
(cons 'alpha #(65535))
(cons 'attribs (list
(list 'autodetect 'Boolean 1)
(list 'zero_suppression 'Enum 0)
(list 'units 'Enum 0)
(list 'digits 'Integer 4)
))
)
(define-layer! 2 (cons 'filename "turbo.topsilk.gbr")
(cons 'visible #f)
(cons 'color #(0 0 0))
(cons 'alpha #(55512))
)
(define-layer! 1 (cons 'filename "turbo.outline.gbr")
(cons 'visible #t)
(cons 'color #(0 0 0))
(cons 'alpha #(65535))
)
(define-layer! 0 (cons 'filename "turbo.fab.gbr")
(cons 'visible #f)
(cons 'color #(0 0 0))
(cons 'alpha #(65535))
)
(define-layer! -1 (cons 'filename "/home/falbala/stephan/eda/turbo_weather/gerber")
(cons 'color #(65535 65535 65535))
)
(set-render-type! 3)

BIN
gerber/turbo-bot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -2,31 +2,31 @@
(define-layer! 8 (cons 'filename "turbo.bottommask.gbr")
(cons 'inverted #t)
(cons 'visible #f)
(cons 'color #(0 57568 6070 21588))
(cons 'color #(0 57568 6070))
(cons 'alpha #(21588))
)
(define-layer! 7 (cons 'filename "turbo.bottom.gbr")
(cons 'visible #t)
(cons 'color #(45177 46748 64893 45489))
(cons 'color #(45177 46748 64893))
)
(define-layer! 6 (cons 'filename "turbo.top.gbr")
(cons 'visible #t)
(cons 'color #(65535 29244 28836 42662))
(cons 'color #(65535 29244 28836))
(cons 'alpha #(42662))
)
(define-layer! 5 (cons 'filename "turbo.toppaste.gbr")
(cons 'visible #t)
(cons 'color #(65535 0 6760 45489))
(cons 'color #(65535 0 6760))
)
(define-layer! 4 (cons 'filename "turbo.topmask.gbr")
(cons 'inverted #t)
(cons 'visible #f)
(cons 'color #(0 64984 7760 13364))
(cons 'color #(0 64984 7760))
(cons 'alpha #(13364))
)
(define-layer! 3 (cons 'filename "turbo.plated-drill.cnc")
(cons 'visible #t)
(cons 'color #(61307 61307 61307 65535))
(cons 'color #(61307 61307 61307))
(cons 'alpha #(65535))
(cons 'attribs (list
(list 'autodetect 'Boolean 1)
@ -37,20 +37,20 @@
)
(define-layer! 2 (cons 'filename "turbo.topsilk.gbr")
(cons 'visible #t)
(cons 'color #(0 0 0 55512))
(cons 'color #(0 0 0))
(cons 'alpha #(55512))
)
(define-layer! 1 (cons 'filename "turbo.outline.gbr")
(cons 'visible #t)
(cons 'color #(0 0 0 65535))
(cons 'color #(0 0 0))
(cons 'alpha #(65535))
)
(define-layer! 0 (cons 'filename "turbo.fab.gbr")
(cons 'visible #f)
(cons 'color #(0 0 0 65535))
(cons 'color #(0 0 0))
(cons 'alpha #(65535))
)
(define-layer! -1 (cons 'filename "/home/blaulicht/stephan/eda/turbo/gerber")
(cons 'color #(65535 65535 65535 0))
(cons 'color #(65535 65535 65535))
)
(set-render-type! 3)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
# PcbBOM Version 1.0
# Date: So 18 Feb 2024 12:56:25 GMT UTC
# Author:
# Date: Mo 19 Feb 2024 12:52:50 GMT UTC
# Author: Stephan Boettcher
# Title: TURBO - PCB BOM
# Quantity, Description, Value, RefDes
# --------------------------------------------

129
src/Makefile Normal file
View file

@ -0,0 +1,129 @@
PROJ=bate
default: all
all: $(PROJ).hex
SN_bate = 1
MCU_bate = attiny424
BATE_PERIOD=152
bate_CFLAGS = -DPERIOD=$(BATE_PERIOD)
SN_bate_wdt = $(SN_bate)
MCU_bate_wdt = $(MCU_bate)
bate_wdt_CFLAGS = $(bate_CFLAGS)
MCU = $(MCU_$(PROJ))
CC=avr-gcc -v -Wall -Wno-parentheses -MMD -std=c99 -O3 \
-mmcu=$(MCU) \
-funsigned-char \
-funsigned-bitfields \
-fpack-struct \
-fshort-enums \
-mtiny-stack \
-mint8 \
-fverbose-asm
SN = $(SN_$(PROJ))
CFLAGS = $($*_CFLAGS) $(DEBUG) -I. -DSN="$(SN)"
C_FILES = $(C_FILES_$(PROJ))
OBJS = $(patsubst %.c, %.o, $(C_FILES))
%.s: %.c
$(CC) $(CFLAGS) -S $<
%.o: %.c
$(CC) -g $(CFLAGS) -c $<
-include *.d
LDFLAGS =
%.elf: %.o $(OBJS)
$(CC) $(CFLAGS) -Wl,-Map=$*.map,--cref $^ --output $@ $(LDFLAGS)
OBJCOPY = avr-objcopy
%.hex: %.elf
$(OBJCOPY) -O ihex -R .eeprom $< $@
pMCU-attiny414 = t414
pMCU-attiny424 = t424
#
#avrdude> dump fuses
#>>> dump fuses 0x0 0x9
#
#Reading | ################################################## | 100% 0.13 s
#
#0000 00 00 7e ff ff f6 ff 00 00 |..~...... |
#
#avrdude>
# WDT
fuse0_bate= 0x00
# BOD
fuse1_bate= 0x00
# OSC, 20 MHz
fuse2_bate= 0x7e
# ???
fuse4_bate= 0xff
# SYS0 (default 0xf6) RESET, EEPROM erase
fuse5_bate= 0xf7
# SYS1 startup time (64ms)
fuse6_bate= 0xff
# APPEND
fuse7_bate= 0x00
# BOOTEND
fuse8_bate= 0x00
fuses_bate =$(patsubst %, 0x%, 00 00 7e ff ff f7 ff 00 00)
AVRDUDEPROG = avrdude
AVRDUDE = $(AVRDUDEPROG)
AVRDUDE_PROGRAMMER = serialupdi
AVRDUDE_PORT = /dev/ttyUSB1
AD = $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
id: $(PROJ).id
%.id:
$(AD) -B 5 -U fuses:v:"$(fuses_$*)":m
ad: $(PROJ).ad
%.ad:
$(AD) -v -t
%.burn: %.hex
$(AD) -U flash:w:$<
fuse: $(PROJ).fuse$F
%.fuse$F:
echo "$*: fuse$F = $(fuse$F_$*)"
[ -n "$(fuse$F_$*)" ] && $(AD) -B 5 -U fuse$F:w:$(fuse$F_$*):m
clean:
rm -f *.hex *.o *.s *.map *.elf *.d
.PHONY: eeprom.eeprom
eeprom.eeprom:
$(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-U eeprom:r:$@:r
%.eeprom.burn: %.eeprom
$(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-U 'eeprom:v:$<:r' \
|| $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-U 'eeprom:w:$<:r'

15
src/README.md Normal file
View file

@ -0,0 +1,15 @@
## Turbo Weather
The ATtiny424 µC requires an up to date toolchain
- binutits: `./configure --target=avr --program-prefix=avr-`
- gcc: `../gcc/configure --program-prefix=avr- --with-avrlibc --target=avr --enable-languages=c --disable-nls`
- avr-libc: `./configure --host=avr`
TODO:
- Use the SPI hardware to talk to the sensor.
- Send results via UART hardware.
- Setup the watchdog.
- Control power to the RF transmitter
- Light the LED.
- Readout the ADCs, thermistors.
- Readout the internal temperature sensor.

338
src/bate.c Normal file
View file

@ -0,0 +1,338 @@
//
// bate.c
//
// !!! int = int8_t
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#define Bit(x) (1<<(x))
#define BATE_PORT PORTA
#define SCK_PORT 3
#define DOUT_PORT 2
#define DIN_PORT 1
////////////////////////////////////////////////////////////////////////////////
//
// Timer1 generates a 32768 Hz clock on OC0A, PB0, MCLK_PORT, RES_PORT
// The nominal f_{clkio} is 9.6 MHz,
// f_{MCLK} needs to be 32768 Hz
// f_{tick} needs to be 2×f_{MCLK}
// Timer 1 TOP needs to be f_{clkio}/65536
#ifndef PERIOD
# define PERIOD 153
#endif
// Save the calibrated period in EEPROM
#define MCLK TCA0.SINGLE
static inline
void init_timer(uint8_t p)
{
if (p < 120 || p > 200)
p = PERIOD;
PORTB.DIRSET = Bit(0);
MCLK.INTCTRL = TCA_SINGLE_CMP0_bm;
MCLK.CMP0 = p;
MCLK.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc;
MCLK.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_FRQ_gc;
}
volatile uint8_t tick;
ISR(TCA0_CMP0_vect, ISR_NAKED)
{
__asm__ ("push r24" "\n\t"
"ldi r24,1" "\n\t"
"sts %[tick], r24" "\n\t"
"pop r24" "\n\t"
"reti" "\n"
:[tick] "+m" (tick)
);
}
/////////////////////////////////////////////////////////////////////////////
//
// Read data from an MS5534C pressure sensor
union {
uint8_t b[16];
uint16_t w[8];
struct {
uint16_t H[2];
uint16_t W[4];
uint16_t D[2];
};
struct {
uint16_t H1;
uint16_t H2;
uint16_t W1;
uint16_t W2;
uint16_t W3;
uint16_t W4;
uint16_t D1;
uint16_t D2;
};
} bate;
__attribute__ ((noinline, noclone))
static
uint8_t bate_bit(uint8_t r, uint8_t c, uint8_t ii)
{
#if 1
__asm__(
/*
; bate.c:136: if (c&ii)
and r22,r20 ; _1, ii
; bate.c:137: BATE_PORT.OUTSET = Bit(DIN_PORT);
ldi r25,lo8(2) ; tmp53,
; bate.c:136: if (c&ii)
cp r22, __zero_reg__ ; _1
breq .L2 ; ,
; bate.c:137: BATE_PORT.OUTSET = Bit(DIN_PORT);
sts 1029,r25 ; MEM[(struct PORT_t *)1024B].OUTSET, tmp53
; bate.c:140: if (BATE_PORT.IN & Bit(DOUT_PORT))
lds r25,1032 ; _2, MEM[(struct PORT_t *)1024B].IN
; bate.c:140: if (BATE_PORT.IN & Bit(DOUT_PORT))
sbrs r25,2 ; _2,
rjmp .L4 ;
.L7:
; bate.c:141: r |= ii;
or r24,r20 ; <retval>, ii
; bate.c:144: BATE_PORT.OUTSET = Bit(SCK_PORT);
ldi r25,lo8(8) ; tmp60,
sts 1029,r25 ; MEM[(struct PORT_t *)1024B].OUTSET, tmp60
; bate.c:145: BATE_PORT.OUTCLR = Bit(SCK_PORT);
sts 1030,r25 ; MEM[(struct PORT_t *)1024B].OUTCLR, tmp60
; bate.c:149: }
ret
.L2:
; bate.c:139: BATE_PORT.OUTCLR = Bit(DIN_PORT);
sts 1030,r25 ; MEM[(struct PORT_t *)1024B].OUTCLR, tmp55
; bate.c:140: if (BATE_PORT.IN & Bit(DOUT_PORT))
lds r25,1032 ; _2, MEM[(struct PORT_t *)1024B].IN
; bate.c:140: if (BATE_PORT.IN & Bit(DOUT_PORT))
sbrc r25,2 ; _2,
rjmp .L7 ;
.L4:
; bate.c:143: r &=~ ii;
com r20 ; _4
; bate.c:143: r &=~ ii;
and r24,r20 ; <retval>, _4
; bate.c:144: BATE_PORT.OUTSET = Bit(SCK_PORT);
ldi r25,lo8(8) ; tmp60,
sts 1029,r25 ; MEM[(struct PORT_t *)1024B].OUTSET, tmp60
; bate.c:145: BATE_PORT.OUTCLR = Bit(SCK_PORT);
sts 1030,r25 ; MEM[(struct PORT_t *)1024B].OUTCLR, tmp60
; bate.c:149: }
ret
*/
"ldi r25, %[DI]" "\n\t"
"and %[c], %[ii]" "\n\t"
"brne .+6" "\n\t"
"sts %[PC], r25" "\n\t"
"breq .+6" "\n\t"
"sts %[PS], r25" "\n\t"
"nop" "\n\t"
"lds r25, %[PI]" "\n\t"
"sbrc r25, %[DO]" "\n\t"
"or %[r], %[ii]" "\n\t"
"com %[ii]" "\n\t"
"sbrs r25, %[DO]" "\n\t"
"and %[r], %[ii]" "\n\t"
"ldi r25, %[SK]" "\n\t"
"sts %[PS], r25" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"sts %[PC], r25" "\n"
:[r] "+r" (r),
[c] "+r" (c)
:[ii] "r" (ii),
[PS] "n" (&BATE_PORT.OUTSET),
[PC] "n" (&BATE_PORT.OUTCLR),
[PI] "n" (&BATE_PORT.IN),
[DI] "n" (Bit(DIN_PORT)),
[DO] "n" (DOUT_PORT),
[SK] "n" (Bit(SCK_PORT))
: "r25", "memory"
);
#else
if (c&ii)
BATE_PORT.OUTSET = Bit(DIN_PORT);
else
BATE_PORT.OUTCLR = Bit(DIN_PORT);
if (BATE_PORT.IN & Bit(DOUT_PORT))
r |= ii;
else
r &=~ ii;
BATE_PORT.OUTSET = Bit(SCK_PORT);
BATE_PORT.OUTCLR = Bit(SCK_PORT);
#endif
return r;
}
__attribute__ ((noinline, noclone))
static
uint16_t bate_frame(uint16_t d, uint8_t n)
{
n--;
uint8_t c0 = d;
uint8_t c1 = d >> 8;
uint8_t r0;
uint8_t r1;
// Force r0 and r1 to be cleared before the switch. Else, the
// compiler generates extra jumps to clear r0 for each target.
__asm__("clr %[r0]" "\n\t"
"clr %[r1]" "\n"
:[r0] "=r" (r0),
[r1] "=r" (r1)
);
switch (n) {
case 15: r1 = bate_bit(r1, c1, 1<<7);
case 14: r1 = bate_bit(r1, c1, 1<<6);
case 13: r1 = bate_bit(r1, c1, 1<<5);
case 12: r1 = bate_bit(r1, c1, 1<<4);
case 11: r1 = bate_bit(r1, c1, 1<<3);
case 10: r1 = bate_bit(r1, c1, 1<<2);
case 9: r1 = bate_bit(r1, c1, 1<<1);
case 8: r1 = bate_bit(r1, c1, 1<<0);
case 7: r0 = bate_bit(r0, c0, 1<<7);
case 6: r0 = bate_bit(r0, c0, 1<<6);
case 5: r0 = bate_bit(r0, c0, 1<<5);
case 4: r0 = bate_bit(r0, c0, 1<<4);
case 3: r0 = bate_bit(r0, c0, 1<<3);
case 2: r0 = bate_bit(r0, c0, 1<<2);
case 1: r0 = bate_bit(r0, c0, 1<<1);
case 0: r0 = bate_bit(r0, c0, 1<<0);
}
return (uint16_t)r1<<8 | r0;
}
__attribute__ ((noinline, noclone))
static
void bate_wait()
{
uint16_t timeout = 3277; // 50ms
sei();
while (BATE_PORT.IN & Bit(DOUT_PORT)) {
if (tick) {
tick = 0;
if (!timeout)
break;
// wdt_reset();
timeout--;
}
}
cli();
}
static inline
void read_bate()
{
cli();
bate.H1 = 0x0001;
bate_frame(0xaaaa, 16);
bate_frame(0, 5);
bate_frame(0x3aa0, 14);
bate.W1 = bate_frame(0, 16);
bate_frame(0x3ac0, 14);
bate.W2 = bate_frame(0, 16);
bate_frame(0x3b20, 14);
bate.W3 = bate_frame(0, 16);
bate_frame(0x3b40, 14);
bate.W4 = bate_frame(0, 16);
bate_frame(0x0f40, 12);
bate.H1 = 0x0002;
bate_wait();
bate_frame(0,1);
bate.D1 = bate_frame(0, 16);
bate_frame(0x0f20, 12);
bate.H1 = 0x0003;
bate_wait();
bate_frame(0,1);
bate.D2 = bate_frame(0, 16);
bate.H1 = 0xba7e;
# ifndef WDT_TRIGGERED
bate.H2 += 1;
# endif
}
int main()
{
BATE_PORT.DIRSET = Bit(SCK_PORT) | Bit(DIN_PORT);
init_timer(0);
// send some MCLKs before we start
uint8_t mclk_delay = 0xff;
set_sleep_mode(SLEEP_MODE_IDLE);
while (1) {
sleep_enable();
sei();
sleep_cpu();
if (!tick)
continue;
tick = 0;
wdt_reset();
// uart();
// if (uart_busy())
// continue;
if (mclk_delay) {
mclk_delay--;
continue;
}
// if (!trigger) {
//# ifndef WDT_TRIGGERED
// // wait for PCINT on PORT_OUT
// continue;
//# else
// // power down, wait for the WDT
// MCUCR = Bit(SE) | SLEEP_MODE_PWR_DOWN;
// cli();
// sleep_cpu();
//# endif
// }
// trigger = 0;
// do a conversion and submit the result to uart()
read_bate();
mclk_delay = 0xff;
// send_bate();
}
}

2
src/bate_wdt.c Normal file
View file

@ -0,0 +1,2 @@
#define WDT_TRIGGERED 1
#include "bate.c"

36
src/eeprom.h Normal file
View file

@ -0,0 +1,36 @@
#include <stdint.h>
#include <avr/io.h>
#include <avr/eeprom.h>
// Entirely unsafe EEPROM access. Just wait 5ms between calls
// int = byte
static inline
void unsafe_eeprom_write_byte(uint8_t *addr, uint8_t data)
{
EEARL = (uint8_t)(uint16_t)addr;
EEDR = data;
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
}
static inline
uint8_t unsafe_eeprom_read_byte(uint8_t *addr)
{
EEARL = (uint8_t)(uint16_t)addr;
EECR |= (1<<EERE);
return EEDR;
}
static inline
void unsafe_eeprom_read_block(void *dest, void *src, uint8_t size)
{
uint8_t *d = dest;
uint8_t a = (uint8_t)(uint16_t)src;
while (size--) {
EEARL = a++;
EECR |= (1<<EERE);
*(d++) = EEDR;
}
}

View file

@ -1,4 +1,4 @@
# release: pcb v4.2.2-g125c85f1
# release: pcb 4.3.0
# To read pcb files, the pcb version (or the git source date) must be >= the file version
FileVersion[20180318]
@ -792,7 +792,7 @@ Symbol['~' 12.00mil]
SymbolLine[15.00mil 35.00mil 20.00mil 35.00mil 8.00mil]
SymbolLine[20.00mil 35.00mil 25.00mil 30.00mil 8.00mil]
)
Attribute("PCB::grid::unit" "mm")
Attribute("PCB::grid::unit" "mil")
Attribute("PCB::grid::size" "0.1000mm")
Via[19.4000mm 27.0000mm 0.9000mm 0.4000mm 0.6000mm 0.4000mm "" "thermal(2X,3X)"]
Via[25.8000mm 44.1000mm 0.9000mm 0.4000mm 0.6000mm 0.4000mm "" ""]
@ -887,21 +887,21 @@ Element["" "SIL_100_4" "U3" "WRL-10534" 7.7500mm 16.0000mm 3.2500mm -0.3000mm 0
Element["" "MS5534C" "U2" "MS5534C" 13.0000mm 43.7000mm -1.0000mm -1.0000mm 0 100 ""]
(
Pad[3.6000mm 1.9100mm 5.4000mm 1.9100mm 1.0000mm 20.00mil 1.5080mm "SCLK" "2" "square,edge2"]
Pad[3.6000mm 3.1800mm 5.4000mm 3.1800mm 1.0000mm 20.00mil 1.5080mm "GND" "1" "square,edge2"]
Pad[3.6000mm 0.6400mm 5.4000mm 0.6400mm 1.0000mm 20.00mil 1.5080mm "DOUT" "3" "square,edge2"]
Pad[3.6000mm -1.9100mm 5.4000mm -1.9100mm 1.0000mm 20.00mil 1.5080mm "MCLK" "5" "square,edge2"]
Pad[3.6000mm -3.1800mm 5.4000mm -3.1800mm 1.0000mm 20.00mil 1.5080mm "VDD" "6" "square,edge2"]
Pad[3.6000mm -0.6400mm 5.4000mm -0.6400mm 1.0000mm 20.00mil 1.5080mm "DIN" "4" "square,edge2"]
Pad[-1.9000mm -4.5000mm -1.9000mm -4.2000mm 1.0000mm 20.00mil 1.5080mm "7" "7" "square"]
Pad[-5.1000mm 1.9100mm -4.6000mm 1.9100mm 1.0000mm 20.00mil 1.5080mm "13" "13" "square"]
Pad[-5.1000mm 3.1800mm -4.8000mm 3.1800mm 1.0000mm 20.00mil 1.5080mm "14" "14" "square"]
Pad[-5.1000mm 0.6400mm -4.6000mm 0.6400mm 1.0000mm 20.00mil 1.5080mm "12" "12" "square"]
Pad[-5.1000mm -1.9100mm -4.6000mm -1.9100mm 1.0000mm 20.00mil 1.5080mm "10" "10" "square"]
Pad[-5.1000mm -3.1800mm -4.6000mm -3.1800mm 1.0000mm 20.00mil 1.5080mm "9" "9" "square"]
Pad[-5.1000mm -0.6400mm -4.6000mm -0.6400mm 1.0000mm 20.00mil 1.5080mm "11" "11" "square"]
Pad[-3.5000mm 4.2000mm -3.5000mm 4.5000mm 1.0000mm 20.00mil 1.5080mm "8" "8" "square,edge2"]
Pad[-3.6500mm 3.0500mm -3.6500mm 4.6500mm 27.56mil 20.00mil 1.2080mm "8" "8" "square,edge2"]
Pad[3.6000mm 1.9100mm 5.4000mm 1.9100mm 1.0000mm 20.00mil 46.00mil "SCLK" "2" "square,edge2"]
Pad[3.6000mm 3.1800mm 5.4000mm 3.1800mm 1.0000mm 20.00mil 46.00mil "GND" "1" "square,edge2"]
Pad[3.6000mm 0.6400mm 5.4000mm 0.6400mm 1.0000mm 20.00mil 46.00mil "DOUT" "3" "square,edge2"]
Pad[3.6000mm -1.9100mm 5.4000mm -1.9100mm 1.0000mm 20.00mil 46.00mil "MCLK" "5" "square,edge2"]
Pad[3.6000mm -3.1800mm 5.4000mm -3.1800mm 1.0000mm 20.00mil 46.00mil "VDD" "6" "square,edge2"]
Pad[3.6000mm -0.6400mm 5.4000mm -0.6400mm 1.0000mm 20.00mil 46.00mil "DIN" "4" "square,edge2"]
Pad[-1.9000mm -4.5000mm -1.9000mm -4.2000mm 1.0000mm 20.00mil 46.00mil "7" "7" "square"]
Pad[-5.1000mm 1.9100mm -4.6000mm 1.9100mm 1.0000mm 20.00mil 46.00mil "13" "13" "square"]
Pad[-5.1000mm 3.1800mm -4.8000mm 3.1800mm 1.0000mm 20.00mil 46.00mil "14" "14" "square"]
Pad[-5.1000mm 0.6400mm -4.6000mm 0.6400mm 1.0000mm 20.00mil 46.00mil "12" "12" "square"]
Pad[-5.1000mm -1.9100mm -4.6000mm -1.9100mm 1.0000mm 20.00mil 46.00mil "10" "10" "square"]
Pad[-5.1000mm -3.1800mm -4.6000mm -3.1800mm 1.0000mm 20.00mil 46.00mil "9" "9" "square"]
Pad[-5.1000mm -0.6400mm -4.6000mm -0.6400mm 1.0000mm 20.00mil 46.00mil "11" "11" "square"]
Pad[-3.5000mm 4.2000mm -3.5000mm 4.5000mm 1.0000mm 20.00mil 46.00mil "8" "8" "square,edge2"]
Pad[-3.6500mm 3.0500mm -3.6500mm 4.6500mm 27.56mil 20.00mil 46.00mil "8" "8" "square,edge2"]
ElementLine [-4.0000mm -4.5000mm 4.0000mm -4.5000mm 0.2000mm]
ElementLine [-4.5000mm -4.0000mm -4.5000mm 4.0000mm 0.2000mm]
ElementLine [-4.0000mm 4.5000mm 4.0000mm 4.5000mm 0.2000mm]