test publish
Dependencies: BLE_API nRF51822 mbed
Fork of KS7 by
io.cpp
- Committer:
- masaaki_makabe
- Date:
- 2016-07-28
- Branch:
- KS3
- Revision:
- 31:b5e19d153db4
- Parent:
- 30:f67850cc3cfe
File content as of revision 31:b5e19d153db4:
#include "io.h" #include "mbed.h" #include "common.h" // COL[2:0]: P0_27 P0_26 P0_21 // ROW[7:0]: P0_19 P0_16 P0_15 P0_13 P0_12 P0_11 P0_09 P0_08 // PowA : P0_00 // Vin : P0_01 // SWx/y : P0_02 P0_03 // PWM : P0_05 // // 0a 0b 0c 1f 1g 1h 3c 3d 3e 4h 5a 5b // 0d 0e 2a 2b 3f 3g 5c 5d 6e 6f 6g // 0f 0g 0h 2c 2d 2e 3h 4a 4b 5e 5f 5g 6h // 1a 1b 2f 2g 4c 4d 5h 6a 7a 7b // 1c 1d 1e 2h 3a 3b 4e 4f 4g 6b 6c 6d 7c 7d 7e // [hgfe:dcba] // // 1 2 3 14 15 16 27 28 29 40 41 42 // 4 5 17 18 30 31 43 44 53 54 55 // 6 7 8 19 20 21 32 33 34 45 46 47 56 // 9 10 22 23 35 36 48 49 57 58 // 11 12 13 24 25 26 37 38 39 50 51 52 59 60 61 // seg[3] seg[2] seg[1] seg[0] // // COL 0 1 2 3 4 5 6 7 // 1-8 9-16 17-24 25-31 32-40 41-48 49-56 57-(64) // // seg0 // seg5 seg1 // seg6 // seg4 seg2 // seg3 // // Joystick connection // // o o o //o //o +->x //o | // y Ticker _tk; // multiple condition in #ifdef // http://qiita.com/D-3/items/b98b63c2629496856654 #if defined(PCB_VER1) || defined(PCB_VER2) I2C i2c(P0_13, P0_15); #define I2C_FREQ 100000 #endif #ifdef PCB_VER2 #define ADC_ADS1115 // use 16bit ADC #ifdef ADC_ADS1115 #define I2C_ADDR 0x90 // for ADS1115 #else #define I2C_ADDR 0x68 // for MAX11613 #endif #endif #ifdef PCB_VER4 io::io(PinName CLK, PinName DAT) : _hx711(P0_14, DAT, CLK) #else io::io() #endif { _col = 0; for (uint8_t i = 0; i < 4; i++) _seg[i] = 0x00; // COL[2:0]: P0_27 P0_26 P0_21 // ROW[7:0]: P0_19 P0_16 P0_15 P0_13 P0_12 P0_11 P0_09 P0_08 #if defined(UART_DEBUG) #if defined(PCB_VER1) || defined(PCB_VER2) // UART: P0_8 & P0_9 (sg0&sg1) _sg2 = new DigitalOut(P0_11, 0); #endif #if defined(PCB_VER3) // UART: P0_8 & P0_11(sg0&sg2) _sg1 = new DigitalOut(P0_9, 0); #endif #if defined(PCB_VER4) // UART: P0_9 & P0_11(sg1&sg2) _sg0 = new DigitalOut(P0_8, 0); #endif #else // UART cannot use _sg0 = new DigitalOut(P0_8, 0); _sg1 = new DigitalOut(P0_9, 0); _sg2 = new DigitalOut(P0_11, 0); #endif _sg3 = new DigitalOut(P0_12, 0); #ifdef PCB_VER1 _sg4 = new DigitalOut(P0_13, 0); _sg5 = new DigitalOut(P0_15, 0); #else _sg4 = new DigitalOut(P0_2, 0); _sg5 = new DigitalOut(P0_3, 0); #endif _sg6 = new DigitalOut(P0_16, 0); _sg7 = new DigitalOut(P0_19, 0); _sa0 = new DigitalOut(P0_21, 0); #ifdef PCB_VER1 _sa1 = new DigitalOut(P0_26, 0); _sa2 = new DigitalOut(P0_27, 0); _jx = new AnalogIn(P0_2); _jy = new AnalogIn(P0_3); _weight = new AnalogIn(P0_1); #endif #if defined(PCB_VER2) || defined(PCB_VER3) || defined(PCB_VER4) _sa1 = new DigitalOut(P0_24, 0); _sa2 = new DigitalOut(P0_25, 0); #endif _pow = new DigitalOut(P0_0, 1); // initial: analog power off _pwm = new PwmOut(P0_5); // _pwm = new PwmOut(P0_15); // for BLEnano debug _adc0 = 0; _pwm->period_us(100); _pwm->write(0.0); #if defined(PCB_VER1) || defined(PCB_VER2) i2c.frequency(I2C_FREQ); #endif #ifdef PCB_VER3 _sw = new DigitalIn(P0_4, PullDown); _adc_ck = new DigitalOut(P0_15, 0); _adc_di = new DigitalIn(P0_13); _adc_ck->write(0); for (uint8_t i = 0; i < 24; i++) { _adc_ck->write(1); wait_us(10); _adc_ck->write(0); wait_us(10); } #endif #ifdef PCB_VER4 _hx711.format(8, 1); // 8bit mode1 _hx711.frequency(500000); // 500kHz _sw = new DigitalIn(P0_4, PullDown); // _sw = new DigitalIn(P0_13, PullDown); // for BLEnano debug // _adc_ck = new DigitalOut(P0_15, 0); // for software SPI // _adc_di = new DigitalIn(P0_13); // for software SPI _PselSCK = NRF_SPI1->PSELSCK; // for hardware SPI _PselMISO = NRF_SPI1->PSELMISO; // for hardware SPI _reg_ps = new DigitalOut(P0_1, 1); // 1=normal, 0=power_save // _adc_rate = new DigitalOut(P0_6, 0); // 0=10Hz, 1=80Hz (HX711's RATE pin) _adc_rate = new DigitalOut(P0_6, 1); // 0=10Hz, 1=80Hz (HX711's RATE pin) #endif _fDisplaying = 0; } io::~io() { } void io::_set_col() { if ((_col & 0x01) == 0) _sa0->write(0); else _sa0->write(1); if ((_col & 0x02) == 0) _sa1->write(0); else _sa1->write(1); if ((_col & 0x04) == 0) _sa2->write(0); else _sa2->write(1); } void io::_set_row(uint8_t d) { #if defined(UART_DEBUG) #if defined(PCB_VER1) || defined(PCB_VER2) // UART: P0_8 & P0_9 (sg0&sg1) if ((d & 0x04) == 0) _sg2->write(0); else _sg2->write(1); #endif #if defined(PCB_VER3) // UART: P0_8 & P0_11 (sg0&sg2) if ((d & 0x02) == 0) _sg1->write(0); else _sg1->write(1); #endif #if defined(PCB_VER4) // UART: P0_9 & P0_11(sg1&sg2) if ((d & 0x01) == 0) _sg0->write(0); else _sg0->write(1); #endif #else if ((d & 0x01) == 0) _sg0->write(0); else _sg0->write(1); if ((d & 0x02) == 0) _sg1->write(0); else _sg1->write(1); if ((d & 0x04) == 0) _sg2->write(0); else _sg2->write(1); #endif if ((d & 0x08) == 0) _sg3->write(0); else _sg3->write(1); if ((d & 0x10) == 0) _sg4->write(0); else _sg4->write(1); if ((d & 0x20) == 0) _sg5->write(0); else _sg5->write(1); if ((d & 0x40) == 0) _sg6->write(0); else _sg6->write(1); if ((d & 0x80) == 0) _sg7->write(0); else _sg7->write(1); } uint8_t io::_set_segment(uint8_t d) { // seg0 // seg5 seg1 // seg6 // seg4 seg2 // seg3 uint8_t v; switch(d) { case 0: v = 0x3f; break; case 1: v = 0x06; break; case 2: v = 0x5b; break; case 3: v = 0x4f; break; case 4: v = 0x66; break; case 5: v = 0x6d; break; case 6: v = 0x7d; break; case 7: v = 0x27; break; case 8: v = 0x7f; break; case 9: v = 0x6f; break; default : v = 0x00; break; } return(v); } void io::_timer_ticker() { _set_row(0); _set_col(); _set_row(_row_out[_col]); _col++; if (_col == 8) { _col = 0; if (display_value < 0) _display_value = 0; else if (display_value > 9999) _display_value = 9999; else _display_value = display_value; #ifdef DISPLAY_ZERO_SUPPRESS if (_display_value < 1000) _seg[3] = 0; else #endif _seg[3] = _set_segment(_display_value / 1000); #ifdef DISPLAY_ZERO_SUPPRESS if (_display_value < 100) _seg[2] = 0; else #endif _seg[2] = _set_segment((_display_value / 100) % 10); #ifdef DISPLAY_ZERO_SUPPRESS if (_display_value < 10) _seg[1] = 0; else #endif _seg[1] = _set_segment((_display_value / 10) % 10); _seg[0] = _set_segment(_display_value % 10); for (uint8_t i = 0; i < 8; i++) _row_out[i] = 0; if ((_seg[3] & 0x40) != 0) _row_out[0] |= 0xe0; // seg6/0f-0g-0h if ((_seg[3] & 0x20) != 0) _row_out[0] |= 0x29; // seg5/0a-0d-0f if ((_seg[3] & 0x10) != 0) { _row_out[0] |= 0x20; // seg4/0f-1a-1c _row_out[1] |= 0x05; } if ((_seg[3] & 0x08) != 0) _row_out[1] |= 0x1c; // seg3/1c-1d-1e if ((_seg[3] & 0x04) != 0) { _row_out[0] |= 0x80; // seg2/0h-1b-1e _row_out[1] |= 0x12; } if ((_seg[3] & 0x02) != 0) _row_out[0] |= 0x94; // seg1/0c-0e-0h if ((_seg[3] & 0x01) != 0) _row_out[0] |= 0x07; // seg0/0a-0b-0c if ((_seg[2] & 0x40) != 0) _row_out[2] |= 0x1c; // seg6/2c-2d-2e if ((_seg[2] & 0x20) != 0) { _row_out[2] |= 0x05; // seg5/1f-2a-2c _row_out[1] |= 0x20; } if ((_seg[2] & 0x10) != 0) _row_out[2] |= 0xa4; // seg4/2c-2f-2h if ((_seg[2] & 0x08) != 0) { _row_out[3] |= 0x03; // seg3/2h-3a-3b _row_out[2] |= 0x80; } if ((_seg[2] & 0x04) != 0) { _row_out[3] |= 0x02; // seg2/2e-2g-3b _row_out[2] |= 0x50; } if ((_seg[2] & 0x02) != 0) { _row_out[2] |= 0x12; // seg1/1h-2b-2e _row_out[1] |= 0x80; } if ((_seg[2] & 0x01) != 0) _row_out[1] |= 0xe0; // seg0/1f-1g-1h if ((_seg[1] & 0x40) != 0) { _row_out[4] |= 0x03; // seg6/3h-4a-4b _row_out[3] |= 0x80; } if ((_seg[1] & 0x20) != 0) _row_out[3] |= 0xa4; // seg5/3c-3f-3h if ((_seg[1] & 0x10) != 0) { _row_out[4] |= 0x14; // seg4/3h-4c-4e _row_out[3] |= 0x80; } if ((_seg[1] & 0x08) != 0) _row_out[4] |= 0x70; // seg3/4e-4f-4g if ((_seg[1] & 0x04) != 0) _row_out[4] |= 0x4a; // seg2/4b-4d-4g if ((_seg[1] & 0x02) != 0) { _row_out[4] |= 0x02; // seg1/3e-3g-4b _row_out[3] |= 0x50; } if ((_seg[1] & 0x01) != 0) _row_out[3] |= 0x1c; // seg0/3c-3d-3e if ((_seg[0] & 0x40) != 0) _row_out[5] |= 0x70; // seg6/5e-5f-5g if ((_seg[0] & 0x20) != 0) { _row_out[5] |= 0x14; // seg5/4h-5c-5e _row_out[4] |= 0x80; } if ((_seg[0] & 0x10) != 0) { _row_out[6] |= 0x02; // seg4/5e-5h-6b _row_out[5] |= 0x90; } if ((_seg[0] & 0x08) != 0) _row_out[6] |= 0x0e; // seg3/6b-6c-6d if ((_seg[0] & 0x04) != 0) { _row_out[6] |= 0x09; // seg2/5g-6a-6d _row_out[5] |= 0x40; } if ((_seg[0] & 0x02) != 0) _row_out[5] |= 0x4a; // seg1/5b-5d-5g if ((_seg[0] & 0x01) != 0) { _row_out[5] |= 0x03; // seg0/4h-5a-5b _row_out[4] |= 0x80; } // _row_out[6] |= 0xf0; _row_out[7] |= 0x1f; // 6e-6f-6g-6h 7a-7b-7c-7d-7e // display unit ('G') /*S-------------------------------------------------------------------*/ display_unit(); //#ifdef PCB_VER1 // _row_out[6] |= 0xf0; // _row_out[7] |= 0x1f; // 6e-6f-6g-6h 7a-7b-7c-7d-7e //#else // _row_out[6] |= 0xf0; // _row_out[7] |= 0xf4; // 6e-6f-6g-6h 7c-7e-7f-7g-7h //#endif #if 0 /*debug*/ /*全灯*/ _row_out[0] = 0xff; _row_out[1] = 0xff; _row_out[2] = 0xff; _row_out[3] = 0xff; _row_out[4] = 0xff; _row_out[5] = 0xff; _row_out[6] = 0xff; _row_out[7] = 0xff; #endif /*E-------------------------------------------------------------------*/ } } void io::display(float f) { _pwm->write(f); if (f > 0.0 && _fDisplaying == 0) { // ref: https://developer.mbed.org/cookbook/Compiler-Error-304 _tk.attach(this, &io::_timer_ticker, 0.002); _fDisplaying = 1; } else if (f == 0.0 && _fDisplaying == 1) { _tk.detach(); _fDisplaying = 0; } } float io::get_weight() { float w; w = (float)get_weight_raw() / WEIGHT_COEFFICIENT; // ToDo: coefficient calibration return(w); } #ifdef PCB_VER4 uint32_t io::get_weight_raw() #else uint16_t io::get_weight_raw() #endif { #ifdef PCB_VER4 long w; #else int w; #endif w = _get_adc_raw(0) - _adc0; if (w < 0) w = 0; return(w); } #ifdef PCB_VER1 float io::_get_x() { float v; v = _get_adc(1); return(v); } #endif #ifdef PCB_VER1 float io::_get_y() { float v; v = _get_adc(2); return(v); } #endif uint8_t io::get_switch() { uint8_t f; #if defined(PCB_VER1) || defined(PCB_VER2) #ifdef USE_JOYSTICK if (_get_x() > 0.8 || _get_y() > 0.8) f = 1; else f = 0; #else if(_get_adc(1) > 0.5) f = 1; else f = 0; #endif #else if (_sw->read() == 1) f = 1; else f = 0; #endif return(f); } void io::analog_pow(uint8_t f) { if (f == 1){ _pow->write(0); #ifdef PCB_VER4 _set_adc_ck(0); #endif } else{ _pow->write(1); #ifdef PCB_VER4 _enableSPI(0); _set_adc_ck(1); wait(0.01); // keep HX711's SCK=1 to enter HX711 into sleep mode #endif } } void io::_set_adc_ck(uint8_t f) { // if (f == 0) NRF_GPIO->OUTCLR |= (1 << _PselSCK); // else NRF_GPIO->OUTSET |= (1 << _PselSCK); if (f == 0) NRF_GPIO->OUTCLR = (1 << _PselSCK); else NRF_GPIO->OUTSET = (1 << _PselSCK); } void io::_enableSPI(uint8_t f) { if (f == 0){ NRF_SPI1->ENABLE = 0; NRF_SPI1->PSELSCK = 0xffffffff; NRF_SPI1->PSELMISO = 0xffffffff; } else{ NRF_SPI1->ENABLE = 0; NRF_SPI1->PSELSCK = _PselSCK; NRF_SPI1->PSELMISO = _PselMISO; NRF_SPI1->ENABLE = 1; } } uint8_t io::_spi_transfer() { return(_hx711.write(0x00)); } void io::calibrate_weight() { // (2016/3/28: take average in weight calibration) int Navg = 10; uint32_t _adc0_s = 0; for (int i = 0; i < Navg; i++){ _adc0_s += _get_adc_raw(0); } _adc0 = (uint32_t)((float)_adc0_s / (float)Navg); } float io::_get_adc(uint8_t ch) { #ifdef PCB_VER4 return(_get_adc_raw(ch) / (float)0xffffff); #else return(_get_adc_raw(ch) / (float)0xffff); #endif } #ifdef PCB_VER4 uint32_t io::_get_adc_raw(uint8_t ch) #else uint16_t io::_get_adc_raw(uint8_t ch) #endif { #ifdef PCB_VER1 if (ch == 0) return(_weight->read()); else if (ch == 1) return(_jx->read()); else return(_jy->read()); #endif #ifdef PCB_VER2 uint16_t adc = 0; uint8_t dh, dl; #ifdef ADC_ADS1115 // for ADS1115 // Input Voltage Range // VIN3 = VDD/2 = 1.65 // VIN0 = 1.8Vpp --> 0.75V - 2.55V // VIN0 - VIN3 = -0.9 - +0.9V (+-1.024V) _adc_dat[0] = 0x01; // config reg. if (ch == 0) _adc_dat[1] = 0x17; // single conv. & FS=+-1.0.24V, AIN0/1/2-AIN3 else if (ch == 1) _adc_dat[1] = 0x27; else _adc_dat[1] = 0x37; _adc_dat[1] |= 0x80; _adc_dat[2] = 0x83; // 128SPS & disable comp. i2c.write(I2C_ADDR, _adc_dat, 3); uint8_t f = 0; uint16_t count = 10; while (f == 0) { _adc_dat[0] = 0x01; i2c.write(I2C_ADDR, _adc_dat, 1); i2c.read(I2C_ADDR, _adc_dat, 2); if ((_adc_dat[0] & 0x80) != 0) f = 1; if(--count == 0) { break; } } _adc_dat[0] = 0x00; i2c.write(I2C_ADDR, _adc_dat, 1); i2c.read(I2C_ADDR, _adc_dat, 2); dh = _adc_dat[0]; dl = _adc_dat[1]; adc = dh << 8 | dl; #else // for MAX11613 _adc_dat[0] = 0xda; // setup / int.reference, ext.clock unipolar _adc_dat[1] = 0x61 | (ch << 1); // config / single-ended i2cwrite(I2C_ADDR, _adc_dat, 2); i2cread(I2C_ADDR, _adc_dat, 2); dh = _adc_dat[0] & 0x0f; dl = _adc_dat[1]; adc = (dh << 8 | dl) << 4; // align to 16 bit #endif // convert 2's complementary -> straight binary // 0x8000 -> 0x0000 // 0x0000 -> 0x8000 // 0x7fff -> 0xffff adc = (adc + 0x8000) & 0xffff; return(adc); #endif #ifdef PCB_VER3 uint16_t adc = 0; // MAX11205, parameter ch is ignored _adc_ck->write(0); while(_adc_di->read() == 1); // wait until conversion is finished // ToDo: data ready timeout for (uint8_t i = 0; i < 16; i++) { _adc_ck->write(1); wait_us(10); adc = adc << 1; if (_adc_di->read() == 1) adc |= 0x01; else adc &= ~0x01; _adc_ck->write(0); wait_us(10); } for (uint8_t i = 0; i < 10; i++) { // additional clock for self calibration _adc_ck->write(1); wait_us(10); _adc_ck->write(0); wait_us(10); } // 0x8000 -> 0x0000 // 0xffff -> 0x7fff // 0x0000 -> 0x8000 // 0x7fff -> 0xffff adc = (adc + 0x8000) & 0xffff; return(adc); #endif #ifdef PCB_VER4 // using HX711 uint32_t adc = 0; // hardware SPI uint8_t d2, d1, d0; _set_adc_ck(0); // note: comment out the while() below for debugging without ADC, HX711 while((NRF_GPIO->IN & (1 << _PselMISO))); _enableSPI(1); d2 = _spi_transfer(); d1 = _spi_transfer(); d0 = _spi_transfer(); _enableSPI(0); _set_adc_ck(1); wait_us(1); _set_adc_ck(0); adc = (d2 << 16) | (d1 << 8) | d0; /* // software SPI while(_adc_di->read() == 1); // wait until conversion is finished // _tk.detach(); // disable timer to keep _adc_ck's H timeb for (uint8_t i = 0; i < 24; i++) { _adc_ck->write(1); wait_us(10); _adc_ck->write(0); wait_us(10); adc = adc << 1; if (_adc_di->read() == 1) adc |= 0x01; else adc &= ~0x01; } for (uint8_t i = 0; i < 1; i++) { _adc_ck->write(1); wait_us(10); _adc_ck->write(0); wait_us(10); } */ // _tk.attach(this, &io::_timer_ticker, 0.002); adc = (adc + 0x800000) & 0xffffff; return(adc); #endif } #ifdef PCB_VER4 // f=1 for power-save mode during sleep void io::power_save_mode(uint8_t f) { if (f == 1) _reg_ps->write(0); // power save mode for sleep else _reg_ps->write(1); // non-power save (high power) mode for normal operation } #endif