Jun 222017
 

Python3 code is below…

also available at this Gitlab link

https://gitlab.com/Alex-rtnVFRmedia/pagertest2

# control the Arduino RF22 pager TX # modified ON1ARF code # # 2017-06-23 Alex The Engineer # The Rat's Nest, Ipswich UK # # import serial import pprint import sys from colorconsole import terminal from colored import fg, bg, attr import readline # global colours res=attr('reset') # tty open now coded as a function # # colored module used here instead of colorconsole/screen object # just in case there isn't a global screen object available # def page(ttydev,capcode,function,repeats,message): # # create msg bytearray (NB: there should be more error # checking here # msg=(b'P ') msg+=(b'%07d' % capcode)+(b' ') msg+=(b'%01d' % function)+(b' ') msg+=(b'%01d' % repeats)+(b' ') msg+=(message)+(b'\r') print (fg(80),bg(0x12),'** opening tty:',ttydev+res) # serial port open with error checking this time try: ser = serial.Serial(ttydev, timeout=3) except serial.SerialException: print(res) sys.exit("** ERROR: cannot open tty\n\n") # if we got here everything is OK # RTS/DTR does not actually need to be flipped # as opening the tty does that anyway # which saves some time starting up the arduino comms # ser.setRTS(True) # ser.setRTS(False) # # get the lines from the buffer print (fg(0x0b),bg(0x15),'** tty open OK: >>check TX<<'+res) ibuf = ser.readlines() print (fg(202)) #pprint.pprint(ibuf) print (' ibuf[0] :',ibuf[0]) print (' ibuf[-1] :',ibuf[-1]) # check to see what came down comms line is expected if ibuf[0] != (b'RF22 init OK\r\n'): print(res) sys.exit("** ERROR: RF22 init error\n\n") if ibuf[-1] != (b'F <freqmhz> <freq100Hz>\r\n'): print(res) sys.exit("** ERROR: RF22 comms error\n\n") # if TX has correctly initialised now send message ser.write(msg) # get a line back from TTY, it should be exactly same as msg # but with a \n after it # if it hasn't something has gone wrong check=ser.readline() print(fg(0x50),'<< from tty:',fg(0x72),bg(0x08),check,res,fg(0x52)) if check != (msg+b'\n'): print(res) sys.exit("** ERROR: pager comms error\n\n") print (' ++ comms to pager TX OK ++') # get data returned over comms link # and now echo it with some pretty colours ๐Ÿ™‚ colindex=0x70 while True: data=ser.readline() # only print it if a sending confirmation if data==(b'POCSAG SEND\r\n'): print (fg(0x30),'<< from tty:',fg(colindex),data) colindex += 1 if data==(b'F <freqmhz> <freq100Hz>\r\n'): break # all done, close tty print (fg(0x28),'** message sent correctly **\n') ser.close() def header(scr): scr = terminal.get_terminal(conEmu=False) scr.clear() scr.xterm256_set_fg_color(0x52) scr.xterm256_set_bk_color(0x08) scr.print_at(2,0,"rtn telecom : pagertest 1.00") scr.xterm256_set_bk_color(0) scr.gotoXY(2,3) scr.xterm256_set_fg_color(0x20) print('capcode:') scr.xterm256_set_bk_color(0x08) scr.xterm256_set_fg_color(0x78) scr.gotoXY(10,3) print(' ') scr.xterm256_set_bk_color(0) scr.gotoXY(20,3) scr.xterm256_set_fg_color(0x20) print('alert:') scr.xterm256_set_bk_color(0x08) scr.xterm256_set_fg_color(0x78) scr.gotoXY(26,3) print(' ') scr.xterm256_set_bk_color(0) scr.gotoXY(2,5) scr.xterm256_set_fg_color(0x20) print('message:') scr.xterm256_set_bk_color(0x08) scr.xterm256_set_fg_color(0x78) scr.gotoXY(10,5) print(' ') scr.xterm256_set_bk_color(0) scr.gotoXY(0,9) scr.xterm256_set_fg_color(0x28) # to be developed, input capcode def get_capcode(scr,default): pass # display capcode in input box def disp_capcode(scr,capcode): scr.xterm256_set_bk_color(0x08) scr.xterm256_set_fg_color(0x78) scr.gotoXY(10,3) print (str((b'%07d' % capcode),'utf-8')) scr.xterm256_set_bk_color(0) # display alert code in input box def disp_alert(scr,alert): scr.xterm256_set_bk_color(0x08) scr.xterm256_set_fg_color(0x78) scr.gotoXY(26,3) print (str((b'%01d' % alert),'utf-8')) scr.xterm256_set_bk_color(0) # display message in input box def disp_msg(scr,message): scr.xterm256_set_bk_color(0x08) scr.xterm256_set_fg_color(0x78) scr.gotoXY(10,5) print (str(message,'utf-8')) scr.xterm256_set_bk_color(0) scr.gotoXY(0,9) # # main code now starts here # # initialise the screen # # 2017-06-23: now accepts interactive input of message # # a blank line transmits the hardcoded message # # 'q' exits the code # while True: # refresh the header screen = terminal.get_terminal(conEmu=False) header(screen) # message now split into capcode, function (0-3), repeats # and 40 character bytearray # # hardcoded values # capcode = 20008 function = 2 repeats = 1 message = b'rtn: miauw naar de maan!<<<pagertest>>>' ttydev="/dev/ttyACM0" # display the capcode and alert that are currently hardcoded # but leave the msg box blank as it now accepts user input # disp_capcode(screen,capcode) disp_alert(screen,function) # # create a quick and dirty coloured prompt for the input # screen.gotoXY(2,7) screen.xterm256_set_fg_color(0x38) print('------>') screen.gotoXY(10,7) screen.xterm256_set_fg_color(0x68) # # this uses readline so has some basic editing functions # # anything over 40 character is clipped # ms1=input() if ms1 !='': message=ms1[0:40].encode('utf-8') if ms1 =='q': break # # display the msg in the top box and transmit it # disp_msg(screen,message) page(ttydev,capcode,function,repeats,message) # # terminate script and reset all the console colours # print (fg(0xc8),'\n++ Script completed sucessfully ++\n',res)
pagertest2.py
Dec 172016
 

