Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
