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