;
;    Mecrimus-B - A firmware-only USB implementation for MSP430 microcontrollers
;    Copyright (C) 2012  Matthias Koch
;
;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;    (at your option) any later version.
;
;    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, see <http://www.gnu.org/licenses/>.
;  

; Synchronize to the pattern 01010100 on D- with 15 MHz
; Entry point for Interrupt


  ifdef 0 ; Prototyp zum Taktezählen, ohne Timeout  Prototype without timeout for counting cycles

  ; bit.b - beeinflusst Flags, aber ändert den Registerinhalt nicht.
  ; Ist wie and.b --> Wenn D- high ist, ist jnz der richtige Sprung.
  
  ; ----------------------- ; Warte, bis Low-Zustand da ist:
- bit.b @r9, r10   ;        
  ; <-- Sampling   ; (  9L 10L 11L 12L )
  jnz -            ; ( 10L 11L 12L  1H )
  ;                ; ( 11L 12L  1H  2H )
  ; ----------------------- ; Low detektiert. Warte, bis High-Zustand da ist:
- bit.b @r9, r11   ; ( 12L  1H  2H  3H )
  ; <-- Sampling   ; (  1H  2H  3H  4H )
  jz -             ; (  2H  3H  4H  5H )
  ;                ; (  3H  4H  5H  6H )
  ; ----------------------- ; Jetzt ist High da.
  
  endif

  ; Enter with interrupt triggered by low-to-high-transtion on D+
  ; This is required to not trigger syncing on Keep-Alive-SE0s.

  ; Idee: Jedes Bit ist 10 Takte lang in der Leitung
  ; Sync to the pattern 01010100 on D- 


  ; ---------------------------------------------------------------------------
    
Usb_Sync_Error_9_10_11_12:
  pop r12  
  pop r11
Usb_Sync_Error_9_10:  ; Error happened
  pop r10
  pop r9
  bic.b #usbplus, &P2IFG ; Clear interrupt pending bit to prevent an endless loop in case of false sync or Reset.
  reti
    
  
  ; ---------------------------------------------------------------------------
USB_Sync: ; Einsprung direkt nach Interrupt.  ; Entry Point
  push r9
  ;
  ;
  push r10
  ; 
  ;
  mov #usbin, r9
  ;
  
USB_quick_Resync:
  mov #usbminus, r10
  ; -----------------------
  bit.b @r9, r10      ;     ; Warte auf ein Low in D-
  ; <-- Sampling      ;  1
  jz +                ;  2
  ;                   ;  3
  bit.b @r9, r10      ;  4
  ; <-- Sampling      ;  5         Warte auf NULL in D-
  jz +                ;  6         Wait for Low in D-
  ;                   ;  7
  bit.b @r9, r10      ;  8
  ; <-- Sampling      ;  9
  jz +                ; 10
  ;                   ; 11
  bit.b @r9, r10      ; 12
  ; <-- Sampling      ; 13
  jnz Usb_Sync_Error_9_10  ;
  ;                   ;
+ ; ----------------------- ; Low detektiert  Low detected
  bit.b @r9, r10      ; 
  ; <-- Sampling      ;  1
  jnz +               ;  2
  ;                   ;  3
  bit.b @r9, r10      ;  4
  ; <-- Sampling      ;  5         Warte auf EINS in D-
  jnz +               ;  6         Wait for High in D-
  ;                   ;  7
  bit.b @r9, r10      ;  8
  ; <-- Sampling      ;  9
  jnz +               ; 10
  ;                   ; 11
  bit.b @r9, r10      ; 12
  ; <-- Sampling      ; 13
  jz Usb_Sync_Error_9_10  ;
  ;                   ; High detektiert, eingequetscht auf 4 Takte. High detected, synced within 4 cycles

+ ;   ------------>   ; (  3H  4H  5H  6H )  Verlasse das vorläufige Sync mit diesen Takten

  ; ----------------------- ; Erster Synchronisationsversuch  First try to sync precisely
  push r11            ; (  4H  5H  6H  7H )
  ;                   ; (  5H  6H  7H  8H )
  ;                   ; (  6H  7H  8H  9H )
  mov.b @r9, r10      ; (  7H  8H  9H 10H )    
  ; <-- Sampling      ; (  8H  9H 10H  1L ) 
  mov.b @r9, r11      ; (  9H 10H  1L  2L )
  ; <-- Sampling      ; ( 10H  1L  2L  3L )
  ; ----------------- ; (   |   |   |   | )
  bit #usbminus, r10  ; (  1L  2L  3L  4L )
  jnc +               ; (  2L  3L  4L  5L )
  ;                   ; (  3L  4L  5L  6L )
  bit #usbminus, r11  ; (  4L  5L  6L   | )
  jnc ++              ; (  5L  6L  7L   | )
  ;                   ; (  6L  7L  8L   | )
+ nop2                ; (  7L   |   |  7L )
  ;                   ; (  8L   |   |  8L )
