├── ArduiPi V1.1.brd ├── ArduiPi V1.1.sch ├── ArduiPi-V1.0-sch.png ├── ArduiPi-V1.1-brd.png ├── ArduiPi-V1.1-sch.png ├── ArduiPi-board.pdf ├── ArduiPi.brd ├── ArduiPi.pdf ├── ArduiPi.sch ├── Arduipi-V1.1-BOM.xlsx ├── README.md ├── arduino ├── bootloader │ └── optiboot_atmega328_115200_16MHz_D13_ProgFlash.hex └── test_firmware │ └── test_firmware.ino ├── raspberry ├── arduipi │ ├── Makefile │ └── arduipi.c ├── autoreset ├── avrdude-autoreset ├── reset-arduino └── test_board │ └── test_board.sh └── test_board_v1.3 ├── arduipi_test.pro ├── arduipi_test_board-board.pdf ├── arduipi_test_board.brd ├── arduipi_test_board.pdf └── arduipi_test_board.sch /ArduiPi-V1.0-sch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/ArduiPi-V1.0-sch.png -------------------------------------------------------------------------------- /ArduiPi-V1.1-brd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/ArduiPi-V1.1-brd.png -------------------------------------------------------------------------------- /ArduiPi-V1.1-sch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/ArduiPi-V1.1-sch.png -------------------------------------------------------------------------------- /ArduiPi-board.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/ArduiPi-board.pdf -------------------------------------------------------------------------------- /ArduiPi.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/ArduiPi.pdf -------------------------------------------------------------------------------- /Arduipi-V1.1-BOM.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/Arduipi-V1.1-BOM.xlsx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ArduiPi 2 | ======= 3 | 4 | ArduiPi is a shield for Raspberry Pi that brings Arduino low level extented I/O to Raspberry Pi. 5 | 6 | 7 | Detailed Description 8 | ==================== 9 | 10 | Everything is documented on this decicated [page][3] 11 | 12 | ![top](http://hallard.me/blog/wp-content/uploads/2013/10/ArduiPi-V10-front-e1381749389278-1024x662.jpg) 13 | ![bottom](http://hallard.me/blog/wp-content/uploads/2013/10/ArduiPi-V10-back-e1381749361529.jpg) 14 | 15 | **Schematic** 16 | ![schematic](https://raw.github.com/hallard/arduipi/master/ArduiPi-V1.1-sch.png) 17 | 18 | **Board** 19 | ![board] (https://raw.github.com/hallard/arduipi/master/ArduiPi-V1.1-brd.png) 20 | 21 | Check out news and other projects on my [blog][4] 22 | 23 | [3]: http://hallard.me/arduipi-the-shield-that-brings-arduino-to-raspberry-pi/ 24 | [4]: http://hallard.me 25 | 26 | -------------------------------------------------------------------------------- /arduino/bootloader/optiboot_atmega328_115200_16MHz_D13_ProgFlash.hex: -------------------------------------------------------------------------------- 1 | :107E0000112484B714BE81FFE8D085E080938100FF 2 | :107E100082E08093C00088E18093C10086E0809377 3 | :107E2000C20080E18093C4008EE0C1D0259A84E036 4 | :107E300020E33CEF91E0309385002093840096BBD3 5 | :107E4000B09BFECF1D9AA8958150A9F7EE24FF2480 6 | :107E5000AA24A394B5E0CB2EA1E1BA2EF3E0DF2E45 7 | :107E600098D0813461F495D0082FA7D0023829F139 8 | :107E7000013811F485E001C083E083D07FC08234F3 9 | :107E800011F484E103C0853419F485E09ED076C0F6 10 | :107E9000853579F47ED0E82EFF247BD0082F10E0C2 11 | :107EA000102F00270E291F29000F111F86D07801DF 12 | :107EB00065C0863521F484E088D080E0DECF84364A 13 | :107EC00009F040C066D065D0082F63D080E0E81686 14 | :107ED00080E7F80618F4F701D7BEE895C0E0D1E0D6 15 | :107EE00058D089930C17E1F7F0E0EF16F0E7FF06A2 16 | :107EF00018F0F701D7BEE89560D007B600FCFDCFBB 17 | :107F0000A701A0E0B1E02C9130E011968C9111977F 18 | :107F100090E0982F8827822B932B1296FA010C0160 19 | :107F2000A7BEE89511244E5F5F4FF1E0A038BF0770 20 | :107F300051F7F701C7BEE89507B600FCFDCFB7BE05 21 | :107F4000E8951CC0843761F424D023D0082F21D0B9 22 | :107F500034D0F70185917F0114D00150D1F70EC0C4 23 | :107F6000853739F42AD08EE10CD085E90AD08FE02C 24 | :107F700084CF813511F488E01AD01FD080E101D080 25 | :107F80006FCF982F8091C00085FFFCCF9093C600E3 26 | :107F900008951D9A8091C00087FFFCCF8091C0009A 27 | :107FA00084FD01C0A8958091C6001D9A0895E0E661 28 | :107FB000F0E098E1908380830895EBDF803219F040 29 | :107FC00088E0F5DFFFCF84E1DCCF1F93182FE1DFDE 30 | :107FD0001150E9F7F2DF1F910895282E80E0E7DFC6 31 | :067FE000EE27FF270994C3 32 | :027FFE0000057C 33 | :0400000300007E007B 34 | :00000001FF 35 | -------------------------------------------------------------------------------- /arduino/test_firmware/test_firmware.ino: -------------------------------------------------------------------------------- 1 | /* ======================================================================== 2 | Program : i2c_demo.ino 3 | Purpose : wait for i2c command, parse command and do action 4 | Version : 1.0 5 | Author : (c) Charles-Henri Hallard (http://hallard.me) 6 | Comments: this file belong to the ArduiPi project 7 | you will find more information on this project on my blog and github 8 | http://hallard.me/arduipi 9 | https://github.com/hallard/arduipi 10 | You can use or distribute this code unless you leave this comment 11 | too see this code correctly indented, please use Tab values of 2 12 | =========================================================================== */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // ====================================================================== 21 | // Constants definition 22 | // ====================================================================== 23 | #define SLAVE_ADDRESS 0x2a /* slave address,any number from 0x01 to 0x7F */ 24 | #define CMD_MAX_SIZE 16 /* max command size */ 25 | #define MAX_SENT_BYTES 3 26 | #define IDENTIFICATION 0x0D 27 | #define LOOP_DELAY 2000 /* by default blink led every 2 seconds */ 28 | #define BLINK_VALUE LOOP_DELAY / 2 29 | 30 | //#define DEBUG_SERIAL 31 | 32 | #define CMD_ARDUINO_PIN0 0x00 33 | #define CMD_ARDUINO_PIN18 0x12 34 | #define CMD_PORT_PIN0 0x00 35 | #define CMD_PORT_PIN7 0x07 36 | #define CMD_A0_ARDUINO 0xA0 37 | #define CMD_A6_ARDUINO 0xA6 38 | #define CMD_AVR_CMD_PORTB 0x1B 39 | #define CMD_AVR_CMD_PORTC 0x1C 40 | #define CMD_AVR_CMD_PORTD 0x1D 41 | #define CMD_AVR_CMD_DDRB 0x2B 42 | #define CMD_AVR_CMD_DDRC 0x2C 43 | #define CMD_AVR_CMD_DDRD 0x2D 44 | #define CMD_A0_AVR 0xC0 45 | #define CMD_A6_AVR 0xC6 46 | #define CMD_DDR0_PIN 0xD0 47 | #define CMD_DDR7_PIN 0xD7 48 | #define CMD_DDR_ARDUINO 0xDD 49 | #define CMD_PING 0xE0 50 | #define CMD_PORT_VALUE 0xF0 51 | #define CMD_DDR_VALUE 0xFD 52 | #define CMD_SEPARATOR 0xFF 53 | 54 | 55 | // Define various ADC prescaler 56 | #define PS_16 ((1 << ADPS2)) 57 | #define PS_32 ((1 << ADPS2) | (1 << ADPS0)) 58 | #define PS_64 ((1 << ADPS2) | (1 << ADPS1)) 59 | #define PS_128 ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)) 60 | 61 | #define pinLed 2 62 | 63 | // State machine for parsing received command 64 | enum parse_cmd { PARSE_CMD, PARSE_DATA, PARSE_NEXT, PARSE_ALL, PARSE_ERR, PARSE_OK }; 65 | 66 | // ====================================================================== 67 | // Volatile Global vars, may be used in interrupts 68 | // standard Global vars 69 | // ====================================================================== 70 | volatile byte g_i2c_rx_buf[CMD_MAX_SIZE]; // i2c command sent by the master 71 | volatile byte g_i2c_rx_len=0; // i2c command len sent by the master 72 | volatile byte g_spi_rx_buf[CMD_MAX_SIZE]; // spi command sent by the master 73 | volatile byte g_spi_rx_len=0; // spi command len sent by the master 74 | volatile byte g_ser_rx_buf[CMD_MAX_SIZE]; // serial command sent by the master 75 | volatile byte g_ser_rx_len=0; // serial command len sent by the master 76 | volatile boolean g_i2c_new = false; // new i2c command received to treat 77 | volatile boolean g_spi_new = false; // new spi command received to treat 78 | volatile boolean g_ser_new = false; // new serial command received to treat 79 | volatile byte g_i2c_tx_len = 0; // lenght of i2c data to return to master 80 | volatile byte g_spi_tx_len = 0; // lenght of spi data to return to master 81 | volatile byte g_ser_tx_len = 0; // lenght of serial data to return to master 82 | //volatile byte g_spi_pos = 0; // SPI pointer on receive buffer 83 | volatile byte g_cmd_err = 0; // global command error 84 | 85 | volatile long g_vcc = 0; // vcc value (read from ADC) 86 | 87 | byte g_i2c_tx_buf[CMD_MAX_SIZE]; // i2c buffer of returned data to master 88 | byte g_spi_tx_buf[CMD_MAX_SIZE]; // spi buffer of returned data to master 89 | byte g_ser_tx_buf[CMD_MAX_SIZE]; // serial buffer of returned data to master 90 | byte g_cmd_size; // new command size (can identify quickly simple command) 91 | byte g_cmd_send= false; // new data to send to master 92 | byte g_ping = 0x2a; // default ping value data to respond 93 | byte g_ds18b20[8] ; 94 | char buff[17]; 95 | 96 | 97 | DS2482 ds(0); 98 | 99 | // Test passed variable flags 100 | volatile boolean g_i2c_tested = false; // indicate that I2C test passed 101 | volatile boolean g_spi_tested = false; // indicate that SPI test passed 102 | volatile boolean g_ser_tested = false; // indicate that serial test passed 103 | volatile boolean g_1w_tested = false; // indicate that 1-Wire test passed 104 | volatile boolean g_analog_tested = false; // indicate that analog input test passed 105 | 106 | 107 | 108 | /* ====================================================================== 109 | Function: readADC 110 | Purpose : Read Analog Avlue 111 | Input : - 112 | Output : value readed 113 | Comments: Channel needed to read has been selected before 114 | ====================================================================== */ 115 | uint16_t readADC() 116 | { 117 | uint8_t low, high; 118 | 119 | // Start Convertion 120 | ADCSRA |= _BV(ADSC); 121 | 122 | // wait end 123 | while (bit_is_set(ADCSRA,ADSC)); 124 | 125 | // read low first 126 | low = ADCL; 127 | high = ADCH; 128 | 129 | return ((high << 8) | low); 130 | } 131 | 132 | /* ====================================================================== 133 | Function: setup 134 | Purpose : initialize arduino board 135 | Input : - 136 | Output : - 137 | Comments: 138 | ====================================================================== */ 139 | void setup() 140 | { 141 | long a, vcc; 142 | uint8_t i; 143 | 144 | 145 | #ifdef DEBUG_SERIAL 146 | Serial.begin(57600); 147 | Serial.println("Starting ArduiPi Test Program"); 148 | #else 149 | Serial.begin(9600); 150 | #endif 151 | 152 | pinMode(pinLed,OUTPUT); 153 | pinMode(2,OUTPUT); 154 | pinMode(3,OUTPUT); 155 | pinMode(4,OUTPUT); 156 | pinMode(5,OUTPUT); 157 | pinMode(6,OUTPUT); 158 | pinMode(7,OUTPUT); 159 | pinMode(8,OUTPUT); 160 | pinMode(9,OUTPUT); 161 | 162 | // clear the ADC prescaler defined by arduino env 163 | // enable ADC and set prescaler to 64 (250Khz) 164 | //ADCSRA &= ~PS_128; 165 | //ADCSRA |= PS_64; 166 | ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) ; 167 | 168 | // REFS1 REFS0 --> 0 1, AVcc internal ref. -Selects AVcc external reference 169 | // MUX3 MUX2 MUX1 MUX0 --> 1110 1.1V (VBG) -Selects channel 14, bandgap voltage, to measure 170 | ADMUX = (0< 6V 331 | if ((_a0 > 3100 && _a0 < 3500 ) && 332 | (_a1 > 1400 && _a1 < 1800 ) && 333 | (_a2 > 3200 && _a2 < 3400 ) && 334 | (_a3 > 6000 ) ) 335 | { 336 | g_analog_tested = true ; 337 | } 338 | else 339 | { 340 | g_analog_tested = false ; 341 | } 342 | 343 | // Check if we received Serial Data 344 | if (Serial.available() > 0) 345 | { 346 | c = Serial.read(); 347 | 348 | // check not overflowing, our buffer is enought ? 349 | if ( g_ser_rx_len < CMD_MAX_SIZE - 1 ) /* keep \0 of the serial string */ 350 | { 351 | // discard \r 352 | if (c != '\r' ) 353 | { 354 | // End of command 355 | if ( c == '\n' ) 356 | { 357 | // We received a string, end it without \r or \n 358 | g_ser_rx_buf[g_ser_rx_len] = 0x00; 359 | 360 | // Time to treat this command 361 | g_ser_new = true; 362 | } 363 | else 364 | { 365 | // Put char in buffer 366 | g_ser_rx_buf[g_ser_rx_len++] = c; 367 | } 368 | } 369 | } 370 | else 371 | { 372 | // overflow 373 | // force treating buffer 374 | g_ser_rx_buf[CMD_MAX_SIZE] = 0x00; 375 | 376 | // Time to treat this command 377 | g_ser_new = true; 378 | } 379 | } 380 | 381 | // wait 10 ms done waiting ADC to settle 382 | // delay(2); 383 | ldelay -= 10 ; 384 | 385 | // each 100 ms if we need to blink 386 | if ( (ldelay % 100) == 0 ) 387 | { 388 | if ( nblink > 0 ) 389 | { 390 | if ( (nblink % 2) == 0 ) 391 | { 392 | // light on the led 393 | digitalWrite(pin,1); 394 | 395 | } 396 | else 397 | { 398 | // light off the led 399 | digitalWrite(pin,0); 400 | 401 | // next led 402 | if (++pin > 9 ) 403 | pin = pinLed; 404 | } 405 | 406 | // we finished this blink 407 | if ( --nblink <= 0 ) 408 | { 409 | // restart loop delay without blink 410 | ldelay = LOOP_DELAY ; 411 | } 412 | } 413 | } 414 | } 415 | 416 | // ok we exited waiting delay for us 417 | // so, is there something to do for I2C ? 418 | if (g_i2c_new ) 419 | { 420 | // parse command and setup the blink 421 | nblink = parse_cmd( false ) * 2; 422 | 423 | // Reset buffer len; 424 | g_i2c_rx_len = 0; 425 | 426 | // we done what ne needed to on our received command 427 | g_i2c_new = false; 428 | } 429 | 430 | // so, is there something to do for SPI ? 431 | // for now do nothing except ACK for test firmware 432 | if ( g_spi_new ) 433 | { 434 | // parse command and setup the blink 435 | //nblink = parse_cmd( false ) * 2; 436 | 437 | // Spi is working 438 | g_spi_tested = true; 439 | 440 | // time to go, we are ready to send 441 | // g_spi_cmd_send = true ; 442 | 443 | // Reset buffer len; 444 | g_spi_rx_len = 0; 445 | 446 | // ack our received command 447 | g_spi_new = false; 448 | } 449 | 450 | // so, is there something to do for Serial ? 451 | if ( g_ser_new ) 452 | { 453 | // parse command and setup the blink 454 | nblink = parse_cmd( false ) * 2; 455 | 456 | // Reset buffer len; 457 | g_ser_rx_len = 0; 458 | 459 | // ack our received command 460 | g_ser_new = false; 461 | } 462 | 463 | // main loop delay expired, time to refresh screen 464 | if (ldelay == 0) 465 | { 466 | 467 | // Display only when received 1st i2c command from PI 468 | // this avoid I2C bus corruption 469 | if ( g_i2c_tested ) 470 | { 471 | // Set i2c to 400Khz 472 | // TWBR = 10 ; 473 | 474 | _millis = millis(); 475 | 476 | // Set i2c to 400Khz 477 | //TWBR = 10 ; 478 | 479 | _millis = millis(); 480 | 481 | SeeedGrayOled.setTextXY(1,0); 482 | SeeedGrayOled.putString("1Wire : "); 483 | SeeedGrayOled.putString(g_1w_tested ? "OK":"--"); 484 | 485 | SeeedGrayOled.setTextXY(2,0); 486 | SeeedGrayOled.putString("Analog : "); 487 | SeeedGrayOled.putString(g_analog_tested ? "OK":"--"); 488 | 489 | SeeedGrayOled.setTextXY(3,0); 490 | SeeedGrayOled.putString("I2C : "); 491 | SeeedGrayOled.putString(g_i2c_tested ? "OK":"--"); 492 | 493 | SeeedGrayOled.setTextXY(4,0); 494 | SeeedGrayOled.putString("SPI : "); 495 | SeeedGrayOled.putString(g_spi_tested ? "OK":"--"); 496 | 497 | SeeedGrayOled.setTextXY(5,0); 498 | SeeedGrayOled.putString("Serial : "); 499 | SeeedGrayOled.putString(g_ser_tested ? "OK":"--"); 500 | 501 | SeeedGrayOled.setTextXY(6,0); 502 | SeeedGrayOled.putString(" Got I2C "); 503 | 504 | 505 | /* 506 | SeeedGrayOled.setTextXY(2,0); 507 | SeeedGrayOled.putString("Vcc "); 508 | dtostrf(g_vcc/1000.0,4,2,buff); 509 | SeeedGrayOled.putString(buff); 510 | SeeedGrayOled.putString(" V"); 511 | 512 | SeeedGrayOled.setTextXY(3,0); 513 | SeeedGrayOled.putString("A0 "); 514 | dtostrf(_a0/1000.0,4,2,buff); 515 | SeeedGrayOled.putString(buff); 516 | SeeedGrayOled.putString(" V"); 517 | 518 | SeeedGrayOled.setTextXY(4,0); 519 | SeeedGrayOled.putString("A1 "); 520 | dtostrf(_a1/1000.0,4,2,buff); 521 | SeeedGrayOled.putString(buff); 522 | SeeedGrayOled.putString(" V"); 523 | 524 | SeeedGrayOled.setTextXY(5,0); 525 | SeeedGrayOled.putString("3V3 "); 526 | dtostrf(_a2/1000.0,4,2,buff); 527 | SeeedGrayOled.putString(buff); 528 | SeeedGrayOled.putString(" V"); 529 | 530 | SeeedGrayOled.setTextXY(6,0); 531 | SeeedGrayOled.putString("Vin "); 532 | dtostrf(_a3/1000.0,4,2,buff); 533 | SeeedGrayOled.putString(buff); 534 | SeeedGrayOled.putString(" V"); 535 | */ 536 | _millis = millis() - _millis; 537 | 538 | SeeedGrayOled.setTextXY(8,0); 539 | SeeedGrayOled.putString("took "); 540 | SeeedGrayOled.putNumber(_millis); 541 | SeeedGrayOled.putString(" ms"); 542 | 543 | // Set i2c to 100Khz 544 | // TWBR = 72 ; 545 | } 546 | /* 547 | SeeedGrayOled.setTextXY(2,0); 548 | SeeedGrayOled.putString("Vcc "); 549 | dtostrf(g_vcc/1000.0,4,2,buff); 550 | SeeedGrayOled.putString(buff); 551 | SeeedGrayOled.putString(" V"); 552 | 553 | SeeedGrayOled.setTextXY(3,0); 554 | SeeedGrayOled.putString("A0 "); 555 | dtostrf(_a0/1000.0,4,2,buff); 556 | SeeedGrayOled.putString(buff); 557 | SeeedGrayOled.putString(" V"); 558 | 559 | SeeedGrayOled.setTextXY(4,0); 560 | SeeedGrayOled.putString("A1 "); 561 | dtostrf(_a1/1000.0,4,2,buff); 562 | SeeedGrayOled.putString(buff); 563 | SeeedGrayOled.putString(" V"); 564 | 565 | SeeedGrayOled.setTextXY(5,0); 566 | SeeedGrayOled.putString("3V3 "); 567 | dtostrf(_a2/1000.0,4,2,buff); 568 | SeeedGrayOled.putString(buff); 569 | SeeedGrayOled.putString(" V"); 570 | 571 | SeeedGrayOled.setTextXY(6,0); 572 | SeeedGrayOled.putString("Vin "); 573 | dtostrf(_a3/1000.0,4,2,buff); 574 | SeeedGrayOled.putString(buff); 575 | SeeedGrayOled.putString(" V"); 576 | */ 577 | 578 | // Set i2c to 100Khz 579 | //TWBR = 72 ; 580 | 581 | // restart new loop 582 | ldelay = LOOP_DELAY ; 583 | 584 | // setup a new blink 585 | nblink = 2; 586 | } 587 | } 588 | 589 | 590 | 591 | 592 | /* ====================================================================== 593 | Function: parse_cmd 594 | Purpose : parse command received 595 | Input : flag indicating if we need to send return value (ie i2cget command) 596 | this flag is set when called from i2c interrupt 597 | Output : number of blink the alive led should blink 598 | Comments: 599 | ====================================================================== */ 600 | int parse_cmd( boolean is_get_command ) 601 | { 602 | volatile byte * prx ; // pointer on received buffer 603 | volatile byte * ptx; // pointer ou transmit buffer 604 | volatile byte * ptx_len; // pointer ou transmit buffer len 605 | volatile byte * prx_len; // pointer ou received buffer len 606 | 607 | static volatile uint8_t *pport ; // pointer to the port we will work on 608 | static volatile uint8_t *pddr ; // pointer to the port DDR we will work on 609 | static int i; 610 | static byte cmd; 611 | 612 | // pointer to the correct buffer 613 | if ( g_i2c_new ) 614 | { 615 | // i2c command 616 | prx = &g_i2c_rx_buf[0] ; 617 | ptx = &g_i2c_tx_buf[0] ; 618 | ptx_len = &g_i2c_tx_len ; 619 | prx_len = &g_i2c_rx_len ; 620 | } 621 | else if (g_spi_new) 622 | { 623 | // spi command 624 | prx = &g_spi_rx_buf[0] ; 625 | ptx = &g_spi_tx_buf[0] ; 626 | ptx_len = &g_spi_tx_len ; 627 | prx_len = &g_i2c_rx_len ; 628 | } 629 | else 630 | { 631 | // serial command 632 | prx = &g_ser_rx_buf[0] ; 633 | ptx = &g_ser_tx_buf[0] ; 634 | ptx_len = &g_ser_tx_len ; 635 | prx_len = &g_ser_rx_len ; 636 | } 637 | 638 | 639 | if ( ! is_get_command) 640 | { 641 | #ifdef DEBUG_SERIAL 642 | Serial.print(g_i2c_new ? "I2C":g_spi_new ? "SPI":"Serial"); 643 | Serial.print(" Command ("); 644 | Serial.print(*prx_len); 645 | Serial.print(") : "); 646 | 647 | // print all buffer received bytes 648 | for (i = 0; i <*prx_len ; i++) 649 | { 650 | Serial.print(*(prx+i), HEX); 651 | Serial.print(" "); 652 | } 653 | Serial.println(""); 654 | #endif 655 | } 656 | 657 | // get command received and point on next value 658 | cmd = *prx++; 659 | 660 | // Ping set return value command 661 | if ( cmd == CMD_PING ) 662 | { 663 | // Ping Get command 664 | if ( is_get_command ) 665 | { 666 | *ptx = g_ping ; 667 | *ptx_len = 1; 668 | 669 | // send response buffer quickly before debug 670 | if ( g_i2c_new) 671 | { 672 | Wire.write( (uint8_t *) ptx, *ptx_len); 673 | g_i2c_tested = true; 674 | } 675 | 676 | #ifdef DEBUG_SERIAL 677 | Serial.print("Ping = 0x"); 678 | Serial.println(*ptx, HEX); 679 | #endif 680 | } 681 | // Ping Set command 682 | else if ( *prx_len == 2 ) 683 | { 684 | // next ping will return the new data received 685 | g_ping = *prx; 686 | 687 | #ifdef DEBUG_SERIAL 688 | Serial.print("Set Ping return value to 0x"); 689 | Serial.println(g_ping, HEX); 690 | #endif 691 | } 692 | } // if ping command 693 | 694 | 695 | // Specific to test firmware, just send back what we get on serial 696 | // followed by :OK, then Pi should send back ACK 697 | if ( g_ser_new) 698 | { 699 | #ifdef DEBUG_SERIAL 700 | Serial.print("Serial received("); 701 | Serial.print(*prx_len); 702 | Serial.print(") : "); 703 | #endif 704 | 705 | // If we received ACK from PI, all is fine 706 | if (*(prx-1) == 'A' && *(prx+0) == 'C' && *(prx+1) == 'K' ) 707 | { 708 | g_ser_tested = true; 709 | } 710 | else 711 | { 712 | // print all buffer received bytes followed by OK 713 | for (i = 0; i <*prx_len ; i++) 714 | Serial.write(*(prx+i-1)); 715 | 716 | // Add the :OK at the end to tell Pi it's OKAY 717 | // After that, PI should send US ACK response 718 | Serial.println(":OK"); 719 | Serial.flush(); 720 | } 721 | 722 | // Nothing more to do 723 | return 0; 724 | } 725 | 726 | // Analog command 727 | else if ( (cmd >= CMD_A0_ARDUINO && cmd <= CMD_A6_ARDUINO) || (cmd >= CMD_A0_AVR && cmd <= CMD_A6_AVR) ) 728 | { 729 | if (cmd >= CMD_A0_AVR ) 730 | // convert avr command to arduino 731 | cmd -= CMD_A0_AVR; 732 | else 733 | // convert arduino command to analog port (0..5) 734 | cmd -= CMD_A0_ARDUINO; 735 | 736 | // Analog Get command 737 | if ( is_get_command ) 738 | { 739 | // A6 is not existing but we will use this command to return vcc value in mV 740 | if (cmd == CMD_A0_ARDUINO - CMD_A6_ARDUINO) 741 | { 742 | i = g_vcc; 743 | } 744 | else 745 | { 746 | // read data (could be optimized with direct avr register control) 747 | i = analogRead ( cmd ); 748 | } 749 | 750 | // LSB first 751 | *ptx = (byte) ( i & 0xFF); 752 | *(ptx+1) = (byte) ( ( i & 0xFF00) >> 8 ); 753 | *ptx_len = 2; 754 | 755 | // send I2C response buffer quickly before debug 756 | Wire.write( (uint8_t *) ptx, *ptx_len); 757 | 758 | // SPI response 759 | if ( g_spi_new) 760 | { 761 | // To DO SPI response 762 | } 763 | 764 | #ifdef DEBUG_SERIAL 765 | Serial.print("AnalogRead("); 766 | Serial.print( cmd ); 767 | Serial.print(") = "); 768 | Serial.println(i, HEX); 769 | #endif 770 | 771 | } 772 | } // if Analog Read command 773 | 774 | // Arduino pin command 775 | else if ( (cmd >= CMD_ARDUINO_PIN0 && cmd <= CMD_ARDUINO_PIN18) ) 776 | { 777 | // Arduino Get pin command 778 | if ( is_get_command ) 779 | { 780 | *ptx = digitalRead ( cmd); 781 | *ptx_len = 1; 782 | 783 | // send response buffer quickly before debug 784 | Wire.write( (uint8_t *) ptx, *ptx_len); 785 | 786 | #ifdef DEBUG_SERIAL 787 | Serial.print("DigitalRead("); 788 | Serial.print( cmd ); 789 | Serial.print(")="); 790 | Serial.println( *ptx ); 791 | #endif 792 | } 793 | // Arduino Set pin command (byte value) 794 | else if ( *prx_len == 2 ) 795 | { 796 | // 1st byte is DDR command 797 | if (*prx == INPUT || *prx==OUTPUT ) 798 | { 799 | digitalWrite ( cmd, *prx); 800 | #ifdef DEBUG_SERIAL 801 | Serial.print("DigitalWrite("); 802 | Serial.print( cmd ); 803 | Serial.print(", 0x"); 804 | Serial.print( *prx, HEX ); 805 | Serial.println(")"); 806 | #endif 807 | } 808 | } 809 | // Arduino Set pin direction command (word value) 810 | else if ( *prx_len == 3 ) 811 | { 812 | // 1st byte is DDR command 813 | if (*prx == CMD_DDR_ARDUINO) 814 | { 815 | // 2nd byte is pin mode value 816 | if (*(prx+1) >= INPUT || *(prx+1) <= INPUT_PULLUP) 817 | { 818 | pinMode ( cmd, *(prx+1) ); 819 | #ifdef DEBUG_SERIAL 820 | Serial.print("pinMode("); 821 | Serial.print( cmd ); 822 | Serial.print(", 0x"); 823 | Serial.print( *prx, HEX ); 824 | Serial.print( "," ); 825 | Serial.print( *(prx+1) ); 826 | Serial.println(")"); 827 | #endif 828 | } 829 | } 830 | } 831 | } // if Arduino pin command 832 | 833 | // AVR port value 834 | else if ( cmd >= CMD_AVR_CMD_PORTB && cmd <= CMD_AVR_CMD_PORTD ) 835 | { 836 | // on which port and DDR we will work 837 | if ( cmd == CMD_AVR_CMD_PORTB ) 838 | { 839 | pport = &PORTB; 840 | } 841 | else if ( cmd == CMD_AVR_CMD_PORTC ) 842 | { 843 | pport = &PORTC; 844 | } 845 | else 846 | { 847 | pport = &PORTD; 848 | } 849 | 850 | // port Get command 851 | if ( is_get_command) 852 | { 853 | // now we know the port, get port value 854 | *ptx = *pport ; 855 | *ptx_len = 1; 856 | 857 | // send response buffer quickly before debug 858 | Wire.write( (uint8_t *) ptx, *ptx_len); 859 | 860 | } 861 | // port Set command 862 | else 863 | { 864 | *pport = *prx; 865 | } 866 | 867 | #ifdef DEBUG_SERIAL 868 | Serial.print("Port "); 869 | Serial.write( 'B' + (cmd - CMD_AVR_CMD_PORTB)); 870 | if (is_get_command) 871 | { 872 | Serial.print(" value is 0x"); 873 | Serial.println(*ptx, HEX); 874 | } 875 | else 876 | { 877 | Serial.print(" Set to 0x"); 878 | Serial.println(*prx, HEX); 879 | } 880 | #endif 881 | 882 | } // if AVR port value 883 | 884 | // AVR DDR port value 885 | else if ( cmd >= CMD_AVR_CMD_DDRB && cmd <= CMD_AVR_CMD_DDRD ) 886 | { 887 | // on which port and DDR we will work 888 | if ( cmd == CMD_AVR_CMD_DDRB ) 889 | { 890 | pddr = &DDRB; 891 | } 892 | else if ( cmd == CMD_AVR_CMD_DDRC ) 893 | { 894 | pddr = &DDRC; 895 | } 896 | else 897 | { 898 | pddr = &DDRD; 899 | } 900 | // port Get command 901 | if ( is_get_command) 902 | { 903 | // now we know the port, get port value 904 | *ptx = *pddr ; 905 | *ptx_len = 1; 906 | 907 | // send response buffer quickly before debug 908 | Wire.write( (uint8_t *) ptx, *ptx_len); 909 | 910 | #ifdef DEBUG_SERIAL 911 | Serial.print("DDR "); 912 | Serial.write( 'B' + (cmd - CMD_AVR_CMD_DDRB) ); 913 | Serial.print(" value is 0x"); 914 | Serial.println(*ptx, HEX); 915 | #endif 916 | 917 | } 918 | // AVR Set port direction (byte value) 919 | else if ( *prx_len == 2 ) 920 | { 921 | *pddr = *prx; 922 | 923 | #ifdef DEBUG_SERIAL 924 | Serial.print("DDR "); 925 | Serial.write( 'B' + (cmd - CMD_AVR_CMD_DDRB) ); 926 | Serial.print(" Set to 0x"); 927 | Serial.println(*prx, HEX); 928 | #endif 929 | 930 | } 931 | // AVR Set port pin direction command (word value) 932 | else if ( *prx_len == 3 ) 933 | { 934 | // 1st byte is port pin 935 | if (*prx >= CMD_PORT_PIN0 && *prx <= CMD_PORT_PIN7) 936 | { 937 | // get bit asked 938 | i = ( 1 << (*prx) ); 939 | 940 | // if 2nd byte is DDR value 1 941 | if (*(prx+1) == 0x01) 942 | { 943 | *pddr |= i; 944 | #ifdef DEBUG_SERIAL 945 | Serial.print("Set Pin DDR"); 946 | Serial.print(cmd); 947 | Serial.print(" (|=0x"); 948 | Serial.print( i, HEX ); 949 | Serial.println(")"); 950 | #endif 951 | } 952 | // reset pin direction 953 | // if 2nd byte is DDR value 1 954 | else if (*(prx+1) == 0x00) 955 | { 956 | *pport &= ~i; 957 | #ifdef DEBUG_SERIAL 958 | Serial.print("Clear Pin DDR "); 959 | Serial.print(cmd); 960 | Serial.print(" (&=0x"); 961 | Serial.print( ~i, HEX ); 962 | Serial.println(")"); 963 | #endif 964 | } 965 | } 966 | } 967 | } // if AVR DDR port value 968 | 969 | // PWM command 970 | else if ( (cmd >= CMD_A0_ARDUINO && cmd <= CMD_A6_ARDUINO) || (cmd >= CMD_A0_AVR && cmd <= CMD_A6_AVR) ) 971 | { 972 | /* TO DO 973 | */ 974 | } 975 | 976 | 977 | } 978 | 979 | 980 | /* ====================================================================== 981 | Function: requesti2cEvent 982 | Purpose : i2c ISR called, master want some data from us, just send it 983 | Input : - 984 | Output : - 985 | Comments: ISR code, should be as small as possible, avoid print, println 986 | or consuming code. If you need heavy treatment, put a flag and 987 | do it async in the main loop 988 | you can also send response as fast as possible and do print after 989 | this oode is called when we issue a i2cget command from Raspberry 990 | so we need to answer in this routine, we can't do it async 991 | !!! here we treat only response to send back to master !!! 992 | ====================================================================== */ 993 | void requesti2cEvent() 994 | { 995 | static int i; 996 | volatile static byte cmd ; 997 | volatile uint8_t *pport ; // pointer to the port we will work on 998 | volatile uint8_t *pddr ; // pointer to the port DDR we will work on 999 | 1000 | 1001 | // we received new data and it is a read command (1 byte data) 1002 | if ( g_i2c_new && g_i2c_rx_len == 1) 1003 | { 1004 | parse_cmd( true) ; 1005 | 1006 | // we done what ne needed to on our received command 1007 | g_i2c_new = false; 1008 | } 1009 | 1010 | // we validated the response 1011 | if( g_i2c_tx_len >0) 1012 | { 1013 | // send response buffer 1014 | //Wire.write(g_i2c_tx_buf, g_i2c_tx_len); 1015 | } 1016 | else 1017 | { 1018 | #ifdef SERIAL_DEBUG 1019 | Serial.println("requesti2cEvent No data"); 1020 | #endif 1021 | } 1022 | } 1023 | 1024 | // 1025 | /* ====================================================================== 1026 | Function: receivei2cEvent 1027 | Purpose : i2c ISR called, master sended some data to us, just grab it 1028 | Input : number of byte received 1029 | Output : - 1030 | Comments: ISR code, should be as small as possible, avoid print, println 1031 | or consuming code. If you need heavy treatment, put a flag and 1032 | do it in the main loop 1033 | ====================================================================== */ 1034 | void receivei2cEvent(int nbyte) 1035 | { 1036 | static byte p; 1037 | 1038 | // if 0 then result of i2c detect from Pi so it works 1039 | if (nbyte == 0) 1040 | g_i2c_tested = true; 1041 | 1042 | 1043 | // check not overflowing, our buffer is enought ? 1044 | if ( nbyte < CMD_MAX_SIZE && nbyte > 0) 1045 | { 1046 | // Grab all the command bytes into the receive buffer 1047 | for (p = 0; p < nbyte; p++) 1048 | { 1049 | g_i2c_rx_buf[p] = Wire.read(); 1050 | } 1051 | 1052 | // len of data received 1053 | g_i2c_rx_len = nbyte; 1054 | 1055 | // init response len 1056 | g_i2c_tx_len = 0; 1057 | 1058 | // get out quickly from isr 1059 | // we will do some long time instruction 1060 | // such as display in the mail loop 1061 | g_i2c_new = true; 1062 | 1063 | } 1064 | else 1065 | { 1066 | // flush the receive buffer 1067 | while(Wire.available()) 1068 | Wire.read(); 1069 | 1070 | // indicate a error 1071 | g_cmd_err++; 1072 | } 1073 | } 1074 | 1075 | /* ====================================================================== 1076 | Function: spi interrupt vector 1077 | Purpose : called when received spi data byte 1078 | Input : - 1079 | Output : - 1080 | Comments: ISR code, should be as small as possible, avoid print, println 1081 | or consuming code. If you need heavy treatment, put a flag and 1082 | do it in the main loop 1083 | 1084 | !!!!!!!!!!!!!!!!! SPI SPECIFIC !!!!!!!!!!!!! 1085 | The slave cannot respond to an incoming byte at the same moment 1086 | The response has to be in the next exchange. 1087 | This is because the bits which are being sent, and the bits 1088 | which are being received, are being sent simultaneously. 1089 | Thus master has to talk to the slave two times, what we decided here 1090 | - Master send the string command according API 1091 | - Slave ACK the command with 0xAA return value 1092 | - Master wait slave to be ok to send back response 1093 | - Master send the 0x55 to tell the slave now he needs answer 1094 | - Slave send back the string response 1095 | 1096 | ====================================================================== */ 1097 | ISR (SPI_STC_vect) 1098 | { 1099 | static byte p; 1100 | 1101 | // get value from SPI Data Register 1102 | p = SPDR; 1103 | 1104 | // SPI next response should always be ping response 1105 | SPDR = g_ping; 1106 | 1107 | // indicate main loop we received a byte 1108 | g_spi_new = true; 1109 | 1110 | /* 1111 | // To be sure we have finished processing our prevoius command 1112 | if ( g_spi_new == false); 1113 | { 1114 | //Serial.print(p, HEX); 1115 | 1116 | // do we want a response from our previous command ? 1117 | if (g_spi_rx_len==0 ) 1118 | { 1119 | SPDR = 0x00 ; 1120 | } 1121 | 1122 | // if buffer is not full 1123 | if (g_spi_rx_len < CMD_MAX_SIZE) 1124 | { 1125 | // New command to process 1126 | if (p != CMD_SEPARATOR) 1127 | { 1128 | // put received data into buffer 1129 | g_spi_rx_buf[g_spi_rx_len++] = p; 1130 | 1131 | if ( g_spi_rx_len == 1 && p==CMD_PING ) 1132 | { 1133 | SPDR = g_ping ; 1134 | } 1135 | 1136 | 1137 | } 1138 | else 1139 | { 1140 | // Send magic code to master indicating we will work 1141 | //SPDR = 0xAA; 1142 | 1143 | // Ping set return value command 1144 | // if ( g_spi_rx_buf[0]==CMD_PING ) 1145 | // { 1146 | // SPDR = g_ping ; 1147 | // } 1148 | 1149 | g_spi_new = true; 1150 | } 1151 | } 1152 | } 1153 | */ 1154 | } 1155 | 1156 | /* ====================================================================== 1157 | Function: ISR issued from ADC 1158 | Purpose : Interrupt routine trigerred when ADC complete 1159 | Input : - 1160 | Output : - 1161 | Comments: ISR code, should be as small as possible, avoid print, println 1162 | or consuming code. If you need heavy treatment, put a flag and 1163 | do it in the main loop 1164 | ====================================================================== */ 1165 | /* 1166 | ISR(ADC_vect) 1167 | { 1168 | // Done reading 1169 | readFlag = 1; 1170 | 1171 | // Must read low first 1172 | analogVal = ADCL | (ADCH << 8); 1173 | 1174 | // Not needed because free-running mode is enabled. 1175 | // Set ADSC in ADCSRA (0x7A) to start another ADC conversion 1176 | // ADCSRA |= B01000000; 1177 | } 1178 | */ 1179 | -------------------------------------------------------------------------------- /raspberry/arduipi/Makefile: -------------------------------------------------------------------------------- 1 | #********************************************************************* 2 | # This is the makefile for the ArduiPi program 3 | # 4 | # 02/18/2013 Charles-Henri Hallard (http://hallard.me) 5 | # Modified for compiling and use on Raspberry ArduiPi Board 6 | # ArduiPi project documentation http://hallard.me/arduipi 7 | # 8 | # ********************************************************************* 9 | 10 | # Where you want it installed when you do 'make install' 11 | PREFIX=/usr/local 12 | 13 | # The recommended compiler flags for the Raspberry Pi 14 | CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s 15 | 16 | # Program to compile 17 | PROGRAM=arduipi 18 | 19 | # make all 20 | all: ${PROGRAM} 21 | 22 | ${PROGRAM}: ${SOURCE} 23 | gcc ${CCFLAGS} -Wall $@.c -o $@ 24 | 25 | clean: 26 | rm -rf $(PROGRAM) 27 | 28 | # Install the executable 29 | install: 30 | @if ( test ! -d $(PREFIX) ) ; then mkdir -p $(PREFIX) ; fi 31 | @if ( test ! -d $(PREFIX)/bin ) ; then mkdir -p $(PREFIX)/bin ; fi 32 | @echo "[Install $(PROGRAM)]"; 33 | @install -m 0755 $(PROGRAM) $(PREFIX)/bin 34 | 35 | # Uninstall the executable 36 | uninstall: 37 | @echo "[Uninstall $(PROGRAM)]"; 38 | @rm -rf $(PREFIX)/bin/$(PROGRAM) ; 39 | 40 | .PHONY: install 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /raspberry/arduipi/arduipi.c: -------------------------------------------------------------------------------- 1 | /* ====================================================================== 2 | Program : arduipi.c 3 | Purpose : arduipi demo program for ArduiPi project 4 | Version : 1.0 5 | Author : (c) Charles-Henri Hallard 6 | Comments: This program is written for the open source project ArduiPi 7 | you can find documentation and all code on my github located at 8 | https://github.com/hallard/arduipi 9 | 10 | You can use or distribute this code unless you leave this comment 11 | too see this code correctly indented, please use tab values of 2 12 | 13 | ====================================================================== */ 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | // ---------------- 36 | // Constants 37 | // ---------------- 38 | #define true 1 39 | #define false 0 40 | 41 | // Program name and version 42 | #define PRG_NAME "arduipi" 43 | #define PRG_VERSION "1.0" 44 | 45 | // Define i2c default device & address 46 | #define I2C_DEVICE_0 "/dev/i2c-0" 47 | #define I2C_DEVICE_1 "/dev/i2c-1" 48 | #define I2C_ADDRESS 0x2A 49 | 50 | // Define spi default device 51 | #define SPI_DEVICE_1 "/dev/spidev0.1" 52 | #define SPI_DEVICE_0 "/dev/spidev0.0" 53 | #define SPI_MODE 0 54 | #define SPI_BITS_WORD 8 55 | #define SPI_SPEED 1000000 56 | #define SPI_DELAY 0 57 | 58 | // Arduipi defined command 59 | #define ARDUIPI_CMD_PING 0xe0 60 | 61 | // receive buffer size 62 | #define BUFFER_SIZE 32 63 | 64 | // Program mode function 65 | enum mode_e { MODE_QUICK_ACK, MODE_READ_ACK, MODE_SET, MODE_GET, MODE_GET_WORD }; 66 | 67 | // Program protocol 68 | enum proto_e { PROTO_I2C, PROTO_SPI, PROTO_SERIAL }; 69 | 70 | // Config Option structure parameters 71 | struct 72 | { 73 | char port[128]; // device name ex:/dev/i2c-0 74 | char data[BUFFER_SIZE]; // Data buffer 75 | int datasize; 76 | int address; // i2c slave address 77 | int mode; // program mode functionnality 78 | char *mode_str; // program mode functionnality human readable 79 | int proto; // protocol used 80 | char *proto_str; // protocol mode functionnality human readable 81 | uint8_t spi_mode; 82 | uint8_t spi_bits; // spi bits per word 83 | uint32_t spi_speed ; // spi frequency max 84 | uint16_t spi_delay; // spi delay 85 | int verbose; // verbose mode, speak more to user 86 | int hexout; 87 | 88 | } opts = { 89 | .port = "", 90 | .data = "", 91 | .datasize =0, 92 | .address = I2C_ADDRESS, 93 | .mode = MODE_QUICK_ACK, 94 | .mode_str = "ack", 95 | .proto = PROTO_I2C, 96 | .proto_str = "i2c", 97 | .spi_mode = SPI_MODE, 98 | .spi_bits = SPI_BITS_WORD, 99 | .spi_speed = SPI_SPEED, 100 | .spi_delay = SPI_DELAY, 101 | .verbose = false, 102 | .hexout = false 103 | }; 104 | 105 | 106 | // ====================================================================== 107 | // Global vars 108 | // ====================================================================== 109 | int g_fd_device; // handle 110 | int g_exit_pgm; // indicate end of the program 111 | int g_pi_rev; // Rasberry Pi Board Revision 112 | 113 | /* ====================================================================== 114 | Function: log_syslog 115 | Purpose : write event to syslog 116 | Input : stream to write if needed 117 | string to write in printf format 118 | printf other arguments 119 | Output : - 120 | Comments: 121 | ====================================================================== */ 122 | void log_syslog( FILE * stream, const char *format, ...) 123 | { 124 | static char tmpbuff[512]=""; 125 | va_list args; 126 | 127 | // do a style printf style in ou buffer 128 | va_start (args, format); 129 | vsnprintf (tmpbuff, sizeof(tmpbuff), format, args); 130 | tmpbuff[sizeof(tmpbuff) - 1] = '\0'; 131 | va_end (args); 132 | 133 | // Write to logfile 134 | openlog( PRG_NAME, LOG_PID|LOG_CONS, LOG_USER); 135 | syslog(LOG_INFO, tmpbuff); 136 | closelog(); 137 | 138 | // stream passed ? write also to it 139 | if ((stream && opts.verbose) || stream == stdout ) 140 | { 141 | fprintf(stream, tmpbuff); 142 | fflush(stream); 143 | } 144 | } 145 | 146 | 147 | /* ====================================================================== 148 | Function: clean_exit 149 | Purpose : exit program 150 | Input : exit code 151 | Output : - 152 | Comments: 153 | ====================================================================== */ 154 | void clean_exit (int exit_code) 155 | { 156 | // close i2c if opened 157 | if (g_fd_device) 158 | { 159 | // then close 160 | close(g_fd_device); 161 | } 162 | 163 | if ( exit_code != EXIT_SUCCESS) 164 | log_syslog(stdout, "Closing %s due to error\n", PRG_NAME); 165 | 166 | exit(exit_code); 167 | } 168 | 169 | /* ====================================================================== 170 | Function: fatal 171 | Purpose : exit program due to a fatal error 172 | Input : string to write in printf format 173 | printf other arguments 174 | Output : - 175 | Comments: 176 | ====================================================================== */ 177 | void fatal (const char *format, ...) 178 | { 179 | char tmpbuff[512] = ""; 180 | va_list args; 181 | 182 | va_start(args, format); 183 | vsnprintf(tmpbuff, sizeof(tmpbuff), format, args); 184 | tmpbuff[sizeof(tmpbuff) - 1] = '\0'; 185 | va_end(args); 186 | 187 | // Write to logfile 188 | openlog( PRG_NAME, LOG_PID | LOG_CONS, LOG_USER); 189 | syslog(LOG_INFO, tmpbuff); 190 | closelog(); 191 | 192 | fprintf(stderr,"\r\nFATAL: %s \r\n", tmpbuff ); 193 | fflush(stderr); 194 | 195 | clean_exit(EXIT_FAILURE); 196 | } 197 | 198 | 199 | /* ====================================================================== 200 | Function: isr_handler 201 | Purpose : Interrupt routine Code for signal 202 | Input : - 203 | Output : - 204 | Comments: 205 | ====================================================================== */ 206 | void isr_handler (int signum) 207 | { 208 | // Does we received CTRL-C ? 209 | if ( signum==SIGINT || signum==SIGTERM) 210 | { 211 | // Indicate we want to quit 212 | g_exit_pgm = true; 213 | 214 | log_syslog(NULL, "Received SIGINT/SIGTERM"); 215 | } 216 | // Our receive buffer is full 217 | else if (signum == SIGIO) 218 | { 219 | log_syslog(NULL, "Received SIGIO"); 220 | 221 | } 222 | 223 | } 224 | 225 | /* ====================================================================== 226 | Function: i2c_init 227 | Purpose : initialize i2c port for communication 228 | Input : - 229 | Output : i2c Port Handle 230 | Comments: - 231 | ====================================================================== */ 232 | int i2c_init(void) 233 | { 234 | int fd ; 235 | 236 | // Open i2c bus 237 | if ( (fd = open(opts.port, O_RDWR)) < 0 ) 238 | fatal( "i2c_init device %s: %s", opts.port, strerror(errno)); 239 | 240 | // set slave address 241 | if ( ioctl(fd, I2C_SLAVE, opts.address) < 0) 242 | fatal( "i2c_init error setting slave address 0x%02X : %s", opts.address, strerror(errno)); 243 | 244 | return fd ; 245 | } 246 | 247 | /* ====================================================================== 248 | Function: spi_init 249 | Purpose : initialize spi port for communication 250 | Input : - 251 | Output : spi Port Handle 252 | Comments: - 253 | ====================================================================== */ 254 | int spi_init(void) 255 | { 256 | int fd ; 257 | int ret; 258 | uint8_t mode; // spi mode 259 | uint8_t bits; // spi bits per word 260 | 261 | // Open spi bus 262 | if ( (fd = open(opts.port, O_RDWR)) < 0 ) 263 | fatal( "spi_init %s: %s", opts.port, strerror(errno)); 264 | 265 | // set spi mode 266 | ret = ioctl(fd, SPI_IOC_WR_MODE, &opts.spi_mode); 267 | if (ret == -1) 268 | fatal( "spi_init %s : error writing mode %02X : %s", opts.port, opts.spi_mode, strerror(errno)); 269 | 270 | // read the value we set and check it is the same 271 | ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); 272 | if (ret == -1 || mode !=opts.spi_mode ) 273 | fatal( "spi_init %s : error checking mode %02X, found %02X : %s", opts.port, opts.spi_mode, mode, strerror(errno)); 274 | 275 | // set spi bits per word 276 | ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &opts.spi_bits); 277 | if (ret == -1) 278 | fatal( "spi_init %s : error setting write bits per word %d : %s", opts.port, opts.spi_bits, strerror(errno)); 279 | 280 | // read the value we set and check it is the same 281 | ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); 282 | if (ret == -1 || bits != opts.spi_bits ) 283 | fatal( "spi_init %s : error checking bits per word %d, found %d : %s", opts.port, opts.spi_bits, bits, strerror(errno)); 284 | 285 | // set spi max speed hz 286 | ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &opts.spi_speed); 287 | if (ret == -1) 288 | fatal( "spi_init %s : error setting write max speed %d Hz: %s", opts.port, opts.spi_speed, strerror(errno)); 289 | 290 | // read the value we set and check it is the same 291 | ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &opts.spi_speed); 292 | if (ret == -1 ) 293 | fatal( "spi_init %s : error setting read max speed %d KHz, %s", opts.port, opts.spi_speed, strerror(errno)); 294 | 295 | return fd ; 296 | } 297 | 298 | /* ====================================================================== 299 | Function: charToHexDigit 300 | Purpose : convert char to hex value 301 | Input : char 302 | Output : byte value 303 | Comments: 304 | ====================================================================== */ 305 | unsigned char charToHexDigit(char c) 306 | { 307 | unsigned char ret ; 308 | 309 | // parse to lower case 310 | if (c >= 'A' && c <= 'F') 311 | c= c - 'A' + 'a'; 312 | 313 | if (c >= 'a') 314 | ret = c - 'a' + 10; 315 | else 316 | ret = c - '0'; 317 | 318 | return (ret); 319 | } 320 | 321 | /* ====================================================================== 322 | Function: get_pi_version 323 | Purpose : Get Raspberry Pi Revision Board Version 324 | Input : - 325 | Output : Raspberry Pi revision (1 or 2) 326 | Comments: 327 | ====================================================================== */ 328 | // Get raspberry PI model version 329 | int get_pi_version( void ) 330 | { 331 | int rev = 0; 332 | char buff[512]; 333 | char * p; 334 | char * pend; 335 | 336 | FILE * fd ; 337 | 338 | // do some clean up 339 | memset(buff,0,sizeof(buff)); 340 | 341 | fd = fopen("/proc/cpuinfo","r"); 342 | 343 | // Opened successfully 344 | if( fd ) 345 | { 346 | //printf("File opened successfully through fopen()\n"); 347 | 348 | // parse each line until we the end or we find the good one 349 | while( fgets(buff, sizeof(buff), fd) != NULL && rev ==0 ) 350 | { 351 | // search 352 | if( (strstr(buff, "Revision" )) != NULL ) 353 | { 354 | // point to the separator ":" format is has follow 355 | // Revision : 000f 356 | if ( (p = strtok( buff, ":")) != NULL ) 357 | { 358 | // Ok get value 359 | if ( (p = strtok( NULL, ":")) != NULL ) 360 | { 361 | // Revision Version is in hex format so put 0x before the number 362 | *p = 'x'; 363 | *--p = '0'; 364 | 365 | // convert to number 366 | rev = strtol(p, &pend, 16); 367 | 368 | //printf("rev=%d 0x%04x\n", rev, rev); 369 | 370 | // not Okay ? 371 | if ( !*pend ) 372 | { 373 | rev= 0; 374 | } 375 | else 376 | { 377 | // Revision 1 or 2 ? 378 | rev = (rev < 4 ) ? 1 : 2 ; 379 | } 380 | } 381 | } 382 | } 383 | } 384 | 385 | // Close the file. 386 | if(fd) 387 | { 388 | fclose(fd); 389 | } 390 | } 391 | 392 | return rev; 393 | } 394 | 395 | 396 | 397 | /* ====================================================================== 398 | Function: usage 399 | Purpose : display usage 400 | Input : program name 401 | Output : - 402 | Comments: 403 | ====================================================================== */ 404 | void usage( char * name) 405 | { 406 | 407 | printf("%s\n", PRG_NAME ); 408 | printf("Usage is: %s [options] [protocol] [mode] [-d device] [-a address] [-t data]\n", PRG_NAME); 409 | printf(" --evice : device name, i2c or spi\n"); 410 | printf(" --ddress : i2c device address (default 0x2A)\n"); 411 | printf(" --data : data to send\n"); 412 | printf("protocol is:\n"); 413 | printf(" --2c : set protocol to i2c (default)\n"); 414 | printf(" --pi : set protocol to spi\n"); 415 | printf("mode is:\n"); 416 | printf(" --et value: set value (byte or word type determined by data size)\n"); 417 | printf(" --etbyte : get byte value\n"); 418 | printf(" --getword : get word value\n"); 419 | printf(" --uick : i2c quick check device\n"); 420 | printf(" --ac : i2c check if device sent ack\n"); 421 | printf("Options are:\n"); 422 | printf(" --maspeed : max spi speed (in KHz)\n"); 423 | printf(" --dela : spi delay (usec)\n"); 424 | printf(" --its : spi bits per word\n"); 425 | printf(" --oop : spi loopback\n"); 426 | printf(" --cpa : spi clock phase\n"); 427 | printf(" --cpl : spi clock polarity\n"); 428 | printf(" --sb : spi least significant bit first\n"); 429 | printf(" --s-high : spi chip select active high\n"); 430 | printf(" --<3>wire : spi SI/SO signals shared\n"); 431 | printf(" --o-cs : spi no chip select\n"); 432 | printf(" --eady : spi Ready\n"); 433 | printf(" --erbose : speak more to user\n"); 434 | printf(" --he : show return values in hexadecimal format\n"); 435 | printf(" --ersion : show program version and Raspberry Pi revision\n"); 436 | printf(" --elp\n"); 437 | printf(" indicates the equivalent short option.\n"); 438 | printf(" long options always in lowercase\n"); 439 | printf("Short options are prefixed by \"-\" instead of by \"--\".\n"); 440 | printf("Example :\n"); 441 | printf( "%s --i2c --getbyte --hex --data 0xe0\nSend a ping command and return ping value in hex format\n", PRG_NAME); 442 | // printf( "%s -m r -v\nstart %s to wait for a value, then display it and exit\n", PRG_NAME, PRG_NAME); 443 | } 444 | 445 | 446 | /* ====================================================================== 447 | Function: parse_args 448 | Purpose : parse argument passed to the program 449 | Input : - 450 | Output : - 451 | Comments: 452 | ====================================================================== */ 453 | void parse_args(int argc, char *argv[]) 454 | { 455 | 456 | static struct option longOptions[] = 457 | { 458 | {"device" ,required_argument, 0, 'D' }, 459 | {"data" ,required_argument, 0, 'd' }, 460 | {"verbose" ,no_argument , 0, 'v' }, 461 | {"version" ,no_argument , 0, 'V' }, 462 | {"address" ,required_argument, 0, 'a' }, 463 | {"i2c" ,no_argument , 0, 'I' }, 464 | {"spi" ,no_argument , 0, 'S' }, 465 | {"set" ,no_argument , 0, 's' }, 466 | {"getbyte" ,no_argument , 0, 'g' }, 467 | {"getword" ,no_argument , 0, 'G' }, 468 | {"quick" ,no_argument , 0, 'q' }, 469 | {"ack" ,no_argument , 0, 'k' }, 470 | {"help" ,no_argument , 0, 'h' }, 471 | {"maxspeed" ,required_argument, 0, 'x' }, 472 | {"delay" ,required_argument, 0, 'y' }, 473 | {"bits" ,required_argument, 0, 'b' }, 474 | {"loop" ,no_argument , 0, 'l' }, 475 | {"cpha" ,no_argument , 0, 'H' }, 476 | {"cpol" ,no_argument , 0, 'O' }, 477 | {"lsb" ,no_argument , 0, 'L' }, 478 | {"cs-high" ,no_argument , 0, 'C' }, 479 | {"3wire" ,no_argument , 0, '3' }, 480 | {"no-cs" ,no_argument , 0, 'N' }, 481 | {"ready" ,no_argument , 0, 'R' }, 482 | {"hex" ,no_argument , 0, 'X' }, 483 | 484 | {0, 0, 0, 0} 485 | }; 486 | 487 | int optionIndex = 0; 488 | int c; 489 | char * pEnd; 490 | 491 | // By default set the correct I2C device function of Pi version 492 | 493 | while (1) 494 | { 495 | /* no default error messages printed. */ 496 | opterr = 0; 497 | 498 | c = getopt_long(argc, argv, "D:d:vVa:x:y:b:ISsgGqkhlHOLC3NRX", longOptions, &optionIndex); 499 | 500 | if (c < 0) 501 | break; 502 | 503 | switch (c) 504 | { 505 | case 'v': opts.verbose = true; break; 506 | 507 | 508 | case 's': opts.mode = MODE_SET ; opts.mode_str = "set" ; break; 509 | case 'k': opts.mode = MODE_READ_ACK ; opts.mode_str = "read ack" ; break; 510 | case 'q': opts.mode = MODE_QUICK_ACK ; opts.mode_str = "quick ack" ; break; 511 | case 'g': opts.mode = MODE_GET ; opts.mode_str = "get byte" ; break; 512 | case 'G': opts.mode = MODE_GET_WORD ; opts.mode_str = "get word" ; break; 513 | case 'I': opts.proto= PROTO_I2C ; opts.proto_str= "i2c" ; break; 514 | case 'l': opts.spi_mode |= SPI_LOOP ; break; 515 | case 'H': opts.spi_mode |= SPI_CPHA ; break; 516 | case 'O': opts.spi_mode |= SPI_CPOL ; break; 517 | case 'L': opts.spi_mode |= SPI_LSB_FIRST ; break; 518 | case 'C': opts.spi_mode |= SPI_CS_HIGH ; break; 519 | case '3': opts.spi_mode |= SPI_3WIRE ; break; 520 | case 'N': opts.spi_mode |= SPI_NO_CS ; break; 521 | case 'R': opts.spi_mode |= SPI_READY ; break; 522 | case 'X': opts.hexout = true ; break; 523 | 524 | 525 | // SPI init default bus 526 | case 'S': 527 | opts.proto= PROTO_SPI ; 528 | opts.proto_str= "spi"; 529 | 530 | // if bus still i2c, default to spi0 531 | // /dev/i2c-x -> i is th 5th char 532 | if ( opts.port[5] == 'i' ) 533 | strcpy(opts.port, SPI_DEVICE_0); 534 | 535 | break; 536 | 537 | 538 | // i2c slave address 539 | case 'a': 540 | opts.address = strtol(optarg,&pEnd,0); 541 | 542 | if ( !pEnd || opts.address < 1 || opts.address > 0x7F ) 543 | { 544 | fprintf(stderr, "--address %d (0x%02x) ignored.\n", opts.address, opts.address); 545 | fprintf(stderr, "--address must be between 1 and 255 or 0x01 and 0xff\n"); 546 | opts.address = I2C_SLAVE; 547 | fprintf(stderr, "--setting slave to default 0x%02x\n", opts.address); 548 | } 549 | break; 550 | 551 | // spi max speed 552 | case 'x': 553 | opts.spi_speed = strtol(optarg,&pEnd,0) ; 554 | 555 | if ( !pEnd || opts.spi_speed < 1 || opts.spi_speed > 10000 ) 556 | { 557 | fprintf(stderr, "--maxspeed %d Khz ignored.\n", opts.spi_speed); 558 | fprintf(stderr, "--maxspeed must be between 1 and 10000 (KHz)\n"); 559 | opts.spi_speed = SPI_SPEED; 560 | fprintf(stderr, "--setting max speed to default %d Khz\n", opts.spi_speed/1000); 561 | } 562 | else 563 | { 564 | opts.spi_speed *= 1000; 565 | } 566 | break; 567 | 568 | // spi delay 569 | case 'y': 570 | opts.spi_delay = strtol(optarg,&pEnd,0) ; 571 | 572 | if ( !pEnd || opts.spi_delay < 0 ) 573 | { 574 | fprintf(stderr, "--delay %dus ignored.\n", opts.spi_delay); 575 | opts.spi_delay = SPI_DELAY; 576 | fprintf(stderr, "--setting delay to default %d us\n", opts.spi_delay); 577 | } 578 | break; 579 | 580 | // spi bits per word 581 | case 'b': 582 | opts.spi_bits = strtol(optarg,&pEnd,0) ; 583 | 584 | if ( !pEnd || opts.spi_bits < 0 || opts.spi_bits > 64 ) 585 | { 586 | fprintf(stderr, "--bits %d ignored.\n", opts.spi_bits); 587 | opts.spi_delay = SPI_BITS_WORD; 588 | fprintf(stderr, "--setting bits per word to default %d us\n", opts.spi_bits); 589 | } 590 | break; 591 | 592 | // Device name 593 | case 'D': 594 | strncpy(opts.port, optarg, sizeof(opts.port) - 1); 595 | opts.port[sizeof(opts.port) - 1] = '\0'; 596 | break; 597 | 598 | // Data 599 | case 'd': 600 | { 601 | int ishex = false; 602 | char * p = opts.data; 603 | 604 | 605 | // Check correct size 606 | if ( strlen (optarg) >= 2) 607 | { 608 | // is it a hex string 609 | if (optarg[0] == '0' && optarg[1] == 'x' ) 610 | ishex = true; 611 | } 612 | 613 | if (ishex) 614 | { 615 | // put hex value into buffer data 616 | for (c = 2 ; optarg[c] != '\0' ; c += 2, p++) 617 | { 618 | // even number of hex char 619 | if ( !optarg[c+1] ) 620 | { 621 | *p = charToHexDigit(optarg[c]) ; 622 | c+=2; 623 | break; 624 | } 625 | else 626 | { 627 | *p = charToHexDigit(optarg[c]) * 16 + charToHexDigit(optarg[c+1]); 628 | } 629 | } 630 | 631 | opts.datasize = (c/2)- 1; 632 | } 633 | else 634 | { 635 | // copy the string 636 | opts.datasize = strlen(optarg); 637 | strncpy (opts.data, optarg, opts.datasize+1); 638 | strncat (opts.data, "\n", 1); 639 | opts.datasize++; 640 | } 641 | } 642 | break; 643 | 644 | // version 645 | case 'V': 646 | { 647 | printf("%s v%s\n", PRG_NAME, PRG_VERSION); 648 | printf("Raspberry Board Revision : %04x\n", g_pi_rev ); 649 | exit(EXIT_SUCCESS); 650 | } 651 | break; 652 | 653 | // help 654 | case 'h': 655 | usage(argv[0]); 656 | exit(EXIT_SUCCESS); 657 | break; 658 | 659 | case '?': 660 | default: 661 | fprintf(stderr, "Unrecognized option.\n"); 662 | fprintf(stderr, "Run with '--help'.\n"); 663 | exit(EXIT_FAILURE); 664 | break; 665 | } 666 | } /* while */ 667 | 668 | 669 | if (opts.verbose) 670 | { 671 | 672 | if ( opts.proto == PROTO_I2C ) 673 | { 674 | printf("-- i2c Stuff -- \n"); 675 | printf("i2c bus : %s\n", opts.port); 676 | printf("slave address : 0x%02X\n", opts.address); 677 | } 678 | if ( opts.proto == PROTO_SPI ) 679 | { 680 | printf("-- spi Stuff -- \n"); 681 | printf("spi bus : %s\n", opts.port); 682 | printf("spi mode : %d\n", opts.spi_mode); 683 | printf("bits per word : %d\n", opts.spi_bits); 684 | printf("max speed : %d Hz (%d KHz)\n", opts.spi_speed, opts.spi_speed/1000); 685 | } 686 | 687 | printf("mode : %s\n", opts.mode_str); 688 | printf("protocol : %s\n", opts.proto_str); 689 | printf("verbose : %s\n", opts.verbose? "yes" : "no"); 690 | printf("data (%02i) : ", opts.datasize); 691 | 692 | if (opts.datasize >0 ) 693 | { 694 | for (c = 0; c = 0 ) 758 | { 759 | // Read the return value 760 | r = i2c_smbus_read_byte(g_fd_device); 761 | } 762 | else 763 | { 764 | log_syslog(stdout, "Error from device 0x%02x on i2c_smbus_write_byte : %d %s\n", opts.address, r, strerror(errno)); 765 | clean_exit( EXIT_FAILURE ); 766 | } 767 | 768 | } 769 | // Get word command 770 | else if (opts.mode == MODE_GET_WORD ) 771 | { 772 | r = i2c_smbus_read_word_data(g_fd_device, opts.data[0]); 773 | //log_syslog(stderr, "Get Word 0x%02x : %d\n", opts.address, r); 774 | } 775 | else if (opts.mode == MODE_SET ) 776 | { 777 | // Set Byte command 778 | if (opts.datasize==1) 779 | { 780 | r = i2c_smbus_write_byte(g_fd_device, opts.data[0]); 781 | } 782 | // Set Word Byte command 783 | else if ( opts.datasize==2) 784 | { 785 | r = i2c_smbus_write_byte_data(g_fd_device, opts.data[0], opts.data[1]); 786 | } 787 | } 788 | 789 | // had a error ? 790 | if (r<0) 791 | { 792 | log_syslog(stdout, "Error from device 0x%02x : %d %s\n", opts.address, r, strerror(errno)); 793 | clean_exit( EXIT_FAILURE ); 794 | } 795 | else 796 | { 797 | //log_syslog(stdout, "Successfully done action on device 0x%02x\n", opts.address); 798 | if (opts.hexout) 799 | log_syslog(stdout, opts.mode == MODE_GET_WORD ? "0x%04X\n":"0x%02X\n", r); 800 | else 801 | log_syslog(stdout, "%d\n", r); 802 | 803 | clean_exit( EXIT_SUCCESS ); 804 | } 805 | } 806 | } 807 | 808 | 809 | /* ====================================================================== 810 | Function: spi_write 811 | Purpose : send spi datado spi stuff 812 | Input : spi Port Handle 813 | pointer to send buffer (buffer will be erased by device response 814 | size of buffer 815 | Output : -1 if error 816 | Comments: 817 | ====================================================================== */ 818 | int spi_transfer(int fd, unsigned char * buf, int n) 819 | { 820 | struct spi_ioc_transfer tr ; 821 | 822 | tr.rx_buf = (unsigned long) buf, 823 | tr.tx_buf = (unsigned long) buf; 824 | tr.len = n; 825 | tr.speed_hz = opts.spi_speed; 826 | tr.delay_usecs = opts.spi_delay; 827 | tr.bits_per_word= opts.spi_bits; 828 | 829 | return (ioctl(fd, SPI_IOC_MESSAGE(1), &tr) ); 830 | } 831 | 832 | /* ====================================================================== 833 | Function: do_spi 834 | Purpose : do spi stuff 835 | Input : - 836 | Output : - 837 | Comments: 838 | ====================================================================== */ 839 | void do_spi(void) 840 | { 841 | int r=0; 842 | 843 | g_fd_device = spi_init(); 844 | 845 | if (opts.verbose) 846 | log_syslog(stdout, "spi Init succeded\n"); 847 | 848 | // Mode : Check device, 849 | // arbitray, just check device response there is no such mode in SPI 850 | if ( opts.mode == MODE_QUICK_ACK || opts.mode == MODE_READ_ACK ) 851 | { 852 | // send a ping command 853 | opts.data[0] = ARDUIPI_CMD_PING ; 854 | 855 | // transfert one byte with the ping command 856 | // test firmware always response 2a 857 | spi_transfer( g_fd_device, (unsigned char *) opts.data, 1); 858 | 859 | // If error 860 | if ( r < 0 ) 861 | { 862 | log_syslog(stdout, "Error from spi device %s : %s\n", opts.port, strerror(errno)); 863 | clean_exit( EXIT_FAILURE ); 864 | } 865 | else 866 | { 867 | // get real response 868 | r = (int) opts.data[0]; 869 | 870 | // not expected response ? 871 | //if ( r != ARDUIPI_CMD_PING) 872 | // log_syslog(stdout, "Warning, expected %02X response and received %02X from spi device %s\n", ARDUIPI_CMD_PING, r, opts.port); 873 | //else 874 | log_syslog(stdout, opts.hexout?"0x%02X\n":"%d\n", r); 875 | } 876 | 877 | // sure, we have finished our job 878 | g_exit_pgm = true; 879 | } 880 | else 881 | { 882 | // Get Byte command 883 | if (opts.mode == MODE_GET ) 884 | { 885 | // Set the command we wand to read send 2 886 | // Dummy 2nd byte this is where we will have our response 887 | opts.data[1] = 0xff ; 888 | r = spi_transfer( g_fd_device, (unsigned char *) opts.data, 2); 889 | 890 | // If OK Read the return value 891 | if ( r >= 0 ) 892 | r = opts.data[1]; 893 | 894 | } 895 | // Get word command 896 | else if (opts.mode == MODE_GET_WORD ) 897 | { 898 | // Dummy 2nd and 3rd bytes this is where we will have our word response 899 | opts.data[1] = 0xff ; 900 | opts.data[2] = 0xff ; 901 | r = spi_transfer( g_fd_device, (unsigned char *) opts.data, 3); 902 | 903 | // If OK // Read the return value 904 | if ( r >= 0 ) 905 | r = opts.data[1] | (opts.data[2] << 8 ); 906 | } 907 | else if (opts.mode == MODE_SET ) 908 | { 909 | // send bulk data data 910 | r = spi_transfer( g_fd_device, (unsigned char *) opts.data, opts.datasize); 911 | } 912 | 913 | // had a error ? 914 | if ( r < 0 ) 915 | { 916 | log_syslog(stdout, "Error from spi_transfer on device %s : %d %s\n", opts.port, r, strerror(errno)); 917 | clean_exit( EXIT_FAILURE ); 918 | } 919 | else 920 | { 921 | if (opts.hexout) 922 | log_syslog(stdout, opts.mode == MODE_GET_WORD ? "0x%04X\n":"0x%02X\n", r); 923 | else 924 | log_syslog(stdout, "%d\n", r); 925 | 926 | clean_exit( EXIT_SUCCESS ); 927 | } 928 | } 929 | } 930 | 931 | 932 | 933 | /* ====================================================================== 934 | Function: main 935 | Purpose : Main entry Point 936 | Input : - 937 | Output : - 938 | Comments: 939 | ====================================================================== */ 940 | int main(int argc, char **argv) 941 | { 942 | struct sigaction exit_action; 943 | int n; 944 | char buff[BUFFER_SIZE]; 945 | 946 | g_fd_device = 0; 947 | g_exit_pgm = false; 948 | 949 | // clean up our buffer size 950 | bzero(buff, BUFFER_SIZE); 951 | 952 | // Get Raspberry Board Revision 953 | g_pi_rev = get_pi_version() ; 954 | 955 | // No Raspberry Board ? 956 | if ( g_pi_rev == 0 ) 957 | { 958 | printf("Error Unable to find Raspberry Board Revision\n"); 959 | clean_exit(EXIT_FAILURE); 960 | } 961 | 962 | // Set i2c device default bus depending on PI version 963 | strcpy(opts.port, g_pi_rev >= 2 ? I2C_DEVICE_1 : I2C_DEVICE_0 ); 964 | 965 | // get command line args 966 | parse_args(argc, argv); 967 | 968 | // Set up the structure to specify the exit action. 969 | exit_action.sa_handler = isr_handler; 970 | sigemptyset (&exit_action.sa_mask); 971 | exit_action.sa_flags = 0; 972 | sigaction (SIGTERM, &exit_action, NULL); 973 | sigaction (SIGINT, &exit_action, NULL); 974 | 975 | // do i2c job 976 | if ( opts.proto == PROTO_I2C ) 977 | do_i2c(); 978 | 979 | // do spi job 980 | if ( opts.proto == PROTO_SPI ) 981 | do_spi(); 982 | 983 | // Do while not end 984 | // this is for demo purpose, you can do whatever you like in this loop 985 | while ( ! g_exit_pgm ) 986 | { 987 | // example Read adc value from arduino 988 | n = i2c_smbus_read_byte_data(g_fd_device, 0x01); 989 | 990 | // We want to display results on stdout even if we are deamon ? 991 | if (opts.verbose) 992 | { 993 | log_syslog(stdout, "Received 0x%02x from slave\n", n); 994 | } 995 | 996 | // Do it again in 5 seconds 997 | sleep(5); 998 | 999 | } 1000 | 1001 | log_syslog(stderr, "Program terminated\n"); 1002 | 1003 | clean_exit(EXIT_SUCCESS); 1004 | 1005 | // avoid compiler warning 1006 | return (0); 1007 | } 1008 | 1009 | -------------------------------------------------------------------------------- /raspberry/autoreset: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import RPi.GPIO as GPIO 4 | import sys, os, re, time, fcntl 5 | 6 | fd = sys.stdin.fileno() 7 | fl = fcntl.fcntl(fd, fcntl.F_GETFL) 8 | fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 9 | 10 | # Avoid warnings during avrdude display 11 | GPIO.setwarnings(False) 12 | 13 | GPIO.setmode(GPIO.BOARD) 14 | dtr = re.compile('.+TIOCM_DTR.+') 15 | start = time.time() 16 | 17 | # pin number is Raspberry PI P1 connector 18 | # 7 is GPIO 4 19 | # 11 is GPIO 17 20 | # 12 is GPIO 18 ... 21 | def reset(): 22 | pin = 12 23 | GPIO.setup(pin, GPIO.OUT) 24 | GPIO.output(pin, GPIO.HIGH) 25 | time.sleep(0.12) 26 | GPIO.output(pin, GPIO.LOW) 27 | 28 | def process(): 29 | while True: 30 | try: 31 | duration = time.time() - start 32 | input = sys.stdin.readline().strip() 33 | if dtr.match(input): 34 | reset() 35 | return 36 | elif duration > 5000: 37 | return 38 | except: 39 | continue 40 | 41 | process() 42 | GPIO.cleanup() 43 | -------------------------------------------------------------------------------- /raspberry/avrdude-autoreset: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | strace -o "|autoreset" -eioctl /usr/bin/avrdude-original $@ 4 | -------------------------------------------------------------------------------- /raspberry/reset-arduino: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # You need to have installed Wiring Pi library to be able 3 | # to use this script 4 | # see http://wiringpi.com/download-and-install/ 5 | 6 | # define GPIO number where RESET line (DTR) is connected to 7 | # here GPIO 18 8 | io=18 9 | 10 | # Set IO pin to output 11 | gpio -g mode $io out 12 | 13 | # Set IO pin to LOW (bring reset to GND) 14 | echo -n "Resetting with GPIO"$io"..." 15 | gpio -g write $io 0 16 | 17 | # wait little time 18 | sleep 1 19 | 20 | # Set IO pin to HIGH (release reset to VDD) 21 | gpio -g write $io 1 22 | echo "done" 23 | 24 | # Optionnal, you can just after reset launch a 25 | # serial connection to Arduino 26 | # uncomment the following line to do it 27 | #picocom -b 115200 --imap lfcrlf /dev/ttyS0 28 | -------------------------------------------------------------------------------- /raspberry/test_board/test_board.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # quick and dirty code, I know, will arrange this later 3 | # 03/17/2014 CHH Modified to test new onboard switch connected to GPIO 17 4 | 5 | echo "------------------------------------" 6 | echo "ArduiPi test program, please verify " 7 | echo "that test board plugged on ArduiPi " 8 | echo " " 9 | echo "Press POWER-PI switch to begin Test " 10 | echo "------------------------------------" 11 | # Set GPIO 17 as input (Switch) 12 | gpio -g mode 17 in 13 | # Set GPIO 18 as output (Arduino Reset) 14 | gpio -g mode 18 out 15 | gpio -g write 18 1 16 | 17 | # loop until button pressed 18 | button=1 19 | while [ $button -ne 0 ] 20 | do 21 | button=`gpio -g read 17` 22 | sleep 0.5 23 | echo -n "." 24 | done 25 | 26 | echo " " 27 | echo "Reseting Arduino and waiting ready " 28 | echo "------------------------------------" 29 | # Bring reset LOW for 100ms 30 | gpio -g write 18 0 31 | sleep 0.1 32 | # Put reset back in idle state 33 | gpio -g write 18 1 34 | sleep 3 35 | 36 | echo " " 37 | echo "Testing ArduiPi Serial communication" 38 | echo "------------------------------------" 39 | # configure serial port to Arduino compatible mode 40 | stty -F /dev/ttyAMA0 cs8 -cstopb -parenb 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts 41 | echo -n " Sending serial port command." 42 | echo "FLUSH" > /dev/ttyAMA0 43 | sleep 1 44 | 45 | # send I_AM_PI string 46 | echo "I_AM_PI" > /dev/ttyAMA0 47 | echo -n "." 48 | # get I_AM_PI:OK response string from Arduino 49 | read RESPONSE < /dev/ttyAMA0 50 | echo -n "." 51 | if `echo ${RESPONSE} | grep "I_AM_PI:OK" 1>/dev/null 2>&1` 52 | then 53 | # response OK send back ACK 54 | echo "Arduino Serial OK" 55 | echo "ACK" > /dev/ttyAMA0 56 | else 57 | echo "Error No Serial response from Arduino" 58 | fi 59 | echo 60 | 61 | 62 | echo "Testing AruiPi I2C communication" 63 | echo "-----------------------------------" 64 | 65 | echo -n " Checking Arduino presence." 66 | # list I2C devices on bus and check Arduino is here, Arduino I2C address is 0x2a 67 | if `i2cdetect -y 1 | grep 2a 1>/dev/null 2>&1` 68 | then 69 | echo "Arduino I2C OK" 70 | else 71 | echo "Error No I2C response from Arduino" 72 | fi 73 | 74 | #echo -n " Checking Arduino Ping." 75 | # send ping command to arduino, Arduino should respond 0x2a in ping response 76 | #if `i2cget -y 1 0x2a 0xe0 | grep "2a" 1>/dev/null 2>&1` 77 | #if `arduipi --i2c --getbyte --hex --data 0xe0 | grep 0x2A 1>/dev/null 2>&1` 78 | #then 79 | # echo "Arduino I2C Ping OK" 80 | #else 81 | # echo "Error in Ping response from Arduino" 82 | #fi 83 | echo 84 | 85 | 86 | echo "Testing AruiPi SPI communication" 87 | echo "-----------------------------------" 88 | 89 | echo -n " Checking Arduino Ping." 90 | # send ping command to arduino, Arduino should respond 0x2a in ping response 91 | #if `i2cget -y 1 0x2a 0xe0 | grep "2a" 1>/dev/null 2>&1` 92 | if `arduipi --maxspeed 1000 --spi --ack --hex | grep 0x2A 1>/dev/null 2>&1` 93 | then 94 | echo "Arduino SPI Ping OK" 95 | else 96 | echo "Error in Ping response from Arduino" 97 | fi 98 | echo 99 | 100 | 101 | function setandclear 102 | { 103 | gpio -g mode $1 out 104 | gpio -g write $1 1 105 | } 106 | 107 | function seton 108 | { 109 | gpio -g write $1 0 110 | } 111 | 112 | 113 | function setio 114 | { 115 | echo "--- Led on GPIO$1" 116 | gpio -g write $1 0 117 | sleep 1 118 | echo "--- Led off GPIO$1" 119 | gpio -g write $1 1 120 | sleep 1 121 | } 122 | 123 | echo "--- All Led off" 124 | for io in 7 4 27 22 23 24 25 28 29 30 31 125 | do 126 | setandclear $io 127 | done 128 | sleep 2 129 | 130 | echo "--- All Led On" 131 | for io in 7 4 27 22 23 24 25 28 29 30 31 132 | do 133 | seton $io 134 | done 135 | sleep 2 136 | 137 | echo "--- All Led off" 138 | for io in 7 4 27 22 23 24 25 28 29 30 31 139 | do 140 | setandclear $io 141 | done 142 | 143 | echo "--- Cycling" 144 | #21 for Pi Rev 1 145 | for io in 7 4 27 22 23 24 25 28 29 30 31 146 | do 147 | setio $io 148 | done 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /test_board_v1.3/arduipi_test.pro: -------------------------------------------------------------------------------- 1 | EAGLE AutoRouter Statistics: 2 | 3 | Job : S:/Skydrive/devt/github/arduipi/arduipi_test_v1.2/arduipi_test.brd 4 | 5 | Start at : 12:17:38 (27/06/2013) 6 | End at : 12:17:38 (27/06/2013) 7 | Elapsed time : 00:00:00 8 | 9 | Signals : 64 RoutingGrid: 50 mil Layers: 2 10 | Connections : 110 predefined: 106 ( 19 Vias ) 11 | 12 | Router memory : 17472 13 | 14 | Passname : Busses Route Optimize1 Optimize2 Optimize3 Optimize4 15 | 16 | Time per pass : 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 17 | Number of Ripups : 0 0 0 0 0 0 18 | max. Level : 0 0 0 0 0 0 19 | max. Total : 0 0 0 0 0 0 20 | 21 | Routed : 2 4 4 4 4 4 22 | Vias : 0 0 0 0 0 0 23 | Resolution : 98.2 % 100.0 % 100.0 % 100.0 % 100.0 % 100.0 % 24 | 25 | Final : 100.0% finished 26 | -------------------------------------------------------------------------------- /test_board_v1.3/arduipi_test_board-board.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/test_board_v1.3/arduipi_test_board-board.pdf -------------------------------------------------------------------------------- /test_board_v1.3/arduipi_test_board.brd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | ArduiPi Test Board 128 | V 1.3 129 | Do Not Place 130 | GND 131 | VDD 132 | SDA 133 | SCL 134 | GND 135 | VDD 136 | + 137 | + 138 | + 139 | + 140 | + 141 | + 142 | + 143 | + 144 | + 145 | + 146 | + 147 | + 148 | + 149 | + 150 | VIN 151 | GND 152 | VDD 153 | 3V3 154 | RST 155 | A5 156 | A4 157 | A3 158 | A2 159 | A1 160 | A0 161 | SDA 162 | SCL 163 | D8 164 | D9 165 | D10 166 | D11 167 | D12 168 | D13 169 | GND 170 | AREF 171 | D0 172 | D1 173 | D2 174 | D3 175 | D4 176 | D5 177 | D6 178 | D7 179 | SS 180 | MOSI 181 | MISO 182 | SCK 183 | RX-I 184 | TX-O 185 | 186 | 187 | 188 | <h3>SparkFun Electronics' preferred foot prints</h3> 189 | In this library you'll find boards and modules: Arduino footprints, breadboards, non-RF modules, etc.<br><br> 190 | We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. 191 | <br><br> 192 | <b>Licensing:</b> CC v3.0 Share-Alike You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | GND 240 | GND 241 | +5V 242 | Reset 243 | Vin 244 | +3.3V 245 | 0 246 | 1 247 | 2 248 | 3 249 | 4 250 | 5 251 | Analog In 252 | GND 253 | 13 254 | 12 255 | 11 256 | Aref 257 | 10 258 | 9 259 | 8 260 | 7 261 | 6 262 | 5 263 | 4 264 | 3 265 | 2 266 | TX 267 | RX 268 | PWM 269 | PWM 270 | PWM 271 | PWM 272 | PWM 273 | PWM 274 | 275 | 276 | 277 | 278 | 279 | 280 | <b>RESISTOR</b><p> 281 | type 0204, grid 7.5 mm 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | >NAME 303 | >VALUE 304 | 305 | 306 | 307 | 308 | <b>TO 92</b> 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | >NAME 321 | >VALUE 322 | >NAME 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | >name 342 | >value 343 | >name 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | >name 356 | >value 357 | >name 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | >name 373 | >value 374 | >name 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | >name 384 | >value 385 | >name 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | >name 399 | >value 400 | >name 401 | 402 | 403 | 404 | 405 | 406 | <b>LEDs</b><p> 407 | <author>Created by librarian@cadsoft.de</author><br> 408 | Extended by Federico Battaglin <author>&lt;federico.rd@fdpinternational.com&gt;</author> with DUOLED 409 | 410 | 411 | <B>LED</B><p> 412 | 3 mm, round 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | >NAME 435 | >VALUE 436 | 437 | 438 | 439 | 440 | 441 | 442 | <b>PIN HEADER</b> 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | >NAME 453 | >VALUE 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | >name 492 | >name 493 | >VALUE 494 | 495 | 496 | 497 | 498 | <b>Diptronics THMD & SMD tact switches</b> 499 | <p><ul> 500 | <li>DTS-3: 3.5x6mm THMD tact switch 501 | <li>DTS-6, DTS-64: 6x6mm THMD tact switch 502 | <li>DTSM-3: 3.5x6mm SMD tact switch 503 | <li>DTSM-6, DTSM-64: 6x6mm SMD tact switch 504 | </ul></p> 505 | <p><b>Doublecheck before using!</b></p> 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | >NAME 527 | >VALUE 528 | 529 | 530 | 531 | 532 | <h3>SparkFun Electronics' preferred foot prints</h3> 533 | In this library you'll find resistors, capacitors, inductors, test points, jumper pads, etc.<br><br> 534 | We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. 535 | <br><br> 536 | <b>Licensing:</b> CC v3.0 Share-Alike You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | >NAME 556 | >VALUE 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | <b>EAGLE Design Rules</b> 580 | <p> 581 | Die Standard-Design-Rules sind so gewählt, dass sie für 582 | die meisten Anwendungen passen. Sollte ihre Platine 583 | besondere Anforderungen haben, treffen Sie die erforderlichen 584 | Einstellungen hier und speichern die Design Rules unter 585 | einem neuen Namen ab. 586 | <b>EAGLE Design Rules</b> 587 | <p> 588 | The default Design Rules have been set to cover 589 | a wide range of applications. Your particular design 590 | may have different requirements, so please make the 591 | necessary adjustments and save your customized 592 | design rules under a new name. 593 | <b>Seeed Studio EAGLE Design Rules</b> 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 | 1583 | 1584 | 1585 | 1586 | 1587 | 1588 | 1589 | 1590 | 1591 | 1592 | 1593 | 1594 | 1595 | 1596 | 1597 | 1598 | 1599 | 1600 | 1601 | 1602 | 1603 | 1604 | 1605 | 1606 | 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | 1619 | 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 1626 | 1627 | 1628 | 1629 | 1630 | 1631 | 1632 | 1633 | 1634 | 1635 | 1636 | 1637 | 1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 | 1660 | 1661 | 1662 | 1663 | 1664 | 1665 | 1666 | 1667 | 1668 | 1669 | 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 | 1679 | 1680 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 | 1687 | -------------------------------------------------------------------------------- /test_board_v1.3/arduipi_test_board.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hallard/arduipi/c1181c3faa9ea4a8357fab2aac8b360824fdb5e1/test_board_v1.3/arduipi_test_board.pdf --------------------------------------------------------------------------------