code below

/*=========================================================================== * Serial Port Programming in C (Serial Port Write) * Non Cannonical mode * Program writes a character to the serial port at 19200 bps 8N1 format *--------------------------------------------------------------------------- * original Programmer : Rahul.S * Date : 21-December-2014 *============================================================================ * altered by : Alex the Engineer * rtn VFRmedia the Rat's nest * Ipswich GB * to work with x86 netbook connected to Sparkfun thermal printer * via USB-TTL serial converter * Date : 2016-05-29 * 2016-05-30 : code recompiled to ZX-SL91 * (old Tosh amd64 laptop with busted keyboard repurposed as mini * server * ---------------------------------------------------------------------------- * 2016-06-10 : sourcecode formatting cleaned up a bit *============================================================================== /*-------------------------------------------------------------*/ /* termios structure - /usr/include/asm-generic/termbits.h */ /* use "man termios" to get more info about termios structure */ /*-------------------------------------------------------------*/ #include <stdio.h> #include <fcntl.h> /* File Control Definitions */ #include <string.h> /* strings */ #include <termios.h> /* POSIX Terminal Control Definitions */ #include <unistd.h> /* UNIX Standard Definitions */ #include <errno.h> /* ERROR Number Definitions */ /* global vars - probably shouldn't be hardcoded like this */ /* and some should be #defines to save memory */ /* but better than sticking them into the sourcecode */ int bytes_written = 0; /* Buffer containing characters to write into port */ char *write_buffer = "\x1b@\n\n\n" "\x1b\x0ertn\n" "telecommunicatie\x1b\x14\n" "printertest ZX-SL91\n" "\nAchtung! Achtung!\n" "The Goose is Loose!\n" "\x1d\x48\x03\n"; char *msg2= "\x1b@" "rtn :miauw naar de maan!\n\n\n\n\n"; char *barcode128n= "\x1d\x6bI"; char *item1= "2815 doedelzak"; char *item2= "9502 asbak "; char *item3= "7281 snakeoil "; char *lin_adv= "\n"; int main(void) { int fd; /*File Descriptor*/ printf("\n +----------------------------------+"); printf("\n | Serial Port Write |"); printf("\n +----------------------------------+"); /*------------------------------- Opening the Serial Port ------*/ /* Change /dev/ttyUSB0 to the one corresponding to your system */ fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY | O_NDELAY); /* ttyUSB0 is the FT232 based USB2SERIAL Converter */ /* O_RDWR Read/Write access to serial port */ /* O_NOCTTY - No terminal will control the process */ /* O_NDELAY -Non Blocking Mode,Does not care about- */ /* -the status of DCD line,Open() returns immediatly */ if(fd == -1) { /* Error Checking */ perror("\n Error! in Opening ttyUSB0 "); return -1; } else perror("\n ttyUSB0 Opened Successfully "); /* set tty attrs 19200 8N1 */ struct termios SerialPortSettings; tcgetattr(fd, &SerialPortSettings); cfsetispeed(&SerialPortSettings,B19200); cfsetospeed(&SerialPortSettings,B19200); SerialPortSettings.c_cflag &= ~PARENB; SerialPortSettings.c_cflag &= ~CSTOPB; SerialPortSettings.c_cflag &= ~CSIZE; SerialPortSettings.c_cflag |= CS8; SerialPortSettings.c_cflag &= ~CRTSCTS; SerialPortSettings.c_cflag |= CREAD | CLOCAL; SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/ /* Set the attributes to the termios structure*/ if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) { perror ("\n ERROR! in set attrs"); return -1; } else printf("\n ttyUSB0 set to 19200-8N1\n"); bytes_written = str_send(fd,write_buffer); printf("\n Sending these 3 barcode:\n%s\n%s\n%s\n",item1,item2,item3); bytes_written += bc128_send(fd,item1); bytes_written += bc128_send(fd,item2); bytes_written += bc128_send(fd,item3); bytes_written += str_send(fd,msg2); printf("\n %d Bytes written to ttyUSB0", bytes_written); printf("\n +----------------------------------+\n\n"); close(fd);/* Close the Serial port */ } /* str_send : write string of bytes to the serial port */ /* specified by fd */ /* returns number of bytes written */ int str_send (int fd, char *msg) { return write(fd,msg,strlen(msg)); } /* bc128_send : send code128 barcode from string */ /* create code 128 barcode - Achtung! uses fixed length sequence */ /* with hardcoded length of 14 (0x0e) sent to printer */ /* which must be specified as a string even though it is only 1 byte */ /* or wrong data is sent down the line */ /* and the barcodes do not print */ int bc128_send (int fd, char *barcode) { int bcount = 0; bcount += write(fd,barcode128n,3); bcount += write(fd,"\x0e",1); bcount += write(fd,barcode,14); return bcount; }
printertest
Feb 062016
 

