Uno Port PB1 & PB2 dead?

These #define(s) work fine:

#define CLK4  19  // pin 28
#define DAT4  18  // pin 27

void set_port()
{
 pinMode(CLK4, OUTPUT);
 digitalWrite(CLK4, 1); 
 pinMode(DAT4, OUTPUT);
 digitalWrite(DAT4, 1); 
}

These do not and are dead. Why?

#define CLK1  9   // pin 15
#define DAT1 10  // pin 16

void set_port()
{
 pinMode(CLK1, OUTPUT);
 digitalWrite(CLK1, 1); 
 pinMode(DAT1, OUTPUT);
 digitalWrite(DAT1, 1);  
}

Is there something more I need to do to use PORTB as digital output on the ATMEGA328 via the Uno board?

NOTE: This is not a bad chip. I already swapped it out with no change.

Nope. That should work fine.

test it with bare numbers:

Hi,
Where is the rest of your code?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Full listing. Note there are no #include files or third party libraries. It's all here! This is a four port PS2 keyboard emulator to send keyboard commands to some industrial hardware that uses a plain PS2 keyboard for remote control.

You send two characters via RS232, first is ASCII 1 thru 4 to select the PS2 port, the second is the keyboard character you want to send, Followed by a CR (0xD). Note the conversion to PS2 scan codes is handled by this code.

Snippets of this code are derived and modified from PS2keypolled written by forum member"westfw".

 * ps2emu_poll.c
*/

/* PS2 connector pinout
 *  1- DATA
 *  2- nc
 *  3- GND
 *  4- +5v
 *  5- CLK
 *  6- nc
 */

#define CLK_PULSE 10
#define MAX_CHAR  10

/* PS2 port Arduino // ATMEGA328 pin assignments */
#define CLK1   9  // pin 15
#define DAT1  10  // pin 16
#define CLK2  14  // pin 23
#define DAT2  15  // pin 24
#define CLK3  16  // pin 25
#define DAT3  17  // pin 26
#define CLK4  18  // pin 27
#define DAT4  19  // pin 28

  unsigned char ps2k_clk, ps2k_dat;
  char inputString[MAX_CHAR];      
  unsigned char_cnt= 0;
  bool stringComplete = false;  
  unsigned char ScanCode[256];
  unsigned char kybd_port[4][2]; 

void setup() {
  
  unsigned char n;

    /* load port pin array */
    load_ScanCodes();
    kybd_port[0][0]= CLK1;   
    kybd_port[0][1]= DAT1;   
    kybd_port[1][0]= CLK2;
    kybd_port[1][1]= DAT2;  
    kybd_port[2][0]= CLK3;
    kybd_port[2][1]= DAT3;  
    kybd_port[3][0]= CLK4;
    kybd_port[3][1]= DAT4;  
    
    for (n= 0; n<= 3; n++)  
         ps2k_init (kybd_port[n][0],kybd_port[n][1]);
    Serial.begin(9600);   /* initialize serial */
}


void ps2k_init (unsigned char clock, unsigned char data)
{
    ps2k_clk = clock;
    ps2k_dat = data;
    pinMode(ps2k_clk, OUTPUT);
    digitalWrite(ps2k_clk, 1);  /* Claim the clock */
    pinMode(ps2k_dat, OUTPUT);
    digitalWrite(ps2k_dat, 0);  /* Enable pullups */
}

void loop() 
{
    unsigned char n;
/*
  ps2k_clk= kybd_port[3][0];
  ps2k_dat= kybd_port[3][1];
  ps2k_sendbyte(ScanCode['A']);
  Serial.println("Running");
 */
    if (stringComplete) {
        Serial.println(inputString);
        n= (inputString[0] - 0x31);
        if (((n >= 1)&&(n <= 4))&&(ScanCode[inputString[1]] > 0)) {
            ps2k_clk= kybd_port[n][0];
            ps2k_dat= kybd_port[n][1];
            ps2k_sendbyte(ScanCode[inputString[1]]);
        }
        inputString[0]=  0;  // clear the string:
        stringComplete = false;
        }
}

void ps2k_sendbyte(unsigned char code)
{
    unsigned char parity = 0;  /* Get first byte */
    unsigned char i;

    /* send start bit */
    digitalWrite(ps2k_dat, 0);
    delayMicroseconds(CLK_PULSE);
    digitalWrite(ps2k_clk, 0);
    delayMicroseconds(CLK_PULSE);
    digitalWrite(ps2k_clk, 1);

    /* Send 8 data bits, LSB first */
    for (i = 0; i < 8; i++) {  /* Send 8 data bits, LSB first */
         if (code & 0x1) {
             digitalWrite(ps2k_dat, 1);
             parity++;  /* Count one bits to calculate parity */
             } 
         else 
             digitalWrite(ps2k_dat, 0);
         delayMicroseconds(CLK_PULSE);
         digitalWrite(ps2k_clk, 0);
         delayMicroseconds(CLK_PULSE);
         digitalWrite(ps2k_clk, 1);
         code >>= 1;  /* Shift to get next bit ready. */
         }

    /* Send proper parity bit */
    if ((parity & 0x1)) 
        digitalWrite(ps2k_dat, 0);
    else
        digitalWrite(ps2k_dat, 1);
    delayMicroseconds(CLK_PULSE);
    digitalWrite(ps2k_clk, 0);
    delayMicroseconds(CLK_PULSE);
    digitalWrite(ps2k_clk, 1); 

    /* Send stop bit */
    digitalWrite(ps2k_dat, 1);
    delayMicroseconds(CLK_PULSE);
    digitalWrite(ps2k_clk, 0);
    delayMicroseconds(CLK_PULSE);
    digitalWrite(ps2k_clk, 1);
    digitalWrite(ps2k_dat, 0);
}

