:::: MENU ::::

Supercharge your MacBook Pro 2013-2015 with M.2 NVME Drive

It’s been a while since I posted anything. I was busy with my work and didn’t get time to publish anything. Today, I am going to show you how you can supercharge your MacBook by making use of Apple’s support for NVMe drives beginning with the MacOS X Yosemite 10.10.3. Even though they added support since this version, I would recommend you update your mac to latest MacOS Catalina (10.15 as of today).

Most of the content here is borrowed from this link at MacRumors. I am just trying to simplify the whole process for you. To keep yourself up to date I would advise you to follow their thread.

Why Do We Do This?

I had a MacBook Pro Early 2015 with 128GB of storage. Space was running low so I decided to give this a shot as M.2 are pretty cheap these days. And, there are good ones out there which perform far better than Apple’s proprietary SSDs and at a fraction of what these actually cost.

So let’s get started! I will try to make this as less of a daunting task as possible.

For this tutorial, here are the prerequisites:

  1. Make sure you have the latest MacOS (Catalina as of today) installed in your system with current M.2 SSD drive. You can install this from App Store. This step is crucial because of latest bios that supports NVMe Express.
  2. If you want to transfer over your existing files (or OS) to new SSD, make sure to do a full Time-Machine Backup.

If you have any questions on these topics, please drop a comment below so that I can help you out further.

Now, onto the actual process. You will need the following:

M.2 NVMe Drive of your choice

I say your choice because it is really up to you which drive you want. But, there are some good NVMe drives out there that have shown to perform much better with these setup. Please look at these charts (taken from MacRumors) to see which one performs better.

SSD NVMe Power Consumption Chart
SSD NVMe Power Consumption Chart
SSD NVMe Power Efficiency Chart
SSD NVMe Power Efficiency Chart
SSD NVMe Performance By Price
SSD NVMe Performance By Price

Recommendation:

I would personally recommend the following SSDs.

For 1TB Option

For 512GB Option

M.2 Adapter

Once you have the M.2 of your choice, next is the interface that goes between Apple’s proprietary M.2 slot and your M.2 drive. For this we have couple of options available from different vendors. But, I personally prefer Sintech Adapters. The MacRumors forum suggests the following as well.

Chenyang vs Sintech2
Chenyang vs Sintech2
Chenyang vs Sintech1
Chenyang vs Sintech1

Kapton Tape (If Required)

Be mindful of the adapter you buy, the later ones do not need Kapton tapes over the connector since they are properly insulated. If your adapter has connector pins exposed you can buy some Kapton tape and apply it over the connector like so.

You can buy one here: https://amzn.to/3vjxlv2

Kapton Tape
Kapton Tape

Once you have everything, next thing is installing the M.2 into the Sintech adapter.

Sintech NGFF M.2 nVME SSD Adapter Card
Sintech NGFF M.2 nVME SSD Adapter Card

Finally, install the Sintech Adapter with M.2 SSD into your macbook. It’s as easy as that!

Remove Screws on your macbook
Remove Screws on your macbook
Remove M.2 SSD
Remove M.2 SSD
Install M.2 SSD with Sintech Adapter
Install M.2 SSD with Sintech Adapter

Hybernation Issue with 2013-2014 Laptops (copied from MacRumor Article)

Starting with macOS Big Sur 11.0.1, Apple has released Root ROM or system firmware for 2013-2014 MacBook Pro and MacBook Air models that allows these models to be upgraded with NVMe drives and prevent deep sleep issues without further system modifications.

* Late 2013 MacBook Pro 13” with Retina Display (MacBookPro11,1): Boot ROM 427.0.0.0 and higher
* Mid-2013 MacBook Air 11”: Boot ROM 4xx.0.0.0 and higher

Updating to those 4xx.0.0.0 versions of Boot ROM or system firmware will make any additional modifications to prevent unexpected system restarts unnecessary; however, it has been noted that the hibernation and autopoweroff behavior of those MacBooks models has been changed and that the battery discharge is higher than with the original PCIe SSD.

macOS release prior to macOS Big Sur 11.0.1 ship with a Boot ROM or system firmware for 2013/2014 MacBook Pro (13”, 15”) and 2013/2014 MacBook Air (11”, 13”) that included a DXE NVMe driver which is incompleted or compressed. This caused 2013 and 2014 MacBook models to not wake up from hibernation and restart. This problem existed with every NVMe SSD (Apple NVMe SSDs that shipped with 2015 MacBook Pro models, third-party drives like the OWC Aura Pro 2, Transcend 850 NVMe SSD).

To prevend this problem you had two options:

  1. Disable hibernation or deep sleep by disabling hibernation via Terminal: “

sudo pmset -a hibernatemode 0 standby 0 autopoweroff 0

  • Patch the Boot ROM or system firmware with an NVMe driver from 2015 MacBook model equivalents.

Disabling hibernation had the drawback that your MacBook would consume more power when sleeping for a longer time compared to proper hibernation (suspend to disk) with the default settings. Your battery would lose ~10% overnight.

The process of patching the Boot ROM or system allowed hibernation to work but required additional hardware. See
https://forums.macrumors.com/thread…ssd-to-m-2-nvme.2034976/page-65#post-26224320 for a guide that walked through the required steps.

Other options included a ”Matt Card” from CMI zapper.

And that’s all folks, you’ve just supercharged your Macbook! 


Programming Basics Prep

Programming Basics Prep

Most of the concepts on this page is taken from : Data Structures and Algorithms in Java by Robert Lafore

This is a basic programming concept anyone must know. I will keep this page updated with new code when I have time.

Linear Search vs Binary Search

Linear Search searches for each item in a list. For ordered,  average number of steps needed to find an item is N/2. For unordered, average number of steps needed to find an item is N.

Binary Search is like a Guess-a-number game where it checks for value in the middle and see if the number is less or more or equal to that middle number  thereby shortening the number of guesses. This can an be applied only to a sorted list.

Guess a number between 1-100 (number 33 guessed)

 Step NumberNumber Guessed Result Range of Possible Values 
01-100
150Too High1-49
225Too Low26-49
337Too High26-36
431Too Low32-36
534Too High32-33
632Too Low33-33
733Correct

Binary search provides a significant speed increase over a linear search. If we used linear search it would have took us 33 guesses but in binary search it only took us 7. For small number of items it is not significant but for large items binary is way more faster than linear.

Logarithms

Comparisions needed in Binary Search

10 -> 4, 100 -> 7, 1000 -> 10, 10,000 -> 14 and so on…

Steps sRange rRange expressed as power of 2
012^0
122^1
242^2
382^3
4162^4
5322^5
6642^6
71282^7

As we can see 7 steps cover the range of 100 (128 in total).

Doubling the range each time creates a series that’s the same as raising two to a power. We can express this power as a formula. If s represents the steps and r represents the range, the equation is

r = 2^s

(eg. 128 = 2^7)

The inverse of raising something to the power is logarithm. This equation says that the number of steps (comparisions) is equal to the logarithm to the base 2 of the range.

s = log2(r)

It is usually log to the base 10 but we can convert easily to base 2 by multiplying by 3.322

[ex. log10(100) = 2,  log1(100) = 2*3.322,  which is equal to 6.644 (approx. 7)]

Big O Notation

Big O Notation is used to measure how efficient a computer algorithm is.

T is time, K is constant

Insertion in unordered array : T = K (Insertion requires a same amount of time no matter how big is the arrray)

Linear Search: T = K * N/2 (The number of comparisions that must be made to find a specified item is, on average, half of the total number of items) We can combine constant with 2 and the new formula is T = K*N where K is the new constant.

Big O Notation dispenses with the constant K. All we want to compare is how T change for different values of N, not what the actual numbers are.

We read O(1) as the order of 1.

Therefore we can say, Linear Search takes O(N) time and Binary Search takes O(log N) time. Insertion into unordered array takes O(1) or constant time which is ideal!

AlgorithmRunning Time in Big O
Linear SearchO(N)
Binary SearchO(log N)
Insertion in unordered arrayO(1)
Insertion in ordered arrayO(N)
Deletion in unordered arrayO(N)
Deletion in ordered arrayO(N)

 

Time Complexity

Time Complexity

O(1) is excellent, O(log N) is good, O(N) is fair, O(N^2) is poor. Bubble sort is O(N^2).

Simple Sorting

Bubble Sort

It is simplest of the sorting algorithms and very slow. You start at the left end of the list and compare the two values in index 0 and 1. If value in 0 is greater than a value in 1 then we swap the positions. If value in 0 is smaller than value in 1 we don’t do anything. We then move over one position and compare values in index 1 and index 2. We do this until all the values are sorted. As the algorithm progresses, the biggest items “bubble up” to the top end of the array. After this first pass through all the data, we’ve made N-1 comparisions and somewhere between 0 and N-1 swaps.