Since putting this project on Youtube I’ve had a surprising amount of interest from across the world about the modifications I made to the original code from ON1ARF ( a radioamateur in Belgiรซ) to allow 1200 and 2400 bps pager transmissions as well as the default 512bps (I wanted to use the circuit to test commercial POCSAG pager receivers used at one site at my work).

The original code is here

https://github.com/on1arf/pocsag

To get 1200 and 2400 bps you must alter the radiohead libraries it depends on.

Two files must change – the first is RH_RF22.cpp. The code snippet is below (cut and paste this into your editor)

// These are indexed by the values of ModemConfigChoice // Canned modem configurations generated with // http://www.hoperf.com/upload/rf/RH_RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls // Stored in flash (program) memory to save SRAM PROGMEM static const RH_RF22::ModemConfig MODEM_CONFIG_TABLE[] = { { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5 // All the following enable FIFO with reg 71 // 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72 // FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x22, 0x3a }, // 2.4, 36 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x22, 0x48 }, // 4.8, 45 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x22, 0x48 }, // 9.6, 45 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x22, 0x0f }, // 19.2, 9.6 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x22, 0x1f }, // 38.4, 19.6 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x22, 0x2e }, // 57.6. 28.8 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x22, 0xc8 }, // 125, 125 // { 0x2b, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x09, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x04, 0x32, 0x2c, 0x22, 0x04 }, // 512 baud, FSK, 2.5 Khz fd for POCSAG compatibility { 0x27, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x06, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x09, 0xd5, 0x2c, 0x22, 0x07 }, // 1200 baud, FSK, 4.5 Khz fd for POCSAG compatibility // { 0x27, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x06, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x04, 0x32, 0x2c, 0x22, 0x07 }, // 512 baud, FSK, 4.5 Khz fd for POCSAG compatibility // 2400 bps { 0x27, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x06, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x22, 0x07 },// 2400 baud, FSK, 4.5 Khz fd for POCSAG compatibility // GFSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm // These differ from FSK only in register 71, for the modulation type { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x23, 0x08 }, // 2, 5 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x23, 0x3a }, // 2.4, 36 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x23, 0x48 }, // 4.8, 45 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x23, 0x48 }, // 9.6, 45 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x23, 0x0f }, // 19.2, 9.6 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x23, 0x1f }, // 38.4, 19.6 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x23, 0x2e }, // 57.6. 28.8 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x23, 0xc8 }, // 125, 125 // OOK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm { 0x51, 0x03, 0x68, 0x00, 0x3a, 0x93, 0x01, 0x3d, 0x2c, 0x11, 0x28, 0x80, 0x60, 0x09, 0xd5, 0x2c, 0x21, 0x08 }, // 1.2, 75 { 0xc8, 0x03, 0x39, 0x20, 0x68, 0xdc, 0x00, 0x6b, 0x2a, 0x08, 0x2a, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x21, 0x08 }, // 2.4, 335 { 0xc8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x29, 0x04, 0x29, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x21, 0x08 }, // 4.8, 335 { 0xb8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x82, 0x29, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x21, 0x08 }, // 9.6, 335 { 0xa8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x41, 0x29, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x21, 0x08 }, // 19.2, 335 { 0x98, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x20, 0x29, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x21, 0x08 }, // 38.4, 335 { 0x98, 0x03, 0x96, 0x00, 0xda, 0x74, 0x00, 0xdc, 0x28, 0x1f, 0x29, 0x80, 0x60, 0x0a, 0x3d, 0x0c, 0x21, 0x08 }, // 40, 335 };
RH_RF22.cpp

