eBoard šŸ‰  ā‘ ā‘§ā‘Ø
Written for SIA 2017/2018
eBoard.h
Go to the documentation of this file.
1 
6  #ifndef EBOARD_HEADER_GUARD
7  #define EBOARD_HEADER_GUARD
8  #pragma GCC diagnostic push
9  #pragma GCC diagnostic ignored "-Wall"
10  #pragma GCC diagnostic ignored "-Wextra"
11  #pragma pack(push)
12  #pragma pack(16)
13 
15  #define EBOARD_VERSION "3.1.5m"
16  #define EBOARD_VERSION_NBR 315
18  #define VALUE_TO_STRING(x) #x
20  #ifdef DOC
22  #define PREPROCESS_DEBUG 1
24  #endif
25  #define VALUE(x) VALUE_TO_STRING(x)
27  #ifndef PREPROCESS_DEBUG
29  #define PREPROCESS_DEBUG 0
30  #endif
31  #define PPERFORM_PRAGMA(str) _Pragma(#str)
33  #if PREPROCESS_DEBUG == 1
34  #define DEBUG_MSG(str) PPERFORM_PRAGMA(message ("" #str))
35 
36  #define MACRO_MSG(mac,str) PPERFORM_PRAGMA(message("You set " #mac " to " VALUE(mac) ": " #str))
37  #else
38  #define DEBUG_MSG(str) ;
39  #define MACRO_MSG(mac,str) ;
40  #endif
41  DEBUG_MSG("If you do not want any preprocessing information from this eBoard-Header set PREPROCESS_DEBUG to 0");
43  DEBUG_MSG("You are using eBoard-header v3.1m written by EagleoutIce");
506  //i am a guard... leave me alone :D
507 
508 
509  #ifdef DOC
510  DEBUG_MSG("Documentation macro SET => Full doc features enabled");
511  #define ARDUINO 200
512 
515  #define EBOARD_I2C 0x1
516 
520  #define EBOARD_LCD 0x1
521 
524  #define EBOARD_SHIFT_REGISTER 0x1
525 
528  #define EBOARD_BLUETOOTH 0x1
529 
532  #define REPT_TASK
533 
536  #define __AVR_ATmega2560__
537 
540  #define __AVR_ATmega328P__
541 
544  #define EBOARD_NEO 0x1
545 
551  #define HIGHSPEED
552  #define __AVR__
554  #endif
555 
561  inline int sine8(uint8_t val){
562  return int((__builtin_sin((val/128.0*PI))+1)*127.5+0.5);
563  }
569  inline int gamma8(uint8_t val){
570  return int(pow((val)/255.0,2.6)*255.0+0.5);
571  }
572 
573  #include <avr/pgmspace.h>
578  namespace eagle_impl {}
579  using namespace eagle_impl;
580  #ifndef EBOARD_GUESSPATH
581  DEBUG_MSG("You are using Guesspath! Necessary libraries for eBoard will be included automatically");
585  #define EBOARD_GUESSPATH 0x1
586  #else
587  DEBUG_MSG("You are not using Guesspath! Necessary libraries for eBoard have to be included manually");
588  #endif
589 
590  #if defined(ARDUINO) //general platform-check [No tab]
591 
595  #define main eVirtual_main //main has a different meaning^^
596 
597  #if ARDUINO >= 100 //this could be only Arduino.h but this snippet is portable :D
598  #include "Arduino.h"
599  #else
600  #include <wiring.h>
601  #endif
602 
603  #if not ( defined(__AVR_ATmega2560__) || defined(__AVR_ATmega328P__))
604  #error "This library was build for ARDUINO UNO R3 Aand ARDUINO MEGA 2560!"
605  #endif
606 
607  #if defined(__AVR_ATmega2560__)
608  DEBUG_MSG("Building for Arduino Mega with ATmega2560");
612  #define PIN_MAX 0x32 //53 pins to address - 4 !!53 is SS
613  #else
614  DEBUG_MSG("Building for Arduino Uno or Nano with ATmega328P");
615  #define PIN_MAX 0xA // 13 Pins to address - 4 !!10 is SS
616  #endif
617 
618  #include <avr/io.h>
619  #include <avr/interrupt.h>
620 
621  #if EBOARD_I2C > 0x0 && EBOARD_GUESSPATH > 0x0
622  DEBUG_MSG("You enabled I²C featurea");
624  #ifndef twi_h
625  #define twi_h
626  #ifndef TwoWire_h
627  //#define ATMEGA8
628 
629  #ifndef TWI_FREQ
630  #define TWI_FREQ 100000L
631  #endif
632 
633  # ifndef TWI_BUFFER_LENGTH
634  #define TWI_BUFFER_LENGTH 32
635  #endif
636 
637  #define TWI_READY 0
638  #define TWI_MRX 1
639  #define TWI_MTX 2
640  #define TWI_SRX 3
641  #define TWI_STX 4
642 
643  //#include <inttypes.h>
644  //#include <avr/io.h>
645  #include <avr/interrupt.h>
646  #include <compat/twi.h>
647 
648  #ifndef cbi
649  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
650  #endif
651 
652  #ifndef sbi
653  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
654  #endif
655 
656  #include "pins_arduino.h"
657 
658  static volatile uint8_t twi_state;
659  static volatile uint8_t twi_slarw;
660  static volatile uint8_t twi_sendStop;
661  static volatile uint8_t twi_inRepStart;
662 
663  static void (*twi_onSlaveTransmit)(void);
664  static void (*twi_onSlaveReceive)(uint8_t*, int);
665 
666  static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
667  static volatile uint8_t twi_masterBufferIndex;
668  static volatile uint8_t twi_masterBufferLength;
669 
670  static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
671  static volatile uint8_t twi_txBufferIndex;
672  static volatile uint8_t twi_txBufferLength;
673 
674  static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
675  static volatile uint8_t twi_rxBufferIndex;
676 
677  static volatile uint8_t twi_error;
678 
679  void twi_init(void) {
680  twi_state = TWI_READY;
681  twi_sendStop = true;
682  twi_inRepStart = false;
683 
684  digitalWrite(SDA, 1);
685  digitalWrite(SCL, 1);
686 
687  cbi(TWSR, TWPS0);
688  cbi(TWSR, TWPS1);
689  TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
690 
691  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
692  }
693 
694  inline void twi_setAddress(uint8_t address) {
695  TWAR = address << 1;
696  }
697 
698  uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) {
699  uint8_t i;
700 
701  if(TWI_BUFFER_LENGTH < length) return 0;
702 
703  while(TWI_READY != twi_state) continue;
704 
705  twi_state = TWI_MRX;
706  twi_sendStop = sendStop;
707 
708  twi_error = 0xFF;
709 
710  twi_masterBufferIndex = 0;
711  twi_masterBufferLength = length-1;
712  twi_slarw = TW_READ;
713  twi_slarw |= address << 1;
714 
715  if (true == twi_inRepStart) {
716  twi_inRepStart = false;
717  TWDR = twi_slarw;
718  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
719  }
720  else
721  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
722 
723  while(TWI_MRX == twi_state) continue;
724 
725  if (twi_masterBufferIndex < length)
726  length = twi_masterBufferIndex;
727 
728  for(i = 0; i < length; ++i) data[i] = twi_masterBuffer[i];
729 
730  return length;
731  }
732 
733  uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) {
734  uint8_t i;
735 
736  if(TWI_BUFFER_LENGTH < length) return 1;
737 
738  while(TWI_READY != twi_state) continue;
739 
740  twi_state = TWI_MTX;
741  twi_sendStop = sendStop;
742  twi_error = 0xFF;
743 
744  twi_masterBufferIndex = 0;
745  twi_masterBufferLength = length;
746 
747  for(i = 0; i < length; ++i) twi_masterBuffer[i] = data[i];
748 
749  twi_slarw = TW_WRITE;
750  twi_slarw |= address << 1;
751 
752  if (true == twi_inRepStart) {
753  twi_inRepStart = false;
754  TWDR = twi_slarw;
755  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
756  }
757  else
758  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
759 
760  while(wait && (TWI_MTX == twi_state)) continue;
761 
762  if (twi_error == 0xFF) return 0;
763  else if (twi_error == TW_MT_SLA_NACK) return 2;
764  else if (twi_error == TW_MT_DATA_NACK) return 3;
765  else return 4;
766  }
767 
768  uint8_t twi_transmit(const uint8_t* data, uint8_t length) {
769  uint8_t i;
770 
771  if(TWI_BUFFER_LENGTH < length) return 1;
772 
773  if(TWI_STX != twi_state) return 2;
774 
775  twi_txBufferLength = length;
776  for(i = 0; i < length; ++i) twi_txBuffer[i] = data[i];
777 
778  return 0;
779  }
780 
781  void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) {
782  twi_onSlaveReceive = function;
783  }
784 
785  void twi_attachSlaveTxEvent( void (*function)(void) ) {
786  twi_onSlaveTransmit = function;
787  }
788 
789  void twi_reply(uint8_t ack) {
790  if(ack){
791  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
792  }else{
793  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
794  }
795  }
796 
797 
798  void twi_stop(void) {
799  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
800 
801  while(TWCR & _BV(TWSTO)) continue;
802 
803  twi_state = TWI_READY;
804  }
805 
806  void twi_releaseBus(void){
807  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
808  twi_state = TWI_READY;
809  }
810 
811  ISR(TWI_vect) {
812  switch(TW_STATUS){
813  case TW_START:
814  case TW_REP_START:
815  TWDR = twi_slarw;
816  twi_reply(1);
817  break;
818 
819  case TW_MT_SLA_ACK:
820  case TW_MT_DATA_ACK:
821  if(twi_masterBufferIndex < twi_masterBufferLength){
822  TWDR = twi_masterBuffer[twi_masterBufferIndex++];
823  twi_reply(1);
824  }else{
825  if (twi_sendStop) twi_stop();
826  else {
827  twi_inRepStart = true;
828  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
829  twi_state = TWI_READY;
830  }
831  }
832  break;
833  case TW_MT_SLA_NACK:
834  twi_error = TW_MT_SLA_NACK;
835  twi_stop();
836  break;
837  case TW_MT_DATA_NACK:
838  twi_error = TW_MT_DATA_NACK;
839  twi_stop();
840  break;
841  case TW_MT_ARB_LOST:
842  twi_error = TW_MT_ARB_LOST;
843  twi_releaseBus();
844  break;
845  case TW_MR_DATA_ACK:
846  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
847  case TW_MR_SLA_ACK:
848  if(twi_masterBufferIndex < twi_masterBufferLength) twi_reply(1);
849  else twi_reply(0);
850  break;
851  case TW_MR_DATA_NACK:
852  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
853  if (twi_sendStop) twi_stop();
854  else {
855  twi_inRepStart = true;
856  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
857  twi_state = TWI_READY;
858  }
859  break;
860  case TW_MR_SLA_NACK:
861  twi_stop();
862  break;
863  case TW_SR_SLA_ACK:
864  case TW_SR_GCALL_ACK:
865  case TW_SR_ARB_LOST_SLA_ACK:
866  case TW_SR_ARB_LOST_GCALL_ACK:
867  twi_state = TWI_SRX;
868  twi_rxBufferIndex = 0;
869  twi_reply(1);
870  break;
871  case TW_SR_DATA_ACK:
872  case TW_SR_GCALL_DATA_ACK:
873  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
874  twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
875  twi_reply(1);
876  } else twi_reply(0);
877 
878  break;
879  case TW_SR_STOP:
880  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH) twi_rxBuffer[twi_rxBufferIndex] = '\0';
881  twi_stop();
882  twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
883  twi_rxBufferIndex = 0;
884  twi_releaseBus();
885  break;
886  case TW_SR_DATA_NACK:
887  case TW_SR_GCALL_DATA_NACK:
888  twi_reply(0);
889  break;
890  case TW_ST_SLA_ACK:
891  case TW_ST_ARB_LOST_SLA_ACK:
892  twi_state = TWI_STX;
893  twi_txBufferIndex = 0;
894  twi_txBufferLength = 0;
895  twi_onSlaveTransmit();
896  if(0 == twi_txBufferLength){
897  twi_txBufferLength = 1;
898  twi_txBuffer[0] = 0x00;
899  }
900  case TW_ST_DATA_ACK:
901  TWDR = twi_txBuffer[twi_txBufferIndex++];
902  if(twi_txBufferIndex < twi_txBufferLength) twi_reply(1);
903  else twi_reply(0);
904  break;
905  case TW_ST_DATA_NACK:
906  case TW_ST_LAST_DATA:
907  twi_reply(1);
908  twi_state = TWI_READY;
909  break;
910 
911  case TW_NO_INFO:
912  break;
913  case TW_BUS_ERROR:
914  twi_error = TW_BUS_ERROR;
915  twi_stop();
916  break;
917  }
918  }
919  #endif
920 
922  #endif
923  #ifndef TwoWire_h
924 
925  #include <inttypes.h>
926  #include "Stream.h"
927 
928  #define BUFFER_LENGTH 32
929  namespace eagle_impl {
946  class TwoWire : public Stream {
947  private:
949  static uint8_t rxBuffer[];
951  static uint8_t rxBufferIndex;
953  static uint8_t rxBufferLength;
954 
956  static uint8_t txAddress;
958  static uint8_t txBuffer[];
960  static uint8_t txBufferIndex;
962  static uint8_t txBufferLength;
963 
965  static uint8_t transmitting;
967  static void (*user_onRequest)(void);
972  static void (*user_onReceive)(int numBytes);
974  static void onRequestService(void);
980  static void onReceiveService(uint8_t* inBytes, int numBytes);
981 
982  public:
984  TwoWire();
986  void begin();
991  void begin(uint8_t address);
997  inline void begin(int address);
1002  void beginTransmission(uint8_t address);
1008  inline void beginTransmission(int address);
1019  inline uint8_t endTransmission(void);
1030  uint8_t endTransmission(uint8_t sendStop);
1038  inline uint8_t requestFrom(uint8_t address, uint8_t quantity);
1046  uint8_t requestFrom(uint8_t address , uint8_t quantity, uint8_t sendStop);
1054  inline uint8_t requestFrom(int address, int quantity);
1063  inline uint8_t requestFrom(int address, int quantity, int sendStop);
1072  virtual size_t write(uint8_t data);
1080  virtual size_t write(const uint8_t *data, size_t quantity);
1085  virtual int available(void);
1091  virtual int read(void);
1097  virtual int peek(void);
1104  void onReceive( void (*function)(int) );
1111  void onRequest( void (*function)(void) );
1112 
1113  /* Removed due to: not needed
1114  inline size_t write(unsigned long n) { return write((uint8_t)n); }
1115  inline size_t write(long n) { return write((uint8_t)n); }
1116  inline size_t write(unsigned int n) { return write((uint8_t)n); }
1117  inline size_t write(int n) { return write((uint8_t)n); }
1118  */
1119  using Print::write;
1120  };
1121  }
1122  extern "C" {
1123  #include <stdlib.h>
1124  #include <string.h>
1125  #include <inttypes.h>
1126  //#include "twi.h"
1127  }
1128 
1131  uint8_t TwoWire::rxBufferIndex = 0;
1132  uint8_t TwoWire::rxBufferLength = 0;
1133 
1134  uint8_t TwoWire::txAddress = 0;
1136  uint8_t TwoWire::txBufferIndex = 0;
1137  uint8_t TwoWire::txBufferLength = 0;
1138 
1139  uint8_t TwoWire::transmitting = 0;
1140  void (*TwoWire::user_onRequest)(void);
1141  void (*TwoWire::user_onReceive)(int);
1142 
1143  TwoWire::TwoWire() {}
1144 
1145  void TwoWire::begin(void) {
1146  rxBufferIndex = 0;
1147  rxBufferLength = 0;
1148 
1149  txBufferIndex = 0;
1150  txBufferLength = 0;
1151 
1152  twi_init();
1153  }
1154 
1155  void TwoWire::begin(uint8_t address) {
1156  twi_setAddress(address);
1157  twi_attachSlaveTxEvent(onRequestService);
1158  twi_attachSlaveRxEvent(onReceiveService);
1159  begin();
1160  }
1161 
1162  void TwoWire::begin(int address) {
1163  begin((uint8_t)address);
1164  }
1165 
1166  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) {
1167  if(quantity > BUFFER_LENGTH){
1168  quantity = BUFFER_LENGTH;
1169  }
1170  uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
1171  rxBufferIndex = 0;
1172  rxBufferLength = read;
1173 
1174  return read;
1175  }
1176 
1177  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) {
1178  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
1179  }
1180 
1181  uint8_t TwoWire::requestFrom(int address, int quantity) {
1182  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
1183  }
1184 
1185  uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) {
1186  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
1187  }
1188 
1189  void TwoWire::beginTransmission(uint8_t address) {
1190  transmitting = 1;
1191  txAddress = address;
1192  txBufferIndex = 0;
1193  txBufferLength = 0;
1194  }
1195 
1196  void TwoWire::beginTransmission(int address) {
1197  beginTransmission((uint8_t)address);
1198  }
1199 
1200  uint8_t TwoWire::endTransmission(uint8_t sendStop) {
1201  int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
1202  txBufferIndex = 0;
1203  txBufferLength = 0;
1204  transmitting = 0;
1205  return ret;
1206  }
1207 
1208  uint8_t TwoWire::endTransmission(void){
1209  return endTransmission(true);
1210  }
1211 
1212  size_t TwoWire::write(uint8_t data) {
1213  if(transmitting) {
1214  if(txBufferLength >= BUFFER_LENGTH) {
1215  setWriteError();
1216  return 0;
1217  }
1218  txBuffer[txBufferIndex] = data;
1219  ++txBufferIndex;
1221  }else{
1222  twi_transmit(&data, 1);
1223  }
1224  return 1;
1225  }
1226 
1227  size_t TwoWire::write(const uint8_t *data, size_t quantity) {
1228  if(transmitting){
1229  for(size_t i = 0; i < quantity; ++i) {
1230  write(data[i]);
1231  }
1232  }else{
1233  twi_transmit(data, quantity);
1234  }
1235  return quantity;
1236  }
1237 
1238  int TwoWire::available(void) {
1239  return rxBufferLength - rxBufferIndex;
1240  }
1241 
1242  int TwoWire::read(void) {
1243  int8_t value = -1;
1244 
1246  value = rxBuffer[rxBufferIndex];
1247  ++rxBufferIndex;
1248  }
1249 
1250  return value;
1251  }
1252 
1253  int TwoWire::peek(void) {
1254  int value = -1;
1255 
1257  value = rxBuffer[rxBufferIndex];
1258  }
1259 
1260  return value;
1261  }
1262 
1263  void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) {
1264  if(!user_onReceive){
1265  return;
1266  }
1267 
1269  return;
1270  }
1271 
1272  for(uint8_t i = 0; i < numBytes; ++i) {
1273  rxBuffer[i] = inBytes[i];
1274  }
1275  rxBufferIndex = 0;
1276  rxBufferLength = numBytes;
1277  user_onReceive(numBytes);
1278  }
1279 
1280  void TwoWire::onRequestService(void) {
1281  if(!user_onRequest) return;
1282 
1283  txBufferIndex = 0;
1284  txBufferLength = 0;
1285  user_onRequest();
1286  }
1287 
1288  void TwoWire::onReceive( void (*function)(int) ) {
1289  user_onReceive = function;
1290  }
1291 
1292  void TwoWire::onRequest( void (*function)(void) ) {
1293  user_onRequest = function;
1294  }
1295 
1297 
1300 
1302  #define TwoWire_h
1303  #endif
1305  #else
1306  DEBUG_MSG("You disabled I²C");
1307  #endif
1308 
1311  #ifndef EBOARD_USE_SPI
1312  #define EBOARD_USE_SPI 0x1
1313  #endif
1314  #if EBOARD_USE_SPI > 0x0
1315  DEBUG_MSG("You enabled SPI");
1316  #ifndef _SPI_H_INCLUDED
1317  #define _SPI_H_INCLUDED
1319 
1320  #include <stdio.h>
1322  #define SPI_CLOCK_DIV4 0x00
1323  #define SPI_CLOCK_DIV16 0x01
1325  #define SPI_CLOCK_DIV64 0x02
1327  #define SPI_CLOCK_DIV128 0x03
1329  #define SPI_CLOCK_DIV2 0x04
1331  #define SPI_CLOCK_DIV8 0x05
1333  #define SPI_CLOCK_DIV32 0x06
1335 
1337  #define SPI_MODE0 0x00
1338  #define SPI_MODE1 0x04
1340  #define SPI_MODE2 0x08
1342  #define SPI_MODE3 0x0C
1344 
1346  #define SPI_MODE_MASK 0x0C
1347  #define SPI_CLOCK_MASK 0x03
1349  #define SPI_2XCLOCK_MASK 0x01
1351  namespace eagle_impl {
1365  struct SPIClass {
1371  inline static byte transfer(byte _data);
1375  inline static void attachInterrupt(void);
1379  inline static void detachInterrupt(void); // Default
1383  static void begin(void); // Default
1387  inline static void end(void);
1392  inline static void setBitOrder(uint8_t bitOrder);
1397  inline static void setDataMode(uint8_t mode);
1402  inline static void setClockDivider(uint8_t rate);
1403  };
1404  }
1406  byte SPIClass::transfer(byte _data) {
1407  SPDR = _data;
1408  while (!(SPSR & _BV(SPIF)));
1409  return SPDR;
1410  }
1411 
1412  void SPIClass::attachInterrupt() { SPCR |= _BV(SPIE);}
1413 
1414  void SPIClass::detachInterrupt() { SPCR &= ~_BV(SPIE);}
1415 
1416  void SPIClass::begin() {
1417  digitalWrite(SS, HIGH);
1418  pinMode(SS, OUTPUT); //doesn't block common use as_ OUTPUT!
1419  SPCR |= _BV(MSTR);
1420  SPCR |= _BV(SPE);
1421  pinMode(SCK, OUTPUT);
1422  pinMode(MOSI, OUTPUT);
1423  }
1424 
1425  void SPIClass::end() {SPCR &= ~_BV(SPE);}
1426 
1427  void SPIClass::setBitOrder(uint8_t bitOrder) {
1428  if(bitOrder == LSBFIRST) SPCR |= _BV(DORD);
1429  else SPCR &= ~(_BV(DORD));
1430  }
1431 
1432  void SPIClass::setDataMode(uint8_t mode) { SPCR = (SPCR & ~SPI_MODE_MASK) | mode; }
1433 
1434  void SPIClass::setClockDivider(uint8_t rate) {
1435  SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
1436  SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
1437  }
1439 
1441  #endif
1442  #else
1443  DEBUG_MSG("You disabled SPI");
1444  #endif
1445 
1446  #if (EBOARD_I2C > 0x0) && (EBOARD_LCD > 0x0)
1447  #include <avr/pgmspace.h>
1448  DEBUG_MSG("You enabled LCD");
1449  #endif
1450 
1456  static bool STOP = false;
1457 
1461  #ifdef IGNORE_SIZE
1462  DEBUG_MSG("You defined IGNORE_SIZE: byte will be used");
1463  typedef byte optVAL_t;
1464  #else
1465  DEBUG_MSG("You did not define IGNORE_SIZE: int will be used");
1466  typedef int optVAL_t;
1467  #endif
1468 
1472  #ifndef EBOARD_DEBUG_MODE
1473  #define EBOARD_DEBUG_MODE 0x1
1474  #endif
1475 
1476  #if EBOARD_DEBUG_MODE > 0x0
1477  MACRO_MSG(EBOARD_DEBUG_MODE,"Serial feedback will be send to Computer");
1478  #else
1479  MACRO_MSG(EBOARD_DEBUG_MODE, "No Serial feedback!");
1480  #endif
1481 
1482 
1486  #ifndef EBOARD_NANO
1487  #define EBOARD_NANO 0x0
1488  #endif
1489 
1490  #if EBOARD_NANO > 0x0 || defined(DOC)
1491  #ifndef EBOARD_NANO_STEER
1492 
1495  #define EBOARD_NANO_STEER 12
1496  #endif
1497  #ifndef EBOARD_NANO_MAIN
1498 
1501  #define EBOARD_NANO_MAIN 13
1502  #endif
1503  MACRO_MSG(EBOARD_NANO,"Using Arduino NANO environment [e.g. remove SoccerBoard]");
1504  #if PREPROCESS_DEBUG > 0x1
1505  #pragma message("Using " VALUE(EBOARD_NANO_STEER) " as data pin for STEERING MOTOR")
1506  #pragma message("Using " VALUE(EBOARD_NANO_MAIN) " as data pin for MAIN (Driving) MOTOR")
1507  #endif
1508  #else
1509  MACRO_MSG(EBOARD_NANO,"Using Arduino UNO/MEGA environment");
1510  #endif
1511 
1515  #ifndef EBOARD_CHECK_PINS
1516  #define EBOARD_CHECK_PINS 0x1
1517  #endif
1518 
1519  #if EBOARD_CHECK_PINS > 0x0
1520  MACRO_MSG(EBOARD_CHECK_PINS,"Check for Pins enabled");
1521  #else
1522  MACRO_MSG(EBOARD_CHECK_PINS,"Check for Pins disabled");
1523  #endif
1524 
1525  #ifndef EBOARD_SHIFT_REGISTER
1526 
1529  #define EBOARD_SHIFT_REGISTER 0x0
1530  #endif
1531 
1532  #if EBOARD_SHIFT_REGISTER > 0x0
1533  MACRO_MSG(EBOARD_SHIFT_REGISTER,"Shiftregister enabled");
1534  #else
1535  MACRO_MSG(EBOARD_SHIFT_REGISTER,"Shiftregister disabled");
1536  #endif
1537 
1541  #ifndef EBOARD_CHECK_PINS_PWM
1542  #define EBOARD_CHECK_PINS_PWM 0x1
1543  #endif
1544 
1545  #if EBOARD_CHECK_PINS_PWM > 0x0
1546  MACRO_MSG(EBOARD_CHECK_PINS_PWM,"Check for PWM-Pins enabled");
1547  #else
1548  MACRO_MSG(EBOARD_CHECK_PINS_PWM,"Check for PWM-Pins disabled");
1549  #endif
1550 
1554  #ifndef EBOARD_DEBUG_SPEED
1555  #define EBOARD_DEBUG_SPEED 9600
1556  #endif
1557  #if PREPROCESS_DEBUG > 0x0
1558  #pragma message("Set Debugging speed to " VALUE(EBOARD_DEBUG_SPEED))
1559  #endif
1560 
1561 
1565  #ifndef EBOARD_SPI_SERVO_MAX
1566  #define EBOARD_SPI_SERVO_MAX 2
1567  #endif
1568  #if PREPROCESS_DEBUG > 0x0
1569  #pragma message("Set amount of used Servos to " VALUE(EBOARD_SPI_SERVO_MAX))
1570  #endif
1571 
1574  #ifndef EBOARD_USE_UTILITY
1575  #define EBOARD_USE_UTILITY 0x1
1576  #endif
1577  #if EBOARD_USE_UTILITY > 0x0
1578  MACRO_MSG(EBOARD_USE_UTILITY,"Utility features will be implemented");
1579  #else
1580  MACRO_MSG(EBOARD_USE_UTILITY,"Utility features will not be implemented");
1581  #endif
1582 
1586  #define EBOARD_COPY_AND_PASTE 0x1
1587 
1590  #ifndef EBOARD_PWM_SPE
1591  #define EBOARD_PWM_SPE 1
1592  #endif
1593  #if PREPROCESS_DEBUG > 0x0
1594  #pragma message("Set PWM interval to " VALUE(EBOARD_PWM_SPE) "s")
1595  #endif
1596 
1597  #ifndef EBOARD_I2C
1598 
1601  #define EBOARD_I2C 0x0 //disabled by default
1602  #endif
1603 
1604  #ifndef EBOARD_BLUETOOTH
1605 
1608  #define EBOARD_BLUETOOTH 0x0
1609  #endif
1610 
1611  #if EBOARD_BLUETOOTH > 0x0
1612  MACRO_MSG(EBOARD_BLUETOOTH,"Bluetooth controls enabled");
1613  #else
1614  MACRO_MSG(EBOARD_BLUETOOTH,"Bluetooth controls disabled");
1615  #endif
1616 
1620  #ifndef EBOARD_CLAMP
1621  #define EBOARD_CLAMP 0x1
1622  #endif
1623  #if EBOARD_CLAMP > 0x0
1624  MACRO_MSG(EBOARD_CLAMP,"Motor Range is set to [0;1023]");
1625  #else
1626  MACRO_MSG(EBOARD_CLAMP,"Motor Range is set to [-300;300]");
1627  #endif
1628 
1629  #ifndef EBOARD_NEO
1630 
1633  #define EBOARD_NEO 0x0
1634  #endif
1635  #if EBOARD_NEO > 0x0
1636  MACRO_MSG(EBOARD_NEO,"Adafruit Neo-Pixel support enabled");
1637  #else
1638  MACRO_MSG(EBOARD_NEO,"Adafruit Neo-Pixel support disabled");
1639  #endif
1640 
1644  #ifndef EBOARD_USE_RESET
1645  #define EBOARD_USE_RESET 0x1
1646  #endif
1647 
1648  #if EBOARD_USE_RESET > 0x0
1649  #include <avr/wdt.h>
1650  MACRO_MSG(EBOARD_USE_RESET,"Software-Reset is available" );
1651  #else
1652  MACRO_MSG(EBOARD_USE_RESET,"Software-Reset is not available" );
1653  #endif
1654 
1658  #ifndef PIN_BLUETOOTH_STATE
1659  #if defined(__AVR_ATmega2560__)
1660  #define PIN_BLUETOOTH_STATE 0x13 // 19
1661  #else
1662  #define PIN_BLUETOOTH_STATE 0x2
1663  #endif
1664  #endif
1665 
1669  #ifndef PIN_BLUETOOTH_RX
1670  #if defined(__AVR_ATmega2560__)
1671  #define PIN_BLUETOOTH_RX 0x13 // 19
1672  #else
1673  #define PIN_BLUETOOTH_RX 0x2
1674  #endif
1675  #endif
1676 
1680  #ifndef PIN_BLUETOOTH_TX
1681  #if defined(__AVR_ATmega2560__)
1682  #define PIN_BLUETOOTH_TX 0x12 // 18
1683  #else
1684  #define PIN_BLUETOOTH_TX 0x3
1685  #endif
1686  #endif
1687 
1691  #ifndef PIN_MOTOR_DIR
1692  #define PIN_MOTOR_DIR 0x4
1693  #endif
1694 
1698  #ifndef PIN_MOTOR_SPE
1699  #define PIN_MOTOR_SPE 0x5
1700  #endif
1701 
1705  #ifndef PIN_SHIFT_CLK
1706  #define PIN_SHIFT_CLK 0x6
1707  #endif
1708 
1711  #ifndef PIN_SHIFT_DAT
1712  #define PIN_SHIFT_DAT 0x7
1713  #endif
1714 
1717  #ifndef PIN_SHIFT_LAT
1718  #define PIN_SHIFT_LAT 0x8
1719  #endif
1720 
1721 
1722  //done by arduino
1723  //if this has an effect... something went wrong :D
1724  #ifndef HIGH
1725  #define HIGH 1
1726  #endif
1727  #ifndef LOW
1728  #define LOW 0
1729  #endif
1730 
1731  #if (EBOARD_BLUETOOTH > 0x0) && defined(__AVR_ATmega328P__)
1732  #if EBOARD_GUESSPATH > 0x0
1733  #ifndef SoftwareSerial_h
1734  //again to resolve including errors we'll include the SoftwareSerial cpp file
1735  #define SoftwareSerial_h
1736  #define _SS_MAX_RX_BUFF 64 // RX buffer size
1737  #ifndef GCC_VERSION
1738  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
1739  #endif
1740  namespace eagle_impl {
1762  class SoftwareSerial : public Stream {
1763  private:
1765  uint8_t _receivePin;
1769  volatile uint8_t *_receivePortRegister;
1773  volatile uint8_t *_transmitPortRegister;
1774 
1782  uint16_t _tx_delay;
1783 
1785  uint16_t _buffer_overflow:1;
1787  uint16_t _inverse_logic:1;
1791  static volatile uint8_t _receive_buffer_tail;
1793  static volatile uint8_t _receive_buffer_head;
1796 
1798  void recv(void);
1803  inline uint8_t rx_pin_read(void);
1808  inline void tx_pin_write(uint8_t pin_state);
1813  void setTX(uint8_t transmitPin);
1818  void setRX(uint8_t receivePin);
1823  static inline void tunedDelay(uint16_t delay);
1824 
1825  public:
1826  // public methods
1833  SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);
1839  ~SoftwareSerial(void);
1855  void begin(long speed);
1860  bool listen(void);
1862  inline void end(void);
1867  inline bool isListening(void);
1872  inline bool overflow(void);
1877  int peek(void);
1884  virtual size_t write(uint8_t byte);
1889  virtual int read(void);
1894  virtual int available(void);
1898  virtual void flush(void);
1899  //used to save codespace
1900  using Print::write;
1902  static inline void handle_interrupt(void);
1903  };
1904  }
1906 
1907  bool SoftwareSerial::isListening(void) {
1908  return this == active_object;
1909  }
1910 
1911  bool SoftwareSerial::overflow(void) {
1912  bool ret = _buffer_overflow;
1913  _buffer_overflow = false;
1914  return ret;
1915  }
1916  /* was a workaround for arduino 0012 but not needed
1917  #undef int
1918  #undef char
1919  #undef long
1920  #undef byte
1921  #undef float
1922  #undef abs
1923  #undef round
1924  */
1925  #if EBOARD_DEBUG_MODE > 0x0
1926  #define _DEBUG 0
1927  #define _DEBUG_PIN1 11
1928  #define _DEBUG_PIN2 13
1929  #endif
1930  typedef struct _DELAY_TABLE {
1931  long baud;
1932  unsigned short rx_delay_centering;
1933  unsigned short rx_delay_intrabit;
1934  unsigned short rx_delay_stopbit;
1935  unsigned short tx_delay;
1936  } DELAY_TABLE;
1937  #if F_CPU == 16000000
1938 
1939  static const DELAY_TABLE PROGMEM table[] = {
1940  // baud rxcenter rxintra rxstop tx
1941  { 115200, 1, 17, 17, 12, },
1942  { 57600, 10, 37, 37, 33, },
1943  { 38400, 25, 57, 57, 54, },
1944  { 31250, 31, 70, 70, 68, },
1945  { 28800, 34, 77, 77, 74, },
1946  { 19200, 54, 117, 117, 114, },
1947  { 14400, 74, 156, 156, 153, },
1948  { 9600, 114, 236, 236, 233, },
1949  { 4800, 233, 474, 474, 471, },
1950  { 2400, 471, 950, 950, 947, },
1951  { 1200, 947, 1902, 1902, 1899, },
1952  { 600, 1902, 3804, 3804, 3800, },
1953  { 300, 3804, 7617, 7617, 7614, },
1954  };
1955 
1956  const int XMIT_START_ADJUSTMENT = 5;
1957 
1958  #elif F_CPU == 8000000
1959 
1960  static const DELAY_TABLE table[] PROGMEM = {
1961  // baud rxcenter rxintra rxstop tx
1962  { 115200, 1, 5, 5, 3, },
1963  { 57600, 1, 15, 15, 13, },
1964  { 38400, 2, 25, 26, 23, },
1965  { 31250, 7, 32, 33, 29, },
1966  { 28800, 11, 35, 35, 32, },
1967  { 19200, 20, 55, 55, 52, },
1968  { 14400, 30, 75, 75, 72, },
1969  { 9600, 50, 114, 114, 112, },
1970  { 4800, 110, 233, 233, 230, },
1971  { 2400, 229, 472, 472, 469, },
1972  { 1200, 467, 948, 948, 945, },
1973  { 600, 948, 1895, 1895, 1890, },
1974  { 300, 1895, 3805, 3805, 3802, },
1975  };
1976 
1977  const int XMIT_START_ADJUSTMENT = 4;
1978 
1979  #elif F_CPU == 20000000
1980 
1981  static const DELAY_TABLE PROGMEM table[] = {
1982  // baud rxcenter rxintra rxstop tx
1983  { 115200, 3, 21, 21, 18, },
1984  { 57600, 20, 43, 43, 41, },
1985  { 38400, 37, 73, 73, 70, },
1986  { 31250, 45, 89, 89, 88, },
1987  { 28800, 46, 98, 98, 95, },
1988  { 19200, 71, 148, 148, 145, },
1989  { 14400, 96, 197, 197, 194, },
1990  { 9600, 146, 297, 297, 294, },
1991  { 4800, 296, 595, 595, 592, },
1992  { 2400, 592, 1189, 1189, 1186, },
1993  { 1200, 1187, 2379, 2379, 2376, },
1994  { 600, 2379, 4759, 4759, 4755, },
1995  { 300, 4759, 9523, 9523, 9520, },
1996  };
1997 
1998  const int XMIT_START_ADJUSTMENT = 6;
1999 
2000  #else
2001  #error This version of SoftwareSerial supports only 20, 16 and 8MHz processors
2002  #endif
2003 
2006  volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
2007  volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
2008  #if EBOARD_DEBUG_MODE > 0x0
2009  inline void DebugPulse(uint8_t pin, uint8_t count) {
2010  #if _DEBUG
2011  volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin));
2012 
2013  uint8_t val = *pport;
2014  while (count--)
2015  {
2016  *pport = val | digitalPinToBitMask(pin);
2017  *pport = val;
2018  }
2019  #endif
2020  }
2021  #endif
2022  inline void SoftwareSerial::tunedDelay(uint16_t delay) {
2023  uint8_t tmp=0;
2024 
2025  asm volatile("sbiw %0, 0x01 \n\t"
2026  "ldi %1, 0xFF \n\t"
2027  "cpi %A0, 0xFF \n\t"
2028  "cpc %B0, %1 \n\t"
2029  "brne .-10 \n\t"
2030  : "+r" (delay), "+a" (tmp)
2031  : "0" (delay)
2032  );
2033  }
2034 
2035  bool SoftwareSerial::listen() {
2036  if (active_object != this)
2037  {
2038  _buffer_overflow = false;
2039  uint8_t oldSREG = SREG;
2040  cli();
2042  active_object = this;
2043  SREG = oldSREG;
2044  return true;
2045  }
2046 
2047  return false;
2048  }
2049 
2050  void SoftwareSerial::recv() {
2051 
2052  #if GCC_VERSION < 40302
2053  asm volatile(
2054  "push r18 \n\t"
2055  "push r19 \n\t"
2056  "push r20 \n\t"
2057  "push r21 \n\t"
2058  "push r22 \n\t"
2059  "push r23 \n\t"
2060  "push r26 \n\t"
2061  "push r27 \n\t"
2062  ::);
2063  #endif
2064 
2065  uint8_t d = 0;
2066 
2067  if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) {
2068  // Wait approximately 1/2 of a bit width to "center" the sample
2070  #if EBOARD_DEBUG_MODE > 0x0
2071  DebugPulse(_DEBUG_PIN2, 1);
2072  #endif
2073  // Read each of the 8 bits
2074  for (uint8_t i=0x1; i; i <<= 1)
2075  {
2077  #if EBOARD_DEBUG_MODE > 0x0
2078  DebugPulse(_DEBUG_PIN2, 1);
2079  #endif
2080  uint8_t noti = ~i;
2081  if (rx_pin_read())
2082  d |= i;
2083  else
2084  d &= noti;
2085  }
2086 
2087  // skip the stop bit
2089  #if EBOARD_DEBUG_MODE > 0x0
2090  DebugPulse(_DEBUG_PIN2, 1);
2091  #endif
2092  if (_inverse_logic)
2093  d = ~d;
2094 
2096  _receive_buffer[_receive_buffer_tail] = d; // save new byte
2098  }
2099  else {
2100  #if EBOARD_DEBUG_MODE > 0x0
2101  #if _DEBUG // for scope: pulse pin as overflow indictator
2102  DebugPulse(_DEBUG_PIN1, 1);
2103  #endif
2104  #endif
2105  _buffer_overflow = true;
2106  }
2107  }
2108 
2109  #if GCC_VERSION < 40302
2110  asm volatile(
2111  "pop r27 \n\t"
2112  "pop r26 \n\t"
2113  "pop r23 \n\t"
2114  "pop r22 \n\t"
2115  "pop r21 \n\t"
2116  "pop r20 \n\t"
2117  "pop r19 \n\t"
2118  "pop r18 \n\t"
2119  ::);
2120  #endif
2121  }
2122 
2123  void SoftwareSerial::tx_pin_write(uint8_t pin_state) {
2124  if (pin_state == LOW)
2126  else
2128  }
2129 
2130  uint8_t SoftwareSerial::rx_pin_read() {
2132  }
2133 
2134  inline void SoftwareSerial::handle_interrupt() {
2135  if (active_object) {
2136  active_object->recv();
2137  }
2138  }
2139 
2140  #if defined(PCINT0_vect)
2141  ISR(PCINT0_vect) {
2143  }
2144  #endif
2145 
2146  #if defined(PCINT1_vect)
2147  ISR(PCINT1_vect) {
2149  }
2150  #endif
2151 
2152  #if defined(PCINT2_vect)
2153  ISR(PCINT2_vect) {
2155  }
2156  #endif
2157 
2158  #if defined(PCINT3_vect)
2159  ISR(PCINT3_vect) {
2161  }
2162  #endif
2163 
2164  SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) :
2165  _rx_delay_centering(0),
2166  _rx_delay_intrabit(0),
2167  _rx_delay_stopbit(0),
2168  _tx_delay(0),
2169  _buffer_overflow(false),
2170  _inverse_logic(inverse_logic) {
2171  setTX(transmitPin);
2172  setRX(receivePin);
2173  }
2174 
2176  end();
2177  }
2178 
2179  void SoftwareSerial::setTX(uint8_t tx) {
2180  pinMode(tx, OUTPUT);
2181  digitalWrite(tx, HIGH);
2182  _transmitBitMask = digitalPinToBitMask(tx);
2183  uint8_t port = digitalPinToPort(tx);
2184  _transmitPortRegister = portOutputRegister(port);
2185  }
2186 
2187  void SoftwareSerial::setRX(uint8_t rx) {
2188  pinMode(rx, INPUT);
2189  if (!_inverse_logic)
2190  digitalWrite(rx, HIGH);
2191  _receivePin = rx;
2192  _receiveBitMask = digitalPinToBitMask(rx);
2193  uint8_t port = digitalPinToPort(rx);
2194  _receivePortRegister = portInputRegister(port);
2195  }
2196 
2197  void SoftwareSerial::begin(long speed) {
2199 
2200  for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i) {
2201  long baud = pgm_read_dword(&table[i].baud);
2202  if (baud == speed) {
2203  _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
2204  _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
2205  _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
2206  _tx_delay = pgm_read_word(&table[i].tx_delay);
2207  break;
2208  }
2209  }
2210 
2211  if (_rx_delay_stopbit) {
2212  if (digitalPinToPCICR(_receivePin)) {
2213  *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin));
2214  *digitalPinToPCMSK(_receivePin) |= _BV(digitalPinToPCMSKbit(_receivePin));
2215  }
2217  }
2218 
2219  #if _DEBUG
2220  pinMode(_DEBUG_PIN1, OUTPUT);
2221  pinMode(_DEBUG_PIN2, OUTPUT);
2222  #endif
2223 
2224  listen();
2225  }
2226 
2227  void SoftwareSerial::end() {
2228  if (digitalPinToPCMSK(_receivePin))
2229  *digitalPinToPCMSK(_receivePin) &= ~_BV(digitalPinToPCMSKbit(_receivePin));
2230  }
2231 
2232 
2233  int SoftwareSerial::read() {
2234  if (!isListening())
2235  return -1;
2236 
2238  return -1;
2239 
2240  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
2242  return d;
2243  }
2244 
2246  if (!isListening())
2247  return 0;
2248 
2250  }
2251 
2252  size_t SoftwareSerial::write(uint8_t b) {
2253  if (_tx_delay == 0) {
2254  setWriteError();
2255  return 0;
2256  }
2257 
2258  uint8_t oldSREG = SREG;
2259  cli();
2260 
2261  tx_pin_write(_inverse_logic ? HIGH : LOW);
2262  tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
2263 
2264  if (_inverse_logic) {
2265  for (byte mask = 0x01; mask; mask <<= 1) {
2266  if (b & mask)
2267  tx_pin_write(LOW);
2268  else
2269  tx_pin_write(HIGH);
2270 
2272  }
2273 
2274  tx_pin_write(LOW);
2275  }
2276  else {
2277  for (byte mask = 0x01; mask; mask <<= 1) {
2278  if (b & mask)
2279  tx_pin_write(HIGH);
2280  else
2281  tx_pin_write(LOW);
2283  }
2284 
2285  tx_pin_write(HIGH);
2286  }
2287 
2288  SREG = oldSREG;
2290 
2291  return 1;
2292  }
2293 
2294  void SoftwareSerial::flush() {
2295  if (!isListening())
2296  return;
2297 
2298  uint8_t oldSREG = SREG;
2299  cli();
2301  SREG = oldSREG;
2302  }
2303 
2304  int SoftwareSerial::peek() {
2305  if (!isListening())
2306  return -1;
2307 
2309  return -1;
2310 
2312  }
2314  #endif
2315  #endif
2316 
2322  #endif
2323 
2324  #if EBOARD_DEBUG_MODE > 0x0
2325 
2328  #define __ASSERT_USE_STDERR
2329  #include <assert.h>
2347  void __assert (const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp);
2349  void __assert (const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp){
2350  Serial.print("Error with: "); Serial.print(__func);
2351  Serial.print(" in "); Serial.print(__file);
2352  Serial.print(" >>");
2353  Serial.println(__sexp);
2354  if(strcmp(__func,"checkIdx")==0){
2355  Serial.println(" This happens if an out of bounds exception");
2356  Serial.println(" has occured. Following pins shouldn't be used:");
2357  Serial.print(" D" + PIN_BLUETOOTH_RX);Serial.print("&");
2358  Serial.print("D");Serial.print(PIN_BLUETOOTH_TX);
2359  Serial.println(" : Used for Bluetooth communication");
2360  Serial.print(" D");Serial.print(PIN_MOTOR_DIR);Serial.print("&");
2361  Serial.print("D");Serial.print(PIN_MOTOR_SPE);
2362  Serial.println(" : Used for main motor control");
2363  #if EBOARD_USE_SPI > 0x0
2364  Serial.print(" D10-13");
2365  Serial.println(": Used for smart-servo-shield");
2366  #endif
2367  } else if (strcmp(__func,"readPin")==0){
2368  Serial.println("You've tried to access an analogPin that isn't present on the board you're currently working on!");
2369  }
2370  Serial.flush();
2371  abort(); // halt after outputting information
2372  }
2374  #endif
2375 
2382  inline void checkIdx(optVAL_t idx);
2384  inline void checkIdx(optVAL_t idx){
2385  #if EBOARD_DEBUG_MODE > 0x0
2386  assert(idx>=0x0 && idx < PIN_MAX); //changed pins? change me! (didn't want to use macros)
2387  assert(idx!=PIN_BLUETOOTH_RX&&idx!=PIN_BLUETOOTH_TX);
2388  #endif
2389  }
2391 
2392  #if EBOARD_COPY_AND_PASTE > 0x0
2393  #if EBOARD_CHECK_PINS_PWM > 0x0
2394 
2403  optVAL_t count; //dont't want to overuse global space^^
2404  for (count = 0; x; count++)
2405  x &= x - 1;
2406  return count;
2407  }
2409  #endif
2410 
2411  #if EBOARD_CHECK_PINS > 0x0
2412 
2417  #if defined(__AVR_ATmega328P__) && not defined(__AVR_ATmega2560__)
2418  uint16_t pin_out = 0x0;
2419  #elif defined(__AVR_ATmega2560__)
2420  uint64_t pin_out = 0x0;
2421  #endif
2422 
2425  #if defined(__AVR_ATmega328P__) && not defined(__AVR_ATmega2560__)
2426  uint16_t pin_in = 0x0;
2427  #elif defined(__AVR_ATmega2560__)
2428  uint64_t pin_in = 0x0;
2429  #endif
2430 
2440  inline bool checkPin(optVAL_t idx, optVAL_t mode = OUTPUT);
2442  inline bool checkPin(optVAL_t idx, optVAL_t mode){
2443  checkIdx(idx);
2444  return (mode == OUTPUT)? ((pin_out & (1<<idx))>0x0):((pin_in & (1<<idx))>0x0);
2445  }
2447  #endif
2448 
2454  void setPin(optVAL_t idx, optVAL_t mode = OUTPUT);
2456  void setPin(optVAL_t idx, optVAL_t mode){
2457  #if EBOARD_CHECK_PINS > 0x0
2458  checkIdx(idx);
2459  if(mode==OUTPUT) { //possible to read from OUTPUT digital ... we won't do it
2460  pin_out |= (1<<idx);
2461  pin_in &= ~(1<<idx);
2462  }
2463  else {
2464  pin_in |= (1<<idx);
2465  pin_out &= ~(1<<idx);
2466  }
2467  #endif
2468  pinMode(idx, mode);
2469  }
2471  #endif
2472 
2473  #if EBOARD_BLUETOOTH > 0x0
2474 
2482  inline char readVal(char oF = '.');
2490  inline bool checkOverflow(void);
2495  template <typename T>
2496  inline void writeVal(const T& val);
2497 
2509  inline bool isConnected(void);
2511  inline bool checkOverflow(void) {
2512  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
2513  return false; //there is no hardware provided control for hardwareserial overflow
2514  #else
2515  return (_serial.overflow());
2516  #endif
2517  }
2518  inline char readVal(char oF) {
2519  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
2520  return ((Serial1.available())?(Serial1.read()):(oF));
2521  #else
2522  return ((_serial.available())?(_serial.read()):(oF));
2523  #endif
2524  }
2525  template<typename T>
2526  inline void writeVal(const T& val){
2527  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
2528  Serial1.write(val);
2529  #else
2530  _serial.write(val);
2531  #endif
2532  }
2533  inline bool isConnected(void) {
2534  #if PIN_BLUETOOTH_RX != PIN_BLUETOOTH_STATE
2535  return digitalRead(PIN_BLUETOOTH_STATE);
2536  #else
2537  return true;
2538  #endif
2539  }
2541  #endif
2542 
2543  #if EBOARD_SHIFT_REGISTER > 0x0
2544 
2547  long store_bits = 0L;
2556  inline void shiftSingle(optVAL_t idx, bool val);
2560  void shiftAll(void);
2562  inline void shiftSingle(optVAL_t idx, bool val) {
2563  bitWrite(store_bits,idx,val);
2564  shiftAll();
2565  }
2566 
2567  void shiftAll(void){
2568  digitalWrite(PIN_SHIFT_LAT,LOW);
2569  for(optVAL_t c = 0; (c<32 && !STOP); c++){
2570  digitalWrite(PIN_SHIFT_CLK,LOW);
2571  shiftOut(PIN_SHIFT_DAT,PIN_SHIFT_CLK,MSBFIRST,bitRead(store_bits,c));
2572  }
2573  digitalWrite(PIN_SHIFT_LAT,LOW);
2574  }
2576  #endif
2577 
2580 
2588  inline void writePWM (optVAL_t val);
2590  inline void writePWM(optVAL_t val){
2591  val = min(val,0xFF); val = max(0x0,val);
2592  _pwmValue = val;
2593  }
2594 
2595  #ifdef REPT_TASK
2596  extern void rept_task(void);
2597  DEBUG_MSG("You defined REPT_TASK: you have to define rept_task(void)!");
2598  #else
2599  DEBUG_MSG("You did not define REPT_TASK: rept_task(void) will not have any effect");
2600  #endif
2601 
2602 
2604 
2613  inline void writePin(optVAL_t idx,bool val);
2615  inline void writePin(optVAL_t idx,bool val){
2616  #if EBOARD_SHIFT_REGISTER > 0x0
2617  if(idx>0x63) {
2618  idx -= 0x64;
2619  shiftSingle(idx,val);
2620  return;
2621  }
2622  #endif
2623  #if EBOARD_CHECK_PINS > 0x0
2624  checkIdx(idx);
2625  if(!checkPin(idx))
2626  #endif
2627  #if EBOARD_COPY_AND_PASTE > 0x0
2628  setPin(idx);
2629  #else
2630  pinMode(idx,OUTPUT);
2631  #endif
2632  digitalWrite(idx,val);
2633  }
2635 
2645  inline optVAL_t readPin(optVAL_t idx,bool dig = true);
2647  inline optVAL_t readPin(optVAL_t idx,bool dig){
2648  #if EBOARD_CHECK_PINS > 0x0
2649  if(dig) checkIdx(idx);
2650  #if defined (__AVR_ATmega2560__)
2651  else if (idx<0||idx>0xF){ //use I2C? change => Wire
2652  #else
2653  else if (idx<0||idx>0x7){ //use I2C? change => Wire
2654  #endif
2655  #if EBOARD_DEBUG_MODE > 0x0
2656  assert(false);
2657  #endif
2658  return 0;
2659  }
2660  if(dig && !checkPin(idx,INPUT))
2661  #endif
2662  #if EBOARD_COPY_AND_PASTE > 0x0
2663  setPin(idx,INPUT);
2664  #else
2665  pinMode(idx,INPUT);
2666  #endif
2667  return((dig)? digitalRead(idx) : analogRead(idx));
2668  }
2670 
2671  #if EBOARD_USE_SPI > 0x0 && (EBOARD_NANO == 0x0)
2672 
2674  //won't be commented
2675  struct ServoCds55 {
2676  public:
2677  #if defined(__AVR_ATmega2560__)
2678  ServoCds55(int CS=53);
2679  #else
2680  ServoCds55(int CS=10);
2681  #endif
2682  void begin();
2683  void WritePos(int ID,int Pos);
2684  void write(int ID,int Pos);
2685  inline void setVelocity(int velocity);
2686  inline void setPoslimit(int posLimit);
2687  void SetServoLimit(int ID,int upperLimit);
2688  void SetMotormode(int ID, int velocity);
2689  void SetID(int ID, int newID);
2690  void Reset(int ID);
2691  byte sendWait (const byte what);
2692 
2693  int velocity_temp;
2694  int upperLimit_temp;
2695  optVAL_t cs;
2696  };
2697  ServoCds55::ServoCds55 (int CS):cs(CS) {
2698  velocity_temp = 150;
2699  upperLimit_temp = 300;
2700  }
2701 
2702  void ServoCds55::begin() {
2703  pinMode(cs,OUTPUT);
2704  digitalWrite(cs,HIGH);
2705  SPI.begin ();
2707  }
2708 
2709  byte ServoCds55::sendWait (const byte what) {
2710  byte a = SPI.transfer (what);
2711  delayMicroseconds (20);
2712  return a;
2713  }
2714 
2715  void ServoCds55::setVelocity(int velocity){ //set servo velocity
2716  velocity_temp = velocity;
2717  }
2718 
2719  void ServoCds55::setPoslimit(int posLimit){ // set servo pos limit
2720  upperLimit_temp = posLimit;
2721  }
2722 
2723  void ServoCds55::write(int ID,int Pos){ // Servo Mode
2724  SetServoLimit(ID,upperLimit_temp);
2725  WritePos(ID,Pos);// default velocity:150
2726  }
2727 
2728 
2729  void ServoCds55::WritePos(int ID,int Pos){
2730  int PosB = (Pos>>8 & 0xff);//low
2731  int PosS = (Pos & 0xff);//high
2732  int velocityB = (velocity_temp>>8 & 0xff);
2733  int velocityS = (velocity_temp & 0xff);
2734  digitalWrite(cs, LOW);
2735  sendWait ('p'); sendWait (ID);
2736  sendWait (PosB); sendWait (PosS);
2737  sendWait (velocityB); sendWait (velocityS);
2738  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2739  digitalWrite(cs, HIGH);
2740  delay(10);
2741  }
2742 
2743  void ServoCds55::SetServoLimit(int ID,int upperLimit_temp){
2744  int upperLimitB = (upperLimit_temp>>8 & 0xff);
2745  int upperLimitS = (upperLimit_temp & 0xff);
2746  digitalWrite(cs, LOW);
2747  sendWait ('s'); sendWait (ID);
2748  sendWait (upperLimitB); sendWait (upperLimitS);
2749  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2750  digitalWrite(cs, HIGH);
2751  delay(10);
2752  }
2753 
2754  void ServoCds55::SetMotormode(int ID, int velocity){
2755  int velocityB = (velocity>>8 & 0xff);
2756  int velocityS = (velocity & 0xff);
2757  digitalWrite(cs, LOW);
2758  sendWait ('m'); sendWait (ID);
2759  sendWait (velocityB); sendWait (velocityS);
2760  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2761  digitalWrite(cs, HIGH);
2762  delay(10);
2763  }
2764 
2765  void ServoCds55::SetID(int ID, int newID){
2766  digitalWrite(cs, LOW);
2767  sendWait ('i'); sendWait (ID);
2768  sendWait (newID);
2769  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2770  digitalWrite(cs, HIGH);
2771  delay(10);
2772  }
2773 
2774  void ServoCds55::Reset(int ID){
2775  digitalWrite(cs, LOW);
2776  sendWait ('r'); sendWait (ID);
2777  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2778  digitalWrite(cs, HIGH);
2779  delay(10);
2780  }
2782 
2784  ServoCds55 _servoHandler;
2785  #endif
2786 
2787  #if EBOARD_COPY_AND_PASTE > 0x0 && EBOARD_NANO == 0
2788 
2813  struct SoccerBoard {
2818  inline SoccerBoard(void);
2819  //inline ~SoccerBoard(void) {}
2820  #if EBOARD_USE_UTILITY > 0x0 or defined(__AVR_ATmega2560__) //won't shrink space... just speed things up
2821 
2829  inline void led(int idx,bool state);
2837  inline void ledOn(int idx);
2845  inline void ledOff(int idx);
2851  inline void ledsOff(void);
2857  inline void ledMeter(int);
2858 
2859  #endif
2860  #if EBOARD_USE_UTILITY > 0x0
2861  inline void /*bool*/ button(int);
2864  inline void waitForButton(int);
2865  #endif
2866 
2876  inline void motor(uint8_t id,int16_t val);
2878  inline void motorsOff(void);
2879  //ARDUINO UNO PINOUT
2880  //D0,D1 => Bluetooth connection
2881  //D4,D5 => MotorControl (D5: 980Hz)
2882  //D10,D13 => SPI
2883 
2893  inline void power(optVAL_t id, bool state);
2903  inline void powerOn(optVAL_t id);
2913  inline void powerOff(optVAL_t id);
2919  inline void sleep(uint16_t t);
2925  inline void msleep(uint16_t t);
2933  inline bool digital (optVAL_t id);
2941  inline optVAL_t analog (optVAL_t id);
2943  inline void reset(void); /* use crash-reset? =>*/ /* wdt_enable(WDTO_15MS); while(1) {} */
2944  };
2946  SoccerBoard::SoccerBoard(void) {}
2947 
2948  #if defined(__AVR_ATmega2560__)
2949  inline void SoccerBoard::led(int idx, bool state) {writePin(13,state);}
2950  void SoccerBoard::ledOn(int) {writePin(13,HIGH);}
2951  void SoccerBoard::ledOff(int) {writePin(13,LOW);}
2952  void SoccerBoard::ledsOff(void) {writePin(13,LOW);}
2953  void SoccerBoard::ledMeter(int) {writePin(13,HIGH);}
2954  #elif EBOARD_USE_UTILITY > 0x0
2955  void SoccerBoard::led(int, bool) {}
2956  void SoccerBoard::ledOn(int) {}
2957  void SoccerBoard::ledOff(int) {}
2958  void SoccerBoard::ledsOff(void) {}
2959  void SoccerBoard::ledMeter(int) {}
2960  #endif
2961 
2962  #if EBOARD_USE_UTILITY > 0x0
2963  void SoccerBoard::button(int) {}
2964  void SoccerBoard::waitForButton(int) {}
2965  #endif
2966 
2967  void SoccerBoard::motor(uint8_t id,int16_t val) {
2968  if(id==0&&(val>-256 && val < 256)) {setPin(PIN_MOTOR_DIR,val<0); writePWM(abs(val));}
2969  else if(id>0&&id<3&&(val>-0 && val < 1024)) {_servoHandler.write((id-1),(val *600/1023 - 300));}
2970  }
2971  void SoccerBoard::motorsOff(void) {writePWM(0);}
2972 
2973  void SoccerBoard::reset(void) {
2974  #if EBOARD_USE_RESET > 0x0
2975  wdt_enable(WDTO_15MS);
2976  for(;;) {}
2977  #endif
2978  }
2979 
2980  void SoccerBoard::power(optVAL_t id, bool state) {writePin(id,state);}
2981  void SoccerBoard::powerOn(optVAL_t id) {this->power(id,1);}
2982  void SoccerBoard::powerOff(optVAL_t id) {this->power(id,0);}
2983  void SoccerBoard::sleep(uint16_t t) {delay(1000*t);}
2984  void SoccerBoard::msleep(uint16_t t) {delay(t);}
2985  bool SoccerBoard::digital (optVAL_t id) {return readPin(id);}
2986  optVAL_t SoccerBoard::analog (optVAL_t id) {return readPin(id,0);}
2987 
2989  //To avoid not_found issues
2991  #define DIGITAL_IN 0x0
2992  #define DIGITAL_IN_INV 0x1
2994  #define DIGITAL_IN_PULLUP 0x2
2996  #define DIGITAL_IN_PULLUP_INV 0x3
2998  #define DIGITAL_OUT 0x4
3000  #define DIGITAL_OUT_INV 0x5
3002  #define DIGITAL_OUT_LOW 0x6
3004  #define DIGITAL_OUT_HIGH 0x7
3006  #define ANALOG_IN_8_BIT 0x8
3008  #define ANALOG_IN_10_BIT 0x9
3010  #define ANALOG_IN_MEAN_8_BIT 0xA
3012  #define ANALOG_IN_MEAN_10_BIT 0xB
3014  #define COUNTER_8_BIT 0xC
3016  #define COUNTER_16_BIT 0xD
3018  #define COUNTER_RISE_8_BIT 0xE
3020  #define COUNTER_RISE_16_BIT 0xF
3022  #define PWM_SLOW 0x8
3024  #define PWM_FAST 0x9
3026  #define FREQ_LOW 0xA
3028  #define FREQ_HIGH 0xB
3030  #define COUNTER_B_DIR 0xC
3032  #define COUNTER_B_DIR_PULLUP 0xD
3034  #define COUNTER_MEAN_8_BIT 0xE
3036  #define COUNTER_MEAN_16_BIT 0xF
3038 
3062  struct I2CInOut{
3069  #if EBOARD_USE_UTILITY > 0x0
3070  inline void read(void);
3073  inline void changeAddress(optVAL_t);
3075  inline void changeModes(optVAL_t,optVAL_t,optVAL_t);
3076  #endif
3077 
3081  inline void write(void);
3082 
3084  optVAL_t A; //if you've used uint16_t values you'll have to replace it here
3085  //we only have B - DiOut and C - AO [OUT]
3090  };
3093  this->A=0x0;this->B=0x0;this->C=0x0;
3094  }
3095  #if EBOARD_USE_UTILITY > 0x0
3096  void I2CInOut::read(void) {}
3097  void I2CInOut::changeAddress(optVAL_t){}
3099  #endif
3100  void I2CInOut::write(void){
3101  setPin(PIN_MOTOR_DIR,((this->B)!=0x0));
3102  writePWM(this->C);
3103  }
3105 
3107  struct DynamixelBoard;
3109 
3134  struct AX12Servo {
3139  AX12Servo(void);
3146  AX12Servo(DynamixelBoard &dBoard, optVAL_t servoID); //if borders => setPosLimit
3147 
3149 
3150  #if EBOARD_USE_UTILITY > 0x0
3151 
3158  inline void setID(optVAL_t newID);
3166  inline void changeMotorID(optVAL_t newID); //this should change the hardwareaddress...
3172  inline void setPositionMode(void);
3178  inline void setSpeedMode(void);
3184  inline void setSpeed(optVAL_t);
3186  inline void ledOff(void);
3188  inline void ledOn(void);
3190  inline void setTorque(uint16_t);
3191  #endif
3192 
3200  void setPosition(int pos, int speed=0x3FF);
3208  inline void storePosition(int pos, int speed = 0x3FF);
3214  inline optVAL_t getPosition(void);
3222  inline bool isMoving(void);
3235 
3236  //bool posMode; //we don't care wich mode we are in ^^
3237 
3240  private:
3242  int actPos;
3244  int actSpe;
3245 
3246  }; //shield //set limits auto register for begin
3247 
3249  AX12Servo::AX12Servo(void) {}
3250  #if EBOARD_USE_UTILITY > 0x0
3251  void AX12Servo::setID(optVAL_t newID) {this->id = newID;_servoHandler.SetServoLimit(this->id,_servoHandler.upperLimit_temp);}
3252  void AX12Servo::changeMotorID(optVAL_t newID) {this->id = newID; _servoHandler.SetID(this->id, newID);} //this -should- *does now* change the hardwareaddress...
3253  //IF needed: _servoHandler.setID(this->id, newID);
3254  void AX12Servo::setPositionMode(void) {}
3255  void AX12Servo::setSpeedMode(void) {}
3256  void AX12Servo::setSpeed(optVAL_t) {} //i won't use the rotate functions...
3257  void AX12Servo::ledOff(void) {} //noone needs the AX12-Servo LED
3258  void AX12Servo::ledOn(void) {} //really.... noone ^^
3259  void AX12Servo::setTorque(uint16_t) {} //which damn register? xD
3260  #endif
3261 
3262  void AX12Servo::setPosition(int pos, int speed) {
3263  #if EBOARD_CLAMP > 0x0
3264  if(pos>1023 || speed > 1023) return;
3265  this->actPos=pos; this->storedPos=pos; this->storedSpe = speed;
3266  speed = speed*600/1023 - 300;
3267  pos = pos *600/1023 - 300;
3268 
3269  #else
3270  if(pos>300 || speed > 300) return;
3271  this->actPos=pos; this->storedPos=pos; this->storedSpe = speed;
3272  #endif
3273  if(speed != actSpe){ _servoHandler.setVelocity(speed); this->actSpe=speed;}
3274  _servoHandler.write(this->id,pos);
3275  }
3277  return this->actPos; //when moving... false value;
3278  }
3279  bool AX12Servo::isMoving(void) {return false;} //we don't know^^
3281 
3309  inline DynamixelBoard(SoccerBoard&);
3310  //inline ~DynamixelBoard(void) {}
3311  #if EBOARD_USE_UTILITY > 0x0
3312  inline void changeId(optVAL_t);
3315  inline void changeMotorID(optVAL_t);
3317  inline void ledOn(optVAL_t);
3319  inline void ledOff(optVAL_t);
3320  #endif
3321  inline void action(void);
3323 
3325  friend struct AX12Servo;
3326  protected:
3333  };
3336  for(optVAL_t i = 0; i < EBOARD_SPI_SERVO_MAX; i++ ) {this->connected[i] = NULL;} //wanna use nullptr... wanna have c++11^^
3337  }
3338  //inline ~DynamixelBoard(void) {}
3339  #if EBOARD_USE_UTILITY > 0x0
3344  #endif
3345  void DynamixelBoard::action(void) {
3346  for(optVAL_t i = 0; (i < EBOARD_SPI_SERVO_MAX && !STOP); i++ ){
3347  if(this->connected[i] != NULL)
3348  (*connected[i]).setPosition((*connected[i]).storedPos,(*connected[i]).storedSpe);
3349  }
3350  }
3351 
3352 
3353  void AX12Servo::storePosition(int pos, int speed){
3354  if(this->id < EBOARD_SPI_SERVO_MAX) _conBoard->connected[this->id] = this;
3355  this->storedPos=pos;this->storedSpe=speed;
3356  }
3357  AX12Servo::AX12Servo(DynamixelBoard &dBoard, optVAL_t servoID): _conBoard( &dBoard),id(servoID-1), actSpe(0x96) {
3358  //#if EBOARD_DEBUG_MODE > 0x0
3359  // assert(servoID<EBOARD_SPI_SERVO_MAX);
3360  //#endif
3361  }
3363  #endif
3364  #if EBOARD_BLUETOOTH > 0x0
3365 
3394  struct RB14Scan {
3398  inline RB14Scan(void);
3401  inline int raw(optVAL_t);
3404  inline char channel(optVAL_t);
3410  inline void write(const char* const val);
3411  };
3412 
3414  inline RB14Scan::RB14Scan(void) {}
3415  inline int RB14Scan::raw(optVAL_t) {return isConnected();}
3416  inline char RB14Scan::channel(optVAL_t) {return ((isConnected())?(readVal()):(-1));}
3417  inline void RB14Scan::write(const char* const val) {writeVal(val);}
3419 
3427  #endif
3428 #if EBOARD_I2C > 0x0
3429 
3444  inline optVAL_t sendI2C(optVAL_t deviceID,byte *buf, byte buf_len);
3445 
3460  inline optVAL_t sendI2C(optVAL_t deviceID, byte buf);
3461 
3470  inline void pingI2C(optVAL_t ret[], optVAL_t ret_len);
3472  inline void pingI2C(optVAL_t ret[], optVAL_t ret_len){
3473  optVAL_t count = 0;
3474  for (byte i = 1; (i < 255 && !STOP); i++) /*ignore special*/ {
3475  if(i==200)continue; //internal
3476  Wire.beginTransmission (i);
3477  if (Wire.endTransmission () == 0) {
3478  if(count < ret_len) ret[count] = i;
3479  count++;
3480  delay (1);
3481  }
3482  }
3483  }
3484  inline optVAL_t sendI2C(optVAL_t deviceID,byte *buf, byte buf_len) {
3485  Wire.beginTransmission(deviceID);
3486  Wire.write(buf,buf_len);
3487  return Wire.endTransmission();
3488  }
3489 
3490  inline optVAL_t sendI2C(optVAL_t deviceID, byte buf){
3491  Wire.beginTransmission(deviceID);
3492  Wire.write(buf);
3493  return Wire.endTransmission();
3494  }
3496 
3507  inline void readI2C(optVAL_t deviceID, optVAL_t ret[], optVAL_t ret_len,bool blocking=true);
3509  inline void readI2C(optVAL_t deviceID,optVAL_t ret[] , optVAL_t ret_len,bool blocking) {
3510  for(optVAL_t rect = 0x0; (Wire.available() || (((blocking && (rect < ret_len))) && (!STOP))); rect++)
3511  ret[rect] = Wire.read();
3512  }
3514 
3515  //Beginof LCD configuration
3516  #if EBOARD_LCD > 0x0
3517 
3518  PROGMEM const byte basicFont[][8] = {
3519  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
3520  {0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00},
3521  {0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00},
3522  {0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00},
3523  {0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00},
3524  {0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00},
3525  {0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00},
3526  {0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00},
3527  {0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00},
3528  {0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00},
3529  {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00},
3530  {0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00},
3531  {0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00},
3532  {0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00},
3533  {0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00},
3534  {0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00},
3535  {0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00},
3536  {0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00},
3537  {0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00},
3538  {0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00},
3539  {0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00},
3540  {0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00},
3541  {0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00},
3542  {0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00},
3543  {0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00},
3544  {0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00},
3545  {0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00},
3546  {0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00},
3547  {0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00},
3548  {0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00},
3549  {0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00},
3550  {0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00},
3551  {0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00},
3552  {0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00},
3553  {0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00},
3554  {0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00},
3555  {0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00},
3556  {0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00},
3557  {0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00},
3558  {0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00},
3559  {0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00},
3560  {0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00},
3561  {0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00},
3562  {0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00},
3563  {0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00},
3564  {0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00},
3565  {0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00},
3566  {0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00},
3567  {0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00},
3568  {0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00},
3569  {0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00},
3570  {0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00},
3571  {0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00},
3572  {0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00},
3573  {0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00},
3574  {0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00},
3575  {0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00},
3576  {0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00},
3577  {0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00},
3578  {0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00},
3579  {0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00},
3580  {0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00},
3581  {0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00},
3582  {0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00},
3583  {0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00},
3584  {0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00},
3585  {0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00},
3586  {0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00},
3587  {0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00},
3588  {0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00},
3589  {0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00},
3590  {0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00},
3591  {0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00},
3592  {0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00},
3593  {0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00},
3594  {0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00},
3595  {0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00},
3596  {0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00},
3597  {0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00},
3598  {0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00},
3599  {0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00},
3600  {0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00},
3601  {0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00},
3602  {0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00},
3603  {0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00},
3604  {0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00},
3605  {0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00},
3606  {0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00},
3607  {0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00},
3608  {0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00},
3609  {0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00},
3610  {0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00},
3611  {0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},
3612  {0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00},
3613  {0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00},
3614  {0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00}
3615  };
3616  /*
3617  * @note if you don't mind the space this is the extended font set!
3618  *
3619  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
3620  {0x7E,0x81,0x95,0xB1,0xB1,0x95,0x81,0x7E}, // 0x01
3621  {0x7E,0xFF,0xEB,0xCF,0xCF,0xEB,0xFF,0x7E}, // 0x02
3622  {0x0E,0x1F,0x3F,0x7E,0x3F,0x1F,0x0E,0x00}, // 0x03
3623  {0x08,0x1C,0x3E,0x7F,0x3E,0x1C,0x08,0x00}, // 0x04
3624  {0x38,0x3A,0x9F,0xFF,0x9F,0x3A,0x38,0x00}, // 0x05
3625  {0x10,0x38,0xBC,0xFF,0xBC,0x38,0x10,0x00}, // 0x06
3626  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
3627  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
3628  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
3629  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
3630  {0x70,0xF8,0x88,0x88,0xFD,0x7F,0x07,0x0F}, // 0x0B
3631  {0x00,0x4E,0x5F,0xF1,0xF1,0x5F,0x4E,0x00}, // 0x0C
3632  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
3633  {0xC0,0xFF,0x7F,0x05,0x05,0x65,0x7F,0x3F}, // 0x0E
3634  {0x99,0x5A,0x3C,0xE7,0xE7,0x3C,0x5A,0x99}, // 0x0F
3635  {0x7F,0x3E,0x3E,0x1C,0x1C,0x08,0x08,0x00}, // 0x10
3636  {0x08,0x08,0x1C,0x1C,0x3E,0x3E,0x7F,0x00}, // 0x11
3637  {0x00,0x24,0x66,0xFF,0xFF,0x66,0x24,0x00}, // 0x12
3638  {0x00,0x5F,0x5F,0x00,0x00,0x5F,0x5F,0x00}, // 0x13
3639  {0x06,0x0F,0x09,0x7F,0x7F,0x01,0x7F,0x7F}, // 0x14
3640  {0xDA,0xBF,0xA5,0xA5,0xFD,0x59,0x03,0x02}, // 0x15
3641  {0x00,0x70,0x70,0x70,0x70,0x70,0x70,0x00}, // 0x16
3642  {0x80,0x94,0xB6,0xFF,0xFF,0xB6,0x94,0x80}, // 0x17
3643  {0x00,0x04,0x06,0x7F,0x7F,0x06,0x04,0x00}, // 0x18
3644  {0x00,0x10,0x30,0x7F,0x7F,0x30,0x10,0x00}, // 0x19
3645  {0x08,0x08,0x08,0x2A,0x3E,0x1C,0x08,0x00}, // 0x1A
3646  {0x08,0x1C,0x3E,0x2A,0x08,0x08,0x08,0x00}, // 0x1B
3647  {0x3C,0x3C,0x20,0x20,0x20,0x20,0x20,0x00}, // 0x1C
3648  {0x08,0x1C,0x3E,0x08,0x08,0x3E,0x1C,0x08}, // 0x1D
3649  {0x30,0x38,0x3C,0x3E,0x3E,0x3C,0x38,0x30}, // 0x1E
3650  {0x06,0x0E,0x1E,0x3E,0x3E,0x1E,0x0E,0x06}, // 0x1F
3651  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
3652  {0x00,0x06,0x5F,0x5F,0x06,0x00,0x00,0x00}, // 0x21
3653  {0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00}, // 0x22
3654  {0x14,0x7F,0x7F,0x14,0x7F,0x7F,0x14,0x00}, // 0x23
3655  {0x24,0x2E,0x6B,0x6B,0x3A,0x12,0x00,0x00}, // 0x24
3656  {0x46,0x66,0x30,0x18,0x0C,0x66,0x62,0x00}, // 0x25
3657  {0x30,0x7A,0x4F,0x5D,0x37,0x7A,0x48,0x00}, // 0x26
3658  {0x04,0x07,0x03,0x00,0x00,0x00,0x00,0x00}, // 0x27
3659  {0x00,0x1C,0x3E,0x63,0x41,0x00,0x00,0x00}, // 0x28
3660  {0x00,0x41,0x63,0x3E,0x1C,0x00,0x00,0x00}, // 0x29
3661  {0x08,0x2A,0x3E,0x1C,0x1C,0x3E,0x2A,0x08}, // 0x2A
3662  {0x08,0x08,0x3E,0x3E,0x08,0x08,0x00,0x00}, // 0x2B
3663  {0x00,0xA0,0xE0,0x60,0x00,0x00,0x00,0x00}, // 0x2C
3664  {0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, // 0x2D
3665  {0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00}, // 0x2E
3666  {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // 0x2F
3667  {0x3E,0x7F,0x59,0x4D,0x7F,0x3E,0x00,0x00}, // 0x30
3668  {0x42,0x42,0x7F,0x7F,0x40,0x40,0x00,0x00}, // 0x31
3669  {0x62,0x73,0x59,0x49,0x6F,0x66,0x00,0x00}, // 0x32
3670  {0x22,0x63,0x49,0x49,0x7F,0x36,0x00,0x00}, // 0x33
3671  {0x18,0x1C,0x16,0x13,0x7F,0x7F,0x10,0x00}, // 0x34
3672  {0x27,0x67,0x45,0x45,0x7D,0x39,0x00,0x00}, // 0x35
3673  {0x3C,0x7E,0x4B,0x49,0x79,0x30,0x00,0x00}, // 0x36
3674  {0x03,0x63,0x71,0x19,0x0F,0x07,0x00,0x00}, // 0x37
3675  {0x36,0x7F,0x49,0x49,0x7F,0x36,0x00,0x00}, // 0x38
3676  {0x06,0x4F,0x49,0x69,0x3F,0x1E,0x00,0x00}, // 0x39
3677  {0x00,0x00,0x6C,0x6C,0x00,0x00,0x00,0x00}, // 0x3A
3678  {0x00,0xA0,0xEC,0x6C,0x00,0x00,0x00,0x00}, // 0x3B
3679  {0x08,0x1C,0x36,0x63,0x41,0x00,0x00,0x00}, // 0x3C
3680  {0x14,0x14,0x14,0x14,0x14,0x14,0x00,0x00}, // 0x3D
3681  {0x00,0x41,0x63,0x36,0x1C,0x08,0x00,0x00}, // 0x3E
3682  {0x02,0x03,0x51,0x59,0x0F,0x06,0x00,0x00}, // 0x3F
3683  {0x3E,0x7F,0x41,0x5D,0x5D,0x1F,0x1E,0x00}, // 0x40
3684  {0x7C,0x7E,0x13,0x13,0x7E,0x7C,0x00,0x00}, // 0x41
3685  {0x41,0x7F,0x7F,0x49,0x49,0x7F,0x36,0x00}, // 0x42
3686  {0x1C,0x3E,0x63,0x41,0x41,0x63,0x22,0x00}, // 0x43
3687  {0x41,0x7F,0x7F,0x41,0x63,0x7F,0x1C,0x00}, // 0x44
3688  {0x41,0x7F,0x7F,0x49,0x5D,0x41,0x63,0x00}, // 0x45
3689  {0x41,0x7F,0x7F,0x49,0x1D,0x01,0x03,0x00}, // 0x46
3690  {0x1C,0x3E,0x63,0x41,0x51,0x73,0x72,0x00}, // 0x47
3691  {0x7F,0x7F,0x08,0x08,0x7F,0x7F,0x00,0x00}, // 0x48
3692  {0x00,0x41,0x7F,0x7F,0x41,0x00,0x00,0x00}, // 0x49
3693  {0x30,0x70,0x40,0x41,0x7F,0x3F,0x01,0x00}, // 0x4A
3694  {0x41,0x7F,0x7F,0x08,0x1C,0x77,0x63,0x00}, // 0x4B
3695  {0x41,0x7F,0x7F,0x41,0x40,0x60,0x70,0x00}, // 0x4C
3696  {0x7F,0x7F,0x06,0x0C,0x06,0x7F,0x7F,0x00}, // 0x4D
3697  {0x7F,0x7F,0x06,0x0C,0x18,0x7F,0x7F,0x00}, // 0x4E
3698  {0x1C,0x3E,0x63,0x41,0x63,0x3E,0x1C,0x00}, // 0x4F
3699  {0x41,0x7F,0x7F,0x49,0x09,0x0F,0x06,0x00}, // 0x50
3700  {0x1E,0x3F,0x21,0x71,0x7F,0x5E,0x00,0x00}, // 0x51
3701  {0x41,0x7F,0x7F,0x19,0x39,0x6F,0x46,0x00}, // 0x52
3702  {0x26,0x67,0x4D,0x59,0x7B,0x32,0x00,0x00}, // 0x53
3703  {0x03,0x41,0x7F,0x7F,0x41,0x03,0x00,0x00}, // 0x54
3704  {0x7F,0x7F,0x40,0x40,0x7F,0x7F,0x00,0x00}, // 0x55
3705  {0x1F,0x3F,0x60,0x60,0x3F,0x1F,0x00,0x00}, // 0x56
3706  {0x7F,0x7F,0x30,0x18,0x30,0x7F,0x7F,0x00}, // 0x57
3707  {0x63,0x77,0x1C,0x08,0x1C,0x77,0x63,0x00}, // 0x58
3708  {0x07,0x4F,0x78,0x78,0x4F,0x07,0x00,0x00}, // 0x59
3709  {0x67,0x73,0x59,0x4D,0x47,0x63,0x71,0x00}, // 0x5A
3710  {0x00,0x7F,0x7F,0x41,0x41,0x00,0x00,0x00}, // 0x5B
3711  {0x01,0x03,0x06,0x0C,0x18,0x30,0x60,0x00}, // 0x5C
3712  {0x00,0x41,0x41,0x7F,0x7F,0x00,0x00,0x00}, // 0x5D
3713  {0x08,0x0C,0x06,0x03,0x06,0x0C,0x08,0x00}, // 0x5E
3714  {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80}, // 0x5F
3715  {0x00,0x00,0x03,0x07,0x04,0x00,0x00,0x00}, // 0x60
3716  {0x20,0x74,0x54,0x54,0x3C,0x78,0x40,0x00}, // 0x61
3717  {0x41,0x3F,0x7F,0x44,0x44,0x7C,0x38,0x00}, // 0x62
3718  {0x38,0x7C,0x44,0x44,0x6C,0x28,0x00,0x00}, // 0x63
3719  {0x30,0x78,0x48,0x49,0x3F,0x7F,0x40,0x00}, // 0x64
3720  {0x38,0x7C,0x54,0x54,0x5C,0x18,0x00,0x00}, // 0x65
3721  {0x48,0x7E,0x7F,0x49,0x03,0x02,0x00,0x00}, // 0x66
3722  {0x98,0xBC,0xA4,0xA4,0xF8,0x7C,0x04,0x00}, // 0x67
3723  {0x41,0x7F,0x7F,0x08,0x04,0x7C,0x78,0x00}, // 0x68
3724  {0x00,0x44,0x7D,0x7D,0x40,0x00,0x00,0x00}, // 0x69
3725  {0x40,0xC4,0x84,0xFD,0x7D,0x00,0x00,0x00}, // 0x6A
3726  {0x41,0x7F,0x7F,0x10,0x38,0x6C,0x44,0x00}, // 0x6B
3727  {0x00,0x41,0x7F,0x7F,0x40,0x00,0x00,0x00}, // 0x6C
3728  {0x7C,0x7C,0x0C,0x18,0x0C,0x7C,0x78,0x00}, // 0x6D
3729  {0x7C,0x7C,0x04,0x04,0x7C,0x78,0x00,0x00}, // 0x6E
3730  {0x38,0x7C,0x44,0x44,0x7C,0x38,0x00,0x00}, // 0x6F
3731  {0x84,0xFC,0xF8,0xA4,0x24,0x3C,0x18,0x00}, // 0x70
3732  {0x18,0x3C,0x24,0xA4,0xF8,0xFC,0x84,0x00}, // 0x71
3733  {0x44,0x7C,0x78,0x44,0x1C,0x18,0x00,0x00}, // 0x72
3734  {0x48,0x5C,0x54,0x54,0x74,0x24,0x00,0x00}, // 0x73
3735  {0x00,0x04,0x3E,0x7F,0x44,0x24,0x00,0x00}, // 0x74
3736  {0x3C,0x7C,0x40,0x40,0x3C,0x7C,0x40,0x00}, // 0x75
3737  {0x1C,0x3C,0x60,0x60,0x3C,0x1C,0x00,0x00}, // 0x76
3738  {0x3C,0x7C,0x60,0x30,0x60,0x7C,0x3C,0x00}, // 0x77
3739  {0x44,0x6C,0x38,0x10,0x38,0x6C,0x44,0x00}, // 0x78
3740  {0x9C,0xBC,0xA0,0xA0,0xFC,0x7C,0x00,0x00}, // 0x79
3741  {0x4C,0x64,0x74,0x5C,0x4C,0x64,0x00,0x00}, // 0x7A
3742  {0x08,0x08,0x3E,0x77,0x41,0x41,0x00,0x00}, // 0x7B
3743  {0x00,0x00,0x00,0x77,0x77,0x00,0x00,0x00}, // 0x7C
3744  {0x41,0x41,0x77,0x3E,0x08,0x08,0x00,0x00}, // 0x7D
3745  {0x02,0x03,0x01,0x03,0x02,0x03,0x01,0x00}, // 0x7E
3746  {0x78,0x7C,0x46,0x43,0x46,0x7C,0x78,0x00}, // 0x7F
3747  {0x1E,0xBF,0xE1,0x61,0x33,0x12,0x00,0x00}, // 0x80
3748  {0x3A,0x7A,0x40,0x40,0x7A,0x7A,0x40,0x00}, // 0x81
3749  {0x38,0x7C,0x56,0x57,0x5D,0x18,0x00,0x00}, // 0x82
3750  {0x02,0x23,0x75,0x55,0x55,0x7D,0x7B,0x42}, // 0x83
3751  {0x21,0x75,0x54,0x54,0x7D,0x79,0x40,0x00}, // 0x84
3752  {0x20,0x75,0x57,0x56,0x7C,0x78,0x40,0x00}, // 0x85
3753  {0x00,0x22,0x77,0x55,0x55,0x7F,0x7A,0x40}, // 0x86
3754  {0x1C,0xBE,0xE2,0x62,0x36,0x14,0x00,0x00}, // 0x87
3755  {0x02,0x3B,0x7D,0x55,0x55,0x5D,0x1B,0x02}, // 0x88
3756  {0x39,0x7D,0x54,0x54,0x5D,0x19,0x00,0x00}, // 0x89
3757  {0x38,0x7D,0x57,0x56,0x5C,0x18,0x00,0x00}, // 0x8A
3758  {0x01,0x45,0x7C,0x7C,0x41,0x01,0x00,0x00}, // 0x8B
3759  {0x02,0x03,0x45,0x7D,0x7D,0x43,0x02,0x00}, // 0x8C
3760  {0x00,0x45,0x7F,0x7E,0x40,0x00,0x00,0x00}, // 0x8D
3761  {0x79,0x7D,0x26,0x26,0x7D,0x79,0x00,0x00}, // 0x8E
3762  {0x70,0x7A,0x2D,0x2D,0x7A,0x70,0x00,0x00}, // 0x8F
3763  {0x44,0x7C,0x7E,0x57,0x55,0x44,0x00,0x00}, // 0x90
3764  {0x20,0x74,0x54,0x54,0x7C,0x7C,0x54,0x54}, // 0x91
3765  {0x7C,0x7E,0x0B,0x09,0x7F,0x7F,0x49,0x00}, // 0x92
3766  {0x32,0x7B,0x49,0x49,0x7B,0x32,0x00,0x00}, // 0x93
3767  {0x32,0x7A,0x48,0x48,0x7A,0x32,0x00,0x00}, // 0x94
3768  {0x30,0x79,0x4B,0x4A,0x78,0x30,0x00,0x00}, // 0x95
3769  {0x3A,0x7B,0x41,0x41,0x7B,0x7A,0x40,0x00}, // 0x96
3770  {0x38,0x79,0x43,0x42,0x78,0x78,0x40,0x00}, // 0x97
3771  {0xBA,0xBA,0xA0,0xA0,0xFA,0x7A,0x00,0x00}, // 0x98
3772  {0x39,0x7D,0x44,0x44,0x44,0x7D,0x39,0x00}, // 0x99
3773  {0x3D,0x7D,0x40,0x40,0x7D,0x3D,0x00,0x00}, // 0x9A
3774  {0x38,0x7C,0x64,0x54,0x4C,0x7C,0x38,0x00}, // 0x9B
3775  {0x68,0x7E,0x7F,0x49,0x43,0x66,0x20,0x00}, // 0x9C
3776  {0x5C,0x3E,0x73,0x49,0x67,0x3E,0x1D,0x00}, // 0x9D
3777  {0x44,0x6C,0x38,0x38,0x6C,0x44,0x00,0x00}, // 0x9E
3778  {0x40,0xC8,0x88,0xFE,0x7F,0x09,0x0B,0x02}, // 0x9F
3779  {0x20,0x74,0x56,0x57,0x7D,0x78,0x40,0x00}, // 0xA0
3780  {0x00,0x44,0x7E,0x7F,0x41,0x00,0x00,0x00}, // 0xA1
3781  {0x30,0x78,0x48,0x4A,0x7B,0x31,0x00,0x00}, // 0xA2
3782  {0x38,0x78,0x40,0x42,0x7B,0x79,0x40,0x00}, // 0xA3
3783  {0x7A,0x7B,0x09,0x0B,0x7A,0x73,0x01,0x00}, // 0xA4
3784  {0x7A,0x7B,0x19,0x33,0x7A,0x7B,0x01,0x00}, // 0xA5
3785  {0x00,0x26,0x2F,0x29,0x2F,0x2F,0x28,0x00}, // 0xA6
3786  {0x00,0x26,0x2F,0x29,0x29,0x2F,0x26,0x00}, // 0xA7
3787  {0x30,0x78,0x4D,0x45,0x60,0x20,0x00,0x00}, // 0xA8
3788  {0x1C,0x22,0x7D,0x4B,0x5B,0x65,0x22,0x1C}, // 0xA9
3789  {0x08,0x08,0x08,0x08,0x38,0x38,0x00,0x00}, // 0xAA
3790  {0x61,0x3F,0x1F,0xCC,0xEE,0xAB,0xB9,0x90}, // 0xAB
3791  {0x61,0x3F,0x1F,0x4C,0x66,0x73,0xD9,0xF8}, // 0xAC
3792  {0x00,0x00,0x60,0xFA,0xFA,0x60,0x00,0x00}, // 0xAD
3793  {0x08,0x1C,0x36,0x22,0x08,0x1C,0x36,0x22}, // 0xAE
3794  {0x22,0x36,0x1C,0x08,0x22,0x36,0x1C,0x08}, // 0xAF
3795  {0xAA,0x00,0x55,0x00,0xAA,0x00,0x55,0x00}, // 0xB0
3796  {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55}, // 0xB1
3797  {0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF}, // 0xB2
3798  {0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00}, // 0xB3
3799  {0x10,0x10,0x10,0xFF,0xFF,0x00,0x00,0x00}, // 0xB4
3800  {0x70,0x78,0x2C,0x2E,0x7B,0x71,0x00,0x00}, // 0xB5
3801  {0x72,0x79,0x2D,0x2D,0x79,0x72,0x00,0x00}, // 0xB6
3802  {0x71,0x7B,0x2E,0x2C,0x78,0x70,0x00,0x00}, // 0xB7
3803  {0x1C,0x22,0x5D,0x55,0x55,0x41,0x22,0x1C}, // 0xB8
3804  {0x14,0x14,0xF7,0xF7,0x00,0xFF,0xFF,0x00}, // 0xB9
3805  {0x00,0x00,0xFF,0xFF,0x00,0xFF,0xFF,0x00}, // 0xBA
3806  {0x14,0x14,0xF4,0xF4,0x04,0xFC,0xFC,0x00}, // 0xBB
3807  {0x14,0x14,0x17,0x17,0x10,0x1F,0x1F,0x00}, // 0xBC
3808  {0x18,0x3C,0x24,0xE7,0xE7,0x24,0x24,0x00}, // 0xBD
3809  {0x2B,0x2F,0xFC,0xFC,0x2F,0x2B,0x00,0x00}, // 0xBE
3810  {0x10,0x10,0x10,0xF0,0xF0,0x00,0x00,0x00}, // 0xBF
3811  {0x00,0x00,0x00,0x1F,0x1F,0x10,0x10,0x10}, // 0xC0
3812  {0x10,0x10,0x10,0x1F,0x1F,0x10,0x10,0x10}, // 0xC1
3813  {0x10,0x10,0x10,0xF0,0xF0,0x10,0x10,0x10}, // 0xC2
3814  {0x00,0x00,0x00,0xFF,0xFF,0x10,0x10,0x10}, // 0xC3
3815  {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10}, // 0xC4
3816  {0x10,0x10,0x10,0xFF,0xFF,0x10,0x10,0x10}, // 0xC5
3817  {0x22,0x77,0x55,0x57,0x7E,0x7B,0x41,0x00}, // 0xC6
3818  {0x72,0x7B,0x2D,0x2F,0x7A,0x73,0x01,0x00}, // 0xC7
3819  {0x00,0x00,0x1F,0x1F,0x10,0x17,0x17,0x14}, // 0xC8
3820  {0x00,0x00,0xFC,0xFC,0x04,0xF4,0xF4,0x14}, // 0xC9
3821  {0x14,0x14,0x17,0x17,0x10,0x17,0x17,0x14}, // 0xCA
3822  {0x14,0x14,0xF4,0xF4,0x04,0xF4,0xF4,0x14}, // 0xCB
3823  {0x00,0x00,0xFF,0xFF,0x00,0xF7,0xF7,0x14}, // 0xCC
3824  {0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14}, // 0xCD
3825  {0x14,0x14,0xF7,0xF7,0x00,0xF7,0xF7,0x14}, // 0xCE
3826  {0x66,0x3C,0x3C,0x24,0x3C,0x3C,0x66,0x00}, // 0xCF
3827  {0x05,0x27,0x72,0x57,0x7D,0x38,0x00,0x00}, // 0xD0
3828  {0x49,0x7F,0x7F,0x49,0x63,0x7F,0x1C,0x00}, // 0xD1
3829  {0x46,0x7D,0x7D,0x55,0x55,0x46,0x00,0x00}, // 0xD2
3830  {0x45,0x7D,0x7C,0x54,0x55,0x45,0x00,0x00}, // 0xD3
3831  {0x44,0x7D,0x7F,0x56,0x54,0x44,0x00,0x00}, // 0xD4
3832  {0x0A,0x0E,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xD5
3833  {0x00,0x44,0x7E,0x7F,0x45,0x00,0x00,0x00}, // 0xD6
3834  {0x02,0x45,0x7D,0x7D,0x45,0x02,0x00,0x00}, // 0xD7
3835  {0x01,0x45,0x7C,0x7C,0x45,0x01,0x00,0x00}, // 0xD8
3836  {0x10,0x10,0x10,0x1F,0x1F,0x00,0x00,0x00}, // 0xD9
3837  {0x00,0x00,0x00,0xF0,0xF0,0x10,0x10,0x10}, // 0xDA
3838  {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, // 0xDB
3839  {0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0}, // 0xDC
3840  {0x00,0x00,0x00,0x77,0x77,0x00,0x00,0x00}, // 0xDD
3841  {0x00,0x45,0x7F,0x7E,0x44,0x00,0x00,0x00}, // 0xDE
3842  {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}, // 0xDF
3843  {0x38,0x7C,0x46,0x47,0x45,0x7C,0x38,0x00}, // 0xE0
3844  {0xFC,0xFE,0x2A,0x2A,0x3E,0x14,0x00,0x00}, // 0xE1
3845  {0x3A,0x7D,0x45,0x45,0x45,0x7D,0x3A,0x00}, // 0xE2
3846  {0x38,0x7C,0x45,0x47,0x46,0x7C,0x38,0x00}, // 0xE3
3847  {0x32,0x7B,0x49,0x4B,0x7A,0x33,0x01,0x00}, // 0xE4
3848  {0x3A,0x7F,0x45,0x47,0x46,0x7F,0x39,0x00}, // 0xE5
3849  {0x80,0xFE,0x7E,0x20,0x20,0x3E,0x1E,0x00}, // 0xE6
3850  {0x42,0x7E,0x7E,0x54,0x1C,0x08,0x00,0x00}, // 0xE7
3851  {0x41,0x7F,0x7F,0x55,0x14,0x1C,0x08,0x00}, // 0xE8
3852  {0x3C,0x7C,0x42,0x43,0x7D,0x3C,0x00,0x00}, // 0xE9
3853  {0x3A,0x79,0x41,0x41,0x79,0x3A,0x00,0x00}, // 0xEA
3854  {0x3C,0x7D,0x43,0x42,0x7C,0x3C,0x00,0x00}, // 0xEB
3855  {0xB8,0xB8,0xA2,0xA3,0xF9,0x78,0x00,0x00}, // 0xEC
3856  {0x0C,0x5C,0x72,0x73,0x5D,0x0C,0x00,0x00}, // 0xED
3857  {0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00}, // 0xEE
3858  {0x00,0x00,0x02,0x03,0x01,0x00,0x00,0x00}, // 0xEF
3859  {0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00}, // 0xF0
3860  {0x44,0x44,0x5F,0x5F,0x44,0x44,0x00,0x00}, // 0xF1
3861  {0x28,0x28,0x28,0x28,0x28,0x28,0x00,0x00}, // 0xF2
3862  {0x71,0x35,0x1F,0x4C,0x66,0x73,0xD9,0xF8}, // 0xF3
3863  {0x06,0x0F,0x09,0x7F,0x7F,0x01,0x7F,0x7F}, // 0xF4
3864  {0xDA,0xBF,0xA5,0xA5,0xFD,0x59,0x03,0x02}, // 0xF5
3865  {0x08,0x08,0x6B,0x6B,0x08,0x08,0x00,0x00}, // 0xF6
3866  {0x00,0x80,0xC0,0x40,0x00,0x00,0x00,0x00}, // 0xF7
3867  {0x00,0x06,0x0F,0x09,0x0F,0x06,0x00,0x00}, // 0xF8
3868  {0x02,0x02,0x00,0x00,0x02,0x02,0x00,0x00}, // 0xF9
3869  {0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00}, // 0xFA
3870  {0x00,0x12,0x13,0x1F,0x1F,0x10,0x10,0x00}, // 0xFB
3871  {0x00,0x11,0x15,0x15,0x1F,0x1F,0x0A,0x00}, // 0xFC
3872  {0x00,0x19,0x1D,0x15,0x17,0x12,0x00,0x00}, // 0xFD
3873  {0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00}, // 0xFE
3874  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
3875  */
3876 
3877  //Definition of OLED Constants
3879  #define LCD_COMMAND_MODE 0x80
3880  #define LCD_DATA_MODE 0x40
3882  #define LCD_COMMAND_DISPLAY_OFF 0xAE
3884  #define LCD_COMMAND_DISPLAY_ON 0xAF
3886  #define LCD_COMMAND_BLACK_BACKGROUND 0xA6
3888  #define LCD_COMMAND_WHITE_BACKGROUND 0xA7
3890  #define LCD_COMMAND_SET_BRIGHTNESS 0x81
3892  #define LCD_PAGE_ADDRESSING 0x02
3894  #define LCD_HORIZONTAL_ADDRESSING 0x00
3896  //The regulator
3898  #define LCD_COMMAND_CHARGE_PUMP_SETTING 0x8d
3899  #define LCD_COMMAND_CHARGE_PUMP_ENABLE 0x14
3901 
3902  #ifndef LCD_WIDTH
3903  #define LCD_WIDTH 128
3905  #endif
3906  #ifndef LCD_HEIGHT
3907  #define LCD_HEIGHT 64
3909  #endif
3910 
3951  struct LCD {
3952  #if EBOARD_NANO == 0
3953 
3961  LCD(SoccerBoard &soccerBoard, optVAL_t id=0x3C);
3962  #else
3963  LCD(optVAL_t id=0x3C);
3964  #endif
3965 
3979  inline bool changeID(optVAL_t newID = 0x3C);
3990  inline bool clear(void);
3996  inline void print(const char* data);
4002  inline void print(int data);
4010  inline void print(optVAL_t line, optVAL_t col, const char* data);
4018  inline void print(optVAL_t line, optVAL_t col, int data);
4027  inline void lightOn(void);
4036  inline void lightOff(void);
4047  inline bool reset(void);
4048 
4049  //added features
4062  inline bool init(void);
4072  inline void drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY);
4080  inline void changeMode(bool newMode = true);
4094  inline bool setCursor(byte posX = 0x0, byte posY = 0x0);
4107  inline bool changeBrightness (byte val = 0x64);
4117  inline void changeBackground(bool newBackground = false);
4120  private:
4124  byte pX;
4127  byte pY;
4129  bool _cI;
4130 
4137  inline void s2Cmd(optVAL_t o, optVAL_t t);
4150  inline bool s1Cmd(optVAL_t o);
4156  inline void s1Dat(optVAL_t o);
4157 
4158  };
4160  #if EBOARD_NANO == 0x0
4161  LCD::LCD(SoccerBoard &soccerBoard, optVAL_t id) {
4162  this->_cI = false;
4163  this->ID = id;
4164  //this->init();
4165  }
4166  #else
4167  LCD::LCD( optVAL_t id) {
4168  this->_cI = false;
4169  this->ID = id;
4170  //this->init();
4171  }
4172  #endif
4173  inline bool LCD::changeID(optVAL_t newID) {
4174  this->ID = newID;
4175  return this->init();
4176  }
4177  inline bool LCD::clear(void) {
4178  if(!this->_cI) this->init();
4179  for(byte i = 0; i < 8; i++){
4180  //maybe *8
4181  setCursor(0,i);
4182 
4183  for (byte j = 0; j < 128; j++)
4184  this->s1Dat(0);
4185  }
4186  return setCursor(0,0);
4187  }
4188  void LCD::print(optVAL_t line, optVAL_t col, const char *data) {
4189  if(!this->_cI) this->init();
4190  byte i = 0x0;
4191  if(col < ((LCD_WIDTH-1)/8.0) && line < ((LCD_HEIGHT-1)/8.0)) {
4192  setCursor(col,line);
4193  }
4194  while(data[i] && (pX*8) < LCD_WIDTH){
4195  //Serial.print(data[i]); Serial.print(" ");
4196  //Serial.print(i); Serial.print(" "); Serial.print(pX); Serial.print(" ");
4197  //Serial.println(this->pY);
4198  if(data[i] == '\n' || this->pX >= LCD_WIDTH) {
4199  setCursor(0,(pY+1));
4200  } else if (this->pY >= LCD_HEIGHT){
4201  setCursor(0,0);
4202  }
4203  if(data[i] < 32 || data[i] > 127){ i++; continue;}
4204  for (byte j = 0; j < 8; j++){
4205  this->s1Dat(pgm_read_byte(&basicFont[data[i]-32][j]));
4206  }
4207  i++;this->pX++;
4208  }
4209  }
4210  void LCD::print(optVAL_t line, optVAL_t col, int data){
4211  char buffer[11] = "";
4212  itoa(data,buffer,10);
4213  this->print(line,col,buffer);
4214  }
4215  inline void LCD::lightOn(void) {
4216  this->changeBrightness(255);
4217  }
4218  inline void LCD::lightOff(void) {
4219  this->changeBrightness(0);
4220  }
4221  inline bool LCD::reset(void) {
4222  return this->clear();
4223  }
4224  inline void LCD::print(int data) {this->print(255,255,data);}
4225  inline void LCD::print(const char* data) {this->print(255,255,data);}
4226  inline bool LCD::init() {
4227  #ifdef HIGHSPEED
4228  TWBR = 0xC;
4229  #endif
4230  this->_cI = true;
4232  this->changeMode(false);
4233  this->changeBackground(false);
4234  this->changeBrightness(255);
4235  this->s2Cmd(0x20,LCD_PAGE_ADDRESSING);
4236  this->changeMode(true);
4237 
4238  //this->print("eBoard \n written by \n EagleoutIce");
4239  return this->clear();
4240  }
4241 
4242  inline void LCD::drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY){
4243  if(!this->_cI) this->init();
4244  setCursor(posX,posY);
4245  byte col = 0x0;
4246  for(int i = 0x0; i < (hiX * 8 * hiY); i++){
4247  this->s1Dat(pgm_read_byte(&bitmap[i]));
4248  if(++col == (hiX * 8)) {
4249  col = 0x0;
4250  setCursor(posX,++posY);
4251  }
4252  }
4253  }
4254  inline void LCD::changeMode(bool newMode) {
4255  if(!this->_cI) this->init();
4256  if(newMode) this->s1Cmd(LCD_COMMAND_DISPLAY_ON);
4257  else this->s1Cmd(LCD_COMMAND_DISPLAY_OFF);
4258  }
4259  inline bool LCD::setCursor(byte posX, byte posY) {
4260  if(!this->_cI) this->init();
4261  this->s2Cmd((0x00 + (8 *posX & 0x0F)),(0x10 + ((8 * posX >> 4) & 0x0F))); //lower and higher address
4262  this->pX = posX; this->pY = posY;
4263  return this->s1Cmd(0xB0 + posY);
4264  }
4265 
4266  inline bool LCD::changeBrightness(byte val) {
4267  if(!this->_cI) this->init();
4268  this->s2Cmd(0x81,val); //brightness mode
4269  Wire.beginTransmission(this->ID);
4270  return (Wire.endTransmission() == 0);
4271  }
4272  inline void LCD::changeBackground(bool newBackground) {
4273  if(!this->_cI) this->init();
4274  if(newBackground) this->s1Cmd(LCD_COMMAND_WHITE_BACKGROUND);
4275  else this->s1Cmd(LCD_COMMAND_BLACK_BACKGROUND);
4276  }
4277 
4278  inline void LCD::s2Cmd(optVAL_t o, optVAL_t t){
4279  if(!this->_cI) this->init();
4280  this->s1Cmd(o); this->s1Cmd(t);
4281  }
4282 
4283  inline bool LCD::s1Cmd(optVAL_t C) {
4284  if(!this->_cI) this->init();
4285  Wire.beginTransmission(this->ID);
4286  Wire.write(LCD_COMMAND_MODE); Wire.write(C);
4287  return (Wire.endTransmission()==0);
4288  }
4289  inline void LCD::s1Dat(optVAL_t o){
4290  if(!this->_cI) this->init();
4291  Wire.beginTransmission(this->ID);
4292  Wire.write(LCD_DATA_MODE); Wire.write(o);
4294  }
4295 
4297  #endif
4298  #endif
4299  #if EBOARD_NEO > 0x0
4300  // Codesection based on official NeoPixel library
4301  // RGB NeoPixel permutations; white and red offsets are always same
4302  // Offset: W R G B
4304  #define EBOARD_NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2))
4305  #define EBOARD_NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1))
4307  #define EBOARD_NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2))
4309  #define EBOARD_NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1))
4311  #define EBOARD_NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0))
4313  #define EBOARD_NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0))
4315 
4316  // RGBW NeoPixel permutations; all 4 offsets are distinct
4317  // Offset: W R G B
4319  #define EBOARD_NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
4320  #define EBOARD_NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
4322  #define EBOARD_NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
4324  #define EBOARD_NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
4326  #define EBOARD_NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
4328  #define EBOARD_NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))
4330  #define EBOARD_NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
4332  #define EBOARD_NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
4334  #define EBOARD_NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
4336  #define EBOARD_NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
4338  #define EBOARD_NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
4340  #define EBOARD_NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))
4342  #define EBOARD_NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
4344  #define EBOARD_NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
4346  #define EBOARD_NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
4348  #define EBOARD_NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
4350  #define EBOARD_NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
4352  #define EBOARD_NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))
4354  #define EBOARD_NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
4356  #define EBOARD_NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
4358  #define EBOARD_NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
4360  #define EBOARD_NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
4362  #define EBOARD_NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
4364  #define EBOARD_NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))
4366 
4367 
4369  #define EBOARD_NEO_800KHZ 0x0000
4370  #define EBOARD_NEO_400KHZ 0x0100
4372 
4373  // uint16_t can be uint8_t in 800Khz mode ^^
4412  struct NeoPixel{
4420  NeoPixel(uint16_t n, uint8_t p = 6, uint16_t t = EBOARD_NEO_GRB + EBOARD_NEO_800KHZ);
4428  NeoPixel(void);
4430  ~NeoPixel(void);
4434  void begin(void);
4438  void show(void);
4443  void setPin(uint8_t p);
4451  void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
4460  void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
4466  void setPixelColor(uint16_t n, uint32_t c);
4474  void setBrightness(uint8_t val);
4478  void clear(void);
4483  void updateLength(uint16_t n);
4488  void updateType(uint16_t t);
4493  inline uint8_t *getPixels(void) const;
4498  inline uint8_t getBrightness(void) const;
4503  inline int8_t getPin(void);
4508  inline uint16_t numPixels(void) const;
4515  static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b);
4523  static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
4528  uint32_t getPixelColor(uint16_t n) const;
4533  inline bool canShow(void);
4534  protected:
4536  bool is800KHz;
4538  bool begun;
4540  uint16_t numLEDs; //maybe shorten with PrepConst 'extendetLED'?
4542  uint16_t numBytes;
4547  int8_t pin;
4549  uint8_t brightness;
4551  uint8_t *pixels;
4553  uint8_t aOffset[4];
4555  uint32_t endTime; //used for diff calc
4556  #ifdef __AVR__ //not needed (rem?)
4557  volatile uint8_t *port;// Output PORT register
4560  uint8_t pinMask; // Output PORT bitmask
4561  #endif
4562 
4563  };
4564 
4566 
4567 
4568  NeoPixel::NeoPixel(uint16_t n, uint8_t p, uint16_t t) :
4569  begun(false), brightness(0), pixels(NULL), endTime(0) {
4570  updateType(t);
4571  updateLength(n);
4572  setPin(p);
4573  }
4574 
4575  inline bool NeoPixel::canShow(void) { return (micros() - endTime) >= 300L; }
4576 
4577  NeoPixel::NeoPixel() :
4578  is800KHz(true),
4579  begun(false), numLEDs(0), numBytes(0), pin(-1), brightness(0), pixels(NULL),
4580  endTime(0)
4581  {aOffset[0]=1;aOffset[1]=0;aOffset[2]=2;aOffset[3]=1;}
4582 
4584  if(pixels) free(pixels);
4585  if(pin >= 0) pinMode(pin, INPUT);
4586  }
4587 
4588  void NeoPixel::begin(void) {
4589  if(pin >= 0) {
4590  pinMode(pin, OUTPUT);
4591  digitalWrite(pin, LOW);
4592  }
4593  begun = true;
4594 
4595  }
4596 
4597  void NeoPixel::updateLength(uint16_t n) {
4598  if(pixels) free(pixels);
4599  numBytes = n * ((aOffset[3] == aOffset[0]) ? 3 : 4);
4600  if((pixels = (uint8_t *)malloc(numBytes))) {
4601  memset(pixels, 0, numBytes);
4602  numLEDs = n;
4603  } else {
4604  numLEDs = numBytes = 0;
4605  }
4606  }
4607 
4608  void NeoPixel::updateType(uint16_t t) {
4609  boolean oldThreeBytesPerPixel = (aOffset[3] == aOffset[0]); // false if RGBW
4610 
4611  aOffset[3] = (t >> 6) & 0b11;
4612  aOffset[0] = (t >> 4) & 0b11;
4613  aOffset[1] = (t >> 2) & 0b11;
4614  aOffset[2] = t & 0b11;
4615  is800KHz = (t < 256); // 400 KHz flag is 1<<8
4616 
4617  if(pixels) {
4618  boolean newThreeBytesPerPixel = (aOffset[3] == aOffset[0]);
4619  if(newThreeBytesPerPixel != oldThreeBytesPerPixel) updateLength(numLEDs);
4620  }
4621  }
4622 
4623  #if defined(ESP8266)
4624  // ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
4625  extern "C" void ICACHE_RAM_ATTR espShow(
4626  uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type);
4627  #elif defined(ESP32)
4628  extern "C" void espShow(
4629  uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type);
4630  #endif
4631 
4632  void NeoPixel::show(void) {
4633  if(!pixels) return;
4634  while(!canShow()); //maybe timeout ?
4635  noInterrupts(); // Need 100% focus on instruction timing
4636 
4637  #ifdef __AVR__
4638  volatile uint16_t
4639  i = numBytes;
4640  volatile uint8_t
4641  *ptr = pixels,
4642  b = *ptr++,
4643  hi,
4644  lo;
4645 
4646  #if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
4647 
4648  if(is800KHz) {
4649  volatile uint8_t n1, n2 = 0;
4650 
4651  #if defined(PORTD)
4652  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
4653  if(port == &PORTD) {
4654  #endif
4655 
4656  hi = PORTD | pinMask;
4657  lo = PORTD & ~pinMask;
4658  n1 = lo;
4659  if(b & 0x80) n1 = hi;
4660 
4661  asm volatile(
4662  "headD:" "\n\t" // Clk Pseudocode
4663  // Bit 7:
4664  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4665  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4666  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4667  "rjmp .+0" "\n\t" // 2 nop nop
4668  "sbrc %[byte] , 6" "\n\t" // 1-2 if(b & 0x40)
4669  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4670  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4671  "rjmp .+0" "\n\t" // 2 nop nop
4672  // Bit 6:
4673  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4674  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4675  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4676  "rjmp .+0" "\n\t" // 2 nop nop
4677  "sbrc %[byte] , 5" "\n\t" // 1-2 if(b & 0x20)
4678  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4679  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4680  "rjmp .+0" "\n\t" // 2 nop nop
4681  // Bit 5:
4682  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4683  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4684  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4685  "rjmp .+0" "\n\t" // 2 nop nop
4686  "sbrc %[byte] , 4" "\n\t" // 1-2 if(b & 0x10)
4687  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4688  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4689  "rjmp .+0" "\n\t" // 2 nop nop
4690  // Bit 4:
4691  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4692  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4693  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4694  "rjmp .+0" "\n\t" // 2 nop nop
4695  "sbrc %[byte] , 3" "\n\t" // 1-2 if(b & 0x08)
4696  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4697  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4698  "rjmp .+0" "\n\t" // 2 nop nop
4699  // Bit 3:
4700  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4701  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4702  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4703  "rjmp .+0" "\n\t" // 2 nop nop
4704  "sbrc %[byte] , 2" "\n\t" // 1-2 if(b & 0x04)
4705  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4706  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4707  "rjmp .+0" "\n\t" // 2 nop nop
4708  // Bit 2:
4709  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4710  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4711  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4712  "rjmp .+0" "\n\t" // 2 nop nop
4713  "sbrc %[byte] , 1" "\n\t" // 1-2 if(b & 0x02)
4714  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4715  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4716  "rjmp .+0" "\n\t" // 2 nop nop
4717  // Bit 1:
4718  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4719  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4720  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4721  "rjmp .+0" "\n\t" // 2 nop nop
4722  "sbrc %[byte] , 0" "\n\t" // 1-2 if(b & 0x01)
4723  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4724  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4725  "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet)
4726  // Bit 0:
4727  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4728  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4729  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4730  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++
4731  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80)
4732  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4733  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4734  "brne headD" "\n" // 2 while(i) (Z flag set above)
4735  : [byte] "+r" (b),
4736  [n1] "+r" (n1),
4737  [n2] "+r" (n2),
4738  [count] "+w" (i)
4739  : [port] "I" (_SFR_IO_ADDR(PORTD)),
4740  [ptr] "e" (ptr),
4741  [hi] "r" (hi),
4742  [lo] "r" (lo));
4743 
4744  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
4745  } else
4746  #endif
4747  #endif
4748  #if defined(PORTB)
4749  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
4750  if(port == &PORTB) {
4751  #endif // defined(PORTD/C/F)
4752  hi = PORTB | pinMask;
4753  lo = PORTB & ~pinMask;
4754  n1 = lo;
4755  if(b & 0x80) n1 = hi;
4756 
4757  asm volatile(
4758  "headB:" "\n\t"
4759  "out %[port] , %[hi]" "\n\t"
4760  "mov %[n2] , %[lo]" "\n\t"
4761  "out %[port] , %[n1]" "\n\t"
4762  "rjmp .+0" "\n\t"
4763  "sbrc %[byte] , 6" "\n\t"
4764  "mov %[n2] , %[hi]" "\n\t"
4765  "out %[port] , %[lo]" "\n\t"
4766  "rjmp .+0" "\n\t"
4767  "out %[port] , %[hi]" "\n\t"
4768  "mov %[n1] , %[lo]" "\n\t"
4769  "out %[port] , %[n2]" "\n\t"
4770  "rjmp .+0" "\n\t"
4771  "sbrc %[byte] , 5" "\n\t"
4772  "mov %[n1] , %[hi]" "\n\t"
4773  "out %[port] , %[lo]" "\n\t"
4774  "rjmp .+0" "\n\t"
4775  "out %[port] , %[hi]" "\n\t"
4776  "mov %[n2] , %[lo]" "\n\t"
4777  "out %[port] , %[n1]" "\n\t"
4778  "rjmp .+0" "\n\t"
4779  "sbrc %[byte] , 4" "\n\t"
4780  "mov %[n2] , %[hi]" "\n\t"
4781  "out %[port] , %[lo]" "\n\t"
4782  "rjmp .+0" "\n\t"
4783  "out %[port] , %[hi]" "\n\t"
4784  "mov %[n1] , %[lo]" "\n\t"
4785  "out %[port] , %[n2]" "\n\t"
4786  "rjmp .+0" "\n\t"
4787  "sbrc %[byte] , 3" "\n\t"
4788  "mov %[n1] , %[hi]" "\n\t"
4789  "out %[port] , %[lo]" "\n\t"
4790  "rjmp .+0" "\n\t"
4791  "out %[port] , %[hi]" "\n\t"
4792  "mov %[n2] , %[lo]" "\n\t"
4793  "out %[port] , %[n1]" "\n\t"
4794  "rjmp .+0" "\n\t"
4795  "sbrc %[byte] , 2" "\n\t"
4796  "mov %[n2] , %[hi]" "\n\t"
4797  "out %[port] , %[lo]" "\n\t"
4798  "rjmp .+0" "\n\t"
4799  "out %[port] , %[hi]" "\n\t"
4800  "mov %[n1] , %[lo]" "\n\t"
4801  "out %[port] , %[n2]" "\n\t"
4802  "rjmp .+0" "\n\t"
4803  "sbrc %[byte] , 1" "\n\t"
4804  "mov %[n1] , %[hi]" "\n\t"
4805  "out %[port] , %[lo]" "\n\t"
4806  "rjmp .+0" "\n\t"
4807  "out %[port] , %[hi]" "\n\t"
4808  "mov %[n2] , %[lo]" "\n\t"
4809  "out %[port] , %[n1]" "\n\t"
4810  "rjmp .+0" "\n\t"
4811  "sbrc %[byte] , 0" "\n\t"
4812  "mov %[n2] , %[hi]" "\n\t"
4813  "out %[port] , %[lo]" "\n\t"
4814  "sbiw %[count], 1" "\n\t"
4815  "out %[port] , %[hi]" "\n\t"
4816  "mov %[n1] , %[lo]" "\n\t"
4817  "out %[port] , %[n2]" "\n\t"
4818  "ld %[byte] , %a[ptr]+" "\n\t"
4819  "sbrc %[byte] , 7" "\n\t"
4820  "mov %[n1] , %[hi]" "\n\t"
4821  "out %[port] , %[lo]" "\n\t"
4822  "brne headB" "\n"
4823  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
4824  : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
4825  [lo] "r" (lo));
4826 
4827  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
4828  }
4829  #endif
4830  #if defined(PORTC) || defined(PORTF)
4831  else
4832  #endif
4833  #endif
4834 
4835  #if defined(PORTC)
4836  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
4837  if(port == &PORTC) {
4838  #endif
4839 
4840  hi = PORTC | pinMask;
4841  lo = PORTC & ~pinMask;
4842  n1 = lo;
4843  if(b & 0x80) n1 = hi;
4844 
4845  asm volatile(
4846  "headC:" "\n\t"
4847  "out %[port] , %[hi]" "\n\t"
4848  "mov %[n2] , %[lo]" "\n\t"
4849  "out %[port] , %[n1]" "\n\t"
4850  "rjmp .+0" "\n\t"
4851  "sbrc %[byte] , 6" "\n\t"
4852  "mov %[n2] , %[hi]" "\n\t"
4853  "out %[port] , %[lo]" "\n\t"
4854  "rjmp .+0" "\n\t"
4855  "out %[port] , %[hi]" "\n\t"
4856  "mov %[n1] , %[lo]" "\n\t"
4857  "out %[port] , %[n2]" "\n\t"
4858  "rjmp .+0" "\n\t"
4859  "sbrc %[byte] , 5" "\n\t"
4860  "mov %[n1] , %[hi]" "\n\t"
4861  "out %[port] , %[lo]" "\n\t"
4862  "rjmp .+0" "\n\t"
4863  "out %[port] , %[hi]" "\n\t"
4864  "mov %[n2] , %[lo]" "\n\t"
4865  "out %[port] , %[n1]" "\n\t"
4866  "rjmp .+0" "\n\t"
4867  "sbrc %[byte] , 4" "\n\t"
4868  "mov %[n2] , %[hi]" "\n\t"
4869  "out %[port] , %[lo]" "\n\t"
4870  "rjmp .+0" "\n\t"
4871  "out %[port] , %[hi]" "\n\t"
4872  "mov %[n1] , %[lo]" "\n\t"
4873  "out %[port] , %[n2]" "\n\t"
4874  "rjmp .+0" "\n\t"
4875  "sbrc %[byte] , 3" "\n\t"
4876  "mov %[n1] , %[hi]" "\n\t"
4877  "out %[port] , %[lo]" "\n\t"
4878  "rjmp .+0" "\n\t"
4879  "out %[port] , %[hi]" "\n\t"
4880  "mov %[n2] , %[lo]" "\n\t"
4881  "out %[port] , %[n1]" "\n\t"
4882  "rjmp .+0" "\n\t"
4883  "sbrc %[byte] , 2" "\n\t"
4884  "mov %[n2] , %[hi]" "\n\t"
4885  "out %[port] , %[lo]" "\n\t"
4886  "rjmp .+0" "\n\t"
4887  "out %[port] , %[hi]" "\n\t"
4888  "mov %[n1] , %[lo]" "\n\t"
4889  "out %[port] , %[n2]" "\n\t"
4890  "rjmp .+0" "\n\t"
4891  "sbrc %[byte] , 1" "\n\t"
4892  "mov %[n1] , %[hi]" "\n\t"
4893  "out %[port] , %[lo]" "\n\t"
4894  "rjmp .+0" "\n\t"
4895  "out %[port] , %[hi]" "\n\t"
4896  "mov %[n2] , %[lo]" "\n\t"
4897  "out %[port] , %[n1]" "\n\t"
4898  "rjmp .+0" "\n\t"
4899  "sbrc %[byte] , 0" "\n\t"
4900  "mov %[n2] , %[hi]" "\n\t"
4901  "out %[port] , %[lo]" "\n\t"
4902  "sbiw %[count], 1" "\n\t"
4903  "out %[port] , %[hi]" "\n\t"
4904  "mov %[n1] , %[lo]" "\n\t"
4905  "out %[port] , %[n2]" "\n\t"
4906  "ld %[byte] , %a[ptr]+" "\n\t"
4907  "sbrc %[byte] , 7" "\n\t"
4908  "mov %[n1] , %[hi]" "\n\t"
4909  "out %[port] , %[lo]" "\n\t"
4910  "brne headC" "\n"
4911  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
4912  : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
4913  [lo] "r" (lo));
4914 
4915  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
4916  }
4917  #endif
4918  #if defined(PORTF)
4919  else
4920  #endif
4921  #endif
4922 
4923  #if defined(PORTF)
4924  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
4925  if(port == &PORTF) {
4926  #endif // defined(PORTD/B/C)
4927 
4928  hi = PORTF | pinMask;
4929  lo = PORTF & ~pinMask;
4930  n1 = lo;
4931  if(b & 0x80) n1 = hi;
4932 
4933  asm volatile(
4934  "headF:" "\n\t"
4935  "out %[port] , %[hi]" "\n\t"
4936  "mov %[n2] , %[lo]" "\n\t"
4937  "out %[port] , %[n1]" "\n\t"
4938  "rjmp .+0" "\n\t"
4939  "sbrc %[byte] , 6" "\n\t"
4940  "mov %[n2] , %[hi]" "\n\t"
4941  "out %[port] , %[lo]" "\n\t"
4942  "rjmp .+0" "\n\t"
4943  "out %[port] , %[hi]" "\n\t"
4944  "mov %[n1] , %[lo]" "\n\t"
4945  "out %[port] , %[n2]" "\n\t"
4946  "rjmp .+0" "\n\t"
4947  "sbrc %[byte] , 5" "\n\t"
4948  "mov %[n1] , %[hi]" "\n\t"
4949  "out %[port] , %[lo]" "\n\t"
4950  "rjmp .+0" "\n\t"
4951  "out %[port] , %[hi]" "\n\t"
4952  "mov %[n2] , %[lo]" "\n\t"
4953  "out %[port] , %[n1]" "\n\t"
4954  "rjmp .+0" "\n\t"
4955  "sbrc %[byte] , 4" "\n\t"
4956  "mov %[n2] , %[hi]" "\n\t"
4957  "out %[port] , %[lo]" "\n\t"
4958  "rjmp .+0" "\n\t"
4959  "out %[port] , %[hi]" "\n\t"
4960  "mov %[n1] , %[lo]" "\n\t"
4961  "out %[port] , %[n2]" "\n\t"
4962  "rjmp .+0" "\n\t"
4963  "sbrc %[byte] , 3" "\n\t"
4964  "mov %[n1] , %[hi]" "\n\t"
4965  "out %[port] , %[lo]" "\n\t"
4966  "rjmp .+0" "\n\t"
4967  "out %[port] , %[hi]" "\n\t"
4968  "mov %[n2] , %[lo]" "\n\t"
4969  "out %[port] , %[n1]" "\n\t"
4970  "rjmp .+0" "\n\t"
4971  "sbrc %[byte] , 2" "\n\t"
4972  "mov %[n2] , %[hi]" "\n\t"
4973  "out %[port] , %[lo]" "\n\t"
4974  "rjmp .+0" "\n\t"
4975  "out %[port] , %[hi]" "\n\t"
4976  "mov %[n1] , %[lo]" "\n\t"
4977  "out %[port] , %[n2]" "\n\t"
4978  "rjmp .+0" "\n\t"
4979  "sbrc %[byte] , 1" "\n\t"
4980  "mov %[n1] , %[hi]" "\n\t"
4981  "out %[port] , %[lo]" "\n\t"
4982  "rjmp .+0" "\n\t"
4983  "out %[port] , %[hi]" "\n\t"
4984  "mov %[n2] , %[lo]" "\n\t"
4985  "out %[port] , %[n1]" "\n\t"
4986  "rjmp .+0" "\n\t"
4987  "sbrc %[byte] , 0" "\n\t"
4988  "mov %[n2] , %[hi]" "\n\t"
4989  "out %[port] , %[lo]" "\n\t"
4990  "sbiw %[count], 1" "\n\t"
4991  "out %[port] , %[hi]" "\n\t"
4992  "mov %[n1] , %[lo]" "\n\t"
4993  "out %[port] , %[n2]" "\n\t"
4994  "ld %[byte] , %a[ptr]+" "\n\t"
4995  "sbrc %[byte] , 7" "\n\t"
4996  "mov %[n1] , %[hi]" "\n\t"
4997  "out %[port] , %[lo]" "\n\t"
4998  "brne headF" "\n"
4999  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
5000  : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
5001  [lo] "r" (lo));
5002 
5003  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
5004  }
5005  #endif // defined(PORTD/B/C)
5006  #endif // defined(PORTF)
5007  } else {
5008 
5009  volatile uint8_t next, bit;
5010 
5011  hi = *port | pinMask;
5012  lo = *port & ~pinMask;
5013  next = lo;
5014  bit = 8;
5015 
5016  asm volatile(
5017  "head20:" "\n\t" // Clk Pseudocode (T = 0)
5018  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
5019  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
5020  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
5021  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 6)
5022  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
5023  "dec %[bit]" "\n\t" // 1 bit-- (T = 8)
5024  "breq nextbyte20" "\n\t" // 1-2 if(bit == 0)
5025  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
5026  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
5027  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
5028  "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
5029  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
5030  "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
5031  "nextbyte20:" "\n\t" // (T = 10)
5032  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
5033  "nop" "\n\t" // 1 nop (T = 13)
5034  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 14)
5035  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 16)
5036  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
5037  "brne head20" "\n" // 2 if(i != 0) -> (next byte)
5038  : [port] "+e" (port),
5039  [byte] "+r" (b),
5040  [bit] "+r" (bit),
5041  [next] "+r" (next),
5042  [count] "+w" (i)
5043  : [hi] "r" (hi),
5044  [lo] "r" (lo),
5045  [ptr] "e" (ptr));
5046  }
5047  #elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
5048  if(is800KHz) {
5049  volatile uint8_t next;
5050 
5051  // PORTD OUTPUT ----------------------------------------------------
5052 
5053  #if defined(PORTD)
5054  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
5055  if(port == &PORTD) {
5056  #endif
5057 
5058  hi = PORTD | pinMask;
5059  lo = PORTD & ~pinMask;
5060  next = lo;
5061  if(b & 0x80) next = hi;
5062  asm volatile(
5063  "headD:" "\n\t" // (T = 0)
5064  "out %[port], %[hi]" "\n\t" // (T = 1)
5065  "rcall bitTimeD" "\n\t" // Bit 7 (T = 15)
5066  "out %[port], %[hi]" "\n\t"
5067  "rcall bitTimeD" "\n\t" // Bit 6
5068  "out %[port], %[hi]" "\n\t"
5069  "rcall bitTimeD" "\n\t" // Bit 5
5070  "out %[port], %[hi]" "\n\t"
5071  "rcall bitTimeD" "\n\t" // Bit 4
5072  "out %[port], %[hi]" "\n\t"
5073  "rcall bitTimeD" "\n\t" // Bit 3
5074  "out %[port], %[hi]" "\n\t"
5075  "rcall bitTimeD" "\n\t" // Bit 2
5076  "out %[port], %[hi]" "\n\t"
5077  "rcall bitTimeD" "\n\t" // Bit 1
5078  // Bit 0:
5079  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi (T = 1)
5080  "rjmp .+0" "\n\t" // 2 nop nop (T = 3)
5081  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 5)
5082  "out %[port] , %[next]" "\n\t" // 1 PORT = next (T = 6)
5083  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
5084  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
5085  "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9)
5086  "nop" "\n\t" // 1 (T = 10)
5087  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo (T = 11)
5088  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 13)
5089  "brne headD" "\n\t" // 2 if(i != 0) -> (next byte)
5090  "rjmp doneD" "\n\t"
5091  "bitTimeD:" "\n\t" // nop nop nop (T = 4)
5092  "out %[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
5093  "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6)
5094  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 7)
5095  "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
5096  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9)
5097  "nop" "\n\t" // 1 (T = 10)
5098  "out %[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11)
5099  "ret" "\n\t" // 4 nop nop nop nop (T = 15)
5100  "doneD:" "\n"
5101  : [byte] "+r" (b),
5102  [next] "+r" (next),
5103  [count] "+w" (i)
5104  : [port] "I" (_SFR_IO_ADDR(PORTD)),
5105  [ptr] "e" (ptr),
5106  [hi] "r" (hi),
5107  [lo] "r" (lo));
5108 
5109  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
5110  } else
5111  #endif
5112  #endif
5113 
5114  #if defined(PORTB)
5115  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
5116  if(port == &PORTB) {
5117  #endif
5118 
5119  hi = PORTB | pinMask;
5120  lo = PORTB & ~pinMask;
5121  next = lo;
5122  if(b & 0x80) next = hi;
5123 
5124  asm volatile(
5125  "headB:" "\n\t"
5126  "out %[port], %[hi]" "\n\t"
5127  "rcall bitTimeB" "\n\t"
5128  "out %[port], %[hi]" "\n\t"
5129  "rcall bitTimeB" "\n\t"
5130  "out %[port], %[hi]" "\n\t"
5131  "rcall bitTimeB" "\n\t"
5132  "out %[port], %[hi]" "\n\t"
5133  "rcall bitTimeB" "\n\t"
5134  "out %[port], %[hi]" "\n\t"
5135  "rcall bitTimeB" "\n\t"
5136  "out %[port], %[hi]" "\n\t"
5137  "rcall bitTimeB" "\n\t"
5138  "out %[port], %[hi]" "\n\t"
5139  "rcall bitTimeB" "\n\t"
5140  "out %[port] , %[hi]" "\n\t"
5141  "rjmp .+0" "\n\t"
5142  "ld %[byte] , %a[ptr]+" "\n\t"
5143  "out %[port] , %[next]" "\n\t"
5144  "mov %[next] , %[lo]" "\n\t"
5145  "sbrc %[byte] , 7" "\n\t"
5146  "mov %[next] , %[hi]" "\n\t"
5147  "nop" "\n\t"
5148  "out %[port] , %[lo]" "\n\t"
5149  "sbiw %[count], 1" "\n\t"
5150  "brne headB" "\n\t"
5151  "rjmp doneB" "\n\t"
5152  "bitTimeB:" "\n\t"
5153  "out %[port], %[next]" "\n\t"
5154  "mov %[next], %[lo]" "\n\t"
5155  "rol %[byte]" "\n\t"
5156  "sbrc %[byte], 7" "\n\t"
5157  "mov %[next], %[hi]" "\n\t"
5158  "nop" "\n\t"
5159  "out %[port], %[lo]" "\n\t"
5160  "ret" "\n\t"
5161  "doneB:" "\n"
5162  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
5163  : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
5164  [lo] "r" (lo));
5165 
5166  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
5167  }
5168  #endif
5169  #if defined(PORTC) || defined(PORTF)
5170  else
5171  #endif
5172  #endif
5173 
5174  #if defined(PORTC)
5175  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
5176  if(port == &PORTC) {
5177  #endif
5178 
5179  hi = PORTC | pinMask;
5180  lo = PORTC & ~pinMask;
5181  next = lo;
5182  if(b & 0x80) next = hi;
5183 
5184  asm volatile(
5185  "headC:" "\n\t"
5186  "out %[port], %[hi]" "\n\t"
5187  "rcall bitTimeC" "\n\t"
5188  "out %[port], %[hi]" "\n\t"
5189  "rcall bitTimeC" "\n\t"
5190  "out %[port], %[hi]" "\n\t"
5191  "rcall bitTimeC" "\n\t"
5192  "out %[port], %[hi]" "\n\t"
5193  "rcall bitTimeC" "\n\t"
5194  "out %[port], %[hi]" "\n\t"
5195  "rcall bitTimeC" "\n\t"
5196  "out %[port], %[hi]" "\n\t"
5197  "rcall bitTimeC" "\n\t"
5198  "out %[port], %[hi]" "\n\t"
5199  "rcall bitTimeC" "\n\t"
5200  "out %[port] , %[hi]" "\n\t"
5201  "rjmp .+0" "\n\t"
5202  "ld %[byte] , %a[ptr]+" "\n\t"
5203  "out %[port] , %[next]" "\n\t"
5204  "mov %[next] , %[lo]" "\n\t"
5205  "sbrc %[byte] , 7" "\n\t"
5206  "mov %[next] , %[hi]" "\n\t"
5207  "nop" "\n\t"
5208  "out %[port] , %[lo]" "\n\t"
5209  "sbiw %[count], 1" "\n\t"
5210  "brne headC" "\n\t"
5211  "rjmp doneC" "\n\t"
5212  "bitTimeC:" "\n\t"
5213  "out %[port], %[next]" "\n\t"
5214  "mov %[next], %[lo]" "\n\t"
5215  "rol %[byte]" "\n\t"
5216  "sbrc %[byte], 7" "\n\t"
5217  "mov %[next], %[hi]" "\n\t"
5218  "nop" "\n\t"
5219  "out %[port], %[lo]" "\n\t"
5220  "ret" "\n\t"
5221  "doneC:" "\n"
5222  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
5223  : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
5224  [lo] "r" (lo));
5225 
5226  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
5227  }
5228  #endif
5229  #if defined(PORTF)
5230  else
5231  #endif
5232  #endif
5233 
5234  #if defined(PORTF)
5235  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
5236  if(port == &PORTF) {
5237  #endif
5238 
5239  hi = PORTF | pinMask;
5240  lo = PORTF & ~pinMask;
5241  next = lo;
5242  if(b & 0x80) next = hi;
5243 
5244  asm volatile(
5245  "headF:" "\n\t"
5246  "out %[port], %[hi]" "\n\t"
5247  "rcall bitTimeC" "\n\t"
5248  "out %[port], %[hi]" "\n\t"
5249  "rcall bitTimeC" "\n\t"
5250  "out %[port], %[hi]" "\n\t"
5251  "rcall bitTimeC" "\n\t"
5252  "out %[port], %[hi]" "\n\t"
5253  "rcall bitTimeC" "\n\t"
5254  "out %[port], %[hi]" "\n\t"
5255  "rcall bitTimeC" "\n\t"
5256  "out %[port], %[hi]" "\n\t"
5257  "rcall bitTimeC" "\n\t"
5258  "out %[port], %[hi]" "\n\t"
5259  "rcall bitTimeC" "\n\t"
5260  "out %[port] , %[hi]" "\n\t"
5261  "rjmp .+0" "\n\t"
5262  "ld %[byte] , %a[ptr]+" "\n\t"
5263  "out %[port] , %[next]" "\n\t"
5264  "mov %[next] , %[lo]" "\n\t"
5265  "sbrc %[byte] , 7" "\n\t"
5266  "mov %[next] , %[hi]" "\n\t"
5267  "nop" "\n\t"
5268  "out %[port] , %[lo]" "\n\t"
5269  "sbiw %[count], 1" "\n\t"
5270  "brne headF" "\n\t"
5271  "rjmp doneC" "\n\t"
5272  "bitTimeC:" "\n\t"
5273  "out %[port], %[next]" "\n\t"
5274  "mov %[next], %[lo]" "\n\t"
5275  "rol %[byte]" "\n\t"
5276  "sbrc %[byte], 7" "\n\t"
5277  "mov %[next], %[hi]" "\n\t"
5278  "nop" "\n\t"
5279  "out %[port], %[lo]" "\n\t"
5280  "ret" "\n\t"
5281  "doneC:" "\n"
5282  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
5283  : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
5284  [lo] "r" (lo));
5285 
5286  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
5287  }
5288  #endif
5289  #endif
5290  } else {
5291  volatile uint8_t next, bit;
5292 
5293  hi = *port | pinMask;
5294  lo = *port & ~pinMask;
5295  next = lo;
5296  bit = 8;
5297 
5298  asm volatile(
5299  "head30:" "\n\t" // Clk Pseudocode (T = 0)
5300  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
5301  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
5302  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
5303  "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
5304  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 8)
5305  "rjmp .+0" "\n\t" // 2 nop nop (T = 10)
5306  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
5307  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
5308  "nop" "\n\t" // 1 nop (T = 15)
5309  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 17)
5310  "rjmp .+0" "\n\t" // 2 nop nop (T = 19)
5311  "dec %[bit]" "\n\t" // 1 bit-- (T = 20)
5312  "breq nextbyte30" "\n\t" // 1-2 if(bit == 0)
5313  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22)
5314  "rjmp .+0" "\n\t" // 2 nop nop (T = 24)
5315  "rjmp .+0" "\n\t" // 2 nop nop (T = 26)
5316  "rjmp .+0" "\n\t" // 2 nop nop (T = 28)
5317  "rjmp head30" "\n\t" // 2 -> head30 (next bit out)
5318  "nextbyte30:" "\n\t" // (T = 22)
5319  "nop" "\n\t" // 1 nop (T = 23)
5320  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 24)
5321  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 26)
5322  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 28)
5323  "brne head30" "\n" // 1-2 if(i != 0) -> (next byte)
5324  : [port] "+e" (port),
5325  [byte] "+r" (b),
5326  [bit] "+r" (bit),
5327  [next] "+r" (next),
5328  [count] "+w" (i)
5329  : [hi] "r" (hi),
5330  [lo] "r" (lo),
5331  [ptr] "e" (ptr));
5332  }
5333  #elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
5334  if(is800KHz) {
5335  volatile uint8_t next, bit;
5336 
5337  hi = *port | pinMask;
5338  lo = *port & ~pinMask;
5339  next = lo;
5340  bit = 8;
5341 
5342  asm volatile(
5343  "head20:" "\n\t" // Clk Pseudocode (T = 0)
5344  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
5345  "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 128)
5346  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
5347  "dec %[bit]" "\n\t" // 1 bit-- (T = 5)
5348  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 7)
5349  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8)
5350  "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) (from dec above)
5351  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
5352  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
5353  "nop" "\n\t" // 1 nop (T = 13)
5354  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
5355  "nop" "\n\t" // 1 nop (T = 16)
5356  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
5357  "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
5358  "nextbyte20:" "\n\t" // (T = 10)
5359  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11)
5360  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13)
5361  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
5362  "nop" "\n\t" // 1 nop (T = 16)
5363  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
5364  "brne head20" "\n" // 2 if(i != 0) -> (next byte)
5365  : [port] "+e" (port),
5366  [byte] "+r" (b),
5367  [bit] "+r" (bit),
5368  [next] "+r" (next),
5369  [count] "+w" (i)
5370  : [ptr] "e" (ptr),
5371  [hi] "r" (hi),
5372  [lo] "r" (lo));
5373  } else {
5374 
5375  volatile uint8_t next, bit;
5376 
5377  hi = *port | pinMask;
5378  lo = *port & ~pinMask;
5379  next = lo;
5380  bit = 8;
5381 
5382  asm volatile(
5383  "head40:" "\n\t" // Clk Pseudocode (T = 0)
5384  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
5385  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
5386  "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 4)
5387  "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
5388  "rjmp .+0" "\n\t" // 2 nop nop (T = 8)
5389  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 10)
5390  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
5391  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
5392  "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
5393  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
5394  "rjmp .+0" "\n\t" // 2 nop nop (T = 20)
5395  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 22)
5396  "nop" "\n\t" // 1 nop (T = 23)
5397  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 24)
5398  "dec %[bit]" "\n\t" // 1 bit-- (T = 25)
5399  "breq nextbyte40" "\n\t" // 1-2 if(bit == 0)
5400  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27)
5401  "nop" "\n\t" // 1 nop (T = 28)
5402  "rjmp .+0" "\n\t" // 2 nop nop (T = 30)
5403  "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
5404  "rjmp .+0" "\n\t" // 2 nop nop (T = 34)
5405  "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
5406  "rjmp .+0" "\n\t" // 2 nop nop (T = 38)
5407  "rjmp head40" "\n\t" // 2 -> head40 (next bit out)
5408  "nextbyte40:" "\n\t" // (T = 27)
5409  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 28)
5410  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 30)
5411  "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
5412  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 34)
5413  "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
5414  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 38)
5415  "brne head40" "\n" // 1-2 if(i != 0) -> (next byte)
5416  : [port] "+e" (port),
5417  [byte] "+r" (b),
5418  [bit] "+r" (bit),
5419  [next] "+r" (next),
5420  [count] "+w" (i)
5421  : [ptr] "e" (ptr),
5422  [hi] "r" (hi),
5423  [lo] "r" (lo));
5424  }
5425  #else
5426  #error "CPU SPEED NOT SUPPORTED"
5427  #endif
5428  #elif defined(__arm__)
5429 
5430 
5431  #if defined(TEENSYDUINO) && defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6
5432  #define CYCLES_800_T0H (F_CPU / 4000000)
5433  #define CYCLES_800_T1H (F_CPU / 1250000)
5434  #define CYCLES_800 (F_CPU / 800000)
5435  #define CYCLES_400_T0H (F_CPU / 2000000)
5436  #define CYCLES_400_T1H (F_CPU / 833333)
5437  #define CYCLES_400 (F_CPU / 400000)
5438 
5439  uint8_t *p = pixels,
5440  *end = p + numBytes, pix, mask;
5441  volatile uint8_t *set = portSetRegister(pin),
5442  *clr = portClearRegister(pin);
5443  uint32_t cyc;
5444 
5445  ARM_DEMCR |= ARM_DEMCR_TRCENA;
5446  ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
5447 
5448  if(is800KHz) {
5449  cyc = ARM_DWT_CYCCNT + CYCLES_800;
5450  while(p < end) {
5451  pix = *p++;
5452  for(mask = 0x80; mask; mask >>= 1) {
5453  while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
5454  cyc = ARM_DWT_CYCCNT;
5455  *set = 1;
5456  if(pix & mask) {
5457  while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H);
5458  } else {
5459  while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H);
5460  }
5461  *clr = 1;
5462  }
5463  }
5464  while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
5465  } else {
5466  cyc = ARM_DWT_CYCCNT + CYCLES_400;
5467  while(p < end) {
5468  pix = *p++;
5469  for(mask = 0x80; mask; mask >>= 1) {
5470  while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
5471  cyc = ARM_DWT_CYCCNT;
5472  *set = 1;
5473  if(pix & mask) {
5474  while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H);
5475  } else {
5476  while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H);
5477  }
5478  *clr = 1;
5479  }
5480  }
5481  while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
5482  }
5483  #else
5484  #error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
5485  #endif
5486  #elif defined(ESP8266) || defined(ESP32)
5487 
5488  espShow(pin, pixels, numBytes, is800KHz);
5489 
5490  #elif defined(__ARDUINO_ARC__)
5491 
5492  // Arduino 101 -----------------------------------------------------------
5493 
5494  #define NOPx7 { __builtin_arc_nop(); \
5495  __builtin_arc_nop(); __builtin_arc_nop(); \
5496  __builtin_arc_nop(); __builtin_arc_nop(); \
5497  __builtin_arc_nop(); __builtin_arc_nop(); }
5498 
5499  PinDescription *pindesc = &g_APinDescription[pin];
5500  register uint32_t loop = 8 * numBytes; // one loop to handle all bytes and all bits
5501  register uint8_t *p = pixels;
5502  register uint32_t currByte = (uint32_t) (*p);
5503  register uint32_t currBit = 0x80 & currByte;
5504  register uint32_t bitCounter = 0;
5505  register uint32_t first = 1;
5506 
5507  if (pindesc->ulGPIOType == SS_GPIO) {
5508  register uint32_t reg = pindesc->ulGPIOBase + SS_GPIO_SWPORTA_DR;
5509  uint32_t reg_val = __builtin_arc_lr((volatile uint32_t)reg);
5510  register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
5511  register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId);
5512 
5513  loop += 1;
5514  while(loop--) {
5515  if(!first) {
5516  currByte <<= 1;
5517  bitCounter++;
5518  }
5519 
5520  // 1 is >550ns high and >450ns low; 0 is 200..500ns high and >450ns low
5521  __builtin_arc_sr(first ? reg_bit_low : reg_bit_high, (volatile uint32_t)reg);
5522  if(currBit) { // ~400ns HIGH (740ns overall)
5523  NOPx7
5524  NOPx7
5525  }
5526  // ~340ns HIGH
5527  NOPx7
5528  __builtin_arc_nop();
5529 
5530  // 820ns LOW; per spec, max allowed low here is 5000ns */
5531  __builtin_arc_sr(reg_bit_low, (volatile uint32_t)reg);
5532  NOPx7
5533  NOPx7
5534 
5535  if(bitCounter >= 8) {
5536  bitCounter = 0;
5537  currByte = (uint32_t) (*++p);
5538  }
5539 
5540  currBit = 0x80 & currByte;
5541  first = 0;
5542  }
5543  } else if(pindesc->ulGPIOType == SOC_GPIO) {
5544  register uint32_t reg = pindesc->ulGPIOBase + SOC_GPIO_SWPORTA_DR;
5545  uint32_t reg_val = MMIO_REG_VAL(reg);
5546  register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
5547  register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId);
5548 
5549  loop += 1; // include first, special iteration
5550  while(loop--) {
5551  if(!first) {
5552  currByte <<= 1;
5553  bitCounter++;
5554  }
5555  MMIO_REG_VAL(reg) = first ? reg_bit_low : reg_bit_high;
5556  if(currBit) { // ~430ns HIGH (740ns overall)
5557  NOPx7
5558  NOPx7
5559  __builtin_arc_nop();
5560  }
5561  // ~310ns HIGH
5562  NOPx7
5563 
5564  // 850ns LOW; per spec, max allowed low here is 5000ns */
5565  MMIO_REG_VAL(reg) = reg_bit_low;
5566  NOPx7
5567  NOPx7
5568 
5569  if(bitCounter >= 8) {
5570  bitCounter = 0;
5571  currByte = (uint32_t) (*++p);
5572  }
5573 
5574  currBit = 0x80 & currByte;
5575  first = 0;
5576  }
5577  }
5578 
5579  #else
5580  #error Architecture not supported
5581  #endif
5582 
5583  interrupts();
5584 
5585  endTime = micros();
5586  }
5587 
5588  void NeoPixel::setPin(uint8_t p) {
5589  if(begun && (pin >= 0)) pinMode(pin, INPUT);
5590  pin = p;
5591  if(begun) {
5592  pinMode(p, OUTPUT);
5593  digitalWrite(p, LOW);
5594  }
5595  #ifdef __AVR__
5596  port = portOutputRegister(digitalPinToPort(p));
5597  pinMask = digitalPinToBitMask(p);
5598  #endif
5599  }
5600 
5602  uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
5603 
5604  if(n < numLEDs) {
5605  if(brightness) { // See notes in setBrightness()
5606  r = (r * brightness) >> 8;
5607  g = (g * brightness) >> 8;
5608  b = (b * brightness) >> 8;
5609  }
5610  uint8_t *p;
5611  if(aOffset[3] == aOffset[0]) {
5612  p = &pixels[n * 3];
5613  } else {
5614  p = &pixels[n * 4];
5615  p[aOffset[3]] = 0;
5616  }
5617  p[aOffset[0]] = r;
5618  p[aOffset[1]] = g;
5619  p[aOffset[2]] = b;
5620  }
5621  }
5622 
5624  uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
5625 
5626  if(n < numLEDs) {
5627  if(brightness) {
5628  r = (r * brightness) >> 8;
5629  g = (g * brightness) >> 8;
5630  b = (b * brightness) >> 8;
5631  w = (w * brightness) >> 8;
5632  }
5633  uint8_t *p;
5634  if(aOffset[3] == aOffset[0]) {
5635  p = &pixels[n * 3];
5636  } else {
5637  p = &pixels[n * 4];
5638  p[aOffset[3]] = w;
5639  }
5640  p[aOffset[0]] = r;
5641  p[aOffset[1]] = g;
5642  p[aOffset[2]] = b;
5643  }
5644  }
5645 
5646  void NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
5647  if(n < numLEDs) {
5648  uint8_t *p,
5649  r = (uint8_t)(c >> 16),
5650  g = (uint8_t)(c >> 8),
5651  b = (uint8_t)c;
5652  if(brightness) {
5653  r = (r * brightness) >> 8;
5654  g = (g * brightness) >> 8;
5655  b = (b * brightness) >> 8;
5656  }
5657  if(aOffset[3] == aOffset[0]) {
5658  p = &pixels[n * 3];
5659  } else {
5660  p = &pixels[n * 4];
5661  uint8_t w = (uint8_t)(c >> 24);
5662  p[aOffset[3]] = brightness ? ((w * brightness) >> 8) : w;
5663  }
5664  p[aOffset[0]] = r;
5665  p[aOffset[1]] = g;
5666  p[aOffset[2]] = b;
5667  }
5668  }
5669 
5670  uint32_t NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) {
5671  return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
5672  }
5673 
5674  uint32_t NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
5675  return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
5676  }
5677 
5678  uint32_t NeoPixel::getPixelColor(uint16_t n) const {
5679  if(n >= numLEDs) return 0;
5680 
5681  uint8_t *p;
5682 
5683  if(aOffset[3] == aOffset[0]) {
5684  p = &pixels[n * 3];
5685  if(brightness) {
5686 
5687  return (((uint32_t)(p[aOffset[0]] << 8) / brightness) << 16) |
5688  (((uint32_t)(p[aOffset[1]] << 8) / brightness) << 8) |
5689  ( (uint32_t)(p[aOffset[2]] << 8) / brightness );
5690  } else {
5691  return ((uint32_t)p[aOffset[0]] << 16) |
5692  ((uint32_t)p[aOffset[1]] << 8) |
5693  (uint32_t)p[aOffset[2]];
5694  }
5695  } else {
5696  p = &pixels[n * 4];
5697  if(brightness) {
5698  return (((uint32_t)(p[aOffset[3]] << 8) / brightness) << 24) |
5699  (((uint32_t)(p[aOffset[0]] << 8) / brightness) << 16) |
5700  (((uint32_t)(p[aOffset[1]] << 8) / brightness) << 8) |
5701  ( (uint32_t)(p[aOffset[2]] << 8) / brightness );
5702  } else {
5703  return ((uint32_t)p[aOffset[3]] << 24) |
5704  ((uint32_t)p[aOffset[0]] << 16) |
5705  ((uint32_t)p[aOffset[1]] << 8) |
5706  (uint32_t)p[aOffset[2]];
5707  }
5708  }
5709  }
5710 
5711 
5712  uint8_t *NeoPixel::getPixels(void) const {
5713  return pixels;
5714  }
5715 
5716  uint16_t NeoPixel::numPixels(void) const {
5717  return numLEDs;
5718  }
5719 
5720  void NeoPixel::setBrightness(uint8_t b) {
5721 
5722  uint8_t newBrightness = b + 1;
5723  if(newBrightness != brightness) {
5724  uint8_t c,
5725  *ptr = pixels,
5726  oldBrightness = brightness - 1;
5727  uint16_t scale;
5728  if(oldBrightness == 0) scale = 0; // Avoid /0
5729  else if(b == 255) scale = 65535 / oldBrightness;
5730  else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
5731  for(uint16_t i=0; i<numBytes; i++) {
5732  c = *ptr;
5733  *ptr++ = (c * scale) >> 8;
5734  }
5735  brightness = newBrightness;
5736  }
5737  }
5738 
5739  uint8_t NeoPixel::getBrightness(void) const {
5740  return brightness - 1;
5741  }
5742 
5743  void NeoPixel::clear() {
5744  memset(pixels, 0, numBytes);
5745  }
5746 
5747  #endif
5748 
6189 #if EBOARD_NANO > 0x0 || defined(DOC)
6190 //offer more functions
6191  #if EBOARD_GUESSPATH > 0x0
6192  //import servo-class
6194  //shameless copy paste :D
6195  #define _useTimer1
6196  typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t;
6197  #define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
6198  #define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
6199  #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
6200  #define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
6201 
6202  #define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
6203  #define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
6204 
6205  #define INVALID_SERVO 255 // flag indicating an invalid servo index
6206  typedef struct {
6207  uint8_t nbr :6 ; // a pin number from 0 to 63
6208  uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
6209  } ServoPin_t;
6210 
6211  typedef struct {
6212  ServoPin_t Pin;
6213  volatile unsigned int ticks;
6214  } servo_t;
6215 
6216  class Servo {
6217  public:
6218  Servo();
6219  uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
6220  uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
6221  void detach();
6222  void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
6223  void writeMicroseconds(int value); // Write pulse width in microseconds
6224  inline int read(); // returns current pulse width as an angle between 0 and 180 degrees
6225  int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
6226  inline bool attached(); // return true if this servo is attached, otherwise false
6227  private:
6228  uint8_t servoIndex; // index into the channel data for this servo
6229  int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
6230  int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
6231  };
6232  #define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009
6233  #define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
6234 
6235 
6236  #define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
6237 
6238  //#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER)
6239 
6240  static servo_t servos[MAX_SERVOS]; // static array of servo structures
6241  static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
6242 
6243  uint8_t ServoCount = 0; // the total number of attached servos
6244 
6245  // convenience macros
6246  #define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
6247  #define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
6248  #define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
6249  #define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
6250 
6251  #define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
6252  #define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
6253 
6254  static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
6255  {
6256  if( Channel[timer] < 0 )
6257  *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
6258  else{
6259  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
6260  digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
6261  }
6262 
6263  Channel[timer]++; // increment to the next channel
6264  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
6265  *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
6266  if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated
6267  digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
6268  }
6269  else {
6270  // finished all channels so wait for the refresh period to expire before starting over
6271  if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
6272  *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
6273  else
6274  *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
6275  Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
6276  }
6277  }
6278 
6279  #ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
6280  // Interrupt handlers for Arduino
6281  #if defined(_useTimer1)
6282  SIGNAL (TIMER1_COMPA_vect)
6283  {
6284  handle_interrupts(_timer1, &TCNT1, &OCR1A);
6285  }
6286  #endif
6287  #elif defined WIRING
6288  // Interrupt handlers for Wiring
6289  #if defined(_useTimer1)
6290  void Timer1Service()
6291  {
6292  handle_interrupts(_timer1, &TCNT1, &OCR1A);
6293  }
6294  #endif
6295  #endif
6296 
6297  static void initISR(timer16_Sequence_t timer) {
6298  if(timer == _timer1) {
6299  TCCR1A = 0; // normal counting mode
6300  TCCR1B = _BV(CS11); // set prescaler of 8
6301  TCNT1 = 0; // clear the timer count
6302  TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
6303  TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
6304  #if defined(WIRING)
6305  timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
6306  #endif
6307  }
6308  }
6309 
6310  static void finISR(timer16_Sequence_t timer) {
6311  #if defined WIRING // Wiring
6312  if(timer == _timer1) {
6313  TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
6314  timerDetach(TIMER1OUTCOMPAREA_INT);
6315  }
6316  else if(timer == _timer3) {
6317  ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
6318  timerDetach(TIMER3OUTCOMPAREA_INT);
6319  }
6320  #else
6321  //For arduino - in future: call here to a currently undefined function to reset the timer
6322  (void) timer; // squash "unused parameter 'timer' [-Wunused-parameter]" warning
6323  #endif
6324  }
6325 
6326  static boolean isTimerActive(timer16_Sequence_t timer) {
6327  // returns true if any servo is active on this timer
6328  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
6329  if(SERVO(timer,channel).Pin.isActive == true)
6330  return true;
6331  }
6332  return false;
6333  }
6334 
6335  Servo::Servo() {
6336  if( ServoCount < MAX_SERVOS) {
6337  this->servoIndex = ServoCount++; // assign a servo index to this instance
6338  servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
6339  }
6340  else
6341  this->servoIndex = INVALID_SERVO ; // too many servos
6342  }
6343 
6344  uint8_t Servo::attach(int pin) {
6345  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
6346  }
6347 
6348  uint8_t Servo::attach(int pin, int min, int max) {
6349  if(this->servoIndex < MAX_SERVOS ) {
6350  pinMode( pin, OUTPUT) ; // set servo pin to output
6351  servos[this->servoIndex].Pin.nbr = pin;
6352  // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
6353  this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
6354  this->max = (MAX_PULSE_WIDTH - max)/4;
6355  // initialize the timer if it has not already been initialized
6356  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
6357  if(isTimerActive(timer) == false)
6358  initISR(timer);
6359  servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
6360  }
6361  return this->servoIndex ;
6362  }
6363 
6364  void Servo::detach() {
6365  servos[this->servoIndex].Pin.isActive = false;
6366  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
6367  if(isTimerActive(timer) == false) {
6368  finISR(timer);
6369  }
6370  }
6371 
6372  void Servo::write(int value) {
6373  if(value < MIN_PULSE_WIDTH)
6374  { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
6375  if(value < 0) value = 0;
6376  if(value > 180) value = 180;
6377  value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
6378  }
6379  this->writeMicroseconds(value);
6380  }
6381 
6382  void Servo::writeMicroseconds(int value) {
6383  // calculate and store the values for the given channel
6384  byte channel = this->servoIndex;
6385  if( (channel < MAX_SERVOS) ) // ensure channel is valid
6386  {
6387  if( value < SERVO_MIN() ) // ensure pulse width is valid
6388  value = SERVO_MIN();
6389  else if( value > SERVO_MAX() )
6390  value = SERVO_MAX();
6391 
6392  value = value - TRIM_DURATION;
6393  value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
6394 
6395  uint8_t oldSREG = SREG;
6396  cli();
6397  servos[channel].ticks = value;
6398  SREG = oldSREG;
6399  }
6400  }
6401 
6402  inline int Servo::read() // return the value as degrees
6403  {
6404  return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
6405  }
6406 
6407  int Servo::readMicroseconds() {
6408  unsigned int pulsewidth;
6409  if( this->servoIndex != INVALID_SERVO )
6410  pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009
6411  else
6412  pulsewidth = 0;
6413 
6414  return pulsewidth;
6415  }
6416 
6417  inline bool Servo::attached() {
6418  return servos[this->servoIndex].Pin.isActive ;
6419  }
6421  #endif
6422 #endif
6423 
6424 #if EBOARD_COPY_AND_PASTE > 0x0
6426  if (_pwmValue!=_OpwmValue){
6427  analogWrite(PIN_MOTOR_SPE,_pwmValue);
6429  }
6430  #ifdef REPT_TASK
6431  rept_task();
6432  #endif
6433  }
6434  #if EBOARD_NANO > 0x0
6435  Servo mainMotor,steerMotor;
6436  #endif
6437  int timer_count = 0;
6438  bool timer_ofl = false;
6439  ISR(TIMER2_OVF_vect) {
6440  timer_count++;
6441  if(timer_count >= EBOARD_PWM_SPE*1000 && !timer_ofl){
6442  timer_ofl = true;
6443  timer_count -= EBOARD_PWM_SPE*1000;
6444  trig_rept_task();
6445  timer_ofl = false;
6446  }
6447  TCNT2 = 256 - (int)((float)F_CPU * 0.001 / 64);
6448  }
6449 
6450 
6452  extern int eVirtual_main();
6454  void setup(void);
6455 
6457  void setup(void) {
6458  //setup of RX and TX should be handled manually - in everyCase ^^
6459  #if EBOARD_NANO == 0x0
6462  #endif
6463  #if EBOARD_DEBUG_MODE > 0x0
6464  Serial.begin(EBOARD_DEBUG_SPEED);
6465  #endif
6466  //this will initialize the interrupt handling!
6467  #if (EBOARD_NANO == 0x0) || defined(REPT_TASK)
6468  cli();
6469  TIMSK2 &= ~(1<<TOIE2);
6470  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
6471  TCCR2B &= ~(1<<WGM22);
6472  ASSR &= ~(1<<AS2);
6473  TIMSK2 &= ~(1<<OCIE2A);
6474  TCCR2B |= (1<<CS22);
6475  TCCR2B &= ~((1<<CS21) | (1<<CS20));
6476  TCNT2 = 256 - (int)((float)F_CPU * 0.001 / 64);
6477  TIMSK2 |= (1<<TOIE2);
6478  sei();
6479  #endif
6480  #if EBOARD_BLUETOOTH > 0x0
6481 
6482  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
6483  Serial1.begin(38400);
6484  #else
6485  _serial.begin(38400);
6486  #endif
6488  #endif
6489  #if EBOARD_I2C > 0x0
6490  Wire.begin();
6491  #endif
6492  #if EBOARD_SHIFT_REGISTER > 0x0
6493  pinMode(PIN_SHIFT_CLK,OUTPUT);
6494  pinMode(PIN_SHIFT_DAT,OUTPUT);
6495  pinMode(PIN_SHIFT_LAT,OUTPUT);
6496  shiftAll(); //set all to 0
6497  #endif
6498  #if EBOARD_USE_SPI > 0x0 && (EBOARD_NANO == 0)
6499  _servoHandler.begin(); //Setup SPI
6500  #endif
6501  #if EBOARD_NANO > 0x0
6502  mainMotor.attach(EBOARD_NANO_MAIN);
6503  steerMotor.attach(EBOARD_NANO_STEER);
6504  #if EBOARD_DEBUG_MODE > 0x0
6505  Serial.println("Initializing main driving motor (3s)");
6506  #endif
6507  mainMotor.write(90);
6508  delay(3005);
6509  #if EBOARD_DEBUG_MODE > 0x0
6510  Serial.println("Initializing of main driving motor completed");
6511  #endif
6512  #endif
6513  #if EBOARD_DEBUG_MODE > 0x0
6514  Serial.print((char) eVirtual_main());
6515  Serial.println("fin");
6516  #else
6517  eVirtual_main();
6518  #endif
6519  if (STOP) {} //prevent unused error
6520  delay(200);
6521  #if EBOARD_NANO > 0x0
6522  mainMotor.write(90);
6523  #endif
6524  cli(); //disable timers after running the program :D
6525  #if EBOARD_NANO == 0x0
6526  writePWM(0);analogWrite(PIN_MOTOR_SPE,0);
6527  #endif
6528  }
6531  void loop(void);
6533  void loop(void){
6534  //shall be empty
6535  }
6537 
6538 #endif
6539 
6540 #if EBOARD_NANO > 0x0 || defined(DOC)
6541 
6545  inline void set_motor_speed(optVAL_t spe);
6546 
6547 
6552  inline void set_steer_angle(optVAL_t ang);
6553 
6555  inline void set_motor_speed(optVAL_t spe){
6556  if(spe < 0 || spe > 180) return;
6557  mainMotor.write(spe);
6558  }
6559  inline void set_steer_angle(optVAL_t ang){
6560  if(ang < 0 || ang > 180) return;
6561  steerMotor.write(ang);
6562  }
6564 #endif
6565 
6566 #else
6567  #error This library is build for arduino-devices and should be used only in the Arduino IDE or with a similar linking process
6568 #endif
6569 #pragma GCC diagnostic pop
6570 #pragma pack(pop)
6571 
6572 #endif
int actPos
stores the actual pos or move-to pos of the AX12Servo
Definition: eBoard.h:3242
uint16_t _rx_delay_intrabit
the rx startbit delay
Definition: eBoard.h:1778
uint8_t * pixels
stores the pixels
Definition: eBoard.h:4551
void onRequest(void(*function)(void))
this will set the user_onRequest method
volatile uint8_t * port
the used port register
Definition: eBoard.h:4558
virtual size_t write(uint8_t data)
this will write a single unsigned 8-bit value to address
void recv(void)
private receive routine called each time interrupt handler gets triggered
#define LCD_COMMAND_DISPLAY_OFF
Definition: eBoard.h:3883
SoccerBoard(void)
The constructor.
void setTX(uint8_t transmitPin)
sets a specific pin to be &#39;the chosen one&#39; as a txPin
int8_t pin
stores the pin -1 if the pin wasn&#39;t set
Definition: eBoard.h:4547
optVAL_t readPin(optVAL_t idx, bool dig=true)
read a digital state from an INPUTpin
optVAL_t C
storing value for C-pin [MOTOR SPE]
Definition: eBoard.h:3089
void begin(long speed)
the start function to setup delay_values etc.
AX12Servo * connected[2]
stores the pointers to the registerd AX12Servo
Definition: eBoard.h:3332
#define LCD_COMMAND_CHARGE_PUMP_ENABLE
Definition: eBoard.h:3900
const unsigned char * buf[11]
to enable &#39;smooth&#39; access (:
uint8_t _transmitBitMask
the pin mask to address the tx pin
Definition: eBoard.h:1771
[COPY&PASTE] This is the SoccerBoard ghost struct :D
Definition: eBoard.h:2813
static void(* user_onReceive)(int numBytes)
twi slave [Rx]receive-event user def handler
Definition: eBoard.h:972
bool checkPin(optVAL_t idx, optVAL_t mode=0x1)
[COPY&PASTE] [CHECK_PINS] Check if a pin is set to a specific mode
#define PIN_MAX
Definition: eBoard.h:612
uint8_t aOffset[4]
stores the offsets in rgbw format
Definition: eBoard.h:4553
#define BUFFER_LENGTH
Definition: eBoard.h:928
#define LCD_COMMAND_MODE
Definition: eBoard.h:3879
#define EBOARD_CHECK_PINS
Definition: eBoard.h:1516
#define LCD_COMMAND_CHARGE_PUMP_SETTING
Definition: eBoard.h:3898
static volatile uint8_t _receive_buffer_head
current location in rxBuffer
Definition: eBoard.h:1793
void checkIdx(optVAL_t idx)
[DEBUG_MODE] used to check if a pin index is in bounds
SoftwareSerial _serial(0x13, 0x12)
this is the recomenned-to-use _serial object for bluetooth communcation :D
optVAL_t _OpwmValue
Definition: eBoard.h:2579
[COPY&PASTE] This is the AX12Servo ghost struct :D
Definition: eBoard.h:3134
static void detachInterrupt(void)
disables the interrupt feature
void write(void)
this will write values stored in B and C
static uint8_t rxBufferIndex
this defines the rxBuffer Index - current position in rxBuffer array
Definition: eBoard.h:951
bool canShow(void)
this will determine if the next show is available [last show finished]
void storePosition(int pos, int speed=0x3FF)
This saves the Servo Position.
int actSpe
stores the actual &#39;would use speed&#39; of the AX12Servo
Definition: eBoard.h:3244
optVAL_t getPosition(void)
This "kind of" returns the Servo-Position.
virtual size_t write(uint8_t byte)
writes a specific value to the tx register
optVAL_t B
storing value for B-pin [MOTOR DIR]
Definition: eBoard.h:3087
void setID(optVAL_t newID)
change the AX-12 Servo this object should speak to
#define PIN_MOTOR_SPE
Definition: eBoard.h:1699
uint8_t getBrightness(void) const
returns the current set brightness
[SPI] This is used to avoid path resolving issues and defines the common known Arduino SPI interface ...
Definition: eBoard.h:1365
void __assert(const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp)
[DEBUG_MODE] custom assert message
uint16_t numLEDs
stores the amount of LEDs
Definition: eBoard.h:4540
I2CInOut(SoccerBoard &, optVAL_t, optVAL_t, optVAL_t, optVAL_t)
The constructor.
void button(int)
šŸ”§ I prevent errors!
bool isListening(void)
checks if this object is the listening object
#define SPI_CLOCK_MASK
Definition: eBoard.h:1348
~NeoPixel(void)
the destructor [calling free on pixel and freeing input pin]
#define EBOARD_BLUETOOTH
Definition: eBoard.h:528
bool timer_ofl
Definition: eBoard.h:6438
byte pY
posY
Definition: eBoard.h:4127
static uint8_t txBufferIndex
this defines the txBuffer Index - current position in txBuffer array
Definition: eBoard.h:960
static void onRequestService(void)
twi slave [Tx]transmitting-event handler
uint16_t _rx_delay_stopbit
the rx stopbit dely
Definition: eBoard.h:1780
char channel(optVAL_t)
will return the next char received by the module. A 64 byte Serial buffer is included! ...
This is used to avoid path resolving issues and defines the common known Arduino Wire-Interface &#160;&#160;&#160;...
Definition: eBoard.h:946
int peek(void)
reads the actual pointed rxBuffer element without dropping it
void led(int idx, bool state)
[MEGA] Control the OnBoard LED
#define PIN_SHIFT_CLK
Definition: eBoard.h:1706
uint8_t rx_pin_read(void)
simple routine to read the rxPin by registers
bool begun
true if NeoPixel::begin has been called
Definition: eBoard.h:4538
static uint8_t transmitting
&#39;boolean&#39; value. Set to 1 if transmitting => in master write mode
Definition: eBoard.h:965
optVAL_t countSetBits(optVAL_t x)
[COPY&PASTE] [CHECK_PWM] counts high-bits in an int/byte (determined by IGNORE_SIZE) ...
RB14Scan(void)
The constructor.
void s2Cmd(optVAL_t o, optVAL_t t)
this function will execute two cmd sends without starting and without ending the transmission ...
void ledOff(int idx)
[MEGA] Deactivate the OnBoard LED
optVAL_t sendI2C(optVAL_t deviceID, byte *buf, byte buf_len)
Sends a buffer of bytes to a certain I²C-Device.
bool checkOverflow(void)
[BLUETOOTH] checks if theres a lack of Data!
void ledMeter(int)
[MEGA] Activate the OnBoard LED
void powerOn(optVAL_t id)
Set the state of a certain D-pin to HIGH.
#define LCD_HEIGHT
Definition: eBoard.h:3908
void changeModes(optVAL_t, optVAL_t, optVAL_t)
šŸ”§ I prevent errors!
static void end(void)
this will end the SPI connection
int8_t getPin(void)
this will return the set data pin
void reset(void)
Resets the Soccerboard if EBOARD_USE_RESET is set to true.
#define EBOARD_USE_UTILITY
Definition: eBoard.h:1575
bool _cI
called_guard
Definition: eBoard.h:4129
void trig_rept_task()
Definition: eBoard.h:6425
#define LCD_WIDTH
Definition: eBoard.h:3904
bool listen(void)
sets the SoftwareSerial object to be the listening one gaining control over the buffers etc...
bool reset(void)
clears the screen
bool isMoving(void)
Use this if you wan&#39;t to have a nice way of writing false.
#define LCD_DATA_MODE
Definition: eBoard.h:3881
void set_steer_angle(optVAL_t ang)
sets the angle of the steering (data pin: EBOARD_NANO_STEER) motor
void sleep(uint16_t t)
Say goodnight!
void setTorque(uint16_t)
šŸ”§ I prevent errors!
long store_bits
[SHIFT] Manipulate me to set Pins via bitSet operations
Definition: eBoard.h:2547
void setup(void)
[COPY&PASTE] As we have an Arduino we need a setup function ;)
void changeMode(bool newMode=true)
enable or disable the display
NeoPixel pixels
the NeoPixel-object we use
void ledOn(void)
Noone needs the AX-12 Servo LED^^.
static uint8_t rxBufferLength
this defines the length of rxBuffer
Definition: eBoard.h:953
static uint8_t txAddress
this defines the txAddress the transmitting Dta
Definition: eBoard.h:956
#define SPI_MODE_MASK
Definition: eBoard.h:1346
int storedPos
stores the position the Servo should go to DynamixelBoard::action()
Definition: eBoard.h:3228
void shiftSingle(optVAL_t idx, bool val)
[SHIFT] Changes a single output Pin
void set_motor_speed(optVAL_t spe)
sets the speed of the main (data pin: EBOARD_NANO_MAIN) motor
bool init(void)
initializes the Display called by:
void tx_pin_write(uint8_t pin_state)
writes a bool value on the txPin by registers
static uint8_t txBuffer[]
this defines the txBuffer used to enable delayed read
Definition: eBoard.h:958
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
sets the rgb color of a specific pixel
void changeAddress(optVAL_t)
šŸ”§ I prevent errors!
#define EBOARD_NANO_STEER
Definition: eBoard.h:1495
#define EBOARD_NEO_800KHZ
Definition: eBoard.h:4369
this namespace contains all the Don&#39;t use manually classes ;)
static void attachInterrupt(void)
enables the interrupt feature
SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic=false)
the constructor for the SoftwareSerial object
#define EBOARD_NANO_MAIN
Definition: eBoard.h:1501
virtual void flush(void)
resets the position in buffer and the buffer itself if the object is listening
#define EBOARD_SPI_SERVO_MAX
Definition: eBoard.h:1566
static char _receive_buffer[64]
the buffer for rxBuffer
Definition: eBoard.h:1789
#define PIN_BLUETOOTH_RX
Definition: eBoard.h:1671
PROGMEM const byte basicFont[][8]
Definition: eBoard.h:3518
static void begin(void)
this will setup everything for SPI connection
optVAL_t _pwmValue
Definition: eBoard.h:2579
optVAL_t id
stores the id of the AX12Servo obejct
Definition: eBoard.h:3239
void msleep(uint16_t t)
Say goodnight!
#define LCD_COMMAND_DISPLAY_ON
Definition: eBoard.h:3885
#define SPI_CLOCK_DIV8
Definition: eBoard.h:1332
uint64_t pin_in
Definition: eBoard.h:2428
int sine8(uint8_t val)
will return the mapped 8-bit sin you can use in e.g. NeoPixel
Definition: eBoard.h:561
byte pX
the addressing mode (page/horizontal)
Definition: eBoard.h:4125
DynamixelBoard(SoccerBoard &)
The constructor.
void updateLength(uint16_t n)
this changes the length of the connected LED stripe
ServoCds55 _servoHandler
this is the "to_use" instance of ServoCds55
Definition: eBoard.h:2784
#define EBOARD_CLAMP
Definition: eBoard.h:1621
void pingI2C(optVAL_t ret[], optVAL_t ret_len)
Sends a byte to a certain I²C-Device.
uint16_t numBytes
stores the byte size [pixels] used internally
Definition: eBoard.h:4542
void writeVal(const T &val)
[BLUETOOTH] writes Data to bluetooth
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b)
returns a color value that can be used with NeoPixel::setPixelColor()
void setPin(uint8_t p)
sets pin for communication
virtual int read(void)
this will read a single byte from rxBuffer and increment the Index
void clear(void)
this will reset all set pixels [won&#39;t call NeoPixel::show()]
bool setCursor(byte posX=0x0, byte posY=0x0)
set the position of the cursor
uint8_t * getPixels(void) const
this will give you access to the pixels
static bool STOP
Definition: eBoard.h:1456
~SoftwareSerial(void)
the destructor of the SoftwareSerial object
#define LCD_PAGE_ADDRESSING
Definition: eBoard.h:3893
#define EBOARD_NANO
Definition: eBoard.h:1487
LCD(SoccerBoard &soccerBoard, optVAL_t id=0x3C)
The constructor.
void waitForButton(int)
šŸ”§ I prevent errors!
#define EBOARD_PWM_SPE
Definition: eBoard.h:1591
#define EBOARD_CHECK_PINS_PWM
Definition: eBoard.h:1542
void motorsOff(void)
As requested this is the shortcut to disable the main motor.
int raw(optVAL_t)
this will check for connection status [will return true if pin not connected]
bool overflow(void)
returns the current overflow flag and disables it
static void setDataMode(uint8_t mode)
this will set the Data transfer mode
void updateType(uint16_t t)
this changes the type of communication between arduino and LED stripe
virtual int available(void)
checks if there is data to read available
uint64_t pin_out
Definition: eBoard.h:2420
#define LCD_COMMAND_WHITE_BACKGROUND
Definition: eBoard.h:3889
NeoPixel(void)
the empty constructor
[COPY&PASTE] [BLUETOOTH] This is the RB14Scan ghost struct :D
Definition: eBoard.h:3394
uint8_t requestFrom(uint8_t address, uint8_t quantity)
this will read a specific quantity of bytes from a specific address
void changeBackground(bool newBackground=false)
changes the background of the display
static void onReceiveService(uint8_t *inBytes, int numBytes)
twi slave [Rx]receive-event handler
void begin()
begin the TwoWire communcation without any data set
#define EBOARD_NEO
Definition: eBoard.h:544
optVAL_t ID
ID of the Display.
Definition: eBoard.h:4119
void motor(uint8_t id, int16_t val)
As requested this is the ultimate shortcut ;)
bool digital(optVAL_t id)
Reads a digital value from a pin.
#define PIN_SHIFT_LAT
Definition: eBoard.h:1718
static void handle_interrupt(void)
used to handle interrupts on active listening object
#define EBOARD_SHIFT_REGISTER
Definition: eBoard.h:524
int storedSpe
stores the Speed of the Servo DynamixelBoard::action()
Definition: eBoard.h:3234
[COPY&PASTE] This is the DynamixelBoard ghost struct :D
Definition: eBoard.h:3305
SPIClass SPI
Definition: eBoard.h:1440
TwoWire()
The constructor of the TwoWire class.
#define EBOARD_NEO_GRB
Definition: eBoard.h:4308
volatile uint8_t * _transmitPortRegister
the register the reveice pin is located on
Definition: eBoard.h:1773
static void setClockDivider(uint8_t rate)
this will change the clock devider the
void write(const char *const val)
this will write a constant string to the output
int timer_count
Definition: eBoard.h:6437
void beginTransmission(uint8_t address)
this will start a new transmission to a specific address => master mode
void power(optVAL_t id, bool state)
Set the state of a certain D-pin.
void writePin(optVAL_t idx, bool val)
write a boolean state to an output pin
void s1Dat(optVAL_t o)
this function will execute one dat send without starting and without ending the transmission ...
#define PIN_MOTOR_DIR
Definition: eBoard.h:1692
uint32_t endTime
stores the last call time of show for NeoPixel::canShow()
Definition: eBoard.h:4555
void changeId(optVAL_t)
šŸ”§ I prevent errors!
uint16_t _tx_delay
the (generic) tx delay
Definition: eBoard.h:1782
DynamixelBoard * _conBoard
Definition: eBoard.h:3148
virtual int peek(void)
this will read a single byte from rxBuffer without increment the Index
void setBrightness(uint8_t val)
changes the brightness for all further acceses via NeoPixel::setPixelColor()
void setSpeed(optVAL_t)
šŸ”§ I prevent errors!
void lightOn(void)
enable the backlight
[COPY&PASTE] This is the I2CInOut ghost struct :D
Definition: eBoard.h:3062
#define LCD_COMMAND_BLACK_BACKGROUND
Definition: eBoard.h:3887
void lightOff(void)
disable the backlight
void setRX(uint8_t receivePin)
sets a specific pin to be &#39;the chosen one&#39; as a rxPin
bool clear(void)
clears the LCD
bool s1Cmd(optVAL_t o)
this function will execute one cmd send without starting and without ending the transmission ...
#define PIN_BLUETOOTH_TX
Definition: eBoard.h:1682
void onReceive(void(*function)(int))
this will set the user_onReceive method
void writePWM(optVAL_t val)
write a clamped pwm value to an output pin
void setPin(optVAL_t idx, optVAL_t mode=0x1)
[COPY&PASTE] set a pin to a certain mode => checkPin() will return true then
uint8_t brightness
stores the brightness
Definition: eBoard.h:4549
uint8_t pinMask
the used pinMask
Definition: eBoard.h:4560
char readVal(char oF='.')
[BLUETOOTH] reads a single value from bluetooth if available!
void ledsOff(void)
[MEGA] Deactivate the OnBoard LED
static uint8_t txBufferLength
this defines the length of txBuffer
Definition: eBoard.h:962
static byte transfer(byte _data)
this will send a single bite via the SPI connection
void setPositionMode(void)
set the AX-12 Servo to positionMode
static void setBitOrder(uint8_t bitOrder)
this will set the BitOrder
int gamma8(uint8_t val)
will return the mapped 8-bit gamma correction you can use in e.g. NeoPixel
Definition: eBoard.h:569
void end(void)
ends communcation on the rx pin
void action(void)
will force every AX12Servo to drive to AX12Servo::storedPos with AX12Servo::storedSpeed ...
static SoftwareSerial * active_object
the active SoftwareSerial object to operate on
Definition: eBoard.h:1795
bool changeBrightness(byte val=0x64)
changes the brightness of the display
void read(void)
šŸ”§ I prevent errors!
optVAL_t analog(optVAL_t id)
Reads an analog value from a pin.
void readI2C(optVAL_t deviceID, optVAL_t ret[], optVAL_t ret_len, bool blocking=true)
Reads a special amount of bits from a certain I²C-Device.
void ledOn(int idx)
[MEGA] Activate the OnBoard LED
AX12Servo(void)
The constructor.
void ledOn(optVAL_t)
šŸ”§ I prevent errors!
bool changeID(optVAL_t newID=0x3C)
changes the address of the LCD display talked to
void setPosition(int pos, int speed=0x3FF)
This moves the Servo to the new position.
uint16_t _inverse_logic
determining if all pin reads etc whould be inverted (e.g. no pullup on rx);
Definition: eBoard.h:1787
DynamixelBoard dBoard(board)
the dBoard object
#define EBOARD_USE_RESET
Definition: eBoard.h:1645
bool is800KHz
determines the speed the communcation is working on
Definition: eBoard.h:4536
int optVAL_t
Definition: eBoard.h:1466
uint16_t _rx_delay_centering
the rx center delay
Definition: eBoard.h:1776
#define _SS_MAX_RX_BUFF
Definition: eBoard.h:1736
ISR(TIMER2_OVF_vect)
Definition: eBoard.h:6439
bool isConnected(void)
[BLUETOOTH] this will check if the HC-05 is paired
TwoWire Wire
this is the well-known Arduino Wire Interface, just a little bit &#39;modified&#39; ;P
Definition: eBoard.h:1299
static volatile uint8_t _receive_buffer_tail
size of rxBuffer
Definition: eBoard.h:1791
uint8_t endTransmission(void)
this will end the transmission and send the STOP-sequence
#define PIN_BLUETOOTH_STATE
Definition: eBoard.h:1660
#define EBOARD_DEBUG_MODE
Definition: eBoard.h:1473
void print(const char *data)
prints a string to the display
void setSpeedMode(void)
set the AX-12 Servo NOT to speedMode
int eVirtual_main()
[COPY&PASTE] Assures the existence of the "qfix-code-main-method"
virtual int available(void)
this will return the amount of rxBuffer left
uint8_t _receivePin
the id of the receive pin
Definition: eBoard.h:1765
#define SPI_2XCLOCK_MASK
Definition: eBoard.h:1350
void drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY)
draws a bitmap representet as an array of bytes
void shiftAll(void)
[SHIFT] Changes bits according to store_bits
void ledOff(void)
Noone needs the AX-12 Servo LED^^.
void powerOff(optVAL_t id)
Set the state of a certain D-pin to LOW.
uint16_t _buffer_overflow
determining if an _buffer_overflow occured
Definition: eBoard.h:1785
static void(* user_onRequest)(void)
twi slave [Tx]transmitting-event user def handler
Definition: eBoard.h:967
uint8_t _receiveBitMask
the pin mask to directly read from register (Rx)
Definition: eBoard.h:1767
virtual int read(void)
reads the actual pointed rxBuffer top element
static uint8_t rxBuffer[]
this defines the rxBuffer used to enable delayed read
Definition: eBoard.h:949
volatile uint8_t * _receivePortRegister
the register the reveice pin is located on
Definition: eBoard.h:1769
void begin(void)
this has to be called to start the communcation (you should call NeoPixel::setPin() before) ...
void loop(void)
[COPY&PASTE] As we have an Arduino we need a setup function ;)
[NEO] this allows you to access Adafruit LED-stripes
Definition: eBoard.h:4412
uint32_t getPixelColor(uint16_t n) const
returns the color of a specific pixel
void changeMotorID(optVAL_t)
šŸ”§ I prevent errors!
void show(void)
this will reveal the setPixels [via NeoPixel::setPixelColor() etc...]
uint16_t numPixels(void) const
returns the size of the LED stripe
void ledOff(optVAL_t)
šŸ”§ I prevent errors!
static void tunedDelay(uint16_t delay)
apply a specific delay to achieve higher precision
#define PIN_SHIFT_DAT
Definition: eBoard.h:1712
[I2C] [LCD] This is used to add support for OLED displays connected to the &#39;SoccerBoard&#39; ...
Definition: eBoard.h:3951
void changeMotorID(optVAL_t newID)
change the hardwareID of this AX-12 Servo and will continue speaking to the new [reconnection recomme...
#define EBOARD_DEBUG_SPEED
Definition: eBoard.h:1555
optVAL_t A
storing value for A-pin (šŸ”§ I prevent errors!)
Definition: eBoard.h:3084
This is used to avoid path resolving issues and defines the common known Arduino SoftwareSerial inter...
Definition: eBoard.h:1762