test publish
Dependencies: BLE_API nRF51822 mbed
Fork of KS7 by
Diff: io.cpp
- Branch:
- KS3
- Revision:
- 30:f67850cc3cfe
- Child:
- 31:b5e19d153db4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/io.cpp Mon May 23 05:15:58 2016 +0000 @@ -0,0 +1,633 @@ +#include "io.h" +#include "mbed.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 + _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') +#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 + } +} + +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