help with bit shifting?

I'm trying to get my head around some code that uses bit shifting to unpack vector coordinates for HPGL font 'draw + move' instructions. I am using a programming calculator to try to work through the code but I am not getting it.

Description of the data format and the function I am working with is below. The lines I am wrestling with are these two:

x = (double) (c >> 4)   - 1.0;      /* Bits 4,5,6 --> value 0..7 */
y = (double) (c & 0x0f) - 4.0;      /* Bits 0-3   --> value 0..f */

To work the problem, according to the data format spec, an input of 324 should result in x == 5, y ==4;

what I get:

(for x) 324 >> 4 is 20; then subtract 1 == 19

then

(for y) 20 AND 15 == 4; then subtract 4 == 0

I have this ass backwards somehow, yes? ;-)

Data format:

** A font or character set is an array of strings. Each character
 ** corresponds to one of these strings, which is addressed by its ASCII code.
 **
 ** A character is a (NULL-terminated) string of bytes. Each byte
 ** codes for a draw or move action according to the code below:
 **
 **      Bit:      7 6 5 4 3 2 1 0
 **            p x x x y y y y
 **
 **      p:      Plot flag. If set, "draw to" new point, else "move to" it.
 **      xxx:      3-bit unsigned integer  (0...7). X coordinate of new point.
 **      yyyy:      4-bit unsigned integer (0..15). Y coordinate of new point.
 **
 ** The baseline is y = 4 instead of y = 0, so characters with parts
 ** below it can be drawn properly without a need for sign bits.
 ** Function "code_to_ucoord()" transforms these coordinates into
 ** actual user coordinates.
 **
 ** Example:      code for character 'L': "\032\224\324" translates to:
 **            moveto(1,10); drawto(1,4); drawto(5,4);

Function:

static void
code_to_ucoord (char c, HPGL_Pt *pp)
/**
 ** Converts internal one-byte code (in c) for a character vector
 ** into HP-GL coordinates (pointed to by pp)
 **/
{
double      x,y;

  /*
   * RS6000 bug fix:
   *       outer braces of casts removed, costing 2 double ops
   * My guess: "char" is unsigned on RS6000
   */
  x = (double) (c >> 4)   - 1.0;      /* Bits 4,5,6 --> value 0..7 */
  y = (double) (c & 0x0f) - 4.0;      /* Bits 0-3   --> value 0..f */
[color=#ff0000]
// NOTE: the stuff below is not important to my question[/color]
  pp->x = tp->Txx * x + tp->Txy * y + tp->refpoint.x + tp->offset.x;
  pp->y = tp->Tyx * x + tp->Tyy * y + tp->refpoint.y + tp->offset.y;
}
code_to_ucoord (char c, HPGL_Pt *pp)

Given that a 'char' can only hold a value between -128 thru 127 inclusive how are you passing it the value 324?

Yeah - I just caught that too. Digging through the code I found that when the function is called the arg is ANDed with 127.

code_to_ucoord ((char)(*ptr&0x7f), &p);

I loaded this all into a sketch but still getting weird values.

void setup() {
  Serial.begin(115200);
}

void loop() {
// ** Example:      code for character 'L': "\032\224\324" translates to:
// ** moveto(1,10); drawto(1,4); drawto(5,4);

  code_to_ucoord(032);
  delay(1000);

  code_to_ucoord(224);
  delay(1000);

  code_to_ucoord(324);
  delay(1000);
}


void code_to_ucoord (char z)
/**
 ** Converts internal one-byte code (in c) for a character vector
 ** into HP-GL coordinates (pointed to by pp)
 **/
{
  double x,y;

  char c = z  &0x7f;
  x = (double) (c >> 4)   - 1.0;       /* Bits 4,5,6 --> value 0..7 */
  y = (double) (c & 0x0f) - 4.0;       /* Bits 0-3   --> value 0..f */

  Serial.print("c ");
  Serial.println(c, DEC);

  Serial.print("x ");
  Serial.println(x);

  Serial.print("y ");
  Serial.println(y);
  //  pp->x = tp->Txx * x + tp->Txy * y + tp->refpoint.x + tp->offset.x;
  //  pp->y = tp->Tyx * x + tp->Tyy * y + tp->refpoint.y + tp->offset.y;
}

I see nothings changed:

code_to_ucoord(032); ← OCTAL VALUE
code_to_ucoord(224); ← OUT OF RANGE, ‘char’ -128 thru 127
code_to_ucoord(324); ← OUT OF RANGE, ‘char’ -128 thru 127