Now, we go back again and start another pass from left end of the array towards the right. However, we stop at N-2 because we know N-1 already contains largest number. On each external iteration/pass we decrease the size of N.

for(int i =array.length-1; i>1; i--){
   for(int j =0; j<= array.length; j++){
      //swap if needed
      if(array[j] > array[j+1]{
         int temp = array[j];
         array[j] = array[j+1];
         array[j+1] = temp;
      }
   }
}

Efficiency of Bubble Sort

In general, where N is the number of items in the array, there are N-1 comparisons on the first pass, N-2 on the second and so on…

(N-1)+(N-2)+(N-3)+…+1 = N*(N-1)/2

Thus, the algorithm makes about N^2/2 comparisions as we get rid of -1 as it makes no difference. We know if data is random, a swap is necessay about half the time on average so there will be N^2/2 * 1/2 = N^2/4 swaps. We can ignore the constant 2 (or 4) thus it gives us the Big O Notation of O(N^2) which is very poor.

Selection Sort

This sort reduces the number of swaps necessary from O(N^2) as in bubble sort to O(N). Unfortunately, the number of comparisions remains the same O(N^2).

In this type of sorting, we look for the lowest number in the list and swap it with the index 0 of the one on the left. We then start again from index 1 and look for the lowest number and swap it with the value in index 1. We continue forward until we reach the index N-1. In this algorithm the sorted numbers accumulate on the left side.

int minVal;
for(int i = 0; i<array.length-1; i++){
   minVal = i;
   for(int j = i+1; j<array.length; j++){
     if(array[j]<array[minVal]){
         minVal = j;
         int temp = array[i]; 
         array[i] = array[minVal]; 
         array[minVal] = temp;
     }
   }
}

Efficiency of Selection Sort

Selection sort performs the same number of comparisions as the bubble sort N*(N-1)/2. But, it is faster because there are so few swaps. For smaller values of N, hte selection sort may in fact be much faster than bubble sort. For large values of N, the comparision times will dominate, so we would have to say that the selection sort runs in O(N^2) time just as bubble sort.

Insertion Sort

In insertion sort, we divide the unsorted list into two and sort the list on the left (partial sorting).  Then we take the value from the start index of the second list, compare it with first list and put the number in appropriate position while shifting remaining numbers from first list to the right. We continue the process until we go through all the numbers in the second list.

int i, j;
for(i = 1; i<array.length; i++){ //i is dividing line
   int temp = array[i]; //remove marked item
   j = i; //start shifts at i
   while(j>0 && array[j-1] >= temp){ //until j is smaller,
       array[j] = array[j-1]; //shift item to right
       --j; //go left one position
   }
   array[j] = temp; //insert marked item
}

Efficiency of Insertion Sort

On the first pass, it compares the maximum of 1 item. On second pass 2 and so on up to N-1

1 + 2 + 3 + … + N-1 = N*(N-1)/2

On each pass only 1/2 of the maximum number of items are actually compared before the insertion point is found, we can divide by 2. So, N*(N-1)/4

The insertion sort runs in O(N^2) time for random data and when data is almost sorted it runs at O(N).

 

Stacks and Queues

Stacks and Queues are more restricted and abstract as we can only access one data at a time – either on top or on the bottom. We can use Arrays to understand the concept but we can also use Linked Lists and Heap.

Stacks

A stack allows access to onle one data item: the last item inserted. Think of it as a stack of books on the table. You put a book on top of the stack and, you take a book from the top of the stack. Basically it is Last-In-First-Out(LIFO)Example: Stack  can be used to check whether paranthesesm, braces and brackets are balanced in a computer program. In binary trees, it can be used to traverse the nodes of a tree. In Graphs, it can be used to search the vertices of a graph. Most microprocessors use a stack based architecture. When a method is called, its return address and arguments are pushed onto a stack, and when it returns, they are popped off.

public class StackX{
//size of stack array
private int maxSize;

//Array
private int[] stackArray;

//top of stack
private int top;

//put an item on a stack
public void push(int j)
{
    stackArray[++top] = j;
}

//take item from top of stack
public int pop(){
   return stackArray[top--];
}

//peek at the top of the stack
public int peek()
{
   return stackArray[top];
}

//check if stack is empty
public boolean isEmpty()
{
   return(top == -1);
}

//check if stack is full
public boolean isFull()
{
   return(top==maxSize-1);
}
} // end of StackX class

public class StackApp
{
   StackX theStack = new StackX(10); // new stack creation

   theStack.push(10);
   theStack.push(30); //add values to stack

   while(!theStack.isEmpty())    //loop through stack to pop and display
   {
      int value = theStack.pop();
      System.out.println(value);
   }
}

 

Efficiency of Stack : Constant O(1) time and is not dependent on number of items.

Queues

It is a data structure that is somewhat like a stack, except that in a queue the first item inserted is the first item to be removed (First-In-First-Out, FIFO). Example: A queue works as a line in an apple store: first person to stand gets the first iPhone, a printer’s queue when you hit that print command and, typing things on a screen, etc.

Circular queue: when you insert an item in a queue, it sits at the back of the line. And, when you remove an item, the spot is empty at the front. You can push all the values to the front to make up that space but it is somewhat inefficient. So, we just circle through the array or spots.

class Queue{
 private int maxSize;
 private int[] queArray;
 private int front;
 private int rear;
 private int nItems;

public Queue(int s){
  maxSize = s;
  queArray = new Int[maxSize];
  front = 0;
  rear = -1;
  nItems = 0;
}

public void insert(int j){
  if(rear == (maxSize-1)){
     rear = -1;
  }
  queArray[++rear] = j;
  nItems++; 
}

public int remove(){
  int temp = queArray[front++];
  if(front==maxSize){
    front=0;
  }
  nItems--;
  return temp;
}

public int peekFront(){
  return queArray[front]
}

public boolen isEmpty(){
  return (nItems==0);
}

public boolean isFull(){
  return (nItems==maxSize); 
}

public int size(){
  return nItems;
}
}


class QueueApp{
Queue theQueue = new Queue(5);

theQueue.insert(10);
theQueue.insert(30);

theQueue.remove();

theQueue.insert(20);

while(!theQueue.isEmpty()){
  int n = theQueue.remove();
  System.out.println(n);
}
}

Efficiency of Queues: O(1) time as we insert and remove data

Priority Queues

This is a more specialized form of a queue. Like an ordinary queue, priority queue has a front and a rear, and items are removed from the front. However, in a priority queue, items are ordered by key value so that the item with the lowest key is always at the front. Example: Sorting of letters in order of priorities, minimum spanning trees, weighted graphs.

Efficiency of Priority Queues: Insertion runs in O(N) time as it has to sort the values first. Deletion takes O(1). We can improve insertion time using heaps.

Arrays

Arrays are the most commonly used data structure. But, it is not always ideal. In an unordered array insert takes O(1) time but searching is slow O(N). In ordered array search is quick O(log N) but insertion takes O(N). For both, deletion takes O(N). Linked Lists is another viable option.

  • Important things to understand: Insertion, Searching, Deletion
  • Average number of steps needed to find and item is N/2 (worst case N)
  • A deletion requires searching through an average of N/2 elements and then moving the remaining elements(N/2) to fill up the resulting hole. Total steps is N.

Creating an array:

//initialization
int[] count = new int[3]; //Integer Array of 3 empty slots.

int[] count2 = new int[]{1, 2, 3};
int[] count3 = {1,2,3};

//initialization		
String[] arrayString = new String[8]; //String Array of 8 empty slots.

String[] arrayString2 = new String[]{"a","b"};
String[] arrayString3 = {"a","b"};

Accessing Array:

int second = count[2];

String third = arrayString[3];

Inserting Values in Array:

count[2] = 4;

arrayString[3] = "c";

Some common examples:

Reverse a String

System.out.println(reverseString("Elephant"));

public String reverseString(String key){
  String reversedString = "";
  for(int i = key.length();i>=0;i--){
    reversedString+=key.charAt(i);
  }
return reversedString;
}


//Recursion
String reversedString = reverseRec("elephant", "", "elephant".length());

public String reverseRec(String key, String reversed, int i){
	if(i<0){
		return reversed;
	}
	reversed = reversed+key.charAt(i);
	return reverseRec(key, reversed, i-1);
}

//Output: tnahpelE

Sorting numbers in an Array

//Bubble Sort
int[] sortArray = {2,3,1,7,5,9,10,4,7,9};
		
for (int i = 0; i < sortArray.length; i++) {
  for (int j = i + 1; j < sortArray.length; j++) {
	int tmp = 0;
	if (sortArray[i] > sortArray[j]) {
	  tmp = sortArray[i];
	  sortArray[i] = sortArray[j];
	  sortArray[j] = tmp;
        }
  }
  System.out.println(sortArray[i]);
}

Sum of Numbers in an Array

int[] sortArray = {2,3,1,7,5,9,10,4,7,9};
int sum = 0;
for(int k:sortArray){
  sum+=k;
}

Fibonacci Series with and without Recursion

//Fibonacci Series
printFibonacci(10, true);//recusrive
printFibonacci(10, false);//non-recursive

static int n1=0,n2=1,n3=0;

static void printFibonacci(int count, boolean recursion){
//using recursion
if(recursion){
	if(count>0){
		n3=n1+n2;
		n1=n2;
		n2=n3;
		System.out.print(" "+n3);
		printFibonacci(count--, true);
	}
}else{
	//without recursion
	System.out.println(n1+" "+n2);
	for (int i=2;i<=count;i++){
		n3=n1+n2;
		n1=n2;
		n2=n3;
		System.out.print(" "+n3);
	}
     }
}

Check prime number

	public boolean findPrime(int value){
		boolean isPrime = false;
		if(value<2){
			isPrime=false;
		}else{
			isPrime=true;
		}
		for(int i=2; i<=value/i; i++){
			if((value%i)==0){
				isPrime = false;
				break;
			}
		}
		return isPrime;
	}

Binary Search

int[] arrayValues = {1,5,8,10,24,35,44,65,76};
int arraySize = arrayValues.length;
boolean checkBinarySearch = binarySearch(10);
public boolean binarySearch(int key){
int low = 0;
int high = arraySize-1;
while(high>=low){
	int middle = (low+high)/2;
	if(arrayValues[middle]==key){
		return true;
	}
	if(arrayValues[middle]< key){
		low=middle+1;
	}
	if(arrayValues[middle]>key){
		high=middle-1;
	}
}
return false;
}

Linear Search

int[] arrayValues = {1,5,8,10,24,35,44,65,76};
int arraySize = arrayValues.length;	
public void linearSearch(int key){
	for(int i=0; i<arraySize; i++){
		if(arrayValues[i]==key){
			System.out.println("Found");
		}else if(i==arraySize){
			System.out.println("Not Found");
		}
	}
}

Factorial

public static int factorial(int key){
	int result = 1;
	for(int i=1; i<= key; i++){
		result = result* i;
	}
	return result;
}

public int factorialrec (int key){
        int result;
	if(key==1){
	   return 1;
	}
	result = key*factorialrec(key-1);
	return result;
}

Palindrome

	public boolean checkPalindrome(String key){
		int i = 0;
		int j = key.length()-1;
		while(j>i){
			if(key.charAt(i)!=key.charAt(j)){
				return false;
			}
			++i;
			--j;
		}
		return true;
	}

Shuffle a deck of cards

	private static final int DECK_SIZE = 52;
	
//Using Collections Library
	public void randomizeCards(){
		ArrayList<Integer> deck = new ArrayList<Integer>();
        for (int i = 0; i < DECK_SIZE; ++i) {
            deck.add(i);
        }
        Collections.shuffle(deck);
        System.out.println(deck);
	}

//Using Arrary List
	public void randomizeCardsB(){
		ArrayList<Integer> deck = new ArrayList<Integer>();

        for (int i = 0; i < DECK_SIZE; ++i) {
            deck.add(i);
        }

        ArrayList<Integer> shuffledDeck = new ArrayList<Integer>();

        while (deck.size() > 0) {
            int index = (int) (Math.random() * deck.size());
            shuffledDeck.add(deck.remove(index));
        }
        System.out.println(shuffledDeck.toString());
	}

Check for Anagrams

	//check for anagrams
	public boolean checkAnagrams(String first, String second){
		int lengthf = first.length();
		int lengths = second.length();
		int j = 0;
		if(lengthf==lengths){
			char[] charArray1 = first.toCharArray();
			char[] charArray2 = second.toCharArray();
			Arrays.sort(charArray1);
			Arrays.sort(charArray2);
			for(int i=0; i<lengthf; i++){
				if(charArray1[i]==charArray2[i]){
					j++;
				}else{
					return false;
				}
				if(lengthf==j){
					return true;
				}
			}
			
		}
			return false;
	}

Find first non repeating char in a string

static final int NO_OF_CHARS = 256;
static char count[] = new char[NO_OF_CHARS];
static void getCharCountArray(String str) 
    {
        for (int i = 0; i < str.length();  i++)
             count[str.charAt(i)]++;
    }
	static int firstNonRepeating(String str)
    {
        getCharCountArray(str);
        int index = -1, i;
      
        for (i = 0; i < str.length();  i++)
        {
            if (count[str.charAt(i)] == 1)
            {
                index = i;
                break;
            }   
        }  
       
      return index;
    }

 

Linked Lists

Arrays have certain disadvantages as data storage structures. In an unordered array, searching is slow, whereas in an ordered array, insertion is slow. In both, deletion is slow. Also, the size of an array can’t be changed after it’s created.

Linked Lists can replace an array as the basis for other storage structures such as stacks and queues. In fact, you can use a linked list in many cases in which you use an array, unless you need frequent random access to individual items using an index.

Links

In a linked list, each data item is embedded in a link. A link is an object of a class Link (or something similar). Each link object contains a reference to next link in the list. A field in the list itself contains a reference to the first link. This kind of class definition is sometimes called self-referential because it contains a field (called next) of the same type as itself.

Class Link{
   public int iData;  //similar to index in array
   public int dData;  //actual value
 
//you can also hold an object instead of variable
   public objetItem obj;

   pubic Link next;   //reference to next link
}

In Java, a Link object doesn’t really contain another Link object. The next field of type Link is only a reference to another link, not an object.

Linked List

Linked List

How Linked List differs from Array

In an array each item occupies a particular position. This position can be directly accessed using an index number.Like a row of houses – once you know the address you know the position. In a List, the only way to find a particular element is to follow along the chain of elements.

A Simple Linked List

  • Inserting an item at the beginning of the list
  • Deleting the item at the beginning of the list
  • Iterating through the list to display contents
class Link
{
  public int iData;
  public String dData;
  public Link next;
  
  public Link(int id, String dd){
      iData = id;
      dData = dd;
  }

  public void displayLink(){
     System.out.println(iData+" has "+dData);
  }
}

class LinkList{
  private Link first;

  public LinkList(){
    first=null;
  }
  public boolean isEmpty(){
    return (first==null);
  }
  public void insertFirst(int id, String dd){
    Link newLink = new Link(id, dd);
    newLink.next = first;
    first = newLink;
  }
  public Link deleteFirst(){
    Link temp = first;
    first = first.next;
    return temp;
  }
  public void displayList(){
    Link current = first;
    while(current!=null){
       current.displayLink();
       current = current.next;
    }
  }
}

class LinkListApp{
  public static void main (String[] args){
     LinkList theList = new LinkList();
     theList.insertFirst(100, "Hello");
     theList.insertFirst(101, "World");
     
     theList.displayList();

     while(!theList.isEmpty()){        //until the list is empty 
       Link aLink = theList.deleteFirst();
     }
  }
}

Finding and Deleting Specified Link

public Link find(int key){
   Link current = first;
   while(current.iData != key){
      if(current.next == null){
         return null;
      }else{
         current = current.next;
      }
   }
return current;
}

public Link delete(int key){
  Link current = first;
  Link previous = first;
  while(current.iData != key){
     if(current.next == null){
         return null;
      }else{
         previous = current;
         current = current.next;
      }
  }
  if(current == first){
    first = first.next;
  }else{
    previous.next = current.next;
  }
  return current;
}

Double-Ended Lists

A double-ended list is similar to an ordinary linked list, but it has one additional feature: a reference to the last link as well as to the first. The reference to the last link permits you to insert a new link directly at the end of the list as well as at the beginning. You can also do this with Linked List but you will have to traverse through the whole list and then insert it which is inefficient.

Linked List Efficiency: Insertion and deletion at the very beginning of a linked list are very fast – O(1). Finding, deleting, or inserting next to a specific item requires searching through an average of half the items in the list. This requires O(N) comparisions. An array is also O(N) for these operations but linked list is nevertheless faster because nothing needs to be moved when an item is inserted or deleted. Linked List uses exactly as much memory as it needs and can expand to fill all of available memory. The size of an array is fixed (except vector, but is still inefficient).


Getting started with Twilio Phone Services

Today I am going to talk about how to create a simple phone application using the popular Twilio API. If you don’t know what Twilio is all about then I recommend you go through their “What is Cloud Communications” section.

Twilio

Twilio

When I was working for Infofree I was given a task to come up with a basic SMS and Voice Authentication system using any available services out there. My two options back then was either Corvisa (now Shoretel) or Twilio. I tried to work with Corvisa and their API but, it lacked a lot of features that Twilio has. So ultimately, I decided to build the feature using Twilio. Sadly, because of economic reasons for my company my code was never live. But, in my free time I went further and used Twilio’s service to test different features.

In this tutorial I will show you how to setup basic twilio service using JAVA.

These are some of the things you will need in order for yor app to work.

  1. Twilio Account SID TWILIO_ACCOUNT_SID
  2. Twilio Authentication Token TWILIO_AUTH_TOKEN
  3. Twilio Number TWILIO_NUMBER
  4. Twilio Application SID (Optional)
  5. Twilio Agent Number (Optional)

Get API Key

Go to twilio and click on the “Get a Free API Key button”.

Get a Free API Key - Twilio

Get a Free API Key – Twilio

Go through the general registration process (should be easy). You need to verify using your phone number.

After you are done, go to Home-> Settings-> General

You should see your  TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN

Get Phone Number

If you plan to use your number then you do not need to get TWILIO_NUMBER else click here and get a phone number. For trial purposes you can only use verified phone numbers.

Get a new phone number

Get a new phone number

You should see this number in your Manage Numbers section.

 

Things you’ll need for JAVA

If you use maven, you need to add this dependency in your pom.xml file:

<dependency>
  <groupId>com.twilio.sdk</groupId>
  <artifactId>twilio</artifactId>
  <version>(7.0,7.9)</version>
</dependency>

If you don’t use maven, use this jar file instead: twilio-7.x.x-with-dependencies.jar

Here I will be using a properties file (db.properties) to store all my API credentials

#mysql DB properties
DB_DRIVER_CLASS=com.mysql.jdbc.Driver
DB_URL=jdbc:mysql://localhost:3306/test
DB_USERNAME=username
DB_PASSWORD=password

TWILIO_ACCOUNT_SID=ACed9da74780242eded3a2fb674a*****
TWILIO_AUTH_TOKEN=fac36407eb1bf66f207d2763671*****
TWILIO_NUMBER=+14023789330
TWILIO_APPLICATION_SID=

Once you have everything setup, we can use Twilio’s API library to do various tasks.

Go ahead and download this sample code to play around some of the features.

I also created a Phone Verification system where you could verify phone using either a SMS or a Voice Call. But because it was part of my company project, I cannot share the code with you. But here is the screenshot of how it looks like.

Phone Verification using Twilio

Phone Verification using Twilio

Following are some of the examples:

Send SMS

SendSMS

SendSMS

 

package com.twilioAPI;

import com.twilio.sdk.resource.instance.Account;
import com.twilioAPI.exceptions.UndefinedEnvironmentVariableException;
import com.twilioAPI.lib.AppSetup;
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import com.twilio.sdk.resource.factory.MessageFactory;
import com.twilio.sdk.resource.instance.Message;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class sendSMS
 */
@WebServlet("/sendSMS")
public class SendSMS extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private AppSetup appsetup;
    /**
     * @see HttpServlet#HttpServlet()
     */
    public SendSMS() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
		this.appsetup = new AppSetup();
		try {
			String accountSid = this.appsetup.getAccountSid();
			String authToken = this.appsetup.getAuthToken();
			String fromNumber = this.appsetup.getTwilioNumber();
			TwilioRestClient client = new TwilioRestClient(accountSid, authToken);
			String pNumber = request.getParameter("phoneSMS");
			String pMessage = request.getParameter("testSMS");
			Account account = client.getAccount();
			MessageFactory messageFactory = account.getMessageFactory();
	        List<NameValuePair> params = new ArrayList<NameValuePair>();
	        params.add(new BasicNameValuePair("To", pNumber)); // Replace with a valid phone number for your account.
	        params.add(new BasicNameValuePair("From", fromNumber)); // Replace with a valid phone number for your account.
	        params.add(new BasicNameValuePair("Body", pMessage));
	        Message sms = messageFactory.create(params);
	        System.out.println("Sending SMS...: To:" + pNumber + "From:"+ fromNumber+ "and Message:" +pMessage);
		} catch (UndefinedEnvironmentVariableException | TwilioRestException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
		
		
		
		
	}

}

