STK500.java 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package nl.digitalthings.mebarista;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.util.Arrays;
  6. public class STK500 {
  7. private OutputStream outStream = null;
  8. private InputStream inputStream = null;
  9. Logx log;
  10. public STK500( InputStream i, OutputStream o, Logx l ) {
  11. outStream = o;
  12. inputStream = i;
  13. log = l;
  14. }
  15. private byte[] sync ( String operation, int n, byte[] data ) throws IOException {
  16. outStream.write(data);
  17. return sync( operation, n );
  18. }
  19. private byte[] sync ( String operation, byte[] data ) throws IOException {
  20. outStream.write(data);
  21. return sync( operation, 0 );
  22. }
  23. private byte[] sync ( String operation, int n ) throws IOException {
  24. outStream.flush();
  25. int insync = inputStream.read();
  26. byte[] res = null;
  27. if( n > 0 ) {
  28. res = new byte[n];
  29. inputStream.read( res, 0, n );
  30. }
  31. int ok = inputStream.read();
  32. boolean syn = insync == 0x14 && ok == 0x10;
  33. if( !syn ) {
  34. log.logcat("not in sync: " + operation, "v");
  35. throw new IOException("not in sync: " + operation);
  36. }
  37. while( inputStream.available() > 0 )
  38. inputStream.read();
  39. return res;
  40. }
  41. // Inspired by https://github.com/robokoding/STK500
  42. public void main ( byte[] program ) throws IOException {
  43. // Consume anything in input stream
  44. while (inputStream.available() > 0)
  45. inputStream.read();
  46. sync("initial sync", new byte[] { 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20 } );
  47. int minor = sync( "minor version", 1, new byte[] { 0x41, (byte) 0x82, 0x20 } )[0];
  48. int major = sync( "major version", 1, new byte[] { 0x41, (byte) 0x81, 0x20 } )[0];
  49. log.logcat( "version: " + major + "." + minor, "v" );
  50. sync( "enter programming mode", new byte[] { 0x50, 0x20 } );
  51. byte[] signature = sync( "device signature", 3, new byte[] { 0x75, 0x20 } );
  52. log.logcat( "signature: " + String.format( "%02X", signature[0] ) + String.format( "%02X", signature[1] ) + String.format( "%02X", signature[2] ), "v" );
  53. log.logcat( "flashing: please wait ...", "v" );
  54. int programIndex = 0;
  55. int pages_per_ten_percent = program.length / 128 / 10;
  56. int pages_programmed = 0;
  57. while ( programIndex < program.length ) {
  58. int size = Math.min( program.length - programIndex, 128 );
  59. sync( "load page address " + programIndex, new byte[]{0x55, (byte) ((programIndex / 2) % 256), (byte) ((programIndex / 2) / 256), 0x20});
  60. outStream.write( new byte[] { 0x64, 0x00, (byte)size, 0x46 } );
  61. outStream.write( Arrays.copyOfRange( program, programIndex, programIndex + size ) );
  62. sync( "write page at " + programIndex, new byte[]{0x20} );
  63. programIndex += size;
  64. pages_programmed++;
  65. if( pages_programmed % pages_per_ten_percent == 0 )
  66. log.logcat("" + (int)( pages_programmed / pages_per_ten_percent * 10 ) + "%", "v" );
  67. }
  68. sync( "leave programming mode", new byte[] { 0x51, 0x20 } );
  69. log.logcat("Programmed " + programIndex + " of " + program.length + " bytes", "v");
  70. }
  71. }