#!/usr/bin/python

# Copyright (C) 2007 Jan Luebbe <jluebbe@lasnet.de>
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import pexpect, re

class OCD(object):
  def __init__(self):
    self.child = pexpect.spawn('telnet localhost 4444')
    self.child.expect(r'>\ ')

  def run(self, cmd):
    self.child.sendline(cmd)
    self.child.sendline('')
    self.child.expect(r'\x00>\ \s+\x00>\ ')
    return re.sub('\x00', '', self.child.before)[len(cmd)+2:]

  def readMem(self, addr, size):
    if size == 8:
      result = self.run('arm920t mdb_phys 0x%x' % (addr,))
    elif size == 16:
      result = self.run('arm920t mdh_phys 0x%x' % (addr,))
    elif size == 32:
      result = self.run('arm920t mdw_phys 0x%x' % (addr,))
    else:
      raise "readMem: invalid size (%i)" % (size,)
    return int(result.split(':')[1].strip(), 16)

  def writeMem(self, addr, value, size):
    if size == 8:
      self.run('arm920t mwb_phys 0x%x 0x%x' % (addr, value))
    elif size == 16:
      self.run('arm920t mwh_phys 0x%x 0x%x' % (addr, value))
    elif size == 32:
      self.run('arm920t mww_phys 0x%x 0x%x' % (addr, value))
    else:
      raise "readMem: invalid size (%i)" % (size,)

def toBinary(x, size):
  return [bool((x>>i) & 0x01) for i in range(size)]

def fromBinary(x, size):
  assert (len(x)==size)
  return sum([x[i]<<i for i in range(size)])

class Field(object):
  def __init__(self, ocd, raddr, rsize, lbit, ubit):
    self.ocd = ocd
    self.raddr = raddr
    self.rsize = rsize
    self.lbit = lbit
    self.ubit = ubit
  def set(self, value):
    x = toBinary(self.ocd.readMem(self.raddr, self.rsize), self.rsize)
    x[self.lbit:self.ubit+1] = toBinary(value, self.ubit-self.lbit+1)
    self.ocd.writeMem(self.raddr, fromBinary(x, self.rsize), self.rsize)
  def get(self):
    x = toBinary(self.ocd.readMem(self.raddr, self.rsize), self.rsize)
    return fromBinary(x[self.lbit:self.ubit+1], self.ubit-self.lbit+1)

