7
 
pygtk.require( '2.0' );
 
8
 
import gtk, serial, struct
 
15
 
        # number of channels to read
 
18
 
        # number of motor channels
 
21
 
        # maximum channel value
 
22
 
        MAX_CHANNEL_VALUE = 1000
 
24
 
        # serial device to use
 
25
 
        SERIAL_DEVICE = '/dev/ttyUSB0'
 
30
 
                        self.link = serial.Serial( self.SERIAL_DEVICE, 9600 )
 
31
 
                        self.link_error = None
 
32
 
                except serial.serialutil.SerialException as e:
 
36
 
                self.motor_values = [ 0 ] * self.NUM_MOTORS
 
38
 
                self.buffer = bytearray()
 
41
 
        def add_info( self, vbox, heading = False, text = '' ):
 
44
 
                        label.set_markup( "<b>%s</b>" % text )
 
46
 
                        label.set_label( text )
 
47
 
#               label.set_justify( gtk.JUSTIFY_LEFT )
 
48
 
                label.set_alignment( 0, 0 )
 
49
 
                vbox.pack_start( label, False, False )
 
51
 
        def setup_window( self ):
 
53
 
                # create and set up window
 
54
 
                self.window = gtk.Window( gtk.WINDOW_TOPLEVEL )
 
55
 
                self.window.connect( "delete_event", self.destroy )
 
56
 
                self.window.connect( "destroy", self.destroy )
 
57
 
                self.window.set_title( "Testing rc-interface serial comms" );
 
58
 
                self.window.set_border_width( 30 )
 
59
 
                self.window.set_modal( True )
 
60
 
                self.window.connect( "key-press-event", self.key_press_event )
 
62
 
                hbox = gtk.HBox( False, 10 )
 
63
 
                self.window.add( hbox )
 
66
 
                frame = gtk.Frame( "Channels" )
 
67
 
                frame.set_shadow_type( gtk.SHADOW_IN )
 
68
 
                hbox.pack_start( frame )
 
70
 
                table = gtk.Table( 2, self.NUM_CHANNELS )
 
71
 
                table.set_border_width( 25 )
 
72
 
                table.set_row_spacings( 10 )
 
73
 
                table.set_col_spacings( 15 )
 
78
 
                for a in range( self.NUM_CHANNELS ):
 
80
 
                        label = gtk.Label( a + 1 )
 
81
 
                        table.attach( label, a, a + 1, 1, 2 )
 
83
 
                        adj = gtk.Adjustment( 0, 0, self.MAX_CHANNEL_VALUE, 1, 0, 0 )
 
84
 
                        control = gtk.VScale( adj )
 
85
 
                        control.set_draw_value( False )
 
86
 
                        control.set_inverted( True )
 
87
 
                        control.set_size_request( -1, 200 )
 
88
 
                        control.set_sensitive( False )
 
89
 
                        table.attach( control, a, a + 1, 0, 1 )
 
91
 
                        self.controls.append( control )
 
94
 
                frame = gtk.Frame( "Motors" )
 
95
 
                frame.set_shadow_type( gtk.SHADOW_IN )
 
96
 
                hbox.pack_start( frame )
 
98
 
                table = gtk.Table( 2, self.NUM_MOTORS )
 
99
 
                table.set_border_width( 25 )
 
100
 
                table.set_row_spacings( 10 )
 
101
 
                table.set_col_spacings( 15 )
 
106
 
                for a in range( self.NUM_MOTORS ):
 
108
 
                        label = gtk.Label( a + 1 )
 
109
 
                        table.attach( label, a, a + 1, 1, 2 )
 
111
 
                        adj = gtk.Adjustment( 0, 0, self.MAX_CHANNEL_VALUE, 1, 0, 0 )
 
112
 
                        control = gtk.VScale( adj )
 
113
 
                        control.set_draw_value( False )
 
114
 
                        control.set_inverted( True )
 
115
 
                        control.set_size_request( -1, 200 )
 
116
 
                        table.attach( control, a, a + 1, 0, 1 )
 
118
 
                        control.connect( "value-changed", self.on_motor_change, a )
 
120
 
                        self.motors.append( control )
 
123
 
                frame = gtk.Frame( "Info" )
 
124
 
                hbox.pack_start( frame )
 
127
 
                vbox.set_border_width( 10 )
 
130
 
                self.add_info( vbox, True, "USB Device:" )
 
131
 
                self.add_info( vbox, False, self.SERIAL_DEVICE )
 
132
 
                self.add_info( vbox )
 
134
 
                if( self.link_error is not None ):
 
135
 
                        self.add_info( vbox, True, "USB Error:" )
 
136
 
                        label = gtk.Label( self.link_error )
 
137
 
                        label.set_line_wrap( True )
 
138
 
                        label.set_size_request( 150, -1 )
 
139
 
                        vbox.pack_start( label, False )
 
143
 
                vbox.pack_start( gtk.Label( "" ) )
 
146
 
                self.window.show_all()
 
149
 
        def on_motor_change( self, widget, motor ):
 
150
 
                self.motor_values[ motor ] = int( widget.get_value() )
 
154
 
        def key_press_event( self, widget, event ):
 
155
 
                if event.keyval == gtk.keysyms.Escape:
 
156
 
                        self.window.destroy()
 
161
 
        def destroy( self, widget, data = None ):
 
165
 
        def process_serial_data_at( self, pos ):
 
166
 
                for a in range( self.NUM_CHANNELS ):
 
168
 
                        value = struct.unpack( "h", self.buffer[ at : at + 2 ] )[ 0 ]
 
171
 
                        self.controls[ a ].set_value( value )
 
174
 
        def read_serial( self ):
 
177
 
                if self.link is None: return
 
180
 
                in_waiting = self.link.inWaiting()
 
182
 
                        self.buffer.extend( self.link.read( in_waiting ) )
 
184
 
                        # check buffer for double -1
 
187
 
                        while i < len( self.buffer ):
 
189
 
                                # check foir double -1
 
190
 
                                if i > 0 and self.buffer[ i ] == 255 and \
 
191
 
                                                self.buffer[ i - 1 ] == 255:
 
193
 
                                        # if we've got enough data, process it
 
194
 
                                        start_index = i - ( self.NUM_CHANNELS * 2 + 1 )
 
196
 
                                                self.process_serial_data_at( start_index )
 
198
 
                                        # remove everything up to and including this double -1 from
 
200
 
                                        self.buffer = self.buffer[ i + 1 : ]
 
207
 
        def write_serial( self ):
 
210
 
                if self.link is None: return
 
214
 
                bytes.extend( struct.pack( "h", -1 ) )
 
215
 
                for i in range( self.NUM_MOTORS ):
 
216
 
                        bytes.extend( struct.pack( "h", self.motor_values[ i ] ) )
 
219
 
                self.link.write( bytes )
 
227
 
                        while gtk.events_pending():
 
228
 
                                gtk.main_iteration( False )
 
230
 
                        # check serial interface
 
234
 
MainDialogue().main()