Click-to-Call

Click-to-Call

Click-to-Call

 

package com.twilioAPI;

import com.twilioAPI.exceptions.UndefinedEnvironmentVariableException;
import com.twilioAPI.lib.AppSetup;
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import org.json.simple.JSONObject;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
 * Servlet implementation class Call
 */
@WebServlet("/Call")
public class Call extends HttpServlet {
	private static final long serialVersionUID = 1L;
	 AppSetup appSetup;
	  TwilioRestClient client;

	  public Call() {}

	  public Call(AppSetup appSetup, TwilioRestClient client) {
	    this.appSetup = appSetup;
	    this.client = client;
	  }
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    String phoneNumber = request.getParameter("phone");
	    if(phoneNumber==null||phoneNumber==""){
	    	phoneNumber = request.getParameter("phoneNumber");
	    }
	    boolean record = request.getParameter( "record" ) != null;
	    String CallRecord = "false";
	    if (record == true){
	    	CallRecord = "true";
	    }
	    request.getServletContext().setAttribute("record", CallRecord);
	    
	    if (phoneNumber != null) {
	      if (this.appSetup == null || this.client == null) {
	        appSetup = new AppSetup();
	        client = null;
	        try {
	          client = new TwilioRestClient(appSetup.getAccountSid(), appSetup.getAuthToken());
	        } catch (UndefinedEnvironmentVariableException e) {
	          response.getOutputStream().write(getJSONResponse(e.getMessage()).getBytes());
	          return;
	        }
	      }

	      Map<String, String> params = new HashMap<>();
	      String twilioNumber;
	      try {
	        twilioNumber = appSetup.getTwilioNumber();
	      } catch (UndefinedEnvironmentVariableException e) {
	        response.getOutputStream().write(getJSONResponse(e.getMessage()).getBytes());
	        return;
	      }

	      // Full path to the end point that will respond with the call TwiML
	      //String path = request.getRequestURL().toString().replace(request.getRequestURI(), "") + "/CorvisaAPI/connect?record="+CallRecord;
	      String path = request.getRequestURL().toString().replace(request.getRequestURI(), "") + "/CorvisaAPI/connect";
	      params.put("From", twilioNumber);
	      params.put("To", phoneNumber);
	      params.put("Url", path);
	      try {
	        client.getAccount().getCallFactory().create(params);
	      } catch (TwilioRestException e) {
	        String message = "Twilio rest client error: " + e.getErrorMessage() +
	            "\nRemember not to use localhost to access this app, use your ngrok URL";
	        response.getOutputStream().write(getJSONResponse(message).getBytes());
	        return;
	      }
	      response.getOutputStream().write(getJSONResponse("Phone call incoming!").getBytes());
	    } else {
	      response.getOutputStream()
	          .write(getJSONResponse("The phone number field can't be empty").getBytes());
	    }
	}
	private String getJSONResponse(String message) {
	    JSONObject obj = new JSONObject();
	    obj.put("message", message);
	    obj.put("status", "ok");

	    return obj.toJSONString();
	  }

}