Also the header file RH_RF22.h must change so the modemconfig table has values that reflect the changed modulation schemes.

typedef enum { UnmodulatedCarrier = 0, ///< Unmodulated carrier for testing FSK_PN9_Rb2Fd5, ///< FSK, No Manchester, Rb = 2kbs, Fd = 5kHz, PN9 random modulation for testing FSK_Rb2Fd5, ///< FSK, No Manchester, Rb = 2kbs, Fd = 5kHz FSK_Rb2_4Fd36, ///< FSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz FSK_Rb4_8Fd45, ///< FSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz FSK_Rb9_6Fd45, ///< FSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz FSK_Rb19_2Fd9_6, ///< FSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz FSK_Rb38_4Fd19_6, ///< FSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz FSK_Rb57_6Fd28_8, ///< FSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz FSK_Rb125Fd125, ///< FSK, No Manchester, Rb = 125kbs, Fd = 125kHz FSK_Rb_1200Fd4_5, ///< FSK, No Manchester, Rb = 1200bs, Fd = 4.5kHz, for POCSAG compatibility // FSK_Rb_512Fd4_5, ///< FSK, No Manchester, Rb = 512bs, Fd = 4.5kHz, for POCSAG compatibility FSK_Rb_2400Fd4_5, ///< FSK, No Manchester, Rb = 2400bs, Fd = 4.5kHz, for POCSAG compatibility GFSK_Rb2Fd5, ///< GFSK, No Manchester, Rb = 2kbs, Fd = 5kHz GFSK_Rb2_4Fd36, ///< GFSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz GFSK_Rb4_8Fd45, ///< GFSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz GFSK_Rb9_6Fd45, ///< GFSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz GFSK_Rb19_2Fd9_6, ///< GFSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz GFSK_Rb38_4Fd19_6, ///< GFSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz GFSK_Rb57_6Fd28_8, ///< GFSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz GFSK_Rb125Fd125, ///< GFSK, No Manchester, Rb = 125kbs, Fd = 125kHz OOK_Rb1_2Bw75, ///< OOK, No Manchester, Rb = 1.2kbs, Rx Bandwidth = 75kHz OOK_Rb2_4Bw335, ///< OOK, No Manchester, Rb = 2.4kbs, Rx Bandwidth = 335kHz OOK_Rb4_8Bw335, ///< OOK, No Manchester, Rb = 4.8kbs, Rx Bandwidth = 335kHz OOK_Rb9_6Bw335, ///< OOK, No Manchester, Rb = 9.6kbs, Rx Bandwidth = 335kHz OOK_Rb19_2Bw335, ///< OOK, No Manchester, Rb = 19.2kbs, Rx Bandwidth = 335kHz OOK_Rb38_4Bw335, ///< OOK, No Manchester, Rb = 38.4kbs, Rx Bandwidth = 335kHz OOK_Rb40Bw335 ///< OOK, No Manchester, Rb = 40kbs, Rx Bandwidth = 335kHz } ModemConfigChoice;
RH_RF22.h

the rest can then be used as normal – remember to alter the main Arduino sketch code to select these new bps rates.

NB: I am based in the UK/Europe; we always use wide deviation for POCSAG signals (although much other PMR traffic is now on narrow deviation).

If your country’s Communications Ministry requires narrow deviation to be used you will have to recalculate the modem settings using the spreadsheet referred to in the library files. (Its not as bad as it might seem; I had to use it to get the 1200/2400bps settings and I am not an RF nor a coding expert by any means)

 

Aug 082015
 

gcc can compile either c source or assembler (.s extension) or even a combination of both.

As I had the assembler source, decided to experiment with altering the string data (I don’t yet know enough to do anything else).

ARM asm source with some slight alterations

it still worked ๐Ÿ™‚

asm source output

note how the addresses of the array pointer change, as the strings have grown by a few characters…

below is the original code

WP_20150807_19_14_07_Rich

of course this is basic easy stuff; those strings are static/constant data and declared at compile time. if your code is dealing with strings that can change their length, it must always have sufficient free memory allocated to wherever the string data ends up, enough for the largest of the data. Otherwise you get a buffer overflow and your goose is cooked…

Aug 082015
 

I wanted to remind myself about C coding and how pointers work – never quite got my head round them at sons.

One of these was experimenting with C code so flawed it caused buffer overflows that crashed the kernel on multi user systems. That means the whole computer must be rebooted and other users would have their projects/data disrupted (it was in 1991, so a 32 bit machine was still known as a minicomputer and often used proprietary flavours of Unix and multiple users logged on using VT100 type terminals). I was already becoming disaffected with the place the profs thought I’d done it deliberately!

Todays Raspberry PI Model 2, placed in a suitable box (use a dark one as strong light can crash it due to a flaw in the chip design) is about the size of two packs of cigarettes; costs way less than they now do in the UK and is less unhealthy.

Aside: I can understand why younger people still smoke as I certainly did back then; but tobacco will knacker your insides and you become very ill as you get past your middle age. it has finished off a lot of my older friends on the electronics/radio scene. So at least try to stop with smoking when you get past age 30 if not before..

Back to the RPi – this amazing device is as powerful as the multi user computer I was using in 1991! The biggest advantage is if I screw up and hose the kernel it is only myself who gets affected by it. and I have done at least once, although most likely via accidental hard shutdowns i.e accidentally disconnecting the DC input whilst it is writing to the SD-card.

It is more tolerant of flawed code (I have made a silly mistake below; who can spot it?)

I used the console (having set the framebuffer font larger using sudo dpkg-reconfigure-console-setup as I couldn’t get the codeblocks debugger to play nicely and I find the GUI IDE more distracting when coding (probably because I am old ๐Ÿ˜‰ )

Tip: To get a console from X-windows on RPI press CTRL-ALT-F2, this opens a separate virtual terminal. (you can use CTRL-ALT-Fn) up to F6CTRL-ALT-F7 returns you to the X-window and CTRL-ALT-F1 has some odd error because it is in use as part of the X-windows system.

oeps

This version is better.

WP_20150807_18_59_49_Rich

It works.

WP_20150807_19_14_07_Rich

OK the code doesn’t do much but it reminds me that in C strings are an array of char, so each string has a char * to point to it. The contents of the char* are, as you would expect, a memory address where the string starts!

I then wanted to see what was going on at lower level, so used gdb. You must compile the code with gcc -g for the debugger to work.

WP_20150808_01_37_45_Rich

back in the day (1986-1990!) I even knew a bit about Assembler, but left high school just as Acorn ARM computers were available. So I thought I’d see if I could still remember any of it today. If you compile with gcc -S you get assembler code.

WP_20150808_01_40_53_Rich

this is what the source looks like, I can see the char* array, and its contents ๐Ÿ™‚

WP_20150808_01_43_02_Rich

This bit I do not quite understand as well yet but I can grasp the fact it is part of the main loop..

WP_20150808_01_44_09_Rich

Of course I need to learn much more about how ARM works (especially as you can only work with registers rather than put memory addresses directly in opcodes) and I am clearly no smarter than I was in my teens but at least my brain hasn’t deteriorated too much over the years ๐Ÿ™‚

 

PS: letting random geese loose in Groningen Netherlands (the message is partly in the Gronings dialect) is not just silly but (quite rightly) illegal under their animal welfare rules.

There would no one to look after it and there are plenty of stray ones already.

However if they were going to be otherwise eaten or put down and I’d arranged with the good folk at Akka’s Ganzenparadijs that the birdies had somewhere suitable to stay it would be a good deed. Emden geese aren’t that expensive (Emden is only just the other side in Germany anyway) and are cheaper alive than dead (a friend of mine farms them).

Although the Ganzenparadijs are a Buddhist animal sanctuary and I am baptised as a Catholic (not a very good one though); sparing the lives of these creatures to atone for someone else’s sin is the sort of thing many religions encourage.

I don’t expect this would get me to Heaven on a chariot towed by geese, but it would be sufficiently silly that all the various Gods would have a good laugh about it and I might even get one of those electric trolleys used at airports and large stations to haul the various heavy items through Purgatory required for the maintenance work I am tasked with.