Skip navigation

Tag Archives: C++

This didn’t occur to me until I was mounting the device, but I had a situation involving an I2C serial display (SSD1306) that needed to rotate it’s display 180 degrees to be easily readable. Due to memory constraints of the rest of the software I wasn’t able to include some of the more robust graphics libraries to drive it so I ended up having to manually alter the display buffer before each draw operation. This was the result.

Each character is a single byte array we are mirroring the bits horizontally and vertically, or flipping the MSB to LSB. This is a common textbook example modified to accommodate the display resolution.

void SSD1306::rotate180(void)
{
  // unsigned integer byte arrays
  uint8_t t;
  uint8_t p;

  // screen dimensions in bytes (1 byte per char)
  int byteCount = ((WIDTH * HEIGHT / 8) / 2) - 1;
  int bufferEnd = (WIDTH * HEIGHT / 8) - 1;

  // for each byte in display area
  for (uint16_t i = 0; i <= byteCount; i++)
  {
    p = 0;
    t = buffer[i];
    // for each bit in current character
    for (int j = 0; j <= 7; j++)
    {
      // shift p 1 bit left
      p = p << 1;
      if ((t & 0x01) > 0)
      {
        // bitwise or
        p = p | 1;
      }
      t = t >> 1;
    }

    // push flipped bit column to display buffer
    buffer[bufferEnd - i] = p;
    // get next byte/character from end of line
    t = buffer[bufferEnd - i];

    // repeat 
    p = 0;
    for (int j = 0; j <= 7; j++)
    {
      p = p << 1;
      if ((t & 0x01) > 0)
      {
        p = p | 1;
      }
      t = t >> 1;
    }
    // push flipped column of pixels
    buffer[i] = p;
  }

Turns out this would be much faster using a lookup table, but that requires more memory.

byte reverse[256] PROGMEM = {
      0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
      0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
      0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
      0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
      0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
      0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
      0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
      0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
      0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
      0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
      0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
      0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
      0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
      0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
      0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
      0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF};

// screen dimensions in bytes (1 byte per char)
int byteCount = ((WIDTH * HEIGHT / 8) / 2) - 1;
int bufferEnd = (WIDTH * HEIGHT / 8) - 1;
void rotate180(void) {
  for (uint16_t i = 0; i <= byteCount; i++)
    buffer[bufferEnd - i] = reverse[i];
  }
}

The WSO2 framework provides comprehensive WSS, WSI security for SOAP and REST based web services with bindings in multiple languages including Java, PHP, Python, C, Ruby and many more. Unfortunately if you are attempting to compile this library extension for PHP > 5.3, you are going to have a bad time.

The first error you will run into is php zend_class_entry has no member named default_properties

The second error once you find a way around that one is php struct_php_core_globals has no member named safe_mode These are both due to changes made in PHP since 5.4, for “Safe Mode” specifically since the concept was deprecated in 5.3 and removed in 5.4, see PHP Safe Mode for more details.

The third error you may encounter is along the lines of error CHECKUID_CHECK_FILE_AND_DIR undeclared which is also due to deprecated/retired components of PHP.

Fortunately the fixes are few and easy, here are the patches:

src/wsf.c:

@@ -458,8 +458,12 @@
 
     ALLOC_HASHTABLE(intern->std.properties);
     zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+#if PHP_VERSION_ID < 50399
     zend_hash_copy(intern->std.properties, &class_type->default_properties,
             (copy_ctor_func_t) zval_add_ref, (void *) & tmp, sizeof (void *));
+#else
+    object_properties_init((zend_object*) &(intern->std.properties), class_type);
+#endif
 
     retval.handle = zend_objects_store_put(intern,
             (zend_objects_store_dtor_t) zend_objects_destroy_object,

src/wsf_util.c:

@@ -1986,10 +1986,6 @@
 
 	if (VCWD_REALPATH(path, resolved_path_buff)) 
 	{
-		if (PG(safe_mode) && (!php_checkuid(resolved_path_buff, NULL, CHECKUID_CHECK_FILE_AND_DIR))) 
-		{
-			return NULL;
-		}
 
 		if (php_check_open_basedir(resolved_path_buff TSRMLS_CC)) 
 		{

You’ll notice that in wsf_util.c we simply removed that particular check because both functions/values no longer existed, there may be a better solution to this but for the moment we are able to compile. Rember to make clean then ./configure
make
sudo make install
and add the extension ini to /etc/php.d/

Done.

Having trouble finding the sources? Try the GitHub repo here or from the WSO2 site here. For some reason trying to wget that last URL resulted in 403 denied for me, but I was able to DL using a browser.