+ ; ----------------- ; (                 )  Kantensampling abgeschlossen
  push r12            ; (  9L  8L  9L  9L )  Edge sampling finished
  ;                   ; (      9L 10L     )
  ;                   ; (     10L  1N     )
  nop                 ; (      1N  2N     )  
  mov @r9, r10        ; (      2N  3N     )  Prüfe, ob ich hier wirklich das Low der Doppelnull habe.
  ; <-- Sampling      ; (      3N  4N     )  Check, if this is really low for two bit times
  bit #usbminus, r10  ; (      4N  5N     )
  jnc Usb_Rec_Einlauf ; (      5N  6N     )
  ;                   ; (      6N  7N     )



  ; ----------------------- ; Zweiter Synchronisationsversuch  Second try to sync precisely
  nop2                ; (  5H  6H  7H  8H )  Erneuter Sync-Einlauf mit 7/8 führt zum Synchronisieren auf einen Takt.
  ;                   ; (  6H  7H  8H  9H )  Another syncinc run with entry on 7/8 leads to sync with one cycle accuracy.
  mov.b @r9, r10      ; (  7H  8H  9H 10H )    
  ; <-- Sampling      ; (  8H  9H 10H  1L ) 
  mov.b @r9, r11      ; (  9H 10H  1L  2L )
  ; <-- Sampling      ; ( 10H  1L  2L  3L )
  ; ----------------- ; (   |   |   |   | )
  bit #usbminus, r10  ; (  1L  2L  3L  4L )
  jnc +               ; (  2L  3L  4L  5L )
  ;                   ; (  3L  4L  5L  6L )
  bit #usbminus, r11  ; (  4L  5L  6L   | )
  jnc ++              ; (  5L  6L  7L   | )
  ;                   ; (  6L  7L  8L   | )
+ nop2                ; (  7L   |   |  7L )
  ;                   ; (  8L   |   |  8L )
+ ; ----------------- ; (                 )  Kantensampling abgeschlossen
  nop2                ; (  9L  8L  9L  9L )  Edge sampling finished
  ;                   ; (      9L 10L     )
  nop2                ; (     10L  1N     )
  ;                   ; (      1N  2N     )
  mov @r9, r10        ; (      2N  3N     )  Prüfe, ob ich hier wirklich das Low der Doppelnull habe.
  ; <-- Sampling      ; (      3N  4N     )  Check, if this is really low for two bit times
  bit #usbminus, r10  ; (      4N  5N     )
  jnc Usb_Rec_Einlauf ; (      5N  6N     )
  ;                   ; (      6N  7N     )



  ; ----------------------- ; Dritter und letzter Synchronisationsversuch  Third and last try to sync precisely
  nop2                ; (  5H  6H  7H  8H )  Erneuter Sync-Einlauf mit 7/8 führt zum Synchronisieren auf einen Takt.
  ;                   ; (  6H  7H  8H  9H )  Another syncinc run with entry on 7/8 leads to sync with one cycle accuracy.
  mov.b @r9, r10      ; (  7H  8H  9H 10H )    
  ; <-- Sampling      ; (  8H  9H 10H  1L ) 
  mov.b @r9, r11      ; (  9H 10H  1L  2L )
  ; <-- Sampling      ; ( 10H  1L  2L  3L )
  ; ----------------- ; (   |   |   |   | )
  bit #usbminus, r10  ; (  1L  2L  3L  4L )
  jnc +               ; (  2L  3L  4L  5L )
  ;                   ; (  3L  4L  5L  6L )
  bit #usbminus, r11  ; (  4L  5L  6L   | )
  jnc ++              ; (  5L  6L  7L   | )
  ;                   ; (  6L  7L  8L   | )
+ nop2                ; (  7L   |   |  7L )
  ;                   ; (  8L   |   |  8L )
+ ; ----------------- ; (                 )  Kantensampling abgeschlossen
  nop2                ; (  9L  8L  9L  9L )  Edge sampling finished
  ;                   ; (      9L 10L     )
  nop2                ; (     10L  1N     )
  ;                   ; (      1N  2N     )
  mov @r9, r10        ; (      2N  3N     )  Prüfe, ob ich hier wirklich das Low der Doppelnull habe.
  ; <-- Sampling      ; (      3N  4N     )  Check, if this is really low for two bit times
  bit #usbminus, r10  ; (      4N  5N     )
  jc Usb_Sync_Error_9_10_11_12   ; (      5N  6N     )
  ;                   ; (      6N  7N     )


Usb_Rec_Einlauf:
  nop2                ; (      7N  8N     )  Sync is finished. Prepare to run into receiver !
  ;                   ; (      8N  9N     )
  toggle_syncled      ; (      9N 10N     )
  ;                   ; (     10N  1B     )
  ;                   ; (      1B  2B     )
  ; <-- Wechsel       ; (      2B  3B     )  Syncled is electrically toggled now.
  ; ---------------------------------------  Einlauf. Entry in receiver now.
  ; mov @r9, ...      ; (      3B  4B     )
  ; <-- Sampling      ; (      4B  5B     )
