Wiki VMAC PiHat v2 OSD

HAMKit Wiki Repository
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
Filter by Categories
 HAMKit Wiki
News and Information
RasDuinoHat
Raspberry Pi
Standard Page
VDAS
VMAC PiHat v1
VMAC PiHat v2

    The HAMKit VMAC PiHat features an on-board, tried and trusted,  MAX7456  single-channel monochrome on-screen display (OSD) generator.

    The MAX7456 serves all national and international markets with 256 user-programmable characters in both NTSC and PAL standards. The MAX7456 easily displays information such as company logo, custom graphics, time, and date with arbitrary characters and sizes. The MAX7456 is preloaded with 256 characters and pictographs and can be reprogrammed in-circuit using the SPI port.

    Using the HAMKit VMAC PiHat video matrix, we are able to take any input to the matrix, map this into the OSD, then take the OSD video output and map to any matrix video output.

    Key OSD Features

    • 256 User-Defined Characters or Pictographs in Integrated EEPROM
    • 12 x 18 Pixel Character Size
    • Blinking, Inverse, and Background Control Character Attributes
    • Selectable Brightness by Row
    • Displays Up to 16 Rows x 30 Characters (PAL)
    • Sag Compensation On Video-Driver Output
    • LOS, Active-Low VSYNC, Active-Low HSYNC, and Clock Outputs
    • Internal Sync Generator
    • NTSC and PAL Compatible
    • SPI-Compatible Serial Interface
    • Preprogrammed Character Set

    In the below test code

    • Video Input 1, is mapped to the OSD input.  The OSD output is then mapped to Video Out 1
    • Video Input 1, is mapped to the Video Out 2 as a straight thru clean video test
    • The OSD IC is enabled and setup to display a basic test page
    • Any video on input 1 will get super-imposed OSD text and displayed on output 1.  With no OSD on output 2

    Example output from the below test code

    # Example of matrix mapping
    # Video 1 Input to OSD Input 0x07 0x81 
    # OSD Output to Video 1 Output 0x01 0x86
    ...
    i2cbus.write_byte_data(DEVICE_ADDR, 0x07, 0x81) #Input 1 to OSD In 
    i2cbus.write_byte_data(DEVICE_ADDR, 0x01, 0x86) #Input OSD to Output 1

    All of our sample and test code is developed in Python.

    # HAMKit VMAC PiHat v2.3 - Test OSD - Dave Williams G8PUO
    # Setup matrix input and outputs, enable OSD and display a test page
    # Video 1 Input to OSD Input 0x07 0x81
    # OSD Output to Video 1 Output 0x01 0x86
    # Video 1 Input to Video 2 Output 0x03 0x81 (Thru Video Test)
    # July 2018.  Thanks to Paul Theunissen, PA5PT, for OSD code template
    #!/usr/bin/python
    
    import smbus
    import RPi.GPIO as GPIO
    import spidev
    import time
    from ctypes import *
    
    #====== GPIO
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    #GPIO.cleanup()
    
    #Define GPIO Outputs
    LEDStatus = 22
    PTT = 27
    OSD_RST = 25
    
    #Setup Outputs
    GPIO.setup(LEDStatus,GPIO.OUT)
    GPIO.setup(PTT,GPIO.OUT)
    GPIO.setup(OSD_RST,GPIO.OUT)
    
    #Initiate LEDs
    GPIO.output(LEDStatus,GPIO.HIGH)
    GPIO.output(PTT,GPIO.HIGH)
    time.sleep(0.5)
    GPIO.output(LEDStatus,GPIO.LOW)
    GPIO.output(PTT,GPIO.LOW)
    time.sleep(0.5)
    
    #====== FMS6501 Matrix
    
    #define values
    DEVICE_BUS = 1
    DEVICE_ADDR = 0x43 #0x43 or 0x03
    
    #setup i2c bus
    i2cbus = smbus.SMBus(DEVICE_BUS)
    
    #OSD REset High
    GPIO.output(OSD_RST,GPIO.HIGH)
    
    def PowerDownPorts():
        print ("PowerDownPorts")
        i2cbus.write_byte_data(DEVICE_ADDR, 0x01, 0x0) #Mute
        time.sleep(.01)
        i2cbus.write_byte_data(DEVICE_ADDR, 0x03, 0x0) #Mute
        time.sleep(.01)
        i2cbus.write_byte_data(DEVICE_ADDR, 0x06, 0x0) #Mute
        time.sleep(.01)
        i2cbus.write_byte_data(DEVICE_ADDR, 0x07, 0x0) #Mute
        time.sleep(.01)
        i2cbus.write_byte_data(DEVICE_ADDR, 0x08, 0x0) #Mute
        time.sleep(.01)	
        i2cbus.write_byte_data(DEVICE_ADDR, 0x09, 0x0) #Mute
        time.sleep(.01)                  
    
    #Disable and Powerdown Matrix Outputs
    PowerDownPorts()
    
    # Setup Matrix Video Switching
    i2cbus.write_byte_data(DEVICE_ADDR, 0x1d, 0xff) #clamp
    i2cbus.write_byte_data(DEVICE_ADDR, 0x1e, 0xff) #clamp
    i2cbus.write_byte_data(DEVICE_ADDR, 0x07, 0x81) #Input 1 to OSD In
    i2cbus.write_byte_data(DEVICE_ADDR, 0x01, 0x86) #Input OSD to Output 1
    i2cbus.write_byte_data(DEVICE_ADDR, 0x03, 0x81) #Input 1 to Output 2
    
    #OSD MAX7456
    class max7456():
        # Create a SPI
        spi = spidev.SpiDev() 
    
        # MAX7456 opcodes
        VM0_reg  = 0x00
        VM1_reg  = 0x01
        HOS_reg  = 0x02
        VOS_reg  = 0x03
        DMM_reg  = 0x04
        DMAH     = 0x05
        DMAL     = 0x06
        DMDI     = 0x07
        OSDM     = 0x0C
        RB0      = 0x10
        HOS_reg  = 0x02
        STATUS   = 0xA0
    
        # PAL - VM0_reg commands
        ENABLE_display      = 0x48
        ENABLE_display_vert = 0x4c
        MAX7456_reset       = 0x42
        DISABLE_display     = 0x40
    
        # Read command
        READ = 0x80
        MAX_screen_rows = 16
    
        # White levels
        WHITE_level_80  = 0x03
        WHITE_level_90  = 0x02
        WHITE_level_100 = 0x01
        WHITE_level_120 = 0x00
    
        chars = {' ':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9,
            '0':10, 'A':11, 'B':12, 'C':13, 'D':14, 'E':15, 'F':16, 'G':17, 'H':18, 'I':19,
            'J':20, 'K':21, 'L':22, 'M':23, 'N':24, 'O':25, 'P':26, 'Q':27, 'R':28, 'S':29,
            'T':30, 'U':31, 'V':32, 'W':33, 'X':34, 'Y':35, 'Z':36, 'a':37, 'b':38, 'c':39,
            'd':40, 'e':41, 'f':42, 'g':43, 'h':44, 'i':45, 'j':46, 'k':47, 'l':48, 'm':49,
            'n':50, 'o':51, 'p':52, 'q':53, 'r':54, 's':55, 't':56, 'u':57, 'v':58, 'x':59,
            'y':60, 'z':61, '(':62, ')':63, '.':64, '?':65, ';':66, ':':67, ',':68, '\'':69,
            '/':70, '"':71, '-':72, '<':73, '>':74, '@':75, '\xa9':76
        }
    
        def __init__(self):
            # Open a SPI port - max7456 connected on SPI0
            self.spi.open(0, 0)
            self.spi.max_speed_hz = 1000000
            self.spi.bits_per_word = 8
            self.spi.cshigh = False
            self.spi.lsbfirst = False
            self.spi.mode = 0
      
            # On init, reset max7456
            self.reset()
    
            # Set all rows at the same white level
            for x in range (0, self.MAX_screen_rows):
              self.spi.xfer2([(self.RB0 + x), self.WHITE_level_90])
    
            # Enable max7456
            self.spi.xfer2([self.VM0_reg, self.ENABLE_display]);
    
        def printStr(self, X, Y, string, enable = True):
            disp = []
            for char in string:
                     disp.append(self.chars[char])
    
            print (string)
    
            if enable == False:
                self.spi.xfer([self.VM0_reg, self.Disable_display])
            
            # Enable 8 bit mode:
            dmm = self.spi.xfer2([self.DMM_reg + self.READ, 0x00])
            dmm = self.setBit(dmm[1], 6)
            self.spi.xfer2([self.DMM_reg, dmm])
    
            start = X * 30 + Y
            
            # Clear position
            self.spi.xfer2([self.DMAH, 0x00])
            self.spi.xfer2([self.DMAL, 0x00])
    
            for char in disp:
                # Write char
                dmah = self.spi.xfer2([self.DMAH + self.READ, 0x00])
                dmah = self.clearBit(dmah[1], 1)
                self.spi.xfer2([self.DMAH, dmah])
    
                dmah_pos = ((start >> 8) & 0x01)
                dmal = (start & 0xff)
                dmah = dmah | dmah_pos
                start = start + 1
    
                # Select MSB
                self.spi.xfer2([self.DMAH, dmah])
                self.spi.xfer2([self.DMAL, dmal])
            
                self.spi.xfer2([self.DMDI, (char)])
    
        def reset(self):
            self.spi.xfer2([self.VM0_reg, self.MAX7456_reset])
            time.sleep(0.1)
            while True:
                r = self.spi.xfer([self.STATUS, 0x00])
                stable = self.testBit(r[1], 1)
                if stable == 0:
                    print ("Reset MAX7456 Ok...")
                    break 
                break
    
        def testBit(self, value, offset):
            mask = 1 << value
            return(value & mask)
     
        def setBit(self, value, offset):
            mask = 1 << offset
            return(value + mask)
    
        def clearBit(self, int_type, offset):
            mask = ~(1 << offset)
            return(int_type & mask)
        
    try:
        max7456 = max7456()
        
        #Display OSD Text
        max7456.printStr(2,5, "VMAC Tesing 1 2 3 4", enable = True)
        max7456.printStr(5,5, "OSD Test ABCDEFGHIJ", enable = True)
        max7456.printStr(9,1, "1234567890123456789012345678", enable = True)
        max7456.printStr(13,5, "HAMKit VMAC PiHat v2", enable = True)
        
    except KeyboardInterrupt:
        spi.close() 
    
    
    

    Further details on the configuration and test code can be found in other Wiki pages.  Also see programming and developing in Python.


    Please feel free to share our product love through the below