Advertisement
mrjonny2

Ports.cpp

Mar 26th, 2012
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.95 KB | None | 0 0
  1. // Ports library definitions
  2. // 2009-02-13 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
  3. // $Id: Ports.cpp 5984 2010-09-02 00:48:55Z jcw $
  4.  
  5. #include "Ports.h"
  6. #include <avr/sleep.h>
  7.  
  8. // flag bits sent to the receiver
  9. #define MODE_CHANGE 0x80    // a pin mode was changed
  10. #define DIG_CHANGE  0x40    // a digital output was changed
  11. #define PWM_CHANGE  0x30    // an analog (pwm) value was changed on port 2..3
  12. #define ANA_MASK    0x0F    // an analog read was requested on port 1..4
  13.  
  14. uint16_t Port::shiftRead(uint8_t bitOrder, uint8_t count) const {
  15.     uint16_t value = 0, mask = bit(LSBFIRST ? 0 : count - 1);
  16.     for (uint8_t i = 0; i < count; ++i) {
  17.         digiWrite2(1);
  18.         delayMicroseconds(5);
  19.         if (digiRead())
  20.             value |= mask;
  21.         if (bitOrder == LSBFIRST)
  22.             mask <<= 1;
  23.         else
  24.             mask >>= 1;
  25.         digiWrite2(0);
  26.         delayMicroseconds(5);
  27.     }
  28.     return value;
  29. }
  30.  
  31. void Port::shiftWrite(uint8_t bitOrder, uint16_t value, uint8_t count) const {
  32.     uint16_t mask = bit(LSBFIRST ? 0 : count - 1);
  33.     for (uint8_t i = 0; i < count; ++i) {
  34.         digiWrite(value & mask);
  35.         if (bitOrder == LSBFIRST)
  36.             mask <<= 1;
  37.         else
  38.             mask >>= 1;
  39.         digiWrite2(1);
  40.         digiWrite2(0);
  41.     }
  42. }
  43.  
  44. RemoteNode::RemoteNode (char id, uint8_t band, uint8_t group)
  45.     : nid (id & 0x1F)
  46. {
  47.     memset(&data, 0, sizeof data);
  48.     RemoteHandler::setup(nid, band, group);
  49. }
  50.  
  51. void RemoteNode::poll(uint16_t msecs) {
  52.     uint8_t pending = millis() >= lastPoll + msecs;
  53.     if (RemoteHandler::poll(*this, pending))
  54.         lastPoll = millis();
  55. }
  56.  
  57. void RemotePort::mode(uint8_t value) const {
  58.     node.data.flags |= MODE_CHANGE;
  59.     bitWrite(node.data.modes, pinBit(), value);
  60. }
  61.  
  62. uint8_t RemotePort::digiRead() const {
  63.     return bitRead(node.data.digiIO, pinBit());
  64. }
  65.  
  66. void RemotePort::digiWrite(uint8_t value) const {
  67.     node.data.flags |= DIG_CHANGE;
  68.     bitWrite(node.data.digiIO, pinBit(), value);
  69. }
  70.  
  71. void RemotePort::anaWrite(uint8_t val) const {
  72.     if (portNum == 2 || portNum == 3) {
  73.         bitSet(node.data.flags, portNum + 2);
  74.         node.data.anaOut[portNum - 2] = val;
  75.     } else
  76.         digiWrite2(val >= 128);
  77. }
  78.    
  79. void RemotePort::mode2(uint8_t value) const {
  80.     node.data.flags |= MODE_CHANGE;
  81.     bitWrite(node.data.modes, pinBit2(), value);
  82. }
  83.    
  84. uint16_t RemotePort::anaRead() const {
  85.     bitSet(node.data.flags, pinBit());
  86.     return node.data.anaIn[pinBit()];
  87. }
  88.    
  89. uint8_t RemotePort::digiRead2() const {
  90.     return bitRead(node.data.digiIO, pinBit2());
  91. }
  92.  
  93. void RemotePort::digiWrite2(uint8_t value) const {
  94.     node.data.flags |= DIG_CHANGE;
  95.     bitWrite(node.data.digiIO, pinBit2(), value);
  96. }
  97.  
  98. PortI2C::PortI2C (uint8_t num, uint8_t rate)
  99.     : Port (num), uswait (rate)
  100. {
  101.     sdaOut(1);
  102.     mode2(OUTPUT);
  103.     sclHi();
  104. }
  105.  
  106. uint8_t PortI2C::start(uint8_t addr) const {
  107.     sclLo();
  108.     sclHi();
  109.     sdaOut(0);
  110.     return write(addr);
  111. }
  112.  
  113. void PortI2C::stop() const {
  114.     sdaOut(0);
  115.     sclHi();
  116.     sdaOut(1);
  117. }
  118.  
  119. uint8_t PortI2C::write(uint8_t data) const {
  120.     sclLo();
  121.     for (uint8_t mask = 0x80; mask != 0; mask >>= 1) {
  122.         sdaOut(data & mask);
  123.         sclHi();
  124.         sclLo();
  125.     }
  126.     sdaOut(1);
  127.     sclHi();
  128.     uint8_t ack = ! sdaIn();
  129.     sclLo();
  130.     return ack;
  131. }
  132.  
  133. uint8_t PortI2C::read(uint8_t last) const {
  134.     uint8_t data = 0;
  135.     for (uint8_t mask = 0x80; mask != 0; mask >>= 1) {
  136.         sclHi();
  137.         if (sdaIn())
  138.             data |= mask;
  139.         sclLo();
  140.     }
  141.     sdaOut(last);
  142.     sclHi();
  143.     sclLo();
  144.     if (last)
  145.         stop();
  146.     sdaOut(1);
  147.     return data;
  148. }
  149.  
  150. bool DeviceI2C::isPresent () const {
  151.     byte ok = send();
  152.     stop();
  153.     return ok;
  154. }
  155.  
  156. byte MilliTimer::poll(word ms) {
  157.     byte ready = 0;
  158.     if (armed) {
  159.         word remain = next - millis();
  160.         // since remain is unsigned, it will overflow to large values when
  161.         // the timeout is reached, so this test works as long as poll() is
  162.         // called no later than 5535 millisecs after the timer has expired
  163.         if (remain <= 60000)
  164.             return 0;
  165.         // return a value between 1 and 255, being msecs+1 past expiration
  166.         // note: the actual return value is only reliable if poll() is
  167.         // called no later than 255 millisecs after the timer has expired
  168.         ready = -remain;
  169.     }
  170.     set(ms);
  171.     return ready;
  172. }
  173.  
  174. word MilliTimer::remaining() const {
  175.     word remain = armed ? next - millis() : 0;
  176.     return remain <= 60000 ? remain : 0;
  177. }
  178.  
  179. void MilliTimer::set(word ms) {
  180.     armed = ms != 0;
  181.     if (armed)
  182.         next = millis() + ms - 1;
  183. }
  184.  
  185. void BlinkPlug::ledOn (byte mask) {
  186.     if (mask & 1) {
  187.         digiWrite(0);
  188.         mode(OUTPUT);
  189.     }
  190.     if (mask & 2) {
  191.         digiWrite2(0);
  192.         mode2(OUTPUT);
  193.     }
  194.     leds |= mask; //TODO could be read back from pins, i.s.o. saving here
  195. }
  196.  
  197. void BlinkPlug::ledOff (byte mask) {
  198.     if (mask & 1) {
  199.         mode(INPUT);
  200.         digiWrite(1);
  201.     }
  202.     if (mask & 2) {
  203.         mode2(INPUT);
  204.         digiWrite2(1);
  205.     }
  206.     leds &= ~ mask; //TODO could be read back from pins, i.s.o. saving here
  207. }
  208.  
  209. byte BlinkPlug::state () {
  210.     byte saved = leds;
  211.     ledOff(1+2);
  212.     byte result = !digiRead() | (!digiRead2() << 1);
  213.     ledOn(saved);
  214.     return result;
  215. }
  216.  
  217. //TODO deprecated, use buttonCheck() !
  218. byte BlinkPlug::pushed () {
  219.     if (debounce.idle() || debounce.poll()) {
  220.         byte newState = state();
  221.         if (newState != lastState) {
  222.             debounce.set(100); // don't check again for at least 100 ms
  223.             byte nowOn = (lastState ^ newState) & newState;
  224.             lastState = newState;
  225.             return nowOn;
  226.         }
  227.     }
  228.     return 0;
  229. }
  230.  
  231. byte BlinkPlug::buttonCheck () {
  232.     // collect button changes in the checkFlags bits, with proper debouncing
  233.     if (debounce.idle() || debounce.poll()) {
  234.         byte newState = state();
  235.         if (newState != lastState) {
  236.             debounce.set(100); // don't check again for at least 100 ms
  237.             if ((lastState ^ newState) & 1)
  238.                 bitSet(checkFlags, newState & 1 ? ON1 : OFF1);
  239.             if ((lastState ^ newState) & 2)
  240.                 bitSet(checkFlags, newState & 2 ? ON2 : OFF2);
  241.             lastState = newState;
  242.         }
  243.     }
  244.     // note that simultaneous button events will be returned in successive calls
  245.     if (checkFlags)
  246.         for (byte i = ON1; i <= OFF2; ++i) {
  247.             if (bitRead(checkFlags, i)) {
  248.                 bitClear(checkFlags, i);
  249.                 return i;
  250.             }
  251.         }
  252.     // if there are no button events, return the overall current button state
  253.     return lastState ? SOME_ON : ALL_OFF;
  254. }
  255.  
  256. void MemoryPlug::load (word page, void* buf, byte offset, int count) {
  257.     setAddress(0x50 + (page >> 8));
  258.     send();
  259.     write((byte) page);
  260.     write(offset);
  261.     receive();
  262.     byte* p = (byte*) buf;
  263.     while (--count >= 0)
  264.         *p++ = read(count == 0);
  265.     stop();
  266. }
  267.  
  268. void MemoryPlug::save (word page, const void* buf, byte offset, int count) {
  269.     // don't do back-to-back saves, last one must have had time to finish!
  270.     while (millis() < nextSave)
  271.         ;
  272.  
  273.     setAddress(0x50 + (page >> 8));
  274.     send();
  275.     write((byte) page);
  276.     write(offset);
  277.     const byte* p = (const byte*) buf;
  278.     while (--count >= 0)
  279.         write(*p++);
  280.     stop();
  281.  
  282.     nextSave = millis() + 6;
  283.     // delay(5);
  284. }
  285.  
  286. long MemoryStream::position (byte writing) const {
  287.     long v = (curr - start) * step;
  288.     if (pos > 0 && !writing)
  289.         --v; // get() advances differently than put()
  290.     return (v << 8) | pos;
  291. }
  292.  
  293. byte MemoryStream::get () {
  294.     if (pos == 0) {
  295.         dev.load(curr, buffer);
  296.         curr += step;
  297.     }
  298.     return buffer[pos++];
  299. }
  300.  
  301. void MemoryStream::put (byte data) {
  302.     buffer[pos++] = data;
  303.     if (pos == 0) {
  304.         dev.save(curr, buffer);
  305.         curr += step;
  306.     }
  307. }
  308.  
  309. word MemoryStream::flush () {
  310.     if (pos != 0) {
  311.         memset(buffer + pos, 0xFF, 256 - pos);
  312.         dev.save(curr, buffer);
  313.     }
  314.     return curr;
  315. }
  316.  
  317. void MemoryStream::reset () {
  318.     curr = start;
  319.     pos = 0;
  320. }
  321.  
  322. // uart register definitions
  323. #define RHR     (0 << 3)
  324. #define THR     (0 << 3)
  325. #define DLL     (0 << 3)
  326. #define DLH     (1 << 3)
  327. #define FCR     (2 << 3)
  328. #define LCR     (3 << 3)
  329. #define RXLVL   (9 << 3)
  330.  
  331. void UartPlug::regSet (byte reg, byte value) {
  332.   dev.send();
  333.   dev.write(reg);
  334.   dev.write(value);
  335. }
  336.  
  337. void UartPlug::regRead (byte reg) {
  338.   dev.send();
  339.   dev.write(reg);
  340.   dev.receive();
  341. }
  342.  
  343. void UartPlug::begin (long baud) {
  344.     word divisor = 230400 / baud;
  345.     regSet(LCR, 0x80);          // divisor latch enable
  346.     regSet(DLL, divisor);       // low byte
  347.     regSet(DLH, divisor >> 8);  // high byte
  348.     regSet(LCR, 0x03);          // 8 bits, no parity
  349.     regSet(FCR, 0x07);          // fifo enable (and flush)
  350.     dev.stop();
  351. }
  352.  
  353. byte UartPlug::available () {
  354.     if (in != out)
  355.         return 1;
  356.     out = 0;
  357.     regRead(RXLVL);
  358.     in = dev.read(1);
  359.     if (in == 0)
  360.         return 0;
  361.     if (in > sizeof rxbuf)
  362.         in = sizeof rxbuf;
  363.     regRead(RHR);
  364.     for (byte i = 0; i < in; ++i)
  365.         rxbuf[i] = dev.read(i == in - 1);
  366.     return 1;
  367. }
  368.  
  369. int UartPlug::read () {
  370.     return available() ? rxbuf[out++] : -1;
  371. }
  372.  
  373. void UartPlug::flush () {
  374.     regSet(FCR, 0x07); // flush both RX and TX queues
  375.     dev.stop();
  376.     in = out;
  377. }
  378.  
  379. size_t UartPlug::write (byte data) {
  380.     regSet(THR, data);
  381.     dev.stop();
  382. }
  383.  
  384. void DimmerPlug::setReg(byte reg, byte value) const {
  385.     send();
  386.     write(reg);
  387.     write(value);
  388.     stop();
  389. }
  390.  
  391. byte DimmerPlug::getReg(byte reg) const {
  392.     send();
  393.     write(reg);
  394.     receive();
  395.     byte result = read(1);
  396.     stop();
  397.     return result;
  398. }
  399.  
  400. const word* LuxPlug::getData() {
  401.     send();
  402.     write(0xA0 | DATA0LOW);
  403.     receive();
  404.     data.b[0] = read(0);
  405.     data.b[1] = read(0);
  406.     data.b[2] = read(0);
  407.     data.b[3] = read(1);
  408.     stop();
  409.     return data.w;
  410. }
  411.  
  412. #define LUX_SCALE   14  // scale by 2^14
  413. #define RATIO_SCALE 9   // scale ratio by 2^9
  414. #define CH_SCALE    10  // scale channel values by 2^10
  415.  
  416. word LuxPlug::calcLux(byte iGain, byte tInt) const
  417. {
  418.     unsigned long chScale;
  419.     switch (tInt) {
  420.         case 0:  chScale = 0x7517; break;
  421.         case 1:  chScale = 0x0fe7; break;
  422.         default: chScale = (1 << CH_SCALE); break;
  423.     }
  424.     if (!iGain)
  425.         chScale <<= 4;
  426.     unsigned long channel0 = (data.w[0] * chScale) >> CH_SCALE;
  427.     unsigned long channel1 = (data.w[1] * chScale) >> CH_SCALE;
  428.  
  429.     unsigned long ratio1 = 0;
  430.     if (channel0 != 0)
  431.         ratio1 = (channel1 << (RATIO_SCALE+1)) / channel0;
  432.     unsigned long ratio = (ratio1 + 1) >> 1;
  433.  
  434.     word b, m;
  435.          if (ratio <= 0x0040) { b = 0x01F2; m = 0x01BE; }
  436.     else if (ratio <= 0x0080) { b = 0x0214; m = 0x02D1; }
  437.     else if (ratio <= 0x00C0) { b = 0x023F; m = 0x037B; }
  438.     else if (ratio <= 0x0100) { b = 0x0270; m = 0x03FE; }
  439.     else if (ratio <= 0x0138) { b = 0x016F; m = 0x01FC; }
  440.     else if (ratio <= 0x019A) { b = 0x00D2; m = 0x00FB; }
  441.     else if (ratio <= 0x029A) { b = 0x0018; m = 0x0012; }
  442.     else                      { b = 0x0000; m = 0x0000; }
  443.  
  444.     unsigned long temp = channel0 * b - channel1 * m;
  445.     temp += 1 << (LUX_SCALE-1);
  446.     return temp >> LUX_SCALE;
  447. }
  448.  
  449. const int* GravityPlug::getAxes() {
  450.     send();
  451.     write(0x02);
  452.     receive();
  453.     for (byte i = 0; i < 5; ++i)
  454.         data.b[i] = read(0);
  455.     data.b[5] = read(1);
  456.     stop();
  457.     data.w[0] = (data.b[0] >> 6) | (data.b[1] << 2);
  458.     data.w[1] = (data.b[2] >> 6) | (data.b[3] << 2);
  459.     data.w[2] = (data.b[4] >> 6) | (data.b[5] << 2);
  460.     for (byte i = 0; i < 3; ++i)
  461.         data.w[i] = (data.w[i] ^ 0x200) - 0x200; // sign extends bit 9
  462.     return data.w;
  463. }
  464.  
  465. byte HeadingPlug::eepromByte(byte reg) const {
  466.     eeprom.send();
  467.     eeprom.write(reg);
  468.     eeprom.receive();
  469.     byte result = eeprom.read(1);
  470.     eeprom.stop();
  471.     return result;
  472. }
  473.  
  474. void HeadingPlug::getConstants() {
  475.     for (byte i = 0; i < 18; ++i)
  476.         ((byte*) &C1)[i < 14 ? i^1 : i] = eepromByte(16 + i);
  477.     // Serial.println(C1);
  478.     // Serial.println(C2);
  479.     // Serial.println(C3);
  480.     // Serial.println(C4);
  481.     // Serial.println(C5);
  482.     // Serial.println(C6);
  483.     // Serial.println(C7);
  484.     // Serial.println(A, DEC);
  485.     // Serial.println(B, DEC);
  486.     // Serial.println(C, DEC);
  487.     // Serial.println(D, DEC);
  488. }
  489.  
  490. word HeadingPlug::adcValue(byte press) const {
  491.     aux.digiWrite(1);
  492.     adc.send();
  493.     adc.write(0xFF);
  494.     adc.write(0xE0 | (press << 4));
  495.     adc.stop();
  496.     delay(40);
  497.     adc.send();
  498.     adc.write(0xFD);
  499.     adc.receive();
  500.     byte msb = adc.read(0);
  501.     int result = (msb << 8) | adc.read(1);
  502.     adc.stop();
  503.     aux.digiWrite(0);
  504.     return result;
  505. }
  506.  
  507. void HeadingPlug::setReset(byte reset) const {
  508.     compass.send();
  509.     compass.write(0x00);
  510.     compass.write(reset ? 0x04 : 0x02);
  511.     compass.stop();
  512.     delay(2);
  513. }
  514.  
  515. void HeadingPlug::begin() {
  516.     // prepare ADC
  517.     aux.mode(OUTPUT);
  518.     aux.digiWrite(0);
  519.    
  520.     // generate 32768 Hz on IRQ pin (OC2B)
  521.     TCCR2A = bit(COM2B0) | bit(WGM21);
  522.     TCCR2B = bit(CS20);
  523.     OCR2A = 243;
  524.     aux.mode3(OUTPUT);
  525.    
  526.     // reset the magnetometer
  527.     delay(10);
  528.     setReset(0);
  529.    
  530.     getConstants();
  531. }
  532.  
  533. void HeadingPlug::pressure(int& temp, int& pres) const {
  534.     word D2 = adcValue(0);
  535.     // Serial.print("D2 = ");
  536.     // Serial.println(D2);
  537.     int corr = (D2 - C5) >> 7;        
  538.     // Serial.print("corr = ");
  539.     // Serial.println(corr);
  540.     int dUT = (D2 - C5) - (corr * (long) corr * (D2 >= C5 ? A : B) >> C);
  541.     // Serial.print("dUT = ");
  542.     // Serial.println(dUT);
  543.     temp = 250 + (dUT * C6 >> 16) - (dUT >> D);
  544.  
  545.     word D1 = adcValue(1);
  546.     // Serial.print("D1 = ");
  547.     // Serial.println(D1);
  548.     word OFF = (C2 + ((C4 - 1024) * dUT >> 14)) << 2;
  549.     // Serial.print("OFF = ");
  550.     // Serial.println(OFF);
  551.     word SENS = C1 + (C3 * dUT >> 10);
  552.     // Serial.print("SENS = ");
  553.     // Serial.println(SENS);
  554.     word X = (SENS * (D1 - 7168L) >> 14) - OFF;
  555.     // Serial.print("X = ");
  556.     // Serial.println(X);
  557.     pres = (X * 10L >> 5) + C7;
  558. }
  559.  
  560. void HeadingPlug::heading(int& xaxis, int& yaxis) const {
  561.     compass.send();
  562.     compass.write(0x00);
  563.     compass.write(0x01);
  564.     compass.stop();
  565.     delay(50);
  566.     compass.send();
  567.     compass.write(0x00);
  568.     compass.receive();
  569.     byte tmp, reg = compass.read(0);
  570.     tmp = compass.read(0);
  571.     xaxis = (tmp << 8) | compass.read(0);
  572.     tmp = compass.read(0);
  573.     yaxis = (tmp << 8) | compass.read(1);
  574.     compass.stop();
  575.     // Serial.println(reg, HEX);
  576. }
  577.  
  578. void InputPlug::select(uint8_t channel) {
  579.     digiWrite(0);
  580.     mode(OUTPUT);
  581.  
  582.     delayMicroseconds(slow ? 400 : 50);
  583.     byte data = 0x10 | (channel & 0x0F);
  584.     byte mask = 1 << (portNum + 3); // digitalWrite is too slow
  585.    
  586.     cli();
  587.     for (byte i = 0; i < 5; ++i) {
  588.         byte us = bitRead(data, 4 - i) ? 9 : 3;
  589.         if (slow)
  590.             us <<= 3;
  591.         PORTD |= mask;
  592.         delayMicroseconds(us);
  593.         PORTD &= ~ mask;
  594.         delayMicroseconds(slow ? 32 : 4);
  595.     }
  596.     sei();
  597. }
  598.  
  599. // EMPTY_INTERRUPT(WDT_vect); // just wakes us up to resume
  600.  
  601. void Sleepy::watchdogInterrupts (char mode) {
  602.     // correct for the fact that WDP3 is *not* in bit position 3!
  603.     if (mode & bit(3))
  604.         mode ^= bit(3) | bit(WDP3);
  605.     // pre-calculate the WDTCSR value, can't do it inside the timed sequence
  606.     byte wdtcsr = mode >= 0 ? bit(WDIE) | mode : 0;
  607.     MCUSR &= ~(1<<WDRF); // only generate interrupts, no reset
  608.     cli();
  609.     WDTCSR |= (1<<WDCE) | (1<<WDE); // timed sequence
  610.     WDTCSR = wdtcsr;
  611.     sei();
  612. }
  613.  
  614. void Sleepy::powerDown () {
  615.     byte prrSave = PRR0, adcsraSave = ADCSRA;
  616.     ADCSRA &= ~ bit(ADEN); // disable the ADC
  617.     PRR0 = 0xFF;
  618.     // see http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
  619.     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  620.     cli();
  621.     sleep_enable();
  622.  #if defined(AVRATmega2560V)
  623.     // sleep_bod_disable(); // can't use this, it's not in my avr-libc version!
  624.     MCUCR = MCUCR | bit(BODSE) | bit(BODS); // timed sequence
  625.     MCUCR = MCUCR & ~ bit(BODSE) | bit(BODS);
  626.  #endif
  627.     sei();
  628.     sleep_cpu();
  629.     sleep_disable();
  630.     // re-enable what we disabled
  631.     PRR0 = prrSave;
  632.     ADCSRA = adcsraSave;
  633. }
  634.  
  635. void Sleepy::loseSomeTime (word msecs) {
  636.     // only slow down for periods longer than the watchdog granularity
  637.     while (msecs >= 16) {
  638.         char wdp = 0; // wdp 0..9 corresponds to roughly 16..8192 ms
  639.         while (msecs >= (32 << wdp) && wdp < 9)
  640.             ++wdp;
  641.         watchdogInterrupts(wdp);
  642.         powerDown();
  643.         watchdogInterrupts(-1); // off
  644.         // adjust the milli ticks, since we will have missed several
  645.         extern volatile unsigned long timer0_millis;
  646.         timer0_millis += 16 << wdp;
  647.         msecs -= 16 << wdp;
  648.     }
  649. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement