/* * Compatibility mode handshaking is a matter of writing data, * strobing it, and waiting for the printer to stop being busy. */ static long write_compat(unsigned minor, const char *c, unsigned long cnt) { long rc; unsigned short pins = get_pins(minor); unsigned long remaining = cnt; while (remaining > 0) { unsigned char byte; get_user_ret(byte, c, -EFAULT); c += 1; rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); if (rc == -1) return -ETIMEDOUT; bpp_outb_p(byte, base_addrs[minor]); remaining -= 1; /* snooze(1, minor); */ pins &= ~BPP_PP_nStrobe; set_pins(pins, minor); rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); pins |= BPP_PP_nStrobe; set_pins(pins, minor); } return cnt - remaining; }
static unsigned i2csw_Read(int dev, bool last) { unsigned char val = 0; int i, databit; // read data byte for(i=0; i<8; i++) { set_pins(dev, 0, 1); delay_us(I2CSW_delay[dev]); // set SDA as input set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // send a clock databit = read_sda(dev); val = (val << 1) | (unsigned char)databit; } set_pins(dev, 0, 1); if (last == false) { // send ACK set_pins(dev, 0, 0); delay_us(I2CSW_delay[dev]); // set SDA = 0 set_pins(dev, 1, 0); delay_us(I2CSW_delay[dev]); // send a clock set_pins(dev, 0, 0); } else { // send NACK set_pins(dev, 0, 1); delay_us(I2CSW_delay[dev]); // set SDA = 1 set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // send a clock set_pins(dev, 0, 1); } return (unsigned)val; }
static long read_nibble(unsigned minor, char __user *c, unsigned long cnt) { unsigned long remaining = cnt; long rc; while (remaining > 0) { unsigned char byte = 0; int pins; /* Event 7: request nibble */ set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); /* Wait for event 9: Peripher strobes first nibble */ pins = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); if (pins == -1) return -ETIMEDOUT; /* Event 10: I handshake nibble */ set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); if (pins & BPP_GP_nFault) byte |= 0x01; if (pins & BPP_GP_Select) byte |= 0x02; if (pins & BPP_GP_PError) byte |= 0x04; if (pins & BPP_GP_Busy) byte |= 0x08; /* Wait for event 11: Peripheral handshakes nibble */ rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); /* Event 7: request nibble */ set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); /* Wait for event 9: Peripher strobes first nibble */ pins = wait_for(0, BPP_GP_nAck, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; /* Event 10: I handshake nibble */ set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); if (pins & BPP_GP_nFault) byte |= 0x10; if (pins & BPP_GP_Select) byte |= 0x20; if (pins & BPP_GP_PError) byte |= 0x40; if (pins & BPP_GP_Busy) byte |= 0x80; if (put_user(byte, c)) return -EFAULT; c += 1; remaining -= 1; /* Wait for event 11: Peripheral handshakes nibble */ rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); if (rc == -1) return -EIO; } return cnt - remaining; }
static int bpp_ioctl(struct inode *inode, struct file *f, unsigned int cmd, unsigned long arg) { int errno = 0; unsigned minor = MINOR(inode->i_rdev); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; switch (cmd) { case BPP_PUT_PINS: set_pins(arg, minor); break; case BPP_GET_PINS: errno = get_pins(minor); break; case BPP_PUT_DATA: bpp_outb_p(arg, base_addrs[minor]); break; case BPP_GET_DATA: errno = bpp_inb_p(base_addrs[minor]); break; case BPP_SET_INPUT: if (arg) if (instances[minor].enhanced) { unsigned short bits = get_pins(minor); instances[minor].direction = 0x20; set_pins(bits, minor); } else { errno = -ENOTTY; } else { unsigned short bits = get_pins(minor); instances[minor].direction = 0x00; set_pins(bits, minor); } break; default: errno = -EINVAL; } return errno; }
/* * Write data using ECP mode. Watch out that the port may be set up * for reading. If so, turn the port around. */ static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) { unsigned short pins = get_pins(minor); unsigned long remaining = cnt; if (instances[minor].direction) { int rc; /* Event 47 Request bus be turned around */ pins |= BPP_PP_nInit; set_pins(pins, minor); /* Wait for Event 49: Peripheral relinquished bus */ rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); pins |= BPP_PP_nAutoFd; instances[minor].direction = 0; set_pins(pins, minor); } while (remaining > 0) { unsigned char byte; int rc; if (get_user(byte, c)) return -EFAULT; rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; c += 1; bpp_outb_p(byte, base_addrs[minor]); pins &= ~BPP_PP_nStrobe; set_pins(pins, minor); pins |= BPP_PP_nStrobe; rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); if (rc == -1) return -EIO; set_pins(pins, minor); } return cnt - remaining; }
static void probeLptPort(unsigned idx) { unsigned int testvalue; const unsigned short lpAddr = base_addrs[idx]; instances[idx].present = 0; instances[idx].enhanced = 0; instances[idx].direction = 0; instances[idx].mode = COMPATIBILITY; instances[idx].wait_queue = 0; instances[idx].run_length = 0; instances[idx].run_flag = 0; init_timer(&instances[idx].timer_list); instances[idx].timer_list.function = bpp_wake_up; if (check_region(lpAddr,3)) return; /* * First, make sure the instance exists. Do this by writing to * the data latch and reading the value back. If the port *is* * present, test to see if it supports extended-mode * operation. This will be required for IEEE1284 reverse * transfers. */ outb_p(BPP_PROBE_CODE, lpAddr); for (testvalue=0; testvalue<BPP_DELAY; testvalue++) ; testvalue = inb_p(lpAddr); if (testvalue == BPP_PROBE_CODE) { unsigned save; instances[idx].present = 1; request_region(lpAddr,3, dev_name); save = inb_p(lpAddr+2); for (testvalue=0; testvalue<BPP_DELAY; testvalue++) ; outb_p(save|0x20, lpAddr+2); for (testvalue=0; testvalue<BPP_DELAY; testvalue++) ; outb_p(~BPP_PROBE_CODE, lpAddr); for (testvalue=0; testvalue<BPP_DELAY; testvalue++) ; testvalue = inb_p(lpAddr); if ((testvalue&0xff) == (0xff&~BPP_PROBE_CODE)) instances[idx].enhanced = 0; else instances[idx].enhanced = 1; outb_p(save, lpAddr+2); } /* * Leave the port in compat idle mode. */ set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); printk("bpp%d: Port at 0x%03x: Enhanced mode %s\n", idx, base_addrs[idx], instances[idx].enhanced? "SUPPORTED" : "UNAVAILABLE"); }
static ssize_t bpp_read(struct file *f, char *c, size_t cnt, loff_t * ppos) { long rc; const unsigned minor = MINOR(f->f_dentry->d_inode->i_rdev); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; switch (instances[minor].mode) { default: if (instances[minor].mode != COMPATIBILITY) terminate(minor); if (instances[minor].enhanced) { /* For now, do all reads with ECP-RLE mode */ unsigned short pins; rc = negotiate(DEFAULT_ECP, minor); if (rc < 0) break; instances[minor].mode = ECP_RLE; /* Event 30: set nAutoFd low to setup for ECP mode */ pins = get_pins(minor); pins &= ~BPP_PP_nAutoFd; set_pins(pins, minor); /* Wait for Event 31: peripheral ready */ rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; rc = read_ecp(minor, c, cnt); } else { rc = negotiate(DEFAULT_NIBBLE, minor); if (rc < 0) break; instances[minor].mode = NIBBLE; rc = read_nibble(minor, c, cnt); } break; case NIBBLE: rc = read_nibble(minor, c, cnt); break; case ECP: case ECP_RLE: rc = read_ecp(minor, c, cnt); break; } return rc; }
void system_init() { /* Stop the watchdog */ startup_watchdog_disable(); /* Do it right now, before it gets a chance to break in */ /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power * it back on if called after system_init() */ system_brown_out_detection_config(0); system_set_default_power_state(); clock_config(SELECTED_FREQ); set_pins(common_pins); set_pins(adc_pins); gpio_on(); status_led_config(&status_led_green, &status_led_red); /* System tick timer MUST be configured and running in order to use the sleeping functions */ systick_timer_on(1); /* 1ms */ systick_start(); }
/* * Return ZERO(0) If the negotiation succeeds, an errno otherwise. An * errno means something broke, and I do not yet know how to fix it. */ static int negotiate(unsigned char mode, unsigned minor) { int rc; unsigned short pins = get_pins(minor); if (pins & BPP_PP_nSelectIn) return -EIO; /* Event 0: Write the mode to the data lines */ bpp_outb_p(mode, base_addrs[minor]); snooze(TIME_PSetup, minor); /* Event 1: Strobe the mode code into the peripheral */ set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nInit, minor); /* Wait for Event 2: Peripheral responds as a 1284 device. */ rc = wait_for(BPP_GP_PError|BPP_GP_Select|BPP_GP_nFault, BPP_GP_nAck, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; /* Event 3: latch extensibility request */ set_pins(BPP_PP_nSelectIn|BPP_PP_nInit, minor); /* ... quick nap while peripheral ponders the byte i'm sending...*/ snooze(1, minor); /* Event 4: restore strobe, to ACK peripheral's response. */ set_pins(BPP_PP_nSelectIn|BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); /* Wait for Event 6: Peripheral latches response bits */ rc = wait_for(BPP_GP_nAck, 0, TIME_PSetup+TIME_PResponse, minor); if (rc == -1) return -EIO; /* A 1284 device cannot refuse nibble mode */ if (mode == DEFAULT_NIBBLE) return 0; if (pins & BPP_GP_Select) return 0; return -EPROTONOSUPPORT; }
static void probeLptPort(unsigned idx) { void __iomem *rp = base_addrs[idx]; __u32 csr; char *brand; instances[idx].present = 0; instances[idx].enhanced = 0; instances[idx].direction = 0; instances[idx].mode = COMPATIBILITY; instances[idx].run_length = 0; instances[idx].run_flag = 0; if (!rp) return; instances[idx].present = 1; instances[idx].enhanced = 1; /* Sure */ csr = sbus_readl(rp + BPP_CSR); if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { udelay(20); csr = sbus_readl(rp + BPP_CSR); if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr); } } printk("bpp%d: reset with 0x%08x ..", idx, csr); sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR); udelay(500); sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR); csr = sbus_readl(rp + BPP_CSR); printk(" done with csr=0x%08x ocr=0x%04x\n", csr, sbus_readw(rp + BPP_OCR)); switch (csr & P_DEV_ID_MASK) { case P_DEV_ID_ZEBRA: brand = "Zebra"; break; case P_DEV_ID_L64854: brand = "DMA2"; break; default: brand = "Unknown"; } printk("bpp%d: %s at %p\n", idx, brand, rp); /* * Leave the port in compat idle mode. */ set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); return; }
static void probeLptPort(unsigned idx) { volatile struct bpp_regs *rp = base_addrs[idx]; __u32 csr; char *brand; instances[idx].present = 0; instances[idx].enhanced = 0; instances[idx].direction = 0; instances[idx].mode = COMPATIBILITY; instances[idx].wait_queue = 0; instances[idx].run_length = 0; instances[idx].run_flag = 0; init_timer(&instances[idx].timer_list); instances[idx].timer_list.function = bpp_wake_up; if (rp == 0) return; instances[idx].present = 1; instances[idx].enhanced = 1; /* Sure */ if (((csr = rp->p_csr) & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { udelay(20); csr = rp->p_csr; if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr); } } printk("bpp%d: reset with 0x%08x ..", idx, csr); rp->p_csr = (csr | P_RESET) & ~P_INT_EN; udelay(500); rp->p_csr &= ~P_RESET; printk(" done with csr=0x%08x ocr=0x%04x\n", rp->p_csr, rp->p_ocr); switch (rp->p_csr & P_DEV_ID_MASK) { case P_DEV_ID_ZEBRA: brand = "Zebra"; break; case P_DEV_ID_L64854: brand = "DMA2"; break; default: brand = "Unknown"; } printk("bpp%d: %s at 0x%p\n", idx, brand, rp); /* * Leave the port in compat idle mode. */ set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); return; }
static bool i2csw_Write(int dev, unsigned char val) { int i, databit; // send data byte for(i=0; i<8; i++) { databit = ((val & 0x80) == 0)? 0 : 1; set_pins(dev, 0, databit); delay_us(I2CSW_delay[dev]); // set data bit set_pins(dev, 1, databit); delay_us(I2CSW_delay[dev]); // send a clock set_pins(dev, 0, databit); val = val << 1; } // read ACK set_pins(dev, 0, 1); delay_us(I2CSW_delay[dev]); // set SDA as input set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // send a clock if (read_sda(dev) == 1) { err_SetMsg(ERROR_I2CACKERR, "receive no ACK after transmitting"); return false; } set_pins(dev, 0, 1); return true; }
int main() { /* * Set the thing at the adress of an int to 0. */ PORTA = 0; PORTB = 0; /* * To the function set_pins, we are passing &PORTX which is * the adress of (the thing at the address of an int) */ set_pins(&PORTA, (1 << PORTA2)|(1 << PORTA1)|(1 << PORTA0)); set_pins(&PORTB, (1 << PORTA7)|(1 << PORTA6)|(1 << PORTA5)); /* * Print the thing at the address of an int */ printf("new value of PORTA : %d\n", PORTA); printf("new value of PORTB : %d\n", PORTB); return 0; }
static int terminate(unsigned minor) { int rc; /* Event 22: Request termination of 1284 mode */ set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); /* Wait for Events 23 and 24: ACK termination request. */ rc = wait_for(BPP_GP_Busy|BPP_GP_nFault, BPP_GP_nAck, TIME_PSetup+TIME_PResponse, minor); instances[minor].direction = 0; instances[minor].mode = COMPATIBILITY; if (rc == -1) { return -EIO; } /* Event 25: Handshake by lowering nAutoFd */ set_pins(BPP_PP_nStrobe|BPP_PP_nInit, minor); /* Event 26: Peripheral wiggles lines... */ /* Event 27: Peripheral sets nAck HIGH to ack handshake */ rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); if (rc == -1) { set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); return -EIO; } /* Event 28: Finish phase by raising nAutoFd */ set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); return 0; }
//draws the linebuffer to the lcd, some loop unrolling void draw_linebuffer() { set_pins(); for (int32_t i = 0; i < SCREENX; i+=20) { set_data(line_buffer[i]); pulse_pins(); set_data(line_buffer[i+1]); pulse_pins(); set_data(line_buffer[i+2]); pulse_pins(); set_data(line_buffer[i+3]); pulse_pins(); set_data(line_buffer[i+4]); pulse_pins(); set_data(line_buffer[i+5]); pulse_pins(); set_data(line_buffer[i+6]); pulse_pins(); set_data(line_buffer[i+7]); pulse_pins(); set_data(line_buffer[i+8]); pulse_pins(); set_data(line_buffer[i+9]); pulse_pins(); set_data(line_buffer[i+10]); pulse_pins(); set_data(line_buffer[i+11]); pulse_pins(); set_data(line_buffer[i+12]); pulse_pins(); set_data(line_buffer[i+13]); pulse_pins(); set_data(line_buffer[i+14]); pulse_pins(); set_data(line_buffer[i+15]); pulse_pins(); set_data(line_buffer[i+16]); pulse_pins(); set_data(line_buffer[i+17]); pulse_pins(); set_data(line_buffer[i+18]); pulse_pins(); set_data(line_buffer[i+19]); pulse_pins(); } unset_pins(); }
RBAPI(bool) i2c_Initialize2(unsigned devs, int i2c0irq, int i2c1irq) { int i; if (I2C_ioSection != -1) { err_SetMsg(ERROR_I2C_INUSE, "I2C lib was already opened"); return false; } if ((I2C_ioSection = io_Init()) == -1) return false; if (i2c_SetDefaultBaseAddress() == 0x0000) i2c_SetBaseAddress(0xfb00); i2c_SetIRQ(i2c0irq, i2c1irq); I2C_action[0] = I2C_action[1] = I2CACT_DISABLE; for (i=0; i<2; i++) { if ((i == 0) && ((devs & I2C_USEMODULE0) == 0)) continue; if ((i == 1) && ((devs & I2C_USEMODULE1) == 0)) continue; I2C_action[i] = I2CACT_IDLE; //switch GPIO/I2C pins into GPIO pins OLD_I2CGPIO3FLAG[i] = read_sb_reg(SB_IPFCTRL3_REG) & OLD_I2CGPIO3MASK[i]; //backup GPIO/I2C switch flag write_sb_reg(SB_IPFCTRL3_REG, read_sb_reg(SB_IPFCTRL3_REG) & (~OLD_I2CGPIO3MASK[i])); //send START & STOP signal to reset I2C devices OLD_I2CGPIO3DIR[i] = io_inpb(0x9b) & (0x03 << (i*2+4)); //backup GPIO3 DIR OLD_I2CGPIO3VAL[i] = io_inpb(0x7b) & (0x03 << (i*2+4)); //backup GPIO3 VAL //set_pins(i, 1, 1); delay_ms(1); //SCL = 1, SDA = 1; START //set_pins(i, 1, 0); delay_ms(1); //SCL = 1, SDA = 0 //set_pins(i, 0, 0); delay_ms(1); //SCL = 0, SDA = 0 //Note: if we send the above START, some I2C sensors, such as ADI ADXL345, may fail to respond //set_pins(i, 0, 0); delay_ms(1); //SCL = 0, SDA = 0; STOP //Note: if we perform the line above, some I2C sensors, such as MEMSIC MXC6202, may fail to respond set_pins(i, 1, 0); delay_ms(1); //SCL = 1, SDA = 0 set_pins(i, 1, 1); delay_ms(1); //SCL = 1, SDA = 1 if (i2c_Reset(i) == false) { i2c_Close(); err_SetMsg(ERROR_I2C_INITFAIL, "can't reset the I2C modules"); return false; } i2c_DisableINT(i, I2CINT_ALL); i2c_ClearSTAT(i, I2CSTAT_ALL); //Remarks: for DX ver.2, we must disable the noise filter to ensure that 3.3Mbps works in high-speed mode i2c_DisableNoiseFilter(i); //i2c_EnableNoiseFilter(i); i2c_DisableStandardHSM(i); //SCL open-drain in high-speed mode //i2c_EnableStandardHSM(i); i2c_SetSpeed(i, I2CMODE_AUTO, 100000L); //default 100Kbps i2cslave_SetAddr(i, 0x7f); //set slave address 0x7F by default (change this if it collide with external I2C devices) i2cslave_EnableACK(i); //switch GPIO pins into I2C SCL,SDA pins //Remarks: Vortex86DX's H/W I2C has an issue here; if you call i2c_Reset() in case GPIO/SCL pin = GPIO out 0, // then, whenever you switch GPIO/SCL pin to SCL pin, the SCL pin always first send the 10 reset dummy clocks write_sb_reg(SB_IPFCTRL3_REG, read_sb_reg(SB_IPFCTRL3_REG) | OLD_I2CGPIO3MASK[i]); } return true; }
static void i2csw_Stop(int dev) { set_pins(dev, 0, 0); timer_DelayMicroseconds(I2CSW_delay[dev]); // SCL = 0, SDA = 0 set_pins(dev, 1, 0); timer_DelayMicroseconds(I2CSW_delay[dev]); // SCL = 1, SDA = 0 set_pins(dev, 1, 1); // SCL = 1, SDA = 1 }
static long read_ecp(unsigned minor, char *c, unsigned long cnt) { unsigned long remaining; long rc; /* Turn ECP mode from forward to reverse if needed. */ if (! instances[minor].direction) { unsigned short pins = get_pins(minor); /* Event 38: Turn the bus around */ instances[minor].direction = 0x20; pins &= ~BPP_PP_nAutoFd; set_pins(pins, minor); /* Event 39: Set pins for reverse mode. */ snooze(TIME_PSetup, minor); set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); /* Wait for event 40: Peripheral ready to be strobed */ rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; } remaining = cnt; while (remaining > 0) { /* If there is a run length for a repeated byte, repeat */ /* that byte a few times. */ if (instances[minor].run_length && !instances[minor].run_flag) { char buffer[128]; unsigned idx; unsigned repeat = remaining < instances[minor].run_length ? remaining : instances[minor].run_length; for (idx = 0 ; idx < repeat ; idx += 1) buffer[idx] = instances[minor].repeat_byte; copy_to_user_ret(c, buffer, repeat, -EFAULT); remaining -= repeat; c += repeat; instances[minor].run_length -= repeat; } if (remaining == 0) break; /* Wait for Event 43: Data active on the bus. */ rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); if (rc == -1) break; if (rc & BPP_GP_Busy) { /* OK, this is data. read it in. */ unsigned char byte = bpp_inb(base_addrs[minor]); put_user_ret(byte, c, -EFAULT); c += 1; remaining -= 1; if (instances[minor].run_flag) { instances[minor].repeat_byte = byte; instances[minor].run_flag = 0; } } else { unsigned char byte = bpp_inb(base_addrs[minor]); if (byte & 0x80) { printk("bpp%d: " "Ignoring ECP channel %u from device.\n", minor, byte & 0x7f); } else { instances[minor].run_length = byte; instances[minor].run_flag = 1; } } /* Event 44: I got it. */ set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor); /* Wait for event 45: peripheral handshake */ rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; /* Event 46: Finish handshake */ set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); } return cnt - remaining; }
static bool i2csw_Start(int dev, unsigned char addr, unsigned char rwbit, bool restart) { int i, databit; if (restart == false) { // send START signal set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 1 set_pins(dev, 1, 0); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 0 set_pins(dev, 0, 0); // SCL = 0, SDA = 0 } else if (I2C_swMode[dev] == I2CSW_LEGO) { // send LEGO NXT's I2C RESTART signal set_pins(dev, 0, 0); delay_us(I2CSW_delay[dev]); // SCL = 0, SDA = 0 set_pins(dev, 1, 0); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 0 set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 1 set_pins(dev, 0, 1); delay_us(I2CSW_delay[dev]); // LEGO NXT special: SCL = 0, SDA = 1 set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 1 set_pins(dev, 1, 0); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 0 set_pins(dev, 0, 0); // SCL = 0, SDA = 0 } else { // send normal I2C RESTART signal set_pins(dev, 0, 0); delay_us(I2CSW_delay[dev]); // SCL = 0, SDA = 0 set_pins(dev, 0, 1); delay_us(I2CSW_delay[dev]); // SCL = 0, SDA = 1 set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 1 set_pins(dev, 1, 0); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 0 set_pins(dev, 0, 0); // SCL = 0, SDA = 0 } // send data byte addr = (addr << 1) | rwbit; for(i=0; i<8; i++) { databit = ((addr & 0x80) == 0)? 0 : 1; set_pins(dev, 0, databit); delay_us(I2CSW_delay[dev]); // set data bit set_pins(dev, 1, databit); delay_us(I2CSW_delay[dev]); // send a clock set_pins(dev, 0, databit); addr = addr << 1; } // read ACK set_pins(dev, 0, 1); delay_us(I2CSW_delay[dev]); // set SDA as input set_pins(dev, 1, 1); delay_us(I2CSW_delay[dev]); // send a clock if (read_sda(dev) == 1) { err_SetMsg(ERROR_I2CACKERR, "receive no ACK after transmitting"); return false; } set_pins(dev, 0, 1); return true; }
static void i2csw_Stop(int dev) { set_pins(dev, 0, 0); delay_us(I2CSW_delay[dev]); // SCL = 0, SDA = 0 set_pins(dev, 1, 0); delay_us(I2CSW_delay[dev]); // SCL = 1, SDA = 0 set_pins(dev, 1, 1); // SCL = 1, SDA = 1 }