;
;    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/>.
;  


; Taktunabhängige Teile der Empfangsroutine
; Frequency independent parts of receiver

  ; ---------------------------------------------------------------------------
  ; Paketende SE0:  End of packet detected.
  ; ---------------------------------------------------------------------------
usb_se0:  ; Komme mit [7] hier an !

  bic.b #usbplus, &P2IFG ; Interrupt-Pending-Flag löschen. Gleich nach SE0 und nach dem Senden. 
  ;                      ; Das Wiederansteigen von SE0 auf J triggert keinen Interrupt.
 
  mov.b r14, @r15 ; [8] :-)  Das letzte Datenbyte vermerken !!     Store last Databyte in Buffer
                  ; [9]
                  ;[10]
 
  mov &Receivebufferpointer, r14            ;  [1]    Fetch bufferpointer
  ;                                         ;  [2]
  ;                                         ;  [3]
  sub r14, r15  ; Paketlänge bestimmen      ;  [4]    Calculate length of received packet
  mov.b r15, @r14                           ;  [5]    Store length like in a counted string
  ;                                         ;  [6]
  ;                                         ;  [7]
  
  toggle_syncled ; Finished. Toggle syncled again, to see on oscilloscope if SE0 detection missed its job due to wrong sync.
    
;------------------------------------------------------------------------------      
  mov.b 1(r14), r10  ; PID holen      Fetch PID of packet for further investigation.
  mov.b 2(r14), r11  ; Adresse holen  Fetch field that may contain address
  mov.b 3(r14), r12  ; Endpunkt holen Fetch field that may contain endpoint
;------------------------------------------------------------------------------
  bit #080h, r11 ; Fetch LSB bit of endpoint
  rlc r12        ; Rotate that bit in
  and #00Fh, r12 ; Remove CRC5 from endpoint
  
  bic #080h, r11 ; Clear Endpoint bit in address  
;------------------------------------------------------------------------------
  
  cmp #usb_pid_in, r10
  jne usb_in_finished
  
    ; Für mich ? For me ?
    cmp.b r11, &Current_Address
    jne usb_pop_and_finish
  
    cmp #1, r12 ; Prüfe den Endpunkt ! Check endpoint !
    jne +
      mov &ReadyforTransmit_Irq_in, r15  ; Zeiger für ausgehende Daten holen  Fetch pointer for outgoing packets for Irq-In endpoint
      clr &ReadyforTransmit_Irq_in       ; Puffer wieder auffüllbereit.       Buffer ready for refill
      jmp ++
  
+   mov &ReadyforTransmit, r15  ; Zeiger für ausgehende Daten holen    Fetch pointer for outgoing packets
    clr &ReadyforTransmit       ; Puffer wieder auffüllbereit.         Buffer ready for refill
    
+   cmp #0, r15                 ; Ist etwas vorhanden ?                Something inside ?
    jne +
      mov #usb_paket_nak, r15   ; Ansonsten ein NAK-Paket senden.      If not, send NAK
+
 
    mov &New_Address, &Current_Address ; Adressänderungen werden nach dem Status Stage übernommen. Tue dies hier !
    jmp usb_transmit                   ; Address changes are committed after Status Stage. Do this here !
    
usb_in_finished:
;------------------------------------------------------------------------------  
  
  cmp #usb_pid_out, r10
  je +
  cmp #usb_pid_setup, r10
  jne ++  
  
+   ; Für mich ? For me ?
    cmp.b r11, &Current_Address
    jne usb_pop_and_finish
        
      mov.b r10, &Datapacketbuffer+15 ; PID vermerken  Save PID
      mov #Datapacketbuffer, &ReceiveBufferPointer ; Zum Empfang bereitmachen !  Get ready to receive data with destination "me"
      jmp usb_pop_and_finish
+        
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; Alles Weitere nur, wenn dies Paket für mich ist und der Empfangspuffer bereits gesetzt wurde.
; Do this only if the packet was for me and the receive pointer has been set accordingly.
  cmp #Datapacketbuffer, &ReceiveBufferPointer
  jne usb_pop_and_finish
  ; Es ist für mich. Nimm es an !       This is for me ! Accept it.
  ; Schalte schonmal den Puffer zurück: Switch back receive buffer
  mov #Tokenpacketbuffer, &ReceiveBufferPointer
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
  cmp #usb_pid_data0, r10
  je +  
  cmp #usb_pid_data1, r10
  jne ++  
  
+   mov #usb_paket_ack, r15
    jmp usb_transmit
+ 
;------------------------------------------------------------------------------
  
usb_pop_and_finish:  
  pop r8
  pop r15
  pop r14
  pop r13
  pop r12
  pop r11
                         ; Is there already the next packet in the line ?
  bit.b #usbplus, &P2IFG ; Kommt bereits das nächste Paket ? (Oder umgekehrt, um Takte zu sparen ?)
  jc USB_quick_Resync    ; Wenn ja, sofort empfangen. Der Einsprung geht nur, wenn r9 nicht verändert wurde. 
                         ; Catch it immediately ! This entry point is only possible if r9 is not changed.
  pop r10                 
  pop r9
                          ; Next packet now in line ?
  bit.b #usbplus, &P2IFG  ; Kommt bereits das nächste Paket ? (Oder umgekehrt, um Takte zu sparen ?)
  jc USB_Sync             ; Wenn ja, sofort empfangen  If yes, catch it. Else handle it with another interrupt. 
  reti                    ; Sonst ausspringen und in einem neuen Interrupt bearbeiten.

        
          ; Rücksprung in die Synchronisation ! Das neue Paket beginnt ziemlich bald.
          ; Mindestwartezeit: 2 Bitzeiten = 20 Takte. Weiterhin kann ich die ersten Bits des Syncs überspringen...
          ; Muss hier noch Proben einfügen, ob gleich ein nächstes Paket kommt, was bei Setup und Out der Fall ist.
          ; Bei IN habe ich 6.5 oder 7.5 Bitzeiten Ruhe, und somit noch ein bisschen Luft.

          ; Next paket may follow in 2 bittimes = 20 cycles.
          ; If I have to reply, I have 6.5 to 7.5 bittimes maximum until I have to transmit my answer.
          ; So I should check first if I have to receive some more...
          ; Note that we can take up some time of the sync pattern, as we need only the second half "0100" of it...

 