void serialEvent() 
{
  char inChar;
  
  while (Serial.available()) {
        if (char_cnt == (MAX_CHAR - 1))
            char_cnt= 0;
        inChar= (char)Serial.read();
        inputString[char_cnt++]= inChar;
        if (inChar == 0xD)  {
            char_cnt= 0;
            stringComplete = true;
        }
  }
}

void load_ScanCodes()
{
  /* Listed are PRESS scan codes. For RELEASE codes, first send 0xF0, then listed scancode */
  
    ScanCode['1'] = 0x16;
    ScanCode['2'] = 0x1E;
    ScanCode['3'] = 0x26;
    ScanCode['4'] = 0x25;
    ScanCode['5'] = 0x2E;
    ScanCode['6'] = 0x36;
    ScanCode['7'] = 0x3D;
    ScanCode['8'] = 0x3E;
    ScanCode['9'] = 0x46;
    ScanCode['0'] = 0x45;
    
    ScanCode['A'] = 0x1C;
    ScanCode['B'] = 0x32;
    ScanCode['C'] = 0x21;
    ScanCode['D'] = 0x23;
    ScanCode['E'] = 0x24;
    ScanCode['F'] = 0x2B;
    ScanCode['G'] = 0x34;
    ScanCode['H'] = 0x33;
    ScanCode['I'] = 0x43;
    ScanCode['J'] = 0x3B;
    ScanCode['K'] = 0x42;
    ScanCode['L'] = 0x4B;
    ScanCode['M'] = 0x3A;
    ScanCode['N'] = 0x31;
    ScanCode['O'] = 0x44;
    ScanCode['P'] = 0x4D;
    ScanCode['Q'] = 0x15;
    ScanCode['R'] = 0x2D;
    ScanCode['S'] = 0x1B;
    ScanCode['T'] = 0x2C;
    ScanCode['U'] = 0x3C;
    ScanCode['V'] = 0x2A;
    ScanCode['W'] = 0x1D;
    ScanCode['X'] = 0x22;
    ScanCode['Y'] = 0x35;
    ScanCode['Z'] = 0x1A;

    ScanCode[';'] = 0x4C;
    ScanCode[','] = 0x41;
    ScanCode['.'] = 0x49;
    ScanCode['/'] = 0x4A;
    ScanCode['*'] = 0x7C;
    ScanCode['-'] = 0x7B;
    ScanCode['+'] = 0x79; 
    ScanCode['.'] = 0x71;
    ScanCode['='] = 0x55;
        
    ScanCode[0x91] = 0x05;  // F1
    ScanCode[0x92] = 0x06;  // F2
    ScanCode[0x93] = 0x04;  // F3
    ScanCode[0x94] = 0x0C;  // F4
    ScanCode[0x95] = 0x03;  // F5
    ScanCode[0x96] = 0x0B;  // F6
    ScanCode[0x97] = 0x83;  // F7
    ScanCode[0x98] = 0x0A;  // F8
    ScanCode[0x99] = 0x01;  // F9
    ScanCode[0x9A] = 0x09;  // F10
    ScanCode[0x9B] = 0x78;  // F11
    ScanCode[0x9C] = 0x07;  // F12
   
    ScanCode[0x20] = 0x29;  // space
    ScanCode[0x08] = 0x66;  // back
    ScanCode[0x1B] = 0x76;  // esc
    ScanCode[0x80] = 0x12;  // shift left
    ScanCode[0x81] = 0x59;  // shift right
    ScanCode[0x82] = 0x58;  // caps lock
      
}

If you print these values, are they plausible?

Is this

     (n >= 1)&&(n <= 4)

correct? Array indices run from 0 to size - 1.

At a glance through the small window. HTH.

a7

I just noticed the same thing! Yes that appears to be the bug. I force the received port number to start at zero as not to waste memory in a dead array address(s). Note I come from the 8051 days when that was important. I guess today not so much. The ATMEGA328 has what, 32K of code memory?

Heavies and old-timers will look to save any byte they can, no matter. And any microseconds that can be shaved must. Be shaved.

But the Arduino boards have, from a certain point of view, vast resources. Add that amazing optimiser in the compiler and you can relax about many things.

Best: programs that use a fraction of the resources, like 1/3. Never worry about running out of anything. :expressionless:

If you aren't fluent in C/C++ it is never too early to start using zero the way it is… number things from zero is the start and yes, you'll get yourself confused once in a while.

a7

The problem is not at all a waste of memory for one element. When you work with an array of 4 elements with such a condition,

(n >= 1)&&(n <= 4)

you have an array overflow with memory corruption, after which the program may work incorrectly or even hang

Not always :slight_smile: It can be really important that the body of an if takes the same time as the body of the associated else.

We used to fill an empty else body with NOPs to achieve that.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.