Web Phone

WebPhone

WebPhone

package com.twilioAPI;

import com.twilioAPI.exceptions.UndefinedEnvironmentVariableException;
import com.twilioAPI.lib.AppSetup;
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import org.json.simple.JSONObject;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
 * Servlet implementation class Call
 */
@WebServlet("/Call")
public class Call extends HttpServlet {
	private static final long serialVersionUID = 1L;
	 AppSetup appSetup;
	  TwilioRestClient client;

	  public Call() {}

	  public Call(AppSetup appSetup, TwilioRestClient client) {
	    this.appSetup = appSetup;
	    this.client = client;
	  }
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    String phoneNumber = request.getParameter("phone");
	    if(phoneNumber==null||phoneNumber==""){
	    	phoneNumber = request.getParameter("phoneNumber");
	    }
	    boolean record = request.getParameter( "record" ) != null;
	    String CallRecord = "false";
	    if (record == true){
	    	CallRecord = "true";
	    }
	    request.getServletContext().setAttribute("record", CallRecord);
	    
	    if (phoneNumber != null) {
	      if (this.appSetup == null || this.client == null) {
	        appSetup = new AppSetup();
	        client = null;
	        try {
	          client = new TwilioRestClient(appSetup.getAccountSid(), appSetup.getAuthToken());
	        } catch (UndefinedEnvironmentVariableException e) {
	          response.getOutputStream().write(getJSONResponse(e.getMessage()).getBytes());
	          return;
	        }
	      }

	      Map<String, String> params = new HashMap<>();
	      String twilioNumber;
	      try {
	        twilioNumber = appSetup.getTwilioNumber();
	      } catch (UndefinedEnvironmentVariableException e) {
	        response.getOutputStream().write(getJSONResponse(e.getMessage()).getBytes());
	        return;
	      }

	      // Full path to the end point that will respond with the call TwiML
	      //String path = request.getRequestURL().toString().replace(request.getRequestURI(), "") + "/CorvisaAPI/connect?record="+CallRecord;
	      String path = request.getRequestURL().toString().replace(request.getRequestURI(), "") + "/CorvisaAPI/connect";
	      params.put("From", twilioNumber);
	      params.put("To", phoneNumber);
	      params.put("Url", path);
	      try {
	        client.getAccount().getCallFactory().create(params);
	      } catch (TwilioRestException e) {
	        String message = "Twilio rest client error: " + e.getErrorMessage() +
	            "\nRemember not to use localhost to access this app, use your ngrok URL";
	        response.getOutputStream().write(getJSONResponse(message).getBytes());
	        return;
	      }
	      response.getOutputStream().write(getJSONResponse("Phone call incoming!").getBytes());
	    } else {
	      response.getOutputStream()
	          .write(getJSONResponse("The phone number field can't be empty").getBytes());
	    }
	}
	private String getJSONResponse(String message) {
	    JSONObject obj = new JSONObject();
	    obj.put("message", message);
	    obj.put("status", "ok");

	    return obj.toJSONString();
	  }

}

 

