masaaki makabe / Mbed 2 deprecated KS7

Dependencies:   BLE_API nRF51822 mbed

Fork of KS7 by masaaki makabe

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers io.cpp Source File

io.cpp

00001 #include "io.h"
00002 #include "mbed.h"
00003 #include "common.h"
00004 
00005 // COL[2:0]: P0_27 P0_26 P0_21
00006 // ROW[7:0]: P0_19 P0_16 P0_15 P0_13 P0_12 P0_11 P0_09 P0_08
00007 // PowA    : P0_00
00008 // Vin     : P0_01
00009 // SWx/y   : P0_02 P0_03
00010 // PWM     : P0_05
00011 //
00012 //  0a 0b 0c  1f 1g 1h  3c 3d 3e  4h 5a 5b
00013 //  0d    0e  2a    2b  3f    3g  5c    5d  6e 6f 6g
00014 //  0f 0g 0h  2c 2d 2e  3h 4a 4b  5e 5f 5g  6h
00015 //  1a    1b  2f    2g  4c    4d  5h    6a  7a    7b
00016 //  1c 1d 1e  2h 3a 3b  4e 4f 4g  6b 6c 6d  7c 7d 7e
00017 // [hgfe:dcba]
00018 //
00019 //  1  2  3   14 15 16  27 28 29  40 41 42
00020 //  4     5   17    18  30    31  43    44  53 54 55
00021 //  6  7  8   19 20 21  32 33 34  45 46 47  56
00022 //  9    10   22    23  35    36  48    49  57    58
00023 // 11 12 13   24 25 26  37 38 39  50 51 52  59 60 61
00024 //  seg[3]     seg[2]    seg[1]    seg[0]
00025 //
00026 // COL 0   1    2     3     4     5     6     7
00027 //     1-8 9-16 17-24 25-31 32-40 41-48 49-56 57-(64)
00028 //
00029 //     seg0
00030 // seg5     seg1
00031 //     seg6
00032 // seg4     seg2
00033 //     seg3
00034 //
00035 // Joystick connection
00036 //
00037 //  o o o
00038 //o
00039 //o   +->x
00040 //o   |
00041 //    y
00042 
00043 
00044 Ticker _tk;
00045 
00046 // multiple condition in #ifdef
00047 // http://qiita.com/D-3/items/b98b63c2629496856654
00048 #if defined(PCB_VER1) || defined(PCB_VER2)
00049 I2C i2c(P0_13, P0_15);
00050 #define I2C_FREQ    100000
00051 #endif
00052 
00053 #ifdef PCB_VER2
00054 #define ADC_ADS1115 // use 16bit ADC
00055 
00056 #ifdef ADC_ADS1115
00057 #define I2C_ADDR 0x90 // for ADS1115
00058 #else
00059 #define I2C_ADDR 0x68 // for MAX11613
00060 #endif
00061 #endif
00062 
00063 #ifdef PCB_VER4
00064 io::io(PinName CLK, PinName DAT) : _hx711(P0_14, DAT, CLK)
00065 #else
00066 io::io()
00067 #endif
00068 {
00069     _col = 0;
00070     for (uint8_t i = 0; i < 4; i++) _seg[i] = 0x00;
00071 // COL[2:0]: P0_27 P0_26 P0_21
00072 // ROW[7:0]: P0_19 P0_16 P0_15 P0_13 P0_12 P0_11 P0_09 P0_08
00073 #if defined(UART_DEBUG)
00074  #if defined(PCB_VER1) || defined(PCB_VER2) // UART: P0_8 & P0_9 (sg0&sg1)
00075     _sg2 = new DigitalOut(P0_11, 0);
00076  #endif
00077  #if defined(PCB_VER3) // UART: P0_8 & P0_11(sg0&sg2)
00078     _sg1 = new DigitalOut(P0_9, 0);
00079  #endif
00080  #if defined(PCB_VER4) // UART: P0_9 & P0_11(sg1&sg2)
00081     _sg0 = new DigitalOut(P0_8, 0);
00082  #endif
00083 #else
00084     // UART cannot use
00085     _sg0 = new DigitalOut(P0_8, 0);
00086     _sg1 = new DigitalOut(P0_9, 0);
00087     _sg2 = new DigitalOut(P0_11, 0);
00088 #endif
00089     _sg3 = new DigitalOut(P0_12, 0);
00090 
00091 #ifdef PCB_VER1
00092     _sg4 = new DigitalOut(P0_13, 0);
00093     _sg5 = new DigitalOut(P0_15, 0);
00094 #else
00095     _sg4 = new DigitalOut(P0_2, 0);
00096     _sg5 = new DigitalOut(P0_3, 0);
00097 #endif
00098     _sg6 = new DigitalOut(P0_16, 0);
00099     _sg7 = new DigitalOut(P0_19, 0);
00100     _sa0 = new DigitalOut(P0_21, 0);
00101 #ifdef PCB_VER1
00102     _sa1 = new DigitalOut(P0_26, 0);
00103     _sa2 = new DigitalOut(P0_27, 0);
00104     _jx = new AnalogIn(P0_2);
00105     _jy = new AnalogIn(P0_3);
00106     _weight = new AnalogIn(P0_1);
00107 #endif
00108 #if defined(PCB_VER2) || defined(PCB_VER3) || defined(PCB_VER4)
00109     _sa1 = new DigitalOut(P0_24, 0);
00110     _sa2 = new DigitalOut(P0_25, 0);
00111 #endif
00112     _pow = new DigitalOut(P0_0, 1); // initial: analog power off
00113     _pwm = new PwmOut(P0_5);
00114 //    _pwm = new PwmOut(P0_15); // for BLEnano debug
00115     _adc0 = 0;
00116     _pwm->period_us(100);
00117     _pwm->write(0.0);
00118 #if defined(PCB_VER1) || defined(PCB_VER2)
00119     i2c.frequency(I2C_FREQ);
00120 #endif
00121 
00122 #ifdef PCB_VER3
00123     _sw = new DigitalIn(P0_4, PullDown);
00124     _adc_ck = new DigitalOut(P0_15, 0);
00125     _adc_di = new DigitalIn(P0_13);
00126     _adc_ck->write(0);
00127     for (uint8_t i = 0; i < 24; i++) {
00128         _adc_ck->write(1);
00129         wait_us(10);
00130         _adc_ck->write(0);
00131         wait_us(10);
00132     }
00133 #endif
00134 #ifdef PCB_VER4
00135     _hx711.format(8, 1); // 8bit mode1
00136     _hx711.frequency(500000); // 500kHz
00137     _sw = new DigitalIn(P0_4, PullDown);
00138 //    _sw = new DigitalIn(P0_13, PullDown); // for BLEnano debug
00139 //    _adc_ck = new DigitalOut(P0_15, 0); // for software SPI
00140 //    _adc_di = new DigitalIn(P0_13); // for software SPI
00141     _PselSCK  = NRF_SPI1->PSELSCK; // for hardware SPI
00142     _PselMISO = NRF_SPI1->PSELMISO; // for hardware SPI
00143     _reg_ps = new DigitalOut(P0_1, 1); // 1=normal, 0=power_save
00144 //    _adc_rate = new DigitalOut(P0_6, 0); // 0=10Hz, 1=80Hz (HX711's RATE pin)
00145     _adc_rate = new DigitalOut(P0_6, 1); // 0=10Hz, 1=80Hz (HX711's RATE pin)
00146 #endif
00147     _fDisplaying = 0;
00148 }
00149 
00150 io::~io()
00151 {
00152 }
00153 
00154 void io::_set_col()
00155 {
00156     if ((_col & 0x01) == 0) _sa0->write(0);
00157     else _sa0->write(1);
00158     if ((_col & 0x02) == 0) _sa1->write(0);
00159     else _sa1->write(1);
00160     if ((_col & 0x04) == 0) _sa2->write(0);
00161     else _sa2->write(1);
00162 }
00163 
00164 void io::_set_row(uint8_t d)
00165 {
00166 #if defined(UART_DEBUG)
00167  #if defined(PCB_VER1) || defined(PCB_VER2) // UART: P0_8 & P0_9 (sg0&sg1)
00168     if ((d & 0x04) == 0) _sg2->write(0); else _sg2->write(1);
00169  #endif
00170  #if defined(PCB_VER3) // UART: P0_8 & P0_11 (sg0&sg2)
00171     if ((d & 0x02) == 0) _sg1->write(0); else _sg1->write(1);
00172  #endif
00173  #if defined(PCB_VER4) // UART: P0_9 & P0_11(sg1&sg2)
00174     if ((d & 0x01) == 0) _sg0->write(0); else _sg0->write(1);
00175  #endif
00176 #else
00177     if ((d & 0x01) == 0) _sg0->write(0); else _sg0->write(1);
00178     if ((d & 0x02) == 0) _sg1->write(0); else _sg1->write(1);
00179     if ((d & 0x04) == 0) _sg2->write(0); else _sg2->write(1);
00180 #endif
00181     if ((d & 0x08) == 0) _sg3->write(0);
00182     else _sg3->write(1);
00183     if ((d & 0x10) == 0) _sg4->write(0);
00184     else _sg4->write(1);
00185     if ((d & 0x20) == 0) _sg5->write(0);
00186     else _sg5->write(1);
00187     if ((d & 0x40) == 0) _sg6->write(0);
00188     else _sg6->write(1);
00189     if ((d & 0x80) == 0) _sg7->write(0);
00190     else _sg7->write(1);
00191     
00192 }
00193 
00194 uint8_t io::_set_segment(uint8_t d)
00195 {
00196 //     seg0
00197 // seg5     seg1
00198 //     seg6
00199 // seg4     seg2
00200 //     seg3
00201     uint8_t v;
00202     switch(d) {
00203         case 0:
00204             v = 0x3f;
00205             break;
00206         case 1:
00207             v = 0x06;
00208             break;
00209         case 2:
00210             v = 0x5b;
00211             break;
00212         case 3:
00213             v = 0x4f;
00214             break;
00215         case 4:
00216             v = 0x66;
00217             break;
00218         case 5:
00219             v = 0x6d;
00220             break;
00221         case 6:
00222             v = 0x7d;
00223             break;
00224         case 7:
00225             v = 0x27;
00226             break;
00227         case 8:
00228             v = 0x7f;
00229             break;
00230         case 9:
00231             v = 0x6f;
00232             break;
00233         default :
00234             v = 0x00;
00235             break;
00236     }
00237     return(v);
00238 }
00239 
00240 void io::_timer_ticker()
00241 {
00242     _set_row(0);
00243     _set_col();
00244     _set_row(_row_out[_col]);
00245     _col++;
00246     if (_col == 8) {
00247         _col = 0;
00248         if (display_value < 0) _display_value = 0;
00249         else if (display_value > 9999) _display_value = 9999;
00250         else _display_value = display_value;
00251 
00252 #ifdef DISPLAY_ZERO_SUPPRESS
00253         if (_display_value < 1000) _seg[3] = 0;
00254         else
00255 #endif
00256             _seg[3] = _set_segment(_display_value / 1000);
00257 #ifdef DISPLAY_ZERO_SUPPRESS
00258         if (_display_value < 100) _seg[2] = 0;
00259         else
00260 #endif
00261             _seg[2] = _set_segment((_display_value / 100) % 10);
00262 #ifdef DISPLAY_ZERO_SUPPRESS
00263         if (_display_value < 10) _seg[1] = 0;
00264         else
00265 #endif
00266             _seg[1] = _set_segment((_display_value / 10) % 10);
00267         _seg[0] = _set_segment(_display_value % 10);
00268         for (uint8_t i = 0; i < 8; i++) _row_out[i] = 0;
00269 
00270         if ((_seg[3] & 0x40) != 0) _row_out[0] |= 0xe0; // seg6/0f-0g-0h
00271         if ((_seg[3] & 0x20) != 0) _row_out[0] |= 0x29; // seg5/0a-0d-0f
00272         if ((_seg[3] & 0x10) != 0) {
00273             _row_out[0] |= 0x20;    // seg4/0f-1a-1c
00274             _row_out[1] |= 0x05;
00275         }
00276         if ((_seg[3] & 0x08) != 0) _row_out[1] |= 0x1c; // seg3/1c-1d-1e
00277         if ((_seg[3] & 0x04) != 0) {
00278             _row_out[0] |= 0x80;    // seg2/0h-1b-1e
00279             _row_out[1] |= 0x12;
00280         }
00281         if ((_seg[3] & 0x02) != 0) _row_out[0] |= 0x94; // seg1/0c-0e-0h
00282         if ((_seg[3] & 0x01) != 0) _row_out[0] |= 0x07; // seg0/0a-0b-0c
00283 
00284         if ((_seg[2] & 0x40) != 0) _row_out[2] |= 0x1c; // seg6/2c-2d-2e
00285         if ((_seg[2] & 0x20) != 0) {
00286             _row_out[2] |= 0x05;    // seg5/1f-2a-2c
00287             _row_out[1] |= 0x20;
00288         }
00289         if ((_seg[2] & 0x10) != 0) _row_out[2] |= 0xa4; // seg4/2c-2f-2h
00290         if ((_seg[2] & 0x08) != 0) {
00291             _row_out[3] |= 0x03;    // seg3/2h-3a-3b
00292             _row_out[2] |= 0x80;
00293         }
00294         if ((_seg[2] & 0x04) != 0) {
00295             _row_out[3] |= 0x02;    // seg2/2e-2g-3b
00296             _row_out[2] |= 0x50;
00297         }
00298         if ((_seg[2] & 0x02) != 0) {
00299             _row_out[2] |= 0x12;    // seg1/1h-2b-2e
00300             _row_out[1] |= 0x80;
00301         }
00302         if ((_seg[2] & 0x01) != 0) _row_out[1] |= 0xe0; // seg0/1f-1g-1h
00303 
00304         if ((_seg[1] & 0x40) != 0) {
00305             _row_out[4] |= 0x03;    // seg6/3h-4a-4b
00306             _row_out[3] |= 0x80;
00307         }
00308         if ((_seg[1] & 0x20) != 0) _row_out[3] |= 0xa4; // seg5/3c-3f-3h
00309         if ((_seg[1] & 0x10) != 0) {
00310             _row_out[4] |= 0x14;    // seg4/3h-4c-4e
00311             _row_out[3] |= 0x80;
00312         }
00313         if ((_seg[1] & 0x08) != 0) _row_out[4] |= 0x70; // seg3/4e-4f-4g
00314         if ((_seg[1] & 0x04) != 0) _row_out[4] |= 0x4a; // seg2/4b-4d-4g
00315         if ((_seg[1] & 0x02) != 0) {
00316             _row_out[4] |= 0x02;    // seg1/3e-3g-4b
00317             _row_out[3] |= 0x50;
00318         }
00319         if ((_seg[1] & 0x01) != 0) _row_out[3] |= 0x1c; // seg0/3c-3d-3e
00320 
00321         if ((_seg[0] & 0x40) != 0) _row_out[5] |= 0x70; // seg6/5e-5f-5g
00322         if ((_seg[0] & 0x20) != 0) {
00323             _row_out[5] |= 0x14;    // seg5/4h-5c-5e
00324             _row_out[4] |= 0x80;
00325         }
00326         if ((_seg[0] & 0x10) != 0) {
00327             _row_out[6] |= 0x02;    // seg4/5e-5h-6b
00328             _row_out[5] |= 0x90;
00329         }
00330         if ((_seg[0] & 0x08) != 0) _row_out[6] |= 0x0e; // seg3/6b-6c-6d
00331         if ((_seg[0] & 0x04) != 0) {
00332             _row_out[6] |= 0x09;    // seg2/5g-6a-6d
00333             _row_out[5] |= 0x40;
00334         }
00335         if ((_seg[0] & 0x02) != 0) _row_out[5] |= 0x4a; // seg1/5b-5d-5g
00336         if ((_seg[0] & 0x01) != 0) {
00337             _row_out[5] |= 0x03;    // seg0/4h-5a-5b
00338             _row_out[4] |= 0x80;
00339         }
00340 //        _row_out[6] |= 0xf0; _row_out[7] |= 0x1f; // 6e-6f-6g-6h 7a-7b-7c-7d-7e
00341 
00342     // display unit ('G')
00343 /*S-------------------------------------------------------------------*/
00344     display_unit();
00345 //#ifdef PCB_VER1
00346 //        _row_out[6] |= 0xf0;
00347 //        _row_out[7] |= 0x1f; // 6e-6f-6g-6h 7a-7b-7c-7d-7e
00348 //#else
00349 //        _row_out[6] |= 0xf0;
00350 //        _row_out[7] |= 0xf4; // 6e-6f-6g-6h 7c-7e-7f-7g-7h
00351 //#endif
00352 #if 0 /*debug*/
00353         /*全灯*/
00354         _row_out[0] = 0xff;
00355         _row_out[1] = 0xff;
00356         _row_out[2] = 0xff;
00357         _row_out[3] = 0xff;
00358         _row_out[4] = 0xff;
00359         _row_out[5] = 0xff;
00360         _row_out[6] = 0xff;
00361         _row_out[7] = 0xff;
00362 #endif
00363 /*E-------------------------------------------------------------------*/
00364     }
00365 }
00366 
00367 void io::display(float f)
00368 {
00369     _pwm->write(f);
00370     if (f > 0.0 && _fDisplaying == 0) {
00371         // ref: https://developer.mbed.org/cookbook/Compiler-Error-304
00372         _tk.attach(this, &io::_timer_ticker, 0.002);
00373         _fDisplaying = 1;
00374     } else if (f == 0.0 && _fDisplaying == 1) {
00375         _tk.detach();
00376         _fDisplaying = 0;
00377     }
00378 }
00379 
00380 float io::get_weight()
00381 {
00382     float w;
00383     w = (float)get_weight_raw() / WEIGHT_COEFFICIENT; // ToDo: coefficient calibration
00384     return(w);
00385 }
00386 
00387 #ifdef PCB_VER4
00388 uint32_t io::get_weight_raw()
00389 #else
00390 uint16_t io::get_weight_raw()
00391 #endif
00392 {
00393 #ifdef PCB_VER4
00394     long w;
00395 #else
00396     int w;
00397 #endif
00398     w = _get_adc_raw(0) - _adc0;
00399     if (w < 0) w = 0;
00400     return(w);
00401 }
00402 
00403 #ifdef PCB_VER1
00404 float io::_get_x()
00405 {
00406     float v;
00407     v = _get_adc(1);
00408     return(v);
00409 }
00410 #endif
00411 
00412 #ifdef PCB_VER1
00413 float io::_get_y()
00414 {
00415     float v;
00416     v = _get_adc(2);
00417     return(v);
00418 }
00419 #endif
00420 
00421 uint8_t io::get_switch()
00422 {
00423     uint8_t f;
00424 #if defined(PCB_VER1) || defined(PCB_VER2)
00425 #ifdef USE_JOYSTICK
00426     if (_get_x() > 0.8 || _get_y() > 0.8) f = 1;
00427     else f = 0;
00428 #else
00429     if(_get_adc(1) > 0.5) f = 1;
00430     else f = 0;
00431 #endif
00432 #else
00433     if (_sw->read() == 1) f = 1;
00434     else f = 0;
00435 #endif
00436     return(f);
00437 }
00438 
00439 void io::analog_pow(uint8_t f)
00440 {
00441     if (f == 1){
00442         _pow->write(0);
00443 #ifdef PCB_VER4
00444         _set_adc_ck(0);
00445 #endif
00446     }
00447     else{
00448          _pow->write(1);
00449 #ifdef PCB_VER4
00450         _enableSPI(0);
00451         _set_adc_ck(1);
00452         wait(0.01); // keep HX711's SCK=1 to enter HX711 into sleep mode
00453 #endif
00454     }
00455 }
00456 
00457 void io::_set_adc_ck(uint8_t f)
00458 {
00459  //   if (f == 0) NRF_GPIO->OUTCLR |= (1 << _PselSCK);
00460  //   else NRF_GPIO->OUTSET |= (1 << _PselSCK);
00461    if (f == 0) NRF_GPIO->OUTCLR = (1 << _PselSCK);
00462    else NRF_GPIO->OUTSET = (1 << _PselSCK);
00463 }
00464 
00465 void io::_enableSPI(uint8_t f)
00466 {
00467     if (f == 0){
00468         NRF_SPI1->ENABLE = 0;
00469         NRF_SPI1->PSELSCK  = 0xffffffff;
00470         NRF_SPI1->PSELMISO = 0xffffffff;
00471     }
00472     else{
00473         NRF_SPI1->ENABLE = 0;
00474         NRF_SPI1->PSELSCK  = _PselSCK;
00475         NRF_SPI1->PSELMISO = _PselMISO;
00476         NRF_SPI1->ENABLE = 1;
00477     }
00478 }
00479 
00480 uint8_t io::_spi_transfer()
00481 {
00482     return(_hx711.write(0x00));
00483 }
00484 
00485 void io::calibrate_weight()
00486 {
00487     // (2016/3/28: take average in weight calibration)
00488     int Navg = 10;
00489     uint32_t _adc0_s = 0;
00490     for (int i = 0; i < Navg; i++){
00491         _adc0_s += _get_adc_raw(0);
00492     }
00493     _adc0 = (uint32_t)((float)_adc0_s / (float)Navg);
00494 }
00495 
00496 float io::_get_adc(uint8_t ch)
00497 {
00498 #ifdef PCB_VER4
00499     return(_get_adc_raw(ch) / (float)0xffffff);
00500 #else
00501     return(_get_adc_raw(ch) / (float)0xffff);
00502 #endif
00503 }
00504 
00505 #ifdef PCB_VER4
00506 uint32_t io::_get_adc_raw(uint8_t ch)
00507 #else
00508 uint16_t io::_get_adc_raw(uint8_t ch)
00509 #endif
00510 {
00511 #ifdef PCB_VER1
00512     if (ch == 0) return(_weight->read());
00513     else if (ch == 1) return(_jx->read());
00514     else return(_jy->read());
00515 #endif
00516 
00517 #ifdef PCB_VER2
00518     uint16_t adc = 0;
00519     uint8_t dh, dl;
00520 #ifdef ADC_ADS1115
00521     // for ADS1115
00522     // Input Voltage Range
00523     // VIN3 = VDD/2 = 1.65
00524     // VIN0 = 1.8Vpp --> 0.75V - 2.55V
00525     // VIN0 - VIN3 = -0.9 - +0.9V (+-1.024V)
00526     _adc_dat[0] = 0x01; // config reg.
00527     if (ch == 0) _adc_dat[1] = 0x17; // single conv. & FS=+-1.0.24V, AIN0/1/2-AIN3
00528     else if (ch == 1) _adc_dat[1] = 0x27;
00529     else _adc_dat[1] = 0x37;
00530     _adc_dat[1] |= 0x80;
00531 
00532     _adc_dat[2] = 0x83; // 128SPS & disable comp.
00533 
00534     i2c.write(I2C_ADDR, _adc_dat, 3);
00535     uint8_t f = 0;
00536     uint16_t count = 10;
00537     while (f == 0) {
00538         _adc_dat[0] = 0x01;
00539         i2c.write(I2C_ADDR, _adc_dat, 1);
00540         i2c.read(I2C_ADDR, _adc_dat, 2);
00541         if ((_adc_dat[0] & 0x80) != 0) f = 1;
00542 
00543         if(--count == 0) {
00544             break;
00545         }
00546     }
00547     _adc_dat[0] = 0x00;
00548     i2c.write(I2C_ADDR, _adc_dat, 1);
00549     i2c.read(I2C_ADDR, _adc_dat, 2);
00550     dh = _adc_dat[0];
00551     dl = _adc_dat[1];
00552     adc = dh << 8 | dl;
00553 #else
00554     // for MAX11613
00555     _adc_dat[0] = 0xda; // setup / int.reference, ext.clock unipolar
00556     _adc_dat[1] = 0x61 | (ch << 1); // config / single-ended
00557     i2cwrite(I2C_ADDR, _adc_dat, 2);
00558 
00559     i2cread(I2C_ADDR, _adc_dat, 2);
00560     dh = _adc_dat[0] & 0x0f;
00561     dl = _adc_dat[1];
00562     adc = (dh << 8 | dl) << 4; // align to 16 bit
00563 #endif
00564     // convert 2's complementary -> straight binary
00565     // 0x8000 -> 0x0000
00566     // 0x0000 -> 0x8000
00567     // 0x7fff -> 0xffff
00568     adc = (adc + 0x8000) & 0xffff;
00569     return(adc);
00570 #endif
00571 
00572 #ifdef PCB_VER3
00573     uint16_t adc = 0;
00574     // MAX11205, parameter ch is ignored
00575     _adc_ck->write(0);
00576     while(_adc_di->read() == 1); // wait until conversion is finished
00577     // ToDo: data ready timeout
00578     for (uint8_t i = 0; i < 16; i++) {
00579         _adc_ck->write(1);
00580         wait_us(10);
00581         adc = adc << 1;
00582         if (_adc_di->read() == 1) adc |= 0x01;
00583         else adc &= ~0x01;
00584         _adc_ck->write(0);
00585         wait_us(10);
00586     }
00587     for (uint8_t i = 0; i < 10; i++) { // additional clock for self calibration
00588         _adc_ck->write(1);
00589         wait_us(10);
00590         _adc_ck->write(0);
00591         wait_us(10);
00592     }
00593     // 0x8000 -> 0x0000
00594     // 0xffff -> 0x7fff
00595     // 0x0000 -> 0x8000
00596     // 0x7fff -> 0xffff
00597     adc = (adc + 0x8000) & 0xffff;
00598     return(adc);
00599 #endif
00600 
00601 #ifdef PCB_VER4
00602     // using HX711
00603     uint32_t adc = 0;
00604     // hardware SPI
00605     uint8_t d2, d1, d0;
00606     _set_adc_ck(0);
00607     // note: comment out the while() below for debugging without ADC, HX711
00608     while((NRF_GPIO->IN & (1 << _PselMISO)));
00609     _enableSPI(1);
00610     d2 = _spi_transfer();
00611     d1 = _spi_transfer();
00612     d0 = _spi_transfer();
00613     _enableSPI(0);
00614     _set_adc_ck(1); wait_us(1);
00615     _set_adc_ck(0);
00616     adc = (d2 << 16) | (d1 << 8) | d0;
00617 /*
00618     // software SPI
00619     while(_adc_di->read() == 1); // wait until conversion is finished
00620 //    _tk.detach(); // disable timer to keep _adc_ck's H timeb
00621     for (uint8_t i = 0; i < 24; i++) {
00622         _adc_ck->write(1);
00623         wait_us(10);
00624         _adc_ck->write(0);
00625         wait_us(10);
00626         adc = adc << 1;
00627         if (_adc_di->read() == 1) adc |= 0x01;
00628         else adc &= ~0x01;
00629     }
00630     for (uint8_t i = 0; i < 1; i++) {
00631         _adc_ck->write(1);
00632         wait_us(10);
00633         _adc_ck->write(0);
00634         wait_us(10);
00635     }
00636 */
00637 //    _tk.attach(this, &io::_timer_ticker, 0.002);
00638     adc = (adc + 0x800000) & 0xffffff;
00639     return(adc);
00640 #endif
00641 }
00642 
00643 #ifdef PCB_VER4
00644 // f=1 for power-save mode during sleep
00645 void io::power_save_mode(uint8_t f)
00646 {
00647     if (f == 1) _reg_ps->write(0); // power save mode for sleep
00648     else _reg_ps->write(1); // non-power save (high power) mode for normal operation
00649 }
00650 #endif