Other uses are Phone Verification system, Conference Call, etc.


Creating a PS Vita Theme – Legend of Zelda Kakariko Village

Creating a PS Vita Theme – Legend of Zelda Kakariko Village

Hi everyone!

If you guys are following the PS Vita scene lately, a lot is going on. Especially with home-brew and customization. I know this voids manufacturer’s warranty but since Sony doesn’t care about PS Vita and PS TV anymore (that’s the general impression), people are trying to come up with new things to make the scene alive.

A week ago I was playing Legend of Zelda: A Link Between the World in my N3DS. Then it gave me an idea of creating a theme for my PS Vita and PS TV.  I was inspired by Sony’s Crystal Theme so It took me almost a week to assemble all the images, create and edit the file and test it out in my Vita. I decided to use their icons as it is free to download. Also the music is from Legend of Zelda: A Link Between the World Kakariko Village (Milk Bar).  I will also post all the psd files that I have if someone needs one. 🙂 Also, I am happy that I am a PlayStation Plus Subscriber. 🙂

If you would like to install this theme then click here to download. Or, download directly to your PS Vita from here.

If you would like to know how to create your own PS Vita themes then this is a great place to start. Also check this out!

Here are some of the screenshots:

Legend of Zelda Kakariko Village Special

Legend of Zelda Kakariko Village Special

Legend of Zelda Kakariko Village Special Lock Screen

Legend of Zelda Kakariko Village Special Lock Screen

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home

Legend of Zelda Kakariko Village Special Home


Retro Gaming Machine with Recalbox in Raspberry Pi 3

This tutorial is to show you how to install recalbox 4.0.2 in a Raspberry Pi 3 and make a true retro gaming machine.

UPDATE: Recalbox 4.1 released – https://github.com/recalbox/recalbox-os/releases

Table of Contents

  1. RetroPi vs Recalbox
  2. Hardware
  3. Software
  4. RecalBox Tutorial
  5. Controller Configuration
  6. Wireless Connection Setup
  7. Recalbox Upgrade
  8. Root Access to Recalbox using SSH
  9. Installing Themes
  10. Adding ROMs in Recalbox
  11. Scraping Artwork and Game Information
  12. Backup your Recalbox
  13. Troubleshooting

First of all what’s better RetroPi or Recalbox?

RetroPi vs Recalbox

Personally for me it all depends on choice and preference. Both are good in their own ways. Both run Retroarch and Emulationstation. So not much of a difference. But there are some features that  only RetroPi has and some that only Recalbox has.

RECALBOXRetroPie
  • Web GUI (just type //recalbox in browser) to monitor system, upload roms, edit and manage files, updates, etc.
  • More like iOS where you get less complexity (don’t have to get into coding to fix/add things)
  • Easy updates
  • Better Loading of OS (doesn’t show lines of codes on boot)
  • Minimal OS Build just for retro gaming (lite buildroot)
  • Faster loading of N64 Games (search for some videos in youtube)
  • Only Root user present
  • Share folder access to add roms and themes
  • Best for less Tech-Savvy people or people who don’t want to get more out of their raspberry pi besides retro gaming.
  • Better community support and more dedicated users
  • Fast/Constant update cycle
  • Features are built especially for RetroPie and then is migrated to Recalbox
  • More Themes present
  • More configuration options like Android
  • Fully working Debian OS
  • More Emulators support
  • Pi user present along with Root user
  • Share folder access to add roms and themes

 

Now, Let’s talk about the things you need:

Go through the compatibility list first. Very very important!!! : CLICK HERE

Hardware

Raspberry Pi 3

I am sure you can install this in any other Raspberry Pis but I prefer Pi3 because of its power and support. You can buy it easily from Amazon : Click Here

Raspberry PI 3 Model B A1.2GHz 64-bit quad-core ARMv8 CPU, 1GB RAM

Raspberry PI 3 Model B A1.2GHz 64-bit quad-core ARMv8 CPU, 1GB RAM

  1. Raspberry PI 3 Model B A1.2GHz 64-bit quad-core ARMv8 CPU, 1GB RAM : Click Here
  2. Raspberry Pi 2 Model B Desktop (Quad Core CPU 900 MHz, 1 GB RAM, Linux) : Click Here
  3. Raspberry Pi Model B+ (B PLUS) 512MB Computer Board : Click Here
  4. Raspberry Pi Zero v1.3 Development Board – Camera Ready : Click Here
  5. Raspberry Pi Zero W (Wireless) (new 2017 model) : Click Here

Raspberry Pi 3 Case

Your pi case makes this build even more interesting! Therefore, I decided to get the NES Case by Old Skool from Amazon : Click Here

NES case for Raspberry Pi 3,2 and B+ by Old Skool Tools

NES case for Raspberry Pi 3,2 and B+ by Old Skool Tools

  1. NES case for Raspberry Pi 3,2 and B+ by Old Skool Tools : Click Here
  2. Super Tinytendo Case for Raspberry Pi 3, 2, Model B with Large Cooling Fan : Click Here

HeatSink

We will need some copper heatsink cooler for this setup. The case comes with airflow grill but doesn’t have a fan support.

SainSmart Copper Heatsink Heat Sink Cooler Set for Raspberry Pi RPI

SainSmart Copper Heatsink Heat Sink Cooler Set for Raspberry Pi RPI

  1. SainSmart Copper Heatsink Heat Sink Cooler Set for Raspberry Pi RPI : Click Here

Micro SD Card or USB drive

Your Micro SD Card or USB drive must be at least 8GB in size. Recalbox recommends Sandisk Ultra series cards or drives. I got the Sandisk 128GB Ultra Series Micro SDXC Card.

Sandisk Ultra 128GB microSDXC UHS-I Card with Adapter

Sandisk Ultra 128GB microSDXC UHS-I Card with Adapter

One important thing to remember is that it is recommended to use USB drive or stick instead of Micro SD Card because SD cards seem to get corrupted over time. But as long as you make a backup, it shouldn’t be a big deal. I suggest you get one of the following:

  1. Sandisk Ultra 128GB microSDXC UHS-I Card with Adapter :  Click Here
  2. SanDisk Ultra 64GB microSDXC UHS-I Card with Adapter : Click Here
  3. SanDisk Ultra 32GB microSDHC UHS-I Card with Adapter : Click Here
  4. SanDisk Ultra 128GB Dual Drive m3.0 for Android Devices and Computers : Click Here
  5. SanDisk Ultra 64GB Dual Drive m3.0 for Android Devices and Computers : Click Here
  6. SanDisk Ultra 32GB Dual Drive m3.0 for Android Devices and Computers : Click Here
  7. SanDisk Ultra 16GB Dual Drive m3.0 for Android Devices and Computers : Click Here

Micro SD Card Reader

This one will be handy if you decide to go the MicroSD route. Honestly, for the case above, Micro SD looks so much better than USB drive as we won’t have to plug anything in the front.

[2-in-1] WEme Type-C (USB 3.1 Gen 1)Card Reader with USB-C Male & USB 3.0 Male Connecter, Support Micro SD/ TF/ SDHC/ SDXC for New MacBook, Google Chromebook Pixel, Surface Pro & SmartPhones

[2-in-1] WEme Type-C (USB 3.1 Gen 1)Card Reader with USB-C Male & USB 3.0 Male Connecter, Support Micro SD/ TF/ SDHC/ SDXC for New MacBook, Google Chromebook Pixel, Surface Pro & SmartPhones

  1. [2-in-1] WEme Type-C (USB 3.1 Gen 1)Card Reader with USB-C Male & USB 3.0 Male Connecter, Support Micro SD/ TF/ SDHC/ SDXC for New MacBook, Google Chromebook Pixel, Surface Pro & SmartPhones : Click Here

HDMI Cable

This might come with your raspberry pi. If you need one, my suggestion is you get HDMI 2.0 with gold plated one (for good conductivity) and preferably grey or white (to match with the pi case!) I recommend the following:

FLAT HDMI Cable – 6 FT (2-Pack) High Speed HDMI Cable (1.8m) Flat Wire – CL3 Rated, Supports, 4K, Ultra HD, 3D, 2160p, 1080p, Ethernet and Audio Return (Latest HDMI 2.0b Standard) White

FLAT HDMI Cable – 6 FT (2-Pack) High Speed HDMI Cable (1.8m) Flat Wire – CL3 Rated, Supports, 4K, Ultra HD, 3D, 2160p, 1080p, Ethernet and Audio Return (Latest HDMI 2.0b Standard) White

  1. FLAT HDMI Cable – 6 FT (2-Pack) High Speed HDMI Cable (1.8m) Flat Wire – CL3 Rated, Supports, 4K, Ultra HD, 3D, 2160p, 1080p, Ethernet and Audio Return (Latest HDMI 2.0b Standard) White – 6 FEET : Click Here

Power Cable

Make sure you get white one as it will match your case 🙂 I recommend one of the following:

Cable Matters 2-Pack, Gold Plated Hi-Speed USB 2.0 Type A to Micro-B Cable in White 6 Feet

Cable Matters 2-Pack, Gold Plated Hi-Speed USB 2.0 Type A to Micro-B Cable in White 6 Feet

  1. Cable Matters 2-Pack, Gold Plated Hi-Speed USB 2.0 Type A to Micro-B Cable in White 6 Feet : Click Here
  2. UGREEN Micro USB Cable Nylon Braided Fast Quick Charger Cable USB to Micro USB 2.0 Android Charging Cord for Samsung Galaxy S7/S6/S5/Edge, Note 5/4/3, LG, Nexus, HTC, Nokia, PS4 (3ft, White) : Click Here

Power Adapter

It is recommended to use a dedicated Power Adapter instead of using your TV’s inbuilt USB port.

AUKEY USB Wall Charger, ULTRA COMPACT Dual Port 2.4A Output & Foldable Plug for iPhone iPad Samsung & Others - White

AUKEY USB Wall Charger, ULTRA COMPACT Dual Port 2.4A Output & Foldable Plug for iPhone iPad Samsung & Others – White

  1. Quick Charge 3.0 AUKEY 6-Port USB Charger for Samsung Galaxy S8/S7/Edge, iPhone 7/7 Plus, iPad Pro/Air 2, LG G5 and More : Click Here
  2. AUKEY USB Wall Charger, ULTRA COMPACT Dual Port 2.4A Output & Foldable Plug for iPhone iPad Samsung & Others – White : Click Here
  3. ORICO USB Wall Charger 18W USB Charger for Power Bank, Android and iPhone devices-White : Click Here

Extras

USB Switch – Adds simplicity to your setup. Make sure you get the usb one and NOT the micro usb one as all the switches that I’ve found is black in color. We don’t want to have a black wire running from the pi to the power outlet.

JBtek® Raspberry Pi & Arduino Male to Female USB Cable with ON / OFF Switch – Easy Start / Reboot !

JBtek® Raspberry Pi & Arduino Male to Female USB Cable with ON / OFF Switch – Easy Start / Reboot !

  1. JBtek® Raspberry Pi & Arduino Male to Female USB Cable with ON / OFF Switch – Easy Start / Reboot ! : Click Here

Bluetooth / Wired Controller – I prefer 8bitdo NES30 Pro Bluetooth Controller as it looks classic with our pi setup. But, you can also use Playstation 4 controller if you have one at home. If you decide to go with PS4 controller then we might have to tweak the code a bit.

8bitdo NES30 Pro Bluetooth Controller with Dynamic Labs Bonus Carrying Case

8bitdo NES30 Pro Bluetooth Controller with Dynamic Labs Bonus Carrying Case

  1. 8bitdo NES30 Pro Bluetooth Controller with Dynamic Labs Bonus Carrying Case : Click Here
  2. 8bitdo FC30 Pro Controller with Bonus Carrying Case : Click Here
  3. 8bitdo SNES30 Wireless Bluetooth Controller Dual Classic Joystick for IOS / Android Gamepad – PC Mac Linux : Click Here
  4. NES30 Game Controller – PC Mac Linux : Click Here
  5. DualShock 4 Wireless Controller for PlayStation 4 – Silver : Click Here
  6. Xbox Wireless Controller – White : Click Here
  7. PlayStation 3 Dualshock 3 Wireless Controller (Classic White) : Click Here

Software

7Zip or any other archiving software : http://www.7-zip.org/download.html

GUI Fat32 formatter : http://www.ridgecrop.demon.co.uk/index.htm?guiformat.htm

Recalbox OS : https://github.com/recalbox/recalbox-os/releases

Recalbox Themes : https://github.com/recalbox/recalbox-themes

Putty : https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html

Win32 Disk Imager : http://sourceforge.net/projects/win32diskimager/

Here is the link to the file that contains all the above files. : Click Here

RecalBox Tutorial

First, just go ahead and put everything in place in terms of setup.

Things to do in PC

1. Unzip and/or install 7Zip, Putty, Win32 Disk Imager and GUI Fat32 Formatter.

Recalbox Files

Recalbox Files

2. Take your Micro SD card (or USB Drive) and insert into your PC.

3. Open GUI Fat32 formatter and format your MicroSD Card (or USB Drive). Make sure it formatted into FAT32 filesystem. You can check this by going into drive properties.

GUIFat32Formatter

GUIFat32Formatter

Check Properties for FAT32

Check Properties for FAT32

4. Unzip Recalbox 4.0.1 OS and copy it over to root of your MicroSD (or USB Drive).

Copy Recalbox to your SD Card

Copy Recalbox to your SD Card

5. Safely eject the Micro SD Card or USB Drive from your PC.

Things to do in Raspberry PI 3

1. Insert your Micro SD Card into Raspberry PI 3 and connect your HDMI to TV and Micro USB Cable to your power outlet. It is recommended that you use dedicated adapter instead of TV’s inbuilt USB port for power supply into your Raspberry PI.

2. Your Pi should boot into Recalbox Setup and install the OS automatically! As easy as 1-2-3!

3. After everything is done, you will enter the Emulationstation Screen where you will have some default ROMs that you can test it out. You are ready for some retro-awesomeness!!

Loading Emulationstation

Loading Emulationstation

 

Recalbox Main Screen

Recalbox Main Screen

Now onto how to configuring your Bluetooth or Wired Controller

Controller Configuration

For the initial setup I suggest you have a keyboard with you as we will need it to configure wifi and other settings. Also I highly recommend you use a Wired USB controller for initial setup. You can use USB cable if you have 8bitdo wireless controller.

Go ahead and connect your wired USB Controller (8bitdo, PS4 or XBox controller will work just fine). Once detected you will see an on-screen popup that will ask you to press and hold a key on your controller.

Controller Detected

Controller Detected

Then just go through your controller key mapping setup process. That’s it! You can now play all the retro games.

Map Controller Keys

Map Controller Keys

Bluetooth Controller Setup

To add a bluetooth controller, set your controller in pairing mode.

Go to the menu with wired controller or a keyboard and select Controller Settings.

A list of detected controllers will appear. Select your controller from the list pair it. That’s it! You can configure it if it’s not already a supported controller!

Bluetooth Pairing

Bluetooth Pairing

Note: When mapping keys, the HOTKEY is a button that will activate buttons combination. For example, to get out of a game into the Emulationstation main menu screen you must press HOTKEY and START button at the same time.

For more info on supported controllers click here.

Wireless Connection Setup

You will need a keyboard for this setup.

Press Start (or go to EmulationStation’s Main Menu).

Main Menu

Main Menu

Then, go to Network Settings

Network Settings Recalbox

Network Settings Recalbox

Make sure the Enable Wifi is set to ON

Type in your network SSID and Password and hit the back button

If your recalbox doesn’t automatically connect to wifi just go ahead and restart. Make sure you use 2.4GHz connection as the RPi3 does not support 5GHz connection.

Once connected, it should show the status as connected in Network Settings.

Recalbox Upgrade

The latest stable verison of Recalbox OS release that you can download, as of today, is 4.0.1 but 4.0.2 update is already out. So, the first thing I would recommend you to do after wifi and controller setup is the OS update.

Go to the main menu and to the System Settings

System Settings

System Settings Menu

In System Settings go to Updates

Updates

Updates Menu

And, make sure the Auto Updates feature is set to on. Go to Start Update and follow on screen instructions. It will ask you for a system reboot. Go ahead and hit OK.

Reboot

Reboot Screen

This might take couple of minutes and should update to 4.0.2.

 

Root Access to Recalbox using SSH

The default username and password for Recalbox is

Username: root

Password: recalboxroot

Make sure you have putty installed in your computer (look into the zip file you downloaded).

Goto Network Settings in your Recalbox.

Network Settings Recalbox

Network Settings Recalbox

Look for the IP Addresss. It should say something like 192.168.1.121.

Putty

Putty

In putty, under hostname type in this ip address. Make sure the port number is set to 22. Click the Open button.

You should see a terminal screen that asks for username and password. Type the username and password as above.

Recalbox Putty SSH

Recalbox Putty SSH

If it asks to add your login to known hosts file. Type ‘yes’ and hit enter.

You now have the root access!

Installing Themes

In order to install themes, make sure you have the Recalbox Theme folder ready from above.

Network

Network

Open your Network from your PC. If you can’t see Recalbox in there then you will have to go through the FTP route as in my case. I couldn’t see the share folder in there so had to use FTP Client like FileZilla.

Folder Options

Folder Options

Before you do that, make sure you can see all hidden files. Just go to folder options and make sure Show hidden files, folders, and drives is turned on.

FileZilla SSH FTP

FileZilla SSH FTP

Open your favorite FTP client like FileZilla and use the same credentials as above to FTP into Recalbox using SSH.

Navigate to \\recalbox\share\system\.emulationstation\themes on your network

Copy the themes you want to use on your recalbox from recalbox-themes-master/themes/ (zip file above)

Retro Gaming Machine with Recalbox 4.0.2 in Raspberry Pi 3

Simplicity Theme

Comic Theme

Comic Theme

DARKADE Theme

DARKADE Theme

And Select the theme from the UI Settings in Main Menu in Recalbox and restart your pi. That’s it!

Main Menu

Main Menu

UI Setttings

UI Setttings

Adding ROMs in Recalbox

Just like installing themes, go to \\recalbox\share\

You will see a folder named ROMs and inside it you will see all the supported systems.

Just copy your game ROMs to the respective folders.

Scraping Artwork and Game Information

On your Recalbox Main Menu go to Scraper

Scraper

Scraper

Scrape From Source

Scrape From Source

On scraper window select the scraper source(from). And start scraping! This will add beautiful artwork and game images into each games you have.

Scraping Progress

Scraping Progress

If it gives you multiple option to choose from for a game artwork, select the one that best fits the name and press A key (or any other key that selects the option).

Backup your Recalbox

This is just a precautionary step. Once you setup everything you might want to make a backup copy of a working OS. Just go ahead and use Win32DiskImager to create an .img backup of your SD Card / USB device.

Win32DiskImager

Win32DiskImager

Connect your USB/SD Card to your PC and Open Win32DiskImager

Give your backup a name in the Image File section and select your device from the drop down list

Click on the Read button and this should create  a backup file in your PC.

Troubleshooting

Audio Issues When using PS4 Controller

The PS4 controllers have an integrated audio module that prevents the broadcast of sound on your tv, or speaker. You need to blacklist audio module.

Connect in ssh via putty (follow directions above)

Mount partition :

mount -o remount,rw /

Edit this file:

nano /etc/modprobe.d/blacklist.conf

Add this line:

blacklist snd-usb-audio

Save (Ctrl+X and Y) & reboot

reboot

Kindle Fire HD 8.9 Root, Roms and Troubleshoot

Just recently, I got a Kindle Fire HD 8.9 with LTE for very cheap price from Woot.com, one of amazon.com companies. My idea is that once you own a product, you should be able to do whatever you want. Sure it does void warranty and you might not be able to get it replaced/repaired but for a very cheap tablet I decided to take that risk. This tablet has a lot of potential given the LTE connection but because of the restricted OS that amazon has, we generally can’t do much outside of Amazon ecosystem when it comes to apps.

This tablet in particular uses Android 4.0.4, one of the KitKat versions and is considered a legacy system or OS. It was really hard to find a good solution to root and change things especially when most of the links out there no longer work and the codes were not maintained well. So in this tutorial I will try my best to provide you with all the links and downloads that are available to root your device and install latest TWRP and some custom roms.

Important: I am personally not liable if something goes wrong in the process. It’s up to you to take the risk!

What you need:

Download Zip File: Click Here!

  • Kindle Fire HD 8.9 (LTE/non-LTE) with 8.5.1 stock rom
  • Micro USB cable that came with the Tablet (important!)
  • Mac or PC
  • Adb and Fastboot installed
  • Latest Kindle USB Driver
  • Install a File Explorer app (any app will do(e.g. ES File Exp but I am using File Explorer app from Amazon App Store)

File Explorer
Before we begin, make sure your settings are set to the following:

  1. Swipe Down and tap on More button
  2. Select Device
  3. Make sure the “Allow Installation of Applications from Unknown Sources” is turned On
  4. Go back and select Security
  5. Make sure the “Enable ADB” is turned On

More Settings

Achieve Root Access

 

Getting a root access on this device is relatively easy. You just have to install the latest version of KingRoot app and try the root process. If it fails, just uninstall the app, restart the tablet, install the app and try again. Now, I have heard couple of bad things about KingRoot. It shows as threat when scanning with AVG app and says that it is a kind of an adware. But I have not found any other good rooting method that actually works. There are other apps like KingRoot but all of these apps seems to come from China 🙂 So it’s up to you to decide.

  1. Head over to Kingroot.net and download the latest apk file.
  2. Copy the apk to your tablet or Use Silk Browser to download the apk
  3. Open File Explorer and go to Downloads folder
  4. Install the apk
  5. Open the app and start the root process, make sure you are connected to internet and if it fails you try again.
  6. Once rooted, you should see as follows.
  7. Make sure everything is green and says Root Successfully and you Disable the Silent Install Option.
  8. Go to Settings inside KingRoot and see if you have Root Authorization Enabled!

Kingroot v5

Install Kingroot App

Disable KingRoot's Root Protection

Make Sure the Root Authorization is Enabled
Once the device is rooted, you should be able to verify in the settings or you can even download Root Checker app from Amazon App Store.
RootChecker


There you go! You have successfully rooted Amazon Kindle Fire HD 8.9 (LTE). Now, off to TWRP and Custom ROMs. 🙂

Backup What you have:

This step is very important! These backup files will be needed if anything goes wrong.

adb shell su -c "dd if=/dev/block/mmcblk0boot0 of=/sdcard/boot0block.img"
adb shell su -c "dd if=/dev/block/platform/omap/omap_hsmmc.1/by-name/boot of=/sdcard/stock-boot.img"
adb shell su -c "dd if=/dev/block/platform/omap/omap_hsmmc.1/by-name/recovery of=/sdcard/stock-recovery.img"
adb shell su -c "dd if=/dev/block/platform/omap/omap_hsmmc.1/by-name/system of=/sdcard/stock-system.img"

mkdir C:\KFHD89

adb pull /sdcard/boot0block.img/ [C:\KFHD89]
adb pull /sdcard/stock-boot.img/ [C:\KFHD89]
adb pull /sdcard/stock-recovery.img/ [C:\KFHD89]
adb pull /sdcard/stock-system.img/ [C:\KFHD89]

Make sure you have adb running. Just run this command in your cmd or terminal as an administrator. Your backup files should be available to you in C: drive under KFHD89 folder.

Installing Unlocked Bootloader, TWRP and Custom ROM

Since this tablet uses a legacy OS it was really hard to find the proper flashing tool to flash Recovery partition. The only apk that seems to work is called FireFlash. Also you do need the TWRP image to flash into the recovery partition.

Important: Amazon OS seems to delete the Recovery partition every time you reboot the device (or keep it in stand-by mode for a long period of time)

What you need:

  • FireFlash 1.1 APK
  • Unlocked Bootloader image file
  • TWRP image file

Go ahead and follow these steps:

  1. Install the FireFlash APK and open it
  2. Make sure you select (as shown in the image below)
    1. Flash kfh8-u-boot-prod-8.1.4.bin (check the box) it will have some red text below saying your tablet doesn’t have 8.1.4. If not, it means you already have 8.1.4 bin and you will not be able to check the check box which is all right.
    2. Select unlocked 8.4.6 bootloader image kfhd8-freedom-boot-8.4.6.img for boot partition
    3. Make sure you check Apply stack override which uses Hashcode’s bootloader
    4. Select TWRP image file kfhd8-twrp-3.0.2-2-recovery.img for Recovery Partition
    5. Make sure you disable recovery auto update
    6. Tap on Flash, Install Script
    7. It should now show a popup saying Flashing and complete the flash process
    8.  You will see a report window when done. Go ahead and hit ok.
    9. Now immediately, tap on the Reboot into recovery button. This is important because Amazon OS tends to wipe the recovery partition from time-to-time.
    10. Your tablet will restart and you will see Kindle Fire logo with the text Fire in red color. You should now boot into Recovery Mode with TWRP.
    11. If for some reason you restart or decide to go to recovery mode later, just flash the recovery partition with recovery auto update disabled using FireFlash and reboot into recovery.
    12. To know that your bootloader is unlocked, whenever you restart your tablet you’ll see Kindle Fire logo with Fire text in blue color.

Install Custom ROM

In order to install custom ROMs, make sure you have the correct rom that supports your device. It is usually in a .zip format. Once you choose the ROM that you want, just boot into recovery and in TWRP select the zip file and flash it. Make sure to wipe data, cache and davlik to restore to factory settings.

Now I heard that ROM from LiquidSmooth (they closed a while ago) is the best ROM out there for Kindle Fire HD 8.9 (both LTE and non-LTE) but I couldn’t find it anywhere. It should have been available here as LS-KK-MileStone-3.2-jem.zip for non-LTE device and LS-KK-MileStone-3.2-jemlte.zip for LTE device, but the links don’t work. So if anyone come across this ROM please do let me know. I’ll host it somewhere so that others can download. For now, I prefer to stick to stock OS as that is by far the best os for this device but will have a root so that I can install launchers that need root access.

Troubleshoot using Fastboot Command

If anything fails or you are stuck in bootloop, there is still a chance that you can fully recover your device. Make sure you have fastboot running in pc/mac and you have a backup of all your partitions as mentioned above. Now to go to a stock firmware all you need to do is shut the tablet down, open up command prompt(cmd) in Windows or terminal in Mac and do the following:

Fastboot Flash Boot Partition

fastboot -i 0x1949 flash boot stock-boot.img

Type this and hit enter it should say <waiting for device> and then go ahead and plug your device into your pc/mac. This should flash your boot image.

Fastboot Flash Recovery Partition

fastboot -i 0x1949 flash recovery stock-recovery.img

Type this and hit enter. (Now if it doesn’t do anything and is stuck. Take the USB cable out and plug it in again. Type the code above and hit enter. Do the same for the following codes.)

Fastboot Flash System Partition

fastboot -i 0x1949 flash system stock-system.img

Type this and hit enter. It will take a while. Once done type the following.

Fastboot Reboot

fastboot -i 0x1949 reboot

Your device should boot up into stock firmware!


Array Splitting using PHP’s and Java’s in-built Array Funtion

Today, I am going to talk about something simple and useful in programming. For people who are professional programmers this might seem relatively easy but for someone who is trying to learn PHP or Java having a knowlege of how arrays work might be really useful. Especially when you have a large set of data and you need to display it in multiple columns.

So let’s talk about how to use PHP’s and Java’s inbuilt array funtion to slice a large array into smaller parts. For this tutorial, I am assuming you have some knowledge of how PHP and Java works. If not, there are hundreds of websites and books available to get basic understanding.

Scenario: I was given a task to list all the 52 US states in a page so that only the ones that are flagged as active in a table inside database is shown on the page. I had to show this in 3 columns.

#State NameActive Flag
1Alabama1
2Alaska1
3Arizona0
4Arkansas1
51

Result: The result should look something like this.

Alabama
Alaska
Arkansas
California
Kentucky
Louisiana
Maine
Maryland
North Dakota
Ohio
Oklahoma
Oregon

Now, the question might seem relatively easy. And we don’t necessarily need PHP or JAVA to solve this. We could also use something on client side like JavaScript. But, I’ll show how it’s done on the server side.

Query Database for Results:

We can get the list of active states from the database as follows:

SELECT * FROM states where active_flag = 1 order by state_id asc;

For PHP you get the data as follows:

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} 

$sql = "SELECT * FROM states WHERE active_flag = 1 ORDER BY state_id ASC;";
$result = $conn->query($sql);
$states = array();
if ($result->num_rows > 0) {
    // output data of each row
    while($row = $result->fetch_assoc()) {
        $states[] = $row;
    }
} else {
    echo "No Results Found";
}

$conn->close();
?>

The above code connects to the database and quries the result and puts it inside the $states[] array.

In Java, you can do the same utilizing Java’s inbuilt database connection library:

Connection conn = null;
CallableStatement stmt = null;
ResultSet result = null;
ArrayList<String> states = new ArrayList<String>();
		
try {
        conn = getConnection();
	stmt = conn.prepareCall("SELECT * FROM states WHERE active_flag = 1 ORDER BY state_id ASC;");

	result = stmt.executeQuery();

	while (result.next()) {

		String state_name = result.getString("state_name");
		states.add(state_name);
	}

} catch (SQLException e) {
	LOG.log(Level.SEVERE, e.getMessage(), e);

} finally {
	result.close();
	stmt.close();
	conn.close();
}

The above code puts the result inside states array. Here, getConnection() actually connects to the database. You can google and read about how to connect to database in Java to understand it much better. But, the idea is simple. We utilize Java’s SQL library to automatically connect to the database. You just define all the required connection settings in a properties file (below is just an example).

protected static Connection getConnection() throws SQLException {
     return DriverManager.getConnection("**** Database Name ****");
}

Now that we have our results in an array. Let’s see how we can split the array into three sub arrays.

Array Count or Length

Before we do the actual splitting, we need to know the count of the total states in the array so that we can split the array evenly across the three arrays.

To do this, in PHP we use the inbuilt function count($array).

$states_count=count($states);

In Java we simply we utilize array.length property of an array.

int states_count = states.length;

Divisible by 3

Now that we know the array length, we need to know how to evenly distribute the states into three sets of list. The logic here is to make the length (or count) of the list divisible by 3 so that we can evenly distribute the states among three sets.

The concept of modulus is very helpful here. The modulo operation (or simply modulus) finds the remainder after division of one number by another. To check if a number is divisible by 3 or not we do the following:

  • First, we check to see if the number is even or odd.
  • If even, we add +1 and do the modulo operand on the length. This is done as number % divisor. If this outputs a number, besides 0, then we know the number is not divisible by divisor. Here we know length or count is even as $states_count % 2 gives us 0. If so, we loop and keep on adding 1 ($states_count++;) until we get a number that is divisible by 3 (loop until $states_count % 3 is not 0).
  • If odd, we test and see if this odd number is divisible by 3 ($states_count % 3 == 0). If the number is not divisible by 3 we keep adding 1 until we get a number that is divisible by 3.

In PHP

if($states_count % 2 == 0){
   do {
      $states_count++;
   }while($states_count % 3 != 0);
}else{
   if($states_count % 3 == 0){
      //do nothing
   }else{
      do {
	 $states_count++;
      }while($states_count % 3 != 0);
   }
}

In Java

if(states_count % 2 == 0){
   do {
      states_count++;
   }while(states_count % 3 != 0);
}else{
   if(states_count % 3 == 0){
      //do nothing
   }else{
      do {
	 states_count++;
      }while(states_count % 3 != 0);
   }
}

Split Array in 3

Now that we have an array length that is divisible by 3, we can do the following to split the array.

In PHP we will use array_slice() method to slice into three parts. The syntax for array_slice() is

array_slice(array, starting index, length);

$states_first = array_slice($states, 0, $states_count/3);
$states_second = array_slice($states, $states_count/3, $states_count/3);
$states_third = array_slice($states, ($states_count/3)*2, $states_count/3);

In Java we will use Arrays.copyOfRange method to make a copy of or split an array. The syntax for copyOfRange() is

int[] newArray = Arrays.copyOfRange(array, starting index, ending index);

ArrayList<String> states_first = new ArrayList<String>();
ArrayList<String> states_second = new ArrayList<String>();
ArrayList<String> states_third = new ArrayList<String>();

states_first = Arrays.copyOfRange(states, 0, states_count/3);
states_second = Arrays.copyOfRange(states, states_count/3, (states_count/3)*2);
states_third = Arrays.copyOfRange(states, (states_count/3)*2, states_count);

And there you go! That’s how you split an array. You can split into any number using the same concept. Let me know what you think or if you have an even better way.